From e5f4e68eed85fa8495d78cd966eecc2b27bb9e53 Mon Sep 17 00:00:00 2001 From: Doug Smythies Date: Mon, 3 Apr 2023 14:11:38 -0700 Subject: tools/power turbostat: Fix added raw MSR output When using --Summary mode, added MSRs in raw mode always print zeros. Print the actual register contents. Example, with patch: note the added column: --add msr0x64f,u32,package,raw,REASON Where: 0x64F is MSR_CORE_PERF_LIMIT_REASONS Busy% Bzy_MHz PkgTmp PkgWatt CorWatt REASON 0.00 4800 35 1.42 0.76 0x00000000 0.00 4801 34 1.42 0.76 0x00000000 80.08 4531 66 108.17 107.52 0x08000000 98.69 4530 66 133.21 132.54 0x08000000 99.28 4505 66 128.26 127.60 0x0c000400 99.65 4486 68 124.91 124.25 0x0c000400 99.63 4483 68 124.90 124.25 0x0c000400 79.34 4481 41 99.80 99.13 0x0c000000 0.00 4801 41 1.40 0.73 0x0c000000 Where, for the test processor (i5-10600K): PKG Limit #1: 125.000 Watts, 8.000000 sec MSR bit 26 = log; bit 10 = status PKG Limit #2: 136.000 Watts, 0.002441 sec MSR bit 27 = log; bit 11 = status Example, without patch: Busy% Bzy_MHz PkgTmp PkgWatt CorWatt REASON 0.01 4800 35 1.43 0.77 0x00000000 0.00 4801 35 1.39 0.73 0x00000000 83.49 4531 66 112.71 112.06 0x00000000 98.69 4530 68 133.35 132.69 0x00000000 99.31 4500 67 127.96 127.30 0x00000000 99.63 4483 69 124.91 124.25 0x00000000 99.61 4481 69 124.90 124.25 0x00000000 99.61 4481 71 124.92 124.25 0x00000000 59.35 4479 42 75.03 74.37 0x00000000 0.00 4800 42 1.39 0.73 0x00000000 0.00 4801 42 1.42 0.76 0x00000000 c000000 [lenb: simplified patch to apply only to package scope] Signed-off-by: Doug Smythies Signed-off-by: Len Brown --- tools/power/x86/turbostat/turbostat.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/tools/power/x86/turbostat/turbostat.c b/tools/power/x86/turbostat/turbostat.c index 7a334377f92b..fca7913f6c84 100644 --- a/tools/power/x86/turbostat/turbostat.c +++ b/tools/power/x86/turbostat/turbostat.c @@ -2444,9 +2444,10 @@ int sum_counters(struct thread_data *t, struct core_data *c, struct pkg_data *p) average.packages.rapl_dram_perf_status += p->rapl_dram_perf_status; for (i = 0, mp = sys.pp; mp; i++, mp = mp->next) { - if (mp->format == FORMAT_RAW) - continue; - average.packages.counter[i] += p->counter[i]; + if ((mp->format == FORMAT_RAW) && (topo.num_packages == 0)) + average.packages.counter[i] = p->counter[i]; + else + average.packages.counter[i] += p->counter[i]; } return 0; } -- cgit v1.2.3 From 3ac1d14d0583a2de75d49a5234d767e2590384dd Mon Sep 17 00:00:00 2001 From: Wyes Karny Date: Tue, 3 Oct 2023 05:07:51 +0000 Subject: tools/power turbostat: Increase the limit for fd opened When running turbostat, a system with 512 cpus reaches the limit for maximum number of file descriptors that can be opened. To solve this problem, the limit is raised to 2^15, which is a large enough number. Below data is collected from AMD server systems while running turbostat: |-----------+-------------------------------| | # of cpus | # of opened fds for turbostat | |-----------+-------------------------------| | 128 | 260 | |-----------+-------------------------------| | 192 | 388 | |-----------+-------------------------------| | 512 | 1028 | |-----------+-------------------------------| So, the new max limit would be sufficient up to 2^14 cpus (but this also depends on how many counters are enabled). Reviewed-by: Doug Smythies Tested-by: Doug Smythies Signed-off-by: Wyes Karny Signed-off-by: Len Brown --- tools/power/x86/turbostat/turbostat.c | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/tools/power/x86/turbostat/turbostat.c b/tools/power/x86/turbostat/turbostat.c index fca7913f6c84..2550a0e35914 100644 --- a/tools/power/x86/turbostat/turbostat.c +++ b/tools/power/x86/turbostat/turbostat.c @@ -53,6 +53,8 @@ #define NAME_BYTES 20 #define PATH_BYTES 128 +#define MAX_NOFILE 0x8000 + enum counter_scope { SCOPE_CPU, SCOPE_CORE, SCOPE_PACKAGE }; enum counter_type { COUNTER_ITEMS, COUNTER_CYCLES, COUNTER_SECONDS, COUNTER_USEC }; enum counter_format { FORMAT_RAW, FORMAT_DELTA, FORMAT_PERCENT }; @@ -6705,6 +6707,22 @@ void cmdline(int argc, char **argv) } } +void set_rlimit(void) +{ + struct rlimit limit; + + if (getrlimit(RLIMIT_NOFILE, &limit) < 0) + err(1, "Failed to get rlimit"); + + if (limit.rlim_max < MAX_NOFILE) + limit.rlim_max = MAX_NOFILE; + if (limit.rlim_cur < MAX_NOFILE) + limit.rlim_cur = MAX_NOFILE; + + if (setrlimit(RLIMIT_NOFILE, &limit) < 0) + err(1, "Failed to set rlimit"); +} + int main(int argc, char **argv) { int fd, ret; @@ -6730,6 +6748,9 @@ skip_cgroup_setting: probe_sysfs(); + if (!getuid()) + set_rlimit(); + turbostat_init(); msr_sum_record(); -- cgit v1.2.3 From 0b13410b52c4636aacb6964a4253a797c0fa0d16 Mon Sep 17 00:00:00 2001 From: Peng Liu Date: Sat, 7 Oct 2023 13:46:22 +0800 Subject: tools/power turbostat: Fix Bzy_MHz documentation typo The code calculates Bzy_MHz by multiplying TSC_delta * APERF_delta/MPERF_delta The man page erroneously showed that TSC_delta was divided. Signed-off-by: Peng Liu Signed-off-by: Len Brown --- tools/power/x86/turbostat/turbostat.8 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/power/x86/turbostat/turbostat.8 b/tools/power/x86/turbostat/turbostat.8 index 8f08c3fd498d..1ba6340d3b3d 100644 --- a/tools/power/x86/turbostat/turbostat.8 +++ b/tools/power/x86/turbostat/turbostat.8 @@ -370,7 +370,7 @@ below the processor's base frequency. Busy% = MPERF_delta/TSC_delta -Bzy_MHz = TSC_delta/APERF_delta/MPERF_delta/measurement_interval +Bzy_MHz = TSC_delta*APERF_delta/MPERF_delta/measurement_interval Note that these calculations depend on TSC_delta, so they are not reliable during intervals when TSC_MHz is not running at the base frequency. -- cgit v1.2.3 From 227ed18f456a68bbb69807294a9089208663a6d3 Mon Sep 17 00:00:00 2001 From: Chen Yu Date: Sun, 22 Oct 2023 13:52:21 +0800 Subject: tools/power turbostat: Do not print negative LPI residency turbostat prints the abnormal SYS%LPI across suspend-to-idle: SYS%LPI = 114479815993277.50 This is reproduced by: Run a freeze cycle, e.g. "sleepgraph -m freeze -rtcwake 15". Then do a reboot. After boot up, launch the suspend-idle-idle and check the SYS%LPI field. The slp_so residence counter is in LPIT table, and BIOS does not clears this register across reset. The PMC expects the OS to calculate the LPI residency based on the delta. However, there is an firmware issue that the LPIT gets cleared to 0 during the second suspend to idle after the reboot, which brings negative delta value. [lenb: updated to print "neg" upon this BIOS failure] Reported-by: Todd Brandt Signed-off-by: Chen Yu Signed-off-by: Len Brown --- tools/power/x86/turbostat/turbostat.c | 30 +++++++++++++++++++++--------- 1 file changed, 21 insertions(+), 9 deletions(-) diff --git a/tools/power/x86/turbostat/turbostat.c b/tools/power/x86/turbostat/turbostat.c index 2550a0e35914..c23703dd54aa 100644 --- a/tools/power/x86/turbostat/turbostat.c +++ b/tools/power/x86/turbostat/turbostat.c @@ -991,8 +991,8 @@ struct pkg_data { unsigned long long pc8; unsigned long long pc9; unsigned long long pc10; - unsigned long long cpu_lpi; - unsigned long long sys_lpi; + long long cpu_lpi; + long long sys_lpi; unsigned long long pkg_wtd_core_c0; unsigned long long pkg_any_core_c0; unsigned long long pkg_any_gfxe_c0; @@ -1978,12 +1978,22 @@ int format_counters(struct thread_data *t, struct core_data *c, struct pkg_data if (DO_BIC(BIC_Pkgpc10)) outp += sprintf(outp, "%s%.2f", (printed++ ? delim : ""), 100.0 * p->pc10 / tsc); - if (DO_BIC(BIC_CPU_LPI)) - outp += - sprintf(outp, "%s%.2f", (printed++ ? delim : ""), 100.0 * p->cpu_lpi / 1000000.0 / interval_float); - if (DO_BIC(BIC_SYS_LPI)) - outp += - sprintf(outp, "%s%.2f", (printed++ ? delim : ""), 100.0 * p->sys_lpi / 1000000.0 / interval_float); + if (DO_BIC(BIC_CPU_LPI)) { + if (p->cpu_lpi >= 0) + outp += + sprintf(outp, "%s%.2f", (printed++ ? delim : ""), + 100.0 * p->cpu_lpi / 1000000.0 / interval_float); + else + outp += sprintf(outp, "%s(neg)", (printed++ ? delim : "")); + } + if (DO_BIC(BIC_SYS_LPI)) { + if (p->sys_lpi >= 0) + outp += + sprintf(outp, "%s%.2f", (printed++ ? delim : ""), + 100.0 * p->sys_lpi / 1000000.0 / interval_float); + else + outp += sprintf(outp, "%s(neg)", (printed++ ? delim : "")); + } if (DO_BIC(BIC_PkgWatt)) outp += @@ -3832,7 +3842,8 @@ void re_initialize(void) { free_all_buffers(); setup_all_buffers(false); - fprintf(outf, "turbostat: re-initialized with num_cpus %d, allowed_cpus %d\n", topo.num_cpus, topo.allowed_cpus); + fprintf(outf, "turbostat: re-initialized with num_cpus %d, allowed_cpus %d\n", topo.num_cpus, + topo.allowed_cpus); } void set_max_cpu_num(void) @@ -6145,6 +6156,7 @@ void topology_update(void) topo.allowed_packages = 0; for_all_cpus(update_topo, ODD_COUNTERS); } + void setup_all_buffers(bool startup) { topology_probe(startup); -- cgit v1.2.3 From bb6181fa6bc942aac3f7f2fa8e3831952a2ef118 Mon Sep 17 00:00:00 2001 From: Len Brown Date: Wed, 20 Dec 2023 13:11:05 -0500 Subject: tools/power turbostat: Expand probe_intel_uncore_frequency() Print current frequency along with the current (and initial) limits Probe and print uncore config also for machines using the new cluster API Signed-off-by: Len Brown --- tools/power/x86/turbostat/turbostat.c | 84 ++++++++++++++++++++++++++--------- 1 file changed, 63 insertions(+), 21 deletions(-) diff --git a/tools/power/x86/turbostat/turbostat.c b/tools/power/x86/turbostat/turbostat.c index c23703dd54aa..bbd2e0edadfa 100644 --- a/tools/power/x86/turbostat/turbostat.c +++ b/tools/power/x86/turbostat/turbostat.c @@ -4581,20 +4581,15 @@ static void dump_sysfs_file(char *path) static void probe_intel_uncore_frequency(void) { int i, j; - char path[128]; + char path[256]; if (!genuine_intel) return; - if (access("/sys/devices/system/cpu/intel_uncore_frequency/package_00_die_00", R_OK)) - return; - - /* Cluster level sysfs not supported yet. */ - if (!access("/sys/devices/system/cpu/intel_uncore_frequency/uncore00", R_OK)) - return; + if (access("/sys/devices/system/cpu/intel_uncore_frequency/package_00_die_00/current_freq_khz", R_OK)) + goto probe_cluster; - if (!access("/sys/devices/system/cpu/intel_uncore_frequency/package_00_die_00/current_freq_khz", R_OK)) - BIC_PRESENT(BIC_UNCORE_MHZ); + BIC_PRESENT(BIC_UNCORE_MHZ); if (quiet) return; @@ -4602,26 +4597,73 @@ static void probe_intel_uncore_frequency(void) for (i = 0; i < topo.num_packages; ++i) { for (j = 0; j < topo.num_die; ++j) { int k, l; + char path_base[128]; + + sprintf(path_base, "/sys/devices/system/cpu/intel_uncore_frequency/package_%02d_die_%02d", i, + j); - sprintf(path, "/sys/devices/system/cpu/intel_uncore_frequency/package_0%d_die_0%d/min_freq_khz", - i, j); + sprintf(path, "%s/min_freq_khz", path_base); k = read_sysfs_int(path); - sprintf(path, "/sys/devices/system/cpu/intel_uncore_frequency/package_0%d_die_0%d/max_freq_khz", - i, j); + sprintf(path, "%s/max_freq_khz", path_base); l = read_sysfs_int(path); - fprintf(outf, "Uncore Frequency pkg%d die%d: %d - %d MHz ", i, j, k / 1000, l / 1000); + fprintf(outf, "Uncore Frequency package%d die%d: %d - %d MHz ", i, j, k / 1000, l / 1000); - sprintf(path, - "/sys/devices/system/cpu/intel_uncore_frequency/package_0%d_die_0%d/initial_min_freq_khz", - i, j); + sprintf(path, "%s/initial_min_freq_khz", path_base); k = read_sysfs_int(path); - sprintf(path, - "/sys/devices/system/cpu/intel_uncore_frequency/package_0%d_die_0%d/initial_max_freq_khz", - i, j); + sprintf(path, "%s/initial_max_freq_khz", path_base); l = read_sysfs_int(path); - fprintf(outf, "(%d - %d MHz)\n", k / 1000, l / 1000); + fprintf(outf, "(%d - %d MHz)", k / 1000, l / 1000); + + sprintf(path, "%s/current_freq_khz", path_base); + k = read_sysfs_int(path); + fprintf(outf, " %d MHz\n", k / 1000); } } + return; + +probe_cluster: + if (access("/sys/devices/system/cpu/intel_uncore_frequency/uncore00/current_freq_khz", R_OK)) + return; + + if (quiet) + return; + + for (i = 0;; ++i) { + int k, l; + char path_base[128]; + int package_id, domain_id, cluster_id; + + sprintf(path_base, "/sys/devices/system/cpu/intel_uncore_frequency/uncore%02d", i); + + if (access(path_base, R_OK)) + break; + + sprintf(path, "%s/package_id", path_base); + package_id = read_sysfs_int(path); + + sprintf(path, "%s/domain_id", path_base); + domain_id = read_sysfs_int(path); + + sprintf(path, "%s/fabric_cluster_id", path_base); + cluster_id = read_sysfs_int(path); + + sprintf(path, "%s/min_freq_khz", path_base); + k = read_sysfs_int(path); + sprintf(path, "%s/max_freq_khz", path_base); + l = read_sysfs_int(path); + fprintf(outf, "Uncore Frequency package%d domain%d cluster%d: %d - %d MHz ", package_id, domain_id, + cluster_id, k / 1000, l / 1000); + + sprintf(path, "%s/initial_min_freq_khz", path_base); + k = read_sysfs_int(path); + sprintf(path, "%s/initial_max_freq_khz", path_base); + l = read_sysfs_int(path); + fprintf(outf, "(%d - %d MHz)", k / 1000, l / 1000); + + sprintf(path, "%s/current_freq_khz", path_base); + k = read_sysfs_int(path); + fprintf(outf, " %d MHz\n", k / 1000); + } } static void probe_graphics(void) -- cgit v1.2.3 From fb5ceca046efc84f69fcf9779a013f8a0e63bbff Mon Sep 17 00:00:00 2001 From: Patryk Wlazlyn Date: Fri, 12 Jan 2024 13:48:14 +0100 Subject: tools/power turbostat: Print ucode revision only if valid If the MSR read were to fail, turbostat would print "microcode 0x0" Signed-off-by: Patryk Wlazlyn Reviewed-by: Len Brown Signed-off-by: Len Brown --- tools/power/x86/turbostat/turbostat.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/tools/power/x86/turbostat/turbostat.c b/tools/power/x86/turbostat/turbostat.c index bbd2e0edadfa..a4a40a6e1b95 100644 --- a/tools/power/x86/turbostat/turbostat.c +++ b/tools/power/x86/turbostat/turbostat.c @@ -5679,6 +5679,7 @@ void process_cpuid() unsigned int eax, ebx, ecx, edx; unsigned int fms, family, model, stepping, ecx_flags, edx_flags; unsigned long long ucode_patch = 0; + bool ucode_patch_valid = false; eax = ebx = ecx = edx = 0; @@ -5708,6 +5709,8 @@ void process_cpuid() if (get_msr(sched_getcpu(), MSR_IA32_UCODE_REV, &ucode_patch)) warnx("get_msr(UCODE)"); + else + ucode_patch_valid = true; /* * check max extended function levels of CPUID. @@ -5718,9 +5721,12 @@ void process_cpuid() __cpuid(0x80000000, max_extended_level, ebx, ecx, edx); if (!quiet) { - fprintf(outf, "CPUID(1): family:model:stepping 0x%x:%x:%x (%d:%d:%d) microcode 0x%x\n", - family, model, stepping, family, model, stepping, - (unsigned int)((ucode_patch >> 32) & 0xFFFFFFFF)); + fprintf(outf, "CPUID(1): family:model:stepping 0x%x:%x:%x (%d:%d:%d)", + family, model, stepping, family, model, stepping); + if (ucode_patch_valid) + fprintf(outf, " microcode 0x%x", (unsigned int)((ucode_patch >> 32) & 0xFFFFFFFF)); + fputc('\n', outf); + fprintf(outf, "CPUID(0x80000000): max_extended_levels: 0x%x\n", max_extended_level); fprintf(outf, "CPUID(1): %s %s %s %s %s %s %s %s %s %s\n", ecx_flags & (1 << 0) ? "SSE3" : "-", -- cgit v1.2.3 From 95f37eb52e18879a1b16e51b972d992b39e50a81 Mon Sep 17 00:00:00 2001 From: Aaro Koskinen Date: Fri, 23 Feb 2024 20:14:35 +0200 Subject: ARM: OMAP2+: fix bogus MMC GPIO labels on Nokia N8x0 The GPIO bank width is 32 on OMAP2, so all labels are incorrect. Fixes: e519f0bb64ef ("ARM/mmc: Convert old mmci-omap to GPIO descriptors") Signed-off-by: Aaro Koskinen Message-ID: <20240223181439.1099750-2-aaro.koskinen@iki.fi> Reviewed-by: Linus Walleij Acked-by: Ulf Hansson Signed-off-by: Tony Lindgren --- arch/arm/mach-omap2/board-n8x0.c | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/arch/arm/mach-omap2/board-n8x0.c b/arch/arm/mach-omap2/board-n8x0.c index 31755a378c73..3e48f34016c1 100644 --- a/arch/arm/mach-omap2/board-n8x0.c +++ b/arch/arm/mach-omap2/board-n8x0.c @@ -144,8 +144,7 @@ static struct gpiod_lookup_table nokia8xx_mmc_gpio_table = { .dev_id = "mmci-omap.0", .table = { /* Slot switch, GPIO 96 */ - GPIO_LOOKUP("gpio-80-111", 16, - "switch", GPIO_ACTIVE_HIGH), + GPIO_LOOKUP("gpio-96-127", 0, "switch", GPIO_ACTIVE_HIGH), { } }, }; @@ -154,11 +153,9 @@ static struct gpiod_lookup_table nokia810_mmc_gpio_table = { .dev_id = "mmci-omap.0", .table = { /* Slot index 1, VSD power, GPIO 23 */ - GPIO_LOOKUP_IDX("gpio-16-31", 7, - "vsd", 1, GPIO_ACTIVE_HIGH), + GPIO_LOOKUP_IDX("gpio-0-31", 23, "vsd", 1, GPIO_ACTIVE_HIGH), /* Slot index 1, VIO power, GPIO 9 */ - GPIO_LOOKUP_IDX("gpio-0-15", 9, - "vio", 1, GPIO_ACTIVE_HIGH), + GPIO_LOOKUP_IDX("gpio-0-31", 9, "vio", 1, GPIO_ACTIVE_HIGH), { } }, }; -- cgit v1.2.3 From 480d44d0820dd5ae043dc97c0b46dabbe53cb1cf Mon Sep 17 00:00:00 2001 From: Aaro Koskinen Date: Fri, 23 Feb 2024 20:14:36 +0200 Subject: ARM: OMAP2+: fix N810 MMC gpiod table Trying to append a second table for the same dev_id doesn't seem to work. The second table is just silently ignored. As a result eMMC GPIOs are not present. Fix by using separate tables for N800 and N810. Fixes: e519f0bb64ef ("ARM/mmc: Convert old mmci-omap to GPIO descriptors") Signed-off-by: Aaro Koskinen Message-ID: <20240223181439.1099750-3-aaro.koskinen@iki.fi> Reviewed-by: Linus Walleij Acked-by: Ulf Hansson Signed-off-by: Tony Lindgren --- arch/arm/mach-omap2/board-n8x0.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/arch/arm/mach-omap2/board-n8x0.c b/arch/arm/mach-omap2/board-n8x0.c index 3e48f34016c1..c933a91751e4 100644 --- a/arch/arm/mach-omap2/board-n8x0.c +++ b/arch/arm/mach-omap2/board-n8x0.c @@ -140,7 +140,7 @@ static int slot1_cover_open; static int slot2_cover_open; static struct device *mmc_device; -static struct gpiod_lookup_table nokia8xx_mmc_gpio_table = { +static struct gpiod_lookup_table nokia800_mmc_gpio_table = { .dev_id = "mmci-omap.0", .table = { /* Slot switch, GPIO 96 */ @@ -152,6 +152,8 @@ static struct gpiod_lookup_table nokia8xx_mmc_gpio_table = { static struct gpiod_lookup_table nokia810_mmc_gpio_table = { .dev_id = "mmci-omap.0", .table = { + /* Slot switch, GPIO 96 */ + GPIO_LOOKUP("gpio-96-127", 0, "switch", GPIO_ACTIVE_HIGH), /* Slot index 1, VSD power, GPIO 23 */ GPIO_LOOKUP_IDX("gpio-0-31", 23, "vsd", 1, GPIO_ACTIVE_HIGH), /* Slot index 1, VIO power, GPIO 9 */ @@ -412,8 +414,6 @@ static struct omap_mmc_platform_data *mmc_data[OMAP24XX_NR_MMC]; static void __init n8x0_mmc_init(void) { - gpiod_add_lookup_table(&nokia8xx_mmc_gpio_table); - if (board_is_n810()) { mmc1_data.slots[0].name = "external"; @@ -426,6 +426,8 @@ static void __init n8x0_mmc_init(void) mmc1_data.slots[1].name = "internal"; mmc1_data.slots[1].ban_openended = 1; gpiod_add_lookup_table(&nokia810_mmc_gpio_table); + } else { + gpiod_add_lookup_table(&nokia800_mmc_gpio_table); } mmc1_data.nr_slots = 2; -- cgit v1.2.3 From d4debbcbffa45c3de5df0040af2eea74a9e794a3 Mon Sep 17 00:00:00 2001 From: Aaro Koskinen Date: Fri, 23 Feb 2024 20:14:37 +0200 Subject: mmc: omap: fix broken slot switch lookup The lookup is done before host->dev is initialized. It will always just fail silently, and the MMC behaviour is totally unpredictable as the switch is left in an undefined state. Fix that. Fixes: e519f0bb64ef ("ARM/mmc: Convert old mmci-omap to GPIO descriptors") Signed-off-by: Aaro Koskinen Message-ID: <20240223181439.1099750-4-aaro.koskinen@iki.fi> Reviewed-by: Linus Walleij Acked-by: Ulf Hansson Signed-off-by: Tony Lindgren --- drivers/mmc/host/omap.c | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/drivers/mmc/host/omap.c b/drivers/mmc/host/omap.c index 9fb8995b43a1..aa40e1a9dc29 100644 --- a/drivers/mmc/host/omap.c +++ b/drivers/mmc/host/omap.c @@ -1384,13 +1384,6 @@ static int mmc_omap_probe(struct platform_device *pdev) if (IS_ERR(host->virt_base)) return PTR_ERR(host->virt_base); - host->slot_switch = gpiod_get_optional(host->dev, "switch", - GPIOD_OUT_LOW); - if (IS_ERR(host->slot_switch)) - return dev_err_probe(host->dev, PTR_ERR(host->slot_switch), - "error looking up slot switch GPIO\n"); - - INIT_WORK(&host->slot_release_work, mmc_omap_slot_release_work); INIT_WORK(&host->send_stop_work, mmc_omap_send_stop_work); @@ -1409,6 +1402,12 @@ static int mmc_omap_probe(struct platform_device *pdev) host->dev = &pdev->dev; platform_set_drvdata(pdev, host); + host->slot_switch = gpiod_get_optional(host->dev, "switch", + GPIOD_OUT_LOW); + if (IS_ERR(host->slot_switch)) + return dev_err_probe(host->dev, PTR_ERR(host->slot_switch), + "error looking up slot switch GPIO\n"); + host->id = pdev->id; host->irq = irq; host->phys_base = res->start; -- cgit v1.2.3 From f6862c7f156d04f81c38467e1c304b7e9517e810 Mon Sep 17 00:00:00 2001 From: Aaro Koskinen Date: Fri, 23 Feb 2024 20:14:38 +0200 Subject: mmc: omap: fix deferred probe After a deferred probe, GPIO descriptor lookup will fail with EBUSY. Fix by using managed descriptors. Fixes: e519f0bb64ef ("ARM/mmc: Convert old mmci-omap to GPIO descriptors") Signed-off-by: Aaro Koskinen Message-ID: <20240223181439.1099750-5-aaro.koskinen@iki.fi> Reviewed-by: Linus Walleij Acked-by: Ulf Hansson Signed-off-by: Tony Lindgren --- drivers/mmc/host/omap.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/drivers/mmc/host/omap.c b/drivers/mmc/host/omap.c index aa40e1a9dc29..50408771ae01 100644 --- a/drivers/mmc/host/omap.c +++ b/drivers/mmc/host/omap.c @@ -1259,18 +1259,18 @@ static int mmc_omap_new_slot(struct mmc_omap_host *host, int id) slot->pdata = &host->pdata->slots[id]; /* Check for some optional GPIO controls */ - slot->vsd = gpiod_get_index_optional(host->dev, "vsd", - id, GPIOD_OUT_LOW); + slot->vsd = devm_gpiod_get_index_optional(host->dev, "vsd", + id, GPIOD_OUT_LOW); if (IS_ERR(slot->vsd)) return dev_err_probe(host->dev, PTR_ERR(slot->vsd), "error looking up VSD GPIO\n"); - slot->vio = gpiod_get_index_optional(host->dev, "vio", - id, GPIOD_OUT_LOW); + slot->vio = devm_gpiod_get_index_optional(host->dev, "vio", + id, GPIOD_OUT_LOW); if (IS_ERR(slot->vio)) return dev_err_probe(host->dev, PTR_ERR(slot->vio), "error looking up VIO GPIO\n"); - slot->cover = gpiod_get_index_optional(host->dev, "cover", - id, GPIOD_IN); + slot->cover = devm_gpiod_get_index_optional(host->dev, "cover", + id, GPIOD_IN); if (IS_ERR(slot->cover)) return dev_err_probe(host->dev, PTR_ERR(slot->cover), "error looking up cover switch GPIO\n"); @@ -1402,8 +1402,8 @@ static int mmc_omap_probe(struct platform_device *pdev) host->dev = &pdev->dev; platform_set_drvdata(pdev, host); - host->slot_switch = gpiod_get_optional(host->dev, "switch", - GPIOD_OUT_LOW); + host->slot_switch = devm_gpiod_get_optional(host->dev, "switch", + GPIOD_OUT_LOW); if (IS_ERR(host->slot_switch)) return dev_err_probe(host->dev, PTR_ERR(host->slot_switch), "error looking up slot switch GPIO\n"); -- cgit v1.2.3 From 894ad61b85d6ba8efd4274aa8719d9ff1c89ea54 Mon Sep 17 00:00:00 2001 From: Aaro Koskinen Date: Fri, 23 Feb 2024 20:14:39 +0200 Subject: mmc: omap: restore original power up/down steps Commit e519f0bb64ef ("ARM/mmc: Convert old mmci-omap to GPIO descriptors") moved Nokia N810 MMC power up/down from the board file into the MMC driver. The change removed some delays, and ordering without a valid reason. Restore power up/down to match the original code. This matters only on N810 where the 2nd GPIO is in use. Other boards will see an additional delay but that should be a lesser concern than omitting delays altogether. Fixes: e519f0bb64ef ("ARM/mmc: Convert old mmci-omap to GPIO descriptors") Signed-off-by: Aaro Koskinen Message-ID: <20240223181439.1099750-6-aaro.koskinen@iki.fi> Reviewed-by: Linus Walleij Acked-by: Ulf Hansson Signed-off-by: Tony Lindgren --- drivers/mmc/host/omap.c | 23 +++++++++++++++++++---- 1 file changed, 19 insertions(+), 4 deletions(-) diff --git a/drivers/mmc/host/omap.c b/drivers/mmc/host/omap.c index 50408771ae01..13fa8588e38c 100644 --- a/drivers/mmc/host/omap.c +++ b/drivers/mmc/host/omap.c @@ -1119,10 +1119,25 @@ static void mmc_omap_set_power(struct mmc_omap_slot *slot, int power_on, host = slot->host; - if (slot->vsd) - gpiod_set_value(slot->vsd, power_on); - if (slot->vio) - gpiod_set_value(slot->vio, power_on); + if (power_on) { + if (slot->vsd) { + gpiod_set_value(slot->vsd, power_on); + msleep(1); + } + if (slot->vio) { + gpiod_set_value(slot->vio, power_on); + msleep(1); + } + } else { + if (slot->vio) { + gpiod_set_value(slot->vio, power_on); + msleep(50); + } + if (slot->vsd) { + gpiod_set_value(slot->vsd, power_on); + msleep(50); + } + } if (slot->pdata->set_power != NULL) slot->pdata->set_power(mmc_dev(slot->mmc), slot->id, power_on, -- cgit v1.2.3 From 4421405e3634a3189b541cf1e34598e44260720d Mon Sep 17 00:00:00 2001 From: Aaro Koskinen Date: Fri, 23 Feb 2024 20:16:56 +0200 Subject: ARM: OMAP2+: fix USB regression on Nokia N8x0 GPIO chip labels are wrong for OMAP2, so the USB does not work. Fix. Fixes: 8e0285ab95a9 ("ARM/musb: omap2: Remove global GPIO numbers from TUSB6010") Signed-off-by: Aaro Koskinen Reviewed-by: Linus Walleij Message-ID: <20240223181656.1099845-1-aaro.koskinen@iki.fi> Signed-off-by: Tony Lindgren --- arch/arm/mach-omap2/board-n8x0.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/arch/arm/mach-omap2/board-n8x0.c b/arch/arm/mach-omap2/board-n8x0.c index c933a91751e4..ff2a4a4d8220 100644 --- a/arch/arm/mach-omap2/board-n8x0.c +++ b/arch/arm/mach-omap2/board-n8x0.c @@ -79,10 +79,8 @@ static struct musb_hdrc_platform_data tusb_data = { static struct gpiod_lookup_table tusb_gpio_table = { .dev_id = "musb-tusb", .table = { - GPIO_LOOKUP("gpio-0-15", 0, "enable", - GPIO_ACTIVE_HIGH), - GPIO_LOOKUP("gpio-48-63", 10, "int", - GPIO_ACTIVE_HIGH), + GPIO_LOOKUP("gpio-0-31", 0, "enable", GPIO_ACTIVE_HIGH), + GPIO_LOOKUP("gpio-32-63", 26, "int", GPIO_ACTIVE_HIGH), { } }, }; -- cgit v1.2.3 From fcf3f7e2fc8a53a6140beee46ec782a4c88e4744 Mon Sep 17 00:00:00 2001 From: Yu Kuai Date: Fri, 8 Mar 2024 17:37:26 +0800 Subject: raid1: fix use-after-free for original bio in raid1_write_request() r1_bio->bios[] is used to record new bios that will be issued to underlying disks, however, in raid1_write_request(), r1_bio->bios[] will set to the original bio temporarily. Meanwhile, if blocked rdev is set, free_r1bio() will be called causing that all r1_bio->bios[] to be freed: raid1_write_request() r1_bio = alloc_r1bio(mddev, bio); -> r1_bio->bios[] is NULL for (i = 0; i < disks; i++) -> for each rdev in conf // first rdev is normal r1_bio->bios[0] = bio; -> set to original bio // second rdev is blocked if (test_bit(Blocked, &rdev->flags)) break if (blocked_rdev) free_r1bio() put_all_bios() bio_put(r1_bio->bios[0]) -> original bio is freed Test scripts: mdadm -CR /dev/md0 -l1 -n4 /dev/sd[abcd] --assume-clean fio -filename=/dev/md0 -ioengine=libaio -rw=write -bs=4k -numjobs=1 \ -iodepth=128 -name=test -direct=1 echo blocked > /sys/block/md0/md/rd2/state Test result: BUG bio-264 (Not tainted): Object already free ----------------------------------------------------------------------------- Allocated in mempool_alloc_slab+0x24/0x50 age=1 cpu=1 pid=869 kmem_cache_alloc+0x324/0x480 mempool_alloc_slab+0x24/0x50 mempool_alloc+0x6e/0x220 bio_alloc_bioset+0x1af/0x4d0 blkdev_direct_IO+0x164/0x8a0 blkdev_write_iter+0x309/0x440 aio_write+0x139/0x2f0 io_submit_one+0x5ca/0xb70 __do_sys_io_submit+0x86/0x270 __x64_sys_io_submit+0x22/0x30 do_syscall_64+0xb1/0x210 entry_SYSCALL_64_after_hwframe+0x6c/0x74 Freed in mempool_free_slab+0x1f/0x30 age=1 cpu=1 pid=869 kmem_cache_free+0x28c/0x550 mempool_free_slab+0x1f/0x30 mempool_free+0x40/0x100 bio_free+0x59/0x80 bio_put+0xf0/0x220 free_r1bio+0x74/0xb0 raid1_make_request+0xadf/0x1150 md_handle_request+0xc7/0x3b0 md_submit_bio+0x76/0x130 __submit_bio+0xd8/0x1d0 submit_bio_noacct_nocheck+0x1eb/0x5c0 submit_bio_noacct+0x169/0xd40 submit_bio+0xee/0x1d0 blkdev_direct_IO+0x322/0x8a0 blkdev_write_iter+0x309/0x440 aio_write+0x139/0x2f0 Since that bios for underlying disks are not allocated yet, fix this problem by using mempool_free() directly to free the r1_bio. Fixes: 992db13a4aee ("md/raid1: free the r1bio before waiting for blocked rdev") Cc: stable@vger.kernel.org # v6.6+ Reported-by: Coly Li Signed-off-by: Yu Kuai Tested-by: Coly Li Signed-off-by: Song Liu Link: https://lore.kernel.org/r/20240308093726.1047420-1-yukuai1@huaweicloud.com --- drivers/md/raid1.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/md/raid1.c b/drivers/md/raid1.c index be8ac24f50b6..7b8a71ca66dd 100644 --- a/drivers/md/raid1.c +++ b/drivers/md/raid1.c @@ -1558,7 +1558,7 @@ static void raid1_write_request(struct mddev *mddev, struct bio *bio, for (j = 0; j < i; j++) if (r1_bio->bios[j]) rdev_dec_pending(conf->mirrors[j].rdev, mddev); - free_r1bio(r1_bio); + mempool_free(r1_bio, &conf->r1bio_pool); allow_barrier(conf, bio->bi_iter.bi_sector); if (bio->bi_opf & REQ_NOWAIT) { -- cgit v1.2.3 From 59097a2a5ecadb0f025232c665fd11c8ae1e1f58 Mon Sep 17 00:00:00 2001 From: Konrad Dybcio Date: Sat, 2 Mar 2024 03:22:49 +0100 Subject: interconnect: qcom: x1e80100: Remove inexistent ACV_PERF BCM Booting the kernel on X1E results in a message like: [ 2.561524] qnoc-x1e80100 interconnect-0: ACV_PERF could not find RPMh address And indeed, taking a look at cmd-db, no such BCM exists. Remove it. Fixes: 9f196772841e ("interconnect: qcom: Add X1E80100 interconnect provider driver") Signed-off-by: Konrad Dybcio Reviewed-by: Mike Tipton Link: https://lore.kernel.org/r/20240302-topic-faux_bcm_x1e-v1-1-c40fab7c4bc5@linaro.org Signed-off-by: Georgi Djakov --- drivers/interconnect/qcom/x1e80100.c | 26 -------------------------- 1 file changed, 26 deletions(-) diff --git a/drivers/interconnect/qcom/x1e80100.c b/drivers/interconnect/qcom/x1e80100.c index cbaf4f9c41be..06f0a6d6cbbc 100644 --- a/drivers/interconnect/qcom/x1e80100.c +++ b/drivers/interconnect/qcom/x1e80100.c @@ -116,15 +116,6 @@ static struct qcom_icc_node xm_sdc2 = { .links = { X1E80100_SLAVE_A2NOC_SNOC }, }; -static struct qcom_icc_node ddr_perf_mode_master = { - .name = "ddr_perf_mode_master", - .id = X1E80100_MASTER_DDR_PERF_MODE, - .channels = 1, - .buswidth = 4, - .num_links = 1, - .links = { X1E80100_SLAVE_DDR_PERF_MODE }, -}; - static struct qcom_icc_node qup0_core_master = { .name = "qup0_core_master", .id = X1E80100_MASTER_QUP_CORE_0, @@ -832,14 +823,6 @@ static struct qcom_icc_node qns_a2noc_snoc = { .links = { X1E80100_MASTER_A2NOC_SNOC }, }; -static struct qcom_icc_node ddr_perf_mode_slave = { - .name = "ddr_perf_mode_slave", - .id = X1E80100_SLAVE_DDR_PERF_MODE, - .channels = 1, - .buswidth = 4, - .num_links = 0, -}; - static struct qcom_icc_node qup0_core_slave = { .name = "qup0_core_slave", .id = X1E80100_SLAVE_QUP_CORE_0, @@ -1591,12 +1574,6 @@ static struct qcom_icc_bcm bcm_acv = { .nodes = { &ebi }, }; -static struct qcom_icc_bcm bcm_acv_perf = { - .name = "ACV_PERF", - .num_nodes = 1, - .nodes = { &ddr_perf_mode_slave }, -}; - static struct qcom_icc_bcm bcm_ce0 = { .name = "CE0", .num_nodes = 1, @@ -1863,18 +1840,15 @@ static const struct qcom_icc_desc x1e80100_aggre2_noc = { }; static struct qcom_icc_bcm * const clk_virt_bcms[] = { - &bcm_acv_perf, &bcm_qup0, &bcm_qup1, &bcm_qup2, }; static struct qcom_icc_node * const clk_virt_nodes[] = { - [MASTER_DDR_PERF_MODE] = &ddr_perf_mode_master, [MASTER_QUP_CORE_0] = &qup0_core_master, [MASTER_QUP_CORE_1] = &qup1_core_master, [MASTER_QUP_CORE_2] = &qup2_core_master, - [SLAVE_DDR_PERF_MODE] = &ddr_perf_mode_slave, [SLAVE_QUP_CORE_0] = &qup0_core_slave, [SLAVE_QUP_CORE_1] = &qup1_core_slave, [SLAVE_QUP_CORE_2] = &qup2_core_slave, -- cgit v1.2.3 From de1bf25b6d771abdb52d43546cf57ad775fb68a1 Mon Sep 17 00:00:00 2001 From: Mike Tipton Date: Tue, 5 Mar 2024 14:56:52 -0800 Subject: interconnect: Don't access req_list while it's being manipulated The icc_lock mutex was split into separate icc_lock and icc_bw_lock mutexes in [1] to avoid lockdep splats. However, this didn't adequately protect access to icc_node::req_list. The icc_set_bw() function will eventually iterate over req_list while only holding icc_bw_lock, but req_list can be modified while only holding icc_lock. This causes races between icc_set_bw(), of_icc_get(), and icc_put(). Example A: CPU0 CPU1 ---- ---- icc_set_bw(path_a) mutex_lock(&icc_bw_lock); icc_put(path_b) mutex_lock(&icc_lock); aggregate_requests() hlist_for_each_entry(r, ... hlist_del(... Example B: CPU0 CPU1 ---- ---- icc_set_bw(path_a) mutex_lock(&icc_bw_lock); path_b = of_icc_get() of_icc_get_by_index() mutex_lock(&icc_lock); path_find() path_init() aggregate_requests() hlist_for_each_entry(r, ... hlist_add_head(... Fix this by ensuring icc_bw_lock is always held before manipulating icc_node::req_list. The additional places icc_bw_lock is held don't perform any memory allocations, so we should still be safe from the original lockdep splats that motivated the separate locks. [1] commit af42269c3523 ("interconnect: Fix locking for runpm vs reclaim") Signed-off-by: Mike Tipton Fixes: af42269c3523 ("interconnect: Fix locking for runpm vs reclaim") Reviewed-by: Rob Clark Link: https://lore.kernel.org/r/20240305225652.22872-1-quic_mdtipton@quicinc.com Signed-off-by: Georgi Djakov --- drivers/interconnect/core.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/drivers/interconnect/core.c b/drivers/interconnect/core.c index 50bac2d79d9b..68edb07d4443 100644 --- a/drivers/interconnect/core.c +++ b/drivers/interconnect/core.c @@ -176,6 +176,8 @@ static struct icc_path *path_init(struct device *dev, struct icc_node *dst, path->num_nodes = num_nodes; + mutex_lock(&icc_bw_lock); + for (i = num_nodes - 1; i >= 0; i--) { node->provider->users++; hlist_add_head(&path->reqs[i].req_node, &node->req_list); @@ -186,6 +188,8 @@ static struct icc_path *path_init(struct device *dev, struct icc_node *dst, node = node->reverse; } + mutex_unlock(&icc_bw_lock); + return path; } @@ -792,12 +796,16 @@ void icc_put(struct icc_path *path) pr_err("%s: error (%d)\n", __func__, ret); mutex_lock(&icc_lock); + mutex_lock(&icc_bw_lock); + for (i = 0; i < path->num_nodes; i++) { node = path->reqs[i].node; hlist_del(&path->reqs[i].req_node); if (!WARN_ON(!node->provider->users)) node->provider->users--; } + + mutex_unlock(&icc_bw_lock); mutex_unlock(&icc_lock); kfree_const(path->name); -- cgit v1.2.3 From 9c0f59e47a90c54d0153f8ddc0f80d7a36207d0e Mon Sep 17 00:00:00 2001 From: Nam Cao Date: Mon, 18 Mar 2024 11:59:02 +0100 Subject: HID: i2c-hid: remove I2C_HID_READ_PENDING flag to prevent lock-up The flag I2C_HID_READ_PENDING is used to serialize I2C operations. However, this is not necessary, because I2C core already has its own locking for that. More importantly, this flag can cause a lock-up: if the flag is set in i2c_hid_xfer() and an interrupt happens, the interrupt handler (i2c_hid_irq) will check this flag and return immediately without doing anything, then the interrupt handler will be invoked again in an infinite loop. Since interrupt handler is an RT task, it takes over the CPU and the flag-clearing task never gets scheduled, thus we have a lock-up. Delete this unnecessary flag. Reported-and-tested-by: Eva Kurchatova Closes: https://lore.kernel.org/r/CA+eeCSPUDpUg76ZO8dszSbAGn+UHjcyv8F1J-CUPVARAzEtW9w@mail.gmail.com Fixes: 4a200c3b9a40 ("HID: i2c-hid: introduce HID over i2c specification implementation") Cc: Signed-off-by: Nam Cao Signed-off-by: Jiri Kosina --- drivers/hid/i2c-hid/i2c-hid-core.c | 9 --------- 1 file changed, 9 deletions(-) diff --git a/drivers/hid/i2c-hid/i2c-hid-core.c b/drivers/hid/i2c-hid/i2c-hid-core.c index 2df1ab3c31cc..1c86c97688e9 100644 --- a/drivers/hid/i2c-hid/i2c-hid-core.c +++ b/drivers/hid/i2c-hid/i2c-hid-core.c @@ -64,7 +64,6 @@ /* flags */ #define I2C_HID_STARTED 0 #define I2C_HID_RESET_PENDING 1 -#define I2C_HID_READ_PENDING 2 #define I2C_HID_PWR_ON 0x00 #define I2C_HID_PWR_SLEEP 0x01 @@ -190,15 +189,10 @@ static int i2c_hid_xfer(struct i2c_hid *ihid, msgs[n].len = recv_len; msgs[n].buf = recv_buf; n++; - - set_bit(I2C_HID_READ_PENDING, &ihid->flags); } ret = i2c_transfer(client->adapter, msgs, n); - if (recv_len) - clear_bit(I2C_HID_READ_PENDING, &ihid->flags); - if (ret != n) return ret < 0 ? ret : -EIO; @@ -556,9 +550,6 @@ static irqreturn_t i2c_hid_irq(int irq, void *dev_id) { struct i2c_hid *ihid = dev_id; - if (test_bit(I2C_HID_READ_PENDING, &ihid->flags)) - return IRQ_HANDLED; - i2c_hid_get_input(ihid); return IRQ_HANDLED; -- cgit v1.2.3 From 92826905ae340b7f2b25759a06c8c60bfc476b9f Mon Sep 17 00:00:00 2001 From: Zhang Lixu Date: Wed, 6 Mar 2024 00:44:04 +0000 Subject: HID: intel-ish-hid: ipc: Fix dev_err usage with uninitialized dev->devc The variable dev->devc in ish_dev_init was utilized by dev_err before it was properly assigned. To rectify this, the assignment of dev->devc has been moved to immediately follow memory allocation. Without this change "(NULL device *)" is printed for device information. Fixes: 8ae2f2b0a284 ("HID: intel-ish-hid: ipc: Fix potential use-after-free in work function") Fixes: ae02e5d40d5f ("HID: intel-ish-hid: ipc layer") Signed-off-by: Zhang Lixu Acked-by: Srinivas Pandruvada Signed-off-by: Jiri Kosina --- drivers/hid/intel-ish-hid/ipc/ipc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/hid/intel-ish-hid/ipc/ipc.c b/drivers/hid/intel-ish-hid/ipc/ipc.c index a49c6affd7c4..dd5fc60874ba 100644 --- a/drivers/hid/intel-ish-hid/ipc/ipc.c +++ b/drivers/hid/intel-ish-hid/ipc/ipc.c @@ -948,6 +948,7 @@ struct ishtp_device *ish_dev_init(struct pci_dev *pdev) if (!dev) return NULL; + dev->devc = &pdev->dev; ishtp_device_init(dev); init_waitqueue_head(&dev->wait_hw_ready); @@ -983,7 +984,6 @@ struct ishtp_device *ish_dev_init(struct pci_dev *pdev) } dev->ops = &ish_hw_ops; - dev->devc = &pdev->dev; dev->mtu = IPC_PAYLOAD_SIZE - sizeof(struct ishtp_msg_hdr); return dev; } -- cgit v1.2.3 From 139b4c37e9cb0943e51adbb9c20c45bf60e44422 Mon Sep 17 00:00:00 2001 From: Benjamin Tissoires Date: Thu, 21 Mar 2024 16:19:27 +0100 Subject: MAINTAINERS: update Benjamin's email address Update my email address to the kernel.org one, as it's getting more convenient this way. Signed-off-by: Benjamin Tissoires Signed-off-by: Jiri Kosina --- .mailmap | 2 ++ MAINTAINERS | 4 ++-- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/.mailmap b/.mailmap index e90797de3256..25019ddf467c 100644 --- a/.mailmap +++ b/.mailmap @@ -96,6 +96,8 @@ Ben Widawsky Ben Widawsky Ben Widawsky Benjamin Poirier +Benjamin Tissoires +Benjamin Tissoires Bjorn Andersson Bjorn Andersson Bjorn Andersson diff --git a/MAINTAINERS b/MAINTAINERS index c50e72258ba9..52bb6f2c3e7b 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -9546,7 +9546,7 @@ F: kernel/power/ HID CORE LAYER M: Jiri Kosina -M: Benjamin Tissoires +M: Benjamin Tissoires L: linux-input@vger.kernel.org S: Maintained T: git git://git.kernel.org/pub/scm/linux/kernel/git/hid/hid.git @@ -22685,7 +22685,7 @@ F: drivers/usb/host/ehci* USB HID/HIDBP DRIVERS (USB KEYBOARDS, MICE, REMOTE CONTROLS, ...) M: Jiri Kosina -M: Benjamin Tissoires +M: Benjamin Tissoires L: linux-usb@vger.kernel.org S: Maintained T: git git://git.kernel.org/pub/scm/linux/kernel/git/hid/hid.git -- cgit v1.2.3 From e249884e106b81c34f8050d23935ffc12623843f Mon Sep 17 00:00:00 2001 From: Erni Sri Satya Vennela Date: Thu, 21 Mar 2024 01:22:05 -0700 Subject: x86/hyperv: Cosmetic changes for hv_apic.c Fix issues reported by checkpatch.pl script for hv_apic.c file - Alignment should match open parenthesis - Remove unnecessary parenthesis No functional changes intended. Signed-off-by: Erni Sri Satya Vennela Reviewed-by: Saurabh Sengar Link: https://lore.kernel.org/r/1711009325-21894-1-git-send-email-ernis@linux.microsoft.com Signed-off-by: Wei Liu Message-ID: <1711009325-21894-1-git-send-email-ernis@linux.microsoft.com> --- arch/x86/hyperv/hv_apic.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/arch/x86/hyperv/hv_apic.c b/arch/x86/hyperv/hv_apic.c index 5fc45543e955..0569f579338b 100644 --- a/arch/x86/hyperv/hv_apic.c +++ b/arch/x86/hyperv/hv_apic.c @@ -105,7 +105,7 @@ static bool cpu_is_self(int cpu) * IPI implementation on Hyper-V. */ static bool __send_ipi_mask_ex(const struct cpumask *mask, int vector, - bool exclude_self) + bool exclude_self) { struct hv_send_ipi_ex *ipi_arg; unsigned long flags; @@ -132,8 +132,8 @@ static bool __send_ipi_mask_ex(const struct cpumask *mask, int vector, if (!cpumask_equal(mask, cpu_present_mask) || exclude_self) { ipi_arg->vp_set.format = HV_GENERIC_SET_SPARSE_4K; - nr_bank = cpumask_to_vpset_skip(&(ipi_arg->vp_set), mask, - exclude_self ? cpu_is_self : NULL); + nr_bank = cpumask_to_vpset_skip(&ipi_arg->vp_set, mask, + exclude_self ? cpu_is_self : NULL); /* * 'nr_bank <= 0' means some CPUs in cpumask can't be @@ -147,7 +147,7 @@ static bool __send_ipi_mask_ex(const struct cpumask *mask, int vector, } status = hv_do_rep_hypercall(HVCALL_SEND_IPI_EX, 0, nr_bank, - ipi_arg, NULL); + ipi_arg, NULL); ipi_mask_ex_done: local_irq_restore(flags); @@ -155,7 +155,7 @@ ipi_mask_ex_done: } static bool __send_ipi_mask(const struct cpumask *mask, int vector, - bool exclude_self) + bool exclude_self) { int cur_cpu, vcpu, this_cpu = smp_processor_id(); struct hv_send_ipi ipi_arg; @@ -181,7 +181,7 @@ static bool __send_ipi_mask(const struct cpumask *mask, int vector, return false; } - if ((vector < HV_IPI_LOW_VECTOR) || (vector > HV_IPI_HIGH_VECTOR)) + if (vector < HV_IPI_LOW_VECTOR || vector > HV_IPI_HIGH_VECTOR) return false; /* @@ -218,7 +218,7 @@ static bool __send_ipi_mask(const struct cpumask *mask, int vector, } status = hv_do_fast_hypercall16(HVCALL_SEND_IPI, ipi_arg.vector, - ipi_arg.cpu_mask); + ipi_arg.cpu_mask); return hv_result_success(status); do_ex_hypercall: @@ -241,7 +241,7 @@ static bool __send_ipi_one(int cpu, int vector) return false; } - if ((vector < HV_IPI_LOW_VECTOR) || (vector > HV_IPI_HIGH_VECTOR)) + if (vector < HV_IPI_LOW_VECTOR || vector > HV_IPI_HIGH_VECTOR) return false; if (vp >= 64) -- cgit v1.2.3 From 1f1dc442c57ec61c08d21d47e4c5b4f16446fe00 Mon Sep 17 00:00:00 2001 From: Nuno Das Neves Date: Fri, 22 Mar 2024 14:10:26 -0700 Subject: mshyperv: Introduce hv_numa_node_to_pxm_info() Factor out logic for converting numa node to hv_proximity_domain_info into a helper function. Change hv_proximity_domain_info to a struct to improve readability. While at it, rename hv_add_logical_processor_* structs to the correct hv_input_/hv_output_ prefix, and remove the flags field which is not present in the ABI. Signed-off-by: Nuno Das Neves Reviewed-by: Wei Liu Link: https://lore.kernel.org/r/1711141826-9458-1-git-send-email-nunodasneves@linux.microsoft.com Signed-off-by: Wei Liu Message-ID: <1711141826-9458-1-git-send-email-nunodasneves@linux.microsoft.com> --- arch/x86/hyperv/hv_proc.c | 22 ++++------------------ include/asm-generic/hyperv-tlfs.h | 19 +++++++------------ include/asm-generic/mshyperv.h | 14 ++++++++++++++ 3 files changed, 25 insertions(+), 30 deletions(-) diff --git a/arch/x86/hyperv/hv_proc.c b/arch/x86/hyperv/hv_proc.c index 68a0843d4750..3fa1f2ee7b0d 100644 --- a/arch/x86/hyperv/hv_proc.c +++ b/arch/x86/hyperv/hv_proc.c @@ -3,7 +3,6 @@ #include #include #include -#include #include #include #include @@ -116,12 +115,11 @@ free_buf: int hv_call_add_logical_proc(int node, u32 lp_index, u32 apic_id) { - struct hv_add_logical_processor_in *input; - struct hv_add_logical_processor_out *output; + struct hv_input_add_logical_processor *input; + struct hv_output_add_logical_processor *output; u64 status; unsigned long flags; int ret = HV_STATUS_SUCCESS; - int pxm = node_to_pxm(node); /* * When adding a logical processor, the hypervisor may return @@ -137,11 +135,7 @@ int hv_call_add_logical_proc(int node, u32 lp_index, u32 apic_id) input->lp_index = lp_index; input->apic_id = apic_id; - input->flags = 0; - input->proximity_domain_info.domain_id = pxm; - input->proximity_domain_info.flags.reserved = 0; - input->proximity_domain_info.flags.proximity_info_valid = 1; - input->proximity_domain_info.flags.proximity_preferred = 1; + input->proximity_domain_info = hv_numa_node_to_pxm_info(node); status = hv_do_hypercall(HVCALL_ADD_LOGICAL_PROCESSOR, input, output); local_irq_restore(flags); @@ -166,7 +160,6 @@ int hv_call_create_vp(int node, u64 partition_id, u32 vp_index, u32 flags) u64 status; unsigned long irq_flags; int ret = HV_STATUS_SUCCESS; - int pxm = node_to_pxm(node); /* Root VPs don't seem to need pages deposited */ if (partition_id != hv_current_partition_id) { @@ -185,14 +178,7 @@ int hv_call_create_vp(int node, u64 partition_id, u32 vp_index, u32 flags) input->vp_index = vp_index; input->flags = flags; input->subnode_type = HvSubnodeAny; - if (node != NUMA_NO_NODE) { - input->proximity_domain_info.domain_id = pxm; - input->proximity_domain_info.flags.reserved = 0; - input->proximity_domain_info.flags.proximity_info_valid = 1; - input->proximity_domain_info.flags.proximity_preferred = 1; - } else { - input->proximity_domain_info.as_uint64 = 0; - } + input->proximity_domain_info = hv_numa_node_to_pxm_info(node); status = hv_do_hypercall(HVCALL_CREATE_VP, input, NULL); local_irq_restore(irq_flags); diff --git a/include/asm-generic/hyperv-tlfs.h b/include/asm-generic/hyperv-tlfs.h index fdac4a1714ec..69f3f68dc249 100644 --- a/include/asm-generic/hyperv-tlfs.h +++ b/include/asm-generic/hyperv-tlfs.h @@ -512,13 +512,9 @@ struct hv_proximity_domain_flags { u32 proximity_info_valid : 1; } __packed; -/* Not a union in windows but useful for zeroing */ -union hv_proximity_domain_info { - struct { - u32 domain_id; - struct hv_proximity_domain_flags flags; - }; - u64 as_uint64; +struct hv_proximity_domain_info { + u32 domain_id; + struct hv_proximity_domain_flags flags; } __packed; struct hv_lp_startup_status { @@ -532,14 +528,13 @@ struct hv_lp_startup_status { } __packed; /* HvAddLogicalProcessor hypercall */ -struct hv_add_logical_processor_in { +struct hv_input_add_logical_processor { u32 lp_index; u32 apic_id; - union hv_proximity_domain_info proximity_domain_info; - u64 flags; + struct hv_proximity_domain_info proximity_domain_info; } __packed; -struct hv_add_logical_processor_out { +struct hv_output_add_logical_processor { struct hv_lp_startup_status startup_status; } __packed; @@ -560,7 +555,7 @@ struct hv_create_vp { u8 padding[3]; u8 subnode_type; u64 subnode_id; - union hv_proximity_domain_info proximity_domain_info; + struct hv_proximity_domain_info proximity_domain_info; u64 flags; } __packed; diff --git a/include/asm-generic/mshyperv.h b/include/asm-generic/mshyperv.h index 430f0ae0dde2..cfb0b51a0998 100644 --- a/include/asm-generic/mshyperv.h +++ b/include/asm-generic/mshyperv.h @@ -21,6 +21,7 @@ #include #include #include +#include #include #include #include @@ -67,6 +68,19 @@ extern u64 hv_do_fast_hypercall8(u16 control, u64 input8); bool hv_isolation_type_snp(void); bool hv_isolation_type_tdx(void); +static inline struct hv_proximity_domain_info hv_numa_node_to_pxm_info(int node) +{ + struct hv_proximity_domain_info pxm_info = {}; + + if (node != NUMA_NO_NODE) { + pxm_info.domain_id = node_to_pxm(node); + pxm_info.flags.proximity_info_valid = 1; + pxm_info.flags.proximity_preferred = 1; + } + + return pxm_info; +} + /* Helper functions that provide a consistent pattern for checking Hyper-V hypercall status. */ static inline int hv_result(u64 status) { -- cgit v1.2.3 From c0454d31e05062b1c7df7eef21855ba1f56c5158 Mon Sep 17 00:00:00 2001 From: Samuel Holland Date: Sat, 2 Mar 2024 15:00:35 +0100 Subject: ASoC: sun50i-codec-analog: Move suspend/resume to set_bias_level MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit With idle_bias_on and suspend_bias_off, there are bias level transitions that match the suspend/resume callbacks. However, there are also transitions during probe (OFF => STANDBY) and removal (STANDBY => OFF). By using the set_bias_level hook, the driver can have one copy of code that would otherwise be duplicated between the probe/resume and suspend/remove hooks. Signed-off-by: Samuel Holland Signed-off-by: Ondřej Jirman Link: https://msgid.link/r/20240302140042.1990256-2-megi@xff.cz Signed-off-by: Mark Brown --- sound/soc/sunxi/sun50i-codec-analog.c | 29 ++++++++++++++++++----------- 1 file changed, 18 insertions(+), 11 deletions(-) diff --git a/sound/soc/sunxi/sun50i-codec-analog.c b/sound/soc/sunxi/sun50i-codec-analog.c index 8a32d05e23e1..cedd4de42d1a 100644 --- a/sound/soc/sunxi/sun50i-codec-analog.c +++ b/sound/soc/sunxi/sun50i-codec-analog.c @@ -471,17 +471,23 @@ static const struct snd_soc_dapm_route sun50i_a64_codec_routes[] = { { "EARPIECE", NULL, "Earpiece Amp" }, }; -static int sun50i_a64_codec_suspend(struct snd_soc_component *component) +static int sun50i_a64_codec_set_bias_level(struct snd_soc_component *component, + enum snd_soc_bias_level level) { - return regmap_update_bits(component->regmap, SUN50I_ADDA_HP_CTRL, - BIT(SUN50I_ADDA_HP_CTRL_PA_CLK_GATE), - BIT(SUN50I_ADDA_HP_CTRL_PA_CLK_GATE)); -} + switch (level) { + case SND_SOC_BIAS_OFF: + regmap_set_bits(component->regmap, SUN50I_ADDA_HP_CTRL, + BIT(SUN50I_ADDA_HP_CTRL_PA_CLK_GATE)); + break; + case SND_SOC_BIAS_STANDBY: + regmap_clear_bits(component->regmap, SUN50I_ADDA_HP_CTRL, + BIT(SUN50I_ADDA_HP_CTRL_PA_CLK_GATE)); + break; + default: + break; + } -static int sun50i_a64_codec_resume(struct snd_soc_component *component) -{ - return regmap_update_bits(component->regmap, SUN50I_ADDA_HP_CTRL, - BIT(SUN50I_ADDA_HP_CTRL_PA_CLK_GATE), 0); + return 0; } static const struct snd_soc_component_driver sun50i_codec_analog_cmpnt_drv = { @@ -491,8 +497,9 @@ static const struct snd_soc_component_driver sun50i_codec_analog_cmpnt_drv = { .num_dapm_widgets = ARRAY_SIZE(sun50i_a64_codec_widgets), .dapm_routes = sun50i_a64_codec_routes, .num_dapm_routes = ARRAY_SIZE(sun50i_a64_codec_routes), - .suspend = sun50i_a64_codec_suspend, - .resume = sun50i_a64_codec_resume, + .set_bias_level = sun50i_a64_codec_set_bias_level, + .idle_bias_on = true, + .suspend_bias_off = true, }; static const struct of_device_id sun50i_codec_analog_of_match[] = { -- cgit v1.2.3 From c556814b926c3f16fdca3d18cac793ccf0d14c44 Mon Sep 17 00:00:00 2001 From: Samuel Holland Date: Sat, 2 Mar 2024 15:00:36 +0100 Subject: ASoC: sun8i-codec: Enable bus clock at STANDBY and higher bias MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit For codec variants that have a bus clock, that clock must be running to receive interrupts. Since jack and mic accessory detection should work even when no audio is playing, that means the bus clock should be enabled any time the system is on. Accomplish that by tying the bus clock to the runtime PM state, which is then tied to the bias level not being OFF. Since the codec sets idle_bias_on, bias will generally never be OFF. However, we can set suspend_bias_off to maintain the power savings of gating the bus clock during suspend, when we don't expect jack/accessory detection to work. Signed-off-by: Samuel Holland Signed-off-by: Ondřej Jirman Link: https://msgid.link/r/20240302140042.1990256-3-megi@xff.cz Signed-off-by: Mark Brown --- sound/soc/sunxi/sun8i-codec.c | 41 +++++++++++++++++++++++++++++++++-------- 1 file changed, 33 insertions(+), 8 deletions(-) diff --git a/sound/soc/sunxi/sun8i-codec.c b/sound/soc/sunxi/sun8i-codec.c index 7b45ddffe990..2a46b96b03cc 100644 --- a/sound/soc/sunxi/sun8i-codec.c +++ b/sound/soc/sunxi/sun8i-codec.c @@ -177,12 +177,14 @@ struct sun8i_codec_aif { }; struct sun8i_codec_quirks { - bool legacy_widgets : 1; - bool lrck_inversion : 1; + bool bus_clock : 1; + bool legacy_widgets : 1; + bool lrck_inversion : 1; }; struct sun8i_codec { struct regmap *regmap; + struct clk *clk_bus; struct clk *clk_module; const struct sun8i_codec_quirks *quirks; struct sun8i_codec_aif aifs[SUN8I_CODEC_NAIFS]; @@ -197,6 +199,14 @@ static int sun8i_codec_runtime_resume(struct device *dev) struct sun8i_codec *scodec = dev_get_drvdata(dev); int ret; + if (scodec->clk_bus) { + ret = clk_prepare_enable(scodec->clk_bus); + if (ret) { + dev_err(dev, "Failed to enable the bus clock\n"); + return ret; + } + } + regcache_cache_only(scodec->regmap, false); ret = regcache_sync(scodec->regmap); @@ -215,6 +225,9 @@ static int sun8i_codec_runtime_suspend(struct device *dev) regcache_cache_only(scodec->regmap, true); regcache_mark_dirty(scodec->regmap); + if (scodec->clk_bus) + clk_disable_unprepare(scodec->clk_bus); + return 0; } @@ -1277,6 +1290,7 @@ static const struct snd_soc_component_driver sun8i_soc_component = { .num_dapm_routes = ARRAY_SIZE(sun8i_codec_dapm_routes), .probe = sun8i_codec_component_probe, .idle_bias_on = 1, + .suspend_bias_off = 1, .endianness = 1, }; @@ -1299,6 +1313,18 @@ static int sun8i_codec_probe(struct platform_device *pdev) if (!scodec) return -ENOMEM; + scodec->quirks = of_device_get_match_data(&pdev->dev); + + platform_set_drvdata(pdev, scodec); + + if (scodec->quirks->bus_clock) { + scodec->clk_bus = devm_clk_get(&pdev->dev, "bus"); + if (IS_ERR(scodec->clk_bus)) { + dev_err(&pdev->dev, "Failed to get the bus clock\n"); + return PTR_ERR(scodec->clk_bus); + } + } + scodec->clk_module = devm_clk_get(&pdev->dev, "mod"); if (IS_ERR(scodec->clk_module)) { dev_err(&pdev->dev, "Failed to get the module clock\n"); @@ -1311,17 +1337,14 @@ static int sun8i_codec_probe(struct platform_device *pdev) return PTR_ERR(base); } - scodec->regmap = devm_regmap_init_mmio_clk(&pdev->dev, "bus", base, - &sun8i_codec_regmap_config); + scodec->regmap = devm_regmap_init_mmio(&pdev->dev, base, + &sun8i_codec_regmap_config); if (IS_ERR(scodec->regmap)) { dev_err(&pdev->dev, "Failed to create our regmap\n"); return PTR_ERR(scodec->regmap); } - scodec->quirks = of_device_get_match_data(&pdev->dev); - - platform_set_drvdata(pdev, scodec); - + regcache_cache_only(scodec->regmap, true); pm_runtime_enable(&pdev->dev); if (!pm_runtime_enabled(&pdev->dev)) { ret = sun8i_codec_runtime_resume(&pdev->dev); @@ -1357,11 +1380,13 @@ static void sun8i_codec_remove(struct platform_device *pdev) } static const struct sun8i_codec_quirks sun8i_a33_quirks = { + .bus_clock = true, .legacy_widgets = true, .lrck_inversion = true, }; static const struct sun8i_codec_quirks sun50i_a64_quirks = { + .bus_clock = true, }; static const struct of_device_id sun8i_codec_of_match[] = { -- cgit v1.2.3 From d5961e43b28668088087befbf4f7a043bd0ae65c Mon Sep 17 00:00:00 2001 From: Arnaud Ferraris Date: Sat, 2 Mar 2024 15:00:37 +0100 Subject: ASoC: sun50i-codec-analog: Enable jack detection on startup MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This commit adds the necessary setup to enable jack detection on startup as well as the callback function enabling the microphone ADC when headset bias is enabled. The microphone ADC is also disabled in suspend. Signed-off-by: Arnaud Ferraris [Samuel: Moved MICADCEN setup to HBIAS event, added bias hooks] Signed-off-by: Samuel Holland Signed-off-by: Ondřej Jirman Link: https://msgid.link/r/20240302140042.1990256-4-megi@xff.cz Signed-off-by: Mark Brown --- sound/soc/sunxi/sun50i-codec-analog.c | 32 +++++++++++++++++++++++++++++++- 1 file changed, 31 insertions(+), 1 deletion(-) diff --git a/sound/soc/sunxi/sun50i-codec-analog.c b/sound/soc/sunxi/sun50i-codec-analog.c index cedd4de42d1a..2081721a8ff2 100644 --- a/sound/soc/sunxi/sun50i-codec-analog.c +++ b/sound/soc/sunxi/sun50i-codec-analog.c @@ -116,8 +116,10 @@ #define SUN50I_ADDA_HS_MBIAS_CTRL_MMICBIASEN 7 #define SUN50I_ADDA_JACK_MIC_CTRL 0x1d +#define SUN50I_ADDA_JACK_MIC_CTRL_JACKDETEN 7 #define SUN50I_ADDA_JACK_MIC_CTRL_INNERRESEN 6 #define SUN50I_ADDA_JACK_MIC_CTRL_HMICBIASEN 5 +#define SUN50I_ADDA_JACK_MIC_CTRL_MICADCEN 4 /* mixer controls */ static const struct snd_kcontrol_new sun50i_a64_codec_mixer_controls[] = { @@ -296,6 +298,19 @@ static const struct snd_kcontrol_new sun50i_codec_earpiece_switch[] = { SUN50I_ADDA_EARPIECE_CTRL1_ESPPA_MUTE, 1, 0), }; +static int sun50i_codec_hbias_event(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, int event) +{ + struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm); + u32 value = !!SND_SOC_DAPM_EVENT_ON(event); + + regmap_update_bits(component->regmap, SUN50I_ADDA_JACK_MIC_CTRL, + BIT(SUN50I_ADDA_JACK_MIC_CTRL_MICADCEN), + value << SUN50I_ADDA_JACK_MIC_CTRL_MICADCEN); + + return 0; +} + static const struct snd_soc_dapm_widget sun50i_a64_codec_widgets[] = { /* DAC */ SND_SOC_DAPM_DAC("Left DAC", NULL, SUN50I_ADDA_MIX_DAC_CTRL, @@ -367,7 +382,8 @@ static const struct snd_soc_dapm_widget sun50i_a64_codec_widgets[] = { /* Microphone Bias */ SND_SOC_DAPM_SUPPLY("HBIAS", SUN50I_ADDA_JACK_MIC_CTRL, SUN50I_ADDA_JACK_MIC_CTRL_HMICBIASEN, - 0, NULL, 0), + 0, sun50i_codec_hbias_event, + SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD), /* Mic input path */ SND_SOC_DAPM_PGA("Mic2 Amplifier", SUN50I_ADDA_MIC2_CTRL, @@ -474,14 +490,28 @@ static const struct snd_soc_dapm_route sun50i_a64_codec_routes[] = { static int sun50i_a64_codec_set_bias_level(struct snd_soc_component *component, enum snd_soc_bias_level level) { + struct snd_soc_dapm_context *dapm = snd_soc_component_get_dapm(component); + int hbias; + switch (level) { case SND_SOC_BIAS_OFF: + regmap_clear_bits(component->regmap, SUN50I_ADDA_JACK_MIC_CTRL, + BIT(SUN50I_ADDA_JACK_MIC_CTRL_JACKDETEN) | + BIT(SUN50I_ADDA_JACK_MIC_CTRL_MICADCEN)); + regmap_set_bits(component->regmap, SUN50I_ADDA_HP_CTRL, BIT(SUN50I_ADDA_HP_CTRL_PA_CLK_GATE)); break; case SND_SOC_BIAS_STANDBY: regmap_clear_bits(component->regmap, SUN50I_ADDA_HP_CTRL, BIT(SUN50I_ADDA_HP_CTRL_PA_CLK_GATE)); + + hbias = snd_soc_dapm_get_pin_status(dapm, "HBIAS"); + regmap_update_bits(component->regmap, SUN50I_ADDA_JACK_MIC_CTRL, + BIT(SUN50I_ADDA_JACK_MIC_CTRL_JACKDETEN) | + BIT(SUN50I_ADDA_JACK_MIC_CTRL_MICADCEN), + BIT(SUN50I_ADDA_JACK_MIC_CTRL_JACKDETEN) | + hbias << SUN50I_ADDA_JACK_MIC_CTRL_MICADCEN); break; default: break; -- cgit v1.2.3 From 21fa98f4197bb3365dda1417708b318f403c13c1 Mon Sep 17 00:00:00 2001 From: Arnaud Ferraris Date: Sat, 2 Mar 2024 15:00:38 +0100 Subject: ASoC: sun8i-codec: Implement jack and accessory detection Add support for the jack detection functionality in the A64 variant, which uses a pair of IRQs; and microphone accessory (button) detection, which uses an ADC with an IRQ trigger. IRQs will only be triggered if the JACKDETEN, HMICBIASEN, and MICADCEN bits are set appropriately in the analog codec component (sun50i-codec-analog), but there is no direct software dependency between the two components. Setup ADC so that it samples with period of 16ms, disable smoothing and enable MDATA threshold (should be below idle voltage/HMIC_DATA value). Also enable HMIC_N, which makes sure we get HMIC_N samples after HMIC_DATA crosses the threshold. This allows us to perform steady state detection of HMIC_DATA, by comparing current and previous ADC samples, to detect end of the transient when the user de-presses the button. Otherwise ADC could sample anywhere within the transient, and the driver may mis-issue key-press events for other buttons attached to the resistor ladder. [Ondrej: Almost complete rewrite of the patch, change to use set_jack API. Better de-bounce, fix mic button handling, better interrupt processing.] Signed-off-by: Arnaud Ferraris [Samuel: Decouple from analog codec, fixes] Co-developed-by: Samuel Holland Signed-off-by: Samuel Holland Co-developed-by: Ondrej Jirman Signed-off-by: Ondrej Jirman Link: https://msgid.link/r/20240302140042.1990256-5-megi@xff.cz Signed-off-by: Mark Brown --- sound/soc/sunxi/sun50i-codec-analog.c | 12 ++ sound/soc/sunxi/sun8i-codec.c | 305 ++++++++++++++++++++++++++++++++++ 2 files changed, 317 insertions(+) diff --git a/sound/soc/sunxi/sun50i-codec-analog.c b/sound/soc/sunxi/sun50i-codec-analog.c index 2081721a8ff2..2dcdf113b66e 100644 --- a/sound/soc/sunxi/sun50i-codec-analog.c +++ b/sound/soc/sunxi/sun50i-codec-analog.c @@ -115,6 +115,11 @@ #define SUN50I_ADDA_HS_MBIAS_CTRL 0x0e #define SUN50I_ADDA_HS_MBIAS_CTRL_MMICBIASEN 7 +#define SUN50I_ADDA_MDET_CTRL 0x1c +#define SUN50I_ADDA_MDET_CTRL_SELDETADC_FS 4 +#define SUN50I_ADDA_MDET_CTRL_SELDETADC_DB 2 +#define SUN50I_ADDA_MDET_CTRL_SELDETADC_BF 0 + #define SUN50I_ADDA_JACK_MIC_CTRL 0x1d #define SUN50I_ADDA_JACK_MIC_CTRL_JACKDETEN 7 #define SUN50I_ADDA_JACK_MIC_CTRL_INNERRESEN 6 @@ -564,6 +569,13 @@ static int sun50i_codec_analog_probe(struct platform_device *pdev) BIT(SUN50I_ADDA_JACK_MIC_CTRL_INNERRESEN), enable << SUN50I_ADDA_JACK_MIC_CTRL_INNERRESEN); + /* Select sample interval of the ADC sample to 16ms */ + regmap_update_bits(regmap, SUN50I_ADDA_MDET_CTRL, + 0x7 << SUN50I_ADDA_MDET_CTRL_SELDETADC_FS | + 0x3 << SUN50I_ADDA_MDET_CTRL_SELDETADC_BF, + 0x3 << SUN50I_ADDA_MDET_CTRL_SELDETADC_FS | + 0x3 << SUN50I_ADDA_MDET_CTRL_SELDETADC_BF); + return devm_snd_soc_register_component(&pdev->dev, &sun50i_codec_analog_cmpnt_drv, NULL, 0); diff --git a/sound/soc/sunxi/sun8i-codec.c b/sound/soc/sunxi/sun8i-codec.c index 2a46b96b03cc..43795362fed0 100644 --- a/sound/soc/sunxi/sun8i-codec.c +++ b/sound/soc/sunxi/sun8i-codec.c @@ -12,12 +12,16 @@ #include #include #include +#include #include +#include +#include #include #include #include #include +#include #include #include #include @@ -118,6 +122,23 @@ #define SUN8I_ADC_VOL_CTRL 0x104 #define SUN8I_ADC_VOL_CTRL_ADCL_VOL 8 #define SUN8I_ADC_VOL_CTRL_ADCR_VOL 0 +#define SUN8I_HMIC_CTRL1 0x110 +#define SUN8I_HMIC_CTRL1_HMIC_M 12 +#define SUN8I_HMIC_CTRL1_HMIC_N 8 +#define SUN8I_HMIC_CTRL1_MDATA_THRESHOLD_DB 5 +#define SUN8I_HMIC_CTRL1_JACK_OUT_IRQ_EN 4 +#define SUN8I_HMIC_CTRL1_JACK_IN_IRQ_EN 3 +#define SUN8I_HMIC_CTRL1_HMIC_DATA_IRQ_EN 0 +#define SUN8I_HMIC_CTRL2 0x114 +#define SUN8I_HMIC_CTRL2_HMIC_SAMPLE 14 +#define SUN8I_HMIC_CTRL2_HMIC_MDATA_THRESHOLD 8 +#define SUN8I_HMIC_CTRL2_HMIC_SF 6 +#define SUN8I_HMIC_STS 0x118 +#define SUN8I_HMIC_STS_MDATA_DISCARD 13 +#define SUN8I_HMIC_STS_HMIC_DATA 8 +#define SUN8I_HMIC_STS_JACK_OUT_IRQ_ST 4 +#define SUN8I_HMIC_STS_JACK_IN_IRQ_ST 3 +#define SUN8I_HMIC_STS_HMIC_DATA_IRQ_ST 0 #define SUN8I_DAC_DIG_CTRL 0x120 #define SUN8I_DAC_DIG_CTRL_ENDA 15 #define SUN8I_DAC_VOL_CTRL 0x124 @@ -143,6 +164,17 @@ #define SUN8I_AIF_CLK_CTRL_WORD_SIZ_MASK GENMASK(5, 4) #define SUN8I_AIF_CLK_CTRL_DATA_FMT_MASK GENMASK(3, 2) #define SUN8I_AIF3_CLK_CTRL_AIF3_CLK_SRC_MASK GENMASK(1, 0) +#define SUN8I_HMIC_CTRL1_HMIC_M_MASK GENMASK(15, 12) +#define SUN8I_HMIC_CTRL1_HMIC_N_MASK GENMASK(11, 8) +#define SUN8I_HMIC_CTRL1_MDATA_THRESHOLD_DB_MASK GENMASK(6, 5) +#define SUN8I_HMIC_CTRL2_HMIC_SAMPLE_MASK GENMASK(15, 14) +#define SUN8I_HMIC_CTRL2_HMIC_SF_MASK GENMASK(7, 6) +#define SUN8I_HMIC_STS_HMIC_DATA_MASK GENMASK(12, 8) + +#define SUN8I_CODEC_BUTTONS (SND_JACK_BTN_0|\ + SND_JACK_BTN_1|\ + SND_JACK_BTN_2|\ + SND_JACK_BTN_3) #define SUN8I_CODEC_PASSTHROUGH_SAMPLE_RATE 48000 @@ -178,16 +210,32 @@ struct sun8i_codec_aif { struct sun8i_codec_quirks { bool bus_clock : 1; + bool jack_detection : 1; bool legacy_widgets : 1; bool lrck_inversion : 1; }; +enum { + SUN8I_JACK_STATUS_DISCONNECTED, + SUN8I_JACK_STATUS_WAITING_HBIAS, + SUN8I_JACK_STATUS_CONNECTED, +}; + struct sun8i_codec { + struct snd_soc_component *component; struct regmap *regmap; struct clk *clk_bus; struct clk *clk_module; const struct sun8i_codec_quirks *quirks; struct sun8i_codec_aif aifs[SUN8I_CODEC_NAIFS]; + struct snd_soc_jack *jack; + struct delayed_work jack_work; + int jack_irq; + int jack_status; + int jack_last_sample; + ktime_t jack_hbias_ready; + struct mutex jack_mutex; + int last_hmic_irq; unsigned int sysclk_rate; int sysclk_refcnt; }; @@ -1245,6 +1293,8 @@ static int sun8i_codec_component_probe(struct snd_soc_component *component) struct sun8i_codec *scodec = snd_soc_component_get_drvdata(component); int ret; + scodec->component = component; + /* Add widgets for backward compatibility with old device trees. */ if (scodec->quirks->legacy_widgets) { ret = snd_soc_dapm_new_controls(dapm, sun8i_codec_legacy_widgets, @@ -1281,6 +1331,251 @@ static int sun8i_codec_component_probe(struct snd_soc_component *component) return 0; } +static void sun8i_codec_set_hmic_bias(struct sun8i_codec *scodec, bool enable) +{ + struct snd_soc_dapm_context *dapm = &scodec->component->card->dapm; + int irq_mask = BIT(SUN8I_HMIC_CTRL1_HMIC_DATA_IRQ_EN); + + if (enable) + snd_soc_dapm_force_enable_pin(dapm, "HBIAS"); + else + snd_soc_dapm_disable_pin(dapm, "HBIAS"); + + snd_soc_dapm_sync(dapm); + + regmap_update_bits(scodec->regmap, SUN8I_HMIC_CTRL1, + irq_mask, enable ? irq_mask : 0); +} + +static void sun8i_codec_jack_work(struct work_struct *work) +{ + struct sun8i_codec *scodec = container_of(work, struct sun8i_codec, + jack_work.work); + unsigned int mdata; + int type_mask = scodec->jack->jack->type; + int type; + + guard(mutex)(&scodec->jack_mutex); + + if (scodec->jack_status == SUN8I_JACK_STATUS_DISCONNECTED) { + if (scodec->last_hmic_irq != SUN8I_HMIC_STS_JACK_IN_IRQ_ST) + return; + + scodec->jack_last_sample = -1; + + if (type_mask & SND_JACK_MICROPHONE) { + /* + * If we were in disconnected state, we enable HBIAS and + * wait 600ms before reading initial HDATA value. + */ + scodec->jack_hbias_ready = ktime_add_ms(ktime_get(), 600); + sun8i_codec_set_hmic_bias(scodec, true); + queue_delayed_work(system_power_efficient_wq, + &scodec->jack_work, + msecs_to_jiffies(610)); + scodec->jack_status = SUN8I_JACK_STATUS_WAITING_HBIAS; + } else { + snd_soc_jack_report(scodec->jack, SND_JACK_HEADPHONE, + type_mask); + scodec->jack_status = SUN8I_JACK_STATUS_CONNECTED; + } + } else if (scodec->jack_status == SUN8I_JACK_STATUS_WAITING_HBIAS) { + /* + * If we're waiting for HBIAS to stabilize, and we get plug-out + * interrupt and nothing more for > 100ms, just cancel the + * initialization. + */ + if (scodec->last_hmic_irq == SUN8I_HMIC_STS_JACK_OUT_IRQ_ST) { + scodec->jack_status = SUN8I_JACK_STATUS_DISCONNECTED; + sun8i_codec_set_hmic_bias(scodec, false); + return; + } + + /* + * If we're not done waiting for HBIAS to stabilize, wait more. + */ + if (!ktime_after(ktime_get(), scodec->jack_hbias_ready)) { + s64 msecs = ktime_ms_delta(scodec->jack_hbias_ready, + ktime_get()); + + queue_delayed_work(system_power_efficient_wq, + &scodec->jack_work, + msecs_to_jiffies(msecs + 10)); + return; + } + + /* + * Everything is stabilized, determine jack type and report it. + */ + regmap_read(scodec->regmap, SUN8I_HMIC_STS, &mdata); + mdata &= SUN8I_HMIC_STS_HMIC_DATA_MASK; + mdata >>= SUN8I_HMIC_STS_HMIC_DATA; + + regmap_write(scodec->regmap, SUN8I_HMIC_STS, 0); + + type = mdata < 16 ? SND_JACK_HEADPHONE : SND_JACK_HEADSET; + if (type == SND_JACK_HEADPHONE) + sun8i_codec_set_hmic_bias(scodec, false); + + snd_soc_jack_report(scodec->jack, type, type_mask); + scodec->jack_status = SUN8I_JACK_STATUS_CONNECTED; + } else if (scodec->jack_status == SUN8I_JACK_STATUS_CONNECTED) { + if (scodec->last_hmic_irq != SUN8I_HMIC_STS_JACK_OUT_IRQ_ST) + return; + + scodec->jack_status = SUN8I_JACK_STATUS_DISCONNECTED; + if (type_mask & SND_JACK_MICROPHONE) + sun8i_codec_set_hmic_bias(scodec, false); + + snd_soc_jack_report(scodec->jack, 0, type_mask); + } +} + +static irqreturn_t sun8i_codec_jack_irq(int irq, void *dev_id) +{ + struct sun8i_codec *scodec = dev_id; + int type = SND_JACK_HEADSET; + unsigned int status, value; + + guard(mutex)(&scodec->jack_mutex); + + regmap_read(scodec->regmap, SUN8I_HMIC_STS, &status); + regmap_write(scodec->regmap, SUN8I_HMIC_STS, status); + + /* + * De-bounce in/out interrupts via a delayed work re-scheduling to + * 100ms after each interrupt.. + */ + if (status & BIT(SUN8I_HMIC_STS_JACK_OUT_IRQ_ST)) { + /* + * Out interrupt has priority over in interrupt so that if + * we get both, we assume the disconnected state, which is + * safer. + */ + scodec->last_hmic_irq = SUN8I_HMIC_STS_JACK_OUT_IRQ_ST; + mod_delayed_work(system_power_efficient_wq, &scodec->jack_work, + msecs_to_jiffies(100)); + } else if (status & BIT(SUN8I_HMIC_STS_JACK_IN_IRQ_ST)) { + scodec->last_hmic_irq = SUN8I_HMIC_STS_JACK_IN_IRQ_ST; + mod_delayed_work(system_power_efficient_wq, &scodec->jack_work, + msecs_to_jiffies(100)); + } else if (status & BIT(SUN8I_HMIC_STS_HMIC_DATA_IRQ_ST)) { + /* + * Ignore data interrupts until jack status turns to connected + * state, which is after HMIC enable stabilization is completed. + * Until then tha data are bogus. + */ + if (scodec->jack_status != SUN8I_JACK_STATUS_CONNECTED) + return IRQ_HANDLED; + + value = (status & SUN8I_HMIC_STS_HMIC_DATA_MASK) >> + SUN8I_HMIC_STS_HMIC_DATA; + + /* + * Assumes 60 mV per ADC LSB increment, 2V bias voltage, 2.2kOhm + * bias resistor. + */ + if (value == 0) + type |= SND_JACK_BTN_0; + else if (value == 1) + type |= SND_JACK_BTN_3; + else if (value <= 3) + type |= SND_JACK_BTN_1; + else if (value <= 8) + type |= SND_JACK_BTN_2; + + /* + * De-bounce. Only report button after two consecutive A/D + * samples are identical. + */ + if (scodec->jack_last_sample >= 0 && + scodec->jack_last_sample == value) + snd_soc_jack_report(scodec->jack, type, + scodec->jack->jack->type); + + scodec->jack_last_sample = value; + } + + return IRQ_HANDLED; +} + +static int sun8i_codec_enable_jack_detect(struct snd_soc_component *component, + struct snd_soc_jack *jack, void *data) +{ + struct sun8i_codec *scodec = snd_soc_component_get_drvdata(component); + struct platform_device *pdev = to_platform_device(component->dev); + int ret; + + if (!scodec->quirks->jack_detection) + return 0; + + scodec->jack = jack; + + scodec->jack_irq = platform_get_irq(pdev, 0); + if (scodec->jack_irq < 0) + return scodec->jack_irq; + + /* Reserved value required for jack IRQs to trigger. */ + regmap_write(scodec->regmap, SUN8I_HMIC_CTRL1, + 0xf << SUN8I_HMIC_CTRL1_HMIC_N | + 0x0 << SUN8I_HMIC_CTRL1_MDATA_THRESHOLD_DB | + 0x4 << SUN8I_HMIC_CTRL1_HMIC_M); + + /* Sample the ADC at 128 Hz; bypass smooth filter. */ + regmap_write(scodec->regmap, SUN8I_HMIC_CTRL2, + 0x0 << SUN8I_HMIC_CTRL2_HMIC_SAMPLE | + 0x17 << SUN8I_HMIC_CTRL2_HMIC_MDATA_THRESHOLD | + 0x0 << SUN8I_HMIC_CTRL2_HMIC_SF); + + /* Do not discard any MDATA, enable user written MDATA threshold. */ + regmap_write(scodec->regmap, SUN8I_HMIC_STS, 0); + + regmap_set_bits(scodec->regmap, SUN8I_HMIC_CTRL1, + BIT(SUN8I_HMIC_CTRL1_JACK_OUT_IRQ_EN) | + BIT(SUN8I_HMIC_CTRL1_JACK_IN_IRQ_EN)); + + ret = devm_request_threaded_irq(&pdev->dev, scodec->jack_irq, + NULL, sun8i_codec_jack_irq, + IRQF_ONESHOT, + dev_name(&pdev->dev), scodec); + if (ret) + return ret; + + return 0; +} + +static void sun8i_codec_disable_jack_detect(struct snd_soc_component *component) +{ + struct sun8i_codec *scodec = snd_soc_component_get_drvdata(component); + + if (!scodec->quirks->jack_detection) + return; + + devm_free_irq(component->dev, scodec->jack_irq, scodec); + + cancel_delayed_work_sync(&scodec->jack_work); + + regmap_clear_bits(scodec->regmap, SUN8I_HMIC_CTRL1, + BIT(SUN8I_HMIC_CTRL1_JACK_OUT_IRQ_EN) | + BIT(SUN8I_HMIC_CTRL1_JACK_IN_IRQ_EN) | + BIT(SUN8I_HMIC_CTRL1_HMIC_DATA_IRQ_EN)); + + scodec->jack = NULL; +} + +static int sun8i_codec_component_set_jack(struct snd_soc_component *component, + struct snd_soc_jack *jack, void *data) +{ + int ret = 0; + + if (jack) + ret = sun8i_codec_enable_jack_detect(component, jack, data); + else + sun8i_codec_disable_jack_detect(component); + + return ret; +} + static const struct snd_soc_component_driver sun8i_soc_component = { .controls = sun8i_codec_controls, .num_controls = ARRAY_SIZE(sun8i_codec_controls), @@ -1288,16 +1583,23 @@ static const struct snd_soc_component_driver sun8i_soc_component = { .num_dapm_widgets = ARRAY_SIZE(sun8i_codec_dapm_widgets), .dapm_routes = sun8i_codec_dapm_routes, .num_dapm_routes = ARRAY_SIZE(sun8i_codec_dapm_routes), + .set_jack = sun8i_codec_component_set_jack, .probe = sun8i_codec_component_probe, .idle_bias_on = 1, .suspend_bias_off = 1, .endianness = 1, }; +static bool sun8i_codec_volatile_reg(struct device *dev, unsigned int reg) +{ + return reg == SUN8I_HMIC_STS; +} + static const struct regmap_config sun8i_codec_regmap_config = { .reg_bits = 32, .reg_stride = 4, .val_bits = 32, + .volatile_reg = sun8i_codec_volatile_reg, .max_register = SUN8I_DAC_MXR_SRC, .cache_type = REGCACHE_FLAT, @@ -1314,6 +1616,8 @@ static int sun8i_codec_probe(struct platform_device *pdev) return -ENOMEM; scodec->quirks = of_device_get_match_data(&pdev->dev); + INIT_DELAYED_WORK(&scodec->jack_work, sun8i_codec_jack_work); + mutex_init(&scodec->jack_mutex); platform_set_drvdata(pdev, scodec); @@ -1387,6 +1691,7 @@ static const struct sun8i_codec_quirks sun8i_a33_quirks = { static const struct sun8i_codec_quirks sun50i_a64_quirks = { .bus_clock = true, + .jack_detection = true, }; static const struct of_device_id sun8i_codec_of_match[] = { -- cgit v1.2.3 From 0cb3b7fd530b8c107443218ce6db5cb6e7b5dbe1 Mon Sep 17 00:00:00 2001 From: Cezary Rojewski Date: Fri, 8 Mar 2024 10:04:58 +0100 Subject: ASoC: Intel: Disable route checks for Skylake boards Topology files that are propagated to the world and utilized by the skylake-driver carry shortcomings in their SectionGraphs. Since commit daa480bde6b3 ("ASoC: soc-core: tidyup for snd_soc_dapm_add_routes()") route checks are no longer permissive. Probe failures for Intel boards have been partially addressed by commit a22ae72b86a4 ("ASoC: soc-core: disable route checks for legacy devices") and its follow up but only skl_nau88l25_ssm4567.c is patched. Fix the problem for the rest of the boards. Link: https://lore.kernel.org/all/20200309192744.18380-1-pierre-louis.bossart@linux.intel.com/ Fixes: daa480bde6b3 ("ASoC: soc-core: tidyup for snd_soc_dapm_add_routes()") Signed-off-by: Cezary Rojewski Link: https://msgid.link/r/20240308090502.2136760-2-cezary.rojewski@intel.com Reviewed-by: Pierre-Louis Bossart Signed-off-by: Mark Brown --- sound/soc/intel/boards/bxt_da7219_max98357a.c | 1 + sound/soc/intel/boards/bxt_rt298.c | 1 + sound/soc/intel/boards/glk_rt5682_max98357a.c | 2 ++ sound/soc/intel/boards/kbl_da7219_max98357a.c | 1 + sound/soc/intel/boards/kbl_da7219_max98927.c | 4 ++++ sound/soc/intel/boards/kbl_rt5660.c | 1 + sound/soc/intel/boards/kbl_rt5663_max98927.c | 2 ++ sound/soc/intel/boards/kbl_rt5663_rt5514_max98927.c | 1 + sound/soc/intel/boards/skl_hda_dsp_generic.c | 2 ++ sound/soc/intel/boards/skl_nau88l25_max98357a.c | 1 + sound/soc/intel/boards/skl_rt286.c | 1 + 11 files changed, 17 insertions(+) diff --git a/sound/soc/intel/boards/bxt_da7219_max98357a.c b/sound/soc/intel/boards/bxt_da7219_max98357a.c index 540f7a29310a..3fe3f38c6cb6 100644 --- a/sound/soc/intel/boards/bxt_da7219_max98357a.c +++ b/sound/soc/intel/boards/bxt_da7219_max98357a.c @@ -768,6 +768,7 @@ static struct snd_soc_card broxton_audio_card = { .dapm_routes = audio_map, .num_dapm_routes = ARRAY_SIZE(audio_map), .fully_routed = true, + .disable_route_checks = true, .late_probe = bxt_card_late_probe, }; diff --git a/sound/soc/intel/boards/bxt_rt298.c b/sound/soc/intel/boards/bxt_rt298.c index c0eb65c14aa9..afc499be8db2 100644 --- a/sound/soc/intel/boards/bxt_rt298.c +++ b/sound/soc/intel/boards/bxt_rt298.c @@ -574,6 +574,7 @@ static struct snd_soc_card broxton_rt298 = { .dapm_routes = broxton_rt298_map, .num_dapm_routes = ARRAY_SIZE(broxton_rt298_map), .fully_routed = true, + .disable_route_checks = true, .late_probe = bxt_card_late_probe, }; diff --git a/sound/soc/intel/boards/glk_rt5682_max98357a.c b/sound/soc/intel/boards/glk_rt5682_max98357a.c index 657e4658234c..4098b2d32f9b 100644 --- a/sound/soc/intel/boards/glk_rt5682_max98357a.c +++ b/sound/soc/intel/boards/glk_rt5682_max98357a.c @@ -649,6 +649,8 @@ static int geminilake_audio_probe(struct platform_device *pdev) card = &glk_audio_card_rt5682_m98357a; card->dev = &pdev->dev; snd_soc_card_set_drvdata(card, ctx); + if (!snd_soc_acpi_sof_parent(&pdev->dev)) + card->disable_route_checks = true; /* override platform name, if required */ mach = pdev->dev.platform_data; diff --git a/sound/soc/intel/boards/kbl_da7219_max98357a.c b/sound/soc/intel/boards/kbl_da7219_max98357a.c index a5d8965303a8..9dbc15f9d1c9 100644 --- a/sound/soc/intel/boards/kbl_da7219_max98357a.c +++ b/sound/soc/intel/boards/kbl_da7219_max98357a.c @@ -639,6 +639,7 @@ static struct snd_soc_card kabylake_audio_card_da7219_m98357a = { .dapm_routes = kabylake_map, .num_dapm_routes = ARRAY_SIZE(kabylake_map), .fully_routed = true, + .disable_route_checks = true, .late_probe = kabylake_card_late_probe, }; diff --git a/sound/soc/intel/boards/kbl_da7219_max98927.c b/sound/soc/intel/boards/kbl_da7219_max98927.c index 98c11ec0adc0..e662da5af83b 100644 --- a/sound/soc/intel/boards/kbl_da7219_max98927.c +++ b/sound/soc/intel/boards/kbl_da7219_max98927.c @@ -1036,6 +1036,7 @@ static struct snd_soc_card kbl_audio_card_da7219_m98927 = { .codec_conf = max98927_codec_conf, .num_configs = ARRAY_SIZE(max98927_codec_conf), .fully_routed = true, + .disable_route_checks = true, .late_probe = kabylake_card_late_probe, }; @@ -1054,6 +1055,7 @@ static struct snd_soc_card kbl_audio_card_max98927 = { .codec_conf = max98927_codec_conf, .num_configs = ARRAY_SIZE(max98927_codec_conf), .fully_routed = true, + .disable_route_checks = true, .late_probe = kabylake_card_late_probe, }; @@ -1071,6 +1073,7 @@ static struct snd_soc_card kbl_audio_card_da7219_m98373 = { .codec_conf = max98373_codec_conf, .num_configs = ARRAY_SIZE(max98373_codec_conf), .fully_routed = true, + .disable_route_checks = true, .late_probe = kabylake_card_late_probe, }; @@ -1088,6 +1091,7 @@ static struct snd_soc_card kbl_audio_card_max98373 = { .codec_conf = max98373_codec_conf, .num_configs = ARRAY_SIZE(max98373_codec_conf), .fully_routed = true, + .disable_route_checks = true, .late_probe = kabylake_card_late_probe, }; diff --git a/sound/soc/intel/boards/kbl_rt5660.c b/sound/soc/intel/boards/kbl_rt5660.c index 30e0aca161cd..894d127c482a 100644 --- a/sound/soc/intel/boards/kbl_rt5660.c +++ b/sound/soc/intel/boards/kbl_rt5660.c @@ -518,6 +518,7 @@ static struct snd_soc_card kabylake_audio_card_rt5660 = { .dapm_routes = kabylake_rt5660_map, .num_dapm_routes = ARRAY_SIZE(kabylake_rt5660_map), .fully_routed = true, + .disable_route_checks = true, .late_probe = kabylake_card_late_probe, }; diff --git a/sound/soc/intel/boards/kbl_rt5663_max98927.c b/sound/soc/intel/boards/kbl_rt5663_max98927.c index 9071b1f1cbd0..646e8ff8e961 100644 --- a/sound/soc/intel/boards/kbl_rt5663_max98927.c +++ b/sound/soc/intel/boards/kbl_rt5663_max98927.c @@ -966,6 +966,7 @@ static struct snd_soc_card kabylake_audio_card_rt5663_m98927 = { .codec_conf = max98927_codec_conf, .num_configs = ARRAY_SIZE(max98927_codec_conf), .fully_routed = true, + .disable_route_checks = true, .late_probe = kabylake_card_late_probe, }; @@ -982,6 +983,7 @@ static struct snd_soc_card kabylake_audio_card_rt5663 = { .dapm_routes = kabylake_5663_map, .num_dapm_routes = ARRAY_SIZE(kabylake_5663_map), .fully_routed = true, + .disable_route_checks = true, .late_probe = kabylake_card_late_probe, }; diff --git a/sound/soc/intel/boards/kbl_rt5663_rt5514_max98927.c b/sound/soc/intel/boards/kbl_rt5663_rt5514_max98927.c index 178fe9c37df6..924d5d1de03a 100644 --- a/sound/soc/intel/boards/kbl_rt5663_rt5514_max98927.c +++ b/sound/soc/intel/boards/kbl_rt5663_rt5514_max98927.c @@ -791,6 +791,7 @@ static struct snd_soc_card kabylake_audio_card = { .codec_conf = max98927_codec_conf, .num_configs = ARRAY_SIZE(max98927_codec_conf), .fully_routed = true, + .disable_route_checks = true, .late_probe = kabylake_card_late_probe, }; diff --git a/sound/soc/intel/boards/skl_hda_dsp_generic.c b/sound/soc/intel/boards/skl_hda_dsp_generic.c index 6e172719c979..4aa7fd2a05e4 100644 --- a/sound/soc/intel/boards/skl_hda_dsp_generic.c +++ b/sound/soc/intel/boards/skl_hda_dsp_generic.c @@ -227,6 +227,8 @@ static int skl_hda_audio_probe(struct platform_device *pdev) ctx->common_hdmi_codec_drv = mach->mach_params.common_hdmi_codec_drv; hda_soc_card.dev = &pdev->dev; + if (!snd_soc_acpi_sof_parent(&pdev->dev)) + hda_soc_card.disable_route_checks = true; if (mach->mach_params.dmic_num > 0) { snprintf(hda_soc_components, sizeof(hda_soc_components), diff --git a/sound/soc/intel/boards/skl_nau88l25_max98357a.c b/sound/soc/intel/boards/skl_nau88l25_max98357a.c index 0e7025834594..e4630c33176e 100644 --- a/sound/soc/intel/boards/skl_nau88l25_max98357a.c +++ b/sound/soc/intel/boards/skl_nau88l25_max98357a.c @@ -654,6 +654,7 @@ static struct snd_soc_card skylake_audio_card = { .dapm_routes = skylake_map, .num_dapm_routes = ARRAY_SIZE(skylake_map), .fully_routed = true, + .disable_route_checks = true, .late_probe = skylake_card_late_probe, }; diff --git a/sound/soc/intel/boards/skl_rt286.c b/sound/soc/intel/boards/skl_rt286.c index c59c60e28091..9a8044274908 100644 --- a/sound/soc/intel/boards/skl_rt286.c +++ b/sound/soc/intel/boards/skl_rt286.c @@ -523,6 +523,7 @@ static struct snd_soc_card skylake_rt286 = { .dapm_routes = skylake_rt286_map, .num_dapm_routes = ARRAY_SIZE(skylake_rt286_map), .fully_routed = true, + .disable_route_checks = true, .late_probe = skylake_card_late_probe, }; -- cgit v1.2.3 From 6974857c2b2c7e2d2db59c0e23cc42b0efc58cd8 Mon Sep 17 00:00:00 2001 From: Cezary Rojewski Date: Fri, 8 Mar 2024 10:04:59 +0100 Subject: ASoC: topology: Do not ignore route checks when parsing graphs One of the framework responsibilities is to ensure that the enumerated DPCMs are valid i.e.: a valid BE is connected to a valid FE DAI. While the are checks in soc-core.c and soc-pcm.c that verify this, a component driver may attempt to workaround this by loading an invalid graph through the topology file. Be strict and fail topology loading when invalid graph is encountered. Signed-off-by: Cezary Rojewski Link: https://msgid.link/r/20240308090502.2136760-3-cezary.rojewski@intel.com Reviewed-by: Pierre-Louis Bossart Signed-off-by: Mark Brown --- sound/soc/soc-topology.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/sound/soc/soc-topology.c b/sound/soc/soc-topology.c index ba4890991f0d..fad9432a10f1 100644 --- a/sound/soc/soc-topology.c +++ b/sound/soc/soc-topology.c @@ -1083,8 +1083,15 @@ static int soc_tplg_dapm_graph_elems_load(struct soc_tplg *tplg, break; } - /* add route, but keep going if some fail */ - snd_soc_dapm_add_routes(dapm, route, 1); + ret = snd_soc_dapm_add_routes(dapm, route, 1); + if (ret) { + if (!dapm->card->disable_route_checks) { + dev_err(tplg->dev, "ASoC: dapm_add_routes failed: %d\n", ret); + break; + } + dev_info(tplg->dev, + "ASoC: disable_route_checks set, ignoring dapm_add_routes errors\n"); + } } return ret; -- cgit v1.2.3 From e6719d48ba6329536c459dcee5a571e535687094 Mon Sep 17 00:00:00 2001 From: Cezary Rojewski Date: Fri, 8 Mar 2024 10:05:00 +0100 Subject: ASoC: Intel: avs: ssm4567: Do not ignore route checks A copy-paste from intel/boards/skl_nau88l25_ssm4567.c made the avs's equivalent disable route checks as well. Such behavior is not desired. Fixes: 69ea14efe99b ("ASoC: Intel: avs: Add ssm4567 machine board") Signed-off-by: Cezary Rojewski Link: https://msgid.link/r/20240308090502.2136760-4-cezary.rojewski@intel.com Signed-off-by: Mark Brown --- sound/soc/intel/avs/boards/ssm4567.c | 1 - 1 file changed, 1 deletion(-) diff --git a/sound/soc/intel/avs/boards/ssm4567.c b/sound/soc/intel/avs/boards/ssm4567.c index 4a0e136835ff..b64be685dc23 100644 --- a/sound/soc/intel/avs/boards/ssm4567.c +++ b/sound/soc/intel/avs/boards/ssm4567.c @@ -172,7 +172,6 @@ static int avs_ssm4567_probe(struct platform_device *pdev) card->dapm_routes = card_base_routes; card->num_dapm_routes = ARRAY_SIZE(card_base_routes); card->fully_routed = true; - card->disable_route_checks = true; ret = snd_soc_fixup_dai_links_platform_name(card, pname); if (ret) -- cgit v1.2.3 From 3a2be3f05110fa1a5c682ff72a26681ed4f54cef Mon Sep 17 00:00:00 2001 From: Cezary Rojewski Date: Fri, 8 Mar 2024 10:05:01 +0100 Subject: ASoC: Intel: avs: ssm4567: Board cleanup The card-name suffix and the DP-widgets are an unintended copy-paste from skl_nau88215_ssm4567.c. Both are redundant. Signed-off-by: Cezary Rojewski Link: https://msgid.link/r/20240308090502.2136760-5-cezary.rojewski@intel.com Signed-off-by: Mark Brown --- sound/soc/intel/avs/boards/ssm4567.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/sound/soc/intel/avs/boards/ssm4567.c b/sound/soc/intel/avs/boards/ssm4567.c index b64be685dc23..abb87bb88fff 100644 --- a/sound/soc/intel/avs/boards/ssm4567.c +++ b/sound/soc/intel/avs/boards/ssm4567.c @@ -37,8 +37,6 @@ static const struct snd_kcontrol_new card_controls[] = { static const struct snd_soc_dapm_widget card_widgets[] = { SND_SOC_DAPM_SPK("Left Speaker", NULL), SND_SOC_DAPM_SPK("Right Speaker", NULL), - SND_SOC_DAPM_SPK("DP1", NULL), - SND_SOC_DAPM_SPK("DP2", NULL), }; static const struct snd_soc_dapm_route card_base_routes[] = { @@ -158,7 +156,7 @@ static int avs_ssm4567_probe(struct platform_device *pdev) if (!card) return -ENOMEM; - card->name = "avs_ssm4567-adi"; + card->name = "avs_ssm4567"; card->dev = dev; card->owner = THIS_MODULE; card->dai_link = dai_link; -- cgit v1.2.3 From 60c10c678b582d41532fefa12667d8adca75811b Mon Sep 17 00:00:00 2001 From: Amadeusz Sławiński Date: Fri, 8 Mar 2024 10:05:02 +0100 Subject: ASoC: Intel: avs: i2s_test: Remove redundant dapm routes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Remove unnecessary widgets and routes as they are created by snd_soc_dapm_connect_dai_link_widgets() automatically. Link: https://lore.kernel.org/all/20230612110958.592674-1-brent.lu@intel.com/ Signed-off-by: Amadeusz Sławiński Signed-off-by: Cezary Rojewski Link: https://msgid.link/r/20240308090502.2136760-6-cezary.rojewski@intel.com Signed-off-by: Mark Brown --- sound/soc/intel/avs/boards/i2s_test.c | 79 ----------------------------------- 1 file changed, 79 deletions(-) diff --git a/sound/soc/intel/avs/boards/i2s_test.c b/sound/soc/intel/avs/boards/i2s_test.c index 28f254eb0d03..282256d18cc6 100644 --- a/sound/soc/intel/avs/boards/i2s_test.c +++ b/sound/soc/intel/avs/boards/i2s_test.c @@ -54,76 +54,13 @@ static int avs_create_dai_link(struct device *dev, const char *platform_name, in return 0; } -static int avs_create_dapm_routes(struct device *dev, int ssp_port, int tdm_slot, - struct snd_soc_dapm_route **routes, int *num_routes) -{ - struct snd_soc_dapm_route *dr; - const int num_dr = 2; - - dr = devm_kcalloc(dev, num_dr, sizeof(*dr), GFP_KERNEL); - if (!dr) - return -ENOMEM; - - dr[0].sink = devm_kasprintf(dev, GFP_KERNEL, - AVS_STRING_FMT("ssp", "pb", ssp_port, tdm_slot)); - dr[0].source = devm_kasprintf(dev, GFP_KERNEL, - AVS_STRING_FMT("ssp", " Tx", ssp_port, tdm_slot)); - if (!dr[0].sink || !dr[0].source) - return -ENOMEM; - - dr[1].sink = devm_kasprintf(dev, GFP_KERNEL, - AVS_STRING_FMT("ssp", " Rx", ssp_port, tdm_slot)); - dr[1].source = devm_kasprintf(dev, GFP_KERNEL, - AVS_STRING_FMT("ssp", "cp", ssp_port, tdm_slot)); - if (!dr[1].sink || !dr[1].source) - return -ENOMEM; - - *routes = dr; - *num_routes = num_dr; - - return 0; -} - -static int avs_create_dapm_widgets(struct device *dev, int ssp_port, int tdm_slot, - struct snd_soc_dapm_widget **widgets, int *num_widgets) -{ - struct snd_soc_dapm_widget *dw; - const int num_dw = 2; - - dw = devm_kcalloc(dev, num_dw, sizeof(*dw), GFP_KERNEL); - if (!dw) - return -ENOMEM; - - dw[0].id = snd_soc_dapm_hp; - dw[0].reg = SND_SOC_NOPM; - dw[0].name = devm_kasprintf(dev, GFP_KERNEL, - AVS_STRING_FMT("ssp", "pb", ssp_port, tdm_slot)); - if (!dw[0].name) - return -ENOMEM; - - dw[1].id = snd_soc_dapm_mic; - dw[1].reg = SND_SOC_NOPM; - dw[1].name = devm_kasprintf(dev, GFP_KERNEL, - AVS_STRING_FMT("ssp", "cp", ssp_port, tdm_slot)); - if (!dw[1].name) - return -ENOMEM; - - *widgets = dw; - *num_widgets = num_dw; - - return 0; -} - static int avs_i2s_test_probe(struct platform_device *pdev) { - struct snd_soc_dapm_widget *widgets; - struct snd_soc_dapm_route *routes; struct snd_soc_dai_link *dai_link; struct snd_soc_acpi_mach *mach; struct snd_soc_card *card; struct device *dev = &pdev->dev; const char *pname; - int num_routes, num_widgets; int ssp_port, tdm_slot, ret; mach = dev_get_platdata(dev); @@ -156,26 +93,10 @@ static int avs_i2s_test_probe(struct platform_device *pdev) return ret; } - ret = avs_create_dapm_routes(dev, ssp_port, tdm_slot, &routes, &num_routes); - if (ret) { - dev_err(dev, "Failed to create dapm routes: %d\n", ret); - return ret; - } - - ret = avs_create_dapm_widgets(dev, ssp_port, tdm_slot, &widgets, &num_widgets); - if (ret) { - dev_err(dev, "Failed to create dapm widgets: %d\n", ret); - return ret; - } - card->dev = dev; card->owner = THIS_MODULE; card->dai_link = dai_link; card->num_links = 1; - card->dapm_routes = routes; - card->num_dapm_routes = num_routes; - card->dapm_widgets = widgets; - card->num_dapm_widgets = num_widgets; card->fully_routed = true; ret = snd_soc_fixup_dai_links_platform_name(card, pname); -- cgit v1.2.3 From 41f96cd53f2838ac4894491ac5eadb06f1e5b858 Mon Sep 17 00:00:00 2001 From: Chancel Liu Date: Mon, 11 Mar 2024 20:13:45 +0900 Subject: ASoC: fsl: imx-pcm-rpmsg: Register component with rpmsg channel name Machine driver uses rpmsg channel name to link this platform component. However if the component is re-registerd card will not find this new created component in snd_soc_try_rebind_card(). Explicitly register this component with rpmsg channel name so that card can always find this component. Signed-off-by: Chancel Liu Link: https://msgid.link/r/20240311111349.723256-2-chancel.liu@nxp.com Acked-by: Shengjiu Wang Signed-off-by: Mark Brown --- sound/soc/fsl/imx-pcm-rpmsg.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/sound/soc/fsl/imx-pcm-rpmsg.c b/sound/soc/fsl/imx-pcm-rpmsg.c index fb9244c1e9c5..b84d1dfddba2 100644 --- a/sound/soc/fsl/imx-pcm-rpmsg.c +++ b/sound/soc/fsl/imx-pcm-rpmsg.c @@ -732,9 +732,6 @@ static int imx_rpmsg_pcm_probe(struct platform_device *pdev) goto fail; } - /* platform component name is used by machine driver to link with */ - component->name = info->rpdev->id.name; - #ifdef CONFIG_DEBUG_FS component->debugfs_prefix = "rpmsg"; #endif @@ -822,9 +819,17 @@ static const struct dev_pm_ops imx_rpmsg_pcm_pm_ops = { imx_rpmsg_pcm_resume) }; +static const struct platform_device_id imx_rpmsg_pcm_id_table[] = { + { .name = "rpmsg-audio-channel" }, + { .name = "rpmsg-micfil-channel" }, + { }, +}; +MODULE_DEVICE_TABLE(platform, imx_rpmsg_pcm_id_table); + static struct platform_driver imx_pcm_rpmsg_driver = { .probe = imx_rpmsg_pcm_probe, .remove_new = imx_rpmsg_pcm_remove, + .id_table = imx_rpmsg_pcm_id_table, .driver = { .name = IMX_PCM_DRV_NAME, .pm = &imx_rpmsg_pcm_pm_ops, -- cgit v1.2.3 From dacc7459745df168152b5cceba34efade9b5e063 Mon Sep 17 00:00:00 2001 From: Chancel Liu Date: Mon, 11 Mar 2024 20:13:46 +0900 Subject: ASoC: fsl: imx-audio-rpmsg: Register device with rpmsg channel name This rpmsg driver registers device for ASoC platform driver. To align with platform driver use rpmsg channel name to create device. Signed-off-by: Chancel Liu Link: https://msgid.link/r/20240311111349.723256-3-chancel.liu@nxp.com Acked-by: Shengjiu Wang Signed-off-by: Mark Brown --- sound/soc/fsl/imx-audio-rpmsg.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/soc/fsl/imx-audio-rpmsg.c b/sound/soc/fsl/imx-audio-rpmsg.c index 289e47c03d40..40820d5ad92d 100644 --- a/sound/soc/fsl/imx-audio-rpmsg.c +++ b/sound/soc/fsl/imx-audio-rpmsg.c @@ -87,8 +87,8 @@ static int imx_audio_rpmsg_probe(struct rpmsg_device *rpdev) /* Register platform driver for rpmsg routine */ data->rpmsg_pdev = platform_device_register_data(&rpdev->dev, - IMX_PCM_DRV_NAME, - PLATFORM_DEVID_AUTO, + rpdev->id.name, + PLATFORM_DEVID_NONE, NULL, 0); if (IS_ERR(data->rpmsg_pdev)) { dev_err(&rpdev->dev, "failed to register rpmsg platform.\n"); -- cgit v1.2.3 From c73524768e9e1a7ac9eb3a4d36a1ac0d34f22644 Mon Sep 17 00:00:00 2001 From: Chancel Liu Date: Mon, 11 Mar 2024 20:13:47 +0900 Subject: ASoC: fsl: Let imx-audio-rpmsg register platform device for card Let imx-audio-rpmsg register platform device for card. So that card register and unregister can be controlled by rpmsg driver's register and unregister. Signed-off-by: Chancel Liu Link: https://msgid.link/r/20240311111349.723256-4-chancel.liu@nxp.com Acked-by: Shengjiu Wang Signed-off-by: Mark Brown --- sound/soc/fsl/fsl_rpmsg.c | 11 ----------- sound/soc/fsl/imx-audio-rpmsg.c | 17 ++++++++++++++++- 2 files changed, 16 insertions(+), 12 deletions(-) diff --git a/sound/soc/fsl/fsl_rpmsg.c b/sound/soc/fsl/fsl_rpmsg.c index 00852f174a69..53bd517e59d6 100644 --- a/sound/soc/fsl/fsl_rpmsg.c +++ b/sound/soc/fsl/fsl_rpmsg.c @@ -240,17 +240,6 @@ static int fsl_rpmsg_probe(struct platform_device *pdev) if (ret) goto err_pm_disable; - rpmsg->card_pdev = platform_device_register_data(&pdev->dev, - "imx-audio-rpmsg", - PLATFORM_DEVID_AUTO, - NULL, - 0); - if (IS_ERR(rpmsg->card_pdev)) { - dev_err(&pdev->dev, "failed to register rpmsg card\n"); - ret = PTR_ERR(rpmsg->card_pdev); - goto err_pm_disable; - } - return 0; err_pm_disable: diff --git a/sound/soc/fsl/imx-audio-rpmsg.c b/sound/soc/fsl/imx-audio-rpmsg.c index 40820d5ad92d..38aafb8954c7 100644 --- a/sound/soc/fsl/imx-audio-rpmsg.c +++ b/sound/soc/fsl/imx-audio-rpmsg.c @@ -12,6 +12,7 @@ */ struct imx_audio_rpmsg { struct platform_device *rpmsg_pdev; + struct platform_device *card_pdev; }; static int imx_audio_rpmsg_cb(struct rpmsg_device *rpdev, void *data, int len, @@ -95,6 +96,16 @@ static int imx_audio_rpmsg_probe(struct rpmsg_device *rpdev) ret = PTR_ERR(data->rpmsg_pdev); } + data->card_pdev = platform_device_register_data(&rpdev->dev, + "imx-audio-rpmsg", + PLATFORM_DEVID_AUTO, + rpdev->id.name, + strlen(rpdev->id.name) + 1); + if (IS_ERR(data->card_pdev)) { + dev_err(&rpdev->dev, "failed to register rpmsg card.\n"); + ret = PTR_ERR(data->card_pdev); + } + return ret; } @@ -105,6 +116,9 @@ static void imx_audio_rpmsg_remove(struct rpmsg_device *rpdev) if (data->rpmsg_pdev) platform_device_unregister(data->rpmsg_pdev); + if (data->card_pdev) + platform_device_unregister(data->card_pdev); + dev_info(&rpdev->dev, "audio rpmsg driver is removed\n"); } @@ -113,6 +127,7 @@ static struct rpmsg_device_id imx_audio_rpmsg_id_table[] = { { .name = "rpmsg-micfil-channel" }, { }, }; +MODULE_DEVICE_TABLE(rpmsg, imx_audio_rpmsg_id_table); static struct rpmsg_driver imx_audio_rpmsg_driver = { .drv.name = "imx_audio_rpmsg", @@ -126,5 +141,5 @@ module_rpmsg_driver(imx_audio_rpmsg_driver); MODULE_DESCRIPTION("Freescale SoC Audio RPMSG interface"); MODULE_AUTHOR("Shengjiu Wang "); -MODULE_ALIAS("platform:imx_audio_rpmsg"); +MODULE_ALIAS("rpmsg:imx_audio_rpmsg"); MODULE_LICENSE("GPL v2"); -- cgit v1.2.3 From 0aa7f5406afa828a93d84d75c9b9ac991cd75367 Mon Sep 17 00:00:00 2001 From: Chancel Liu Date: Mon, 11 Mar 2024 20:13:48 +0900 Subject: ASoC: fsl: fsl_rpmsg: Register CPU DAI with name of rpmsg channel Each rpmsg sound card sits on one rpmsg channel. Register CPU DAI with name of rpmsg channel so that ASoC machine driver can easily link CPU DAI with rpmsg channel name. Signed-off-by: Chancel Liu Link: https://msgid.link/r/20240311111349.723256-5-chancel.liu@nxp.com Acked-by: Shengjiu Wang Signed-off-by: Mark Brown --- sound/soc/fsl/fsl_rpmsg.c | 32 ++++++++++++++++++++++++++------ 1 file changed, 26 insertions(+), 6 deletions(-) diff --git a/sound/soc/fsl/fsl_rpmsg.c b/sound/soc/fsl/fsl_rpmsg.c index 53bd517e59d6..bc41a0666856 100644 --- a/sound/soc/fsl/fsl_rpmsg.c +++ b/sound/soc/fsl/fsl_rpmsg.c @@ -135,7 +135,6 @@ static struct snd_soc_dai_driver fsl_rpmsg_dai = { static const struct snd_soc_component_driver fsl_component = { .name = "fsl-rpmsg", - .legacy_dai_naming = 1, }; static const struct fsl_rpmsg_soc_data imx7ulp_data = { @@ -190,19 +189,40 @@ MODULE_DEVICE_TABLE(of, fsl_rpmsg_ids); static int fsl_rpmsg_probe(struct platform_device *pdev) { struct device_node *np = pdev->dev.of_node; + struct snd_soc_dai_driver *dai_drv; + const char *dai_name; struct fsl_rpmsg *rpmsg; int ret; + dai_drv = devm_kzalloc(&pdev->dev, sizeof(struct snd_soc_dai_driver), GFP_KERNEL); + if (!dai_drv) + return -ENOMEM; + memcpy(dai_drv, &fsl_rpmsg_dai, sizeof(fsl_rpmsg_dai)); + rpmsg = devm_kzalloc(&pdev->dev, sizeof(struct fsl_rpmsg), GFP_KERNEL); if (!rpmsg) return -ENOMEM; rpmsg->soc_data = of_device_get_match_data(&pdev->dev); - fsl_rpmsg_dai.playback.rates = rpmsg->soc_data->rates; - fsl_rpmsg_dai.capture.rates = rpmsg->soc_data->rates; - fsl_rpmsg_dai.playback.formats = rpmsg->soc_data->formats; - fsl_rpmsg_dai.capture.formats = rpmsg->soc_data->formats; + if (rpmsg->soc_data) { + dai_drv->playback.rates = rpmsg->soc_data->rates; + dai_drv->capture.rates = rpmsg->soc_data->rates; + dai_drv->playback.formats = rpmsg->soc_data->formats; + dai_drv->capture.formats = rpmsg->soc_data->formats; + } + + /* Use rpmsg channel name as cpu dai name */ + ret = of_property_read_string(np, "fsl,rpmsg-channel-name", &dai_name); + if (ret) { + if (ret == -EINVAL) { + dai_name = "rpmsg-audio-channel"; + } else { + dev_err(&pdev->dev, "Failed to get rpmsg channel name: %d!\n", ret); + return ret; + } + } + dai_drv->name = dai_name; if (of_property_read_bool(np, "fsl,enable-lpa")) { rpmsg->enable_lpa = 1; @@ -236,7 +256,7 @@ static int fsl_rpmsg_probe(struct platform_device *pdev) pm_runtime_enable(&pdev->dev); ret = devm_snd_soc_register_component(&pdev->dev, &fsl_component, - &fsl_rpmsg_dai, 1); + dai_drv, 1); if (ret) goto err_pm_disable; -- cgit v1.2.3 From c14445bdcb98feddf9afaeb05e6193cc1f8eec1a Mon Sep 17 00:00:00 2001 From: Chancel Liu Date: Mon, 11 Mar 2024 20:13:49 +0900 Subject: ASoC: fsl: imx-rpmsg: Update to correct DT node In order to support register and unregister rpmsg sound card through remoteproc platform device for card to probe is registered in imx-audio-rpmsg. ASoC machine driver no longer can get DT node of ASoC CPU DAI device through parent device. ASoC machine driver can get DT node of ASoC CPU DAI device with rpmsg channel name acquired from platform specific data. Signed-off-by: Chancel Liu Link: https://msgid.link/r/20240311111349.723256-6-chancel.liu@nxp.com Acked-by: Shengjiu Wang Signed-off-by: Mark Brown --- sound/soc/fsl/imx-rpmsg.c | 28 +++++++++++++++++++--------- 1 file changed, 19 insertions(+), 9 deletions(-) diff --git a/sound/soc/fsl/imx-rpmsg.c b/sound/soc/fsl/imx-rpmsg.c index e5bd63dab10c..0f1ad7ad7d27 100644 --- a/sound/soc/fsl/imx-rpmsg.c +++ b/sound/soc/fsl/imx-rpmsg.c @@ -108,10 +108,8 @@ static int imx_rpmsg_late_probe(struct snd_soc_card *card) static int imx_rpmsg_probe(struct platform_device *pdev) { struct snd_soc_dai_link_component *dlc; - struct device *dev = pdev->dev.parent; - /* rpmsg_pdev is the platform device for the rpmsg node that probed us */ - struct platform_device *rpmsg_pdev = to_platform_device(dev); - struct device_node *np = rpmsg_pdev->dev.of_node; + struct snd_soc_dai *cpu_dai; + struct device_node *np = NULL; struct of_phandle_args args; const char *platform_name; struct imx_rpmsg *data; @@ -127,10 +125,6 @@ static int imx_rpmsg_probe(struct platform_device *pdev) goto fail; } - ret = of_reserved_mem_device_init_by_idx(&pdev->dev, np, 0); - if (ret) - dev_warn(&pdev->dev, "no reserved DMA memory\n"); - data->dai.cpus = &dlc[0]; data->dai.num_cpus = 1; data->dai.platforms = &dlc[1]; @@ -152,6 +146,23 @@ static int imx_rpmsg_probe(struct platform_device *pdev) */ data->dai.ignore_pmdown_time = 1; + data->dai.cpus->dai_name = pdev->dev.platform_data; + cpu_dai = snd_soc_find_dai(data->dai.cpus); + if (!cpu_dai) { + ret = -EPROBE_DEFER; + goto fail; + } + np = cpu_dai->dev->of_node; + if (!np) { + dev_err(&pdev->dev, "failed to parse CPU DAI device node\n"); + ret = -ENODEV; + goto fail; + } + + ret = of_reserved_mem_device_init_by_idx(&pdev->dev, np, 0); + if (ret) + dev_warn(&pdev->dev, "no reserved DMA memory\n"); + /* Optional codec node */ ret = of_parse_phandle_with_fixed_args(np, "audio-codec", 0, 0, &args); if (ret) { @@ -170,7 +181,6 @@ static int imx_rpmsg_probe(struct platform_device *pdev) data->sysclk = clk_get_rate(clk); } - data->dai.cpus->dai_name = dev_name(&rpmsg_pdev->dev); if (!of_property_read_string(np, "fsl,rpmsg-channel-name", &platform_name)) data->dai.platforms->name = platform_name; else -- cgit v1.2.3 From 39938bb1bb23fd70f1c75ce9f52d92185403b89a Mon Sep 17 00:00:00 2001 From: Zhang Yi Date: Wed, 20 Mar 2024 16:30:11 +0800 Subject: ASoC: codecs: ES8326: Reducing power consumption For lower power consumption during hibernation, the configuration of es8326_suspend and es8326_remove will be adjusted. Adding es8326_i2c_shutdown and es8326_i2c_remove to cover different situations Signed-off-by: Zhang Yi Link: https://msgid.link/r/20240320083012.4282-2-zhangyi@everest-semi.com Signed-off-by: Mark Brown --- sound/soc/codecs/es8326.c | 33 ++++++++++++++++++++++++++++++++- 1 file changed, 32 insertions(+), 1 deletion(-) diff --git a/sound/soc/codecs/es8326.c b/sound/soc/codecs/es8326.c index 15289dadafea..635320c86c00 100644 --- a/sound/soc/codecs/es8326.c +++ b/sound/soc/codecs/es8326.c @@ -1072,12 +1072,13 @@ static int es8326_suspend(struct snd_soc_component *component) es8326->calibrated = false; regmap_write(es8326->regmap, ES8326_CLK_CTL, ES8326_CLK_OFF); regcache_cache_only(es8326->regmap, true); - regcache_mark_dirty(es8326->regmap); /* reset register value to default */ regmap_write(es8326->regmap, ES8326_CSM_I2C_STA, 0x01); usleep_range(1000, 3000); regmap_write(es8326->regmap, ES8326_CSM_I2C_STA, 0x00); + + regcache_mark_dirty(es8326->regmap); return 0; } @@ -1163,8 +1164,13 @@ static int es8326_set_jack(struct snd_soc_component *component, static void es8326_remove(struct snd_soc_component *component) { + struct es8326_priv *es8326 = snd_soc_component_get_drvdata(component); + es8326_disable_jack_detect(component); es8326_set_bias_level(component, SND_SOC_BIAS_OFF); + regmap_write(es8326->regmap, ES8326_CSM_I2C_STA, 0x01); + usleep_range(1000, 3000); + regmap_write(es8326->regmap, ES8326_CSM_I2C_STA, 0x00); } static const struct snd_soc_component_driver soc_component_dev_es8326 = { @@ -1236,6 +1242,29 @@ static int es8326_i2c_probe(struct i2c_client *i2c) &es8326_dai, 1); } + +static void es8326_i2c_shutdown(struct i2c_client *i2c) +{ + struct snd_soc_component *component; + struct es8326_priv *es8326; + + es8326 = i2c_get_clientdata(i2c); + component = es8326->component; + dev_dbg(component->dev, "Enter into %s\n", __func__); + cancel_delayed_work_sync(&es8326->jack_detect_work); + cancel_delayed_work_sync(&es8326->button_press_work); + + regmap_write(es8326->regmap, ES8326_CSM_I2C_STA, 0x01); + usleep_range(1000, 3000); + regmap_write(es8326->regmap, ES8326_CSM_I2C_STA, 0x00); + +} + +static void es8326_i2c_remove(struct i2c_client *i2c) +{ + es8326_i2c_shutdown(i2c); +} + static const struct i2c_device_id es8326_i2c_id[] = { {"es8326", 0 }, {} @@ -1265,6 +1294,8 @@ static struct i2c_driver es8326_i2c_driver = { .of_match_table = of_match_ptr(es8326_of_match), }, .probe = es8326_i2c_probe, + .shutdown = es8326_i2c_shutdown, + .remove = es8326_i2c_remove, .id_table = es8326_i2c_id, }; module_i2c_driver(es8326_i2c_driver); -- cgit v1.2.3 From e6913c6ef83c80aa7569c9e08204542222fbf542 Mon Sep 17 00:00:00 2001 From: Zhang Yi Date: Wed, 20 Mar 2024 16:30:12 +0800 Subject: ASoC: codecs: ES8326: Delete unused REG_SUPPLY REG_SUPPLY mutes the DAC when switching between HDMI and speaker, so remove it to fix the mute issues Signed-off-by: Zhang Yi Link: https://msgid.link/r/20240320083012.4282-3-zhangyi@everest-semi.com Signed-off-by: Mark Brown --- sound/soc/codecs/es8326.c | 8 -------- 1 file changed, 8 deletions(-) diff --git a/sound/soc/codecs/es8326.c b/sound/soc/codecs/es8326.c index 635320c86c00..e8526844337d 100644 --- a/sound/soc/codecs/es8326.c +++ b/sound/soc/codecs/es8326.c @@ -292,11 +292,6 @@ static const struct snd_soc_dapm_widget es8326_dapm_widgets[] = { SND_SOC_DAPM_PGA("LHPMIX", ES8326_DAC2HPMIX, 7, 0, NULL, 0), SND_SOC_DAPM_PGA("RHPMIX", ES8326_DAC2HPMIX, 3, 0, NULL, 0), - SND_SOC_DAPM_REG(snd_soc_dapm_supply, "HPOR Supply", ES8326_HP_CAL, - 4, 7, 0, 0), - SND_SOC_DAPM_REG(snd_soc_dapm_supply, "HPOL Supply", ES8326_HP_CAL, - 0, 7, 0, 0), - SND_SOC_DAPM_OUTPUT("HPOL"), SND_SOC_DAPM_OUTPUT("HPOR"), }; @@ -316,9 +311,6 @@ static const struct snd_soc_dapm_route es8326_dapm_routes[] = { {"LHPMIX", NULL, "Left DAC"}, {"RHPMIX", NULL, "Right DAC"}, - {"HPOR", NULL, "HPOR Supply"}, - {"HPOL", NULL, "HPOL Supply"}, - {"HPOL", NULL, "LHPMIX"}, {"HPOR", NULL, "RHPMIX"}, }; -- cgit v1.2.3 From cee28113db17f0de58df0eaea4e2756c404ee01f Mon Sep 17 00:00:00 2001 From: Tomi Valkeinen Date: Tue, 19 Mar 2024 10:22:36 +0200 Subject: ASoC: dmaengine_pcm: Allow passing component name via config At the moment we cannot instantiate two dmaengine_pcms with the same parent device, as the components will be named the same, leading to conflicts. Add 'name' field to the snd_dmaengine_pcm_config, and use that (if defined) as the component name instead of deriving the component name from the device. Signed-off-by: Tomi Valkeinen Link: https://msgid.link/r/20240319-xilinx-dp-audio-v2-1-92d6d3a7ca7e@ideasonboard.com Signed-off-by: Mark Brown --- include/sound/dmaengine_pcm.h | 2 ++ sound/soc/soc-core.c | 8 +++++--- sound/soc/soc-generic-dmaengine-pcm.c | 3 +++ 3 files changed, 10 insertions(+), 3 deletions(-) diff --git a/include/sound/dmaengine_pcm.h b/include/sound/dmaengine_pcm.h index d70c55f17df7..c11aaf8079fb 100644 --- a/include/sound/dmaengine_pcm.h +++ b/include/sound/dmaengine_pcm.h @@ -118,6 +118,7 @@ int snd_dmaengine_pcm_refine_runtime_hwparams( * which do not use devicetree. * @process: Callback used to apply processing on samples transferred from/to * user space. + * @name: Component name. If null, dev_name will be used. * @compat_filter_fn: Will be used as the filter function when requesting a * channel for platforms which do not use devicetree. The filter parameter * will be the DAI's DMA data. @@ -143,6 +144,7 @@ struct snd_dmaengine_pcm_config { int (*process)(struct snd_pcm_substream *substream, int channel, unsigned long hwoff, unsigned long bytes); + const char *name; dma_filter_fn compat_filter_fn; struct device *dma_dev; const char *chan_names[SNDRV_PCM_STREAM_LAST + 1]; diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index 2ec13d1634b6..3ab6626ad680 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -2796,10 +2796,12 @@ int snd_soc_component_initialize(struct snd_soc_component *component, INIT_LIST_HEAD(&component->list); mutex_init(&component->io_mutex); - component->name = fmt_single_name(dev, &component->id); if (!component->name) { - dev_err(dev, "ASoC: Failed to allocate name\n"); - return -ENOMEM; + component->name = fmt_single_name(dev, &component->id); + if (!component->name) { + dev_err(dev, "ASoC: Failed to allocate name\n"); + return -ENOMEM; + } } component->dev = dev; diff --git a/sound/soc/soc-generic-dmaengine-pcm.c b/sound/soc/soc-generic-dmaengine-pcm.c index 092ca09f3631..83db1a83d8ba 100644 --- a/sound/soc/soc-generic-dmaengine-pcm.c +++ b/sound/soc/soc-generic-dmaengine-pcm.c @@ -441,6 +441,9 @@ int snd_dmaengine_pcm_register(struct device *dev, pcm->config = config; pcm->flags = flags; + if (config->name) + pcm->component.name = config->name; + ret = dmaengine_pcm_request_chan_of(pcm, dev, config); if (ret) goto err_free_dma; -- cgit v1.2.3 From 1a4bd2b128fb5ca62e4d1c5ca298d3d06b9c1e8e Mon Sep 17 00:00:00 2001 From: Jens Wiklander Date: Mon, 11 Mar 2024 12:07:00 +0100 Subject: firmware: arm_ffa: Fix the partition ID check in ffa_notification_info_get() FFA_NOTIFICATION_INFO_GET retrieves information about pending notifications. Notifications can be either global or per VCPU. Global notifications are reported with the partition ID only in the list of endpoints with pending notifications. ffa_notification_info_get() incorrectly expect no ID at all for global notifications. Fix this by checking for ID = 1 instead of ID = 0. Fixes: 3522be48d82b ("firmware: arm_ffa: Implement the NOTIFICATION_INFO_GET interface") Signed-off-by: Jens Wiklander Reviewed-by: Lorenzo Pieralisi Link: https://lore.kernel.org/r/20240311110700.2367142-1-jens.wiklander@linaro.org Signed-off-by: Sudeep Holla --- drivers/firmware/arm_ffa/driver.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/firmware/arm_ffa/driver.c b/drivers/firmware/arm_ffa/driver.c index f2556a8e9401..9bc2e10381af 100644 --- a/drivers/firmware/arm_ffa/driver.c +++ b/drivers/firmware/arm_ffa/driver.c @@ -790,7 +790,7 @@ static void ffa_notification_info_get(void) part_id = packed_id_list[ids_processed++]; - if (!ids_count[list]) { /* Global Notification */ + if (ids_count[list] == 1) { /* Global Notification */ __do_sched_recv_cb(part_id, 0, false); continue; } -- cgit v1.2.3 From 17f243adf1653bdbaeec767e3e74c9ad089f470b Mon Sep 17 00:00:00 2001 From: Pierre Gondois Date: Mon, 11 Mar 2024 10:04:12 +0100 Subject: firmware: arm_scmi: Fix wrong fastchannel initialization Fastchannels are initialized with an incorrect index(POWERCAP_PAI_GET) in: commit 2441caa84aac ("firmware: arm_scmi: Populate fast channel rate_limit") Fix this and provide a correct index(POWERCAP_FC_PAI) Fixes: 2441caa84aac ("firmware: arm_scmi: Populate fast channel rate_limit") Reported-by: kernel test robot Reported-by: Dan Carpenter Closes: https://lore.kernel.org/r/202403100744.7Op3PI8L-lkp@intel.com/ Signed-off-by: Pierre Gondois Link: https://lore.kernel.org/r/20240311090413.1710725-1-pierre.gondois@arm.com Signed-off-by: Sudeep Holla --- drivers/firmware/arm_scmi/powercap.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/firmware/arm_scmi/powercap.c b/drivers/firmware/arm_scmi/powercap.c index ea9201e7044c..1fa79bba492e 100644 --- a/drivers/firmware/arm_scmi/powercap.c +++ b/drivers/firmware/arm_scmi/powercap.c @@ -736,7 +736,7 @@ static void scmi_powercap_domain_init_fc(const struct scmi_protocol_handle *ph, ph->hops->fastchannel_init(ph, POWERCAP_DESCRIBE_FASTCHANNEL, POWERCAP_PAI_GET, 4, domain, &fc[POWERCAP_FC_PAI].get_addr, NULL, - &fc[POWERCAP_PAI_GET].rate_limit); + &fc[POWERCAP_FC_PAI].rate_limit); *p_fc = fc; } -- cgit v1.2.3 From b70c7996d4ffb2e02895132e8a79a37cee66504f Mon Sep 17 00:00:00 2001 From: Cristian Marussi Date: Fri, 15 Mar 2024 14:03:24 +0000 Subject: firmware: arm_scmi: Make raw debugfs entries non-seekable SCMI raw debugfs entries are used to inject and snoop messages out of the SCMI core and, as such, the underlying virtual files have no reason to support seeking. Modify the related file_operations descriptors to be non-seekable. Fixes: 3c3d818a9317 ("firmware: arm_scmi: Add core raw transmission support") Signed-off-by: Cristian Marussi Link: https://lore.kernel.org/r/20240315140324.231830-1-cristian.marussi@arm.com Signed-off-by: Sudeep Holla --- drivers/firmware/arm_scmi/raw_mode.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/drivers/firmware/arm_scmi/raw_mode.c b/drivers/firmware/arm_scmi/raw_mode.c index 350573518503..130d13e9cd6b 100644 --- a/drivers/firmware/arm_scmi/raw_mode.c +++ b/drivers/firmware/arm_scmi/raw_mode.c @@ -921,7 +921,7 @@ static int scmi_dbg_raw_mode_open(struct inode *inode, struct file *filp) rd->raw = raw; filp->private_data = rd; - return 0; + return nonseekable_open(inode, filp); } static int scmi_dbg_raw_mode_release(struct inode *inode, struct file *filp) @@ -950,6 +950,7 @@ static const struct file_operations scmi_dbg_raw_mode_reset_fops = { .open = scmi_dbg_raw_mode_open, .release = scmi_dbg_raw_mode_release, .write = scmi_dbg_raw_mode_reset_write, + .llseek = no_llseek, .owner = THIS_MODULE, }; @@ -959,6 +960,7 @@ static const struct file_operations scmi_dbg_raw_mode_message_fops = { .read = scmi_dbg_raw_mode_message_read, .write = scmi_dbg_raw_mode_message_write, .poll = scmi_dbg_raw_mode_message_poll, + .llseek = no_llseek, .owner = THIS_MODULE, }; @@ -975,6 +977,7 @@ static const struct file_operations scmi_dbg_raw_mode_message_async_fops = { .read = scmi_dbg_raw_mode_message_read, .write = scmi_dbg_raw_mode_message_async_write, .poll = scmi_dbg_raw_mode_message_poll, + .llseek = no_llseek, .owner = THIS_MODULE, }; @@ -998,6 +1001,7 @@ static const struct file_operations scmi_dbg_raw_mode_notification_fops = { .release = scmi_dbg_raw_mode_release, .read = scmi_test_dbg_raw_mode_notif_read, .poll = scmi_test_dbg_raw_mode_notif_poll, + .llseek = no_llseek, .owner = THIS_MODULE, }; @@ -1021,6 +1025,7 @@ static const struct file_operations scmi_dbg_raw_mode_errors_fops = { .release = scmi_dbg_raw_mode_release, .read = scmi_test_dbg_raw_mode_errors_read, .poll = scmi_test_dbg_raw_mode_errors_poll, + .llseek = no_llseek, .owner = THIS_MODULE, }; -- cgit v1.2.3 From 33a499668eb6781a4518e4facf2d85cc8cd1a650 Mon Sep 17 00:00:00 2001 From: Frank Li Date: Thu, 21 Mar 2024 11:04:00 -0400 Subject: ASoC: dt-bindings: fsl-audmix: Convert fsl,audmix.txt to yaml Convert fsl,audmix.txt to yaml to let dtb check tools check audmix part. Signed-off-by: Frank Li Reviewed-by: Rob Herring Link: https://msgid.link/r/20240321150401.2464783-1-Frank.Li@nxp.com Signed-off-by: Mark Brown --- .../devicetree/bindings/sound/fsl,audmix.txt | 50 ------------- .../devicetree/bindings/sound/fsl,audmix.yaml | 83 ++++++++++++++++++++++ 2 files changed, 83 insertions(+), 50 deletions(-) delete mode 100644 Documentation/devicetree/bindings/sound/fsl,audmix.txt create mode 100644 Documentation/devicetree/bindings/sound/fsl,audmix.yaml diff --git a/Documentation/devicetree/bindings/sound/fsl,audmix.txt b/Documentation/devicetree/bindings/sound/fsl,audmix.txt deleted file mode 100644 index 840b7e0d6a63..000000000000 --- a/Documentation/devicetree/bindings/sound/fsl,audmix.txt +++ /dev/null @@ -1,50 +0,0 @@ -NXP Audio Mixer (AUDMIX). - -The Audio Mixer is a on-chip functional module that allows mixing of two -audio streams into a single audio stream. Audio Mixer has two input serial -audio interfaces. These are driven by two Synchronous Audio interface -modules (SAI). Each input serial interface carries 8 audio channels in its -frame in TDM manner. Mixer mixes audio samples of corresponding channels -from two interfaces into a single sample. Before mixing, audio samples of -two inputs can be attenuated based on configuration. The output of the -Audio Mixer is also a serial audio interface. Like input interfaces it has -the same TDM frame format. This output is used to drive the serial DAC TDM -interface of audio codec and also sent to the external pins along with the -receive path of normal audio SAI module for readback by the CPU. - -The output of Audio Mixer can be selected from any of the three streams - - serial audio input 1 - - serial audio input 2 - - mixed audio - -Mixing operation is independent of audio sample rate but the two audio -input streams must have same audio sample rate with same number of channels -in TDM frame to be eligible for mixing. - -Device driver required properties: -================================= - - compatible : Compatible list, contains "fsl,imx8qm-audmix" - - - reg : Offset and length of the register set for the device. - - - clocks : Must contain an entry for each entry in clock-names. - - - clock-names : Must include the "ipg" for register access. - - - power-domains : Must contain the phandle to AUDMIX power domain node - - - dais : Must contain a list of phandles to AUDMIX connected - DAIs. The current implementation requires two phandles - to SAI interfaces to be provided, the first SAI in the - list being used to route the AUDMIX output. - -Device driver configuration example: -====================================== - audmix: audmix@59840000 { - compatible = "fsl,imx8qm-audmix"; - reg = <0x0 0x59840000 0x0 0x10000>; - clocks = <&clk IMX8QXP_AUD_AUDMIX_IPG>; - clock-names = "ipg"; - power-domains = <&pd_audmix>; - dais = <&sai4>, <&sai5>; - }; diff --git a/Documentation/devicetree/bindings/sound/fsl,audmix.yaml b/Documentation/devicetree/bindings/sound/fsl,audmix.yaml new file mode 100644 index 000000000000..9413b901cf77 --- /dev/null +++ b/Documentation/devicetree/bindings/sound/fsl,audmix.yaml @@ -0,0 +1,83 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/sound/fsl,audmix.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: NXP Audio Mixer (AUDMIX). + +maintainers: + - Shengjiu Wang + - Frank Li + +description: | + The Audio Mixer is a on-chip functional module that allows mixing of two + audio streams into a single audio stream. Audio Mixer has two input serial + audio interfaces. These are driven by two Synchronous Audio interface + modules (SAI). Each input serial interface carries 8 audio channels in its + frame in TDM manner. Mixer mixes audio samples of corresponding channels + from two interfaces into a single sample. Before mixing, audio samples of + two inputs can be attenuated based on configuration. The output of the + Audio Mixer is also a serial audio interface. Like input interfaces it has + the same TDM frame format. This output is used to drive the serial DAC TDM + interface of audio codec and also sent to the external pins along with the + receive path of normal audio SAI module for readback by the CPU. + + The output of Audio Mixer can be selected from any of the three streams + - serial audio input 1 + - serial audio input 2 + - mixed audio + + Mixing operation is independent of audio sample rate but the two audio + input streams must have same audio sample rate with same number of channels + in TDM frame to be eligible for mixing. + +properties: + compatible: + const: fsl,imx8qm-audmix + + reg: + maxItems: 1 + + clocks: + maxItems: 1 + + clock-names: + items: + - const: ipg + + power-domains: + maxItems: 1 + + dais: + description: contain a list of phandles to AUDMIX connected DAIs. + $ref: /schemas/types.yaml#/definitions/phandle-array + minItems: 2 + items: + - description: the AUDMIX output + maxItems: 1 + - description: serial audio input 1 + maxItems: 1 + - description: serial audio input 2 + maxItems: 1 + +required: + - compatible + - reg + - clocks + - clock-names + - power-domains + - dais + +unevaluatedProperties: false + +examples: + - | + audmix@59840000 { + compatible = "fsl,imx8qm-audmix"; + reg = <0x59840000 0x10000>; + clocks = <&amix_lpcg 0>; + clock-names = "ipg"; + power-domains = <&pd_audmix>; + dais = <&sai4>, <&sai5>; + }; -- cgit v1.2.3 From a806793f231e390510343837668d8f0eade75a72 Mon Sep 17 00:00:00 2001 From: Vijendar Mukunda Date: Fri, 22 Mar 2024 16:50:15 +0530 Subject: ASoC: amd: simplify soundwire dependencies for legacy stack The CONFIG_SOUNDWIRE_AMD is a user-visible option, it should be never selected by another driver. So replace the extra complexity with a normal Kconfig dependency in SND_SOC_AMD_SOUNDWIRE. Signed-off-by: Vijendar Mukunda Link: https://msgid.link/r/20240322112018.3063344-1-Vijendar.Mukunda@amd.com Signed-off-by: Mark Brown --- sound/soc/amd/Kconfig | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/sound/soc/amd/Kconfig b/sound/soc/amd/Kconfig index fa74635cee08..3508f5a96b75 100644 --- a/sound/soc/amd/Kconfig +++ b/sound/soc/amd/Kconfig @@ -134,15 +134,14 @@ config SND_SOC_AMD_RPL_ACP6x config SND_SOC_AMD_SOUNDWIRE_LINK_BASELINE tristate - select SOUNDWIRE_AMD if SND_SOC_AMD_SOUNDWIRE != n select SND_AMD_SOUNDWIRE_ACPI if ACPI config SND_SOC_AMD_SOUNDWIRE tristate "Support for SoundWire based AMD platforms" default SND_SOC_AMD_SOUNDWIRE_LINK_BASELINE depends on SND_SOC_AMD_SOUNDWIRE_LINK_BASELINE - depends on ACPI && SOUNDWIRE - depends on !(SOUNDWIRE=m && SND_SOC_AMD_SOUNDWIRE_LINK_BASELINE=y) + depends on ACPI + depends on SOUNDWIRE_AMD help This adds support for SoundWire for AMD platforms. Say Y if you want to enable SoundWire links with SOF. -- cgit v1.2.3 From 1fdc23aa57913d7a0a521f71dcdefdde9364d4f9 Mon Sep 17 00:00:00 2001 From: Kartik Agarwala Date: Mon, 18 Mar 2024 01:32:02 +0530 Subject: ASoC: dt-bindings: wm8776: Convert to dtschema Convert WM8776 audio CODEC bindings from text to dtschema. Signed-off-by: Kartik Agarwala Reviewed-by: Charles Keepax Reviewed-by: Krzysztof Kozlowski Link: https://msgid.link/r/20240317200201.119233-1-agarwala.kartik@gmail.com Signed-off-by: Mark Brown --- .../devicetree/bindings/sound/wlf,wm8776.yaml | 41 ++++++++++++++++++++++ Documentation/devicetree/bindings/sound/wm8776.txt | 18 ---------- 2 files changed, 41 insertions(+), 18 deletions(-) create mode 100644 Documentation/devicetree/bindings/sound/wlf,wm8776.yaml delete mode 100644 Documentation/devicetree/bindings/sound/wm8776.txt diff --git a/Documentation/devicetree/bindings/sound/wlf,wm8776.yaml b/Documentation/devicetree/bindings/sound/wlf,wm8776.yaml new file mode 100644 index 000000000000..7bbc96ee81be --- /dev/null +++ b/Documentation/devicetree/bindings/sound/wlf,wm8776.yaml @@ -0,0 +1,41 @@ +# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/sound/wlf,wm8776.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: WM8776 audio CODEC + +maintainers: + - patches@opensource.cirrus.com + +allOf: + - $ref: dai-common.yaml# + +properties: + compatible: + const: wlf,wm8776 + + reg: + maxItems: 1 + + "#sound-dai-cells": + const: 0 + +required: + - compatible + - reg + +unevaluatedProperties: false + +examples: + - | + i2c { + #address-cells = <1>; + #size-cells = <0>; + + codec@1a { + compatible = "wlf,wm8776"; + reg = <0x1a>; + }; + }; diff --git a/Documentation/devicetree/bindings/sound/wm8776.txt b/Documentation/devicetree/bindings/sound/wm8776.txt deleted file mode 100644 index 01173369c3ed..000000000000 --- a/Documentation/devicetree/bindings/sound/wm8776.txt +++ /dev/null @@ -1,18 +0,0 @@ -WM8776 audio CODEC - -This device supports both I2C and SPI (configured with pin strapping -on the board). - -Required properties: - - - compatible : "wlf,wm8776" - - - reg : the I2C address of the device for I2C, the chip select - number for SPI. - -Example: - -wm8776: codec@1a { - compatible = "wlf,wm8776"; - reg = <0x1a>; -}; -- cgit v1.2.3 From 3ca49e7f9475ac06614edf1bfece123eafbdf8f3 Mon Sep 17 00:00:00 2001 From: Alexander Stein Date: Thu, 14 Mar 2024 15:16:42 +0100 Subject: ASoC: fsl: fsl_ssi: Add dev_err_probe if PCM DMA init fails This happens especially if this driver is built-in, but SDMA driver is configured as module. Signed-off-by: Alexander Stein Link: https://msgid.link/r/20240314141642.2943605-1-alexander.stein@ew.tq-group.com Signed-off-by: Mark Brown --- sound/soc/fsl/fsl_ssi.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/sound/soc/fsl/fsl_ssi.c b/sound/soc/fsl/fsl_ssi.c index ab6ec1974807..4ca3a16f7ac0 100644 --- a/sound/soc/fsl/fsl_ssi.c +++ b/sound/soc/fsl/fsl_ssi.c @@ -1401,8 +1401,10 @@ static int fsl_ssi_imx_probe(struct platform_device *pdev, goto error_pcm; } else { ret = imx_pcm_dma_init(pdev); - if (ret) + if (ret) { + dev_err_probe(dev, ret, "Failed to init PCM DMA\n"); goto error_pcm; + } } return 0; -- cgit v1.2.3 From 9855f05e553637f05494cf47a3154cbf9a5cfc67 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Mon, 18 Mar 2024 22:07:56 +0200 Subject: ASoC: fsl: imx-es8328: Switch to using gpiod API This updates the driver to gpiod API, and removes yet another use of of_get_named_gpio(). Signed-off-by: Andy Shevchenko Link: https://msgid.link/r/20240318200804.181516-1-andriy.shevchenko@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/fsl/imx-es8328.c | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/sound/soc/fsl/imx-es8328.c b/sound/soc/fsl/imx-es8328.c index 6f0d031c1d5f..d67b8a149bff 100644 --- a/sound/soc/fsl/imx-es8328.c +++ b/sound/soc/fsl/imx-es8328.c @@ -3,7 +3,7 @@ // Copyright 2012 Freescale Semiconductor, Inc. // Copyright 2012 Linaro Ltd. -#include +#include #include #include #include @@ -23,7 +23,7 @@ struct imx_es8328_data { struct snd_soc_card card; char codec_dai_name[DAI_NAME_SIZE]; char platform_name[DAI_NAME_SIZE]; - int jack_gpio; + struct gpio_desc *jack_gpiod; }; static struct snd_soc_jack_gpio headset_jack_gpios[] = { @@ -54,8 +54,8 @@ static int imx_es8328_dai_init(struct snd_soc_pcm_runtime *rtd) struct imx_es8328_data, card); int ret = 0; - /* Headphone jack detection */ - if (gpio_is_valid(data->jack_gpio)) { + if (data->jack_gpiod) { + /* Headphone jack detection */ ret = snd_soc_card_jack_new_pins(rtd->card, "Headphone", SND_JACK_HEADSET | SND_JACK_BTN_0, &headset_jack, @@ -64,7 +64,7 @@ static int imx_es8328_dai_init(struct snd_soc_pcm_runtime *rtd) if (ret) return ret; - headset_jack_gpios[0].gpio = data->jack_gpio; + headset_jack_gpios[0].desc = data->jack_gpiod; ret = snd_soc_jack_add_gpios(&headset_jack, ARRAY_SIZE(headset_jack_gpios), headset_jack_gpios); @@ -174,7 +174,11 @@ static int imx_es8328_probe(struct platform_device *pdev) data->dev = dev; - data->jack_gpio = of_get_named_gpio(pdev->dev.of_node, "jack-gpio", 0); + data->jack_gpiod = devm_gpiod_get_optional(dev, "jack", GPIOD_IN); + if (IS_ERR(data->jack_gpiod)) { + ret = PTR_ERR(data->jack_gpiod); + goto put_device; + } /* * CPU == Platform -- cgit v1.2.3 From 7aaaa22de56ce0dae15fd9f42a69a1d1a7a6e078 Mon Sep 17 00:00:00 2001 From: AngeloGioacchino Del Regno Date: Wed, 13 Mar 2024 12:01:26 +0100 Subject: ASoC: mediatek: mt8192-afe-pcm: Convert to devm_pm_runtime_enable() Switch from pm_runtime_enable() to devm_pm_runtime_enable(), allowing to remove all gotos from the probe function. Signed-off-by: AngeloGioacchino Del Regno Reviewed-by: Chen-Yu Tsai Link: https://msgid.link/r/20240313110147.1267793-2-angelogioacchino.delregno@collabora.com Signed-off-by: Mark Brown --- sound/soc/mediatek/mt8192/mt8192-afe-pcm.c | 46 +++++++++++------------------- 1 file changed, 17 insertions(+), 29 deletions(-) diff --git a/sound/soc/mediatek/mt8192/mt8192-afe-pcm.c b/sound/soc/mediatek/mt8192/mt8192-afe-pcm.c index bdd1e91824d9..794419d16b01 100644 --- a/sound/soc/mediatek/mt8192/mt8192-afe-pcm.c +++ b/sound/soc/mediatek/mt8192/mt8192-afe-pcm.c @@ -2217,21 +2217,20 @@ static int mt8192_afe_pcm_dev_probe(struct platform_device *pdev) return ret; } - pm_runtime_enable(&pdev->dev); - if (!pm_runtime_enabled(&pdev->dev)) - goto err_pm_disable; + ret = devm_pm_runtime_enable(&pdev->dev); + if (ret) + return ret; /* regmap init */ afe->regmap = syscon_node_to_regmap(dev->parent->of_node); if (IS_ERR(afe->regmap)) { dev_err(dev, "could not get regmap from parent\n"); - ret = PTR_ERR(afe->regmap); - goto err_pm_disable; + return PTR_ERR(afe->regmap); } ret = regmap_attach_dev(dev, afe->regmap, &mt8192_afe_regmap_config); if (ret) { dev_warn(dev, "regmap_attach_dev fail, ret %d\n", ret); - goto err_pm_disable; + return ret; } /* enable clock for regcache get default value from hw */ @@ -2241,7 +2240,7 @@ static int mt8192_afe_pcm_dev_probe(struct platform_device *pdev) ret = regmap_reinit_cache(afe->regmap, &mt8192_afe_regmap_config); if (ret) { dev_err(dev, "regmap_reinit_cache fail, ret %d\n", ret); - goto err_pm_disable; + return ret; } pm_runtime_put_sync(&pdev->dev); @@ -2254,10 +2253,8 @@ static int mt8192_afe_pcm_dev_probe(struct platform_device *pdev) afe->memif_size = MT8192_MEMIF_NUM; afe->memif = devm_kcalloc(dev, afe->memif_size, sizeof(*afe->memif), GFP_KERNEL); - if (!afe->memif) { - ret = -ENOMEM; - goto err_pm_disable; - } + if (!afe->memif) + return -ENOMEM; for (i = 0; i < afe->memif_size; i++) { afe->memif[i].data = &memif_data[i]; @@ -2271,26 +2268,22 @@ static int mt8192_afe_pcm_dev_probe(struct platform_device *pdev) afe->irqs_size = MT8192_IRQ_NUM; afe->irqs = devm_kcalloc(dev, afe->irqs_size, sizeof(*afe->irqs), GFP_KERNEL); - if (!afe->irqs) { - ret = -ENOMEM; - goto err_pm_disable; - } + if (!afe->irqs) + return -ENOMEM; for (i = 0; i < afe->irqs_size; i++) afe->irqs[i].irq_data = &irq_data[i]; /* request irq */ irq_id = platform_get_irq(pdev, 0); - if (irq_id < 0) { - ret = irq_id; - goto err_pm_disable; - } + if (irq_id < 0) + return irq_id; ret = devm_request_irq(dev, irq_id, mt8192_afe_irq_handler, IRQF_TRIGGER_NONE, "asys-isr", (void *)afe); if (ret) { dev_err(dev, "could not request_irq for Afe_ISR_Handle\n"); - goto err_pm_disable; + return ret; } /* init sub_dais */ @@ -2301,7 +2294,7 @@ static int mt8192_afe_pcm_dev_probe(struct platform_device *pdev) if (ret) { dev_warn(afe->dev, "dai register i %d fail, ret %d\n", i, ret); - goto err_pm_disable; + return ret; } } @@ -2310,7 +2303,7 @@ static int mt8192_afe_pcm_dev_probe(struct platform_device *pdev) if (ret) { dev_warn(afe->dev, "mtk_afe_combine_sub_dai fail, ret %d\n", ret); - goto err_pm_disable; + return ret; } /* others */ @@ -2329,7 +2322,7 @@ static int mt8192_afe_pcm_dev_probe(struct platform_device *pdev) &mt8192_afe_component, NULL, 0); if (ret) { dev_warn(dev, "err_platform\n"); - goto err_pm_disable; + return ret; } ret = devm_snd_soc_register_component(&pdev->dev, @@ -2338,15 +2331,10 @@ static int mt8192_afe_pcm_dev_probe(struct platform_device *pdev) afe->num_dai_drivers); if (ret) { dev_warn(dev, "err_dai_component\n"); - goto err_pm_disable; + return ret; } return 0; - -err_pm_disable: - pm_runtime_disable(&pdev->dev); - - return ret; } static void mt8192_afe_pcm_dev_remove(struct platform_device *pdev) -- cgit v1.2.3 From 324c603a4efca7d1045e0bf3477ca54970eac72c Mon Sep 17 00:00:00 2001 From: AngeloGioacchino Del Regno Date: Wed, 13 Mar 2024 12:01:27 +0100 Subject: ASoC: mediatek: mt8192-afe-pcm: Simplify with dev_err_probe() Simplify the probe function by switching error prints to return dev_err_probe(), lowering the lines count; while at it, also beautify some messages and change some others' level from warn to error. Signed-off-by: AngeloGioacchino Del Regno Reviewed-by: Chen-Yu Tsai Link: https://msgid.link/r/20240313110147.1267793-3-angelogioacchino.delregno@collabora.com Signed-off-by: Mark Brown --- sound/soc/mediatek/mt8192/mt8192-afe-pcm.c | 65 ++++++++++-------------------- 1 file changed, 22 insertions(+), 43 deletions(-) diff --git a/sound/soc/mediatek/mt8192/mt8192-afe-pcm.c b/sound/soc/mediatek/mt8192/mt8192-afe-pcm.c index 794419d16b01..aed22baef9fb 100644 --- a/sound/soc/mediatek/mt8192/mt8192-afe-pcm.c +++ b/sound/soc/mediatek/mt8192/mt8192-afe-pcm.c @@ -2205,17 +2205,12 @@ static int mt8192_afe_pcm_dev_probe(struct platform_device *pdev) /* reset controller to reset audio regs before regmap cache */ rstc = devm_reset_control_get_exclusive(dev, "audiosys"); - if (IS_ERR(rstc)) { - ret = PTR_ERR(rstc); - dev_err(dev, "could not get audiosys reset:%d\n", ret); - return ret; - } + if (IS_ERR(rstc)) + return dev_err_probe(dev, PTR_ERR(rstc), "could not get audiosys reset\n"); ret = reset_control_reset(rstc); - if (ret) { - dev_err(dev, "failed to trigger audio reset:%d\n", ret); - return ret; - } + if (ret) + return dev_err_probe(dev, ret, "failed to trigger audio reset\n"); ret = devm_pm_runtime_enable(&pdev->dev); if (ret) @@ -2223,25 +2218,21 @@ static int mt8192_afe_pcm_dev_probe(struct platform_device *pdev) /* regmap init */ afe->regmap = syscon_node_to_regmap(dev->parent->of_node); - if (IS_ERR(afe->regmap)) { - dev_err(dev, "could not get regmap from parent\n"); - return PTR_ERR(afe->regmap); - } + if (IS_ERR(afe->regmap)) + return dev_err_probe(dev, PTR_ERR(afe->regmap), + "could not get regmap from parent"); + ret = regmap_attach_dev(dev, afe->regmap, &mt8192_afe_regmap_config); - if (ret) { - dev_warn(dev, "regmap_attach_dev fail, ret %d\n", ret); - return ret; - } + if (ret) + return dev_err_probe(dev, ret, "regmap_attach_dev fail\n"); /* enable clock for regcache get default value from hw */ afe_priv->pm_runtime_bypass_reg_ctl = true; pm_runtime_get_sync(&pdev->dev); ret = regmap_reinit_cache(afe->regmap, &mt8192_afe_regmap_config); - if (ret) { - dev_err(dev, "regmap_reinit_cache fail, ret %d\n", ret); - return ret; - } + if (ret) + return dev_err_probe(dev, ret, "regmap_reinit_cache fail\n"); pm_runtime_put_sync(&pdev->dev); afe_priv->pm_runtime_bypass_reg_ctl = false; @@ -2281,30 +2272,22 @@ static int mt8192_afe_pcm_dev_probe(struct platform_device *pdev) ret = devm_request_irq(dev, irq_id, mt8192_afe_irq_handler, IRQF_TRIGGER_NONE, "asys-isr", (void *)afe); - if (ret) { - dev_err(dev, "could not request_irq for Afe_ISR_Handle\n"); - return ret; - } + if (ret) + return dev_err_probe(dev, ret, "could not request_irq for Afe_ISR_Handle\n"); /* init sub_dais */ INIT_LIST_HEAD(&afe->sub_dais); for (i = 0; i < ARRAY_SIZE(dai_register_cbs); i++) { ret = dai_register_cbs[i](afe); - if (ret) { - dev_warn(afe->dev, "dai register i %d fail, ret %d\n", - i, ret); - return ret; - } + if (ret) + return dev_err_probe(afe->dev, ret, "dai %d register fail", i); } /* init dai_driver and component_driver */ ret = mtk_afe_combine_sub_dai(afe); - if (ret) { - dev_warn(afe->dev, "mtk_afe_combine_sub_dai fail, ret %d\n", - ret); - return ret; - } + if (ret) + return dev_err_probe(afe->dev, ret, "mtk_afe_combine_sub_dai fail\n"); /* others */ afe->mtk_afe_hardware = &mt8192_afe_hardware; @@ -2320,19 +2303,15 @@ static int mt8192_afe_pcm_dev_probe(struct platform_device *pdev) /* register platform */ ret = devm_snd_soc_register_component(&pdev->dev, &mt8192_afe_component, NULL, 0); - if (ret) { - dev_warn(dev, "err_platform\n"); - return ret; - } + if (ret) + return dev_err_probe(dev, ret, "Couldn't register AFE component\n"); ret = devm_snd_soc_register_component(&pdev->dev, &mt8192_afe_pcm_component, afe->dai_drivers, afe->num_dai_drivers); - if (ret) { - dev_warn(dev, "err_dai_component\n"); - return ret; - } + if (ret) + return dev_err_probe(dev, ret, "Couldn't register AFE-PCM component\n"); return 0; } -- cgit v1.2.3 From d6c01755805d346a1382d2d81c214b2ca557487a Mon Sep 17 00:00:00 2001 From: AngeloGioacchino Del Regno Date: Wed, 13 Mar 2024 12:01:28 +0100 Subject: ASoC: mediatek: Commonize ADDA rate transform functions and enums Both the enumerations for UL/DL rates, delay data and the functions adda_{dl,ul}_rate_transform were duplicated for each MediaTek SoC dai-adda driver: move the common bits to a new mtk-dai-adda-common file and its header. While at it, also add the "mtk_" prefix to the exported functions. Signed-off-by: AngeloGioacchino Del Regno Link: https://msgid.link/r/20240313110147.1267793-4-angelogioacchino.delregno@collabora.com Signed-off-by: Mark Brown --- sound/soc/mediatek/common/Makefile | 2 + sound/soc/mediatek/common/mtk-dai-adda-common.c | 70 +++++++++++++++++++ sound/soc/mediatek/common/mtk-dai-adda-common.h | 45 ++++++++++++ sound/soc/mediatek/mt6797/mt6797-dai-adda.c | 85 +---------------------- sound/soc/mediatek/mt8183/mt8183-dai-adda.c | 90 +----------------------- sound/soc/mediatek/mt8186/mt8186-dai-adda.c | 92 +------------------------ sound/soc/mediatek/mt8188/mt8188-dai-adda.c | 89 +----------------------- sound/soc/mediatek/mt8192/mt8192-dai-adda.c | 90 +----------------------- sound/soc/mediatek/mt8195/mt8195-dai-adda.c | 90 +----------------------- 9 files changed, 135 insertions(+), 518 deletions(-) create mode 100644 sound/soc/mediatek/common/mtk-dai-adda-common.c create mode 100644 sound/soc/mediatek/common/mtk-dai-adda-common.h diff --git a/sound/soc/mediatek/common/Makefile b/sound/soc/mediatek/common/Makefile index 42e636c10c1e..363cc258a3d5 100644 --- a/sound/soc/mediatek/common/Makefile +++ b/sound/soc/mediatek/common/Makefile @@ -1,6 +1,8 @@ # SPDX-License-Identifier: GPL-2.0 # platform driver snd-soc-mtk-common-objs := mtk-afe-platform-driver.o mtk-afe-fe-dai.o mtk-dsp-sof-common.o mtk-soundcard-driver.o +snd-soc-mtk-common-objs += mtk-dai-adda-common.o + obj-$(CONFIG_SND_SOC_MEDIATEK) += snd-soc-mtk-common.o obj-$(CONFIG_SND_SOC_MTK_BTCVSD) += mtk-btcvsd.o diff --git a/sound/soc/mediatek/common/mtk-dai-adda-common.c b/sound/soc/mediatek/common/mtk-dai-adda-common.c new file mode 100644 index 000000000000..4dc1412489d6 --- /dev/null +++ b/sound/soc/mediatek/common/mtk-dai-adda-common.c @@ -0,0 +1,70 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * MediaTek ALSA SoC Audio DAI ADDA Common + * + * Copyright (c) 2021 MediaTek Inc. + * Copyright (c) 2024 Collabora Ltd. + * AngeloGioacchino Del Regno + */ + +#include +#include + +#include "mtk-base-afe.h" +#include "mtk-dai-adda-common.h" + +unsigned int mtk_adda_dl_rate_transform(struct mtk_base_afe *afe, u32 rate) +{ + switch (rate) { + case 8000: + return MTK_AFE_ADDA_DL_RATE_8K; + case 11025: + return MTK_AFE_ADDA_DL_RATE_11K; + case 12000: + return MTK_AFE_ADDA_DL_RATE_12K; + case 16000: + return MTK_AFE_ADDA_DL_RATE_16K; + case 22050: + return MTK_AFE_ADDA_DL_RATE_22K; + case 24000: + return MTK_AFE_ADDA_DL_RATE_24K; + case 32000: + return MTK_AFE_ADDA_DL_RATE_32K; + case 44100: + return MTK_AFE_ADDA_DL_RATE_44K; + case 48000: + return MTK_AFE_ADDA_DL_RATE_48K; + case 96000: + return MTK_AFE_ADDA_DL_RATE_96K; + case 192000: + return MTK_AFE_ADDA_DL_RATE_192K; + default: + dev_info(afe->dev, "%s(), rate %d invalid, use 48kHz!!!\n", + __func__, rate); + return MTK_AFE_ADDA_DL_RATE_48K; + } +} +EXPORT_SYMBOL_GPL(mtk_adda_dl_rate_transform); + +unsigned int mtk_adda_ul_rate_transform(struct mtk_base_afe *afe, u32 rate) +{ + switch (rate) { + case 8000: + return MTK_AFE_ADDA_UL_RATE_8K; + case 16000: + return MTK_AFE_ADDA_UL_RATE_16K; + case 32000: + return MTK_AFE_ADDA_UL_RATE_32K; + case 48000: + return MTK_AFE_ADDA_UL_RATE_48K; + case 96000: + return MTK_AFE_ADDA_UL_RATE_96K; + case 192000: + return MTK_AFE_ADDA_UL_RATE_192K; + default: + dev_info(afe->dev, "%s(), rate %d invalid, use 48kHz!!!\n", + __func__, rate); + return MTK_AFE_ADDA_UL_RATE_48K; + } +} +EXPORT_SYMBOL_GPL(mtk_adda_ul_rate_transform); diff --git a/sound/soc/mediatek/common/mtk-dai-adda-common.h b/sound/soc/mediatek/common/mtk-dai-adda-common.h new file mode 100644 index 000000000000..208b0dd89f57 --- /dev/null +++ b/sound/soc/mediatek/common/mtk-dai-adda-common.h @@ -0,0 +1,45 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2021 MediaTek Inc. + * Copyright (c) 2024 Collabora Ltd. + * AngeloGioacchino Del Regno + */ + +#ifndef _MTK_DAI_ADDA_COMMON_H_ +#define _MTK_DAI_ADDA_COMMON_H_ + +struct mtk_base_afe; + +enum adda_input_mode_rate { + MTK_AFE_ADDA_DL_RATE_8K = 0, + MTK_AFE_ADDA_DL_RATE_11K = 1, + MTK_AFE_ADDA_DL_RATE_12K = 2, + MTK_AFE_ADDA_DL_RATE_16K = 3, + MTK_AFE_ADDA_DL_RATE_22K = 4, + MTK_AFE_ADDA_DL_RATE_24K = 5, + MTK_AFE_ADDA_DL_RATE_32K = 6, + MTK_AFE_ADDA_DL_RATE_44K = 7, + MTK_AFE_ADDA_DL_RATE_48K = 8, + MTK_AFE_ADDA_DL_RATE_96K = 9, + MTK_AFE_ADDA_DL_RATE_192K = 10, +}; + +enum adda_voice_mode_rate { + MTK_AFE_ADDA_UL_RATE_8K = 0, + MTK_AFE_ADDA_UL_RATE_16K = 1, + MTK_AFE_ADDA_UL_RATE_32K = 2, + MTK_AFE_ADDA_UL_RATE_48K = 3, + MTK_AFE_ADDA_UL_RATE_96K = 4, + MTK_AFE_ADDA_UL_RATE_192K = 5, + MTK_AFE_ADDA_UL_RATE_48K_HD = 6, +}; + +enum adda_rxif_delay_data { + DELAY_DATA_MISO1 = 0, + DELAY_DATA_MISO0 = 1, + DELAY_DATA_MISO2 = 1, +}; + +unsigned int mtk_adda_dl_rate_transform(struct mtk_base_afe *afe, u32 rate); +unsigned int mtk_adda_ul_rate_transform(struct mtk_base_afe *afe, u32 rate); +#endif diff --git a/sound/soc/mediatek/mt6797/mt6797-dai-adda.c b/sound/soc/mediatek/mt6797/mt6797-dai-adda.c index 0ac6409c6d61..78f3ad758c12 100644 --- a/sound/soc/mediatek/mt6797/mt6797-dai-adda.c +++ b/sound/soc/mediatek/mt6797/mt6797-dai-adda.c @@ -10,86 +10,7 @@ #include "mt6797-afe-common.h" #include "mt6797-interconnection.h" #include "mt6797-reg.h" - -enum { - MTK_AFE_ADDA_DL_RATE_8K = 0, - MTK_AFE_ADDA_DL_RATE_11K = 1, - MTK_AFE_ADDA_DL_RATE_12K = 2, - MTK_AFE_ADDA_DL_RATE_16K = 3, - MTK_AFE_ADDA_DL_RATE_22K = 4, - MTK_AFE_ADDA_DL_RATE_24K = 5, - MTK_AFE_ADDA_DL_RATE_32K = 6, - MTK_AFE_ADDA_DL_RATE_44K = 7, - MTK_AFE_ADDA_DL_RATE_48K = 8, - MTK_AFE_ADDA_DL_RATE_96K = 9, - MTK_AFE_ADDA_DL_RATE_192K = 10, -}; - -enum { - MTK_AFE_ADDA_UL_RATE_8K = 0, - MTK_AFE_ADDA_UL_RATE_16K = 1, - MTK_AFE_ADDA_UL_RATE_32K = 2, - MTK_AFE_ADDA_UL_RATE_48K = 3, - MTK_AFE_ADDA_UL_RATE_96K = 4, - MTK_AFE_ADDA_UL_RATE_192K = 5, - MTK_AFE_ADDA_UL_RATE_48K_HD = 6, -}; - -static unsigned int adda_dl_rate_transform(struct mtk_base_afe *afe, - unsigned int rate) -{ - switch (rate) { - case 8000: - return MTK_AFE_ADDA_DL_RATE_8K; - case 11025: - return MTK_AFE_ADDA_DL_RATE_11K; - case 12000: - return MTK_AFE_ADDA_DL_RATE_12K; - case 16000: - return MTK_AFE_ADDA_DL_RATE_16K; - case 22050: - return MTK_AFE_ADDA_DL_RATE_22K; - case 24000: - return MTK_AFE_ADDA_DL_RATE_24K; - case 32000: - return MTK_AFE_ADDA_DL_RATE_32K; - case 44100: - return MTK_AFE_ADDA_DL_RATE_44K; - case 48000: - return MTK_AFE_ADDA_DL_RATE_48K; - case 96000: - return MTK_AFE_ADDA_DL_RATE_96K; - case 192000: - return MTK_AFE_ADDA_DL_RATE_192K; - default: - dev_warn(afe->dev, "%s(), rate %d invalid, use 48kHz!!!\n", - __func__, rate); - return MTK_AFE_ADDA_DL_RATE_48K; - } -} - -static unsigned int adda_ul_rate_transform(struct mtk_base_afe *afe, - unsigned int rate) -{ - switch (rate) { - case 8000: - return MTK_AFE_ADDA_UL_RATE_8K; - case 16000: - return MTK_AFE_ADDA_UL_RATE_16K; - case 32000: - return MTK_AFE_ADDA_UL_RATE_32K; - case 48000: - return MTK_AFE_ADDA_UL_RATE_48K; - case 96000: - return MTK_AFE_ADDA_UL_RATE_96K; - case 192000: - return MTK_AFE_ADDA_UL_RATE_192K; - default: - dev_warn(afe->dev, "%s(), rate %d invalid, use 48kHz!!!\n", - __func__, rate); - return MTK_AFE_ADDA_UL_RATE_48K; - } -} +#include "../common/mtk-dai-adda-common.h" /* dai component */ static const struct snd_kcontrol_new mtk_adda_dl_ch1_mix[] = { @@ -246,7 +167,7 @@ static int mtk_dai_adda_hw_params(struct snd_pcm_substream *substream, regmap_write(afe->regmap, AFE_ADDA_PREDIS_CON1, 0); /* set input sampling rate */ - dl_src2_con0 = adda_dl_rate_transform(afe, rate) << 28; + dl_src2_con0 = mtk_adda_dl_rate_transform(afe, rate) << 28; /* set output mode */ switch (rate) { @@ -296,7 +217,7 @@ static int mtk_dai_adda_hw_params(struct snd_pcm_substream *substream, 0x1 << 0, 0x0 << 0); - voice_mode = adda_ul_rate_transform(afe, rate); + voice_mode = mtk_adda_ul_rate_transform(afe, rate); ul_src_con0 |= (voice_mode << 17) & (0x7 << 17); diff --git a/sound/soc/mediatek/mt8183/mt8183-dai-adda.c b/sound/soc/mediatek/mt8183/mt8183-dai-adda.c index 5b8a274419ed..be69bcea2a78 100644 --- a/sound/soc/mediatek/mt8183/mt8183-dai-adda.c +++ b/sound/soc/mediatek/mt8183/mt8183-dai-adda.c @@ -10,6 +10,7 @@ #include "mt8183-afe-common.h" #include "mt8183-interconnection.h" #include "mt8183-reg.h" +#include "../common/mtk-dai-adda-common.h" enum { AUDIO_SDM_LEVEL_MUTE = 0, @@ -18,91 +19,6 @@ enum { /* you need to change formula of hp impedance and dc trim too */ }; -enum { - DELAY_DATA_MISO1 = 0, - DELAY_DATA_MISO2, -}; - -enum { - MTK_AFE_ADDA_DL_RATE_8K = 0, - MTK_AFE_ADDA_DL_RATE_11K = 1, - MTK_AFE_ADDA_DL_RATE_12K = 2, - MTK_AFE_ADDA_DL_RATE_16K = 3, - MTK_AFE_ADDA_DL_RATE_22K = 4, - MTK_AFE_ADDA_DL_RATE_24K = 5, - MTK_AFE_ADDA_DL_RATE_32K = 6, - MTK_AFE_ADDA_DL_RATE_44K = 7, - MTK_AFE_ADDA_DL_RATE_48K = 8, - MTK_AFE_ADDA_DL_RATE_96K = 9, - MTK_AFE_ADDA_DL_RATE_192K = 10, -}; - -enum { - MTK_AFE_ADDA_UL_RATE_8K = 0, - MTK_AFE_ADDA_UL_RATE_16K = 1, - MTK_AFE_ADDA_UL_RATE_32K = 2, - MTK_AFE_ADDA_UL_RATE_48K = 3, - MTK_AFE_ADDA_UL_RATE_96K = 4, - MTK_AFE_ADDA_UL_RATE_192K = 5, - MTK_AFE_ADDA_UL_RATE_48K_HD = 6, -}; - -static unsigned int adda_dl_rate_transform(struct mtk_base_afe *afe, - unsigned int rate) -{ - switch (rate) { - case 8000: - return MTK_AFE_ADDA_DL_RATE_8K; - case 11025: - return MTK_AFE_ADDA_DL_RATE_11K; - case 12000: - return MTK_AFE_ADDA_DL_RATE_12K; - case 16000: - return MTK_AFE_ADDA_DL_RATE_16K; - case 22050: - return MTK_AFE_ADDA_DL_RATE_22K; - case 24000: - return MTK_AFE_ADDA_DL_RATE_24K; - case 32000: - return MTK_AFE_ADDA_DL_RATE_32K; - case 44100: - return MTK_AFE_ADDA_DL_RATE_44K; - case 48000: - return MTK_AFE_ADDA_DL_RATE_48K; - case 96000: - return MTK_AFE_ADDA_DL_RATE_96K; - case 192000: - return MTK_AFE_ADDA_DL_RATE_192K; - default: - dev_warn(afe->dev, "%s(), rate %d invalid, use 48kHz!!!\n", - __func__, rate); - return MTK_AFE_ADDA_DL_RATE_48K; - } -} - -static unsigned int adda_ul_rate_transform(struct mtk_base_afe *afe, - unsigned int rate) -{ - switch (rate) { - case 8000: - return MTK_AFE_ADDA_UL_RATE_8K; - case 16000: - return MTK_AFE_ADDA_UL_RATE_16K; - case 32000: - return MTK_AFE_ADDA_UL_RATE_32K; - case 48000: - return MTK_AFE_ADDA_UL_RATE_48K; - case 96000: - return MTK_AFE_ADDA_UL_RATE_96K; - case 192000: - return MTK_AFE_ADDA_UL_RATE_192K; - default: - dev_warn(afe->dev, "%s(), rate %d invalid, use 48kHz!!!\n", - __func__, rate); - return MTK_AFE_ADDA_UL_RATE_48K; - } -} - /* dai component */ static const struct snd_kcontrol_new mtk_adda_dl_ch1_mix[] = { SOC_DAPM_SINGLE_AUTODISABLE("DL1_CH1", AFE_CONN3, I_DL1_CH1, 1, 0), @@ -369,7 +285,7 @@ static int mtk_dai_adda_hw_params(struct snd_pcm_substream *substream, regmap_write(afe->regmap, AFE_ADDA_PREDIS_CON1, 0); /* set sampling rate */ - dl_src2_con0 = adda_dl_rate_transform(afe, rate) << 28; + dl_src2_con0 = mtk_adda_dl_rate_transform(afe, rate) << 28; /* set output mode */ switch (rate) { @@ -420,7 +336,7 @@ static int mtk_dai_adda_hw_params(struct snd_pcm_substream *substream, 0x1 << 0, 0x0 << 0); - voice_mode = adda_ul_rate_transform(afe, rate); + voice_mode = mtk_adda_ul_rate_transform(afe, rate); ul_src_con0 |= (voice_mode << 17) & (0x7 << 17); diff --git a/sound/soc/mediatek/mt8186/mt8186-dai-adda.c b/sound/soc/mediatek/mt8186/mt8186-dai-adda.c index ad6d4b5cf697..dbd157d1a1ea 100644 --- a/sound/soc/mediatek/mt8186/mt8186-dai-adda.c +++ b/sound/soc/mediatek/mt8186/mt8186-dai-adda.c @@ -11,6 +11,7 @@ #include "mt8186-afe-common.h" #include "mt8186-afe-gpio.h" #include "mt8186-interconnection.h" +#include "../common/mtk-dai-adda-common.h" enum { UL_IIR_SW = 0, @@ -33,35 +34,6 @@ enum { AUDIO_SDM_3RD, }; -enum { - DELAY_DATA_MISO1 = 0, - DELAY_DATA_MISO2, -}; - -enum { - MTK_AFE_ADDA_DL_RATE_8K = 0, - MTK_AFE_ADDA_DL_RATE_11K = 1, - MTK_AFE_ADDA_DL_RATE_12K = 2, - MTK_AFE_ADDA_DL_RATE_16K = 3, - MTK_AFE_ADDA_DL_RATE_22K = 4, - MTK_AFE_ADDA_DL_RATE_24K = 5, - MTK_AFE_ADDA_DL_RATE_32K = 6, - MTK_AFE_ADDA_DL_RATE_44K = 7, - MTK_AFE_ADDA_DL_RATE_48K = 8, - MTK_AFE_ADDA_DL_RATE_96K = 9, - MTK_AFE_ADDA_DL_RATE_192K = 10, -}; - -enum { - MTK_AFE_ADDA_UL_RATE_8K = 0, - MTK_AFE_ADDA_UL_RATE_16K = 1, - MTK_AFE_ADDA_UL_RATE_32K = 2, - MTK_AFE_ADDA_UL_RATE_48K = 3, - MTK_AFE_ADDA_UL_RATE_96K = 4, - MTK_AFE_ADDA_UL_RATE_192K = 5, - MTK_AFE_ADDA_UL_RATE_48K_HD = 6, -}; - #define SDM_AUTO_RESET_THRESHOLD 0x190000 struct mtk_afe_adda_priv { @@ -83,64 +55,6 @@ static struct mtk_afe_adda_priv *get_adda_priv_by_name(struct mtk_base_afe *afe, return afe_priv->dai_priv[dai_id]; } -static unsigned int adda_dl_rate_transform(struct mtk_base_afe *afe, - unsigned int rate) -{ - switch (rate) { - case 8000: - return MTK_AFE_ADDA_DL_RATE_8K; - case 11025: - return MTK_AFE_ADDA_DL_RATE_11K; - case 12000: - return MTK_AFE_ADDA_DL_RATE_12K; - case 16000: - return MTK_AFE_ADDA_DL_RATE_16K; - case 22050: - return MTK_AFE_ADDA_DL_RATE_22K; - case 24000: - return MTK_AFE_ADDA_DL_RATE_24K; - case 32000: - return MTK_AFE_ADDA_DL_RATE_32K; - case 44100: - return MTK_AFE_ADDA_DL_RATE_44K; - case 48000: - return MTK_AFE_ADDA_DL_RATE_48K; - case 96000: - return MTK_AFE_ADDA_DL_RATE_96K; - case 192000: - return MTK_AFE_ADDA_DL_RATE_192K; - default: - dev_dbg(afe->dev, "%s(), rate %d invalid, use 48kHz!!!\n", - __func__, rate); - } - - return MTK_AFE_ADDA_DL_RATE_48K; -} - -static unsigned int adda_ul_rate_transform(struct mtk_base_afe *afe, - unsigned int rate) -{ - switch (rate) { - case 8000: - return MTK_AFE_ADDA_UL_RATE_8K; - case 16000: - return MTK_AFE_ADDA_UL_RATE_16K; - case 32000: - return MTK_AFE_ADDA_UL_RATE_32K; - case 48000: - return MTK_AFE_ADDA_UL_RATE_48K; - case 96000: - return MTK_AFE_ADDA_UL_RATE_96K; - case 192000: - return MTK_AFE_ADDA_UL_RATE_192K; - default: - dev_dbg(afe->dev, "%s(), rate %d invalid, use 48kHz!!!\n", - __func__, rate); - } - - return MTK_AFE_ADDA_UL_RATE_48K; -} - /* dai component */ static const struct snd_kcontrol_new mtk_adda_dl_ch1_mix[] = { SOC_DAPM_SINGLE_AUTODISABLE("DL1_CH1 Switch", AFE_CONN3, I_DL1_CH1, 1, 0), @@ -658,7 +572,7 @@ static int mtk_dai_adda_hw_params(struct snd_pcm_substream *substream, adda_priv->dl_rate = rate; /* set sampling rate */ - dl_src2_con0 = adda_dl_rate_transform(afe, rate) << + dl_src2_con0 = mtk_adda_dl_rate_transform(afe, rate) << DL_2_INPUT_MODE_CTL_SFT; /* set output mode, UP_SAMPLING_RATE_X8 */ @@ -721,7 +635,7 @@ static int mtk_dai_adda_hw_params(struct snd_pcm_substream *substream, } } else { unsigned int ul_src_con0 = 0; - unsigned int voice_mode = adda_ul_rate_transform(afe, rate); + unsigned int voice_mode = mtk_adda_ul_rate_transform(afe, rate); adda_priv->ul_rate = rate; ul_src_con0 |= (voice_mode << 17) & (0x7 << 17); diff --git a/sound/soc/mediatek/mt8188/mt8188-dai-adda.c b/sound/soc/mediatek/mt8188/mt8188-dai-adda.c index 7dc029f2b428..8a17d1935c48 100644 --- a/sound/soc/mediatek/mt8188/mt8188-dai-adda.c +++ b/sound/soc/mediatek/mt8188/mt8188-dai-adda.c @@ -14,6 +14,7 @@ #include "mt8188-afe-clk.h" #include "mt8188-afe-common.h" #include "mt8188-reg.h" +#include "../common/mtk-dai-adda-common.h" #define ADDA_HIRES_THRES 48000 @@ -24,94 +25,10 @@ enum { SUPPLY_SEQ_ADDA_AFE_ON, }; -enum { - MTK_AFE_ADDA_DL_RATE_8K = 0, - MTK_AFE_ADDA_DL_RATE_11K = 1, - MTK_AFE_ADDA_DL_RATE_12K = 2, - MTK_AFE_ADDA_DL_RATE_16K = 3, - MTK_AFE_ADDA_DL_RATE_22K = 4, - MTK_AFE_ADDA_DL_RATE_24K = 5, - MTK_AFE_ADDA_DL_RATE_32K = 6, - MTK_AFE_ADDA_DL_RATE_44K = 7, - MTK_AFE_ADDA_DL_RATE_48K = 8, - MTK_AFE_ADDA_DL_RATE_96K = 9, - MTK_AFE_ADDA_DL_RATE_192K = 10, -}; - -enum { - MTK_AFE_ADDA_UL_RATE_8K = 0, - MTK_AFE_ADDA_UL_RATE_16K = 1, - MTK_AFE_ADDA_UL_RATE_32K = 2, - MTK_AFE_ADDA_UL_RATE_48K = 3, - MTK_AFE_ADDA_UL_RATE_96K = 4, - MTK_AFE_ADDA_UL_RATE_192K = 5, -}; - -enum { - DELAY_DATA_MISO1 = 0, - DELAY_DATA_MISO0 = 1, -}; - struct mtk_dai_adda_priv { bool hires_required; }; -static unsigned int afe_adda_dl_rate_transform(struct mtk_base_afe *afe, - unsigned int rate) -{ - switch (rate) { - case 8000: - return MTK_AFE_ADDA_DL_RATE_8K; - case 11025: - return MTK_AFE_ADDA_DL_RATE_11K; - case 12000: - return MTK_AFE_ADDA_DL_RATE_12K; - case 16000: - return MTK_AFE_ADDA_DL_RATE_16K; - case 22050: - return MTK_AFE_ADDA_DL_RATE_22K; - case 24000: - return MTK_AFE_ADDA_DL_RATE_24K; - case 32000: - return MTK_AFE_ADDA_DL_RATE_32K; - case 44100: - return MTK_AFE_ADDA_DL_RATE_44K; - case 48000: - return MTK_AFE_ADDA_DL_RATE_48K; - case 96000: - return MTK_AFE_ADDA_DL_RATE_96K; - case 192000: - return MTK_AFE_ADDA_DL_RATE_192K; - default: - dev_info(afe->dev, "%s(), rate %u invalid, use 48kHz!!!\n", - __func__, rate); - return MTK_AFE_ADDA_DL_RATE_48K; - } -} - -static unsigned int afe_adda_ul_rate_transform(struct mtk_base_afe *afe, - unsigned int rate) -{ - switch (rate) { - case 8000: - return MTK_AFE_ADDA_UL_RATE_8K; - case 16000: - return MTK_AFE_ADDA_UL_RATE_16K; - case 32000: - return MTK_AFE_ADDA_UL_RATE_32K; - case 48000: - return MTK_AFE_ADDA_UL_RATE_48K; - case 96000: - return MTK_AFE_ADDA_UL_RATE_96K; - case 192000: - return MTK_AFE_ADDA_UL_RATE_192K; - default: - dev_info(afe->dev, "%s(), rate %u invalid, use 48kHz!!!\n", - __func__, rate); - return MTK_AFE_ADDA_UL_RATE_48K; - } -} - static int mt8188_adda_mtkaif_init(struct mtk_base_afe *afe) { struct mt8188_afe_private *afe_priv = afe->platform_priv; @@ -440,7 +357,7 @@ static int mtk_dai_da_configure(struct mtk_base_afe *afe, /* set sampling rate */ mask |= DL_2_INPUT_MODE_CTL_MASK; val |= FIELD_PREP(DL_2_INPUT_MODE_CTL_MASK, - afe_adda_dl_rate_transform(afe, rate)); + mtk_adda_dl_rate_transform(afe, rate)); /* turn off saturation */ mask |= DL_2_CH1_SATURATION_EN_CTL; @@ -474,7 +391,7 @@ static int mtk_dai_ad_configure(struct mtk_base_afe *afe, mask = UL_VOICE_MODE_CTL_MASK; val = FIELD_PREP(UL_VOICE_MODE_CTL_MASK, - afe_adda_ul_rate_transform(afe, rate)); + mtk_adda_ul_rate_transform(afe, rate)); regmap_update_bits(afe->regmap, AFE_ADDA_UL_SRC_CON0, mask, val); diff --git a/sound/soc/mediatek/mt8192/mt8192-dai-adda.c b/sound/soc/mediatek/mt8192/mt8192-dai-adda.c index 36d33032a37a..99de85b87643 100644 --- a/sound/soc/mediatek/mt8192/mt8192-dai-adda.c +++ b/sound/soc/mediatek/mt8192/mt8192-dai-adda.c @@ -13,6 +13,7 @@ #include "mt8192-afe-common.h" #include "mt8192-afe-gpio.h" #include "mt8192-interconnection.h" +#include "../common/mtk-dai-adda-common.h" enum { UL_IIR_SW = 0, @@ -35,93 +36,8 @@ enum { AUDIO_SDM_3RD, }; -enum { - DELAY_DATA_MISO1 = 0, - DELAY_DATA_MISO2, -}; - -enum { - MTK_AFE_ADDA_DL_RATE_8K = 0, - MTK_AFE_ADDA_DL_RATE_11K = 1, - MTK_AFE_ADDA_DL_RATE_12K = 2, - MTK_AFE_ADDA_DL_RATE_16K = 3, - MTK_AFE_ADDA_DL_RATE_22K = 4, - MTK_AFE_ADDA_DL_RATE_24K = 5, - MTK_AFE_ADDA_DL_RATE_32K = 6, - MTK_AFE_ADDA_DL_RATE_44K = 7, - MTK_AFE_ADDA_DL_RATE_48K = 8, - MTK_AFE_ADDA_DL_RATE_96K = 9, - MTK_AFE_ADDA_DL_RATE_192K = 10, -}; - -enum { - MTK_AFE_ADDA_UL_RATE_8K = 0, - MTK_AFE_ADDA_UL_RATE_16K = 1, - MTK_AFE_ADDA_UL_RATE_32K = 2, - MTK_AFE_ADDA_UL_RATE_48K = 3, - MTK_AFE_ADDA_UL_RATE_96K = 4, - MTK_AFE_ADDA_UL_RATE_192K = 5, - MTK_AFE_ADDA_UL_RATE_48K_HD = 6, -}; - #define SDM_AUTO_RESET_THRESHOLD 0x190000 -static unsigned int adda_dl_rate_transform(struct mtk_base_afe *afe, - unsigned int rate) -{ - switch (rate) { - case 8000: - return MTK_AFE_ADDA_DL_RATE_8K; - case 11025: - return MTK_AFE_ADDA_DL_RATE_11K; - case 12000: - return MTK_AFE_ADDA_DL_RATE_12K; - case 16000: - return MTK_AFE_ADDA_DL_RATE_16K; - case 22050: - return MTK_AFE_ADDA_DL_RATE_22K; - case 24000: - return MTK_AFE_ADDA_DL_RATE_24K; - case 32000: - return MTK_AFE_ADDA_DL_RATE_32K; - case 44100: - return MTK_AFE_ADDA_DL_RATE_44K; - case 48000: - return MTK_AFE_ADDA_DL_RATE_48K; - case 96000: - return MTK_AFE_ADDA_DL_RATE_96K; - case 192000: - return MTK_AFE_ADDA_DL_RATE_192K; - default: - dev_warn(afe->dev, "%s(), rate %d invalid, use 48kHz!!!\n", - __func__, rate); - return MTK_AFE_ADDA_DL_RATE_48K; - } -} - -static unsigned int adda_ul_rate_transform(struct mtk_base_afe *afe, - unsigned int rate) -{ - switch (rate) { - case 8000: - return MTK_AFE_ADDA_UL_RATE_8K; - case 16000: - return MTK_AFE_ADDA_UL_RATE_16K; - case 32000: - return MTK_AFE_ADDA_UL_RATE_32K; - case 48000: - return MTK_AFE_ADDA_UL_RATE_48K; - case 96000: - return MTK_AFE_ADDA_UL_RATE_96K; - case 192000: - return MTK_AFE_ADDA_UL_RATE_192K; - default: - dev_warn(afe->dev, "%s(), rate %d invalid, use 48kHz!!!\n", - __func__, rate); - return MTK_AFE_ADDA_UL_RATE_48K; - } -} - /* dai component */ static const struct snd_kcontrol_new mtk_adda_dl_ch1_mix[] = { SOC_DAPM_SINGLE_AUTODISABLE("DL1_CH1", AFE_CONN3, I_DL1_CH1, 1, 0), @@ -1156,7 +1072,7 @@ static int mtk_dai_adda_hw_params(struct snd_pcm_substream *substream, unsigned int dl_src2_con1 = 0; /* set sampling rate */ - dl_src2_con0 = adda_dl_rate_transform(afe, rate) << + dl_src2_con0 = mtk_adda_dl_rate_transform(afe, rate) << DL_2_INPUT_MODE_CTL_SFT; /* set output mode, UP_SAMPLING_RATE_X8 */ @@ -1246,7 +1162,7 @@ static int mtk_dai_adda_hw_params(struct snd_pcm_substream *substream, unsigned int voice_mode = 0; unsigned int ul_src_con0 = 0; /* default value */ - voice_mode = adda_ul_rate_transform(afe, rate); + voice_mode = mtk_adda_ul_rate_transform(afe, rate); ul_src_con0 |= (voice_mode << 17) & (0x7 << 17); diff --git a/sound/soc/mediatek/mt8195/mt8195-dai-adda.c b/sound/soc/mediatek/mt8195/mt8195-dai-adda.c index 0dd35255066b..8da1587128cc 100644 --- a/sound/soc/mediatek/mt8195/mt8195-dai-adda.c +++ b/sound/soc/mediatek/mt8195/mt8195-dai-adda.c @@ -12,6 +12,7 @@ #include "mt8195-afe-clk.h" #include "mt8195-afe-common.h" #include "mt8195-reg.h" +#include "../common/mtk-dai-adda-common.h" #define ADDA_DL_GAIN_LOOPBACK 0x1800 #define ADDA_HIRES_THRES 48000 @@ -25,35 +26,6 @@ enum { SUPPLY_SEQ_ADDA_AFE_ON, }; -enum { - MTK_AFE_ADDA_DL_RATE_8K = 0, - MTK_AFE_ADDA_DL_RATE_11K = 1, - MTK_AFE_ADDA_DL_RATE_12K = 2, - MTK_AFE_ADDA_DL_RATE_16K = 3, - MTK_AFE_ADDA_DL_RATE_22K = 4, - MTK_AFE_ADDA_DL_RATE_24K = 5, - MTK_AFE_ADDA_DL_RATE_32K = 6, - MTK_AFE_ADDA_DL_RATE_44K = 7, - MTK_AFE_ADDA_DL_RATE_48K = 8, - MTK_AFE_ADDA_DL_RATE_96K = 9, - MTK_AFE_ADDA_DL_RATE_192K = 10, -}; - -enum { - MTK_AFE_ADDA_UL_RATE_8K = 0, - MTK_AFE_ADDA_UL_RATE_16K = 1, - MTK_AFE_ADDA_UL_RATE_32K = 2, - MTK_AFE_ADDA_UL_RATE_48K = 3, - MTK_AFE_ADDA_UL_RATE_96K = 4, - MTK_AFE_ADDA_UL_RATE_192K = 5, -}; - -enum { - DELAY_DATA_MISO1 = 0, - DELAY_DATA_MISO0 = 1, - DELAY_DATA_MISO2 = 1, -}; - enum { MTK_AFE_ADDA, MTK_AFE_ADDA6, @@ -63,62 +35,6 @@ struct mtk_dai_adda_priv { bool hires_required; }; -static unsigned int afe_adda_dl_rate_transform(struct mtk_base_afe *afe, - unsigned int rate) -{ - switch (rate) { - case 8000: - return MTK_AFE_ADDA_DL_RATE_8K; - case 11025: - return MTK_AFE_ADDA_DL_RATE_11K; - case 12000: - return MTK_AFE_ADDA_DL_RATE_12K; - case 16000: - return MTK_AFE_ADDA_DL_RATE_16K; - case 22050: - return MTK_AFE_ADDA_DL_RATE_22K; - case 24000: - return MTK_AFE_ADDA_DL_RATE_24K; - case 32000: - return MTK_AFE_ADDA_DL_RATE_32K; - case 44100: - return MTK_AFE_ADDA_DL_RATE_44K; - case 48000: - return MTK_AFE_ADDA_DL_RATE_48K; - case 96000: - return MTK_AFE_ADDA_DL_RATE_96K; - case 192000: - return MTK_AFE_ADDA_DL_RATE_192K; - default: - dev_info(afe->dev, "%s(), rate %d invalid, use 48kHz!!!\n", - __func__, rate); - return MTK_AFE_ADDA_DL_RATE_48K; - } -} - -static unsigned int afe_adda_ul_rate_transform(struct mtk_base_afe *afe, - unsigned int rate) -{ - switch (rate) { - case 8000: - return MTK_AFE_ADDA_UL_RATE_8K; - case 16000: - return MTK_AFE_ADDA_UL_RATE_16K; - case 32000: - return MTK_AFE_ADDA_UL_RATE_32K; - case 48000: - return MTK_AFE_ADDA_UL_RATE_48K; - case 96000: - return MTK_AFE_ADDA_UL_RATE_96K; - case 192000: - return MTK_AFE_ADDA_UL_RATE_192K; - default: - dev_info(afe->dev, "%s(), rate %d invalid, use 48kHz!!!\n", - __func__, rate); - return MTK_AFE_ADDA_UL_RATE_48K; - } -} - static int mt8195_adda_mtkaif_init(struct mtk_base_afe *afe) { struct mt8195_afe_private *afe_priv = afe->platform_priv; @@ -644,7 +560,7 @@ static int mtk_dai_da_configure(struct mtk_base_afe *afe, /* set sampling rate */ mask |= DL_2_INPUT_MODE_CTL_MASK; - val |= DL_2_INPUT_MODE_CTL(afe_adda_dl_rate_transform(afe, rate)); + val |= DL_2_INPUT_MODE_CTL(mtk_adda_dl_rate_transform(afe, rate)); /* turn off saturation */ mask |= DL_2_CH1_SATURATION_EN_CTL; @@ -681,7 +597,7 @@ static int mtk_dai_ad_configure(struct mtk_base_afe *afe, unsigned int mask = 0; mask |= UL_VOICE_MODE_CTL_MASK; - val |= UL_VOICE_MODE_CTL(afe_adda_ul_rate_transform(afe, rate)); + val |= UL_VOICE_MODE_CTL(mtk_adda_ul_rate_transform(afe, rate)); switch (id) { case MT8195_AFE_IO_UL_SRC1: -- cgit v1.2.3 From 5f39231888c63f0a7708abc86b51b847476379d8 Mon Sep 17 00:00:00 2001 From: AngeloGioacchino Del Regno Date: Wed, 13 Mar 2024 12:01:29 +0100 Subject: ASoC: mediatek: Assign dummy when codec not specified for a DAI link MediaTek sound card drivers are checking whether a DAI link is present and used on a board to assign the correct parameters and this is done by checking the codec DAI names at probe time. If no real codec is present, assign the dummy codec to the DAI link to avoid NULL pointer during string comparison. Fixes: 4302187d955f ("ASoC: mediatek: common: add soundcard driver common code") Signed-off-by: AngeloGioacchino Del Regno Link: https://msgid.link/r/20240313110147.1267793-5-angelogioacchino.delregno@collabora.com Signed-off-by: Mark Brown --- sound/soc/mediatek/common/mtk-soundcard-driver.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/sound/soc/mediatek/common/mtk-soundcard-driver.c b/sound/soc/mediatek/common/mtk-soundcard-driver.c index a58e1e3674de..000a086a8cf4 100644 --- a/sound/soc/mediatek/common/mtk-soundcard-driver.c +++ b/sound/soc/mediatek/common/mtk-soundcard-driver.c @@ -22,7 +22,11 @@ static int set_card_codec_info(struct snd_soc_card *card, codec_node = of_get_child_by_name(sub_node, "codec"); if (!codec_node) { - dev_dbg(dev, "%s no specified codec\n", dai_link->name); + dev_dbg(dev, "%s no specified codec: setting dummy.\n", dai_link->name); + + dai_link->codecs = &snd_soc_dummy_dlc; + dai_link->num_codecs = 1; + dai_link->dynamic = 1; return 0; } -- cgit v1.2.3 From 885dd75f41f9fff5b277bc6ab28ad798f98a37b4 Mon Sep 17 00:00:00 2001 From: Frank Li Date: Fri, 22 Mar 2024 10:54:05 -0400 Subject: ASoC: dt-bindings: fsl-esai: Convert fsl,esai.txt to yaml Convert fsl,esai.txt to yaml. So DTB_CHECK tools can verify dts file about esai part. clock-names 'spba' is optional according to description. So minItems of clocks and clock-names is 3. Signed-off-by: Frank Li Reviewed-by: Rob Herring Link: https://msgid.link/r/20240322145406.2613256-1-Frank.Li@nxp.com Signed-off-by: Mark Brown --- .../devicetree/bindings/sound/fsl,esai.txt | 68 ------------ .../devicetree/bindings/sound/fsl,esai.yaml | 116 +++++++++++++++++++++ 2 files changed, 116 insertions(+), 68 deletions(-) delete mode 100644 Documentation/devicetree/bindings/sound/fsl,esai.txt create mode 100644 Documentation/devicetree/bindings/sound/fsl,esai.yaml diff --git a/Documentation/devicetree/bindings/sound/fsl,esai.txt b/Documentation/devicetree/bindings/sound/fsl,esai.txt deleted file mode 100644 index 90112ca1ff42..000000000000 --- a/Documentation/devicetree/bindings/sound/fsl,esai.txt +++ /dev/null @@ -1,68 +0,0 @@ -Freescale Enhanced Serial Audio Interface (ESAI) Controller - -The Enhanced Serial Audio Interface (ESAI) provides a full-duplex serial port -for serial communication with a variety of serial devices, including industry -standard codecs, Sony/Phillips Digital Interface (S/PDIF) transceivers, and -other DSPs. It has up to six transmitters and four receivers. - -Required properties: - - - compatible : Compatible list, should contain one of the following - compatibles: - "fsl,imx35-esai", - "fsl,vf610-esai", - "fsl,imx6ull-esai", - "fsl,imx8qm-esai", - - - reg : Offset and length of the register set for the device. - - - interrupts : Contains the spdif interrupt. - - - dmas : Generic dma devicetree binding as described in - Documentation/devicetree/bindings/dma/dma.txt. - - - dma-names : Two dmas have to be defined, "tx" and "rx". - - - clocks : Contains an entry for each entry in clock-names. - - - clock-names : Includes the following entries: - "core" The core clock used to access registers - "extal" The esai baud clock for esai controller used to - derive HCK, SCK and FS. - "fsys" The system clock derived from ahb clock used to - derive HCK, SCK and FS. - "spba" The spba clock is required when ESAI is placed as a - bus slave of the Shared Peripheral Bus and when two - or more bus masters (CPU, DMA or DSP) try to access - it. This property is optional depending on the SoC - design. - - - fsl,fifo-depth : The number of elements in the transmit and receive - FIFOs. This number is the maximum allowed value for - TFCR[TFWM] or RFCR[RFWM]. - - - fsl,esai-synchronous: This is a boolean property. If present, indicating - that ESAI would work in the synchronous mode, which - means all the settings for Receiving would be - duplicated from Transmission related registers. - -Optional properties: - - - big-endian : If this property is absent, the native endian mode - will be in use as default, or the big endian mode - will be in use for all the device registers. - -Example: - -esai: esai@2024000 { - compatible = "fsl,imx35-esai"; - reg = <0x02024000 0x4000>; - interrupts = <0 51 0x04>; - clocks = <&clks 208>, <&clks 118>, <&clks 208>; - clock-names = "core", "extal", "fsys"; - dmas = <&sdma 23 21 0>, <&sdma 24 21 0>; - dma-names = "rx", "tx"; - fsl,fifo-depth = <128>; - fsl,esai-synchronous; - big-endian; -}; diff --git a/Documentation/devicetree/bindings/sound/fsl,esai.yaml b/Documentation/devicetree/bindings/sound/fsl,esai.yaml new file mode 100644 index 000000000000..f167f1634d7e --- /dev/null +++ b/Documentation/devicetree/bindings/sound/fsl,esai.yaml @@ -0,0 +1,116 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/sound/fsl,esai.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Freescale Enhanced Serial Audio Interface (ESAI) Controller + +maintainers: + - Shengjiu Wang + - Frank Li + +description: + The Enhanced Serial Audio Interface (ESAI) provides a full-duplex serial port + for serial communication with a variety of serial devices, including industry + standard codecs, Sony/Phillips Digital Interface (S/PDIF) transceivers, and + other DSPs. It has up to six transmitters and four receivers. + +properties: + compatible: + enum: + - fsl,imx35-esai + - fsl,imx6ull-esai + - fsl,imx8qm-esai + - fsl,vf610-esai + + reg: + maxItems: 1 + + interrupts: + maxItems: 1 + + clocks: + minItems: 3 + items: + - description: + The core clock used to access registers. + - description: + The esai baud clock for esai controller used to + derive HCK, SCK and FS. + - description: + The system clock derived from ahb clock used to + derive HCK, SCK and FS. + - description: + The spba clock is required when ESAI is placed as a + bus slave of the Shared Peripheral Bus and when two + or more bus masters (CPU, DMA or DSP) try to access + it. This property is optional depending on the SoC + design. + + clock-names: + minItems: 3 + items: + - const: core + - const: extal + - const: fsys + - const: spba + + dmas: + minItems: 2 + maxItems: 2 + + dma-names: + items: + - const: rx + - const: tx + + fsl,fifo-depth: + $ref: /schemas/types.yaml#/definitions/uint32 + description: + The number of elements in the transmit and receive + FIFOs. This number is the maximum allowed value for + TFCR[TFWM] or RFCR[RFWM]. + + fsl,esai-synchronous: + $ref: /schemas/types.yaml#/definitions/flag + description: + This is a boolean property. If present, indicating + that ESAI would work in the synchronous mode, which + means all the settings for Receiving would be + duplicated from Transmission related registers. + + big-endian: + $ref: /schemas/types.yaml#/definitions/flag + description: + If this property is absent, the native endian mode + will be in use as default, or the big endian mode + will be in use for all the device registers. + +required: + - compatible + - reg + - interrupts + - clocks + - clock-names + - dmas + - dma-names + - fsl,fifo-depth + - fsl,esai-synchronous + +unevaluatedProperties: false + +examples: + - | + esai@2024000 { + compatible = "fsl,imx35-esai"; + reg = <0x02024000 0x4000>; + interrupts = <0 51 0x04>; + clocks = <&clks 208>, <&clks 118>, <&clks 208>; + clock-names = "core", "extal", "fsys"; + dmas = <&sdma 23 21 0>, <&sdma 24 21 0>; + dma-names = "rx", "tx"; + fsl,fifo-depth = <128>; + fsl,esai-synchronous; + big-endian; + }; -- cgit v1.2.3 From b340f56a74b62d8ce8617650c8ab4a26c87ba5c5 Mon Sep 17 00:00:00 2001 From: Kartik Agarwala Date: Mon, 25 Mar 2024 23:49:42 +0530 Subject: ASoC: dt-bindings: wm8974: Convert to dtschema Convert WM8974 audio CODEC bindings from text to dtschema. Signed-off-by: Kartik Agarwala Reviewed-by: Krzysztof Kozlowski Link: https://msgid.link/r/20240325181943.116733-1-agarwala.kartik@gmail.com Signed-off-by: Mark Brown --- .../devicetree/bindings/sound/wlf,wm8974.txt | 15 -------- .../devicetree/bindings/sound/wlf,wm8974.yaml | 41 ++++++++++++++++++++++ 2 files changed, 41 insertions(+), 15 deletions(-) delete mode 100644 Documentation/devicetree/bindings/sound/wlf,wm8974.txt create mode 100644 Documentation/devicetree/bindings/sound/wlf,wm8974.yaml diff --git a/Documentation/devicetree/bindings/sound/wlf,wm8974.txt b/Documentation/devicetree/bindings/sound/wlf,wm8974.txt deleted file mode 100644 index 01d3a7c83419..000000000000 --- a/Documentation/devicetree/bindings/sound/wlf,wm8974.txt +++ /dev/null @@ -1,15 +0,0 @@ -WM8974 audio CODEC - -This device supports both I2C and SPI (configured with pin strapping -on the board). - -Required properties: - - compatible: "wlf,wm8974" - - reg: the I2C address or SPI chip select number of the device - -Examples: - -codec: wm8974@1a { - compatible = "wlf,wm8974"; - reg = <0x1a>; -}; diff --git a/Documentation/devicetree/bindings/sound/wlf,wm8974.yaml b/Documentation/devicetree/bindings/sound/wlf,wm8974.yaml new file mode 100644 index 000000000000..d27300207c67 --- /dev/null +++ b/Documentation/devicetree/bindings/sound/wlf,wm8974.yaml @@ -0,0 +1,41 @@ +# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/sound/wlf,wm8974.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: WM8974 audio CODEC + +maintainers: + - patches@opensource.cirrus.com + +allOf: + - $ref: dai-common.yaml# + +properties: + compatible: + const: wlf,wm8974 + + reg: + maxItems: 1 + + "#sound-dai-cells": + const: 0 + +required: + - compatible + - reg + +unevaluatedProperties: false + +examples: + - | + i2c { + #address-cells = <1>; + #size-cells = <0>; + + codec@1a { + compatible = "wlf,wm8974"; + reg = <0x1a>; + }; + }; -- cgit v1.2.3 From b020aff0ec6ec089bd3e07bd6b58623826752ff7 Mon Sep 17 00:00:00 2001 From: Brent Lu Date: Mon, 25 Mar 2024 17:10:39 -0500 Subject: ASoC: Intel: board_helpers: support DAI link ID customization Add an new field link_id_overwrite to sof_card_private structure to support machine drivers which DAI link ID is fixed number or discontinue (i.e. no-codec boards). If this field is zero, DAI array index will be used as link ID. Otherwise the value extracted from link_id_overwrite will be used. The field link_id_overwrite is supposed to be initialized by SOF_LINK_IDS macro like following example. ctx->link_id_overwrite = SOF_LINK_IDS(HEADPHONE_BE_ID, \ DMIC01_BE_ID, \ DMIC16K_BE_ID, \ IDISP_HDMI_BE_ID, \ SPK_BE_ID, \ BT_OFFLOAD_BE_ID, \ HDMI_IN_BE_ID) An exception is that, if you use link_order_overwrite to overwrite DAI link order, then you need to use the same order to build link_id_overwrite variable as well. Reviewed-by: Bard Liao Signed-off-by: Brent Lu Signed-off-by: Pierre-Louis Bossart Link: https://msgid.link/r/20240325221059.206042-2-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/intel/boards/sof_board_helpers.c | 36 ++++++++++++++++++++++-------- sound/soc/intel/boards/sof_board_helpers.h | 18 +++++++++++++++ 2 files changed, 45 insertions(+), 9 deletions(-) diff --git a/sound/soc/intel/boards/sof_board_helpers.c b/sound/soc/intel/boards/sof_board_helpers.c index 088894ff4165..e853dc851c42 100644 --- a/sound/soc/intel/boards/sof_board_helpers.c +++ b/sound/soc/intel/boards/sof_board_helpers.c @@ -427,6 +427,7 @@ int sof_intel_board_set_dai_link(struct device *dev, struct snd_soc_card *card, int ret; int ssp_hdmi_in = 0; unsigned long link_order, link; + unsigned long link_ids, be_id; num_links = calculate_num_links(ctx); @@ -440,12 +441,26 @@ int sof_intel_board_set_dai_link(struct device *dev, struct snd_soc_card *card, else link_order = DEFAULT_LINK_ORDER; - dev_dbg(dev, "create dai links, link_order 0x%lx\n", link_order); + if (ctx->link_id_overwrite) + link_ids = ctx->link_id_overwrite; + else + link_ids = 0; + + dev_dbg(dev, "create dai links, link_order 0x%lx, id_overwrite 0x%lx\n", + link_order, link_ids); while (link_order) { link = link_order & SOF_LINK_ORDER_MASK; link_order >>= SOF_LINK_ORDER_SHIFT; + if (ctx->link_id_overwrite) { + be_id = link_ids & SOF_LINK_IDS_MASK; + link_ids >>= SOF_LINK_IDS_SHIFT; + } else { + /* use array index as link id */ + be_id = idx; + } + switch (link) { case SOF_LINK_CODEC: /* headphone codec */ @@ -453,7 +468,7 @@ int sof_intel_board_set_dai_link(struct device *dev, struct snd_soc_card *card, continue; ret = sof_intel_board_set_codec_link(dev, &links[idx], - idx, + be_id, ctx->codec_type, ctx->ssp_codec); if (ret) { @@ -472,7 +487,7 @@ int sof_intel_board_set_dai_link(struct device *dev, struct snd_soc_card *card, /* at least we have dmic01 */ ret = sof_intel_board_set_dmic_link(dev, &links[idx], - idx, SOF_DMIC_01); + be_id, SOF_DMIC_01); if (ret) { dev_err(dev, "fail to set dmic01 link, ret %d\n", ret); @@ -488,7 +503,7 @@ int sof_intel_board_set_dai_link(struct device *dev, struct snd_soc_card *card, /* set up 2 BE links at most */ ret = sof_intel_board_set_dmic_link(dev, &links[idx], - idx, SOF_DMIC_16K); + be_id, SOF_DMIC_16K); if (ret) { dev_err(dev, "fail to set dmic16k link, ret %d\n", ret); @@ -502,7 +517,8 @@ int sof_intel_board_set_dai_link(struct device *dev, struct snd_soc_card *card, for (i = 1; i <= ctx->hdmi_num; i++) { ret = sof_intel_board_set_intel_hdmi_link(dev, &links[idx], - idx, i, + be_id, + i, ctx->hdmi.idisp_codec); if (ret) { dev_err(dev, "fail to set hdmi link, ret %d\n", @@ -511,6 +527,7 @@ int sof_intel_board_set_dai_link(struct device *dev, struct snd_soc_card *card, } idx++; + be_id++; } break; case SOF_LINK_AMP: @@ -519,7 +536,7 @@ int sof_intel_board_set_dai_link(struct device *dev, struct snd_soc_card *card, continue; ret = sof_intel_board_set_ssp_amp_link(dev, &links[idx], - idx, + be_id, ctx->amp_type, ctx->ssp_amp); if (ret) { @@ -536,8 +553,8 @@ int sof_intel_board_set_dai_link(struct device *dev, struct snd_soc_card *card, if (!ctx->bt_offload_present) continue; - ret = sof_intel_board_set_bt_link(dev, &links[idx], idx, - ctx->ssp_bt); + ret = sof_intel_board_set_bt_link(dev, &links[idx], + be_id, ctx->ssp_bt); if (ret) { dev_err(dev, "fail to set bt link, ret %d\n", ret); @@ -551,7 +568,7 @@ int sof_intel_board_set_dai_link(struct device *dev, struct snd_soc_card *card, for_each_set_bit(ssp_hdmi_in, &ctx->ssp_mask_hdmi_in, 32) { ret = sof_intel_board_set_hdmi_in_link(dev, &links[idx], - idx, + be_id, ssp_hdmi_in); if (ret) { dev_err(dev, "fail to set hdmi-in link, ret %d\n", @@ -560,6 +577,7 @@ int sof_intel_board_set_dai_link(struct device *dev, struct snd_soc_card *card, } idx++; + be_id++; } break; case SOF_LINK_NONE: diff --git a/sound/soc/intel/boards/sof_board_helpers.h b/sound/soc/intel/boards/sof_board_helpers.h index f42d5d640321..162a5f4841da 100644 --- a/sound/soc/intel/boards/sof_board_helpers.h +++ b/sound/soc/intel/boards/sof_board_helpers.h @@ -33,6 +33,18 @@ enum { (((k6) & SOF_LINK_ORDER_MASK) << (SOF_LINK_ORDER_SHIFT * 5)) | \ (((k7) & SOF_LINK_ORDER_MASK) << (SOF_LINK_ORDER_SHIFT * 6))) +#define SOF_LINK_IDS_MASK (0xF) +#define SOF_LINK_IDS_SHIFT (4) + +#define SOF_LINK_IDS(k1, k2, k3, k4, k5, k6, k7) \ + ((((k1) & SOF_LINK_IDS_MASK) << (SOF_LINK_IDS_SHIFT * 0)) | \ + (((k2) & SOF_LINK_IDS_MASK) << (SOF_LINK_IDS_SHIFT * 1)) | \ + (((k3) & SOF_LINK_IDS_MASK) << (SOF_LINK_IDS_SHIFT * 2)) | \ + (((k4) & SOF_LINK_IDS_MASK) << (SOF_LINK_IDS_SHIFT * 3)) | \ + (((k5) & SOF_LINK_IDS_MASK) << (SOF_LINK_IDS_SHIFT * 4)) | \ + (((k6) & SOF_LINK_IDS_MASK) << (SOF_LINK_IDS_SHIFT * 5)) | \ + (((k7) & SOF_LINK_IDS_MASK) << (SOF_LINK_IDS_SHIFT * 6))) + /* * sof_rt5682_private: private data for rt5682 machine driver * @@ -61,6 +73,7 @@ struct sof_rt5682_private { * @codec_link: pointer to headset codec dai link * @amp_link: pointer to speaker amplifier dai link * @link_order_overwrite: custom DAI link order + * @link_id_overwrite: custom DAI link ID * @rt5682: private data for rt5682 machine driver */ struct sof_card_private { @@ -84,6 +97,11 @@ struct sof_card_private { struct snd_soc_dai_link *amp_link; unsigned long link_order_overwrite; + /* + * A variable stores id for all BE DAI links, use SOF_LINK_IDS macro to + * build the value; use DAI link array index as id if zero. + */ + unsigned long link_id_overwrite; union { struct sof_rt5682_private rt5682; -- cgit v1.2.3 From 8906d8663d72642b05108963a47a069b7a04b23f Mon Sep 17 00:00:00 2001 From: Brent Lu Date: Mon, 25 Mar 2024 17:10:40 -0500 Subject: ASoC: Intel: sof_ssp_amp: use common module for DAI link generation Use intel_board module to generate DAI link array and update num_links field in snd_soc_card structure. Reviewed-by: Bard Liao Signed-off-by: Brent Lu Signed-off-by: Pierre-Louis Bossart Link: https://msgid.link/r/20240325221059.206042-3-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/intel/boards/sof_ssp_amp.c | 180 +++++++++++------------------------ 1 file changed, 54 insertions(+), 126 deletions(-) diff --git a/sound/soc/intel/boards/sof_ssp_amp.c b/sound/soc/intel/boards/sof_ssp_amp.c index ee2e813bf4c0..0b8adab76755 100644 --- a/sound/soc/intel/boards/sof_ssp_amp.c +++ b/sound/soc/intel/boards/sof_ssp_amp.c @@ -75,126 +75,64 @@ static struct snd_soc_card sof_ssp_amp_card = { #define HDMI_IN_BE_ID 0 #define SPK_BE_ID 2 #define DMIC01_BE_ID 3 -#define DMIC16K_BE_ID 4 #define INTEL_HDMI_BE_ID 5 - -static struct snd_soc_dai_link * -sof_card_dai_links_create(struct device *dev, enum sof_ssp_codec amp_type, - int ssp_amp, int dmic_be_num, int hdmi_num, - bool idisp_codec) +/* extra BE links to support no-hdmi-in boards */ +#define DMIC16K_BE_ID 4 +#define BT_OFFLOAD_BE_ID 8 + +#define SSP_AMP_LINK_ORDER SOF_LINK_ORDER(SOF_LINK_HDMI_IN, \ + SOF_LINK_AMP, \ + SOF_LINK_DMIC01, \ + SOF_LINK_DMIC16K, \ + SOF_LINK_IDISP_HDMI, \ + SOF_LINK_BT_OFFLOAD, \ + SOF_LINK_NONE) + +#define SSP_AMP_LINK_IDS SOF_LINK_ORDER(HDMI_IN_BE_ID, \ + SPK_BE_ID, \ + DMIC01_BE_ID, \ + DMIC16K_BE_ID, \ + INTEL_HDMI_BE_ID, \ + BT_OFFLOAD_BE_ID, \ + 0) + +static int +sof_card_dai_links_create(struct device *dev, struct snd_soc_card *card, + struct sof_card_private *ctx) { - struct snd_soc_dai_link *links; - int i; - int id = 0; int ret; - bool fixed_be = false; - int be_id; - unsigned long ssp_mask_hdmi_in; - - links = devm_kcalloc(dev, sof_ssp_amp_card.num_links, - sizeof(struct snd_soc_dai_link), GFP_KERNEL); - if (!links) - return NULL; - - /* HDMI-In SSP */ - ssp_mask_hdmi_in = (sof_ssp_amp_quirk & SOF_HDMI_CAPTURE_SSP_MASK_MASK) >> - SOF_HDMI_CAPTURE_SSP_MASK_SHIFT; - - if (ssp_mask_hdmi_in) { - int port = 0; - - /* the topology supports HDMI-IN uses fixed BE ID for DAI links */ - fixed_be = true; - - be_id = HDMI_IN_BE_ID; - for_each_set_bit(port, &ssp_mask_hdmi_in, 32) { - ret = sof_intel_board_set_hdmi_in_link(dev, &links[id], - be_id, port); - if (ret) - return NULL; - - id++; - be_id++; - } - } - - /* codec SSP */ - if (amp_type != CODEC_NONE) { - be_id = fixed_be ? SPK_BE_ID : id; - ret = sof_intel_board_set_ssp_amp_link(dev, &links[id], be_id, - amp_type, ssp_amp); - if (ret) - return NULL; - - /* codec-specific fields */ - switch (amp_type) { - case CODEC_CS35L41: - cs35l41_set_dai_link(&links[id]); - break; - case CODEC_RT1308: - sof_rt1308_dai_link(&links[id]); - break; - default: - dev_err(dev, "invalid amp type %d\n", amp_type); - return NULL; - } - - id++; - } - - /* dmic */ - if (dmic_be_num > 0) { - /* at least we have dmic01 */ - be_id = fixed_be ? DMIC01_BE_ID : id; - ret = sof_intel_board_set_dmic_link(dev, &links[id], be_id, - SOF_DMIC_01); - if (ret) - return NULL; - id++; - } - - if (dmic_be_num > 1) { - /* set up 2 BE links at most */ - be_id = fixed_be ? DMIC16K_BE_ID : id; - ret = sof_intel_board_set_dmic_link(dev, &links[id], be_id, - SOF_DMIC_16K); - if (ret) - return NULL; - - id++; - } + ret = sof_intel_board_set_dai_link(dev, card, ctx); + if (ret) + return ret; - /* HDMI playback */ - for (i = 1; i <= hdmi_num; i++) { - be_id = fixed_be ? (INTEL_HDMI_BE_ID + i - 1) : id; - ret = sof_intel_board_set_intel_hdmi_link(dev, &links[id], be_id, - i, idisp_codec); - if (ret) - return NULL; + if (ctx->amp_type == CODEC_NONE) + return 0; - id++; + if (!ctx->amp_link) { + dev_err(dev, "amp link not available"); + return -EINVAL; } - /* BT audio offload */ - if (sof_ssp_amp_quirk & SOF_SSP_BT_OFFLOAD_PRESENT) { - int port = (sof_ssp_amp_quirk & SOF_BT_OFFLOAD_SSP_MASK) >> - SOF_BT_OFFLOAD_SSP_SHIFT; - - ret = sof_intel_board_set_bt_link(dev, &links[id], id, port); - if (ret) - return NULL; - - id++; + /* codec-specific fields for speaker amplifier */ + switch (ctx->amp_type) { + case CODEC_CS35L41: + cs35l41_set_dai_link(ctx->amp_link); + break; + case CODEC_RT1308: + sof_rt1308_dai_link(ctx->amp_link); + break; + default: + dev_err(dev, "invalid amp type %d\n", ctx->amp_type); + return -EINVAL; } - return links; + return 0; } static int sof_ssp_amp_probe(struct platform_device *pdev) { struct snd_soc_acpi_mach *mach = pdev->dev.platform_data; - struct snd_soc_dai_link *dai_links; struct sof_card_private *ctx; int ret; @@ -221,15 +159,6 @@ static int sof_ssp_amp_probe(struct platform_device *pdev) ctx->ssp_amp = sof_ssp_amp_quirk & SOF_AMPLIFIER_SSP_MASK; - /* set number of dai links */ - sof_ssp_amp_card.num_links = ctx->dmic_be_num; - - if (ctx->amp_type != CODEC_NONE) - sof_ssp_amp_card.num_links++; - - if (ctx->ssp_mask_hdmi_in) - sof_ssp_amp_card.num_links += hweight32(ctx->ssp_mask_hdmi_in); - if (sof_ssp_amp_quirk & SOF_HDMI_PLAYBACK_PRESENT) { ctx->hdmi_num = (sof_ssp_amp_quirk & SOF_NO_OF_HDMI_PLAYBACK_MASK) >> SOF_NO_OF_HDMI_PLAYBACK_SHIFT; @@ -239,25 +168,24 @@ static int sof_ssp_amp_probe(struct platform_device *pdev) if (mach->mach_params.codec_mask & IDISP_CODEC_MASK) ctx->hdmi.idisp_codec = true; - - sof_ssp_amp_card.num_links += ctx->hdmi_num; } else { ctx->hdmi_num = 0; } - if (sof_ssp_amp_quirk & SOF_SSP_BT_OFFLOAD_PRESENT) { + if (sof_ssp_amp_quirk & SOF_SSP_BT_OFFLOAD_PRESENT) ctx->bt_offload_present = true; - sof_ssp_amp_card.num_links++; - } - dai_links = sof_card_dai_links_create(&pdev->dev, ctx->amp_type, - ctx->ssp_amp, ctx->dmic_be_num, - ctx->hdmi_num, - ctx->hdmi.idisp_codec); - if (!dai_links) - return -ENOMEM; + ctx->link_order_overwrite = SSP_AMP_LINK_ORDER; - sof_ssp_amp_card.dai_link = dai_links; + if (ctx->ssp_mask_hdmi_in) { + /* the topology supports HDMI-IN uses fixed BE ID for DAI links */ + ctx->link_id_overwrite = SSP_AMP_LINK_IDS; + } + + /* update dai_link */ + ret = sof_card_dai_links_create(&pdev->dev, &sof_ssp_amp_card, ctx); + if (ret) + return ret; /* update codec_conf */ switch (ctx->amp_type) { -- cgit v1.2.3 From 3b6378bb8baf519e641151dcdb9171c2bdecb7b7 Mon Sep 17 00:00:00 2001 From: Brent Lu Date: Mon, 25 Mar 2024 17:10:41 -0500 Subject: ASoC: Intel: board_helpers: change dai link helpers to static function Since there is a helper function to generate entire DAI link array, we switch individual dai link helpers to static function. No functional change in this commit. Reviewed-by: Bard Liao Signed-off-by: Brent Lu Signed-off-by: Pierre-Louis Bossart Link: https://msgid.link/r/20240325221059.206042-4-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/intel/boards/sof_board_helpers.c | 85 ++++++++++++------------------ sound/soc/intel/boards/sof_board_helpers.h | 24 --------- 2 files changed, 35 insertions(+), 74 deletions(-) diff --git a/sound/soc/intel/boards/sof_board_helpers.c b/sound/soc/intel/boards/sof_board_helpers.c index e853dc851c42..feba1a522527 100644 --- a/sound/soc/intel/boards/sof_board_helpers.c +++ b/sound/soc/intel/boards/sof_board_helpers.c @@ -74,6 +74,11 @@ static int dmic_init(struct snd_soc_pcm_runtime *rtd) * DAI Link Helpers */ +enum sof_dmic_be_type { + SOF_DMIC_01, + SOF_DMIC_16K, +}; + /* DEFAULT_LINK_ORDER: the order used in sof_rt5682 */ #define DEFAULT_LINK_ORDER SOF_LINK_ORDER(SOF_LINK_CODEC, \ SOF_LINK_DMIC01, \ @@ -97,13 +102,13 @@ static struct snd_soc_dai_link_component platform_component[] = { } }; -int sof_intel_board_set_codec_link(struct device *dev, - struct snd_soc_dai_link *link, int be_id, - enum sof_ssp_codec codec_type, int ssp_codec) +static int set_ssp_codec_link(struct device *dev, struct snd_soc_dai_link *link, + int be_id, enum sof_ssp_codec codec_type, + int ssp_codec) { struct snd_soc_dai_link_component *cpus; - dev_dbg(dev, "link %d: codec %s, ssp %d\n", be_id, + dev_dbg(dev, "link %d: ssp codec %s, ssp %d\n", be_id, sof_ssp_get_codec_name(codec_type), ssp_codec); /* link name */ @@ -144,11 +149,9 @@ int sof_intel_board_set_codec_link(struct device *dev, return 0; } -EXPORT_SYMBOL_NS(sof_intel_board_set_codec_link, SND_SOC_INTEL_SOF_BOARD_HELPERS); -int sof_intel_board_set_dmic_link(struct device *dev, - struct snd_soc_dai_link *link, int be_id, - enum sof_dmic_be_type be_type) +static int set_dmic_link(struct device *dev, struct snd_soc_dai_link *link, + int be_id, enum sof_dmic_be_type be_type) { struct snd_soc_dai_link_component *cpus; @@ -196,16 +199,14 @@ int sof_intel_board_set_dmic_link(struct device *dev, return 0; } -EXPORT_SYMBOL_NS(sof_intel_board_set_dmic_link, SND_SOC_INTEL_SOF_BOARD_HELPERS); -int sof_intel_board_set_intel_hdmi_link(struct device *dev, - struct snd_soc_dai_link *link, int be_id, - int hdmi_id, bool idisp_codec) +static int set_idisp_hdmi_link(struct device *dev, struct snd_soc_dai_link *link, + int be_id, int hdmi_id, bool idisp_codec) { struct snd_soc_dai_link_component *cpus, *codecs; - dev_dbg(dev, "link %d: intel hdmi, hdmi id %d, idisp codec %d\n", - be_id, hdmi_id, idisp_codec); + dev_dbg(dev, "link %d: idisp hdmi %d, idisp codec %d\n", be_id, hdmi_id, + idisp_codec); /* link name */ link->name = devm_kasprintf(dev, GFP_KERNEL, "iDisp%d", hdmi_id); @@ -256,11 +257,9 @@ int sof_intel_board_set_intel_hdmi_link(struct device *dev, return 0; } -EXPORT_SYMBOL_NS(sof_intel_board_set_intel_hdmi_link, SND_SOC_INTEL_SOF_BOARD_HELPERS); -int sof_intel_board_set_ssp_amp_link(struct device *dev, - struct snd_soc_dai_link *link, int be_id, - enum sof_ssp_codec amp_type, int ssp_amp) +static int set_ssp_amp_link(struct device *dev, struct snd_soc_dai_link *link, + int be_id, enum sof_ssp_codec amp_type, int ssp_amp) { struct snd_soc_dai_link_component *cpus; @@ -298,11 +297,9 @@ int sof_intel_board_set_ssp_amp_link(struct device *dev, return 0; } -EXPORT_SYMBOL_NS(sof_intel_board_set_ssp_amp_link, SND_SOC_INTEL_SOF_BOARD_HELPERS); -int sof_intel_board_set_bt_link(struct device *dev, - struct snd_soc_dai_link *link, int be_id, - int ssp_bt) +static int set_bt_offload_link(struct device *dev, struct snd_soc_dai_link *link, + int be_id, int ssp_bt) { struct snd_soc_dai_link_component *cpus; @@ -341,11 +338,9 @@ int sof_intel_board_set_bt_link(struct device *dev, return 0; } -EXPORT_SYMBOL_NS(sof_intel_board_set_bt_link, SND_SOC_INTEL_SOF_BOARD_HELPERS); -int sof_intel_board_set_hdmi_in_link(struct device *dev, - struct snd_soc_dai_link *link, int be_id, - int ssp_hdmi) +static int set_hdmi_in_link(struct device *dev, struct snd_soc_dai_link *link, + int be_id, int ssp_hdmi) { struct snd_soc_dai_link_component *cpus; @@ -383,7 +378,6 @@ int sof_intel_board_set_hdmi_in_link(struct device *dev, return 0; } -EXPORT_SYMBOL_NS(sof_intel_board_set_hdmi_in_link, SND_SOC_INTEL_SOF_BOARD_HELPERS); static int calculate_num_links(struct sof_card_private *ctx) { @@ -467,10 +461,8 @@ int sof_intel_board_set_dai_link(struct device *dev, struct snd_soc_card *card, if (ctx->codec_type == CODEC_NONE) continue; - ret = sof_intel_board_set_codec_link(dev, &links[idx], - be_id, - ctx->codec_type, - ctx->ssp_codec); + ret = set_ssp_codec_link(dev, &links[idx], be_id, + ctx->codec_type, ctx->ssp_codec); if (ret) { dev_err(dev, "fail to set codec link, ret %d\n", ret); @@ -486,8 +478,7 @@ int sof_intel_board_set_dai_link(struct device *dev, struct snd_soc_card *card, continue; /* at least we have dmic01 */ - ret = sof_intel_board_set_dmic_link(dev, &links[idx], - be_id, SOF_DMIC_01); + ret = set_dmic_link(dev, &links[idx], be_id, SOF_DMIC_01); if (ret) { dev_err(dev, "fail to set dmic01 link, ret %d\n", ret); @@ -502,8 +493,8 @@ int sof_intel_board_set_dai_link(struct device *dev, struct snd_soc_card *card, continue; /* set up 2 BE links at most */ - ret = sof_intel_board_set_dmic_link(dev, &links[idx], - be_id, SOF_DMIC_16K); + ret = set_dmic_link(dev, &links[idx], be_id, + SOF_DMIC_16K); if (ret) { dev_err(dev, "fail to set dmic16k link, ret %d\n", ret); @@ -515,11 +506,9 @@ int sof_intel_board_set_dai_link(struct device *dev, struct snd_soc_card *card, case SOF_LINK_IDISP_HDMI: /* idisp HDMI */ for (i = 1; i <= ctx->hdmi_num; i++) { - ret = sof_intel_board_set_intel_hdmi_link(dev, - &links[idx], - be_id, - i, - ctx->hdmi.idisp_codec); + ret = set_idisp_hdmi_link(dev, &links[idx], + be_id, i, + ctx->hdmi.idisp_codec); if (ret) { dev_err(dev, "fail to set hdmi link, ret %d\n", ret); @@ -535,10 +524,8 @@ int sof_intel_board_set_dai_link(struct device *dev, struct snd_soc_card *card, if (ctx->amp_type == CODEC_NONE) continue; - ret = sof_intel_board_set_ssp_amp_link(dev, &links[idx], - be_id, - ctx->amp_type, - ctx->ssp_amp); + ret = set_ssp_amp_link(dev, &links[idx], be_id, + ctx->amp_type, ctx->ssp_amp); if (ret) { dev_err(dev, "fail to set amp link, ret %d\n", ret); @@ -553,8 +540,8 @@ int sof_intel_board_set_dai_link(struct device *dev, struct snd_soc_card *card, if (!ctx->bt_offload_present) continue; - ret = sof_intel_board_set_bt_link(dev, &links[idx], - be_id, ctx->ssp_bt); + ret = set_bt_offload_link(dev, &links[idx], be_id, + ctx->ssp_bt); if (ret) { dev_err(dev, "fail to set bt link, ret %d\n", ret); @@ -566,10 +553,8 @@ int sof_intel_board_set_dai_link(struct device *dev, struct snd_soc_card *card, case SOF_LINK_HDMI_IN: /* HDMI-In */ for_each_set_bit(ssp_hdmi_in, &ctx->ssp_mask_hdmi_in, 32) { - ret = sof_intel_board_set_hdmi_in_link(dev, - &links[idx], - be_id, - ssp_hdmi_in); + ret = set_hdmi_in_link(dev, &links[idx], be_id, + ssp_hdmi_in); if (ret) { dev_err(dev, "fail to set hdmi-in link, ret %d\n", ret); diff --git a/sound/soc/intel/boards/sof_board_helpers.h b/sound/soc/intel/boards/sof_board_helpers.h index 162a5f4841da..38e459e6af9b 100644 --- a/sound/soc/intel/boards/sof_board_helpers.h +++ b/sound/soc/intel/boards/sof_board_helpers.h @@ -108,34 +108,10 @@ struct sof_card_private { }; }; -enum sof_dmic_be_type { - SOF_DMIC_01, - SOF_DMIC_16K, -}; - int sof_intel_board_card_late_probe(struct snd_soc_card *card); int sof_intel_board_set_dai_link(struct device *dev, struct snd_soc_card *card, struct sof_card_private *ctx); -int sof_intel_board_set_codec_link(struct device *dev, - struct snd_soc_dai_link *link, int be_id, - enum sof_ssp_codec codec_type, int ssp_codec); -int sof_intel_board_set_dmic_link(struct device *dev, - struct snd_soc_dai_link *link, int be_id, - enum sof_dmic_be_type be_type); -int sof_intel_board_set_intel_hdmi_link(struct device *dev, - struct snd_soc_dai_link *link, int be_id, - int hdmi_id, bool idisp_codec); -int sof_intel_board_set_ssp_amp_link(struct device *dev, - struct snd_soc_dai_link *link, int be_id, - enum sof_ssp_codec amp_type, int ssp_amp); -int sof_intel_board_set_bt_link(struct device *dev, - struct snd_soc_dai_link *link, int be_id, - int ssp_bt); -int sof_intel_board_set_hdmi_in_link(struct device *dev, - struct snd_soc_dai_link *link, int be_id, - int ssp_hdmi); - struct snd_soc_dai *get_codec_dai_by_name(struct snd_soc_pcm_runtime *rtd, const char * const dai_name[], int num_dais); -- cgit v1.2.3 From 54bac56954a7c36eb8d1c7047b63133635999eb8 Mon Sep 17 00:00:00 2001 From: Brent Lu Date: Mon, 25 Mar 2024 17:10:42 -0500 Subject: ASoC: Intel: sof_da7219: add rpl_mx98360_da7219 board config This configuration supports RPL boards which implement DA7219 on SSP0 and MAX98360A on SSP1. DA7219 uses PLL bypass mode to avoid WCLK locking problem. To use this mode, the MCLK frequency must be 12.288 or 24.576MHz in the topology binary. Reviewed-by: Bard Liao Signed-off-by: Brent Lu Signed-off-by: Pierre-Louis Bossart Link: https://msgid.link/r/20240325221059.206042-5-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/intel/boards/sof_da7219.c | 4 ++++ sound/soc/intel/common/soc-acpi-intel-rpl-match.c | 7 +++++++ 2 files changed, 11 insertions(+) diff --git a/sound/soc/intel/boards/sof_da7219.c b/sound/soc/intel/boards/sof_da7219.c index 6eb5a6144e97..290bf75bdaef 100644 --- a/sound/soc/intel/boards/sof_da7219.c +++ b/sound/soc/intel/boards/sof_da7219.c @@ -545,6 +545,10 @@ static const struct platform_device_id board_ids[] = { .name = "adl_mx98360_da7219", /* no quirk needed for this board */ }, + { + .name = "rpl_mx98360_da7219", + /* no quirk needed for this board */ + }, { } }; MODULE_DEVICE_TABLE(platform, board_ids); diff --git a/sound/soc/intel/common/soc-acpi-intel-rpl-match.c b/sound/soc/intel/common/soc-acpi-intel-rpl-match.c index 00a21af210fa..f797937cf9d8 100644 --- a/sound/soc/intel/common/soc-acpi-intel-rpl-match.c +++ b/sound/soc/intel/common/soc-acpi-intel-rpl-match.c @@ -455,6 +455,13 @@ struct snd_soc_acpi_mach snd_soc_acpi_intel_rpl_machines[] = { .drv_name = "rpl_lt6911_hdmi_ssp", .sof_tplg_filename = "sof-rpl-nocodec-hdmi-ssp02.tplg" }, + { + .id = "DLGS7219", + .drv_name = "rpl_mx98360_da7219", + .machine_quirk = snd_soc_acpi_codec_list, + .quirk_data = &rpl_max98360a_amp, + .sof_tplg_filename = "sof-rpl-max98360a-da7219.tplg", + }, {}, }; EXPORT_SYMBOL_GPL(snd_soc_acpi_intel_rpl_machines); -- cgit v1.2.3 From 94e9dd5b38bc3d04f86c4a876f3b4b397add248b Mon Sep 17 00:00:00 2001 From: Brent Lu Date: Mon, 25 Mar 2024 17:10:43 -0500 Subject: ASoC: Intel: sof_rt5682: support ALC5650 on RPL boards This commit supports RPL boards which implement ALC5650 dual I2S interface codec. SSP port usage: HP: SSP0 -> AIF1 SPK: SSP1 -> AIF2 BT: SSP2 -> BT Reviewed-by: Bard Liao Signed-off-by: Brent Lu Signed-off-by: Pierre-Louis Bossart Link: https://msgid.link/r/20240325221059.206042-6-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/intel/common/soc-acpi-intel-rpl-match.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/sound/soc/intel/common/soc-acpi-intel-rpl-match.c b/sound/soc/intel/common/soc-acpi-intel-rpl-match.c index f797937cf9d8..c43e537e60d2 100644 --- a/sound/soc/intel/common/soc-acpi-intel-rpl-match.c +++ b/sound/soc/intel/common/soc-acpi-intel-rpl-match.c @@ -462,6 +462,11 @@ struct snd_soc_acpi_mach snd_soc_acpi_intel_rpl_machines[] = { .quirk_data = &rpl_max98360a_amp, .sof_tplg_filename = "sof-rpl-max98360a-da7219.tplg", }, + { + .id = "10EC5650", + .drv_name = "rpl_rt5682_def", + .sof_tplg_filename = "sof-rpl-rt5650.tplg", + }, {}, }; EXPORT_SYMBOL_GPL(snd_soc_acpi_intel_rpl_machines); -- cgit v1.2.3 From 109896246a5311aa05692ecf38c0d71e1837fe23 Mon Sep 17 00:00:00 2001 From: Brent Lu Date: Mon, 25 Mar 2024 17:10:44 -0500 Subject: ASoC: Intel: sof_cs42l42: rename BT offload quirk Rename the quirk in preparation for future changes: common quriks will be defined and handled in board helper module. Reviewed-by: Bard Liao Signed-off-by: Brent Lu Signed-off-by: Pierre-Louis Bossart Link: https://msgid.link/r/20240325221059.206042-7-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/intel/boards/sof_cs42l42.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/sound/soc/intel/boards/sof_cs42l42.c b/sound/soc/intel/boards/sof_cs42l42.c index 323b86c42ef9..330d596b2eb6 100644 --- a/sound/soc/intel/boards/sof_cs42l42.c +++ b/sound/soc/intel/boards/sof_cs42l42.c @@ -34,7 +34,7 @@ #define SOF_CS42L42_NUM_HDMIDEV_MASK (GENMASK(9, 7)) #define SOF_CS42L42_NUM_HDMIDEV(quirk) \ (((quirk) << SOF_CS42L42_NUM_HDMIDEV_SHIFT) & SOF_CS42L42_NUM_HDMIDEV_MASK) -#define SOF_BT_OFFLOAD_PRESENT BIT(25) +#define SOF_CS42L42_BT_OFFLOAD_PRESENT BIT(25) #define SOF_CS42L42_SSP_BT_SHIFT 26 #define SOF_CS42L42_SSP_BT_MASK (GENMASK(28, 26)) #define SOF_CS42L42_SSP_BT(quirk) \ @@ -268,7 +268,7 @@ static int sof_audio_probe(struct platform_device *pdev) ctx->ssp_codec = sof_cs42l42_quirk & SOF_CS42L42_SSP_CODEC_MASK; - if (sof_cs42l42_quirk & SOF_BT_OFFLOAD_PRESENT) + if (sof_cs42l42_quirk & SOF_CS42L42_BT_OFFLOAD_PRESENT) ctx->bt_offload_present = true; /* update dai_link */ @@ -306,7 +306,7 @@ static const struct platform_device_id board_ids[] = { .driver_data = (kernel_ulong_t)(SOF_CS42L42_SSP_CODEC(0) | SOF_CS42L42_SSP_AMP(1) | SOF_CS42L42_NUM_HDMIDEV(4) | - SOF_BT_OFFLOAD_PRESENT | + SOF_CS42L42_BT_OFFLOAD_PRESENT | SOF_CS42L42_SSP_BT(2)), }, { } -- cgit v1.2.3 From cf22d15ecf61c783e6903f3409e78d439f9c9b4a Mon Sep 17 00:00:00 2001 From: Brent Lu Date: Mon, 25 Mar 2024 17:10:45 -0500 Subject: ASoC: Intel: board_helpers: support sof_card_private initialization Add a helper function for machine drivers to initialize common part of sof_card_private structure. Also unify the macros of board quirks for the initialization. Reviewed-by: Bard Liao Signed-off-by: Brent Lu Signed-off-by: Pierre-Louis Bossart Link: https://msgid.link/r/20240325221059.206042-8-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/intel/boards/sof_board_helpers.c | 43 ++++++++++++++++++++++++++++++ sound/soc/intel/boards/sof_board_helpers.h | 40 +++++++++++++++++++++++++++ 2 files changed, 83 insertions(+) diff --git a/sound/soc/intel/boards/sof_board_helpers.c b/sound/soc/intel/boards/sof_board_helpers.c index feba1a522527..a5135be94f32 100644 --- a/sound/soc/intel/boards/sof_board_helpers.c +++ b/sound/soc/intel/boards/sof_board_helpers.c @@ -587,6 +587,49 @@ int sof_intel_board_set_dai_link(struct device *dev, struct snd_soc_card *card, } EXPORT_SYMBOL_NS(sof_intel_board_set_dai_link, SND_SOC_INTEL_SOF_BOARD_HELPERS); +struct sof_card_private * +sof_intel_board_get_ctx(struct device *dev, unsigned long board_quirk) +{ + struct sof_card_private *ctx; + + dev_dbg(dev, "create ctx, board_quirk 0x%lx\n", board_quirk); + + ctx = devm_kzalloc(dev, sizeof(struct sof_card_private), GFP_KERNEL); + if (!ctx) + return NULL; + + ctx->codec_type = sof_ssp_detect_codec_type(dev); + ctx->amp_type = sof_ssp_detect_amp_type(dev); + + ctx->dmic_be_num = 2; + ctx->hdmi_num = (board_quirk & SOF_NUM_IDISP_HDMI_MASK) >> + SOF_NUM_IDISP_HDMI_SHIFT; + /* default number of HDMI DAI's */ + if (!ctx->hdmi_num) + ctx->hdmi_num = 3; + + /* port number/mask of peripherals attached to ssp interface */ + if (ctx->codec_type != CODEC_NONE) + ctx->ssp_codec = (board_quirk & SOF_SSP_PORT_CODEC_MASK) >> + SOF_SSP_PORT_CODEC_SHIFT; + + if (ctx->amp_type != CODEC_NONE) + ctx->ssp_amp = (board_quirk & SOF_SSP_PORT_AMP_MASK) >> + SOF_SSP_PORT_AMP_SHIFT; + + if (board_quirk & SOF_BT_OFFLOAD_PRESENT) { + ctx->bt_offload_present = true; + ctx->ssp_bt = (board_quirk & SOF_SSP_PORT_BT_OFFLOAD_MASK) >> + SOF_SSP_PORT_BT_OFFLOAD_SHIFT; + } + + ctx->ssp_mask_hdmi_in = (board_quirk & SOF_SSP_MASK_HDMI_CAPTURE_MASK) >> + SOF_SSP_MASK_HDMI_CAPTURE_SHIFT; + + return ctx; +} +EXPORT_SYMBOL_NS(sof_intel_board_get_ctx, SND_SOC_INTEL_SOF_BOARD_HELPERS); + struct snd_soc_dai *get_codec_dai_by_name(struct snd_soc_pcm_runtime *rtd, const char * const dai_name[], int num_dais) { diff --git a/sound/soc/intel/boards/sof_board_helpers.h b/sound/soc/intel/boards/sof_board_helpers.h index 38e459e6af9b..0d0a8d97843b 100644 --- a/sound/soc/intel/boards/sof_board_helpers.h +++ b/sound/soc/intel/boards/sof_board_helpers.h @@ -10,6 +10,44 @@ #include "sof_hdmi_common.h" #include "sof_ssp_common.h" +/* + * Common board quirks: from bit 8 to 31, LSB 8 bits reserved for machine + * drivers + */ + +/* SSP port number for headphone codec: 3 bits */ +#define SOF_SSP_PORT_CODEC_SHIFT 8 +#define SOF_SSP_PORT_CODEC_MASK (GENMASK(10, 8)) +#define SOF_SSP_PORT_CODEC(quirk) \ + (((quirk) << SOF_SSP_PORT_CODEC_SHIFT) & SOF_SSP_PORT_CODEC_MASK) + +/* SSP port number for speaker amplifier: 3 bits */ +#define SOF_SSP_PORT_AMP_SHIFT 11 +#define SOF_SSP_PORT_AMP_MASK (GENMASK(13, 11)) +#define SOF_SSP_PORT_AMP(quirk) \ + (((quirk) << SOF_SSP_PORT_AMP_SHIFT) & SOF_SSP_PORT_AMP_MASK) + +/* SSP port number for BT audio offload: 3 bits */ +#define SOF_SSP_PORT_BT_OFFLOAD_SHIFT 14 +#define SOF_SSP_PORT_BT_OFFLOAD_MASK (GENMASK(16, 14)) +#define SOF_SSP_PORT_BT_OFFLOAD(quirk) \ + (((quirk) << SOF_SSP_PORT_BT_OFFLOAD_SHIFT) & SOF_SSP_PORT_BT_OFFLOAD_MASK) + +/* SSP port mask for HDMI capture: 6 bits */ +#define SOF_SSP_MASK_HDMI_CAPTURE_SHIFT 17 +#define SOF_SSP_MASK_HDMI_CAPTURE_MASK (GENMASK(22, 17)) +#define SOF_SSP_MASK_HDMI_CAPTURE(quirk) \ + (((quirk) << SOF_SSP_MASK_HDMI_CAPTURE_SHIFT) & SOF_SSP_MASK_HDMI_CAPTURE_MASK) + +/* Number of idisp HDMI BE link: 3 bits */ +#define SOF_NUM_IDISP_HDMI_SHIFT 23 +#define SOF_NUM_IDISP_HDMI_MASK (GENMASK(25, 23)) +#define SOF_NUM_IDISP_HDMI(quirk) \ + (((quirk) << SOF_NUM_IDISP_HDMI_SHIFT) & SOF_NUM_IDISP_HDMI_MASK) + +/* Board uses BT audio offload */ +#define SOF_BT_OFFLOAD_PRESENT BIT(26) + enum { SOF_LINK_NONE = 0, SOF_LINK_CODEC, @@ -111,6 +149,8 @@ struct sof_card_private { int sof_intel_board_card_late_probe(struct snd_soc_card *card); int sof_intel_board_set_dai_link(struct device *dev, struct snd_soc_card *card, struct sof_card_private *ctx); +struct sof_card_private * +sof_intel_board_get_ctx(struct device *dev, unsigned long board_quirk); struct snd_soc_dai *get_codec_dai_by_name(struct snd_soc_pcm_runtime *rtd, const char * const dai_name[], int num_dais); -- cgit v1.2.3 From 96258c3348e1a2cb6842175a0ac895ef3963f2e2 Mon Sep 17 00:00:00 2001 From: Brent Lu Date: Mon, 25 Mar 2024 17:10:46 -0500 Subject: ASoC: Intel: sof_cs42l42: use common module for sof_card_private initialization Use intel_board module to initialize sof_card_private structure. Reviewed-by: Bard Liao Signed-off-by: Brent Lu Signed-off-by: Pierre-Louis Bossart Link: https://msgid.link/r/20240325221059.206042-9-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/intel/boards/sof_cs42l42.c | 72 ++++++++---------------------------- 1 file changed, 16 insertions(+), 56 deletions(-) diff --git a/sound/soc/intel/boards/sof_cs42l42.c b/sound/soc/intel/boards/sof_cs42l42.c index 330d596b2eb6..40ecfeaa1d26 100644 --- a/sound/soc/intel/boards/sof_cs42l42.c +++ b/sound/soc/intel/boards/sof_cs42l42.c @@ -22,23 +22,6 @@ #include "../common/soc-intel-quirks.h" #include "sof_board_helpers.h" #include "sof_maxim_common.h" -#include "sof_ssp_common.h" - -#define SOF_CS42L42_SSP_CODEC(quirk) ((quirk) & GENMASK(2, 0)) -#define SOF_CS42L42_SSP_CODEC_MASK (GENMASK(2, 0)) -#define SOF_CS42L42_SSP_AMP_SHIFT 4 -#define SOF_CS42L42_SSP_AMP_MASK (GENMASK(6, 4)) -#define SOF_CS42L42_SSP_AMP(quirk) \ - (((quirk) << SOF_CS42L42_SSP_AMP_SHIFT) & SOF_CS42L42_SSP_AMP_MASK) -#define SOF_CS42L42_NUM_HDMIDEV_SHIFT 7 -#define SOF_CS42L42_NUM_HDMIDEV_MASK (GENMASK(9, 7)) -#define SOF_CS42L42_NUM_HDMIDEV(quirk) \ - (((quirk) << SOF_CS42L42_NUM_HDMIDEV_SHIFT) & SOF_CS42L42_NUM_HDMIDEV_MASK) -#define SOF_CS42L42_BT_OFFLOAD_PRESENT BIT(25) -#define SOF_CS42L42_SSP_BT_SHIFT 26 -#define SOF_CS42L42_SSP_BT_MASK (GENMASK(28, 26)) -#define SOF_CS42L42_SSP_BT(quirk) \ - (((quirk) << SOF_CS42L42_SSP_BT_SHIFT) & SOF_CS42L42_SSP_BT_MASK) static struct snd_soc_jack_pin jack_pins[] = { { @@ -52,7 +35,7 @@ static struct snd_soc_jack_pin jack_pins[] = { }; /* Default: SSP2 */ -static unsigned long sof_cs42l42_quirk = SOF_CS42L42_SSP_CODEC(2); +static unsigned long sof_cs42l42_quirk = SOF_SSP_PORT_CODEC(2); static int sof_cs42l42_init(struct snd_soc_pcm_runtime *rtd) { @@ -229,48 +212,26 @@ static int sof_audio_probe(struct platform_device *pdev) struct sof_card_private *ctx; int ret; - ctx = devm_kzalloc(&pdev->dev, sizeof(*ctx), GFP_KERNEL); - if (!ctx) - return -ENOMEM; - if (pdev->id_entry && pdev->id_entry->driver_data) sof_cs42l42_quirk = (unsigned long)pdev->id_entry->driver_data; - ctx->codec_type = sof_ssp_detect_codec_type(&pdev->dev); - ctx->amp_type = sof_ssp_detect_amp_type(&pdev->dev); + dev_dbg(&pdev->dev, "sof_cs42l42_quirk = %lx\n", sof_cs42l42_quirk); + + /* initialize ctx with board quirk */ + ctx = sof_intel_board_get_ctx(&pdev->dev, sof_cs42l42_quirk); + if (!ctx) + return -ENOMEM; if (soc_intel_is_glk()) { ctx->dmic_be_num = 1; - ctx->hdmi_num = 3; /* overwrite the DAI link order for GLK boards */ ctx->link_order_overwrite = GLK_LINK_ORDER; - } else { - ctx->dmic_be_num = 2; - ctx->hdmi_num = (sof_cs42l42_quirk & SOF_CS42L42_NUM_HDMIDEV_MASK) >> - SOF_CS42L42_NUM_HDMIDEV_SHIFT; - /* default number of HDMI DAI's */ - if (!ctx->hdmi_num) - ctx->hdmi_num = 3; } if (mach->mach_params.codec_mask & IDISP_CODEC_MASK) ctx->hdmi.idisp_codec = true; - dev_dbg(&pdev->dev, "sof_cs42l42_quirk = %lx\n", sof_cs42l42_quirk); - - /* port number of peripherals attached to ssp interface */ - ctx->ssp_bt = (sof_cs42l42_quirk & SOF_CS42L42_SSP_BT_MASK) >> - SOF_CS42L42_SSP_BT_SHIFT; - - ctx->ssp_amp = (sof_cs42l42_quirk & SOF_CS42L42_SSP_AMP_MASK) >> - SOF_CS42L42_SSP_AMP_SHIFT; - - ctx->ssp_codec = sof_cs42l42_quirk & SOF_CS42L42_SSP_CODEC_MASK; - - if (sof_cs42l42_quirk & SOF_CS42L42_BT_OFFLOAD_PRESENT) - ctx->bt_offload_present = true; - /* update dai_link */ ret = sof_card_dai_links_create(&pdev->dev, &sof_audio_card_cs42l42, ctx); if (ret) @@ -293,21 +254,21 @@ static int sof_audio_probe(struct platform_device *pdev) static const struct platform_device_id board_ids[] = { { .name = "glk_cs4242_mx98357a", - .driver_data = (kernel_ulong_t)(SOF_CS42L42_SSP_CODEC(2) | - SOF_CS42L42_SSP_AMP(1)), + .driver_data = (kernel_ulong_t)(SOF_SSP_PORT_CODEC(2) | + SOF_SSP_PORT_AMP(1)), }, { .name = "jsl_cs4242_mx98360a", - .driver_data = (kernel_ulong_t)(SOF_CS42L42_SSP_CODEC(0) | - SOF_CS42L42_SSP_AMP(1)), + .driver_data = (kernel_ulong_t)(SOF_SSP_PORT_CODEC(0) | + SOF_SSP_PORT_AMP(1)), }, { .name = "adl_mx98360a_cs4242", - .driver_data = (kernel_ulong_t)(SOF_CS42L42_SSP_CODEC(0) | - SOF_CS42L42_SSP_AMP(1) | - SOF_CS42L42_NUM_HDMIDEV(4) | - SOF_CS42L42_BT_OFFLOAD_PRESENT | - SOF_CS42L42_SSP_BT(2)), + .driver_data = (kernel_ulong_t)(SOF_SSP_PORT_CODEC(0) | + SOF_SSP_PORT_AMP(1) | + SOF_NUM_IDISP_HDMI(4) | + SOF_BT_OFFLOAD_PRESENT | + SOF_SSP_PORT_BT_OFFLOAD(2)), }, { } }; @@ -329,4 +290,3 @@ MODULE_AUTHOR("Brent Lu "); MODULE_LICENSE("GPL"); MODULE_IMPORT_NS(SND_SOC_INTEL_SOF_BOARD_HELPERS); MODULE_IMPORT_NS(SND_SOC_INTEL_SOF_MAXIM_COMMON); -MODULE_IMPORT_NS(SND_SOC_INTEL_SOF_SSP_COMMON); -- cgit v1.2.3 From bfa8c0088f02440653bfdc7e72144302f2f5f22b Mon Sep 17 00:00:00 2001 From: Brent Lu Date: Mon, 25 Mar 2024 17:10:47 -0500 Subject: ASoC: Intel: sof_nau8825: use common module for sof_card_private initialization Use intel_board module to initialize sof_card_private structure. Reviewed-by: Bard Liao Signed-off-by: Brent Lu Signed-off-by: Pierre-Louis Bossart Link: https://msgid.link/r/20240325221059.206042-10-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/intel/boards/sof_nau8825.c | 88 ++++++++++-------------------------- 1 file changed, 23 insertions(+), 65 deletions(-) diff --git a/sound/soc/intel/boards/sof_nau8825.c b/sound/soc/intel/boards/sof_nau8825.c index 719c2fbaf515..b9db6e236a93 100644 --- a/sound/soc/intel/boards/sof_nau8825.c +++ b/sound/soc/intel/boards/sof_nau8825.c @@ -24,27 +24,8 @@ #include "sof_realtek_common.h" #include "sof_maxim_common.h" #include "sof_nuvoton_common.h" -#include "sof_ssp_common.h" - -#define SOF_NAU8825_SSP_CODEC(quirk) ((quirk) & GENMASK(2, 0)) -#define SOF_NAU8825_SSP_CODEC_MASK (GENMASK(2, 0)) -#define SOF_NAU8825_SSP_AMP_SHIFT 4 -#define SOF_NAU8825_SSP_AMP_MASK (GENMASK(6, 4)) -#define SOF_NAU8825_SSP_AMP(quirk) \ - (((quirk) << SOF_NAU8825_SSP_AMP_SHIFT) & SOF_NAU8825_SSP_AMP_MASK) -#define SOF_NAU8825_NUM_HDMIDEV_SHIFT 7 -#define SOF_NAU8825_NUM_HDMIDEV_MASK (GENMASK(9, 7)) -#define SOF_NAU8825_NUM_HDMIDEV(quirk) \ - (((quirk) << SOF_NAU8825_NUM_HDMIDEV_SHIFT) & SOF_NAU8825_NUM_HDMIDEV_MASK) - -/* BT audio offload: reserve 3 bits for future */ -#define SOF_BT_OFFLOAD_SSP_SHIFT 10 -#define SOF_BT_OFFLOAD_SSP_MASK (GENMASK(12, 10)) -#define SOF_BT_OFFLOAD_SSP(quirk) \ - (((quirk) << SOF_BT_OFFLOAD_SSP_SHIFT) & SOF_BT_OFFLOAD_SSP_MASK) -#define SOF_SSP_BT_OFFLOAD_PRESENT BIT(13) - -static unsigned long sof_nau8825_quirk = SOF_NAU8825_SSP_CODEC(0); + +static unsigned long sof_nau8825_quirk = SOF_SSP_PORT_CODEC(0); static struct snd_soc_jack_pin jack_pins[] = { { @@ -264,41 +245,19 @@ static int sof_audio_probe(struct platform_device *pdev) struct sof_card_private *ctx; int ret; - ctx = devm_kzalloc(&pdev->dev, sizeof(*ctx), GFP_KERNEL); - if (!ctx) - return -ENOMEM; - if (pdev->id_entry && pdev->id_entry->driver_data) sof_nau8825_quirk = (unsigned long)pdev->id_entry->driver_data; - ctx->codec_type = sof_ssp_detect_codec_type(&pdev->dev); - ctx->amp_type = sof_ssp_detect_amp_type(&pdev->dev); - dev_dbg(&pdev->dev, "sof_nau8825_quirk = %lx\n", sof_nau8825_quirk); - /* default number of DMIC DAI's */ - ctx->dmic_be_num = 2; - ctx->hdmi_num = (sof_nau8825_quirk & SOF_NAU8825_NUM_HDMIDEV_MASK) >> - SOF_NAU8825_NUM_HDMIDEV_SHIFT; - /* default number of HDMI DAI's */ - if (!ctx->hdmi_num) - ctx->hdmi_num = 3; + /* initialize ctx with board quirk */ + ctx = sof_intel_board_get_ctx(&pdev->dev, sof_nau8825_quirk); + if (!ctx) + return -ENOMEM; if (mach->mach_params.codec_mask & IDISP_CODEC_MASK) ctx->hdmi.idisp_codec = true; - /* port number of peripherals attached to ssp interface */ - ctx->ssp_bt = (sof_nau8825_quirk & SOF_BT_OFFLOAD_SSP_MASK) >> - SOF_BT_OFFLOAD_SSP_SHIFT; - - ctx->ssp_amp = (sof_nau8825_quirk & SOF_NAU8825_SSP_AMP_MASK) >> - SOF_NAU8825_SSP_AMP_SHIFT; - - ctx->ssp_codec = sof_nau8825_quirk & SOF_NAU8825_SSP_CODEC_MASK; - - if (sof_nau8825_quirk & SOF_SSP_BT_OFFLOAD_PRESENT) - ctx->bt_offload_present = true; - /* update dai_link */ ret = sof_card_dai_links_create(&pdev->dev, &sof_audio_card_nau8825, ctx); if (ret) @@ -340,33 +299,33 @@ static int sof_audio_probe(struct platform_device *pdev) static const struct platform_device_id board_ids[] = { { .name = "sof_nau8825", - .driver_data = (kernel_ulong_t)(SOF_NAU8825_SSP_CODEC(0) | - SOF_NAU8825_NUM_HDMIDEV(4) | - SOF_BT_OFFLOAD_SSP(2) | - SOF_SSP_BT_OFFLOAD_PRESENT), + .driver_data = (kernel_ulong_t)(SOF_SSP_PORT_CODEC(0) | + SOF_NUM_IDISP_HDMI(4) | + SOF_SSP_PORT_BT_OFFLOAD(2) | + SOF_BT_OFFLOAD_PRESENT), }, { .name = "adl_rt1019p_8825", - .driver_data = (kernel_ulong_t)(SOF_NAU8825_SSP_CODEC(0) | - SOF_NAU8825_SSP_AMP(2) | - SOF_NAU8825_NUM_HDMIDEV(4)), + .driver_data = (kernel_ulong_t)(SOF_SSP_PORT_CODEC(0) | + SOF_SSP_PORT_AMP(2) | + SOF_NUM_IDISP_HDMI(4)), }, { .name = "adl_nau8825_def", - .driver_data = (kernel_ulong_t)(SOF_NAU8825_SSP_CODEC(0) | - SOF_NAU8825_SSP_AMP(1) | - SOF_NAU8825_NUM_HDMIDEV(4) | - SOF_BT_OFFLOAD_SSP(2) | - SOF_SSP_BT_OFFLOAD_PRESENT), + .driver_data = (kernel_ulong_t)(SOF_SSP_PORT_CODEC(0) | + SOF_SSP_PORT_AMP(1) | + SOF_NUM_IDISP_HDMI(4) | + SOF_SSP_PORT_BT_OFFLOAD(2) | + SOF_BT_OFFLOAD_PRESENT), }, { .name = "rpl_nau8825_def", - .driver_data = (kernel_ulong_t)(SOF_NAU8825_SSP_CODEC(0) | - SOF_NAU8825_SSP_AMP(1) | - SOF_NAU8825_NUM_HDMIDEV(4) | - SOF_BT_OFFLOAD_SSP(2) | - SOF_SSP_BT_OFFLOAD_PRESENT), + .driver_data = (kernel_ulong_t)(SOF_SSP_PORT_CODEC(0) | + SOF_SSP_PORT_AMP(1) | + SOF_NUM_IDISP_HDMI(4) | + SOF_SSP_PORT_BT_OFFLOAD(2) | + SOF_BT_OFFLOAD_PRESENT), }, { } }; @@ -392,4 +351,3 @@ MODULE_IMPORT_NS(SND_SOC_INTEL_SOF_BOARD_HELPERS); MODULE_IMPORT_NS(SND_SOC_INTEL_SOF_MAXIM_COMMON); MODULE_IMPORT_NS(SND_SOC_INTEL_SOF_NUVOTON_COMMON); MODULE_IMPORT_NS(SND_SOC_INTEL_SOF_REALTEK_COMMON); -MODULE_IMPORT_NS(SND_SOC_INTEL_SOF_SSP_COMMON); -- cgit v1.2.3 From 8efcd48646526dc41dc54a5044b434cd8a139d82 Mon Sep 17 00:00:00 2001 From: Brent Lu Date: Mon, 25 Mar 2024 17:10:48 -0500 Subject: ASoC: Intel: sof_rt5682: use common module for sof_card_private initialization Use intel_board module to initialize sof_card_private structure Reviewed-by: Bard Liao Signed-off-by: Brent Lu Signed-off-by: Pierre-Louis Bossart Link: https://msgid.link/r/20240325221059.206042-11-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/intel/boards/sof_rt5682.c | 220 +++++++++++++++--------------------- 1 file changed, 89 insertions(+), 131 deletions(-) diff --git a/sound/soc/intel/boards/sof_rt5682.c b/sound/soc/intel/boards/sof_rt5682.c index 640d17c6cd35..672636f07456 100644 --- a/sound/soc/intel/boards/sof_rt5682.c +++ b/sound/soc/intel/boards/sof_rt5682.c @@ -27,37 +27,14 @@ #include "sof_board_helpers.h" #include "sof_maxim_common.h" #include "sof_realtek_common.h" -#include "sof_ssp_common.h" - -#define SOF_RT5682_SSP_CODEC(quirk) ((quirk) & GENMASK(2, 0)) -#define SOF_RT5682_SSP_CODEC_MASK (GENMASK(2, 0)) -#define SOF_RT5682_MCLK_EN BIT(3) -#define SOF_RT5682_SSP_AMP_SHIFT 6 -#define SOF_RT5682_SSP_AMP_MASK (GENMASK(8, 6)) -#define SOF_RT5682_SSP_AMP(quirk) \ - (((quirk) << SOF_RT5682_SSP_AMP_SHIFT) & SOF_RT5682_SSP_AMP_MASK) -#define SOF_RT5682_MCLK_BYTCHT_EN BIT(9) -#define SOF_RT5682_NUM_HDMIDEV_SHIFT 10 -#define SOF_RT5682_NUM_HDMIDEV_MASK (GENMASK(12, 10)) -#define SOF_RT5682_NUM_HDMIDEV(quirk) \ - ((quirk << SOF_RT5682_NUM_HDMIDEV_SHIFT) & SOF_RT5682_NUM_HDMIDEV_MASK) - -/* BT audio offload: reserve 3 bits for future */ -#define SOF_BT_OFFLOAD_SSP_SHIFT 19 -#define SOF_BT_OFFLOAD_SSP_MASK (GENMASK(21, 19)) -#define SOF_BT_OFFLOAD_SSP(quirk) \ - (((quirk) << SOF_BT_OFFLOAD_SSP_SHIFT) & SOF_BT_OFFLOAD_SSP_MASK) -#define SOF_SSP_BT_OFFLOAD_PRESENT BIT(22) - -/* HDMI capture*/ -#define SOF_NO_OF_HDMI_CAPTURE_SSP_SHIFT 27 -#define SOF_SSP_HDMI_CAPTURE_PRESENT_MASK (GENMASK(30, 27)) -#define SOF_HDMI_CAPTURE_SSP_MASK(quirk) \ - (((quirk) << SOF_NO_OF_HDMI_CAPTURE_SSP_SHIFT) & SOF_SSP_HDMI_CAPTURE_PRESENT_MASK) + +/* Driver-specific board quirks: from bit 0 to 7 */ +#define SOF_RT5682_MCLK_EN BIT(0) +#define SOF_RT5682_MCLK_BYTCHT_EN BIT(1) /* Default: MCLK on, MCLK 19.2M, SSP0 */ static unsigned long sof_rt5682_quirk = SOF_RT5682_MCLK_EN | - SOF_RT5682_SSP_CODEC(0); + SOF_SSP_PORT_CODEC(0); static int sof_rt5682_quirk_cb(const struct dmi_system_id *id) { @@ -72,7 +49,7 @@ static const struct dmi_system_id sof_rt5682_quirk_table[] = { DMI_MATCH(DMI_SYS_VENDOR, "Circuitco"), DMI_MATCH(DMI_PRODUCT_NAME, "Minnowboard Max"), }, - .driver_data = (void *)(SOF_RT5682_SSP_CODEC(2)), + .driver_data = (void *)(SOF_SSP_PORT_CODEC(2)), }, { .callback = sof_rt5682_quirk_cb, @@ -80,7 +57,7 @@ static const struct dmi_system_id sof_rt5682_quirk_table[] = { DMI_MATCH(DMI_SYS_VENDOR, "AAEON"), DMI_MATCH(DMI_PRODUCT_NAME, "UP-CHT01"), }, - .driver_data = (void *)(SOF_RT5682_SSP_CODEC(2)), + .driver_data = (void *)(SOF_SSP_PORT_CODEC(2)), }, { .callback = sof_rt5682_quirk_cb, @@ -89,7 +66,7 @@ static const struct dmi_system_id sof_rt5682_quirk_table[] = { DMI_MATCH(DMI_PRODUCT_NAME, "WhiskeyLake Client"), }, .driver_data = (void *)(SOF_RT5682_MCLK_EN | - SOF_RT5682_SSP_CODEC(1)), + SOF_SSP_PORT_CODEC(1)), }, { .callback = sof_rt5682_quirk_cb, @@ -97,8 +74,8 @@ static const struct dmi_system_id sof_rt5682_quirk_table[] = { DMI_MATCH(DMI_PRODUCT_FAMILY, "Google_Hatch"), }, .driver_data = (void *)(SOF_RT5682_MCLK_EN | - SOF_RT5682_SSP_CODEC(0) | - SOF_RT5682_SSP_AMP(1)), + SOF_SSP_PORT_CODEC(0) | + SOF_SSP_PORT_AMP(1)), }, { .callback = sof_rt5682_quirk_cb, @@ -107,7 +84,7 @@ static const struct dmi_system_id sof_rt5682_quirk_table[] = { DMI_MATCH(DMI_PRODUCT_NAME, "Ice Lake Client"), }, .driver_data = (void *)(SOF_RT5682_MCLK_EN | - SOF_RT5682_SSP_CODEC(0)), + SOF_SSP_PORT_CODEC(0)), }, { .callback = sof_rt5682_quirk_cb, @@ -116,9 +93,9 @@ static const struct dmi_system_id sof_rt5682_quirk_table[] = { DMI_MATCH(DMI_OEM_STRING, "AUDIO-MAX98373_ALC5682I_I2S_UP4"), }, .driver_data = (void *)(SOF_RT5682_MCLK_EN | - SOF_RT5682_SSP_CODEC(0) | - SOF_RT5682_SSP_AMP(2) | - SOF_RT5682_NUM_HDMIDEV(4)), + SOF_SSP_PORT_CODEC(0) | + SOF_SSP_PORT_AMP(2) | + SOF_NUM_IDISP_HDMI(4)), }, { .callback = sof_rt5682_quirk_cb, @@ -128,9 +105,9 @@ static const struct dmi_system_id sof_rt5682_quirk_table[] = { DMI_MATCH(DMI_OEM_STRING, "AUDIO-ADL_MAX98373_ALC5682I_I2S"), }, .driver_data = (void *)(SOF_RT5682_MCLK_EN | - SOF_RT5682_SSP_CODEC(0) | - SOF_RT5682_SSP_AMP(2) | - SOF_RT5682_NUM_HDMIDEV(4)), + SOF_SSP_PORT_CODEC(0) | + SOF_SSP_PORT_AMP(2) | + SOF_NUM_IDISP_HDMI(4)), }, { .callback = sof_rt5682_quirk_cb, @@ -139,9 +116,9 @@ static const struct dmi_system_id sof_rt5682_quirk_table[] = { DMI_MATCH(DMI_OEM_STRING, "AUDIO-MAX98390_ALC5682I_I2S"), }, .driver_data = (void *)(SOF_RT5682_MCLK_EN | - SOF_RT5682_SSP_CODEC(0) | - SOF_RT5682_SSP_AMP(2) | - SOF_RT5682_NUM_HDMIDEV(4)), + SOF_SSP_PORT_CODEC(0) | + SOF_SSP_PORT_AMP(2) | + SOF_NUM_IDISP_HDMI(4)), }, { .callback = sof_rt5682_quirk_cb, @@ -150,9 +127,9 @@ static const struct dmi_system_id sof_rt5682_quirk_table[] = { DMI_MATCH(DMI_OEM_STRING, "AUDIO-MAX98360_ALC5682I_I2S_AMP_SSP2"), }, .driver_data = (void *)(SOF_RT5682_MCLK_EN | - SOF_RT5682_SSP_CODEC(0) | - SOF_RT5682_SSP_AMP(2) | - SOF_RT5682_NUM_HDMIDEV(4)), + SOF_SSP_PORT_CODEC(0) | + SOF_SSP_PORT_AMP(2) | + SOF_NUM_IDISP_HDMI(4)), }, { .callback = sof_rt5682_quirk_cb, @@ -160,11 +137,11 @@ static const struct dmi_system_id sof_rt5682_quirk_table[] = { DMI_MATCH(DMI_PRODUCT_FAMILY, "Google_Rex"), }, .driver_data = (void *)(SOF_RT5682_MCLK_EN | - SOF_RT5682_SSP_CODEC(2) | - SOF_RT5682_SSP_AMP(0) | - SOF_RT5682_NUM_HDMIDEV(3) | - SOF_BT_OFFLOAD_SSP(1) | - SOF_SSP_BT_OFFLOAD_PRESENT + SOF_SSP_PORT_CODEC(2) | + SOF_SSP_PORT_AMP(0) | + SOF_NUM_IDISP_HDMI(3) | + SOF_SSP_PORT_BT_OFFLOAD(1) | + SOF_BT_OFFLOAD_PRESENT ), }, {} @@ -630,19 +607,29 @@ static int sof_audio_probe(struct platform_device *pdev) { struct snd_soc_acpi_mach *mach = pdev->dev.platform_data; struct sof_card_private *ctx; + bool is_legacy_cpu; int ret; - ctx = devm_kzalloc(&pdev->dev, sizeof(*ctx), GFP_KERNEL); - if (!ctx) - return -ENOMEM; - if (pdev->id_entry && pdev->id_entry->driver_data) sof_rt5682_quirk = (unsigned long)pdev->id_entry->driver_data; dmi_check_system(sof_rt5682_quirk_table); - ctx->codec_type = sof_ssp_detect_codec_type(&pdev->dev); - ctx->amp_type = sof_ssp_detect_amp_type(&pdev->dev); + if (soc_intel_is_byt() || soc_intel_is_cht()) { + is_legacy_cpu = true; + + /* default quirk for legacy cpu */ + sof_rt5682_quirk = SOF_RT5682_MCLK_EN | + SOF_RT5682_MCLK_BYTCHT_EN | + SOF_SSP_PORT_CODEC(2); + } + + dev_dbg(&pdev->dev, "sof_rt5682_quirk = %lx\n", sof_rt5682_quirk); + + /* initialize ctx with board quirk */ + ctx = sof_intel_board_get_ctx(&pdev->dev, sof_rt5682_quirk); + if (!ctx) + return -ENOMEM; if (ctx->codec_type == CODEC_RT5650) { sof_audio_card_rt5682.name = devm_kstrdup(&pdev->dev, "rt5650", @@ -653,23 +640,12 @@ static int sof_audio_probe(struct platform_device *pdev) ctx->amp_type = CODEC_RT5650; } - if (soc_intel_is_byt() || soc_intel_is_cht()) { + if (is_legacy_cpu) { ctx->rt5682.is_legacy_cpu = true; ctx->dmic_be_num = 0; /* HDMI is not supported by SOF on Baytrail/CherryTrail */ ctx->hdmi_num = 0; - /* default quirk for legacy cpu */ - sof_rt5682_quirk = SOF_RT5682_MCLK_EN | - SOF_RT5682_MCLK_BYTCHT_EN | - SOF_RT5682_SSP_CODEC(2); } else { - ctx->dmic_be_num = 2; - ctx->hdmi_num = (sof_rt5682_quirk & SOF_RT5682_NUM_HDMIDEV_MASK) >> - SOF_RT5682_NUM_HDMIDEV_SHIFT; - /* default number of HDMI DAI's */ - if (!ctx->hdmi_num) - ctx->hdmi_num = 3; - if (mach->mach_params.codec_mask & IDISP_CODEC_MASK) ctx->hdmi.idisp_codec = true; } @@ -694,23 +670,6 @@ static int sof_audio_probe(struct platform_device *pdev) } } - dev_dbg(&pdev->dev, "sof_rt5682_quirk = %lx\n", sof_rt5682_quirk); - - /* port number/mask of peripherals attached to ssp interface */ - ctx->ssp_mask_hdmi_in = (sof_rt5682_quirk & SOF_SSP_HDMI_CAPTURE_PRESENT_MASK) >> - SOF_NO_OF_HDMI_CAPTURE_SSP_SHIFT; - - ctx->ssp_bt = (sof_rt5682_quirk & SOF_BT_OFFLOAD_SSP_MASK) >> - SOF_BT_OFFLOAD_SSP_SHIFT; - - ctx->ssp_amp = (sof_rt5682_quirk & SOF_RT5682_SSP_AMP_MASK) >> - SOF_RT5682_SSP_AMP_SHIFT; - - ctx->ssp_codec = sof_rt5682_quirk & SOF_RT5682_SSP_CODEC_MASK; - - if (sof_rt5682_quirk & SOF_SSP_BT_OFFLOAD_PRESENT) - ctx->bt_offload_present = true; - /* update dai_link */ ret = sof_card_dai_links_create(&pdev->dev, &sof_audio_card_rt5682, ctx); if (ret) @@ -766,96 +725,96 @@ static const struct platform_device_id board_ids[] = { { .name = "cml_rt1015_rt5682", .driver_data = (kernel_ulong_t)(SOF_RT5682_MCLK_EN | - SOF_RT5682_SSP_CODEC(0) | - SOF_RT5682_SSP_AMP(1)), + SOF_SSP_PORT_CODEC(0) | + SOF_SSP_PORT_AMP(1)), }, { .name = "jsl_rt5682_def", .driver_data = (kernel_ulong_t)(SOF_RT5682_MCLK_EN | - SOF_RT5682_SSP_CODEC(0) | - SOF_RT5682_SSP_AMP(1)), + SOF_SSP_PORT_CODEC(0) | + SOF_SSP_PORT_AMP(1)), }, { .name = "tgl_rt5682_def", .driver_data = (kernel_ulong_t)(SOF_RT5682_MCLK_EN | - SOF_RT5682_SSP_CODEC(0) | - SOF_RT5682_SSP_AMP(1) | - SOF_RT5682_NUM_HDMIDEV(4) | - SOF_BT_OFFLOAD_SSP(2) | - SOF_SSP_BT_OFFLOAD_PRESENT), + SOF_SSP_PORT_CODEC(0) | + SOF_SSP_PORT_AMP(1) | + SOF_NUM_IDISP_HDMI(4) | + SOF_SSP_PORT_BT_OFFLOAD(2) | + SOF_BT_OFFLOAD_PRESENT), }, { .name = "adl_rt5682_def", .driver_data = (kernel_ulong_t)(SOF_RT5682_MCLK_EN | - SOF_RT5682_SSP_CODEC(0) | - SOF_RT5682_SSP_AMP(1) | - SOF_RT5682_NUM_HDMIDEV(4) | - SOF_BT_OFFLOAD_SSP(2) | - SOF_SSP_BT_OFFLOAD_PRESENT), + SOF_SSP_PORT_CODEC(0) | + SOF_SSP_PORT_AMP(1) | + SOF_NUM_IDISP_HDMI(4) | + SOF_SSP_PORT_BT_OFFLOAD(2) | + SOF_BT_OFFLOAD_PRESENT), }, { .name = "adl_mx98357_rt5682", .driver_data = (kernel_ulong_t)(SOF_RT5682_MCLK_EN | - SOF_RT5682_SSP_CODEC(0) | - SOF_RT5682_SSP_AMP(2) | - SOF_RT5682_NUM_HDMIDEV(4)), + SOF_SSP_PORT_CODEC(0) | + SOF_SSP_PORT_AMP(2) | + SOF_NUM_IDISP_HDMI(4)), }, { .name = "adl_rt5682_c1_h02", .driver_data = (kernel_ulong_t)(SOF_RT5682_MCLK_EN | - SOF_RT5682_SSP_CODEC(1) | - SOF_RT5682_NUM_HDMIDEV(3) | + SOF_SSP_PORT_CODEC(1) | + SOF_NUM_IDISP_HDMI(3) | /* SSP 0 and SSP 2 are used for HDMI IN */ - SOF_HDMI_CAPTURE_SSP_MASK(0x5)), + SOF_SSP_MASK_HDMI_CAPTURE(0x5)), }, { .name = "rpl_mx98357_rt5682", .driver_data = (kernel_ulong_t)(SOF_RT5682_MCLK_EN | - SOF_RT5682_SSP_CODEC(0) | - SOF_RT5682_SSP_AMP(2) | - SOF_RT5682_NUM_HDMIDEV(4)), + SOF_SSP_PORT_CODEC(0) | + SOF_SSP_PORT_AMP(2) | + SOF_NUM_IDISP_HDMI(4)), }, { .name = "rpl_rt5682_def", .driver_data = (kernel_ulong_t)(SOF_RT5682_MCLK_EN | - SOF_RT5682_SSP_CODEC(0) | - SOF_RT5682_SSP_AMP(1) | - SOF_RT5682_NUM_HDMIDEV(4) | - SOF_BT_OFFLOAD_SSP(2) | - SOF_SSP_BT_OFFLOAD_PRESENT), + SOF_SSP_PORT_CODEC(0) | + SOF_SSP_PORT_AMP(1) | + SOF_NUM_IDISP_HDMI(4) | + SOF_SSP_PORT_BT_OFFLOAD(2) | + SOF_BT_OFFLOAD_PRESENT), }, { .name = "rpl_rt5682_c1_h02", .driver_data = (kernel_ulong_t)(SOF_RT5682_MCLK_EN | - SOF_RT5682_SSP_CODEC(1) | - SOF_RT5682_NUM_HDMIDEV(3) | + SOF_SSP_PORT_CODEC(1) | + SOF_NUM_IDISP_HDMI(3) | /* SSP 0 and SSP 2 are used for HDMI IN */ - SOF_HDMI_CAPTURE_SSP_MASK(0x5)), + SOF_SSP_MASK_HDMI_CAPTURE(0x5)), }, { .name = "mtl_mx98357_rt5682", .driver_data = (kernel_ulong_t)(SOF_RT5682_MCLK_EN | - SOF_RT5682_SSP_CODEC(0) | - SOF_RT5682_SSP_AMP(1) | - SOF_RT5682_NUM_HDMIDEV(3) | - SOF_BT_OFFLOAD_SSP(2) | - SOF_SSP_BT_OFFLOAD_PRESENT), + SOF_SSP_PORT_CODEC(0) | + SOF_SSP_PORT_AMP(1) | + SOF_NUM_IDISP_HDMI(3) | + SOF_SSP_PORT_BT_OFFLOAD(2) | + SOF_BT_OFFLOAD_PRESENT), }, { .name = "mtl_mx98360_rt5682", .driver_data = (kernel_ulong_t)(SOF_RT5682_MCLK_EN | - SOF_RT5682_SSP_CODEC(0) | - SOF_RT5682_SSP_AMP(1) | - SOF_RT5682_NUM_HDMIDEV(3)), + SOF_SSP_PORT_CODEC(0) | + SOF_SSP_PORT_AMP(1) | + SOF_NUM_IDISP_HDMI(3)), }, { .name = "mtl_rt5682_def", .driver_data = (kernel_ulong_t)(SOF_RT5682_MCLK_EN | - SOF_RT5682_SSP_CODEC(2) | - SOF_RT5682_SSP_AMP(0) | - SOF_RT5682_NUM_HDMIDEV(3) | - SOF_BT_OFFLOAD_SSP(1) | - SOF_SSP_BT_OFFLOAD_PRESENT), + SOF_SSP_PORT_CODEC(2) | + SOF_SSP_PORT_AMP(0) | + SOF_NUM_IDISP_HDMI(3) | + SOF_SSP_PORT_BT_OFFLOAD(1) | + SOF_BT_OFFLOAD_PRESENT), }, { } }; @@ -881,4 +840,3 @@ MODULE_LICENSE("GPL v2"); MODULE_IMPORT_NS(SND_SOC_INTEL_SOF_BOARD_HELPERS); MODULE_IMPORT_NS(SND_SOC_INTEL_SOF_MAXIM_COMMON); MODULE_IMPORT_NS(SND_SOC_INTEL_SOF_REALTEK_COMMON); -MODULE_IMPORT_NS(SND_SOC_INTEL_SOF_SSP_COMMON); -- cgit v1.2.3 From 495d5b48d4b54efb4fa9f972f8bb599c780d209e Mon Sep 17 00:00:00 2001 From: Brent Lu Date: Mon, 25 Mar 2024 17:10:49 -0500 Subject: ASoC: Intel: sof_ssp_amp: use common module for sof_card_private initialization Use intel_board module to initialize sof_card_private structure. Reviewed-by: Bard Liao Signed-off-by: Brent Lu Signed-off-by: Pierre-Louis Bossart Link: https://msgid.link/r/20240325221059.206042-12-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/intel/boards/sof_ssp_amp.c | 93 ++++++++++-------------------------- 1 file changed, 26 insertions(+), 67 deletions(-) diff --git a/sound/soc/intel/boards/sof_ssp_amp.c b/sound/soc/intel/boards/sof_ssp_amp.c index 0b8adab76755..b99af8bc4ccc 100644 --- a/sound/soc/intel/boards/sof_ssp_amp.c +++ b/sound/soc/intel/boards/sof_ssp_amp.c @@ -20,34 +20,12 @@ #include "sof_board_helpers.h" #include "sof_realtek_common.h" #include "sof_cirrus_common.h" -#include "sof_ssp_common.h" - -/* SSP port ID for speaker amplifier */ -#define SOF_AMPLIFIER_SSP(quirk) ((quirk) & GENMASK(3, 0)) -#define SOF_AMPLIFIER_SSP_MASK (GENMASK(3, 0)) - -/* HDMI capture*/ -#define SOF_HDMI_CAPTURE_SSP_MASK_SHIFT 4 -#define SOF_HDMI_CAPTURE_SSP_MASK_MASK (GENMASK(9, 4)) -#define SOF_HDMI_CAPTURE_SSP_MASK(quirk) \ - (((quirk) << SOF_HDMI_CAPTURE_SSP_MASK_SHIFT) & SOF_HDMI_CAPTURE_SSP_MASK_MASK) - -/* HDMI playback */ -#define SOF_HDMI_PLAYBACK_PRESENT BIT(13) -#define SOF_NO_OF_HDMI_PLAYBACK_SHIFT 14 -#define SOF_NO_OF_HDMI_PLAYBACK_MASK (GENMASK(16, 14)) -#define SOF_NO_OF_HDMI_PLAYBACK(quirk) \ - (((quirk) << SOF_NO_OF_HDMI_PLAYBACK_SHIFT) & SOF_NO_OF_HDMI_PLAYBACK_MASK) - -/* BT audio offload */ -#define SOF_SSP_BT_OFFLOAD_PRESENT BIT(17) -#define SOF_BT_OFFLOAD_SSP_SHIFT 18 -#define SOF_BT_OFFLOAD_SSP_MASK (GENMASK(20, 18)) -#define SOF_BT_OFFLOAD_SSP(quirk) \ - (((quirk) << SOF_BT_OFFLOAD_SSP_SHIFT) & SOF_BT_OFFLOAD_SSP_MASK) + +/* Driver-specific board quirks: from bit 0 to 7 */ +#define SOF_HDMI_PLAYBACK_PRESENT BIT(0) /* Default: SSP2 */ -static unsigned long sof_ssp_amp_quirk = SOF_AMPLIFIER_SSP(2); +static unsigned long sof_ssp_amp_quirk = SOF_SSP_PORT_AMP(2); static const struct dmi_system_id chromebook_platforms[] = { { @@ -136,45 +114,27 @@ static int sof_ssp_amp_probe(struct platform_device *pdev) struct sof_card_private *ctx; int ret; - ctx = devm_kzalloc(&pdev->dev, sizeof(*ctx), GFP_KERNEL); - if (!ctx) - return -ENOMEM; - if (pdev->id_entry && pdev->id_entry->driver_data) sof_ssp_amp_quirk = (unsigned long)pdev->id_entry->driver_data; - ctx->amp_type = sof_ssp_detect_amp_type(&pdev->dev); - - if (dmi_check_system(chromebook_platforms) || mach->mach_params.dmic_num > 0) - ctx->dmic_be_num = 2; - else - ctx->dmic_be_num = 0; - - /* port number/mask of peripherals attached to ssp interface */ - ctx->ssp_mask_hdmi_in = (sof_ssp_amp_quirk & SOF_HDMI_CAPTURE_SSP_MASK_MASK) >> - SOF_HDMI_CAPTURE_SSP_MASK_SHIFT; + dev_dbg(&pdev->dev, "sof_ssp_amp_quirk = %lx\n", sof_ssp_amp_quirk); - ctx->ssp_bt = (sof_ssp_amp_quirk & SOF_BT_OFFLOAD_SSP_MASK) >> - SOF_BT_OFFLOAD_SSP_SHIFT; + /* initialize ctx with board quirk */ + ctx = sof_intel_board_get_ctx(&pdev->dev, sof_ssp_amp_quirk); + if (!ctx) + return -ENOMEM; - ctx->ssp_amp = sof_ssp_amp_quirk & SOF_AMPLIFIER_SSP_MASK; + if (!dmi_check_system(chromebook_platforms) && + (mach->mach_params.dmic_num == 0)) + ctx->dmic_be_num = 0; if (sof_ssp_amp_quirk & SOF_HDMI_PLAYBACK_PRESENT) { - ctx->hdmi_num = (sof_ssp_amp_quirk & SOF_NO_OF_HDMI_PLAYBACK_MASK) >> - SOF_NO_OF_HDMI_PLAYBACK_SHIFT; - /* default number of HDMI DAI's */ - if (!ctx->hdmi_num) - ctx->hdmi_num = 3; - if (mach->mach_params.codec_mask & IDISP_CODEC_MASK) ctx->hdmi.idisp_codec = true; } else { ctx->hdmi_num = 0; } - if (sof_ssp_amp_quirk & SOF_SSP_BT_OFFLOAD_PRESENT) - ctx->bt_offload_present = true; - ctx->link_order_overwrite = SSP_AMP_LINK_ORDER; if (ctx->ssp_mask_hdmi_in) { @@ -220,38 +180,38 @@ static const struct platform_device_id board_ids[] = { }, { .name = "tgl_rt1308_hdmi_ssp", - .driver_data = (kernel_ulong_t)(SOF_AMPLIFIER_SSP(2) | - SOF_HDMI_CAPTURE_SSP_MASK(0x22)), + .driver_data = (kernel_ulong_t)(SOF_SSP_PORT_AMP(2) | + SOF_SSP_MASK_HDMI_CAPTURE(0x22)), /* SSP 1 and SSP 5 are used for HDMI IN */ }, { .name = "adl_cs35l41", - .driver_data = (kernel_ulong_t)(SOF_AMPLIFIER_SSP(1) | - SOF_NO_OF_HDMI_PLAYBACK(4) | + .driver_data = (kernel_ulong_t)(SOF_SSP_PORT_AMP(1) | + SOF_NUM_IDISP_HDMI(4) | SOF_HDMI_PLAYBACK_PRESENT | - SOF_BT_OFFLOAD_SSP(2) | - SOF_SSP_BT_OFFLOAD_PRESENT), + SOF_SSP_PORT_BT_OFFLOAD(2) | + SOF_BT_OFFLOAD_PRESENT), }, { .name = "adl_lt6911_hdmi_ssp", - .driver_data = (kernel_ulong_t)(SOF_HDMI_CAPTURE_SSP_MASK(0x5) | + .driver_data = (kernel_ulong_t)(SOF_SSP_MASK_HDMI_CAPTURE(0x5) | /* SSP 0 and SSP 2 are used for HDMI IN */ - SOF_NO_OF_HDMI_PLAYBACK(3) | + SOF_NUM_IDISP_HDMI(3) | SOF_HDMI_PLAYBACK_PRESENT), }, { .name = "rpl_lt6911_hdmi_ssp", - .driver_data = (kernel_ulong_t)(SOF_HDMI_CAPTURE_SSP_MASK(0x5) | + .driver_data = (kernel_ulong_t)(SOF_SSP_MASK_HDMI_CAPTURE(0x5) | /* SSP 0 and SSP 2 are used for HDMI IN */ - SOF_NO_OF_HDMI_PLAYBACK(3) | + SOF_NUM_IDISP_HDMI(3) | SOF_HDMI_PLAYBACK_PRESENT), }, { .name = "mtl_lt6911_hdmi_ssp", - .driver_data = (kernel_ulong_t)(SOF_HDMI_CAPTURE_SSP_MASK(0x5) | - /* SSP 0 and SSP 2 are used for HDMI IN */ - SOF_NO_OF_HDMI_PLAYBACK(3) | - SOF_HDMI_PLAYBACK_PRESENT), + .driver_data = (kernel_ulong_t)(SOF_SSP_MASK_HDMI_CAPTURE(0x5) | + /* SSP 0 and SSP 2 are used for HDMI IN */ + SOF_NUM_IDISP_HDMI(3) | + SOF_HDMI_PLAYBACK_PRESENT), }, { } }; @@ -274,4 +234,3 @@ MODULE_LICENSE("GPL"); MODULE_IMPORT_NS(SND_SOC_INTEL_SOF_BOARD_HELPERS); MODULE_IMPORT_NS(SND_SOC_INTEL_SOF_REALTEK_COMMON); MODULE_IMPORT_NS(SND_SOC_INTEL_SOF_CIRRUS_COMMON); -MODULE_IMPORT_NS(SND_SOC_INTEL_SOF_SSP_COMMON); -- cgit v1.2.3 From a8f408dc8733d83c1cbd0ff238fc90d8b43db1c4 Mon Sep 17 00:00:00 2001 From: Brent Lu Date: Mon, 25 Mar 2024 17:10:50 -0500 Subject: ASoC: Intel: sof_da7219: use common module for DAI link generation Use intel_board module to generate DAI link array and update num_links field in snd_soc_card structure. Reviewed-by: Bard Liao Signed-off-by: Brent Lu Signed-off-by: Pierre-Louis Bossart Link: https://msgid.link/r/20240325221059.206042-13-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/intel/boards/Kconfig | 1 + sound/soc/intel/boards/sof_board_helpers.h | 13 + sound/soc/intel/boards/sof_da7219.c | 391 +++++++++-------------------- 3 files changed, 129 insertions(+), 276 deletions(-) diff --git a/sound/soc/intel/boards/Kconfig b/sound/soc/intel/boards/Kconfig index 18ac3ce0752e..e5df64fec319 100644 --- a/sound/soc/intel/boards/Kconfig +++ b/sound/soc/intel/boards/Kconfig @@ -624,6 +624,7 @@ config SND_SOC_INTEL_SOF_DA7219_MACH select SND_SOC_MAX98357A select SND_SOC_MAX98373_I2C select SND_SOC_DMIC + select SND_SOC_INTEL_SOF_BOARD_HELPERS select SND_SOC_INTEL_SOF_MAXIM_COMMON select SND_SOC_INTEL_SOF_SSP_COMMON help diff --git a/sound/soc/intel/boards/sof_board_helpers.h b/sound/soc/intel/boards/sof_board_helpers.h index 0d0a8d97843b..1701481ab6ae 100644 --- a/sound/soc/intel/boards/sof_board_helpers.h +++ b/sound/soc/intel/boards/sof_board_helpers.h @@ -83,6 +83,17 @@ enum { (((k6) & SOF_LINK_IDS_MASK) << (SOF_LINK_IDS_SHIFT * 5)) | \ (((k7) & SOF_LINK_IDS_MASK) << (SOF_LINK_IDS_SHIFT * 6))) +/* + * sof_da7219_private: private data for da7219 machine driver + * + * @is_jsl_board: true for JSL boards + * @pll_bypass: true for PLL bypass mode + */ +struct sof_da7219_private { + bool is_jsl_board; + bool pll_bypass; +}; + /* * sof_rt5682_private: private data for rt5682 machine driver * @@ -112,6 +123,7 @@ struct sof_rt5682_private { * @amp_link: pointer to speaker amplifier dai link * @link_order_overwrite: custom DAI link order * @link_id_overwrite: custom DAI link ID + * @da7219: private data for da7219 machine driver * @rt5682: private data for rt5682 machine driver */ struct sof_card_private { @@ -142,6 +154,7 @@ struct sof_card_private { unsigned long link_id_overwrite; union { + struct sof_da7219_private da7219; struct sof_rt5682_private rt5682; }; }; diff --git a/sound/soc/intel/boards/sof_da7219.c b/sound/soc/intel/boards/sof_da7219.c index 290bf75bdaef..f0cb1572c6c4 100644 --- a/sound/soc/intel/boards/sof_da7219.c +++ b/sound/soc/intel/boards/sof_da7219.c @@ -15,35 +15,24 @@ #include #include #include "../../codecs/da7219.h" -#include "hda_dsp_common.h" -#include "sof_hdmi_common.h" +#include "sof_board_helpers.h" #include "sof_maxim_common.h" -#include "sof_ssp_common.h" -/* Board Quirks */ -#define SOF_DA7219_JSL_BOARD BIT(2) +/* Driver-specific board quirks: from bit 0 to 7 */ +#define SOF_DA7219_JSL_BOARD BIT(0) #define DIALOG_CODEC_DAI "da7219-hifi" -struct card_private { - struct snd_soc_jack headset_jack; - struct sof_hdmi_private hdmi; - enum sof_ssp_codec codec_type; - enum sof_ssp_codec amp_type; - - unsigned int pll_bypass:1; -}; - static int platform_clock_control(struct snd_soc_dapm_widget *w, struct snd_kcontrol *k, int event) { struct snd_soc_dapm_context *dapm = w->dapm; struct snd_soc_card *card = dapm->card; - struct card_private *ctx = snd_soc_card_get_drvdata(card); + struct sof_card_private *ctx = snd_soc_card_get_drvdata(card); struct snd_soc_dai *codec_dai; int ret = 0; - if (ctx->pll_bypass) + if (ctx->da7219.pll_bypass) return ret; /* PLL SRM mode */ @@ -74,8 +63,6 @@ static const struct snd_kcontrol_new controls[] = { SOC_DAPM_PIN_SWITCH("Headphone Jack"), SOC_DAPM_PIN_SWITCH("Headset Mic"), SOC_DAPM_PIN_SWITCH("Line Out"), - SOC_DAPM_PIN_SWITCH("Left Spk"), - SOC_DAPM_PIN_SWITCH("Right Spk"), }; static const struct snd_soc_dapm_widget widgets[] = { @@ -83,14 +70,9 @@ static const struct snd_soc_dapm_widget widgets[] = { SND_SOC_DAPM_MIC("Headset Mic", NULL), SND_SOC_DAPM_LINE("Line Out", NULL), - SND_SOC_DAPM_SPK("Left Spk", NULL), - SND_SOC_DAPM_SPK("Right Spk", NULL), - SND_SOC_DAPM_SUPPLY("Platform Clock", SND_SOC_NOPM, 0, 0, platform_clock_control, SND_SOC_DAPM_POST_PMD | SND_SOC_DAPM_PRE_PMU), - - SND_SOC_DAPM_MIC("SoC DMIC", NULL), }; static const struct snd_soc_dapm_route audio_map[] = { @@ -102,9 +84,6 @@ static const struct snd_soc_dapm_route audio_map[] = { { "Headphone Jack", NULL, "Platform Clock" }, { "Headset Mic", NULL, "Platform Clock" }, { "Line Out", NULL, "Platform Clock" }, - - /* digital mics */ - {"DMic", NULL, "SoC DMIC"}, }; static struct snd_soc_jack_pin jack_pins[] = { @@ -124,7 +103,7 @@ static struct snd_soc_jack_pin jack_pins[] = { static int da7219_codec_init(struct snd_soc_pcm_runtime *rtd) { - struct card_private *ctx = snd_soc_card_get_drvdata(rtd->card); + struct sof_card_private *ctx = snd_soc_card_get_drvdata(rtd->card); struct snd_soc_dai *codec_dai = snd_soc_rtd_to_codec(rtd, 0); struct snd_soc_component *component = codec_dai->component; struct snd_soc_jack *jack = &ctx->headset_jack; @@ -157,7 +136,7 @@ static int da7219_codec_init(struct snd_soc_pcm_runtime *rtd) return ret; } - ctx->pll_bypass = 1; + ctx->da7219.pll_bypass = true; } /* @@ -222,215 +201,11 @@ static const struct snd_soc_ops max98373_ops = { .hw_params = max98373_hw_params, }; -static int hdmi_init(struct snd_soc_pcm_runtime *rtd) -{ - struct card_private *ctx = snd_soc_card_get_drvdata(rtd->card); - struct snd_soc_dai *dai = snd_soc_rtd_to_codec(rtd, 0); - - ctx->hdmi.hdmi_comp = dai->component; - - return 0; -} - static int card_late_probe(struct snd_soc_card *card) { - struct card_private *ctx = snd_soc_card_get_drvdata(card); - - if (!ctx->hdmi.idisp_codec) - return 0; - - if (!ctx->hdmi.hdmi_comp) - return -EINVAL; - - return hda_dsp_hdmi_build_controls(card, ctx->hdmi.hdmi_comp); + return sof_intel_board_card_late_probe(card); } -SND_SOC_DAILINK_DEF(ssp0_pin, - DAILINK_COMP_ARRAY(COMP_CPU("SSP0 Pin"))); -SND_SOC_DAILINK_DEF(ssp0_codec, - DAILINK_COMP_ARRAY(COMP_CODEC("i2c-DLGS7219:00", DIALOG_CODEC_DAI))); - -SND_SOC_DAILINK_DEF(ssp1_pin, - DAILINK_COMP_ARRAY(COMP_CPU("SSP1 Pin"))); - -SND_SOC_DAILINK_DEF(ssp2_pin, - DAILINK_COMP_ARRAY(COMP_CPU("SSP2 Pin"))); -SND_SOC_DAILINK_DEF(dummy_codec, - DAILINK_COMP_ARRAY(COMP_CODEC("snd-soc-dummy", "snd-soc-dummy-dai"))); - -SND_SOC_DAILINK_DEF(dmic_pin, - DAILINK_COMP_ARRAY(COMP_CPU("DMIC01 Pin"))); -SND_SOC_DAILINK_DEF(dmic_codec, - DAILINK_COMP_ARRAY(COMP_CODEC("dmic-codec", "dmic-hifi"))); - -SND_SOC_DAILINK_DEF(dmic16k_pin, - DAILINK_COMP_ARRAY(COMP_CPU("DMIC16k Pin"))); - -SND_SOC_DAILINK_DEF(idisp1_pin, - DAILINK_COMP_ARRAY(COMP_CPU("iDisp1 Pin"))); -SND_SOC_DAILINK_DEF(idisp1_codec, - DAILINK_COMP_ARRAY(COMP_CODEC("ehdaudio0D2", "intel-hdmi-hifi1"))); - -SND_SOC_DAILINK_DEF(idisp2_pin, - DAILINK_COMP_ARRAY(COMP_CPU("iDisp2 Pin"))); -SND_SOC_DAILINK_DEF(idisp2_codec, - DAILINK_COMP_ARRAY(COMP_CODEC("ehdaudio0D2", "intel-hdmi-hifi2"))); - -SND_SOC_DAILINK_DEF(idisp3_pin, - DAILINK_COMP_ARRAY(COMP_CPU("iDisp3 Pin"))); -SND_SOC_DAILINK_DEF(idisp3_codec, - DAILINK_COMP_ARRAY(COMP_CODEC("ehdaudio0D2", "intel-hdmi-hifi3"))); - -SND_SOC_DAILINK_DEF(idisp4_pin, - DAILINK_COMP_ARRAY(COMP_CPU("iDisp4 Pin"))); -SND_SOC_DAILINK_DEF(idisp4_codec, - DAILINK_COMP_ARRAY(COMP_CODEC("ehdaudio0D2", "intel-hdmi-hifi4"))); - -SND_SOC_DAILINK_DEF(platform, /* subject to be overridden during probe */ - DAILINK_COMP_ARRAY(COMP_PLATFORM("0000:00:1f.3"))); - -static struct snd_soc_dai_link jsl_dais[] = { - /* Back End DAI links */ - { - .name = "SSP1-Codec", - .id = 0, - .ignore_pmdown_time = 1, - .no_pcm = 1, - .dpcm_playback = 1, - .dpcm_capture = 1, /* IV feedback */ - SND_SOC_DAILINK_REG(ssp1_pin, max_98373_components, platform), - }, - { - .name = "SSP0-Codec", - .id = 1, - .no_pcm = 1, - .init = da7219_codec_init, - .ignore_pmdown_time = 1, - .dpcm_playback = 1, - .dpcm_capture = 1, - SND_SOC_DAILINK_REG(ssp0_pin, ssp0_codec, platform), - }, - { - .name = "dmic01", - .id = 2, - .ignore_suspend = 1, - .dpcm_capture = 1, - .no_pcm = 1, - SND_SOC_DAILINK_REG(dmic_pin, dmic_codec, platform), - }, - { - .name = "iDisp1", - .id = 3, - .init = hdmi_init, - .dpcm_playback = 1, - .no_pcm = 1, - SND_SOC_DAILINK_REG(idisp1_pin, idisp1_codec, platform), - }, - { - .name = "iDisp2", - .id = 4, - .init = hdmi_init, - .dpcm_playback = 1, - .no_pcm = 1, - SND_SOC_DAILINK_REG(idisp2_pin, idisp2_codec, platform), - }, - { - .name = "iDisp3", - .id = 5, - .init = hdmi_init, - .dpcm_playback = 1, - .no_pcm = 1, - SND_SOC_DAILINK_REG(idisp3_pin, idisp3_codec, platform), - }, - { - .name = "dmic16k", - .id = 6, - .ignore_suspend = 1, - .dpcm_capture = 1, - .no_pcm = 1, - SND_SOC_DAILINK_REG(dmic16k_pin, dmic_codec, platform), - } -}; - -static struct snd_soc_dai_link adl_dais[] = { - /* Back End DAI links */ - { - .name = "SSP0-Codec", - .id = 0, - .no_pcm = 1, - .init = da7219_codec_init, - .ignore_pmdown_time = 1, - .dpcm_playback = 1, - .dpcm_capture = 1, - SND_SOC_DAILINK_REG(ssp0_pin, ssp0_codec, platform), - }, - { - .name = "dmic01", - .id = 1, - .ignore_suspend = 1, - .dpcm_capture = 1, - .no_pcm = 1, - SND_SOC_DAILINK_REG(dmic_pin, dmic_codec, platform), - }, - { - .name = "dmic16k", - .id = 2, - .ignore_suspend = 1, - .dpcm_capture = 1, - .no_pcm = 1, - SND_SOC_DAILINK_REG(dmic16k_pin, dmic_codec, platform), - }, - { - .name = "iDisp1", - .id = 3, - .init = hdmi_init, - .dpcm_playback = 1, - .no_pcm = 1, - SND_SOC_DAILINK_REG(idisp1_pin, idisp1_codec, platform), - }, - { - .name = "iDisp2", - .id = 4, - .init = hdmi_init, - .dpcm_playback = 1, - .no_pcm = 1, - SND_SOC_DAILINK_REG(idisp2_pin, idisp2_codec, platform), - }, - { - .name = "iDisp3", - .id = 5, - .init = hdmi_init, - .dpcm_playback = 1, - .no_pcm = 1, - SND_SOC_DAILINK_REG(idisp3_pin, idisp3_codec, platform), - }, - { - .name = "iDisp4", - .id = 6, - .init = hdmi_init, - .dpcm_playback = 1, - .no_pcm = 1, - SND_SOC_DAILINK_REG(idisp4_pin, idisp4_codec, platform), - }, - { - .name = "SSP1-Codec", - .id = 7, - .no_pcm = 1, - .dpcm_playback = 1, - /* feedback stream or firmware-generated echo reference */ - .dpcm_capture = 1, - SND_SOC_DAILINK_REG(ssp1_pin, max_98373_components, platform), - }, - { - .name = "SSP2-BT", - .id = 8, - .no_pcm = 1, - .dpcm_playback = 1, - .dpcm_capture = 1, - SND_SOC_DAILINK_REG(ssp2_pin, dummy_codec, platform), - }, -}; - static struct snd_soc_card card_da7219 = { .name = "da7219", /* the sof- prefix is added by the core */ .owner = THIS_MODULE, @@ -444,28 +219,100 @@ static struct snd_soc_card card_da7219 = { .late_probe = card_late_probe, }; +static struct snd_soc_dai_link_component da7219_component[] = { + { + .name = "i2c-DLGS7219:00", + .dai_name = DIALOG_CODEC_DAI, + } +}; + +static int +sof_card_dai_links_create(struct device *dev, struct snd_soc_card *card, + struct sof_card_private *ctx) +{ + int ret; + + ret = sof_intel_board_set_dai_link(dev, card, ctx); + if (ret) + return ret; + + if (!ctx->codec_link) { + dev_err(dev, "codec link not available"); + return -EINVAL; + } + + /* codec-specific fields for headphone codec */ + ctx->codec_link->codecs = da7219_component; + ctx->codec_link->num_codecs = ARRAY_SIZE(da7219_component); + ctx->codec_link->init = da7219_codec_init; + + if (ctx->amp_type == CODEC_NONE) + return 0; + + if (!ctx->amp_link) { + dev_err(dev, "amp link not available"); + return -EINVAL; + } + + /* codec-specific fields for speaker amplifier */ + switch (ctx->amp_type) { + case CODEC_MAX98360A: + max_98360a_dai_link(ctx->amp_link); + break; + case CODEC_MAX98373: + ctx->amp_link->codecs = max_98373_components; + ctx->amp_link->num_codecs = ARRAY_SIZE(max_98373_components); + ctx->amp_link->init = max_98373_spk_codec_init; + if (ctx->da7219.is_jsl_board) { + ctx->amp_link->ops = &max98373_ops; /* use local ops */ + } else { + /* TBD: implement the amp for later platform */ + dev_err(dev, "max98373 not support yet\n"); + return -EINVAL; + } + break; + default: + dev_err(dev, "invalid amp type %d\n", ctx->amp_type); + return -EINVAL; + } + + return 0; +} + +#define JSL_LINK_ORDER SOF_LINK_ORDER(SOF_LINK_AMP, \ + SOF_LINK_CODEC, \ + SOF_LINK_DMIC01, \ + SOF_LINK_IDISP_HDMI, \ + SOF_LINK_DMIC16K, \ + SOF_LINK_NONE, \ + SOF_LINK_NONE) + static int audio_probe(struct platform_device *pdev) { struct snd_soc_acpi_mach *mach = pdev->dev.platform_data; - struct snd_soc_dai_link *dai_links; - struct card_private *ctx; + struct sof_card_private *ctx; unsigned long board_quirk = 0; - int ret, amp_idx; - - ctx = devm_kzalloc(&pdev->dev, sizeof(*ctx), GFP_KERNEL); - if (!ctx) - return -ENOMEM; + int ret; if (pdev->id_entry && pdev->id_entry->driver_data) board_quirk = (unsigned long)pdev->id_entry->driver_data; - ctx->codec_type = sof_ssp_detect_codec_type(&pdev->dev); - ctx->amp_type = sof_ssp_detect_amp_type(&pdev->dev); + dev_dbg(&pdev->dev, "board_quirk = %lx\n", board_quirk); + + /* initialize ctx with board quirk */ + ctx = sof_intel_board_get_ctx(&pdev->dev, board_quirk); + if (!ctx) + return -ENOMEM; if (mach->mach_params.codec_mask & IDISP_CODEC_MASK) ctx->hdmi.idisp_codec = true; if (board_quirk & SOF_DA7219_JSL_BOARD) { + ctx->da7219.is_jsl_board = true; + + /* overwrite the DAI link order for JSL boards */ + ctx->link_order_overwrite = JSL_LINK_ORDER; + /* backward-compatible with existing devices */ switch (ctx->amp_type) { case CODEC_MAX98360A: @@ -480,46 +327,27 @@ static int audio_probe(struct platform_device *pdev) default: break; } - - dai_links = jsl_dais; - amp_idx = 0; - - card_da7219.num_links = ARRAY_SIZE(jsl_dais); - } else { - dai_links = adl_dais; - amp_idx = 7; - - card_da7219.num_links = ARRAY_SIZE(adl_dais); } - dev_dbg(&pdev->dev, "board_quirk = %lx\n", board_quirk); + /* update dai_link */ + ret = sof_card_dai_links_create(&pdev->dev, &card_da7219, ctx); + if (ret) + return ret; - /* speaker amp */ + /* update codec_conf */ switch (ctx->amp_type) { - case CODEC_MAX98360A: - max_98360a_dai_link(&dai_links[amp_idx]); - break; case CODEC_MAX98373: - dai_links[amp_idx].codecs = max_98373_components; - dai_links[amp_idx].num_codecs = ARRAY_SIZE(max_98373_components); - dai_links[amp_idx].init = max_98373_spk_codec_init; - if (board_quirk & SOF_DA7219_JSL_BOARD) { - dai_links[amp_idx].ops = &max98373_ops; /* use local ops */ - } else { - /* TBD: implement the amp for later platform */ - dev_err(&pdev->dev, "max98373 not support yet\n"); - return -EINVAL; - } - max_98373_set_codec_conf(&card_da7219); break; + case CODEC_MAX98360A: + case CODEC_NONE: + /* no codec conf required */ + break; default: dev_err(&pdev->dev, "invalid amp type %d\n", ctx->amp_type); return -EINVAL; } - card_da7219.dai_link = dai_links; - card_da7219.dev = &pdev->dev; ret = snd_soc_fixup_dai_links_platform_name(&card_da7219, @@ -535,19 +363,31 @@ static int audio_probe(struct platform_device *pdev) static const struct platform_device_id board_ids[] = { { .name = "jsl_mx98373_da7219", - .driver_data = (kernel_ulong_t)(SOF_DA7219_JSL_BOARD), + .driver_data = (kernel_ulong_t)(SOF_DA7219_JSL_BOARD | + SOF_SSP_PORT_CODEC(0) | + SOF_SSP_PORT_AMP(1)), }, { .name = "jsl_mx98360_da7219", - .driver_data = (kernel_ulong_t)(SOF_DA7219_JSL_BOARD), + .driver_data = (kernel_ulong_t)(SOF_DA7219_JSL_BOARD | + SOF_SSP_PORT_CODEC(0) | + SOF_SSP_PORT_AMP(1)), }, { .name = "adl_mx98360_da7219", - /* no quirk needed for this board */ + .driver_data = (kernel_ulong_t)(SOF_SSP_PORT_CODEC(0) | + SOF_SSP_PORT_AMP(1) | + SOF_NUM_IDISP_HDMI(4) | + SOF_SSP_PORT_BT_OFFLOAD(2) | + SOF_BT_OFFLOAD_PRESENT), }, { .name = "rpl_mx98360_da7219", - /* no quirk needed for this board */ + .driver_data = (kernel_ulong_t)(SOF_SSP_PORT_CODEC(0) | + SOF_SSP_PORT_AMP(1) | + SOF_NUM_IDISP_HDMI(4) | + SOF_SSP_PORT_BT_OFFLOAD(2) | + SOF_BT_OFFLOAD_PRESENT), }, { } }; @@ -568,6 +408,5 @@ MODULE_DESCRIPTION("ASoC Intel(R) SOF Machine driver for Dialog codec"); MODULE_AUTHOR("Yong Zhi "); MODULE_AUTHOR("Brent Lu "); MODULE_LICENSE("GPL v2"); -MODULE_IMPORT_NS(SND_SOC_INTEL_HDA_DSP_COMMON); +MODULE_IMPORT_NS(SND_SOC_INTEL_SOF_BOARD_HELPERS); MODULE_IMPORT_NS(SND_SOC_INTEL_SOF_MAXIM_COMMON); -MODULE_IMPORT_NS(SND_SOC_INTEL_SOF_SSP_COMMON); -- cgit v1.2.3 From a7963f6ecc4be8a331d7740cb276651f2045e92c Mon Sep 17 00:00:00 2001 From: Brent Lu Date: Mon, 25 Mar 2024 17:10:51 -0500 Subject: ASoC: Intel: sof_da7219: add codec exit function Add exit function to headphone codec dai link. Reviewed-by: Bard Liao Signed-off-by: Brent Lu Signed-off-by: Pierre-Louis Bossart Link: https://msgid.link/r/20240325221059.206042-14-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/intel/boards/sof_da7219.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/sound/soc/intel/boards/sof_da7219.c b/sound/soc/intel/boards/sof_da7219.c index f0cb1572c6c4..3d9c48107f58 100644 --- a/sound/soc/intel/boards/sof_da7219.c +++ b/sound/soc/intel/boards/sof_da7219.c @@ -167,6 +167,13 @@ static int da7219_codec_init(struct snd_soc_pcm_runtime *rtd) return ret; } +static void da7219_codec_exit(struct snd_soc_pcm_runtime *rtd) +{ + struct snd_soc_component *component = snd_soc_rtd_to_codec(rtd, 0)->component; + + snd_soc_component_set_jack(component, NULL, NULL); +} + static int max98373_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { @@ -245,6 +252,7 @@ sof_card_dai_links_create(struct device *dev, struct snd_soc_card *card, ctx->codec_link->codecs = da7219_component; ctx->codec_link->num_codecs = ARRAY_SIZE(da7219_component); ctx->codec_link->init = da7219_codec_init; + ctx->codec_link->exit = da7219_codec_exit; if (ctx->amp_type == CODEC_NONE) return 0; -- cgit v1.2.3 From ed61b2ef5aa0036ef1dc593c191e762386a92cc5 Mon Sep 17 00:00:00 2001 From: Brent Lu Date: Mon, 25 Mar 2024 17:10:52 -0500 Subject: ASoC: Intel: sof_da7219: add SOF_DA7219_MCLK_EN quirk PLL bypass mode requires mclk to be present. However, mclk pin is not connected in JSL boards. Here we add the SOF_DA7219_MCLK_EN quirk to improve driver readability. Reviewed-by: Bard Liao Signed-off-by: Brent Lu Signed-off-by: Pierre-Louis Bossart Link: https://msgid.link/r/20240325221059.206042-15-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/intel/boards/sof_board_helpers.h | 2 ++ sound/soc/intel/boards/sof_da7219.c | 13 ++++++++++--- 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/sound/soc/intel/boards/sof_board_helpers.h b/sound/soc/intel/boards/sof_board_helpers.h index 1701481ab6ae..2f27ad8726f8 100644 --- a/sound/soc/intel/boards/sof_board_helpers.h +++ b/sound/soc/intel/boards/sof_board_helpers.h @@ -87,10 +87,12 @@ enum { * sof_da7219_private: private data for da7219 machine driver * * @is_jsl_board: true for JSL boards + * @mclk_en: true for mclk pin is connected * @pll_bypass: true for PLL bypass mode */ struct sof_da7219_private { bool is_jsl_board; + bool mclk_en; bool pll_bypass; }; diff --git a/sound/soc/intel/boards/sof_da7219.c b/sound/soc/intel/boards/sof_da7219.c index 3d9c48107f58..4417e2b7adfd 100644 --- a/sound/soc/intel/boards/sof_da7219.c +++ b/sound/soc/intel/boards/sof_da7219.c @@ -20,6 +20,7 @@ /* Driver-specific board quirks: from bit 0 to 7 */ #define SOF_DA7219_JSL_BOARD BIT(0) +#define SOF_DA7219_MCLK_EN BIT(1) #define DIALOG_CODEC_DAI "da7219-hifi" @@ -126,7 +127,8 @@ static int da7219_codec_init(struct snd_soc_pcm_runtime *rtd) * Use PLL bypass mode if MCLK is available, be sure to set the * frequency of MCLK to 12.288 or 24.576MHz on topology side. */ - if (mclk_rate == 12288000 || mclk_rate == 24576000) { + if (ctx->da7219.mclk_en && + (mclk_rate == 12288000 || mclk_rate == 24576000)) { /* PLL bypass mode */ dev_dbg(rtd->dev, "pll bypass mode, mclk rate %d\n", mclk_rate); @@ -337,6 +339,9 @@ static int audio_probe(struct platform_device *pdev) } } + if (board_quirk & SOF_DA7219_MCLK_EN) + ctx->da7219.mclk_en = true; + /* update dai_link */ ret = sof_card_dai_links_create(&pdev->dev, &card_da7219, ctx); if (ret) @@ -383,7 +388,8 @@ static const struct platform_device_id board_ids[] = { }, { .name = "adl_mx98360_da7219", - .driver_data = (kernel_ulong_t)(SOF_SSP_PORT_CODEC(0) | + .driver_data = (kernel_ulong_t)(SOF_DA7219_MCLK_EN | + SOF_SSP_PORT_CODEC(0) | SOF_SSP_PORT_AMP(1) | SOF_NUM_IDISP_HDMI(4) | SOF_SSP_PORT_BT_OFFLOAD(2) | @@ -391,7 +397,8 @@ static const struct platform_device_id board_ids[] = { }, { .name = "rpl_mx98360_da7219", - .driver_data = (kernel_ulong_t)(SOF_SSP_PORT_CODEC(0) | + .driver_data = (kernel_ulong_t)(SOF_DA7219_MCLK_EN | + SOF_SSP_PORT_CODEC(0) | SOF_SSP_PORT_AMP(1) | SOF_NUM_IDISP_HDMI(4) | SOF_SSP_PORT_BT_OFFLOAD(2) | -- cgit v1.2.3 From 45728dc6df48118b4e49f5abac4de87935bfc255 Mon Sep 17 00:00:00 2001 From: Brent Lu Date: Mon, 25 Mar 2024 17:10:53 -0500 Subject: ASoC: Intel: sof_da7219: board id cleanup for jsl boards Introduce "jsl_da7219_def" board to reduce the number of jsl board configs. This config could support all boards which implement headphone codec on SSP0 and speaker amplifiers on SSP1. Reviewed-by: Bard Liao Signed-off-by: Brent Lu Signed-off-by: Pierre-Louis Bossart Link: https://msgid.link/r/20240325221059.206042-16-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/intel/boards/sof_da7219.c | 8 +------- sound/soc/intel/common/soc-acpi-intel-jsl-match.c | 4 ++-- 2 files changed, 3 insertions(+), 9 deletions(-) diff --git a/sound/soc/intel/boards/sof_da7219.c b/sound/soc/intel/boards/sof_da7219.c index 4417e2b7adfd..3057798a0dca 100644 --- a/sound/soc/intel/boards/sof_da7219.c +++ b/sound/soc/intel/boards/sof_da7219.c @@ -375,13 +375,7 @@ static int audio_probe(struct platform_device *pdev) static const struct platform_device_id board_ids[] = { { - .name = "jsl_mx98373_da7219", - .driver_data = (kernel_ulong_t)(SOF_DA7219_JSL_BOARD | - SOF_SSP_PORT_CODEC(0) | - SOF_SSP_PORT_AMP(1)), - }, - { - .name = "jsl_mx98360_da7219", + .name = "jsl_da7219_def", .driver_data = (kernel_ulong_t)(SOF_DA7219_JSL_BOARD | SOF_SSP_PORT_CODEC(0) | SOF_SSP_PORT_AMP(1)), diff --git a/sound/soc/intel/common/soc-acpi-intel-jsl-match.c b/sound/soc/intel/common/soc-acpi-intel-jsl-match.c index a6ac2525df17..d4b397c53bcc 100644 --- a/sound/soc/intel/common/soc-acpi-intel-jsl-match.c +++ b/sound/soc/intel/common/soc-acpi-intel-jsl-match.c @@ -52,14 +52,14 @@ static const struct snd_soc_acpi_codecs rt5682_rt5682s_hp = { struct snd_soc_acpi_mach snd_soc_acpi_intel_jsl_machines[] = { { .id = "DLGS7219", - .drv_name = "jsl_mx98373_da7219", + .drv_name = "jsl_da7219_def", .machine_quirk = snd_soc_acpi_codec_list, .quirk_data = &mx98373_spk, .sof_tplg_filename = "sof-jsl-da7219.tplg", }, { .id = "DLGS7219", - .drv_name = "jsl_mx98360_da7219", + .drv_name = "jsl_da7219_def", .machine_quirk = snd_soc_acpi_codec_list, .quirk_data = &mx98360a_spk, .sof_tplg_filename = "sof-jsl-da7219-mx98360a.tplg", -- cgit v1.2.3 From ef771be889f0e5e036ff54e4f0178b6eba177d56 Mon Sep 17 00:00:00 2001 From: Brent Lu Date: Mon, 25 Mar 2024 17:10:54 -0500 Subject: ASoC: Intel: sof_da7219: board id cleanup for adl boards Introduce "adl_da7219_def" board to reduce the number of jsl board configs. This config could support all boards which implement headphone codec on SSP0 and speaker amplifiers on SSP1. Reviewed-by: Bard Liao Signed-off-by: Brent Lu Signed-off-by: Pierre-Louis Bossart Link: https://msgid.link/r/20240325221059.206042-17-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/intel/boards/sof_da7219.c | 2 +- sound/soc/intel/common/soc-acpi-intel-adl-match.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/soc/intel/boards/sof_da7219.c b/sound/soc/intel/boards/sof_da7219.c index 3057798a0dca..0da7aa2e31c2 100644 --- a/sound/soc/intel/boards/sof_da7219.c +++ b/sound/soc/intel/boards/sof_da7219.c @@ -381,7 +381,7 @@ static const struct platform_device_id board_ids[] = { SOF_SSP_PORT_AMP(1)), }, { - .name = "adl_mx98360_da7219", + .name = "adl_da7219_def", .driver_data = (kernel_ulong_t)(SOF_DA7219_MCLK_EN | SOF_SSP_PORT_CODEC(0) | SOF_SSP_PORT_AMP(1) | diff --git a/sound/soc/intel/common/soc-acpi-intel-adl-match.c b/sound/soc/intel/common/soc-acpi-intel-adl-match.c index 0da79a3ba1f0..6c710e9a26f1 100644 --- a/sound/soc/intel/common/soc-acpi-intel-adl-match.c +++ b/sound/soc/intel/common/soc-acpi-intel-adl-match.c @@ -616,7 +616,7 @@ struct snd_soc_acpi_mach snd_soc_acpi_intel_adl_machines[] = { }, { .id = "DLGS7219", - .drv_name = "adl_mx98360_da7219", + .drv_name = "adl_da7219_def", .machine_quirk = snd_soc_acpi_codec_list, .quirk_data = &adl_max98360a_amp, .sof_tplg_filename = "sof-adl-max98360a-da7219.tplg", -- cgit v1.2.3 From 9ca54c3356f488e7800b6bcdbccb1f6de90e1621 Mon Sep 17 00:00:00 2001 From: Brent Lu Date: Mon, 25 Mar 2024 17:10:55 -0500 Subject: ASoC: Intel: sof_da7219: board id cleanup for rpl boards Introduce "rpl_da7219_def" board to reduce the number of rpl board configs. This config could support all boards which implement headphone codec on SSP0 and speaker amplifiers on SSP1. Reviewed-by: Bard Liao Signed-off-by: Brent Lu Signed-off-by: Pierre-Louis Bossart Link: https://msgid.link/r/20240325221059.206042-18-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/intel/boards/sof_da7219.c | 2 +- sound/soc/intel/common/soc-acpi-intel-rpl-match.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/soc/intel/boards/sof_da7219.c b/sound/soc/intel/boards/sof_da7219.c index 0da7aa2e31c2..fd3a7be993c1 100644 --- a/sound/soc/intel/boards/sof_da7219.c +++ b/sound/soc/intel/boards/sof_da7219.c @@ -390,7 +390,7 @@ static const struct platform_device_id board_ids[] = { SOF_BT_OFFLOAD_PRESENT), }, { - .name = "rpl_mx98360_da7219", + .name = "rpl_da7219_def", .driver_data = (kernel_ulong_t)(SOF_DA7219_MCLK_EN | SOF_SSP_PORT_CODEC(0) | SOF_SSP_PORT_AMP(1) | diff --git a/sound/soc/intel/common/soc-acpi-intel-rpl-match.c b/sound/soc/intel/common/soc-acpi-intel-rpl-match.c index c43e537e60d2..77c917897c8d 100644 --- a/sound/soc/intel/common/soc-acpi-intel-rpl-match.c +++ b/sound/soc/intel/common/soc-acpi-intel-rpl-match.c @@ -457,7 +457,7 @@ struct snd_soc_acpi_mach snd_soc_acpi_intel_rpl_machines[] = { }, { .id = "DLGS7219", - .drv_name = "rpl_mx98360_da7219", + .drv_name = "rpl_da7219_def", .machine_quirk = snd_soc_acpi_codec_list, .quirk_data = &rpl_max98360a_amp, .sof_tplg_filename = "sof-rpl-max98360a-da7219.tplg", -- cgit v1.2.3 From b497654f1d3d95c37c8f2c6950047e022be04a2e Mon Sep 17 00:00:00 2001 From: Brent Lu Date: Mon, 25 Mar 2024 17:10:56 -0500 Subject: ASoC: Intel: sof_rt5682: remove unnecessary idisp HDMI quirk Remove SOF_NUM_IDISP_HDMI(3) from board quirks since the value is 3 if not defined. Reviewed-by: Pierre-Louis Bossart Signed-off-by: Brent Lu Signed-off-by: Pierre-Louis Bossart Link: https://msgid.link/r/20240325221059.206042-19-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/intel/boards/sof_rt5682.c | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/sound/soc/intel/boards/sof_rt5682.c b/sound/soc/intel/boards/sof_rt5682.c index 672636f07456..f80fdbd8fdac 100644 --- a/sound/soc/intel/boards/sof_rt5682.c +++ b/sound/soc/intel/boards/sof_rt5682.c @@ -139,7 +139,6 @@ static const struct dmi_system_id sof_rt5682_quirk_table[] = { .driver_data = (void *)(SOF_RT5682_MCLK_EN | SOF_SSP_PORT_CODEC(2) | SOF_SSP_PORT_AMP(0) | - SOF_NUM_IDISP_HDMI(3) | SOF_SSP_PORT_BT_OFFLOAD(1) | SOF_BT_OFFLOAD_PRESENT ), @@ -692,11 +691,11 @@ static int sof_audio_probe(struct platform_device *pdev) case CODEC_RT1015P: sof_rt1015p_codec_conf(&sof_audio_card_rt5682); break; - case CODEC_NONE: case CODEC_MAX98357A: case CODEC_MAX98360A: case CODEC_RT1019P: case CODEC_RT5650: + case CODEC_NONE: /* no codec conf required */ break; default: @@ -763,7 +762,6 @@ static const struct platform_device_id board_ids[] = { .name = "adl_rt5682_c1_h02", .driver_data = (kernel_ulong_t)(SOF_RT5682_MCLK_EN | SOF_SSP_PORT_CODEC(1) | - SOF_NUM_IDISP_HDMI(3) | /* SSP 0 and SSP 2 are used for HDMI IN */ SOF_SSP_MASK_HDMI_CAPTURE(0x5)), }, @@ -787,7 +785,6 @@ static const struct platform_device_id board_ids[] = { .name = "rpl_rt5682_c1_h02", .driver_data = (kernel_ulong_t)(SOF_RT5682_MCLK_EN | SOF_SSP_PORT_CODEC(1) | - SOF_NUM_IDISP_HDMI(3) | /* SSP 0 and SSP 2 are used for HDMI IN */ SOF_SSP_MASK_HDMI_CAPTURE(0x5)), }, @@ -796,7 +793,6 @@ static const struct platform_device_id board_ids[] = { .driver_data = (kernel_ulong_t)(SOF_RT5682_MCLK_EN | SOF_SSP_PORT_CODEC(0) | SOF_SSP_PORT_AMP(1) | - SOF_NUM_IDISP_HDMI(3) | SOF_SSP_PORT_BT_OFFLOAD(2) | SOF_BT_OFFLOAD_PRESENT), }, @@ -804,15 +800,13 @@ static const struct platform_device_id board_ids[] = { .name = "mtl_mx98360_rt5682", .driver_data = (kernel_ulong_t)(SOF_RT5682_MCLK_EN | SOF_SSP_PORT_CODEC(0) | - SOF_SSP_PORT_AMP(1) | - SOF_NUM_IDISP_HDMI(3)), + SOF_SSP_PORT_AMP(1)), }, { .name = "mtl_rt5682_def", .driver_data = (kernel_ulong_t)(SOF_RT5682_MCLK_EN | SOF_SSP_PORT_CODEC(2) | SOF_SSP_PORT_AMP(0) | - SOF_NUM_IDISP_HDMI(3) | SOF_SSP_PORT_BT_OFFLOAD(1) | SOF_BT_OFFLOAD_PRESENT), }, -- cgit v1.2.3 From 16e5700644bda0d236288f17fd68b15a1e2e6f2c Mon Sep 17 00:00:00 2001 From: Brent Lu Date: Mon, 25 Mar 2024 17:10:57 -0500 Subject: ASoC: Intel: sof_ssp_amp: remove unnecessary idisp HDMI quirk Remove SOF_NUM_IDISP_HDMI(3) from board quirks since the value is 3 if not defined. Reviewed-by: Bard Liao Signed-off-by: Brent Lu Signed-off-by: Pierre-Louis Bossart Link: https://msgid.link/r/20240325221059.206042-20-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/intel/boards/sof_ssp_amp.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/sound/soc/intel/boards/sof_ssp_amp.c b/sound/soc/intel/boards/sof_ssp_amp.c index b99af8bc4ccc..206c9b723805 100644 --- a/sound/soc/intel/boards/sof_ssp_amp.c +++ b/sound/soc/intel/boards/sof_ssp_amp.c @@ -152,8 +152,8 @@ static int sof_ssp_amp_probe(struct platform_device *pdev) case CODEC_CS35L41: cs35l41_set_codec_conf(&sof_ssp_amp_card); break; - case CODEC_NONE: case CODEC_RT1308: + case CODEC_NONE: /* no codec conf required */ break; default: @@ -196,21 +196,18 @@ static const struct platform_device_id board_ids[] = { .name = "adl_lt6911_hdmi_ssp", .driver_data = (kernel_ulong_t)(SOF_SSP_MASK_HDMI_CAPTURE(0x5) | /* SSP 0 and SSP 2 are used for HDMI IN */ - SOF_NUM_IDISP_HDMI(3) | SOF_HDMI_PLAYBACK_PRESENT), }, { .name = "rpl_lt6911_hdmi_ssp", .driver_data = (kernel_ulong_t)(SOF_SSP_MASK_HDMI_CAPTURE(0x5) | /* SSP 0 and SSP 2 are used for HDMI IN */ - SOF_NUM_IDISP_HDMI(3) | SOF_HDMI_PLAYBACK_PRESENT), }, { .name = "mtl_lt6911_hdmi_ssp", .driver_data = (kernel_ulong_t)(SOF_SSP_MASK_HDMI_CAPTURE(0x5) | /* SSP 0 and SSP 2 are used for HDMI IN */ - SOF_NUM_IDISP_HDMI(3) | SOF_HDMI_PLAYBACK_PRESENT), }, { } -- cgit v1.2.3 From 2b384bcd2cb727edb5647692134f4eec2f0a32ae Mon Sep 17 00:00:00 2001 From: Brent Lu Date: Mon, 25 Mar 2024 17:10:58 -0500 Subject: ASoC: Intel: sof_nau8825: remove sof_nau8825 board id Remove sof_nau8825 board id and use adl_nau8825_def instead since SSP port assignment is the same. Reviewed-by: Bard Liao Signed-off-by: Brent Lu Signed-off-by: Pierre-Louis Bossart Link: https://msgid.link/r/20240325221059.206042-21-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/intel/boards/sof_nau8825.c | 10 +--------- sound/soc/intel/common/soc-acpi-intel-adl-match.c | 2 +- 2 files changed, 2 insertions(+), 10 deletions(-) diff --git a/sound/soc/intel/boards/sof_nau8825.c b/sound/soc/intel/boards/sof_nau8825.c index b9db6e236a93..23fe8b4015cc 100644 --- a/sound/soc/intel/boards/sof_nau8825.c +++ b/sound/soc/intel/boards/sof_nau8825.c @@ -271,10 +271,10 @@ static int sof_audio_probe(struct platform_device *pdev) case CODEC_RT1015P: sof_rt1015p_codec_conf(&sof_audio_card_nau8825); break; - case CODEC_NONE: case CODEC_MAX98360A: case CODEC_NAU8318: case CODEC_RT1019P: + case CODEC_NONE: /* no codec conf required */ break; default: @@ -297,14 +297,6 @@ static int sof_audio_probe(struct platform_device *pdev) } static const struct platform_device_id board_ids[] = { - { - .name = "sof_nau8825", - .driver_data = (kernel_ulong_t)(SOF_SSP_PORT_CODEC(0) | - SOF_NUM_IDISP_HDMI(4) | - SOF_SSP_PORT_BT_OFFLOAD(2) | - SOF_BT_OFFLOAD_PRESENT), - - }, { .name = "adl_rt1019p_8825", .driver_data = (kernel_ulong_t)(SOF_SSP_PORT_CODEC(0) | diff --git a/sound/soc/intel/common/soc-acpi-intel-adl-match.c b/sound/soc/intel/common/soc-acpi-intel-adl-match.c index 6c710e9a26f1..7ce8aade07d7 100644 --- a/sound/soc/intel/common/soc-acpi-intel-adl-match.c +++ b/sound/soc/intel/common/soc-acpi-intel-adl-match.c @@ -563,7 +563,7 @@ struct snd_soc_acpi_mach snd_soc_acpi_intel_adl_machines[] = { }, { .id = "10508825", - .drv_name = "sof_nau8825", + .drv_name = "adl_nau8825_def", .sof_tplg_filename = "sof-adl-nau8825.tplg", }, { -- cgit v1.2.3 From 61cafaeab5bca2d3e6a68ee8fa92b5c10b8610ca Mon Sep 17 00:00:00 2001 From: Brent Lu Date: Mon, 25 Mar 2024 17:10:59 -0500 Subject: ASoC: Intel: sof_rt5682: board id cleanup for cml boards Introduce "cml_rt5682_def" for cml boards which implement headphone codec on SSP0 and speaker amplifiers on SSP1. Reviewed-by: Bard Liao Signed-off-by: Brent Lu Signed-off-by: Pierre-Louis Bossart Link: https://msgid.link/r/20240325221059.206042-22-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/intel/boards/sof_rt5682.c | 2 +- sound/soc/intel/common/soc-acpi-intel-cml-match.c | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/sound/soc/intel/boards/sof_rt5682.c b/sound/soc/intel/boards/sof_rt5682.c index f80fdbd8fdac..aadd341a202c 100644 --- a/sound/soc/intel/boards/sof_rt5682.c +++ b/sound/soc/intel/boards/sof_rt5682.c @@ -722,7 +722,7 @@ static const struct platform_device_id board_ids[] = { .name = "sof_rt5682", }, { - .name = "cml_rt1015_rt5682", + .name = "cml_rt5682_def", .driver_data = (kernel_ulong_t)(SOF_RT5682_MCLK_EN | SOF_SSP_PORT_CODEC(0) | SOF_SSP_PORT_AMP(1)), diff --git a/sound/soc/intel/common/soc-acpi-intel-cml-match.c b/sound/soc/intel/common/soc-acpi-intel-cml-match.c index 5eab17820532..d47a548959ea 100644 --- a/sound/soc/intel/common/soc-acpi-intel-cml-match.c +++ b/sound/soc/intel/common/soc-acpi-intel-cml-match.c @@ -49,21 +49,21 @@ struct snd_soc_acpi_mach snd_soc_acpi_intel_cml_machines[] = { }, { .id = "10EC5682", - .drv_name = "cml_rt1015_rt5682", + .drv_name = "cml_rt5682_def", .machine_quirk = snd_soc_acpi_codec_list, .quirk_data = &rt1015_spk_codecs, .sof_tplg_filename = "sof-cml-rt1011-rt5682.tplg", }, { .id = "10EC5682", - .drv_name = "sof_rt5682", + .drv_name = "cml_rt5682_def", .machine_quirk = snd_soc_acpi_codec_list, .quirk_data = &max98357a_spk_codecs, .sof_tplg_filename = "sof-cml-rt5682-max98357a.tplg", }, { .id = "10EC5682", - .drv_name = "sof_rt5682", + .drv_name = "cml_rt5682_def", .sof_tplg_filename = "sof-cml-rt5682.tplg", }, { -- cgit v1.2.3 From 502892bbd2021fbe20f0d702b6b0bae281a742fa Mon Sep 17 00:00:00 2001 From: Irui Wang Date: Wed, 6 Mar 2024 10:12:23 +0800 Subject: media: mediatek: vcodec: Handle VP9 superframe bitstream with 8 sub-frames The VP9 bitstream uses superframes, which each contain 8 sub-frames, enable accessing the last superframe by increasing the range of the index vaidation as the maximum number of superframes is 8 and not 7, so that the last sub-frame can be decoded normally with the stateful VP9 decoder. Signed-off-by: Irui Wang Signed-off-by: Sebastian Fricke Signed-off-by: Hans Verkuil --- .../media/platform/mediatek/vcodec/decoder/vdec/vdec_vp9_if.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/drivers/media/platform/mediatek/vcodec/decoder/vdec/vdec_vp9_if.c b/drivers/media/platform/mediatek/vcodec/decoder/vdec/vdec_vp9_if.c index 55355fa70090..039082f600c8 100644 --- a/drivers/media/platform/mediatek/vcodec/decoder/vdec/vdec_vp9_if.c +++ b/drivers/media/platform/mediatek/vcodec/decoder/vdec/vdec_vp9_if.c @@ -16,6 +16,7 @@ #include "../vdec_drv_base.h" #include "../vdec_vpu_if.h" +#define VP9_MAX_SUPER_FRAMES_NUM 8 #define VP9_SUPER_FRAME_BS_SZ 64 #define MAX_VP9_DPB_SIZE 9 @@ -133,11 +134,11 @@ struct vp9_sf_ref_fb { */ struct vdec_vp9_vsi { unsigned char sf_bs_buf[VP9_SUPER_FRAME_BS_SZ]; - struct vp9_sf_ref_fb sf_ref_fb[VP9_MAX_FRM_BUF_NUM-1]; + struct vp9_sf_ref_fb sf_ref_fb[VP9_MAX_SUPER_FRAMES_NUM]; int sf_next_ref_fb_idx; unsigned int sf_frm_cnt; - unsigned int sf_frm_offset[VP9_MAX_FRM_BUF_NUM-1]; - unsigned int sf_frm_sz[VP9_MAX_FRM_BUF_NUM-1]; + unsigned int sf_frm_offset[VP9_MAX_SUPER_FRAMES_NUM]; + unsigned int sf_frm_sz[VP9_MAX_SUPER_FRAMES_NUM]; unsigned int sf_frm_idx; unsigned int sf_init; struct vdec_fb fb; @@ -526,7 +527,7 @@ static void vp9_swap_frm_bufs(struct vdec_vp9_inst *inst) /* if this super frame and it is not last sub-frame, get next fb for * sub-frame decode */ - if (vsi->sf_frm_cnt > 0 && vsi->sf_frm_idx != vsi->sf_frm_cnt - 1) + if (vsi->sf_frm_cnt > 0 && vsi->sf_frm_idx != vsi->sf_frm_cnt) vsi->sf_next_ref_fb_idx = vp9_get_sf_ref_fb(inst); } @@ -735,7 +736,7 @@ static void get_free_fb(struct vdec_vp9_inst *inst, struct vdec_fb **out_fb) static int validate_vsi_array_indexes(struct vdec_vp9_inst *inst, struct vdec_vp9_vsi *vsi) { - if (vsi->sf_frm_idx >= VP9_MAX_FRM_BUF_NUM - 1) { + if (vsi->sf_frm_idx > VP9_MAX_SUPER_FRAMES_NUM) { mtk_vdec_err(inst->ctx, "Invalid vsi->sf_frm_idx=%u.", vsi->sf_frm_idx); return -EIO; } -- cgit v1.2.3 From 97c75ee5de060d271d80109b0c47cb6008439e5b Mon Sep 17 00:00:00 2001 From: Nicolas Dufresne Date: Mon, 26 Feb 2024 16:19:52 -0500 Subject: media: mediatek: vcodec: Fix oops when HEVC init fails The stateless HEVC decoder saves the instance pointer in the context regardless if the initialization worked or not. This caused a use after free, when the pointer is freed in case of a failure in the deinit function. Only store the instance pointer when the initialization was successful, to solve this issue. Hardware name: Acer Tomato (rev3 - 4) board (DT) pstate: 80400009 (Nzcv daif +PAN -UAO -TCO -DIT -SSBS BTYPE=--) pc : vcodec_vpu_send_msg+0x4c/0x190 [mtk_vcodec_dec] lr : vcodec_send_ap_ipi+0x78/0x170 [mtk_vcodec_dec] sp : ffff80008750bc20 x29: ffff80008750bc20 x28: ffff1299f6d70000 x27: 0000000000000000 x26: 0000000000000000 x25: 0000000000000000 x24: 0000000000000000 x23: ffff80008750bc98 x22: 000000000000a003 x21: ffffd45c4cfae000 x20: 0000000000000010 x19: ffff1299fd668310 x18: 000000000000001a x17: 000000040044ffff x16: ffffd45cb15dc648 x15: 0000000000000000 x14: ffff1299c08da1c0 x13: ffffd45cb1f87a10 x12: ffffd45cb2f5fe80 x11: 0000000000000001 x10: 0000000000001b30 x9 : ffffd45c4d12b488 x8 : 1fffe25339380d81 x7 : 0000000000000001 x6 : ffff1299c9c06c00 x5 : 0000000000000132 x4 : 0000000000000000 x3 : 0000000000000000 x2 : 0000000000000010 x1 : ffff80008750bc98 x0 : 0000000000000000 Call trace: vcodec_vpu_send_msg+0x4c/0x190 [mtk_vcodec_dec] vcodec_send_ap_ipi+0x78/0x170 [mtk_vcodec_dec] vpu_dec_deinit+0x1c/0x30 [mtk_vcodec_dec] vdec_hevc_slice_deinit+0x30/0x98 [mtk_vcodec_dec] vdec_if_deinit+0x38/0x68 [mtk_vcodec_dec] mtk_vcodec_dec_release+0x20/0x40 [mtk_vcodec_dec] fops_vcodec_release+0x64/0x118 [mtk_vcodec_dec] v4l2_release+0x7c/0x100 __fput+0x80/0x2d8 __fput_sync+0x58/0x70 __arm64_sys_close+0x40/0x90 invoke_syscall+0x50/0x128 el0_svc_common.constprop.0+0x48/0xf0 do_el0_svc+0x24/0x38 el0_svc+0x38/0xd8 el0t_64_sync_handler+0xc0/0xc8 el0t_64_sync+0x1a8/0x1b0 Code: d503201f f9401660 b900127f b900227f (f9400400) Signed-off-by: Nicolas Dufresne Fixes: 2674486aac7d ("media: mediatek: vcodec: support stateless hevc decoder") Reviewed-by: AngeloGioacchino Del Regno Signed-off-by: Sebastian Fricke Signed-off-by: Hans Verkuil --- .../platform/mediatek/vcodec/decoder/vdec/vdec_hevc_req_multi_if.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/media/platform/mediatek/vcodec/decoder/vdec/vdec_hevc_req_multi_if.c b/drivers/media/platform/mediatek/vcodec/decoder/vdec/vdec_hevc_req_multi_if.c index 06ed47df693b..21836dd6ef85 100644 --- a/drivers/media/platform/mediatek/vcodec/decoder/vdec/vdec_hevc_req_multi_if.c +++ b/drivers/media/platform/mediatek/vcodec/decoder/vdec/vdec_hevc_req_multi_if.c @@ -869,7 +869,6 @@ static int vdec_hevc_slice_init(struct mtk_vcodec_dec_ctx *ctx) inst->vpu.codec_type = ctx->current_codec; inst->vpu.capture_type = ctx->capture_fourcc; - ctx->drv_handle = inst; err = vpu_dec_init(&inst->vpu); if (err) { mtk_vdec_err(ctx, "vdec_hevc init err=%d", err); @@ -898,6 +897,7 @@ static int vdec_hevc_slice_init(struct mtk_vcodec_dec_ctx *ctx) mtk_vdec_debug(ctx, "lat hevc instance >> %p, codec_type = 0x%x", inst, inst->vpu.codec_type); + ctx->drv_handle = inst; return 0; error_free_inst: kfree(inst); -- cgit v1.2.3 From 6467cda18c9f9b5f2f9a0aa1e2861c653e41f382 Mon Sep 17 00:00:00 2001 From: Yunfei Dong Date: Thu, 14 Mar 2024 20:30:08 +0800 Subject: media: mediatek: vcodec: adding lock to protect decoder context list Add a lock for the ctx_list, to avoid accessing a NULL pointer within the 'vpu_dec_ipi_handler' function when the ctx_list has been deleted due to an unexpected behavior on the SCP IP block. Hardware name: Google juniper sku16 board (DT) pstate: 20400005 (nzCv daif +PAN -UAO -TCO BTYPE=--) pc : vpu_dec_ipi_handler+0x58/0x1f8 [mtk_vcodec_dec] lr : scp_ipi_handler+0xd0/0x194 [mtk_scp] sp : ffffffc0131dbbd0 x29: ffffffc0131dbbd0 x28: 0000000000000000 x27: ffffff9bb277f348 x26: ffffff9bb242ad00 x25: ffffffd2d440d3b8 x24: ffffffd2a13ff1d4 x23: ffffff9bb7fe85a0 x22: ffffffc0133fbdb0 x21: 0000000000000010 x20: ffffff9b050ea328 x19: ffffffc0131dbc08 x18: 0000000000001000 x17: 0000000000000000 x16: ffffffd2d461c6e0 x15: 0000000000000242 x14: 000000000000018f x13: 000000000000004d x12: 0000000000000000 x11: 0000000000000001 x10: fffffffffffffff0 x9 : ffffff9bb6e793a8 x8 : 0000000000000000 x7 : 0000000000000000 x6 : 000000000000003f x5 : 0000000000000040 x4 : fffffffffffffff0 x3 : 0000000000000020 x2 : ffffff9bb6e79080 x1 : 0000000000000010 x0 : ffffffc0131dbc08 Call trace: vpu_dec_ipi_handler+0x58/0x1f8 [mtk_vcodec_dec (HASH:6c3f 2)] scp_ipi_handler+0xd0/0x194 [mtk_scp (HASH:7046 3)] mt8183_scp_irq_handler+0x44/0x88 [mtk_scp (HASH:7046 3)] scp_irq_handler+0x48/0x90 [mtk_scp (HASH:7046 3)] irq_thread_fn+0x38/0x94 irq_thread+0x100/0x1c0 kthread+0x140/0x1fc ret_from_fork+0x10/0x30 Code: 54000088 f94ca50a eb14015f 54000060 (f9400108) ---[ end trace ace43ce36cbd5c93 ]--- Kernel panic - not syncing: Oops: Fatal exception SMP: stopping secondary CPUs Kernel Offset: 0x12c4000000 from 0xffffffc010000000 PHYS_OFFSET: 0xffffffe580000000 CPU features: 0x08240002,2188200c Memory Limit: none Fixes: 655b86e52eac ("media: mediatek: vcodec: Fix possible invalid memory access for decoder") Signed-off-by: Yunfei Dong Reviewed-by: Nicolas Dufresne Reviewed-by: AngeloGioacchino Del Regno Signed-off-by: Sebastian Fricke Signed-off-by: Hans Verkuil --- drivers/media/platform/mediatek/vcodec/common/mtk_vcodec_fw_vpu.c | 4 ++-- drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec_drv.c | 5 +++++ drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec_drv.h | 2 ++ drivers/media/platform/mediatek/vcodec/decoder/vdec_vpu_if.c | 2 ++ 4 files changed, 11 insertions(+), 2 deletions(-) diff --git a/drivers/media/platform/mediatek/vcodec/common/mtk_vcodec_fw_vpu.c b/drivers/media/platform/mediatek/vcodec/common/mtk_vcodec_fw_vpu.c index 4c34344dc7dc..62cafe25fed9 100644 --- a/drivers/media/platform/mediatek/vcodec/common/mtk_vcodec_fw_vpu.c +++ b/drivers/media/platform/mediatek/vcodec/common/mtk_vcodec_fw_vpu.c @@ -50,12 +50,12 @@ static void mtk_vcodec_vpu_reset_dec_handler(void *priv) dev_err(&dev->plat_dev->dev, "Watchdog timeout!!"); - mutex_lock(&dev->dev_mutex); + mutex_lock(&dev->dev_ctx_lock); list_for_each_entry(ctx, &dev->ctx_list, list) { ctx->state = MTK_STATE_ABORT; mtk_v4l2_vdec_dbg(0, ctx, "[%d] Change to state MTK_STATE_ABORT", ctx->id); } - mutex_unlock(&dev->dev_mutex); + mutex_unlock(&dev->dev_ctx_lock); } static void mtk_vcodec_vpu_reset_enc_handler(void *priv) diff --git a/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec_drv.c b/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec_drv.c index f47c98faf068..2073781ccadb 100644 --- a/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec_drv.c +++ b/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec_drv.c @@ -268,7 +268,9 @@ static int fops_vcodec_open(struct file *file) ctx->dev->vdec_pdata->init_vdec_params(ctx); + mutex_lock(&dev->dev_ctx_lock); list_add(&ctx->list, &dev->ctx_list); + mutex_unlock(&dev->dev_ctx_lock); mtk_vcodec_dbgfs_create(ctx); mutex_unlock(&dev->dev_mutex); @@ -311,7 +313,9 @@ static int fops_vcodec_release(struct file *file) v4l2_ctrl_handler_free(&ctx->ctrl_hdl); mtk_vcodec_dbgfs_remove(dev, ctx->id); + mutex_lock(&dev->dev_ctx_lock); list_del_init(&ctx->list); + mutex_unlock(&dev->dev_ctx_lock); kfree(ctx); mutex_unlock(&dev->dev_mutex); return 0; @@ -404,6 +408,7 @@ static int mtk_vcodec_probe(struct platform_device *pdev) for (i = 0; i < MTK_VDEC_HW_MAX; i++) mutex_init(&dev->dec_mutex[i]); mutex_init(&dev->dev_mutex); + mutex_init(&dev->dev_ctx_lock); spin_lock_init(&dev->irqlock); snprintf(dev->v4l2_dev.name, sizeof(dev->v4l2_dev.name), "%s", diff --git a/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec_drv.h b/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec_drv.h index 849b89dd205c..85b2c0d3d8bc 100644 --- a/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec_drv.h +++ b/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec_drv.h @@ -241,6 +241,7 @@ struct mtk_vcodec_dec_ctx { * * @dec_mutex: decoder hardware lock * @dev_mutex: video_device lock + * @dev_ctx_lock: the lock of context list * @decode_workqueue: decode work queue * * @irqlock: protect data access by irq handler and work thread @@ -282,6 +283,7 @@ struct mtk_vcodec_dec_dev { /* decoder hardware mutex lock */ struct mutex dec_mutex[MTK_VDEC_HW_MAX]; struct mutex dev_mutex; + struct mutex dev_ctx_lock; struct workqueue_struct *decode_workqueue; spinlock_t irqlock; diff --git a/drivers/media/platform/mediatek/vcodec/decoder/vdec_vpu_if.c b/drivers/media/platform/mediatek/vcodec/decoder/vdec_vpu_if.c index 82e57ae983d5..da6be556727b 100644 --- a/drivers/media/platform/mediatek/vcodec/decoder/vdec_vpu_if.c +++ b/drivers/media/platform/mediatek/vcodec/decoder/vdec_vpu_if.c @@ -77,12 +77,14 @@ static bool vpu_dec_check_ap_inst(struct mtk_vcodec_dec_dev *dec_dev, struct vde struct mtk_vcodec_dec_ctx *ctx; int ret = false; + mutex_lock(&dec_dev->dev_ctx_lock); list_for_each_entry(ctx, &dec_dev->ctx_list, list) { if (!IS_ERR_OR_NULL(ctx) && ctx->vpu_inst == vpu) { ret = true; break; } } + mutex_unlock(&dec_dev->dev_ctx_lock); return ret; } -- cgit v1.2.3 From afaaf3a0f647a24a7bf6a2145d8ade37baaf75ad Mon Sep 17 00:00:00 2001 From: Yunfei Dong Date: Thu, 14 Mar 2024 20:30:09 +0800 Subject: media: mediatek: vcodec: adding lock to protect encoder context list Add a lock for the ctx_list, to avoid accessing a NULL pointer within the 'vpu_enc_ipi_handler' function when the ctx_list has been deleted due to an unexpected behavior on the SCP IP block. Fixes: 1972e32431ed ("media: mediatek: vcodec: Fix possible invalid memory access for encoder") Signed-off-by: Yunfei Dong Reviewed-by: Nicolas Dufresne Reviewed-by: AngeloGioacchino Del Regno Signed-off-by: Sebastian Fricke Signed-off-by: Hans Verkuil --- drivers/media/platform/mediatek/vcodec/common/mtk_vcodec_fw_vpu.c | 4 ++-- drivers/media/platform/mediatek/vcodec/encoder/mtk_vcodec_enc_drv.c | 5 +++++ drivers/media/platform/mediatek/vcodec/encoder/mtk_vcodec_enc_drv.h | 2 ++ drivers/media/platform/mediatek/vcodec/encoder/venc_vpu_if.c | 2 ++ 4 files changed, 11 insertions(+), 2 deletions(-) diff --git a/drivers/media/platform/mediatek/vcodec/common/mtk_vcodec_fw_vpu.c b/drivers/media/platform/mediatek/vcodec/common/mtk_vcodec_fw_vpu.c index 62cafe25fed9..d7027d600208 100644 --- a/drivers/media/platform/mediatek/vcodec/common/mtk_vcodec_fw_vpu.c +++ b/drivers/media/platform/mediatek/vcodec/common/mtk_vcodec_fw_vpu.c @@ -65,12 +65,12 @@ static void mtk_vcodec_vpu_reset_enc_handler(void *priv) dev_err(&dev->plat_dev->dev, "Watchdog timeout!!"); - mutex_lock(&dev->dev_mutex); + mutex_lock(&dev->dev_ctx_lock); list_for_each_entry(ctx, &dev->ctx_list, list) { ctx->state = MTK_STATE_ABORT; mtk_v4l2_vdec_dbg(0, ctx, "[%d] Change to state MTK_STATE_ABORT", ctx->id); } - mutex_unlock(&dev->dev_mutex); + mutex_unlock(&dev->dev_ctx_lock); } static const struct mtk_vcodec_fw_ops mtk_vcodec_vpu_msg = { diff --git a/drivers/media/platform/mediatek/vcodec/encoder/mtk_vcodec_enc_drv.c b/drivers/media/platform/mediatek/vcodec/encoder/mtk_vcodec_enc_drv.c index 6319f24bc714..3cb8a1622222 100644 --- a/drivers/media/platform/mediatek/vcodec/encoder/mtk_vcodec_enc_drv.c +++ b/drivers/media/platform/mediatek/vcodec/encoder/mtk_vcodec_enc_drv.c @@ -177,7 +177,9 @@ static int fops_vcodec_open(struct file *file) mtk_v4l2_venc_dbg(2, ctx, "Create instance [%d]@%p m2m_ctx=%p ", ctx->id, ctx, ctx->m2m_ctx); + mutex_lock(&dev->dev_ctx_lock); list_add(&ctx->list, &dev->ctx_list); + mutex_unlock(&dev->dev_ctx_lock); mutex_unlock(&dev->dev_mutex); mtk_v4l2_venc_dbg(0, ctx, "%s encoder [%d]", dev_name(&dev->plat_dev->dev), @@ -212,7 +214,9 @@ static int fops_vcodec_release(struct file *file) v4l2_fh_exit(&ctx->fh); v4l2_ctrl_handler_free(&ctx->ctrl_hdl); + mutex_lock(&dev->dev_ctx_lock); list_del_init(&ctx->list); + mutex_unlock(&dev->dev_ctx_lock); kfree(ctx); mutex_unlock(&dev->dev_mutex); return 0; @@ -294,6 +298,7 @@ static int mtk_vcodec_probe(struct platform_device *pdev) mutex_init(&dev->enc_mutex); mutex_init(&dev->dev_mutex); + mutex_init(&dev->dev_ctx_lock); spin_lock_init(&dev->irqlock); snprintf(dev->v4l2_dev.name, sizeof(dev->v4l2_dev.name), "%s", diff --git a/drivers/media/platform/mediatek/vcodec/encoder/mtk_vcodec_enc_drv.h b/drivers/media/platform/mediatek/vcodec/encoder/mtk_vcodec_enc_drv.h index a042f607ed8d..0bd85d0fb379 100644 --- a/drivers/media/platform/mediatek/vcodec/encoder/mtk_vcodec_enc_drv.h +++ b/drivers/media/platform/mediatek/vcodec/encoder/mtk_vcodec_enc_drv.h @@ -178,6 +178,7 @@ struct mtk_vcodec_enc_ctx { * * @enc_mutex: encoder hardware lock. * @dev_mutex: video_device lock + * @dev_ctx_lock: the lock of context list * @encode_workqueue: encode work queue * * @enc_irq: h264 encoder irq resource @@ -205,6 +206,7 @@ struct mtk_vcodec_enc_dev { /* encoder hardware mutex lock */ struct mutex enc_mutex; struct mutex dev_mutex; + struct mutex dev_ctx_lock; struct workqueue_struct *encode_workqueue; int enc_irq; diff --git a/drivers/media/platform/mediatek/vcodec/encoder/venc_vpu_if.c b/drivers/media/platform/mediatek/vcodec/encoder/venc_vpu_if.c index 84ad1cc6ad17..51bb7ee141b9 100644 --- a/drivers/media/platform/mediatek/vcodec/encoder/venc_vpu_if.c +++ b/drivers/media/platform/mediatek/vcodec/encoder/venc_vpu_if.c @@ -47,12 +47,14 @@ static bool vpu_enc_check_ap_inst(struct mtk_vcodec_enc_dev *enc_dev, struct ven struct mtk_vcodec_enc_ctx *ctx; int ret = false; + mutex_lock(&enc_dev->dev_ctx_lock); list_for_each_entry(ctx, &enc_dev->ctx_list, list) { if (!IS_ERR_OR_NULL(ctx) && ctx->vpu_inst == vpu) { ret = true; break; } } + mutex_unlock(&enc_dev->dev_ctx_lock); return ret; } -- cgit v1.2.3 From d353c3c34af08cfd4eaafc8c55f664eacec274ee Mon Sep 17 00:00:00 2001 From: Yunfei Dong Date: Wed, 6 Mar 2024 20:19:02 +0800 Subject: media: mediatek: vcodec: support 36 bits physical address The physical address on the MT8188 platform is larger than 32 bits, change the type from unsigned int to dma_addr_t to be able to access the high bits of the address. Signed-off-by: Yunfei Dong Reviewed-by: AngeloGioacchino Del Regno Signed-off-by: Sebastian Fricke Signed-off-by: Hans Verkuil --- drivers/media/platform/mediatek/vcodec/decoder/vdec/vdec_vp8_if.c | 2 +- .../media/platform/mediatek/vcodec/decoder/vdec/vdec_vp9_req_lat_if.c | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/media/platform/mediatek/vcodec/decoder/vdec/vdec_vp8_if.c b/drivers/media/platform/mediatek/vcodec/decoder/vdec/vdec_vp8_if.c index 19407f9bc773..987b3d71b662 100644 --- a/drivers/media/platform/mediatek/vcodec/decoder/vdec/vdec_vp8_if.c +++ b/drivers/media/platform/mediatek/vcodec/decoder/vdec/vdec_vp8_if.c @@ -449,7 +449,7 @@ static int vdec_vp8_decode(void *h_vdec, struct mtk_vcodec_mem *bs, inst->frm_cnt, y_fb_dma, c_fb_dma, fb); inst->cur_fb = fb; - dec->bs_dma = (unsigned long)bs->dma_addr; + dec->bs_dma = (uint64_t)bs->dma_addr; dec->bs_sz = bs->size; dec->cur_y_fb_dma = y_fb_dma; dec->cur_c_fb_dma = c_fb_dma; diff --git a/drivers/media/platform/mediatek/vcodec/decoder/vdec/vdec_vp9_req_lat_if.c b/drivers/media/platform/mediatek/vcodec/decoder/vdec/vdec_vp9_req_lat_if.c index cf48d09b78d7..eea709d93820 100644 --- a/drivers/media/platform/mediatek/vcodec/decoder/vdec/vdec_vp9_req_lat_if.c +++ b/drivers/media/platform/mediatek/vcodec/decoder/vdec/vdec_vp9_req_lat_if.c @@ -1074,7 +1074,7 @@ static int vdec_vp9_slice_setup_tile_buffer(struct vdec_vp9_slice_instance *inst unsigned int mi_row; unsigned int mi_col; unsigned int offset; - unsigned int pa; + dma_addr_t pa; unsigned int size; struct vdec_vp9_slice_tiles *tiles; unsigned char *pos; @@ -1109,7 +1109,7 @@ static int vdec_vp9_slice_setup_tile_buffer(struct vdec_vp9_slice_instance *inst pos = va + offset; end = va + bs->size; /* truncated */ - pa = (unsigned int)bs->dma_addr + offset; + pa = bs->dma_addr + offset; tb = instance->tile.va; for (i = 0; i < rows; i++) { for (j = 0; j < cols; j++) { -- cgit v1.2.3 From 6a92834166b16babd70e99c3e0ce9262893ad6ae Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Mon, 25 Mar 2024 21:13:41 +0200 Subject: ASoC: fsl: imx-es8328: Remove leftover gpio initialisation The gpio field is not used anymore, remove the leftover. This also fixes the compilation error after the ... Fixes: 9855f05e5536 ("ASoC: fsl: imx-es8328: Switch to using gpiod API") Signed-off-by: Andy Shevchenko Link: https://msgid.link/r/20240325191341.3977321-1-andriy.shevchenko@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/fsl/imx-es8328.c | 1 - 1 file changed, 1 deletion(-) diff --git a/sound/soc/fsl/imx-es8328.c b/sound/soc/fsl/imx-es8328.c index d67b8a149bff..5b9648f3b087 100644 --- a/sound/soc/fsl/imx-es8328.c +++ b/sound/soc/fsl/imx-es8328.c @@ -28,7 +28,6 @@ struct imx_es8328_data { static struct snd_soc_jack_gpio headset_jack_gpios[] = { { - .gpio = -1, .name = "headset-gpio", .report = SND_JACK_HEADSET, .invert = 0, -- cgit v1.2.3 From ea5fee227ff3dae209062ac9544906debe1e9ac1 Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Mon, 25 Mar 2024 17:19:25 -0500 Subject: ASoC: hdac_hda: improve error logs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We have a couple of duplicate logs and missing information, add __func__ consistently and make sure useful error codes are logged. Signed-off-by: Pierre-Louis Bossart Reviewed-by: Bard Liao Reviewed-by: Péter Ujfalusi Link: https://msgid.link/r/20240325221925.206507-1-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/codecs/hdac_hda.c | 44 ++++++++++++++++++++++++-------------------- 1 file changed, 24 insertions(+), 20 deletions(-) diff --git a/sound/soc/codecs/hdac_hda.c b/sound/soc/codecs/hdac_hda.c index 6aa3223985be..29c88de5508b 100644 --- a/sound/soc/codecs/hdac_hda.c +++ b/sound/soc/codecs/hdac_hda.c @@ -230,7 +230,8 @@ static int hdac_hda_dai_hw_params(struct snd_pcm_substream *substream, format_val = snd_hdac_stream_format(params_channels(params), bits, params_rate(params)); if (!format_val) { dev_err(dai->dev, - "invalid format_val, rate=%d, ch=%d, format=%d, maxbps=%d\n", + "%s: invalid format_val, rate=%d, ch=%d, format=%d, maxbps=%d\n", + __func__, params_rate(params), params_channels(params), params_format(params), maxbps); @@ -266,14 +267,12 @@ static int hdac_hda_dai_prepare(struct snd_pcm_substream *substream, struct snd_soc_component *component = dai->component; struct hda_pcm_stream *hda_stream; struct hdac_hda_priv *hda_pvt; - struct hdac_device *hdev; unsigned int format_val; struct hda_pcm *pcm; unsigned int stream; int ret = 0; hda_pvt = snd_soc_component_get_drvdata(component); - hdev = &hda_pvt->codec->core; pcm = snd_soc_find_pcm_from_dai(hda_pvt, dai); if (!pcm) return -EINVAL; @@ -286,7 +285,7 @@ static int hdac_hda_dai_prepare(struct snd_pcm_substream *substream, ret = snd_hda_codec_prepare(hda_pvt->codec, hda_stream, stream, format_val, substream); if (ret < 0) - dev_err(&hdev->dev, "codec prepare failed %d\n", ret); + dev_err(dai->dev, "%s: failed %d\n", __func__, ret); return ret; } @@ -298,6 +297,7 @@ static int hdac_hda_dai_open(struct snd_pcm_substream *substream, struct hdac_hda_priv *hda_pvt; struct hda_pcm_stream *hda_stream; struct hda_pcm *pcm; + int ret; hda_pvt = snd_soc_component_get_drvdata(component); pcm = snd_soc_find_pcm_from_dai(hda_pvt, dai); @@ -308,7 +308,11 @@ static int hdac_hda_dai_open(struct snd_pcm_substream *substream, hda_stream = &pcm->stream[substream->stream]; - return hda_stream->ops.open(hda_stream, hda_pvt->codec, substream); + ret = hda_stream->ops.open(hda_stream, hda_pvt->codec, substream); + if (ret < 0) + dev_err(dai->dev, "%s: failed %d\n", __func__, ret); + + return ret; } static void hdac_hda_dai_close(struct snd_pcm_substream *substream, @@ -367,7 +371,7 @@ static struct hda_pcm *snd_soc_find_pcm_from_dai(struct hdac_hda_priv *hda_pvt, pcm_name = "HDMI 3"; break; default: - dev_err(&hcodec->core.dev, "invalid dai id %d\n", dai->id); + dev_err(dai->dev, "%s: invalid dai id %d\n", __func__, dai->id); return NULL; } @@ -381,7 +385,7 @@ static struct hda_pcm *snd_soc_find_pcm_from_dai(struct hdac_hda_priv *hda_pvt, } } - dev_err(&hcodec->core.dev, "didn't find PCM for DAI %s\n", dai->name); + dev_err(dai->dev, "%s: didn't find PCM for DAI %s\n", __func__, dai->name); return NULL; } @@ -411,7 +415,7 @@ static int hdac_hda_codec_probe(struct snd_soc_component *component) hlink = snd_hdac_ext_bus_get_hlink_by_name(hdev->bus, dev_name(&hdev->dev)); if (!hlink) { - dev_err(&hdev->dev, "hdac link not found\n"); + dev_err(&hdev->dev, "%s: hdac link not found\n", __func__); return -EIO; } @@ -429,7 +433,7 @@ static int hdac_hda_codec_probe(struct snd_soc_component *component) ret = snd_hda_codec_device_new(hcodec->bus, component->card->snd_card, hdev->addr, hcodec, true); if (ret < 0) { - dev_err(&hdev->dev, "failed to create hda codec %d\n", ret); + dev_err(&hdev->dev, "%s: failed to create hda codec %d\n", __func__, ret); goto error_no_pm; } @@ -446,7 +450,7 @@ static int hdac_hda_codec_probe(struct snd_soc_component *component) if (fw) { ret = snd_hda_load_patch(hcodec->bus, fw->size, fw->data); if (ret < 0) { - dev_err(&hdev->dev, "failed to load hda patch %d\n", ret); + dev_err(&hdev->dev, "%s: failed to load hda patch %d\n", __func__, ret); goto error_no_pm; } release_firmware(fw); @@ -470,13 +474,13 @@ static int hdac_hda_codec_probe(struct snd_soc_component *component) ret = snd_hda_codec_set_name(hcodec, hcodec->preset->name); if (ret < 0) { - dev_err(&hdev->dev, "name failed %s\n", hcodec->preset->name); + dev_err(&hdev->dev, "%s: name failed %s\n", __func__, hcodec->preset->name); goto error_pm; } ret = snd_hdac_regmap_init(&hcodec->core); if (ret < 0) { - dev_err(&hdev->dev, "regmap init failed\n"); + dev_err(&hdev->dev, "%s: regmap init failed\n", __func__); goto error_pm; } @@ -484,16 +488,16 @@ static int hdac_hda_codec_probe(struct snd_soc_component *component) if (patch) { ret = patch(hcodec); if (ret < 0) { - dev_err(&hdev->dev, "patch failed %d\n", ret); + dev_err(&hdev->dev, "%s: patch failed %d\n", __func__, ret); goto error_regmap; } } else { - dev_dbg(&hdev->dev, "no patch file found\n"); + dev_dbg(&hdev->dev, "%s: no patch file found\n", __func__); } ret = snd_hda_codec_parse_pcms(hcodec); if (ret < 0) { - dev_err(&hdev->dev, "unable to map pcms to dai %d\n", ret); + dev_err(&hdev->dev, "%s: unable to map pcms to dai %d\n", __func__, ret); goto error_patch; } @@ -501,8 +505,8 @@ static int hdac_hda_codec_probe(struct snd_soc_component *component) if (!is_hdmi_codec(hcodec)) { ret = snd_hda_codec_build_controls(hcodec); if (ret < 0) { - dev_err(&hdev->dev, "unable to create controls %d\n", - ret); + dev_err(&hdev->dev, "%s: unable to create controls %d\n", + __func__, ret); goto error_patch; } } @@ -548,7 +552,7 @@ static void hdac_hda_codec_remove(struct snd_soc_component *component) hlink = snd_hdac_ext_bus_get_hlink_by_name(hdev->bus, dev_name(&hdev->dev)); if (!hlink) { - dev_err(&hdev->dev, "hdac link not found\n"); + dev_err(&hdev->dev, "%s: hdac link not found\n", __func__); return; } @@ -624,7 +628,7 @@ static int hdac_hda_dev_probe(struct hdac_device *hdev) /* hold the ref while we probe */ hlink = snd_hdac_ext_bus_get_hlink_by_name(hdev->bus, dev_name(&hdev->dev)); if (!hlink) { - dev_err(&hdev->dev, "hdac link not found\n"); + dev_err(&hdev->dev, "%s: hdac link not found\n", __func__); return -EIO; } snd_hdac_ext_bus_link_get(hdev->bus, hlink); @@ -640,7 +644,7 @@ static int hdac_hda_dev_probe(struct hdac_device *hdev) ARRAY_SIZE(hdac_hda_dais)); if (ret < 0) { - dev_err(&hdev->dev, "failed to register HDA codec %d\n", ret); + dev_err(&hdev->dev, "%s: failed to register HDA codec %d\n", __func__, ret); return ret; } -- cgit v1.2.3 From 1e90a846493c716e3e6b4d901fc0844e9eea6430 Mon Sep 17 00:00:00 2001 From: John Watts Date: Tue, 26 Mar 2024 22:48:00 +1100 Subject: ASoC: soc-dai: Note valid values of sysclock direction Clock direction is marked as 'unsigned int' but only two values are currently used in practice. Note these down in the documentation. Signed-off-by: John Watts Link: https://msgid.link/r/20240326-dai_mclk_hint-v1-1-653cbd2d78d9@jookia.org Signed-off-by: Mark Brown --- sound/soc/soc-dai.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/soc-dai.c b/sound/soc/soc-dai.c index 6f8773a8fc05..fefe394dce72 100644 --- a/sound/soc/soc-dai.c +++ b/sound/soc/soc-dai.c @@ -45,7 +45,7 @@ static inline int _soc_dai_ret(struct snd_soc_dai *dai, * @dai: DAI * @clk_id: DAI specific clock ID * @freq: new clock frequency in Hz - * @dir: new clock direction - input/output. + * @dir: new clock direction (SND_SOC_CLOCK_IN or SND_SOC_CLOCK_OUT) * * Configures the DAI master (MCLK) or system (SYSCLK) clocking. */ -- cgit v1.2.3 From cce4cbb157493483f03c21213753b66425a31430 Mon Sep 17 00:00:00 2001 From: Luca Ceresoli Date: Tue, 5 Mar 2024 15:36:29 +0100 Subject: ASoC: dt-bindings: Add Rockchip RK3308 internal audio codec Add device tree bindings document for the internal audio codec of the Rockchip RK3308 SoC. Reviewed-by: Rob Herring Signed-off-by: Luca Ceresoli Link: https://msgid.link/r/20240305-rk3308-audio-codec-v4-2-312acdbe628f@bootlin.com Signed-off-by: Mark Brown --- .../bindings/sound/rockchip,rk3308-codec.yaml | 98 ++++++++++++++++++++++ MAINTAINERS | 5 ++ 2 files changed, 103 insertions(+) create mode 100644 Documentation/devicetree/bindings/sound/rockchip,rk3308-codec.yaml diff --git a/Documentation/devicetree/bindings/sound/rockchip,rk3308-codec.yaml b/Documentation/devicetree/bindings/sound/rockchip,rk3308-codec.yaml new file mode 100644 index 000000000000..ecf3d7d968c8 --- /dev/null +++ b/Documentation/devicetree/bindings/sound/rockchip,rk3308-codec.yaml @@ -0,0 +1,98 @@ +# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/sound/rockchip,rk3308-codec.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Rockchip RK3308 Internal Codec + +description: | + This is the audio codec embedded in the Rockchip RK3308 + SoC. It has 8 24-bit ADCs and 2 24-bit DACs. The maximum supported + sampling rate is 192 kHz. + + It is connected internally to one out of a selection of the internal I2S + controllers. + + The RK3308 audio codec has 8 independent capture channels, but some + features work on stereo pairs called groups: + * grp 0 -- MIC1 / MIC2 + * grp 1 -- MIC3 / MIC4 + * grp 2 -- MIC5 / MIC6 + * grp 3 -- MIC7 / MIC8 + +maintainers: + - Luca Ceresoli + +properties: + compatible: + const: rockchip,rk3308-codec + + reg: + maxItems: 1 + + rockchip,grf: + $ref: /schemas/types.yaml#/definitions/phandle + description: + Phandle to the General Register Files (GRF) + + clocks: + items: + - description: clock for TX + - description: clock for RX + - description: AHB clock driving the interface + + clock-names: + items: + - const: mclk_tx + - const: mclk_rx + - const: hclk + + resets: + maxItems: 1 + + reset-names: + items: + - const: codec + + "#sound-dai-cells": + const: 0 + + rockchip,micbias-avdd-percent: + description: | + Voltage setting for the MICBIAS pins expressed as a percentage of + AVDD. + + E.g. if rockchip,micbias-avdd-percent = 85 and AVDD = 3v3, then the + MIC BIAS voltage will be 3.3 V * 85% = 2.805 V. + + enum: [ 50, 55, 60, 65, 70, 75, 80, 85 ] + +required: + - compatible + - reg + - rockchip,grf + - clocks + - resets + - "#sound-dai-cells" + +additionalProperties: false + +examples: + - | + #include + + audio_codec: audio-codec@ff560000 { + compatible = "rockchip,rk3308-codec"; + reg = <0xff560000 0x10000>; + rockchip,grf = <&grf>; + clock-names = "mclk_tx", "mclk_rx", "hclk"; + clocks = <&cru SCLK_I2S2_8CH_TX_OUT>, + <&cru SCLK_I2S2_8CH_RX_OUT>, + <&cru PCLK_ACODEC>; + reset-names = "codec"; + resets = <&cru SRST_ACODEC_P>; + #sound-dai-cells = <0>; + }; + +... diff --git a/MAINTAINERS b/MAINTAINERS index aa3b947fb080..89a59660bf0f 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -19046,6 +19046,11 @@ S: Maintained F: Documentation/devicetree/bindings/media/rockchip-rga.yaml F: drivers/media/platform/rockchip/rga/ +ROCKCHIP RK3308 INTERNAL AUDIO CODEC +M: Luca Ceresoli +S: Maintained +F: Documentation/devicetree/bindings/sound/rockchip,rk3308-codec.yaml + ROCKCHIP VIDEO DECODER DRIVER M: Ezequiel Garcia L: linux-media@vger.kernel.org -- cgit v1.2.3 From d75a21611a6e723d81db3f827e131ad39b69186c Mon Sep 17 00:00:00 2001 From: Luca Ceresoli Date: Tue, 5 Mar 2024 15:36:30 +0100 Subject: ASoC: core: add SOC_DOUBLE_RANGE_TLV() helper macro No macro currently allows handling a stereo control that has left and right in the same register and whose minimum register value is not zero. Add one that does that. Note that even though the snd_soc_*_volsw_range() look more appropriate given the _range suffix, they are not suitable because they don't honor the two shift values. The snd_soc_*_volsw() look more generic and are suitable for the task. Signed-off-by: Luca Ceresoli Link: https://msgid.link/r/20240305-rk3308-audio-codec-v4-3-312acdbe628f@bootlin.com Signed-off-by: Mark Brown --- include/sound/soc.h | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/include/sound/soc.h b/include/sound/soc.h index 39613b406b1d..0376f7e4c15d 100644 --- a/include/sound/soc.h +++ b/include/sound/soc.h @@ -149,6 +149,18 @@ {.reg = xreg, .rreg = xreg, \ .shift = shift_left, .rshift = shift_right, \ .max = xmax, .min = xmin} } +#define SOC_DOUBLE_RANGE_TLV(xname, xreg, xshift_left, xshift_right, xmin, xmax, \ + xinvert, tlv_array) \ +{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname),\ + .access = SNDRV_CTL_ELEM_ACCESS_TLV_READ |\ + SNDRV_CTL_ELEM_ACCESS_READWRITE,\ + .tlv.p = (tlv_array), \ + .info = snd_soc_info_volsw, \ + .get = snd_soc_get_volsw, .put = snd_soc_put_volsw, \ + .private_value = (unsigned long)&(struct soc_mixer_control) \ + {.reg = xreg, .rreg = xreg, \ + .shift = xshift_left, .rshift = xshift_right, \ + .min = xmin, .max = xmax, .invert = xinvert} } #define SOC_DOUBLE_R_TLV(xname, reg_left, reg_right, xshift, xmax, xinvert, tlv_array) \ { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname),\ .access = SNDRV_CTL_ELEM_ACCESS_TLV_READ |\ -- cgit v1.2.3 From 4ed0915f5bc4bcc81bca783a5b984f3d81e9764e Mon Sep 17 00:00:00 2001 From: Luca Ceresoli Date: Tue, 5 Mar 2024 15:36:31 +0100 Subject: ASoC: codecs: Add RK3308 internal audio codec driver Add driver for the internal audio codec of the Rockchip RK3308 SoC. Initially based on the vendor kernel driver [0], with lots of cleanups, fixes, improvements, conversion to DAPM and removal of some features. [0] https://github.com/rockchip-linux/kernel/blob/develop-4.19/sound/soc/codecs/rk3308_codec.c Signed-off-by: Luca Ceresoli Link: https://msgid.link/r/20240305-rk3308-audio-codec-v4-4-312acdbe628f@bootlin.com Signed-off-by: Mark Brown --- MAINTAINERS | 2 + sound/soc/codecs/Kconfig | 11 + sound/soc/codecs/Makefile | 2 + sound/soc/codecs/rk3308_codec.c | 974 ++++++++++++++++++++++++++++++++++++++++ sound/soc/codecs/rk3308_codec.h | 579 ++++++++++++++++++++++++ 5 files changed, 1568 insertions(+) create mode 100644 sound/soc/codecs/rk3308_codec.c create mode 100644 sound/soc/codecs/rk3308_codec.h diff --git a/MAINTAINERS b/MAINTAINERS index 89a59660bf0f..74ab768c0f6f 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -19050,6 +19050,8 @@ ROCKCHIP RK3308 INTERNAL AUDIO CODEC M: Luca Ceresoli S: Maintained F: Documentation/devicetree/bindings/sound/rockchip,rk3308-codec.yaml +F: sound/soc/codecs/rk3308_codec.c +F: sound/soc/codecs/rk3308_codec.h ROCKCHIP VIDEO DECODER DRIVER M: Ezequiel Garcia diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig index f78ea2f86fa6..1752814fffdd 100644 --- a/sound/soc/codecs/Kconfig +++ b/sound/soc/codecs/Kconfig @@ -180,6 +180,7 @@ config SND_SOC_ALL_CODECS imply SND_SOC_PCM512x_I2C imply SND_SOC_PCM512x_SPI imply SND_SOC_PEB2466 + imply SND_SOC_RK3308 imply SND_SOC_RK3328 imply SND_SOC_RK817 imply SND_SOC_RT274 @@ -1433,6 +1434,16 @@ config SND_SOC_PEB2466 To compile this driver as a module, choose M here: the module will be called snd-soc-peb2466. +config SND_SOC_RK3308 + tristate "Rockchip RK3308 audio CODEC" + select REGMAP_MMIO + help + This is a device driver for the audio codec embedded in the + Rockchip RK3308 SoC. + + It has 8 24-bit ADCs and 2 24-bit DACs. The maximum supported + sampling rate is 192 kHz. + config SND_SOC_RK3328 tristate "Rockchip RK3328 audio CODEC" select REGMAP_MMIO diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile index 7c075539dc47..9ba24fb870b1 100644 --- a/sound/soc/codecs/Makefile +++ b/sound/soc/codecs/Makefile @@ -205,6 +205,7 @@ snd-soc-pcm512x-objs := pcm512x.o snd-soc-pcm512x-i2c-objs := pcm512x-i2c.o snd-soc-pcm512x-spi-objs := pcm512x-spi.o snd-soc-peb2466-objs := peb2466.o +snd-soc-rk3308-objs := rk3308_codec.o snd-soc-rk3328-objs := rk3328_codec.o snd-soc-rk817-objs := rk817_codec.o snd-soc-rl6231-objs := rl6231.o @@ -595,6 +596,7 @@ obj-$(CONFIG_SND_SOC_PCM512x) += snd-soc-pcm512x.o obj-$(CONFIG_SND_SOC_PCM512x_I2C) += snd-soc-pcm512x-i2c.o obj-$(CONFIG_SND_SOC_PCM512x_SPI) += snd-soc-pcm512x-spi.o obj-$(CONFIG_SND_SOC_PEB2466) += snd-soc-peb2466.o +obj-$(CONFIG_SND_SOC_RK3308) += snd-soc-rk3308.o obj-$(CONFIG_SND_SOC_RK3328) += snd-soc-rk3328.o obj-$(CONFIG_SND_SOC_RK817) += snd-soc-rk817.o obj-$(CONFIG_SND_SOC_RL6231) += snd-soc-rl6231.o diff --git a/sound/soc/codecs/rk3308_codec.c b/sound/soc/codecs/rk3308_codec.c new file mode 100644 index 000000000000..9d3e4691a7b5 --- /dev/null +++ b/sound/soc/codecs/rk3308_codec.c @@ -0,0 +1,974 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Rockchip RK3308 internal audio codec driver + * + * Copyright (c) 2018, Fuzhou Rockchip Electronics Co., Ltd All rights reserved. + * Copyright (c) 2024, Vivax-Metrotech Ltd + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "rk3308_codec.h" + +#define ADC_LR_GROUP_MAX 4 + +#define GRF_CHIP_ID 0x800 + +enum { + ACODEC_VERSION_A = 'A', + ACODEC_VERSION_B, + ACODEC_VERSION_C, +}; + +struct rk3308_codec_priv { + const struct device *dev; + struct regmap *regmap; + struct regmap *grf; + struct reset_control *reset; + struct clk *hclk; + struct clk *mclk_rx; + struct clk *mclk_tx; + struct snd_soc_component *component; + unsigned char codec_ver; +}; + +static struct clk_bulk_data rk3308_codec_clocks[] = { + { .id = "hclk" }, + { .id = "mclk_rx" }, + { .id = "mclk_tx" }, +}; + +static const DECLARE_TLV_DB_SCALE(rk3308_codec_adc_alc_gain_tlv, -1800, 150, 0); +static const DECLARE_TLV_DB_SCALE(rk3308_codec_dac_hpout_gain_tlv, -3900, 150, 0); +static const DECLARE_TLV_DB_SCALE(rk3308_codec_dac_hpmix_gain_tlv, -600, 600, 0); + +static const DECLARE_TLV_DB_RANGE(rk3308_codec_dac_lineout_gain_tlv, + 0, 0, TLV_DB_SCALE_ITEM(-600, 0, 0), + 1, 1, TLV_DB_SCALE_ITEM(-300, 0, 0), + 2, 2, TLV_DB_SCALE_ITEM(-150, 0, 0), + 3, 3, TLV_DB_SCALE_ITEM(0, 0, 0), +); + +static const char * const rk3308_codec_hpf_cutoff_text[] = { + "20 Hz", "245 Hz", "612 Hz" +}; + +static SOC_ENUM_SINGLE_DECL(rk3308_codec_hpf_cutoff_enum12, RK3308_ADC_DIG_CON04(0), 0, + rk3308_codec_hpf_cutoff_text); +static SOC_ENUM_SINGLE_DECL(rk3308_codec_hpf_cutoff_enum34, RK3308_ADC_DIG_CON04(1), 0, + rk3308_codec_hpf_cutoff_text); +static SOC_ENUM_SINGLE_DECL(rk3308_codec_hpf_cutoff_enum56, RK3308_ADC_DIG_CON04(2), 0, + rk3308_codec_hpf_cutoff_text); +static SOC_ENUM_SINGLE_DECL(rk3308_codec_hpf_cutoff_enum78, RK3308_ADC_DIG_CON04(3), 0, + rk3308_codec_hpf_cutoff_text); + +static const struct snd_kcontrol_new rk3308_codec_controls[] = { + /* Despite the register names, these set the gain when AGC is OFF */ + SOC_SINGLE_RANGE_TLV("MIC1 Capture Volume", + RK3308_ADC_ANA_CON03(0), + RK3308_ADC_CH1_ALC_GAIN_SFT, + RK3308_ADC_CH1_ALC_GAIN_MIN, + RK3308_ADC_CH1_ALC_GAIN_MAX, + 0, rk3308_codec_adc_alc_gain_tlv), + SOC_SINGLE_RANGE_TLV("MIC2 Capture Volume", + RK3308_ADC_ANA_CON04(0), + RK3308_ADC_CH2_ALC_GAIN_SFT, + RK3308_ADC_CH2_ALC_GAIN_MIN, + RK3308_ADC_CH2_ALC_GAIN_MAX, + 0, rk3308_codec_adc_alc_gain_tlv), + SOC_SINGLE_RANGE_TLV("MIC3 Capture Volume", + RK3308_ADC_ANA_CON03(1), + RK3308_ADC_CH1_ALC_GAIN_SFT, + RK3308_ADC_CH1_ALC_GAIN_MIN, + RK3308_ADC_CH1_ALC_GAIN_MAX, + 0, rk3308_codec_adc_alc_gain_tlv), + SOC_SINGLE_RANGE_TLV("MIC4 Capture Volume", + RK3308_ADC_ANA_CON04(1), + RK3308_ADC_CH2_ALC_GAIN_SFT, + RK3308_ADC_CH2_ALC_GAIN_MIN, + RK3308_ADC_CH2_ALC_GAIN_MAX, + 0, rk3308_codec_adc_alc_gain_tlv), + SOC_SINGLE_RANGE_TLV("MIC5 Capture Volume", + RK3308_ADC_ANA_CON03(2), + RK3308_ADC_CH1_ALC_GAIN_SFT, + RK3308_ADC_CH1_ALC_GAIN_MIN, + RK3308_ADC_CH1_ALC_GAIN_MAX, + 0, rk3308_codec_adc_alc_gain_tlv), + SOC_SINGLE_RANGE_TLV("MIC6 Capture Volume", + RK3308_ADC_ANA_CON04(2), + RK3308_ADC_CH2_ALC_GAIN_SFT, + RK3308_ADC_CH2_ALC_GAIN_MIN, + RK3308_ADC_CH2_ALC_GAIN_MAX, + 0, rk3308_codec_adc_alc_gain_tlv), + SOC_SINGLE_RANGE_TLV("MIC7 Capture Volume", + RK3308_ADC_ANA_CON03(3), + RK3308_ADC_CH1_ALC_GAIN_SFT, + RK3308_ADC_CH1_ALC_GAIN_MIN, + RK3308_ADC_CH1_ALC_GAIN_MAX, + 0, rk3308_codec_adc_alc_gain_tlv), + SOC_SINGLE_RANGE_TLV("MIC8 Capture Volume", + RK3308_ADC_ANA_CON04(3), + RK3308_ADC_CH2_ALC_GAIN_SFT, + RK3308_ADC_CH2_ALC_GAIN_MIN, + RK3308_ADC_CH2_ALC_GAIN_MAX, + 0, rk3308_codec_adc_alc_gain_tlv), + + SOC_SINGLE("MIC1 Capture Switch", RK3308_ADC_ANA_CON00(0), 3, 1, 0), + SOC_SINGLE("MIC2 Capture Switch", RK3308_ADC_ANA_CON00(0), 7, 1, 0), + SOC_SINGLE("MIC3 Capture Switch", RK3308_ADC_ANA_CON00(1), 3, 1, 0), + SOC_SINGLE("MIC4 Capture Switch", RK3308_ADC_ANA_CON00(1), 7, 1, 0), + SOC_SINGLE("MIC5 Capture Switch", RK3308_ADC_ANA_CON00(2), 3, 1, 0), + SOC_SINGLE("MIC6 Capture Switch", RK3308_ADC_ANA_CON00(2), 7, 1, 0), + SOC_SINGLE("MIC7 Capture Switch", RK3308_ADC_ANA_CON00(3), 3, 1, 0), + SOC_SINGLE("MIC8 Capture Switch", RK3308_ADC_ANA_CON00(3), 7, 1, 0), + + SOC_SINGLE("MIC12 HPF Capture Switch", RK3308_ADC_DIG_CON04(0), 2, 1, 1), + SOC_SINGLE("MIC34 HPF Capture Switch", RK3308_ADC_DIG_CON04(1), 2, 1, 1), + SOC_SINGLE("MIC56 HPF Capture Switch", RK3308_ADC_DIG_CON04(2), 2, 1, 1), + SOC_SINGLE("MIC78 HPF Capture Switch", RK3308_ADC_DIG_CON04(3), 2, 1, 1), + + SOC_ENUM("MIC12 HPF Cutoff", rk3308_codec_hpf_cutoff_enum12), + SOC_ENUM("MIC34 HPF Cutoff", rk3308_codec_hpf_cutoff_enum34), + SOC_ENUM("MIC56 HPF Cutoff", rk3308_codec_hpf_cutoff_enum56), + SOC_ENUM("MIC78 HPF Cutoff", rk3308_codec_hpf_cutoff_enum78), + + SOC_DOUBLE_TLV("Line Out Playback Volume", + RK3308_DAC_ANA_CON04, + RK3308_DAC_L_LINEOUT_GAIN_SFT, + RK3308_DAC_R_LINEOUT_GAIN_SFT, + RK3308_DAC_x_LINEOUT_GAIN_MAX, + 0, rk3308_codec_dac_lineout_gain_tlv), + SOC_DOUBLE("Line Out Playback Switch", + RK3308_DAC_ANA_CON04, + RK3308_DAC_L_LINEOUT_MUTE_SFT, + RK3308_DAC_R_LINEOUT_MUTE_SFT, 1, 0), + SOC_DOUBLE_R_TLV("Headphone Playback Volume", + RK3308_DAC_ANA_CON05, + RK3308_DAC_ANA_CON06, + RK3308_DAC_x_HPOUT_GAIN_SFT, + RK3308_DAC_x_HPOUT_GAIN_MAX, + 0, rk3308_codec_dac_hpout_gain_tlv), + SOC_DOUBLE("Headphone Playback Switch", + RK3308_DAC_ANA_CON03, + RK3308_DAC_L_HPOUT_MUTE_SFT, + RK3308_DAC_R_HPOUT_MUTE_SFT, 1, 0), + SOC_DOUBLE_RANGE_TLV("DAC HPMIX Playback Volume", + RK3308_DAC_ANA_CON12, + RK3308_DAC_L_HPMIX_GAIN_SFT, + RK3308_DAC_R_HPMIX_GAIN_SFT, + 1, 2, 0, rk3308_codec_dac_hpmix_gain_tlv), +}; + +static int rk3308_codec_pop_sound_set(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, + int event) +{ + struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm); + struct rk3308_codec_priv *rk3308 = snd_soc_component_get_drvdata(component); + unsigned int val = (event == SND_SOC_DAPM_POST_PMU) ? + RK3308_DAC_HPOUT_POP_SOUND_x_WORK : + RK3308_DAC_HPOUT_POP_SOUND_x_INIT; + unsigned int mask = RK3308_DAC_HPOUT_POP_SOUND_x_MSK; + + regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON01, + mask << w->shift, val << w->shift); + + return 0; +} + +static const struct snd_soc_dapm_widget rk3308_codec_dapm_widgets[] = { + SND_SOC_DAPM_INPUT("MIC1"), + SND_SOC_DAPM_INPUT("MIC2"), + SND_SOC_DAPM_INPUT("MIC3"), + SND_SOC_DAPM_INPUT("MIC4"), + SND_SOC_DAPM_INPUT("MIC5"), + SND_SOC_DAPM_INPUT("MIC6"), + SND_SOC_DAPM_INPUT("MIC7"), + SND_SOC_DAPM_INPUT("MIC8"), + + SND_SOC_DAPM_SUPPLY("ADC_CURRENT_EN12", RK3308_ADC_ANA_CON06(0), 0, 0, NULL, 0), + SND_SOC_DAPM_SUPPLY("ADC_CURRENT_EN34", RK3308_ADC_ANA_CON06(1), 0, 0, NULL, 0), + SND_SOC_DAPM_SUPPLY("ADC_CURRENT_EN56", RK3308_ADC_ANA_CON06(2), 0, 0, NULL, 0), + SND_SOC_DAPM_SUPPLY("ADC_CURRENT_EN78", RK3308_ADC_ANA_CON06(3), 0, 0, NULL, 0), + + SND_SOC_DAPM_REG(snd_soc_dapm_mic, "MIC1_EN", RK3308_ADC_ANA_CON00(0), 1, 1, 1, 0), + SND_SOC_DAPM_REG(snd_soc_dapm_mic, "MIC2_EN", RK3308_ADC_ANA_CON00(0), 5, 1, 1, 0), + SND_SOC_DAPM_REG(snd_soc_dapm_mic, "MIC3_EN", RK3308_ADC_ANA_CON00(1), 1, 1, 1, 0), + SND_SOC_DAPM_REG(snd_soc_dapm_mic, "MIC4_EN", RK3308_ADC_ANA_CON00(1), 5, 1, 1, 0), + SND_SOC_DAPM_REG(snd_soc_dapm_mic, "MIC5_EN", RK3308_ADC_ANA_CON00(2), 1, 1, 1, 0), + SND_SOC_DAPM_REG(snd_soc_dapm_mic, "MIC6_EN", RK3308_ADC_ANA_CON00(2), 5, 1, 1, 0), + SND_SOC_DAPM_REG(snd_soc_dapm_mic, "MIC7_EN", RK3308_ADC_ANA_CON00(3), 1, 1, 1, 0), + SND_SOC_DAPM_REG(snd_soc_dapm_mic, "MIC8_EN", RK3308_ADC_ANA_CON00(3), 5, 1, 1, 0), + + SND_SOC_DAPM_REG(snd_soc_dapm_mic, "MIC1_WORK", RK3308_ADC_ANA_CON00(0), 2, 1, 1, 0), + SND_SOC_DAPM_REG(snd_soc_dapm_mic, "MIC2_WORK", RK3308_ADC_ANA_CON00(0), 6, 1, 1, 0), + SND_SOC_DAPM_REG(snd_soc_dapm_mic, "MIC3_WORK", RK3308_ADC_ANA_CON00(1), 2, 1, 1, 0), + SND_SOC_DAPM_REG(snd_soc_dapm_mic, "MIC4_WORK", RK3308_ADC_ANA_CON00(1), 6, 1, 1, 0), + SND_SOC_DAPM_REG(snd_soc_dapm_mic, "MIC5_WORK", RK3308_ADC_ANA_CON00(2), 2, 1, 1, 0), + SND_SOC_DAPM_REG(snd_soc_dapm_mic, "MIC6_WORK", RK3308_ADC_ANA_CON00(2), 6, 1, 1, 0), + SND_SOC_DAPM_REG(snd_soc_dapm_mic, "MIC7_WORK", RK3308_ADC_ANA_CON00(3), 2, 1, 1, 0), + SND_SOC_DAPM_REG(snd_soc_dapm_mic, "MIC8_WORK", RK3308_ADC_ANA_CON00(3), 6, 1, 1, 0), + + /* + * In theory MIC1 and MIC2 can switch to LINE IN, but this is not + * supported so all we can do is enabling the MIC input. + */ + SND_SOC_DAPM_REG(snd_soc_dapm_adc, "CH1_IN_SEL", RK3308_ADC_ANA_CON07(0), 4, 1, 1, 0), + SND_SOC_DAPM_REG(snd_soc_dapm_adc, "CH2_IN_SEL", RK3308_ADC_ANA_CON07(0), 6, 1, 1, 0), + + SND_SOC_DAPM_SUPPLY("ADC1_BUF_REF_EN", RK3308_ADC_ANA_CON00(0), 0, 0, NULL, 0), + SND_SOC_DAPM_SUPPLY("ADC2_BUF_REF_EN", RK3308_ADC_ANA_CON00(0), 4, 0, NULL, 0), + SND_SOC_DAPM_SUPPLY("ADC3_BUF_REF_EN", RK3308_ADC_ANA_CON00(1), 0, 0, NULL, 0), + SND_SOC_DAPM_SUPPLY("ADC4_BUF_REF_EN", RK3308_ADC_ANA_CON00(1), 4, 0, NULL, 0), + SND_SOC_DAPM_SUPPLY("ADC5_BUF_REF_EN", RK3308_ADC_ANA_CON00(2), 0, 0, NULL, 0), + SND_SOC_DAPM_SUPPLY("ADC6_BUF_REF_EN", RK3308_ADC_ANA_CON00(2), 4, 0, NULL, 0), + SND_SOC_DAPM_SUPPLY("ADC7_BUF_REF_EN", RK3308_ADC_ANA_CON00(3), 0, 0, NULL, 0), + SND_SOC_DAPM_SUPPLY("ADC8_BUF_REF_EN", RK3308_ADC_ANA_CON00(3), 4, 0, NULL, 0), + + SND_SOC_DAPM_SUPPLY("ADC_MCLK_GATE", RK3308_GLB_CON, 5, 1, NULL, 0), + + SND_SOC_DAPM_SUPPLY("ADC1_CLK_EN", RK3308_ADC_ANA_CON05(0), 0, 0, NULL, 0), + SND_SOC_DAPM_SUPPLY("ADC2_CLK_EN", RK3308_ADC_ANA_CON05(0), 4, 0, NULL, 0), + SND_SOC_DAPM_SUPPLY("ADC3_CLK_EN", RK3308_ADC_ANA_CON05(1), 0, 0, NULL, 0), + SND_SOC_DAPM_SUPPLY("ADC4_CLK_EN", RK3308_ADC_ANA_CON05(1), 4, 0, NULL, 0), + SND_SOC_DAPM_SUPPLY("ADC5_CLK_EN", RK3308_ADC_ANA_CON05(2), 0, 0, NULL, 0), + SND_SOC_DAPM_SUPPLY("ADC6_CLK_EN", RK3308_ADC_ANA_CON05(2), 4, 0, NULL, 0), + SND_SOC_DAPM_SUPPLY("ADC7_CLK_EN", RK3308_ADC_ANA_CON05(3), 0, 0, NULL, 0), + SND_SOC_DAPM_SUPPLY("ADC8_CLK_EN", RK3308_ADC_ANA_CON05(3), 4, 0, NULL, 0), + + /* The "ALC" name from the TRM is misleading, these are needed even without ALC/AGC */ + SND_SOC_DAPM_REG(snd_soc_dapm_adc, "ALC1_EN", RK3308_ADC_ANA_CON02(0), 0, 1, 1, 0), + SND_SOC_DAPM_REG(snd_soc_dapm_adc, "ALC2_EN", RK3308_ADC_ANA_CON02(0), 4, 1, 1, 0), + SND_SOC_DAPM_REG(snd_soc_dapm_adc, "ALC3_EN", RK3308_ADC_ANA_CON02(1), 0, 1, 1, 0), + SND_SOC_DAPM_REG(snd_soc_dapm_adc, "ALC4_EN", RK3308_ADC_ANA_CON02(1), 4, 1, 1, 0), + SND_SOC_DAPM_REG(snd_soc_dapm_adc, "ALC5_EN", RK3308_ADC_ANA_CON02(2), 0, 1, 1, 0), + SND_SOC_DAPM_REG(snd_soc_dapm_adc, "ALC6_EN", RK3308_ADC_ANA_CON02(2), 4, 1, 1, 0), + SND_SOC_DAPM_REG(snd_soc_dapm_adc, "ALC7_EN", RK3308_ADC_ANA_CON02(3), 0, 1, 1, 0), + SND_SOC_DAPM_REG(snd_soc_dapm_adc, "ALC8_EN", RK3308_ADC_ANA_CON02(3), 4, 1, 1, 0), + + SND_SOC_DAPM_REG(snd_soc_dapm_adc, "ADC1_EN", RK3308_ADC_ANA_CON05(0), 1, 1, 1, 0), + SND_SOC_DAPM_REG(snd_soc_dapm_adc, "ADC2_EN", RK3308_ADC_ANA_CON05(0), 5, 1, 1, 0), + SND_SOC_DAPM_REG(snd_soc_dapm_adc, "ADC3_EN", RK3308_ADC_ANA_CON05(1), 1, 1, 1, 0), + SND_SOC_DAPM_REG(snd_soc_dapm_adc, "ADC4_EN", RK3308_ADC_ANA_CON05(1), 5, 1, 1, 0), + SND_SOC_DAPM_REG(snd_soc_dapm_adc, "ADC5_EN", RK3308_ADC_ANA_CON05(2), 1, 1, 1, 0), + SND_SOC_DAPM_REG(snd_soc_dapm_adc, "ADC6_EN", RK3308_ADC_ANA_CON05(2), 5, 1, 1, 0), + SND_SOC_DAPM_REG(snd_soc_dapm_adc, "ADC7_EN", RK3308_ADC_ANA_CON05(3), 1, 1, 1, 0), + SND_SOC_DAPM_REG(snd_soc_dapm_adc, "ADC8_EN", RK3308_ADC_ANA_CON05(3), 5, 1, 1, 0), + + SND_SOC_DAPM_ADC("ADC1_WORK", "Capture", RK3308_ADC_ANA_CON05(0), 2, 0), + SND_SOC_DAPM_ADC("ADC2_WORK", "Capture", RK3308_ADC_ANA_CON05(0), 6, 0), + SND_SOC_DAPM_ADC("ADC3_WORK", "Capture", RK3308_ADC_ANA_CON05(1), 2, 0), + SND_SOC_DAPM_ADC("ADC4_WORK", "Capture", RK3308_ADC_ANA_CON05(1), 6, 0), + SND_SOC_DAPM_ADC("ADC5_WORK", "Capture", RK3308_ADC_ANA_CON05(2), 2, 0), + SND_SOC_DAPM_ADC("ADC6_WORK", "Capture", RK3308_ADC_ANA_CON05(2), 6, 0), + SND_SOC_DAPM_ADC("ADC7_WORK", "Capture", RK3308_ADC_ANA_CON05(3), 2, 0), + SND_SOC_DAPM_ADC("ADC8_WORK", "Capture", RK3308_ADC_ANA_CON05(3), 6, 0), + + /* The "ALC" name from the TRM is misleading, these are needed even without ALC/AGC */ + SND_SOC_DAPM_REG(snd_soc_dapm_adc, "ALC1_WORK", RK3308_ADC_ANA_CON02(0), 1, 1, 1, 0), + SND_SOC_DAPM_REG(snd_soc_dapm_adc, "ALC2_WORK", RK3308_ADC_ANA_CON02(0), 5, 1, 1, 0), + SND_SOC_DAPM_REG(snd_soc_dapm_adc, "ALC3_WORK", RK3308_ADC_ANA_CON02(1), 1, 1, 1, 0), + SND_SOC_DAPM_REG(snd_soc_dapm_adc, "ALC4_WORK", RK3308_ADC_ANA_CON02(1), 5, 1, 1, 0), + SND_SOC_DAPM_REG(snd_soc_dapm_adc, "ALC5_WORK", RK3308_ADC_ANA_CON02(2), 1, 1, 1, 0), + SND_SOC_DAPM_REG(snd_soc_dapm_adc, "ALC6_WORK", RK3308_ADC_ANA_CON02(2), 5, 1, 1, 0), + SND_SOC_DAPM_REG(snd_soc_dapm_adc, "ALC7_WORK", RK3308_ADC_ANA_CON02(3), 1, 1, 1, 0), + SND_SOC_DAPM_REG(snd_soc_dapm_adc, "ALC8_WORK", RK3308_ADC_ANA_CON02(3), 5, 1, 1, 0), + + SND_SOC_DAPM_SUPPLY("MICBIAS Current", RK3308_ADC_ANA_CON08(0), 4, 0, NULL, 0), + SND_SOC_DAPM_SUPPLY("MICBIAS1", RK3308_ADC_ANA_CON07(1), 3, 0, NULL, 0), + SND_SOC_DAPM_SUPPLY("MICBIAS2", RK3308_ADC_ANA_CON07(2), 3, 0, NULL, 0), + + SND_SOC_DAPM_OUT_DRV("DAC_L_HPMIX_EN", RK3308_DAC_ANA_CON13, 0, 0, NULL, 0), + SND_SOC_DAPM_OUT_DRV("DAC_R_HPMIX_EN", RK3308_DAC_ANA_CON13, 4, 0, NULL, 0), + SND_SOC_DAPM_OUT_DRV("DAC_L_HPMIX_WORK", RK3308_DAC_ANA_CON13, 1, 0, NULL, 0), + SND_SOC_DAPM_OUT_DRV("DAC_R_HPMIX_WORK", RK3308_DAC_ANA_CON13, 5, 0, NULL, 0), + /* HPMIX is not actually acting as a mixer as the only supported input is I2S */ + SND_SOC_DAPM_OUT_DRV("DAC_L_HPMIX_SEL", RK3308_DAC_ANA_CON12, 2, 0, NULL, 0), + SND_SOC_DAPM_OUT_DRV("DAC_R_HPMIX_SEL", RK3308_DAC_ANA_CON12, 6, 0, NULL, 0), + SND_SOC_DAPM_MIXER("DAC HPMIX Left", RK3308_DAC_ANA_CON13, 2, 0, NULL, 0), + SND_SOC_DAPM_MIXER("DAC HPMIX Right", RK3308_DAC_ANA_CON13, 6, 0, NULL, 0), + + SND_SOC_DAPM_SUPPLY("DAC_MCLK_GATE", RK3308_GLB_CON, 4, 1, NULL, 0), + + SND_SOC_DAPM_SUPPLY("DAC_CURRENT_EN", RK3308_DAC_ANA_CON00, 0, 0, NULL, 0), + SND_SOC_DAPM_SUPPLY("DAC_L_REF_EN", RK3308_DAC_ANA_CON02, 0, 0, NULL, 0), + SND_SOC_DAPM_SUPPLY("DAC_R_REF_EN", RK3308_DAC_ANA_CON02, 4, 0, NULL, 0), + SND_SOC_DAPM_SUPPLY("DAC_L_CLK_EN", RK3308_DAC_ANA_CON02, 1, 0, NULL, 0), + SND_SOC_DAPM_SUPPLY("DAC_R_CLK_EN", RK3308_DAC_ANA_CON02, 5, 0, NULL, 0), + SND_SOC_DAPM_DAC("DAC_L_DAC_WORK", NULL, RK3308_DAC_ANA_CON02, 3, 0), + SND_SOC_DAPM_DAC("DAC_R_DAC_WORK", NULL, RK3308_DAC_ANA_CON02, 7, 0), + + SND_SOC_DAPM_SUPPLY("DAC_BUF_REF_L", RK3308_DAC_ANA_CON01, 2, 0, NULL, 0), + SND_SOC_DAPM_SUPPLY("DAC_BUF_REF_R", RK3308_DAC_ANA_CON01, 6, 0, NULL, 0), + SND_SOC_DAPM_OUT_DRV_E("HPOUT_POP_SOUND_L", SND_SOC_NOPM, 0, 0, NULL, 0, + rk3308_codec_pop_sound_set, + SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD), + SND_SOC_DAPM_OUT_DRV_E("HPOUT_POP_SOUND_R", SND_SOC_NOPM, 4, 0, NULL, 0, + rk3308_codec_pop_sound_set, + SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD), + SND_SOC_DAPM_OUT_DRV("L_HPOUT_EN", RK3308_DAC_ANA_CON03, 1, 0, NULL, 0), + SND_SOC_DAPM_OUT_DRV("R_HPOUT_EN", RK3308_DAC_ANA_CON03, 5, 0, NULL, 0), + SND_SOC_DAPM_OUT_DRV("L_HPOUT_WORK", RK3308_DAC_ANA_CON03, 2, 0, NULL, 0), + SND_SOC_DAPM_OUT_DRV("R_HPOUT_WORK", RK3308_DAC_ANA_CON03, 6, 0, NULL, 0), + SND_SOC_DAPM_OUTPUT("HPOUT_L"), + SND_SOC_DAPM_OUTPUT("HPOUT_R"), + + SND_SOC_DAPM_OUT_DRV("L_LINEOUT_EN", RK3308_DAC_ANA_CON04, 0, 0, NULL, 0), + SND_SOC_DAPM_OUT_DRV("R_LINEOUT_EN", RK3308_DAC_ANA_CON04, 4, 0, NULL, 0), + SND_SOC_DAPM_OUTPUT("LINEOUT_L"), + SND_SOC_DAPM_OUTPUT("LINEOUT_R"), +}; + +static const struct snd_soc_dapm_route rk3308_codec_dapm_routes[] = { + { "MICBIAS1", NULL, "MICBIAS Current" }, + { "MICBIAS2", NULL, "MICBIAS Current" }, + + { "MIC1_EN", NULL, "MIC1" }, + { "MIC2_EN", NULL, "MIC2" }, + { "MIC3_EN", NULL, "MIC3" }, + { "MIC4_EN", NULL, "MIC4" }, + { "MIC5_EN", NULL, "MIC5" }, + { "MIC6_EN", NULL, "MIC6" }, + { "MIC7_EN", NULL, "MIC7" }, + { "MIC8_EN", NULL, "MIC8" }, + + { "MIC1_WORK", NULL, "MIC1_EN" }, + { "MIC2_WORK", NULL, "MIC2_EN" }, + { "MIC3_WORK", NULL, "MIC3_EN" }, + { "MIC4_WORK", NULL, "MIC4_EN" }, + { "MIC5_WORK", NULL, "MIC5_EN" }, + { "MIC6_WORK", NULL, "MIC6_EN" }, + { "MIC7_WORK", NULL, "MIC7_EN" }, + { "MIC8_WORK", NULL, "MIC8_EN" }, + + { "CH1_IN_SEL", NULL, "MIC1_WORK" }, + { "CH2_IN_SEL", NULL, "MIC2_WORK" }, + + { "ALC1_EN", NULL, "CH1_IN_SEL" }, + { "ALC2_EN", NULL, "CH2_IN_SEL" }, + { "ALC3_EN", NULL, "MIC3_WORK" }, + { "ALC4_EN", NULL, "MIC4_WORK" }, + { "ALC5_EN", NULL, "MIC5_WORK" }, + { "ALC6_EN", NULL, "MIC6_WORK" }, + { "ALC7_EN", NULL, "MIC7_WORK" }, + { "ALC8_EN", NULL, "MIC8_WORK" }, + + { "ADC1_EN", NULL, "ALC1_EN" }, + { "ADC2_EN", NULL, "ALC2_EN" }, + { "ADC3_EN", NULL, "ALC3_EN" }, + { "ADC4_EN", NULL, "ALC4_EN" }, + { "ADC5_EN", NULL, "ALC5_EN" }, + { "ADC6_EN", NULL, "ALC6_EN" }, + { "ADC7_EN", NULL, "ALC7_EN" }, + { "ADC8_EN", NULL, "ALC8_EN" }, + + { "ADC1_WORK", NULL, "ADC1_EN" }, + { "ADC2_WORK", NULL, "ADC2_EN" }, + { "ADC3_WORK", NULL, "ADC3_EN" }, + { "ADC4_WORK", NULL, "ADC4_EN" }, + { "ADC5_WORK", NULL, "ADC5_EN" }, + { "ADC6_WORK", NULL, "ADC6_EN" }, + { "ADC7_WORK", NULL, "ADC7_EN" }, + { "ADC8_WORK", NULL, "ADC8_EN" }, + + { "ADC1_BUF_REF_EN", NULL, "ADC_CURRENT_EN12" }, + { "ADC2_BUF_REF_EN", NULL, "ADC_CURRENT_EN12" }, + { "ADC3_BUF_REF_EN", NULL, "ADC_CURRENT_EN34" }, + { "ADC4_BUF_REF_EN", NULL, "ADC_CURRENT_EN34" }, + { "ADC5_BUF_REF_EN", NULL, "ADC_CURRENT_EN56" }, + { "ADC6_BUF_REF_EN", NULL, "ADC_CURRENT_EN56" }, + { "ADC7_BUF_REF_EN", NULL, "ADC_CURRENT_EN78" }, + { "ADC8_BUF_REF_EN", NULL, "ADC_CURRENT_EN78" }, + + { "ADC1_WORK", NULL, "ADC1_BUF_REF_EN" }, + { "ADC2_WORK", NULL, "ADC2_BUF_REF_EN" }, + { "ADC3_WORK", NULL, "ADC3_BUF_REF_EN" }, + { "ADC4_WORK", NULL, "ADC4_BUF_REF_EN" }, + { "ADC5_WORK", NULL, "ADC5_BUF_REF_EN" }, + { "ADC6_WORK", NULL, "ADC6_BUF_REF_EN" }, + { "ADC7_WORK", NULL, "ADC7_BUF_REF_EN" }, + { "ADC8_WORK", NULL, "ADC8_BUF_REF_EN" }, + + { "ADC1_CLK_EN", NULL, "ADC_MCLK_GATE" }, + { "ADC2_CLK_EN", NULL, "ADC_MCLK_GATE" }, + { "ADC3_CLK_EN", NULL, "ADC_MCLK_GATE" }, + { "ADC4_CLK_EN", NULL, "ADC_MCLK_GATE" }, + { "ADC5_CLK_EN", NULL, "ADC_MCLK_GATE" }, + { "ADC6_CLK_EN", NULL, "ADC_MCLK_GATE" }, + { "ADC7_CLK_EN", NULL, "ADC_MCLK_GATE" }, + { "ADC8_CLK_EN", NULL, "ADC_MCLK_GATE" }, + + { "ADC1_WORK", NULL, "ADC1_CLK_EN" }, + { "ADC2_WORK", NULL, "ADC2_CLK_EN" }, + { "ADC3_WORK", NULL, "ADC3_CLK_EN" }, + { "ADC4_WORK", NULL, "ADC4_CLK_EN" }, + { "ADC5_WORK", NULL, "ADC5_CLK_EN" }, + { "ADC6_WORK", NULL, "ADC6_CLK_EN" }, + { "ADC7_WORK", NULL, "ADC7_CLK_EN" }, + { "ADC8_WORK", NULL, "ADC8_CLK_EN" }, + + { "ALC1_WORK", NULL, "ADC1_WORK" }, + { "ALC2_WORK", NULL, "ADC2_WORK" }, + { "ALC3_WORK", NULL, "ADC3_WORK" }, + { "ALC4_WORK", NULL, "ADC4_WORK" }, + { "ALC5_WORK", NULL, "ADC5_WORK" }, + { "ALC6_WORK", NULL, "ADC6_WORK" }, + { "ALC7_WORK", NULL, "ADC7_WORK" }, + { "ALC8_WORK", NULL, "ADC8_WORK" }, + + { "HiFi Capture", NULL, "ALC1_WORK" }, + { "HiFi Capture", NULL, "ALC2_WORK" }, + { "HiFi Capture", NULL, "ALC3_WORK" }, + { "HiFi Capture", NULL, "ALC4_WORK" }, + { "HiFi Capture", NULL, "ALC5_WORK" }, + { "HiFi Capture", NULL, "ALC6_WORK" }, + { "HiFi Capture", NULL, "ALC7_WORK" }, + { "HiFi Capture", NULL, "ALC8_WORK" }, + + { "DAC_L_HPMIX_EN", NULL, "HiFi Playback" }, + { "DAC_R_HPMIX_EN", NULL, "HiFi Playback" }, + { "DAC_L_HPMIX_WORK", NULL, "DAC_L_HPMIX_EN" }, + { "DAC_R_HPMIX_WORK", NULL, "DAC_R_HPMIX_EN" }, + { "DAC HPMIX Left", NULL, "DAC_L_HPMIX_WORK" }, + { "DAC HPMIX Right", NULL, "DAC_R_HPMIX_WORK" }, + + { "DAC_L_DAC_WORK", NULL, "DAC HPMIX Left" }, + { "DAC_R_DAC_WORK", NULL, "DAC HPMIX Right" }, + + { "DAC_L_REF_EN", NULL, "DAC_CURRENT_EN" }, + { "DAC_R_REF_EN", NULL, "DAC_CURRENT_EN" }, + { "DAC_L_CLK_EN", NULL, "DAC_L_REF_EN" }, + { "DAC_R_CLK_EN", NULL, "DAC_R_REF_EN" }, + { "DAC_L_CLK_EN", NULL, "DAC_MCLK_GATE" }, + { "DAC_R_CLK_EN", NULL, "DAC_MCLK_GATE" }, + { "DAC_L_DAC_WORK", NULL, "DAC_L_CLK_EN" }, + { "DAC_R_DAC_WORK", NULL, "DAC_R_CLK_EN" }, + { "DAC_L_HPMIX_SEL", NULL, "DAC_L_DAC_WORK" }, + { "DAC_R_HPMIX_SEL", NULL, "DAC_R_DAC_WORK" }, + + { "HPOUT_L", NULL, "DAC_BUF_REF_L" }, + { "HPOUT_R", NULL, "DAC_BUF_REF_R" }, + { "L_HPOUT_EN", NULL, "DAC_L_HPMIX_SEL" }, + { "R_HPOUT_EN", NULL, "DAC_R_HPMIX_SEL" }, + { "L_HPOUT_WORK", NULL, "L_HPOUT_EN" }, + { "R_HPOUT_WORK", NULL, "R_HPOUT_EN" }, + { "HPOUT_POP_SOUND_L", NULL, "L_HPOUT_WORK" }, + { "HPOUT_POP_SOUND_R", NULL, "R_HPOUT_WORK" }, + { "HPOUT_L", NULL, "HPOUT_POP_SOUND_L" }, + { "HPOUT_R", NULL, "HPOUT_POP_SOUND_R" }, + + { "L_LINEOUT_EN", NULL, "DAC_L_HPMIX_SEL" }, + { "R_LINEOUT_EN", NULL, "DAC_R_HPMIX_SEL" }, + { "LINEOUT_L", NULL, "L_LINEOUT_EN" }, + { "LINEOUT_R", NULL, "R_LINEOUT_EN" }, +}; + +static int rk3308_codec_set_dai_fmt(struct snd_soc_dai *codec_dai, + unsigned int fmt) +{ + struct snd_soc_component *component = codec_dai->component; + struct rk3308_codec_priv *rk3308 = snd_soc_component_get_drvdata(component); + const unsigned int inv_bits = fmt & SND_SOC_DAIFMT_INV_MASK; + const bool inv_bitclk = + (inv_bits & SND_SOC_DAIFMT_IB_IF) || + (inv_bits & SND_SOC_DAIFMT_IB_NF); + const bool inv_frmclk = + (inv_bits & SND_SOC_DAIFMT_IB_IF) || + (inv_bits & SND_SOC_DAIFMT_NB_IF); + const unsigned int dac_master_bits = rk3308->codec_ver < ACODEC_VERSION_C ? + RK3308_DAC_IO_MODE_MASTER | RK3308_DAC_MODE_MASTER : + RK3308BS_DAC_IO_MODE_MASTER | RK3308BS_DAC_MODE_MASTER; + unsigned int adc_aif1 = 0, adc_aif2 = 0, dac_aif1 = 0, dac_aif2 = 0; + bool is_master = false; + int grp; + + switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { + case SND_SOC_DAIFMT_CBC_CFC: + break; + case SND_SOC_DAIFMT_CBP_CFP: + adc_aif2 |= RK3308_ADC_IO_MODE_MASTER; + adc_aif2 |= RK3308_ADC_MODE_MASTER; + dac_aif2 |= dac_master_bits; + is_master = true; + break; + default: + return -EINVAL; + } + + switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { + case SND_SOC_DAIFMT_DSP_A: + adc_aif1 |= RK3308_ADC_I2S_MODE_PCM; + dac_aif1 |= RK3308_DAC_I2S_MODE_PCM; + break; + case SND_SOC_DAIFMT_I2S: + adc_aif1 |= RK3308_ADC_I2S_MODE_I2S; + dac_aif1 |= RK3308_DAC_I2S_MODE_I2S; + break; + case SND_SOC_DAIFMT_RIGHT_J: + adc_aif1 |= RK3308_ADC_I2S_MODE_RJ; + dac_aif1 |= RK3308_DAC_I2S_MODE_RJ; + break; + case SND_SOC_DAIFMT_LEFT_J: + adc_aif1 |= RK3308_ADC_I2S_MODE_LJ; + dac_aif1 |= RK3308_DAC_I2S_MODE_LJ; + break; + default: + return -EINVAL; + } + + if (inv_bitclk) { + adc_aif2 |= RK3308_ADC_I2S_BIT_CLK_POL_REVERSAL; + dac_aif2 |= RK3308_DAC_I2S_BIT_CLK_POL_REVERSAL; + } + + if (inv_frmclk) { + adc_aif1 |= RK3308_ADC_I2S_LRC_POL_REVERSAL; + dac_aif1 |= RK3308_DAC_I2S_LRC_POL_REVERSAL; + } + + /* + * Hold ADC Digital registers start at master mode + * + * There are 8 ADCs which use the same internal SCLK and LRCK for + * master mode. We need to make sure that they are in effect at the + * same time, otherwise they will cause abnormal clocks. + */ + if (is_master) + regmap_clear_bits(rk3308->regmap, RK3308_GLB_CON, RK3308_ADC_DIG_WORK); + + for (grp = 0; grp < ADC_LR_GROUP_MAX; grp++) { + regmap_update_bits(rk3308->regmap, RK3308_ADC_DIG_CON01(grp), + RK3308_ADC_I2S_LRC_POL_REVERSAL | + RK3308_ADC_I2S_MODE_MSK, + adc_aif1); + regmap_update_bits(rk3308->regmap, RK3308_ADC_DIG_CON02(grp), + RK3308_ADC_IO_MODE_MASTER | + RK3308_ADC_MODE_MASTER | + RK3308_ADC_I2S_BIT_CLK_POL_REVERSAL, + adc_aif2); + } + + /* Hold ADC Digital registers end at master mode */ + if (is_master) + regmap_set_bits(rk3308->regmap, RK3308_GLB_CON, RK3308_ADC_DIG_WORK); + + regmap_update_bits(rk3308->regmap, RK3308_DAC_DIG_CON01, + RK3308_DAC_I2S_LRC_POL_REVERSAL | + RK3308_DAC_I2S_MODE_MSK, + dac_aif1); + regmap_update_bits(rk3308->regmap, RK3308_DAC_DIG_CON02, + dac_master_bits | RK3308_DAC_I2S_BIT_CLK_POL_REVERSAL, + dac_aif2); + + return 0; +} + +static int rk3308_codec_dac_dig_config(struct rk3308_codec_priv *rk3308, + struct snd_pcm_hw_params *params) +{ + unsigned int dac_aif1 = 0; + + switch (params_format(params)) { + case SNDRV_PCM_FORMAT_S16_LE: + dac_aif1 |= RK3308_DAC_I2S_VALID_LEN_16BITS; + break; + case SNDRV_PCM_FORMAT_S20_3LE: + dac_aif1 |= RK3308_DAC_I2S_VALID_LEN_20BITS; + break; + case SNDRV_PCM_FORMAT_S24_LE: + dac_aif1 |= RK3308_DAC_I2S_VALID_LEN_24BITS; + break; + case SNDRV_PCM_FORMAT_S32_LE: + dac_aif1 |= RK3308_DAC_I2S_VALID_LEN_32BITS; + break; + default: + return -EINVAL; + } + + regmap_update_bits(rk3308->regmap, RK3308_DAC_DIG_CON01, + RK3308_DAC_I2S_VALID_LEN_MSK, dac_aif1); + regmap_set_bits(rk3308->regmap, RK3308_DAC_DIG_CON02, RK3308_DAC_I2S_WORK); + + return 0; +} + +static int rk3308_codec_adc_dig_config(struct rk3308_codec_priv *rk3308, + struct snd_pcm_hw_params *params) +{ + unsigned int adc_aif1 = 0; + /* + * grp 0 = ADC1 and ADC2 + * grp 1 = ADC3 and ADC4 + * grp 2 = ADC5 and ADC6 + * grp 3 = ADC7 and ADC8 + */ + u32 used_adc_grps; + int grp; + + switch (params_channels(params)) { + case 1: + adc_aif1 |= RK3308_ADC_I2S_MONO; + used_adc_grps = 1; + break; + case 2: + case 4: + case 6: + case 8: + used_adc_grps = params_channels(params) / 2; + break; + default: + dev_err(rk3308->dev, "Invalid channel number %d\n", params_channels(params)); + return -EINVAL; + } + + switch (params_format(params)) { + case SNDRV_PCM_FORMAT_S16_LE: + adc_aif1 |= RK3308_ADC_I2S_VALID_LEN_16BITS; + break; + case SNDRV_PCM_FORMAT_S20_3LE: + adc_aif1 |= RK3308_ADC_I2S_VALID_LEN_20BITS; + break; + case SNDRV_PCM_FORMAT_S24_LE: + adc_aif1 |= RK3308_ADC_I2S_VALID_LEN_24BITS; + break; + case SNDRV_PCM_FORMAT_S32_LE: + adc_aif1 |= RK3308_ADC_I2S_VALID_LEN_32BITS; + break; + default: + return -EINVAL; + } + + for (grp = 0; grp < used_adc_grps; grp++) { + regmap_update_bits(rk3308->regmap, + RK3308_ADC_DIG_CON03(grp), + RK3308_ADC_L_CH_BIST_MSK | RK3308_ADC_R_CH_BIST_MSK, + RK3308_ADC_L_CH_NORMAL_LEFT | RK3308_ADC_R_CH_NORMAL_RIGHT); + regmap_update_bits(rk3308->regmap, RK3308_ADC_DIG_CON01(grp), + RK3308_ADC_I2S_VALID_LEN_MSK | RK3308_ADC_I2S_MONO, adc_aif1); + regmap_set_bits(rk3308->regmap, RK3308_ADC_DIG_CON02(grp), RK3308_ADC_I2S_WORK); + } + + return 0; +} + +static int rk3308_codec_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params, + struct snd_soc_dai *dai) +{ + struct snd_soc_component *component = dai->component; + struct rk3308_codec_priv *rk3308 = snd_soc_component_get_drvdata(component); + + return (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) ? + rk3308_codec_dac_dig_config(rk3308, params) : + rk3308_codec_adc_dig_config(rk3308, params); +} + +static const struct snd_soc_dai_ops rk3308_codec_dai_ops = { + .hw_params = rk3308_codec_hw_params, + .set_fmt = rk3308_codec_set_dai_fmt, +}; + +static struct snd_soc_dai_driver rk3308_codec_dai_driver = { + .name = "rk3308-hifi", + .playback = { + .stream_name = "HiFi Playback", + .channels_min = 2, + .channels_max = 2, + .rates = SNDRV_PCM_RATE_8000_192000, + .formats = (SNDRV_PCM_FMTBIT_S16_LE | + SNDRV_PCM_FMTBIT_S20_3LE | + SNDRV_PCM_FMTBIT_S24_LE | + SNDRV_PCM_FMTBIT_S32_LE), + }, + .capture = { + .stream_name = "HiFi Capture", + .channels_min = 1, + .channels_max = 8, + .rates = SNDRV_PCM_RATE_8000_192000, + .formats = (SNDRV_PCM_FMTBIT_S16_LE | + SNDRV_PCM_FMTBIT_S20_3LE | + SNDRV_PCM_FMTBIT_S24_LE | + SNDRV_PCM_FMTBIT_S32_LE), + }, + .ops = &rk3308_codec_dai_ops, +}; + +static void rk3308_codec_reset(struct snd_soc_component *component) +{ + struct rk3308_codec_priv *rk3308 = snd_soc_component_get_drvdata(component); + + reset_control_assert(rk3308->reset); + usleep_range(10000, 11000); /* estimated value */ + reset_control_deassert(rk3308->reset); + + regmap_write(rk3308->regmap, RK3308_GLB_CON, 0x00); + usleep_range(10000, 11000); /* estimated value */ + regmap_write(rk3308->regmap, RK3308_GLB_CON, + RK3308_SYS_WORK | + RK3308_DAC_DIG_WORK | + RK3308_ADC_DIG_WORK); +} + +/* + * Initialize register whose default after HW reset is problematic or which + * are never modified. + */ +static int rk3308_codec_initialize(struct rk3308_codec_priv *rk3308) +{ + int grp; + + /* + * Init ADC digital vol to 0 dB (reset value is 0xff, undocumented). + * Range: -97dB ~ +32dB. + */ + if (rk3308->codec_ver == ACODEC_VERSION_C) { + for (grp = 0; grp < ADC_LR_GROUP_MAX; grp++) { + regmap_write(rk3308->regmap, RK3308_ADC_DIG_CON05(grp), + RK3308_ADC_DIG_VOL_CON_x_0DB); + regmap_write(rk3308->regmap, RK3308_ADC_DIG_CON06(grp), + RK3308_ADC_DIG_VOL_CON_x_0DB); + } + } + + /* set HPMIX default gains (reset value is 0, which is illegal) */ + regmap_update_bits(rk3308->regmap, RK3308_DAC_ANA_CON12, + RK3308_DAC_L_HPMIX_GAIN_MSK | + RK3308_DAC_R_HPMIX_GAIN_MSK, + RK3308_DAC_L_HPMIX_GAIN_NDB_6 | + RK3308_DAC_R_HPMIX_GAIN_NDB_6); + + /* recover DAC digital gain to 0 dB (reset value is 0xff, undocumented) */ + if (rk3308->codec_ver == ACODEC_VERSION_C) + regmap_write(rk3308->regmap, RK3308_DAC_DIG_CON04, + RK3308BS_DAC_DIG_GAIN_0DB); + + /* + * Unconditionally enable zero-cross detection (needed for AGC, + * harmless without AGC) + */ + for (grp = 0; grp < ADC_LR_GROUP_MAX; grp++) + regmap_set_bits(rk3308->regmap, RK3308_ADC_ANA_CON02(grp), + RK3308_ADC_CH1_ZEROCROSS_DET_EN | + RK3308_ADC_CH2_ZEROCROSS_DET_EN); + + return 0; +} + +static int rk3308_codec_probe(struct snd_soc_component *component) +{ + struct rk3308_codec_priv *rk3308 = snd_soc_component_get_drvdata(component); + + rk3308->component = component; + + rk3308_codec_reset(component); + rk3308_codec_initialize(rk3308); + + return 0; +} + +static int rk3308_codec_set_bias_level(struct snd_soc_component *component, + enum snd_soc_bias_level level) +{ + struct rk3308_codec_priv *rk3308 = snd_soc_component_get_drvdata(component); + + switch (level) { + case SND_SOC_BIAS_ON: + break; + case SND_SOC_BIAS_PREPARE: + break; + case SND_SOC_BIAS_STANDBY: + if (snd_soc_component_get_bias_level(component) != SND_SOC_BIAS_OFF) + break; + + /* Sequence from TRM Section 8.6.3 "Power Up" */ + regmap_set_bits(rk3308->regmap, RK3308_DAC_ANA_CON02, + RK3308_DAC_L_DAC_EN | RK3308_DAC_R_DAC_EN); + regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON10(0), + RK3308_ADC_CURRENT_CHARGE_MSK, 1); + regmap_set_bits(rk3308->regmap, RK3308_ADC_ANA_CON10(0), + RK3308_ADC_REF_EN); + regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON10(0), + RK3308_ADC_CURRENT_CHARGE_MSK, 0x7f); + msleep(20); /* estimated value */ + break; + case SND_SOC_BIAS_OFF: + /* Sequence from TRM Section 8.6.4 "Power Down" */ + regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON10(0), + RK3308_ADC_CURRENT_CHARGE_MSK, 1); + regmap_clear_bits(rk3308->regmap, RK3308_ADC_ANA_CON10(0), + RK3308_ADC_REF_EN); + regmap_clear_bits(rk3308->regmap, RK3308_DAC_ANA_CON02, + RK3308_DAC_L_DAC_EN | RK3308_DAC_R_DAC_EN); + msleep(20); /* estimated value */ + break; + } + return 0; +} + +static const struct snd_soc_component_driver rk3308_codec_component_driver = { + .probe = rk3308_codec_probe, + .set_bias_level = rk3308_codec_set_bias_level, + .controls = rk3308_codec_controls, + .num_controls = ARRAY_SIZE(rk3308_codec_controls), + .dapm_widgets = rk3308_codec_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(rk3308_codec_dapm_widgets), + .dapm_routes = rk3308_codec_dapm_routes, + .num_dapm_routes = ARRAY_SIZE(rk3308_codec_dapm_routes), +}; + +static const struct regmap_config rk3308_codec_regmap_config = { + .reg_bits = 32, + .reg_stride = 4, + .val_bits = 32, + .max_register = RK3308_DAC_ANA_CON15, +}; + +static int rk3308_codec_get_version(struct rk3308_codec_priv *rk3308) +{ + unsigned int chip_id; + int err; + + err = regmap_read(rk3308->grf, GRF_CHIP_ID, &chip_id); + if (err) + return err; + + switch (chip_id) { + case 3306: + rk3308->codec_ver = ACODEC_VERSION_A; + break; + case 0x3308: + rk3308->codec_ver = ACODEC_VERSION_B; + return dev_err_probe(rk3308->dev, -EINVAL, "Chip version B not supported\n"); + case 0x3308c: + rk3308->codec_ver = ACODEC_VERSION_C; + break; + default: + return dev_err_probe(rk3308->dev, -EINVAL, "Unknown chip_id: 0x%x\n", chip_id); + } + + dev_info(rk3308->dev, "Found codec version %c\n", rk3308->codec_ver); + return 0; +} + +static int rk3308_codec_set_micbias_level(struct rk3308_codec_priv *rk3308) +{ + struct device_node *np = rk3308->dev->of_node; + u32 percent; + u32 mult; + int err; + + err = of_property_read_u32(np, "rockchip,micbias-avdd-percent", &percent); + if (err == -EINVAL) + return 0; + if (err) + return dev_err_probe(rk3308->dev, err, + "Error reading 'rockchip,micbias-avdd-percent'\n"); + + /* Convert percent to register value, linerarly (50% -> 0, 5% step = +1) */ + mult = (percent - 50) / 5; + + /* Check range and that the percent was an exact value allowed */ + if (mult > RK3308_ADC_LEVEL_RANGE_MICBIAS_MAX || mult * 5 + 50 != percent) + return dev_err_probe(rk3308->dev, -EINVAL, + "Invalid value %u for 'rockchip,micbias-avdd-percent'\n", + percent); + + regmap_update_bits(rk3308->regmap, RK3308_ADC_ANA_CON07(0), + RK3308_ADC_LEVEL_RANGE_MICBIAS_MSK, + mult << RK3308_ADC_LEVEL_RANGE_MICBIAS_SFT); + + return 0; +} + +static int rk3308_codec_platform_probe(struct platform_device *pdev) +{ + struct device_node *np = pdev->dev.of_node; + struct device *dev = &pdev->dev; + struct rk3308_codec_priv *rk3308; + void __iomem *base; + int err; + + rk3308 = devm_kzalloc(&pdev->dev, sizeof(*rk3308), GFP_KERNEL); + if (!rk3308) + return -ENOMEM; + + rk3308->dev = dev; + + rk3308->grf = syscon_regmap_lookup_by_phandle(np, "rockchip,grf"); + if (IS_ERR(rk3308->grf)) + return dev_err_probe(dev, PTR_ERR(rk3308->grf), "Error getting GRF\n"); + + rk3308->reset = devm_reset_control_get_optional_exclusive(dev, "codec"); + if (IS_ERR(rk3308->reset)) + return dev_err_probe(dev, PTR_ERR(rk3308->reset), "Failed to get reset control\n"); + + err = devm_clk_bulk_get(dev, ARRAY_SIZE(rk3308_codec_clocks), rk3308_codec_clocks); + if (err) + return dev_err_probe(dev, err, "Failed to get clocks\n"); + + err = clk_bulk_prepare_enable(ARRAY_SIZE(rk3308_codec_clocks), rk3308_codec_clocks); + if (err) + return dev_err_probe(dev, err, "Failed to enable clocks\n"); + + err = rk3308_codec_get_version(rk3308); + if (err) + return err; + + base = devm_platform_ioremap_resource(pdev, 0); + if (IS_ERR(base)) + return PTR_ERR(base); + + rk3308->regmap = devm_regmap_init_mmio(dev, base, &rk3308_codec_regmap_config); + if (IS_ERR(rk3308->regmap)) + return dev_err_probe(dev, PTR_ERR(rk3308->regmap), + "Failed to init regmap\n"); + + platform_set_drvdata(pdev, rk3308); + + err = rk3308_codec_set_micbias_level(rk3308); + if (err) + return err; + + err = devm_snd_soc_register_component(dev, &rk3308_codec_component_driver, + &rk3308_codec_dai_driver, 1); + if (err) + return dev_err_probe(dev, err, "Failed to register codec\n"); + + return 0; +} + +static const struct of_device_id rk3308_codec_of_match[] = { + { .compatible = "rockchip,rk3308-codec", }, + {}, +}; +MODULE_DEVICE_TABLE(of, rk3308_codec_of_match); + +static struct platform_driver rk3308_codec_driver = { + .driver = { + .name = "rk3308-acodec", + .of_match_table = of_match_ptr(rk3308_codec_of_match), + }, + .probe = rk3308_codec_platform_probe, +}; +module_platform_driver(rk3308_codec_driver); + +MODULE_AUTHOR("Xing Zheng "); +MODULE_AUTHOR("Luca Ceresoli "); +MODULE_DESCRIPTION("ASoC RK3308 Codec Driver"); +MODULE_LICENSE("GPL"); diff --git a/sound/soc/codecs/rk3308_codec.h b/sound/soc/codecs/rk3308_codec.h new file mode 100644 index 000000000000..a4226b235ab7 --- /dev/null +++ b/sound/soc/codecs/rk3308_codec.h @@ -0,0 +1,579 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Rockchip RK3308 internal audio codec driver -- register definitions + * + * Copyright (c) 2018, Fuzhou Rockchip Electronics Co., Ltd All rights reserved. + * Copyright (c) 2022, Vivax-Metrotech Ltd + */ + +#ifndef __RK3308_CODEC_H__ +#define __RK3308_CODEC_H__ + +#define RK3308_GLB_CON 0x00 + +/* ADC DIGITAL REGISTERS */ + +/* + * The ADC group are 0 ~ 3, that control: + * + * CH0: left_0(ADC1) and right_0(ADC2) + * CH1: left_1(ADC3) and right_1(ADC4) + * CH2: left_2(ADC5) and right_2(ADC6) + * CH3: left_3(ADC7) and right_3(ADC8) + */ +#define RK3308_ADC_DIG_OFFSET(ch) (((ch) & 0x3) * 0xc0 + 0x0) + +#define RK3308_ADC_DIG_CON01(ch) (RK3308_ADC_DIG_OFFSET((ch)) + 0x04) +#define RK3308_ADC_DIG_CON02(ch) (RK3308_ADC_DIG_OFFSET((ch)) + 0x08) +#define RK3308_ADC_DIG_CON03(ch) (RK3308_ADC_DIG_OFFSET((ch)) + 0x0c) +#define RK3308_ADC_DIG_CON04(ch) (RK3308_ADC_DIG_OFFSET((ch)) + 0x10) +#define RK3308_ADC_DIG_CON05(ch) (RK3308_ADC_DIG_OFFSET((ch)) + 0x14) // ver.C only +#define RK3308_ADC_DIG_CON06(ch) (RK3308_ADC_DIG_OFFSET((ch)) + 0x18) // ver.C only +#define RK3308_ADC_DIG_CON07(ch) (RK3308_ADC_DIG_OFFSET((ch)) + 0x1c) + +#define RK3308_ALC_L_DIG_CON00(ch) (RK3308_ADC_DIG_OFFSET((ch)) + 0x40) +#define RK3308_ALC_L_DIG_CON01(ch) (RK3308_ADC_DIG_OFFSET((ch)) + 0x44) +#define RK3308_ALC_L_DIG_CON02(ch) (RK3308_ADC_DIG_OFFSET((ch)) + 0x48) +#define RK3308_ALC_L_DIG_CON03(ch) (RK3308_ADC_DIG_OFFSET((ch)) + 0x4c) +#define RK3308_ALC_L_DIG_CON04(ch) (RK3308_ADC_DIG_OFFSET((ch)) + 0x50) +#define RK3308_ALC_L_DIG_CON05(ch) (RK3308_ADC_DIG_OFFSET((ch)) + 0x54) +#define RK3308_ALC_L_DIG_CON06(ch) (RK3308_ADC_DIG_OFFSET((ch)) + 0x58) +#define RK3308_ALC_L_DIG_CON07(ch) (RK3308_ADC_DIG_OFFSET((ch)) + 0x5c) +#define RK3308_ALC_L_DIG_CON08(ch) (RK3308_ADC_DIG_OFFSET((ch)) + 0x60) +#define RK3308_ALC_L_DIG_CON09(ch) (RK3308_ADC_DIG_OFFSET((ch)) + 0x64) +#define RK3308_ALC_L_DIG_CON12(ch) (RK3308_ADC_DIG_OFFSET((ch)) + 0x70) + +#define RK3308_ALC_R_DIG_CON00(ch) (RK3308_ADC_DIG_OFFSET((ch)) + 0x80) +#define RK3308_ALC_R_DIG_CON01(ch) (RK3308_ADC_DIG_OFFSET((ch)) + 0x84) +#define RK3308_ALC_R_DIG_CON02(ch) (RK3308_ADC_DIG_OFFSET((ch)) + 0x88) +#define RK3308_ALC_R_DIG_CON03(ch) (RK3308_ADC_DIG_OFFSET((ch)) + 0x8c) +#define RK3308_ALC_R_DIG_CON04(ch) (RK3308_ADC_DIG_OFFSET((ch)) + 0x90) +#define RK3308_ALC_R_DIG_CON05(ch) (RK3308_ADC_DIG_OFFSET((ch)) + 0x94) +#define RK3308_ALC_R_DIG_CON06(ch) (RK3308_ADC_DIG_OFFSET((ch)) + 0x98) +#define RK3308_ALC_R_DIG_CON07(ch) (RK3308_ADC_DIG_OFFSET((ch)) + 0x9c) +#define RK3308_ALC_R_DIG_CON08(ch) (RK3308_ADC_DIG_OFFSET((ch)) + 0xa0) +#define RK3308_ALC_R_DIG_CON09(ch) (RK3308_ADC_DIG_OFFSET((ch)) + 0xa4) +#define RK3308_ALC_R_DIG_CON12(ch) (RK3308_ADC_DIG_OFFSET((ch)) + 0xb0) + +/* DAC DIGITAL REGISTERS */ +#define RK3308_DAC_DIG_OFFSET 0x300 +#define RK3308_DAC_DIG_CON01 (RK3308_DAC_DIG_OFFSET + 0x04) +#define RK3308_DAC_DIG_CON02 (RK3308_DAC_DIG_OFFSET + 0x08) +#define RK3308_DAC_DIG_CON03 (RK3308_DAC_DIG_OFFSET + 0x0c) +#define RK3308_DAC_DIG_CON04 (RK3308_DAC_DIG_OFFSET + 0x10) +#define RK3308_DAC_DIG_CON05 (RK3308_DAC_DIG_OFFSET + 0x14) +#define RK3308_DAC_DIG_CON10 (RK3308_DAC_DIG_OFFSET + 0x28) +#define RK3308_DAC_DIG_CON11 (RK3308_DAC_DIG_OFFSET + 0x2c) +#define RK3308_DAC_DIG_CON13 (RK3308_DAC_DIG_OFFSET + 0x34) +#define RK3308_DAC_DIG_CON14 (RK3308_DAC_DIG_OFFSET + 0x38) + +/* ADC ANALOG REGISTERS */ +/* + * The ADC group are 0 ~ 3, that control: + * + * CH0: left_0(ADC1) and right_0(ADC2) + * CH1: left_1(ADC3) and right_1(ADC4) + * CH2: left_2(ADC5) and right_2(ADC6) + * CH3: left_3(ADC7) and right_3(ADC8) + */ +#define RK3308_ADC_ANA_OFFSET(ch) (((ch) & 0x3) * 0x40 + 0x340) +#define RK3308_ADC_ANA_CON00(ch) (RK3308_ADC_ANA_OFFSET((ch)) + 0x00) +#define RK3308_ADC_ANA_CON01(ch) (RK3308_ADC_ANA_OFFSET((ch)) + 0x04) +#define RK3308_ADC_ANA_CON02(ch) (RK3308_ADC_ANA_OFFSET((ch)) + 0x08) +#define RK3308_ADC_ANA_CON03(ch) (RK3308_ADC_ANA_OFFSET((ch)) + 0x0c) +#define RK3308_ADC_ANA_CON04(ch) (RK3308_ADC_ANA_OFFSET((ch)) + 0x10) +#define RK3308_ADC_ANA_CON05(ch) (RK3308_ADC_ANA_OFFSET((ch)) + 0x14) +#define RK3308_ADC_ANA_CON06(ch) (RK3308_ADC_ANA_OFFSET((ch)) + 0x18) +#define RK3308_ADC_ANA_CON07(ch) (RK3308_ADC_ANA_OFFSET((ch)) + 0x1c) +#define RK3308_ADC_ANA_CON08(ch) (RK3308_ADC_ANA_OFFSET((ch)) + 0x20) +#define RK3308_ADC_ANA_CON10(ch) (RK3308_ADC_ANA_OFFSET((ch)) + 0x28) +#define RK3308_ADC_ANA_CON11(ch) (RK3308_ADC_ANA_OFFSET((ch)) + 0x2c) + +/* DAC ANALOG REGISTERS */ +#define RK3308_DAC_ANA_OFFSET 0x440 +#define RK3308_DAC_ANA_CON00 (RK3308_DAC_ANA_OFFSET + 0x00) +#define RK3308_DAC_ANA_CON01 (RK3308_DAC_ANA_OFFSET + 0x04) +#define RK3308_DAC_ANA_CON02 (RK3308_DAC_ANA_OFFSET + 0x08) +#define RK3308_DAC_ANA_CON03 (RK3308_DAC_ANA_OFFSET + 0x0c) +#define RK3308_DAC_ANA_CON04 (RK3308_DAC_ANA_OFFSET + 0x10) +#define RK3308_DAC_ANA_CON05 (RK3308_DAC_ANA_OFFSET + 0x14) +#define RK3308_DAC_ANA_CON06 (RK3308_DAC_ANA_OFFSET + 0x18) +#define RK3308_DAC_ANA_CON07 (RK3308_DAC_ANA_OFFSET + 0x1c) +#define RK3308_DAC_ANA_CON08 (RK3308_DAC_ANA_OFFSET + 0x20) +#define RK3308_DAC_ANA_CON12 (RK3308_DAC_ANA_OFFSET + 0x30) +#define RK3308_DAC_ANA_CON13 (RK3308_DAC_ANA_OFFSET + 0x34) +#define RK3308_DAC_ANA_CON14 (RK3308_DAC_ANA_OFFSET + 0x38) +#define RK3308_DAC_ANA_CON15 (RK3308_DAC_ANA_OFFSET + 0x3c) + +/* + * These are the bits for registers + */ + +/* RK3308_GLB_CON - REG: 0x0000 */ +#define RK3308_ADC_BIST_WORK BIT(7) +#define RK3308_DAC_BIST_WORK BIT(6) +#define RK3308_ADC_MCLK_GATING BIT(5) +#define RK3308_DAC_MCLK_GATING BIT(4) +#define RK3308_ADC_DIG_WORK BIT(2) +#define RK3308_DAC_DIG_WORK BIT(1) +#define RK3308_SYS_WORK BIT(0) + +/* RK3308_ADC_DIG_CON01 - REG: 0x0004 */ +#define RK3308_ADC_I2S_LRC_POL_REVERSAL BIT(7) +#define RK3308_ADC_I2S_VALID_LEN_SFT 5 +#define RK3308_ADC_I2S_VALID_LEN_MSK (0x3 << RK3308_ADC_I2S_VALID_LEN_SFT) +#define RK3308_ADC_I2S_VALID_LEN_32BITS (0x3 << RK3308_ADC_I2S_VALID_LEN_SFT) +#define RK3308_ADC_I2S_VALID_LEN_24BITS (0x2 << RK3308_ADC_I2S_VALID_LEN_SFT) +#define RK3308_ADC_I2S_VALID_LEN_20BITS (0x1 << RK3308_ADC_I2S_VALID_LEN_SFT) +#define RK3308_ADC_I2S_VALID_LEN_16BITS (0x0 << RK3308_ADC_I2S_VALID_LEN_SFT) +#define RK3308_ADC_I2S_MODE_SFT 3 +#define RK3308_ADC_I2S_MODE_MSK (0x3 << RK3308_ADC_I2S_MODE_SFT) +#define RK3308_ADC_I2S_MODE_PCM (0x3 << RK3308_ADC_I2S_MODE_SFT) +#define RK3308_ADC_I2S_MODE_I2S (0x2 << RK3308_ADC_I2S_MODE_SFT) +#define RK3308_ADC_I2S_MODE_LJ (0x1 << RK3308_ADC_I2S_MODE_SFT) +#define RK3308_ADC_I2S_MODE_RJ (0x0 << RK3308_ADC_I2S_MODE_SFT) +#define RK3308_ADC_I2S_LR_SWAP BIT(1) +#define RK3308_ADC_I2S_MONO BIT(0) + +/* RK3308_ADC_DIG_CON02 - REG: 0x0008 */ +#define RK3308_ADC_IO_MODE_MASTER BIT(5) +#define RK3308_ADC_MODE_MASTER BIT(4) +#define RK3308_ADC_I2S_FRAME_LEN_SFT 2 +#define RK3308_ADC_I2S_FRAME_LEN_MSK (0x3 << RK3308_ADC_I2S_FRAME_LEN_SFT) +#define RK3308_ADC_I2S_FRAME_32BITS (0x3 << RK3308_ADC_I2S_FRAME_LEN_SFT) +#define RK3308_ADC_I2S_FRAME_24BITS (0x2 << RK3308_ADC_I2S_FRAME_LEN_SFT) +#define RK3308_ADC_I2S_FRAME_20BITS (0x1 << RK3308_ADC_I2S_FRAME_LEN_SFT) +#define RK3308_ADC_I2S_FRAME_16BITS (0x0 << RK3308_ADC_I2S_FRAME_LEN_SFT) +#define RK3308_ADC_I2S_WORK BIT(1) +#define RK3308_ADC_I2S_BIT_CLK_POL_REVERSAL BIT(0) + +/* RK3308_ADC_DIG_CON03 - REG: 0x000c */ +#define RK3308_ADC_L_CH_BIST_SFT 2 +#define RK3308_ADC_L_CH_BIST_MSK (0x3 << RK3308_ADC_L_CH_BIST_SFT) +#define RK3308_ADC_L_CH_NORMAL_RIGHT (0x3 << RK3308_ADC_L_CH_BIST_SFT) /* normal mode */ +#define RK3308_ADC_L_CH_BIST_CUBE (0x2 << RK3308_ADC_L_CH_BIST_SFT) +#define RK3308_ADC_L_CH_BIST_SINE (0x1 << RK3308_ADC_L_CH_BIST_SFT) +#define RK3308_ADC_L_CH_NORMAL_LEFT (0x0 << RK3308_ADC_L_CH_BIST_SFT) /* normal mode */ +#define RK3308_ADC_R_CH_BIST_SFT 0 +#define RK3308_ADC_R_CH_BIST_MSK (0x3 << RK3308_ADC_R_CH_BIST_SFT) +#define RK3308_ADC_R_CH_NORMAL_LEFT (0x3 << RK3308_ADC_R_CH_BIST_SFT) /* normal mode */ +#define RK3308_ADC_R_CH_BIST_CUBE (0x2 << RK3308_ADC_R_CH_BIST_SFT) +#define RK3308_ADC_R_CH_BIST_SINE (0x1 << RK3308_ADC_R_CH_BIST_SFT) +#define RK3308_ADC_R_CH_NORMAL_RIGHT (0x0 << RK3308_ADC_R_CH_BIST_SFT) /* normal mode */ + +/* RK3308_ADC_DIG_CON04 - REG: 0x0010 */ +#define RK3308_ADC_HPF_PATH_DIS BIT(2) +#define RK3308_ADC_HPF_CUTOFF_SFT 0 +#define RK3308_ADC_HPF_CUTOFF_MSK (0x3 << RK3308_ADC_HPF_CUTOFF_SFT) +#define RK3308_ADC_HPF_CUTOFF_612HZ (0x2 << RK3308_ADC_HPF_CUTOFF_SFT) +#define RK3308_ADC_HPF_CUTOFF_245HZ (0x1 << RK3308_ADC_HPF_CUTOFF_SFT) +#define RK3308_ADC_HPF_CUTOFF_20HZ (0x0 << RK3308_ADC_HPF_CUTOFF_SFT) + +/* RK3308_ADC_DIG_CON07 - REG: 0x001c */ +#define RK3308_ADCL_DATA_SFT 4 +#define RK3308_ADCR_DATA_SFT 2 +#define RK3308_ADCL_DATA_SEL_ADCL BIT(1) +#define RK3308_ADCR_DATA_SEL_ADCR BIT(0) + +/* + * RK3308_ALC_L_DIG_CON00 - REG: 0x0040 + ch * 0xc0 + * RK3308_ALC_R_DIG_CON00 - REG: 0x0080 + ch * 0xc0 + */ +#define RK3308_GAIN_ATTACK_JACK BIT(6) +#define RK3308_CTRL_GEN_SFT 4 +#define RK3308_CTRL_GEN_MSK (0x3 << RK3308_ALC_CTRL_GEN_SFT) +#define RK3308_CTRL_GEN_JACK3 (0x3 << RK3308_ALC_CTRL_GEN_SFT) +#define RK3308_CTRL_GEN_JACK2 (0x2 << RK3308_ALC_CTRL_GEN_SFT) +#define RK3308_CTRL_GEN_JACK1 (0x1 << RK3308_ALC_CTRL_GEN_SFT) +#define RK3308_CTRL_GEN_NORMAL (0x0 << RK3308_ALC_CTRL_GEN_SFT) +#define RK3308_AGC_HOLD_TIME_SFT 0 +#define RK3308_AGC_HOLD_TIME_MSK (0xf << RK3308_AGC_HOLD_TIME_SFT) +#define RK3308_AGC_HOLD_TIME_1S (0xa << RK3308_AGC_HOLD_TIME_SFT) +#define RK3308_AGC_HOLD_TIME_512MS (0x9 << RK3308_AGC_HOLD_TIME_SFT) +#define RK3308_AGC_HOLD_TIME_256MS (0x8 << RK3308_AGC_HOLD_TIME_SFT) +#define RK3308_AGC_HOLD_TIME_128MS (0x7 << RK3308_AGC_HOLD_TIME_SFT) +#define RK3308_AGC_HOLD_TIME_64MS (0x6 << RK3308_AGC_HOLD_TIME_SFT) +#define RK3308_AGC_HOLD_TIME_32MS (0x5 << RK3308_AGC_HOLD_TIME_SFT) +#define RK3308_AGC_HOLD_TIME_16MS (0x4 << RK3308_AGC_HOLD_TIME_SFT) +#define RK3308_AGC_HOLD_TIME_8MS (0x3 << RK3308_AGC_HOLD_TIME_SFT) +#define RK3308_AGC_HOLD_TIME_4MS (0x2 << RK3308_AGC_HOLD_TIME_SFT) +#define RK3308_AGC_HOLD_TIME_2MS (0x1 << RK3308_AGC_HOLD_TIME_SFT) +#define RK3308_AGC_HOLD_TIME_0MS (0x0 << RK3308_AGC_HOLD_TIME_SFT) + +/* + * RK3308_ALC_L_DIG_CON01 - REG: 0x0044 + ch * 0xc0 + * RK3308_ALC_R_DIG_CON01 - REG: 0x0084 + ch * 0xc0 + */ +#define RK3308_AGC_DECAY_TIME_SFT 4 +#define RK3308_AGC_ATTACK_TIME_SFT 0 + +/* + * RK3308_ALC_L_DIG_CON02 - REG: 0x0048 + ch * 0xc0 + * RK3308_ALC_R_DIG_CON02 - REG: 0x0088 + ch * 0xc0 + */ +#define RK3308_AGC_MODE_LIMITER BIT(7) +#define RK3308_AGC_ZERO_CRO_EN BIT(6) +#define RK3308_AGC_AMP_RECOVER_GAIN BIT(5) +#define RK3308_AGC_FAST_DEC_EN BIT(4) +#define RK3308_AGC_NOISE_GATE_EN BIT(3) +#define RK3308_AGC_NOISE_GATE_THRESH_SFT 0 +#define RK3308_AGC_NOISE_GATE_THRESH_MSK (0x7 << RK3308_AGC_NOISE_GATE_THRESH_SFT) + +/* + * RK3308_ALC_L_DIG_CON03 - REG: 0x004c + ch * 0xc0 + * RK3308_ALC_R_DIG_CON03 - REG: 0x008c + ch * 0xc0 + */ +#define RK3308_AGC_PGA_ZERO_CRO_EN BIT(5) +#define RK3308_AGC_PGA_GAIN_MAX 0x1f +#define RK3308_AGC_PGA_GAIN_MIN 0 +#define RK3308_AGC_PGA_GAIN_SFT 0 + +/* + * RK3308_ALC_L_DIG_CON04 - REG: 0x0050 + ch * 0xc0 + * RK3308_ALC_R_DIG_CON04 - REG: 0x0090 + ch * 0xc0 + */ +#define RK3308_AGC_SLOW_CLK_EN BIT(3) +#define RK3308_AGC_APPROX_RATE_SFT 0 +#define RK3308_AGC_APPROX_RATE_MSK (0x7 << RK3308_AGC_APPROX_RATE_SFT) + +/* + * RK3308_ALC_L_DIG_CON05 - REG: 0x0054 + ch * 0xc0 + * RK3308_ALC_R_DIG_CON05 - REG: 0x0094 + ch * 0xc0 + */ +#define RK3308_AGC_LO_8BITS_AGC_MAX_MSK 0xff + +/* + * RK3308_ALC_L_DIG_CON06 - REG: 0x0058 + ch * 0xc0 + * RK3308_ALC_R_DIG_CON06 - REG: 0x0098 + ch * 0xc0 + */ +#define RK3308_AGC_HI_8BITS_AGC_MAX_MSK 0xff + +/* + * RK3308_ALC_L_DIG_CON07 - REG: 0x005c + ch * 0xc0 + * RK3308_ALC_R_DIG_CON07 - REG: 0x009c + ch * 0xc0 + */ +#define RK3308_AGC_LO_8BITS_AGC_MIN_MSK 0xff + +/* + * RK3308_ALC_L_DIG_CON08 - REG: 0x0060 + ch * 0xc0 + * RK3308_ALC_R_DIG_CON08 - REG: 0x00a0 + ch * 0xc0 + */ +#define RK3308_AGC_HI_8BITS_AGC_MIN_MSK 0xff + +/* + * RK3308_ALC_L_DIG_CON09 - REG: 0x0064 + ch * 0xc0 + * RK3308_ALC_R_DIG_CON09 - REG: 0x00a4 + ch * 0xc0 + */ +#define RK3308_AGC_FUNC_SEL BIT(6) +#define RK3308_AGC_MAX_GAIN_PGA_MAX 0x7 +#define RK3308_AGC_MAX_GAIN_PGA_MIN 0 +#define RK3308_AGC_MAX_GAIN_PGA_SFT 3 +#define RK3308_AGC_MAX_GAIN_PGA_MSK (0x7 << RK3308_AGC_MAX_GAIN_PGA_SFT) +#define RK3308_AGC_MIN_GAIN_PGA_MAX 0x7 +#define RK3308_AGC_MIN_GAIN_PGA_MIN 0 +#define RK3308_AGC_MIN_GAIN_PGA_SFT 0 +#define RK3308_AGC_MIN_GAIN_PGA_MSK (0x7 << RK3308_AGC_MIN_GAIN_PGA_SFT) + +/* + * RK3308_ALC_L_DIG_CON12 - REG: 0x0068 + ch * 0xc0 + * RK3308_ALC_R_DIG_CON12 - REG: 0x00a8 + ch * 0xc0 + */ +#define RK3308_AGC_GAIN_MSK 0x1f + +/* RK3308_DAC_DIG_CON01 - REG: 0x0304 */ +#define RK3308_DAC_I2S_LRC_POL_REVERSAL BIT(7) +#define RK3308_DAC_I2S_VALID_LEN_SFT 5 +#define RK3308_DAC_I2S_VALID_LEN_MSK (0x3 << RK3308_DAC_I2S_VALID_LEN_SFT) +#define RK3308_DAC_I2S_VALID_LEN_32BITS (0x3 << RK3308_DAC_I2S_VALID_LEN_SFT) +#define RK3308_DAC_I2S_VALID_LEN_24BITS (0x2 << RK3308_DAC_I2S_VALID_LEN_SFT) +#define RK3308_DAC_I2S_VALID_LEN_20BITS (0x1 << RK3308_DAC_I2S_VALID_LEN_SFT) +#define RK3308_DAC_I2S_VALID_LEN_16BITS (0x0 << RK3308_DAC_I2S_VALID_LEN_SFT) +#define RK3308_DAC_I2S_MODE_SFT 3 +#define RK3308_DAC_I2S_MODE_MSK (0x3 << RK3308_DAC_I2S_MODE_SFT) +#define RK3308_DAC_I2S_MODE_PCM (0x3 << RK3308_DAC_I2S_MODE_SFT) +#define RK3308_DAC_I2S_MODE_I2S (0x2 << RK3308_DAC_I2S_MODE_SFT) +#define RK3308_DAC_I2S_MODE_LJ (0x1 << RK3308_DAC_I2S_MODE_SFT) +#define RK3308_DAC_I2S_MODE_RJ (0x0 << RK3308_DAC_I2S_MODE_SFT) +#define RK3308_DAC_I2S_LR_SWAP BIT(2) + +/* RK3308_DAC_DIG_CON02 - REG: 0x0308 */ +#define RK3308BS_DAC_IO_MODE_MASTER BIT(7) +#define RK3308BS_DAC_MODE_MASTER BIT(6) +#define RK3308_DAC_IO_MODE_MASTER BIT(5) +#define RK3308_DAC_MODE_MASTER BIT(4) +#define RK3308_DAC_I2S_FRAME_LEN_SFT 2 +#define RK3308_DAC_I2S_FRAME_LEN_MSK (0x3 << RK3308_DAC_I2S_FRAME_LEN_SFT) +#define RK3308_DAC_I2S_FRAME_32BITS (0x3 << RK3308_DAC_I2S_FRAME_LEN_SFT) +#define RK3308_DAC_I2S_FRAME_24BITS (0x2 << RK3308_DAC_I2S_FRAME_LEN_SFT) +#define RK3308_DAC_I2S_FRAME_20BITS (0x1 << RK3308_DAC_I2S_FRAME_LEN_SFT) +#define RK3308_DAC_I2S_FRAME_16BITS (0x0 << RK3308_DAC_I2S_FRAME_LEN_SFT) +#define RK3308_DAC_I2S_WORK BIT(1) +#define RK3308_DAC_I2S_BIT_CLK_POL_REVERSAL BIT(0) + +/* RK3308_DAC_DIG_CON03 - REG: 0x030C */ +#define RK3308_DAC_L_CH_BIST_SFT 2 +#define RK3308_DAC_L_CH_BIST_MSK (0x3 << RK3308_DAC_L_CH_BIST_SFT) +#define RK3308_DAC_L_CH_BIST_LEFT (0x3 << RK3308_DAC_L_CH_BIST_SFT) /* normal mode */ +#define RK3308_DAC_L_CH_BIST_CUBE (0x2 << RK3308_DAC_L_CH_BIST_SFT) +#define RK3308_DAC_L_CH_BIST_SINE (0x1 << RK3308_DAC_L_CH_BIST_SFT) +#define RK3308_DAC_L_CH_BIST_RIGHT (0x0 << RK3308_DAC_L_CH_BIST_SFT) /* normal mode */ +#define RK3308_DAC_R_CH_BIST_SFT 0 +#define RK3308_DAC_R_CH_BIST_MSK (0x3 << RK3308_DAC_R_CH_BIST_SFT) +#define RK3308_DAC_R_CH_BIST_LEFT (0x3 << RK3308_DAC_R_CH_BIST_SFT) /* normal mode */ +#define RK3308_DAC_R_CH_BIST_CUBE (0x2 << RK3308_DAC_R_CH_BIST_SFT) +#define RK3308_DAC_R_CH_BIST_SINE (0x1 << RK3308_DAC_R_CH_BIST_SFT) +#define RK3308_DAC_R_CH_BIST_RIGHT (0x0 << RK3308_DAC_R_CH_BIST_SFT) /* normal mode */ + +/* RK3308_DAC_DIG_CON04 - REG: 0x0310 */ +/* Versions up to B: */ +#define RK3308_DAC_MODULATOR_GAIN_SFT 4 +#define RK3308_DAC_MODULATOR_GAIN_MSK (0x7 << RK3308_DAC_MODULATOR_GAIN_SFT) +#define RK3308_DAC_CIC_IF_GAIN_SFT 0 +#define RK3308_DAC_CIC_IF_GAIN_MSK (0x7 << RK3308_DAC_CIC_IF_GAIN_SFT) +/* Version C: */ +#define RK3308BS_DAC_DIG_GAIN_SFT 0 +#define RK3308BS_DAC_DIG_GAIN_MSK (0xff << RK3308BS_DAC_DIG_GAIN_SFT) +#define RK3308BS_DAC_DIG_GAIN_0DB (0xed << RK3308BS_DAC_DIG_GAIN_SFT) + +/* RK3308BS_ADC_DIG_CON05..06 (Version C only) */ +#define RK3308_ADC_DIG_VOL_CON_x_SFT 0 +#define RK3308_ADC_DIG_VOL_CON_x_MSK (0xff << RK3308_ADC_DIG_VOL_CON_x_SFT) +#define RK3308_ADC_DIG_VOL_CON_x_0DB (0xc2 << RK3308_ADC_DIG_VOL_CON_x_SFT) + +/* RK3308_DAC_DIG_CON05 - REG: 0x0314 */ +#define RK3308_DAC_L_REG_CTL_INDATA BIT(2) +#define RK3308_DAC_R_REG_CTL_INDATA BIT(1) + +/* RK3308_DAC_DIG_CON10 - REG: 0x0328 */ +#define RK3308_DAC_DATA_HI4(x) ((x) & 0xf) + +/* RK3308_DAC_DIG_CON11 - REG: 0x032c */ +#define RK3308_DAC_DATA_LO8(x) ((x) & 0xff) + +/* RK3308_ADC_ANA_CON00 - REG: 0x0340 */ +#define RK3308_ADC_CH1_CH2_MIC_ALL_MSK (0xff << 0) +#define RK3308_ADC_CH1_CH2_MIC_ALL 0xff +#define RK3308_ADC_CH2_MIC_UNMUTE BIT(7) +#define RK3308_ADC_CH2_MIC_WORK BIT(6) +#define RK3308_ADC_CH2_MIC_EN BIT(5) +#define RK3308_ADC_CH2_BUF_REF_EN BIT(4) +#define RK3308_ADC_CH1_MIC_UNMUTE BIT(3) +#define RK3308_ADC_CH1_MIC_WORK BIT(2) +#define RK3308_ADC_CH1_MIC_EN BIT(1) +#define RK3308_ADC_CH1_BUF_REF_EN BIT(0) + +/* RK3308_ADC_ANA_CON01 - REG: 0x0344 + * + * The PGA of MIC-INs: + * - HW version A: + * 0x0 - MIC1~MIC8 0 dB (recommended when ADC used as loopback) + * 0x3 - MIC1~MIC8 20 dB (recommended when ADC used as MIC input) + * - HW version B: + * 0x0 - MIC1~MIC8 0 dB + * 0x1 - MIC1~MIC8 6.6 dB + * 0x2 - MIC1~MIC8 13 dB + * 0x3 - MIC1~MIC8 20 dB + */ +#define RK3308_ADC_CH2_MIC_GAIN_MAX 0x3 +#define RK3308_ADC_CH2_MIC_GAIN_MIN 0 +#define RK3308_ADC_CH2_MIC_GAIN_SFT 4 +#define RK3308_ADC_CH2_MIC_GAIN_MSK (0x3 << RK3308_ADC_CH2_MIC_GAIN_SFT) +#define RK3308_ADC_CH2_MIC_GAIN_20DB (0x3 << RK3308_ADC_CH2_MIC_GAIN_SFT) +#define RK3308_ADC_CH2_MIC_GAIN_13DB (0x2 << RK3308_ADC_CH2_MIC_GAIN_SFT) +#define RK3308_ADC_CH2_MIC_GAIN_6_6DB (0x1 << RK3308_ADC_CH2_MIC_GAIN_SFT) +#define RK3308_ADC_CH2_MIC_GAIN_0DB (0x0 << RK3308_ADC_CH2_MIC_GAIN_SFT) + +#define RK3308_ADC_CH1_MIC_GAIN_MAX 0x3 +#define RK3308_ADC_CH1_MIC_GAIN_MIN 0 +#define RK3308_ADC_CH1_MIC_GAIN_SFT 0 +#define RK3308_ADC_CH1_MIC_GAIN_MSK (0x3 << RK3308_ADC_CH1_MIC_GAIN_SFT) +#define RK3308_ADC_CH1_MIC_GAIN_20DB (0x3 << RK3308_ADC_CH1_MIC_GAIN_SFT) +#define RK3308_ADC_CH1_MIC_GAIN_13DB (0x2 << RK3308_ADC_CH1_MIC_GAIN_SFT) +#define RK3308_ADC_CH1_MIC_GAIN_6_6DB (0x1 << RK3308_ADC_CH1_MIC_GAIN_SFT) +#define RK3308_ADC_CH1_MIC_GAIN_0DB (0x0 << RK3308_ADC_CH1_MIC_GAIN_SFT) + +/* RK3308_ADC_ANA_CON02 - REG: 0x0348 */ +#define RK3308_ADC_CH2_ZEROCROSS_DET_EN BIT(6) +#define RK3308_ADC_CH2_ALC_WORK BIT(5) +#define RK3308_ADC_CH2_ALC_EN BIT(4) +#define RK3308_ADC_CH1_ZEROCROSS_DET_EN BIT(2) +#define RK3308_ADC_CH1_ALC_WORK BIT(1) +#define RK3308_ADC_CH1_ALC_EN BIT(0) + +/* RK3308_ADC_ANA_CON03 - REG: 0x034c */ +#define RK3308_ADC_CH1_ALC_GAIN_MAX 0x1f +#define RK3308_ADC_CH1_ALC_GAIN_MIN 0 +#define RK3308_ADC_CH1_ALC_GAIN_SFT 0 +#define RK3308_ADC_CH1_ALC_GAIN_MSK (0x1f << RK3308_ADC_CH1_ALC_GAIN_SFT) +#define RK3308_ADC_CH1_ALC_GAIN_0DB (0x0c << RK3308_ADC_CH1_ALC_GAIN_SFT) + +/* RK3308_ADC_ANA_CON04 - REG: 0x0350 */ +#define RK3308_ADC_CH2_ALC_GAIN_MAX 0x1f +#define RK3308_ADC_CH2_ALC_GAIN_MIN 0 +#define RK3308_ADC_CH2_ALC_GAIN_SFT 0 +#define RK3308_ADC_CH2_ALC_GAIN_MSK (0x1f << RK3308_ADC_CH2_ALC_GAIN_SFT) +#define RK3308_ADC_CH2_ALC_GAIN_0DB (0x0c << RK3308_ADC_CH2_ALC_GAIN_SFT) + +/* RK3308_ADC_ANA_CON05 - REG: 0x0354 */ +#define RK3308_ADC_CH2_ADC_WORK BIT(6) +#define RK3308_ADC_CH2_ADC_EN BIT(5) +#define RK3308_ADC_CH2_CLK_EN BIT(4) +#define RK3308_ADC_CH1_ADC_WORK BIT(2) +#define RK3308_ADC_CH1_ADC_EN BIT(1) +#define RK3308_ADC_CH1_CLK_EN BIT(0) + +/* RK3308_ADC_ANA_CON06 - REG: 0x0358 */ +#define RK3308_ADC_CURRENT_EN BIT(0) + +/* RK3308_ADC_ANA_CON07 - REG: 0x035c */ +/* Note: The register configuration is only valid for ADC2 */ +#define RK3308_ADC_CH2_IN_SEL_SFT 6 +#define RK3308_ADC_CH2_IN_SEL_MSK (0x3 << RK3308_ADC_CH2_IN_SEL_SFT) +#define RK3308_ADC_CH2_IN_LINEIN_MIC (0x3 << RK3308_ADC_CH2_IN_SEL_SFT) +#define RK3308_ADC_CH2_IN_LINEIN (0x2 << RK3308_ADC_CH2_IN_SEL_SFT) +#define RK3308_ADC_CH2_IN_MIC (0x1 << RK3308_ADC_CH2_IN_SEL_SFT) +#define RK3308_ADC_CH2_IN_NONE (0x0 << RK3308_ADC_CH2_IN_SEL_SFT) +/* Note: The register configuration is only valid for ADC1 */ +#define RK3308_ADC_CH1_IN_SEL_SFT 4 +#define RK3308_ADC_CH1_IN_SEL_MSK (0x3 << RK3308_ADC_CH1_IN_SEL_SFT) +#define RK3308_ADC_CH1_IN_LINEIN_MIC (0x3 << RK3308_ADC_CH1_IN_SEL_SFT) +#define RK3308_ADC_CH1_IN_LINEIN (0x2 << RK3308_ADC_CH1_IN_SEL_SFT) +#define RK3308_ADC_CH1_IN_MIC (0x1 << RK3308_ADC_CH1_IN_SEL_SFT) +#define RK3308_ADC_CH1_IN_NONE (0x0 << RK3308_ADC_CH1_IN_SEL_SFT) +#define RK3308_ADC_MIC_BIAS_BUF_EN BIT(3) +#define RK3308_ADC_LEVEL_RANGE_MICBIAS_MAX 7 +#define RK3308_ADC_LEVEL_RANGE_MICBIAS_SFT 0 +#define RK3308_ADC_LEVEL_RANGE_MICBIAS_MSK (0x7 << RK3308_ADC_LEVEL_RANGE_MICBIAS_SFT) + +/* RK3308_ADC_ANA_CON08 - REG: 0x0360 */ +#define RK3308_ADC_MICBIAS_CURRENT_EN BIT(4) + +/* RK3308_ADC_ANA_CON10 - REG: 0x0368 */ +#define RK3308_ADC_REF_EN BIT(7) +#define RK3308_ADC_CURRENT_CHARGE_SFT 0 +#define RK3308_ADC_CURRENT_CHARGE_MSK (0x7f << RK3308_ADC_CURRENT_CHARGE_SFT) + +/* RK3308_ADC_ANA_CON11 - REG: 0x036c */ +#define RK3308_ADC_ALCR_CON_GAIN_PGAR_EN BIT(1) +#define RK3308_ADC_ALCL_CON_GAIN_PGAL_EN BIT(0) + +/* RK3308_DAC_ANA_CON00 - REG: 0x0440 */ +#define RK3308_DAC_HEADPHONE_DET_EN BIT(1) +#define RK3308_DAC_CURRENT_EN BIT(0) + +/* RK3308_DAC_ANA_CON01 - REG: 0x0444 */ +#define RK3308_DAC_BUF_REF_R_EN BIT(6) +#define RK3308_DAC_BUF_REF_L_EN BIT(2) +#define RK3308_DAC_HPOUT_POP_SOUND_R_SFT 4 +#define RK3308_DAC_HPOUT_POP_SOUND_L_SFT 0 +// unshifted values for both L and R: +#define RK3308_DAC_HPOUT_POP_SOUND_x_MSK 0x3 +#define RK3308_DAC_HPOUT_POP_SOUND_x_WORK 0x2 +#define RK3308_DAC_HPOUT_POP_SOUND_x_INIT 0x1 + +/* RK3308_DAC_ANA_CON02 - REG: 0x0448 */ +#define RK3308_DAC_R_DAC_WORK BIT(7) +#define RK3308_DAC_R_DAC_EN BIT(6) +#define RK3308_DAC_R_CLK_EN BIT(5) +#define RK3308_DAC_R_REF_EN BIT(4) +#define RK3308_DAC_L_DAC_WORK BIT(3) +#define RK3308_DAC_L_DAC_EN BIT(2) +#define RK3308_DAC_L_CLK_EN BIT(1) +#define RK3308_DAC_L_REF_EN BIT(0) + +/* RK3308_DAC_ANA_CON03 - REG: 0x044c */ +#define RK3308_DAC_R_HPOUT_WORK BIT(6) +#define RK3308_DAC_R_HPOUT_EN BIT(5) +#define RK3308_DAC_R_HPOUT_MUTE_SFT 4 +#define RK3308_DAC_L_HPOUT_WORK BIT(2) +#define RK3308_DAC_L_HPOUT_EN BIT(1) +#define RK3308_DAC_L_HPOUT_MUTE_SFT 0 + +/* RK3308_DAC_ANA_CON04 - REG: 0x0450 */ +#define RK3308_DAC_x_LINEOUT_GAIN_MAX 0x3 +#define RK3308_DAC_R_LINEOUT_GAIN_SFT 6 +#define RK3308_DAC_R_LINEOUT_GAIN_MSK (0x3 << RK3308_DAC_R_LINEOUT_GAIN_SFT) +#define RK3308_DAC_R_LINEOUT_GAIN_0DB (0x3 << RK3308_DAC_R_LINEOUT_GAIN_SFT) +#define RK3308_DAC_R_LINEOUT_GAIN_NDB_1_5 (0x2 << RK3308_DAC_R_LINEOUT_GAIN_SFT) +#define RK3308_DAC_R_LINEOUT_GAIN_NDB_3 (0x1 << RK3308_DAC_R_LINEOUT_GAIN_SFT) +#define RK3308_DAC_R_LINEOUT_GAIN_NDB_6 (0x0 << RK3308_DAC_R_LINEOUT_GAIN_SFT) +#define RK3308_DAC_R_LINEOUT_MUTE_SFT 5 +#define RK3308_DAC_R_LINEOUT_EN BIT(4) +#define RK3308_DAC_L_LINEOUT_GAIN_SFT 2 +#define RK3308_DAC_L_LINEOUT_GAIN_MSK (0x3 << RK3308_DAC_L_LINEOUT_GAIN_SFT) +#define RK3308_DAC_L_LINEOUT_GAIN_0DB (0x3 << RK3308_DAC_L_LINEOUT_GAIN_SFT) +#define RK3308_DAC_L_LINEOUT_GAIN_NDB_1_5 (0x2 << RK3308_DAC_L_LINEOUT_GAIN_SFT) +#define RK3308_DAC_L_LINEOUT_GAIN_NDB_3 (0x1 << RK3308_DAC_L_LINEOUT_GAIN_SFT) +#define RK3308_DAC_L_LINEOUT_GAIN_NDB_6 (0x0 << RK3308_DAC_L_LINEOUT_GAIN_SFT) +#define RK3308_DAC_L_LINEOUT_MUTE_SFT 1 +#define RK3308_DAC_L_LINEOUT_EN BIT(0) + +/* RK3308_DAC_ANA_CON05 - REG: 0x0454, step is 1.5db */ +/* RK3308_DAC_ANA_CON06 - REG: 0x0458, step is 1.5db */ +#define RK3308_DAC_x_HPOUT_GAIN_MAX 0x1e +#define RK3308_DAC_x_HPOUT_GAIN_SFT 0 +#define RK3308_DAC_x_HPOUT_GAIN_MSK (0x1f << RK3308_DAC_x_HPOUT_GAIN_SFT) +#define RK3308_DAC_x_HPOUT_GAIN_MIN (0x00 << RK3308_DAC_x_HPOUT_GAIN_SFT) + +/* RK3308_DAC_ANA_CON07 - REG: 0x045c */ +#define RK3308_DAC_R_HPOUT_DRV_SFT 4 +#define RK3308_DAC_R_HPOUT_DRV_MSK (0xf << RK3308_DAC_R_HPOUT_DRV_SFT) +#define RK3308_DAC_L_HPOUT_DRV_SFT 0 +#define RK3308_DAC_L_HPOUT_DRV_MSK (0xf << RK3308_DAC_L_HPOUT_DRV_SFT) + +/* RK3308_DAC_ANA_CON08 - REG: 0x0460 */ +#define RK3308_DAC_R_LINEOUT_DRV_SFT 4 +#define RK3308_DAC_R_LINEOUT_DRV_MSK (0xf << RK3308_DAC_R_LINEOUT_DRV_SFT) +#define RK3308_DAC_L_LINEOUT_DRV_SFT 0 +#define RK3308_DAC_L_LINEOUT_DRV_MSK (0xf << RK3308_DAC_L_LINEOUT_DRV_SFT) + +/* RK3308_DAC_ANA_CON12 - REG: 0x0470 */ +#define RK3308_DAC_R_HPMIX_SEL_SFT 6 +#define RK3308_DAC_R_HPMIX_SEL_MSK (0x3 << RK3308_DAC_R_HPMIX_SEL_SFT) +#define RK3308_DAC_R_HPMIX_LINEIN_I2S (0x3 << RK3308_DAC_R_HPMIX_SEL_SFT) +#define RK3308_DAC_R_HPMIX_LINEIN (0x2 << RK3308_DAC_R_HPMIX_SEL_SFT) +#define RK3308_DAC_R_HPMIX_I2S (0x1 << RK3308_DAC_R_HPMIX_SEL_SFT) +#define RK3308_DAC_R_HPMIX_NONE (0x0 << RK3308_DAC_R_HPMIX_SEL_SFT) +#define RK3308_DAC_L_HPMIX_SEL_SFT 2 +#define RK3308_DAC_L_HPMIX_SEL_MSK (0x3 << RK3308_DAC_L_HPMIX_SEL_SFT) +#define RK3308_DAC_L_HPMIX_LINEIN_I2S (0x3 << RK3308_DAC_L_HPMIX_SEL_SFT) +#define RK3308_DAC_L_HPMIX_LINEIN (0x2 << RK3308_DAC_L_HPMIX_SEL_SFT) +#define RK3308_DAC_L_HPMIX_I2S (0x1 << RK3308_DAC_L_HPMIX_SEL_SFT) +#define RK3308_DAC_L_HPMIX_NONE (0x0 << RK3308_DAC_L_HPMIX_SEL_SFT) +#define RK3308_DAC_x_HPMIX_GAIN_MIN 0x1 /* 0x0 and 0x3 are reserved */ +#define RK3308_DAC_x_HPMIX_GAIN_MAX 0x2 +#define RK3308_DAC_R_HPMIX_GAIN_SFT 4 +#define RK3308_DAC_R_HPMIX_GAIN_MSK (0x3 << RK3308_DAC_R_HPMIX_GAIN_SFT) +#define RK3308_DAC_R_HPMIX_GAIN_0DB (0x2 << RK3308_DAC_R_HPMIX_GAIN_SFT) +#define RK3308_DAC_R_HPMIX_GAIN_NDB_6 (0x1 << RK3308_DAC_R_HPMIX_GAIN_SFT) +#define RK3308_DAC_L_HPMIX_GAIN_SFT 0 +#define RK3308_DAC_L_HPMIX_GAIN_MSK (0x3 << RK3308_DAC_L_HPMIX_GAIN_SFT) +#define RK3308_DAC_L_HPMIX_GAIN_0DB (0x2 << RK3308_DAC_L_HPMIX_GAIN_SFT) +#define RK3308_DAC_L_HPMIX_GAIN_NDB_6 (0x1 << RK3308_DAC_L_HPMIX_GAIN_SFT) + +/* RK3308_DAC_ANA_CON13 - REG: 0x0474 */ +#define RK3308_DAC_R_HPMIX_UNMUTE BIT(6) +#define RK3308_DAC_R_HPMIX_WORK BIT(5) +#define RK3308_DAC_R_HPMIX_EN BIT(4) +#define RK3308_DAC_L_HPMIX_UNMUTE BIT(2) +#define RK3308_DAC_L_HPMIX_WORK BIT(1) +#define RK3308_DAC_L_HPMIX_EN BIT(0) + +/* RK3308_DAC_ANA_CON14 - REG: 0x0478 */ +#define RK3308_DAC_VCM_LINEOUT_EN (0x1 << 4) +#define RK3308_DAC_CURRENT_CHARGE_SFT 0 +#define RK3308_DAC_CURRENT_CHARGE_MSK (0xf << RK3308_DAC_CURRENT_CHARGE_SFT) + +/* RK3308_DAC_ANA_CON15 - REG: 0x047C */ +#define RK3308_DAC_LINEOUT_POP_SOUND_R_SFT 4 +#define RK3308_DAC_LINEOUT_POP_SOUND_R_MSK (0x3 << RK3308_DAC_LINEOUT_POP_SOUND_R_SFT) +#define RK3308_DAC_R_SEL_DC_FROM_INTERNAL (0x2 << RK3308_DAC_LINEOUT_POP_SOUND_R_SFT) +#define RK3308_DAC_R_SEL_DC_FROM_VCM (0x1 << RK3308_DAC_LINEOUT_POP_SOUND_R_SFT) +#define RK3308_DAC_R_SEL_LINEOUT_FROM_INTERNAL (0x0 << RK3308_DAC_LINEOUT_POP_SOUND_R_SFT) +#define RK3308_DAC_LINEOUT_POP_SOUND_L_SFT 0 +#define RK3308_DAC_LINEOUT_POP_SOUND_L_MSK (0x3 << RK3308_DAC_LINEOUT_POP_SOUND_L_SFT) +#define RK3308_DAC_L_SEL_DC_FROM_INTERNAL (0x2 << RK3308_DAC_LINEOUT_POP_SOUND_L_SFT) +#define RK3308_DAC_L_SEL_DC_FROM_VCM (0x1 << RK3308_DAC_LINEOUT_POP_SOUND_L_SFT) +#define RK3308_DAC_L_SEL_LINEOUT_FROM_INTERNAL (0x0 << RK3308_DAC_LINEOUT_POP_SOUND_L_SFT) + +#endif /* __RK3308_CODEC_H__ */ -- cgit v1.2.3 From 087777347bea060f82fa97827e7d1f625c0f9376 Mon Sep 17 00:00:00 2001 From: Charles Keepax Date: Tue, 26 Mar 2024 11:03:56 -0500 Subject: ASoC: intel: sof_sdw: Make find_codec_info_part() return a pointer Rather than returning an index simply return a pointer to the located codec info, this simplifies all the callers which only want to access the codec info structure. Also remove the inline specifier the function is fairly large for an inline function, let the compiler decide. Reviewed-by: Bard Liao Signed-off-by: Charles Keepax Signed-off-by: Pierre-Louis Bossart Link: https://msgid.link/r/20240326160429.13560-2-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/intel/boards/sof_sdw.c | 79 ++++++++++++++++++---------------------- 1 file changed, 36 insertions(+), 43 deletions(-) diff --git a/sound/soc/intel/boards/sof_sdw.c b/sound/soc/intel/boards/sof_sdw.c index 08f330ed5c2e..08b19a32cf9c 100644 --- a/sound/soc/intel/boards/sof_sdw.c +++ b/sound/soc/intel/boards/sof_sdw.c @@ -1055,7 +1055,7 @@ static struct sof_sdw_codec_info codec_info_list[] = { }, }; -static inline int find_codec_info_part(const u64 adr) +static struct sof_sdw_codec_info *find_codec_info_part(const u64 adr) { unsigned int part_id, sdw_version; int i; @@ -1070,9 +1070,9 @@ static inline int find_codec_info_part(const u64 adr) if (part_id == codec_info_list[i].part_id && (!codec_info_list[i].version_id || sdw_version == codec_info_list[i].version_id)) - return i; + return &codec_info_list[i]; - return -EINVAL; + return NULL; } @@ -1116,7 +1116,6 @@ static int get_dailink_info(struct device *dev, for (; adr_link->num_adr; adr_link++) { const struct snd_soc_acpi_endpoint *endpoint; struct sof_sdw_codec_info *codec_info; - int codec_index; int stream; u64 adr; @@ -1126,11 +1125,9 @@ static int get_dailink_info(struct device *dev, for (i = 0; i < adr_link->num_adr; i++) { adr = adr_link->adr_d[i].adr; - codec_index = find_codec_info_part(adr); - if (codec_index < 0) - return codec_index; - - codec_info = &codec_info_list[codec_index]; + codec_info = find_codec_info_part(adr); + if (!codec_info) + return -EINVAL; *codecs_num += codec_info->dai_num; @@ -1257,11 +1254,11 @@ static int fill_sdw_codec_dlc(struct device *dev, { unsigned int sdw_version, unique_id, mfg_id, link_id, part_id, class_id; u64 adr = adr_link->adr_d[adr_index].adr; - int codec_index; + struct sof_sdw_codec_info *codec_info; - codec_index = find_codec_info_part(adr); - if (codec_index < 0) - return codec_index; + codec_info = find_codec_info_part(adr); + if (!codec_info) + return -EINVAL; sdw_version = SDW_VERSION(adr); link_id = SDW_DISCO_LINK_ID(adr); @@ -1270,10 +1267,8 @@ static int fill_sdw_codec_dlc(struct device *dev, part_id = SDW_PART_ID(adr); class_id = SDW_CLASS_ID(adr); - if (codec_info_list[codec_index].codec_name) - codec->name = devm_kstrdup(dev, - codec_info_list[codec_index].codec_name, - GFP_KERNEL); + if (codec_info->codec_name) + codec->name = devm_kstrdup(dev, codec_info->codec_name, GFP_KERNEL); else if (is_unique_device(adr_link, sdw_version, mfg_id, part_id, class_id, adr_index)) codec->name = devm_kasprintf(dev, GFP_KERNEL, @@ -1287,7 +1282,7 @@ static int fill_sdw_codec_dlc(struct device *dev, if (!codec->name) return -ENOMEM; - codec->dai_name = codec_info_list[codec_index].dais[dai_index].dai_name; + codec->dai_name = codec_info->dais[dai_index].dai_name; return 0; } @@ -1309,22 +1304,22 @@ static int set_codec_init_func(struct snd_soc_card *card, * we should end immediately if it is not aggregated (group_id=0) */ for ( ; i < adr_link->num_adr; i++) { - int codec_index; + struct sof_sdw_codec_info *codec_info; - codec_index = find_codec_info_part(adr_link->adr_d[i].adr); - if (codec_index < 0) - return codec_index; + codec_info = find_codec_info_part(adr_link->adr_d[i].adr); + if (!codec_info) + return -EINVAL; /* The group_id is > 0 iff the codec is aggregated */ if (adr_link->adr_d[i].endpoints->group_id != group_id) continue; - if (codec_info_list[codec_index].dais[dai_index].init) - codec_info_list[codec_index].dais[dai_index].init(card, - adr_link, - dai_links, - &codec_info_list[codec_index], - playback); + if (codec_info->dais[dai_index].init) + codec_info->dais[dai_index].init(card, + adr_link, + dai_links, + codec_info, + playback); if (!group_id) return 0; } @@ -1481,7 +1476,6 @@ static int create_sdw_dailink(struct snd_soc_card *card, int *link_index, int cpu_dai_num; unsigned int group_id; int codec_dlc_index = 0; - int codec_index; int codec_num; int stream; int i = 0; @@ -1541,10 +1535,9 @@ static int create_sdw_dailink(struct snd_soc_card *card, int *link_index, } /* find codec info to create BE DAI */ - codec_index = find_codec_info_part(adr_link->adr_d[adr_index].adr); - if (codec_index < 0) - return codec_index; - codec_info = &codec_info_list[codec_index]; + codec_info = find_codec_info_part(adr_link->adr_d[adr_index].adr); + if (!codec_info) + return -EINVAL; if (codec_info->ignore_pch_dmic) *ignore_pch_dmic = true; @@ -1631,7 +1624,7 @@ static int create_sdw_dailink(struct snd_soc_card *card, int *link_index, ret = set_codec_init_func(card, adr_link, dai_links + (*link_index)++, playback, group_id, adr_index, dai_index); if (ret < 0) { - dev_err(dev, "failed to init codec %d\n", codec_index); + dev_err(dev, "failed to init codec 0x%x\n", codec_info->part_id); return ret; } } @@ -1649,6 +1642,7 @@ static int sof_card_dai_links_create(struct snd_soc_card *card) const struct snd_soc_acpi_link_adr *adr_link = mach_params->links; bool aggregation = !(sof_sdw_quirk & SOF_SDW_NO_AGGREGATION); struct snd_soc_codec_conf *codec_conf; + struct sof_sdw_codec_info *codec_info; bool append_dai_type = false; bool ignore_pch_dmic = false; int codec_conf_num = 0; @@ -1660,7 +1654,6 @@ static int sof_card_dai_links_create(struct snd_soc_card *card) char *name, *cpu_dai_name; char *codec_name, *codec_dai_name; int i, j, be_id = 0; - int codec_index; int hdmi_num; int ret; @@ -1729,10 +1722,10 @@ static int sof_card_dai_links_create(struct snd_soc_card *card) */ for (i = 0; i < adr_link->num_adr; i++) { /* find codec info to get dai_num */ - codec_index = find_codec_info_part(adr_link->adr_d[i].adr); - if (codec_index < 0) - return codec_index; - if (codec_info_list[codec_index].dai_num > 1) { + codec_info = find_codec_info_part(adr_link->adr_d[i].adr); + if (!codec_info) + return -EINVAL; + if (codec_info->dai_num > 1) { append_dai_type = true; goto out; } @@ -1762,11 +1755,11 @@ out: continue; /* find codec info to get dai_num */ - codec_index = find_codec_info_part(adr_link->adr_d[i].adr); - if (codec_index < 0) - return codec_index; + codec_info = find_codec_info_part(adr_link->adr_d[i].adr); + if (!codec_info) + return -EINVAL; - for (j = 0; j < codec_info_list[codec_index].dai_num ; j++) { + for (j = 0; j < codec_info->dai_num ; j++) { int current_be_id; ret = create_sdw_dailink(card, &link_index, dai_links, -- cgit v1.2.3 From c2c7a8b3848127f3355109d72c865b7741af9f0c Mon Sep 17 00:00:00 2001 From: Charles Keepax Date: Tue, 26 Mar 2024 11:03:57 -0500 Subject: ASoC: intel: sof_sdw: Make find_codec_info_acpi() return a pointer Rather than returning an index simply return a pointer to the located codec info, this simplifies all the callers which only want to access the codec info structure. Also remove the inline specifier the function is fairly large for an inline function, let the compiler decide. Reviewed-by: Bard Liao Signed-off-by: Charles Keepax Signed-off-by: Pierre-Louis Bossart Link: https://msgid.link/r/20240326160429.13560-3-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/intel/boards/sof_sdw.c | 31 +++++++++++++++---------------- 1 file changed, 15 insertions(+), 16 deletions(-) diff --git a/sound/soc/intel/boards/sof_sdw.c b/sound/soc/intel/boards/sof_sdw.c index 08b19a32cf9c..517ff44de1f0 100644 --- a/sound/soc/intel/boards/sof_sdw.c +++ b/sound/soc/intel/boards/sof_sdw.c @@ -1076,18 +1076,18 @@ static struct sof_sdw_codec_info *find_codec_info_part(const u64 adr) } -static inline int find_codec_info_acpi(const u8 *acpi_id) +static struct sof_sdw_codec_info *find_codec_info_acpi(const u8 *acpi_id) { int i; if (!acpi_id[0]) - return -EINVAL; + return NULL; for (i = 0; i < ARRAY_SIZE(codec_info_list); i++) if (!memcmp(codec_info_list[i].acpi_id, acpi_id, ACPI_ID_LEN)) - return i; + return &codec_info_list[i]; - return -EINVAL; + return NULL; } /* @@ -1643,18 +1643,19 @@ static int sof_card_dai_links_create(struct snd_soc_card *card) bool aggregation = !(sof_sdw_quirk & SOF_SDW_NO_AGGREGATION); struct snd_soc_codec_conf *codec_conf; struct sof_sdw_codec_info *codec_info; + struct sof_sdw_codec_info *ssp_info; bool append_dai_type = false; bool ignore_pch_dmic = false; int codec_conf_num = 0; int codec_conf_index = 0; bool group_generated[SDW_MAX_GROUPS] = { }; - int ssp_codec_index, ssp_mask; struct snd_soc_dai_link *dai_links; int num_links, link_index = 0; char *name, *cpu_dai_name; char *codec_name, *codec_dai_name; int i, j, be_id = 0; int hdmi_num; + int ssp_mask; int ret; ret = get_dailink_info(dev, adr_link, &sdw_be_num, &codec_conf_num); @@ -1669,8 +1670,8 @@ static int sof_card_dai_links_create(struct snd_soc_card *card) * system only when I2S mode is supported, not sdw mode. * Here check ACPI ID to confirm I2S is supported. */ - ssp_codec_index = find_codec_info_acpi(mach->id); - if (ssp_codec_index >= 0) { + ssp_info = find_codec_info_acpi(mach->id); + if (ssp_info) { ssp_mask = SOF_SSP_GET_PORT(sof_sdw_quirk); ssp_num = hweight_long(ssp_mask); } @@ -1788,30 +1789,28 @@ SSP: goto DMIC; for (i = 0, j = 0; ssp_mask; i++, ssp_mask >>= 1) { - struct sof_sdw_codec_info *info; int playback, capture; if (!(ssp_mask & 0x1)) continue; - info = &codec_info_list[ssp_codec_index]; - name = devm_kasprintf(dev, GFP_KERNEL, "SSP%d-Codec", i); cpu_dai_name = devm_kasprintf(dev, GFP_KERNEL, "SSP%d Pin", i); codec_name = devm_kasprintf(dev, GFP_KERNEL, "i2c-%s:0%d", - info->acpi_id, j++); + ssp_info->acpi_id, j++); - playback = info->dais[0].direction[SNDRV_PCM_STREAM_PLAYBACK]; - capture = info->dais[0].direction[SNDRV_PCM_STREAM_CAPTURE]; + playback = ssp_info->dais[0].direction[SNDRV_PCM_STREAM_PLAYBACK]; + capture = ssp_info->dais[0].direction[SNDRV_PCM_STREAM_CAPTURE]; ret = init_simple_dai_link(dev, dai_links + link_index, &be_id, name, playback, capture, cpu_dai_name, - codec_name, info->dais[0].dai_name, - NULL, info->ops); + codec_name, ssp_info->dais[0].dai_name, + NULL, ssp_info->ops); if (ret) return ret; - ret = info->dais[0].init(card, NULL, dai_links + link_index, info, 0); + ret = ssp_info->dais[0].init(card, NULL, dai_links + link_index, + ssp_info, 0); if (ret < 0) return ret; -- cgit v1.2.3 From 1329f5b0d9d0b26021b6bd469a41139b9ccef58a Mon Sep 17 00:00:00 2001 From: Charles Keepax Date: Tue, 26 Mar 2024 11:03:58 -0500 Subject: ASoC: intel: sof_sdw: Make find_codec_info_dai() return a pointer Rather than returning an index simply return a pointer to the located codec info, this simplifies all the callers which only want to access the codec info structure. Also remove the inline specifier the function is fairly large for an inline function, let the compiler decide. And move the function such that it is located with the other find_codec_info_*() functions. Reviewed-by: Bard Liao Signed-off-by: Charles Keepax Signed-off-by: Pierre-Louis Bossart Link: https://msgid.link/r/20240326160429.13560-4-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/intel/boards/sof_sdw.c | 39 +++++++++++++++++++-------------------- 1 file changed, 19 insertions(+), 20 deletions(-) diff --git a/sound/soc/intel/boards/sof_sdw.c b/sound/soc/intel/boards/sof_sdw.c index 517ff44de1f0..4bd9f62c48fc 100644 --- a/sound/soc/intel/boards/sof_sdw.c +++ b/sound/soc/intel/boards/sof_sdw.c @@ -1090,6 +1090,23 @@ static struct sof_sdw_codec_info *find_codec_info_acpi(const u8 *acpi_id) return NULL; } +static struct sof_sdw_codec_info *find_codec_info_dai(const char *dai_name, + int *dai_index) +{ + int i, j; + + for (i = 0; i < ARRAY_SIZE(codec_info_list); i++) { + for (j = 0; j < codec_info_list[i].dai_num; j++) { + if (!strcmp(codec_info_list[i].dais[j].dai_name, dai_name)) { + *dai_index = j; + return &codec_info_list[i]; + } + } + } + + return NULL; +} + /* * get BE dailink number and CPU DAI number based on sdw link adr. * Since some sdw slaves may be aggregated, the CPU DAI number @@ -1403,37 +1420,19 @@ static void set_dailink_map(struct snd_soc_dai_link_ch_map *sdw_codec_ch_maps, } } -static inline int find_codec_info_dai(const char *dai_name, int *dai_index) -{ - int i, j; - - for (i = 0; i < ARRAY_SIZE(codec_info_list); i++) { - for (j = 0; j < codec_info_list[i].dai_num; j++) { - if (!strcmp(codec_info_list[i].dais[j].dai_name, dai_name)) { - *dai_index = j; - return i; - } - } - } - - return -EINVAL; -} - static int sof_sdw_rtd_init(struct snd_soc_pcm_runtime *rtd) { struct sof_sdw_codec_info *codec_info; struct snd_soc_dai *dai; - int codec_index; int dai_index; int ret; int i; for_each_rtd_codec_dais(rtd, i, dai) { - codec_index = find_codec_info_dai(dai->name, &dai_index); - if (codec_index < 0) + codec_info = find_codec_info_dai(dai->name, &dai_index); + if (!codec_info) return -EINVAL; - codec_info = &codec_info_list[codec_index]; /* * A codec dai can be connected to different dai links for capture and playback, * but we only need to call the rtd_init function once. -- cgit v1.2.3 From 961e694749fb8ddb8591512216e2fa6b4e3f42e2 Mon Sep 17 00:00:00 2001 From: Charles Keepax Date: Tue, 26 Mar 2024 11:03:59 -0500 Subject: ASoC: intel: sof_sdw: Only pass codec_conf pointer around Rather than passing around a pointer to the codec_conf array, an index into it and a size, simply pass around a pointer to the current codec_conf. This reduces the amount of state moving around. Reviewed-by: Bard Liao Signed-off-by: Charles Keepax Signed-off-by: Pierre-Louis Bossart Link: https://msgid.link/r/20240326160429.13560-5-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/intel/boards/sof_sdw.c | 28 ++++++++++++---------------- 1 file changed, 12 insertions(+), 16 deletions(-) diff --git a/sound/soc/intel/boards/sof_sdw.c b/sound/soc/intel/boards/sof_sdw.c index 4bd9f62c48fc..7b61d45df5da 100644 --- a/sound/soc/intel/boards/sof_sdw.c +++ b/sound/soc/intel/boards/sof_sdw.c @@ -1457,10 +1457,8 @@ static const char * const type_strings[] = {"SimpleJack", "SmartAmp", "SmartMic" static int create_sdw_dailink(struct snd_soc_card *card, int *link_index, struct snd_soc_dai_link *dai_links, int sdw_be_num, const struct snd_soc_acpi_link_adr *adr_link, - struct snd_soc_codec_conf *codec_conf, - int codec_count, int *be_id, - int *codec_conf_index, - bool *ignore_pch_dmic, + struct snd_soc_codec_conf **codec_conf, + int *be_id, bool *ignore_pch_dmic, bool append_dai_type, int adr_index, int dai_index) @@ -1509,7 +1507,7 @@ static int create_sdw_dailink(struct snd_soc_card *card, int *link_index, continue; /* sanity check */ - if (*codec_conf_index >= codec_count) { + if (*codec_conf >= card->codec_conf + card->num_configs) { dev_err(dev, "codec_conf array overflowed\n"); return -EINVAL; } @@ -1520,12 +1518,11 @@ static int create_sdw_dailink(struct snd_soc_card *card, int *link_index, if (ret) return ret; - codec_conf[*codec_conf_index].dlc = codecs[codec_dlc_index]; - codec_conf[*codec_conf_index].name_prefix = - adr_link_next->adr_d[j].name_prefix; + (*codec_conf)->dlc = codecs[codec_dlc_index]; + (*codec_conf)->name_prefix = adr_link_next->adr_d[j].name_prefix; codec_dlc_index++; - (*codec_conf_index)++; + (*codec_conf)++; } j = 0; @@ -1646,7 +1643,6 @@ static int sof_card_dai_links_create(struct snd_soc_card *card) bool append_dai_type = false; bool ignore_pch_dmic = false; int codec_conf_num = 0; - int codec_conf_index = 0; bool group_generated[SDW_MAX_GROUPS] = { }; struct snd_soc_dai_link *dai_links; int num_links, link_index = 0; @@ -1706,6 +1702,9 @@ static int sof_card_dai_links_create(struct snd_soc_card *card) if (!codec_conf) return -ENOMEM; + card->codec_conf = codec_conf; + card->num_configs = codec_conf_num; + /* SDW */ if (!sdw_be_num) goto SSP; @@ -1764,9 +1763,9 @@ out: ret = create_sdw_dailink(card, &link_index, dai_links, sdw_be_num, adr_link, - codec_conf, codec_conf_num, - ¤t_be_id, &codec_conf_index, - &ignore_pch_dmic, append_dai_type, i, j); + &codec_conf, ¤t_be_id, + &ignore_pch_dmic, + append_dai_type, i, j); if (ret < 0) { dev_err(dev, "failed to create dai link %d\n", link_index); return ret; @@ -1886,9 +1885,6 @@ HDMI: card->dai_link = dai_links; card->num_links = num_links; - card->codec_conf = codec_conf; - card->num_configs = codec_conf_num; - return 0; } -- cgit v1.2.3 From 634ffef9cbc41b9db2b45974969dda06219ffce1 Mon Sep 17 00:00:00 2001 From: Charles Keepax Date: Tue, 26 Mar 2024 11:04:00 -0500 Subject: ASoC: intel: sof_sdw: Set channel map directly from endpoints The current code evenly distributes the CODEC DAIs across the CPU DAIs in the DAI link, but this is just an assumption about how the devices are connected to the host. All the information about which CODEC is connected to which CPU DAI is contained in the endpoints datastructures and those structures are already parsed to work out which CODECs to include in the DAI link. Simply fill in the mapping from CPUs -> CODECs as we parse through the endpoints structures, this will ensure that mapping matches the physical layout. Reviewed-by: Bard Liao Signed-off-by: Charles Keepax Signed-off-by: Pierre-Louis Bossart Link: https://msgid.link/r/20240326160429.13560-6-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/intel/boards/sof_sdw.c | 31 ++++++++++--------------------- 1 file changed, 10 insertions(+), 21 deletions(-) diff --git a/sound/soc/intel/boards/sof_sdw.c b/sound/soc/intel/boards/sof_sdw.c index 7b61d45df5da..e2c1822b185f 100644 --- a/sound/soc/intel/boards/sof_sdw.c +++ b/sound/soc/intel/boards/sof_sdw.c @@ -1407,19 +1407,6 @@ static int get_slave_info(const struct snd_soc_acpi_link_adr *adr_link, return 0; } -static void set_dailink_map(struct snd_soc_dai_link_ch_map *sdw_codec_ch_maps, - int codec_num, int cpu_num) -{ - int step; - int i; - - step = codec_num / cpu_num; - for (i = 0; i < codec_num; i++) { - sdw_codec_ch_maps[i].cpu = i / step; - sdw_codec_ch_maps[i].codec = i; - } -} - static int sof_sdw_rtd_init(struct snd_soc_pcm_runtime *rtd) { struct sof_sdw_codec_info *codec_info; @@ -1466,6 +1453,7 @@ static int create_sdw_dailink(struct snd_soc_card *card, int *link_index, struct mc_private *ctx = snd_soc_card_get_drvdata(card); struct device *dev = card->dev; const struct snd_soc_acpi_link_adr *adr_link_next; + struct snd_soc_dai_link_ch_map *sdw_codec_ch_maps; struct snd_soc_dai_link_component *codecs; struct snd_soc_dai_link_component *cpus; struct sof_sdw_codec_info *codec_info; @@ -1488,6 +1476,11 @@ static int create_sdw_dailink(struct snd_soc_card *card, int *link_index, if (!codecs) return -ENOMEM; + sdw_codec_ch_maps = devm_kcalloc(dev, codec_num, + sizeof(*sdw_codec_ch_maps), GFP_KERNEL); + if (!sdw_codec_ch_maps) + return -ENOMEM; + /* generate codec name on different links in the same group */ j = adr_index; for (adr_link_next = adr_link; adr_link_next && adr_link_next->num_adr && @@ -1521,6 +1514,9 @@ static int create_sdw_dailink(struct snd_soc_card *card, int *link_index, (*codec_conf)->dlc = codecs[codec_dlc_index]; (*codec_conf)->name_prefix = adr_link_next->adr_d[j].name_prefix; + sdw_codec_ch_maps[codec_dlc_index].cpu = i; + sdw_codec_ch_maps[codec_dlc_index].codec = codec_dlc_index; + codec_dlc_index++; (*codec_conf)++; } @@ -1539,7 +1535,6 @@ static int create_sdw_dailink(struct snd_soc_card *card, int *link_index, *ignore_pch_dmic = true; for_each_pcm_streams(stream) { - struct snd_soc_dai_link_ch_map *sdw_codec_ch_maps; char *name, *cpu_name; int playback, capture; static const char * const sdw_stream_name[] = { @@ -1558,11 +1553,6 @@ static int create_sdw_dailink(struct snd_soc_card *card, int *link_index, return -EINVAL; } - sdw_codec_ch_maps = devm_kcalloc(dev, codec_num, - sizeof(*sdw_codec_ch_maps), GFP_KERNEL); - if (!sdw_codec_ch_maps) - return -ENOMEM; - /* create stream name according to first link id */ if (append_dai_type) { name = devm_kasprintf(dev, GFP_KERNEL, @@ -1614,9 +1604,8 @@ static int create_sdw_dailink(struct snd_soc_card *card, int *link_index, * based on wait_for_completion(), tag them as 'nonatomic'. */ dai_links[*link_index].nonatomic = true; - - set_dailink_map(sdw_codec_ch_maps, codec_num, cpu_dai_num); dai_links[*link_index].ch_maps = sdw_codec_ch_maps; + ret = set_codec_init_func(card, adr_link, dai_links + (*link_index)++, playback, group_id, adr_index, dai_index); if (ret < 0) { -- cgit v1.2.3 From 0703329606a237c3604230603d58254a8bdf4b81 Mon Sep 17 00:00:00 2001 From: Charles Keepax Date: Tue, 26 Mar 2024 11:04:01 -0500 Subject: ASoC: Intel: sof_sdw: Move get_codec_dai_by_name() into sof_sdw itself Currently sof_sdw relies on sof_board_helpers to provide get_codec_dai_by_name(), but that is the only function from sof_board_helpers it uses and no other machine driver requires that function. There is no reason for sof_sdw to select SSP_COMMON but more and more functions in sof_board_helpers are gaining dependencies on functions that would require stubs for sof_sdw to build without it. Firstly it was sof_ssp_get_codec_name(), as was fixed in commit c1469c3a8a30 ("ASoC: Intel: ssp-common: Add stub for sof_ssp_get_codec_name"), now it is: ERROR: modpost: "sof_ssp_detect_amp_type" [sound/soc/intel/boards/snd-soc-intel-sof-board-helpers.ko] undefined! ERROR: modpost: "sof_ssp_detect_codec_type" [sound/soc/intel/boards/snd-soc-intel-sof-board-helpers.ko] undefined! Rather than adding more stubs, simply move the affected function to the sof_sdw machine driver itself and no longer select SND_SOC_INTEL_SOF_BOARD_HELPERS at all. This should allow work on SSP_COMMON to progress without affecting sof_sdw. Reviewed-by: Bard Liao Signed-off-by: Charles Keepax Signed-off-by: Pierre-Louis Bossart Link: https://msgid.link/r/20240326160429.13560-7-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/intel/boards/Kconfig | 1 - sound/soc/intel/boards/sof_board_helpers.c | 18 ------------------ sound/soc/intel/boards/sof_board_helpers.h | 3 --- sound/soc/intel/boards/sof_sdw.c | 18 ++++++++++++++++++ sound/soc/intel/boards/sof_sdw_common.h | 4 ++++ sound/soc/intel/boards/sof_sdw_cs42l42.c | 1 - sound/soc/intel/boards/sof_sdw_rt5682.c | 1 - sound/soc/intel/boards/sof_sdw_rt700.c | 1 - sound/soc/intel/boards/sof_sdw_rt711.c | 1 - sound/soc/intel/boards/sof_sdw_rt712_sdca.c | 1 - sound/soc/intel/boards/sof_sdw_rt_sdca_jack_common.c | 1 - sound/soc/intel/boards/sof_ssp_common.h | 7 ------- 12 files changed, 22 insertions(+), 35 deletions(-) diff --git a/sound/soc/intel/boards/Kconfig b/sound/soc/intel/boards/Kconfig index e5df64fec319..b7a6ac4b6c0c 100644 --- a/sound/soc/intel/boards/Kconfig +++ b/sound/soc/intel/boards/Kconfig @@ -678,7 +678,6 @@ config SND_SOC_INTEL_SOUNDWIRE_SOF_MACH depends on MFD_INTEL_LPSS || COMPILE_TEST depends on SND_SOC_INTEL_USER_FRIENDLY_LONG_NAMES || COMPILE_TEST depends on SOUNDWIRE - select SND_SOC_INTEL_SOF_BOARD_HELPERS select SND_SOC_MAX98363 select SND_SOC_MAX98373_I2C select SND_SOC_MAX98373_SDW diff --git a/sound/soc/intel/boards/sof_board_helpers.c b/sound/soc/intel/boards/sof_board_helpers.c index a5135be94f32..586600680e84 100644 --- a/sound/soc/intel/boards/sof_board_helpers.c +++ b/sound/soc/intel/boards/sof_board_helpers.c @@ -630,24 +630,6 @@ sof_intel_board_get_ctx(struct device *dev, unsigned long board_quirk) } EXPORT_SYMBOL_NS(sof_intel_board_get_ctx, SND_SOC_INTEL_SOF_BOARD_HELPERS); -struct snd_soc_dai *get_codec_dai_by_name(struct snd_soc_pcm_runtime *rtd, - const char * const dai_name[], int num_dais) -{ - struct snd_soc_dai *dai; - int index; - int i; - - for (index = 0; index < num_dais; index++) - for_each_rtd_codec_dais(rtd, i, dai) - if (strstr(dai->name, dai_name[index])) { - dev_dbg(rtd->card->dev, "get dai %s\n", dai->name); - return dai; - } - - return NULL; -} -EXPORT_SYMBOL_NS(get_codec_dai_by_name, SND_SOC_INTEL_SOF_BOARD_HELPERS); - MODULE_DESCRIPTION("ASoC Intel SOF Machine Driver Board Helpers"); MODULE_AUTHOR("Brent Lu "); MODULE_LICENSE("GPL"); diff --git a/sound/soc/intel/boards/sof_board_helpers.h b/sound/soc/intel/boards/sof_board_helpers.h index 2f27ad8726f8..b6a83ca14fa8 100644 --- a/sound/soc/intel/boards/sof_board_helpers.h +++ b/sound/soc/intel/boards/sof_board_helpers.h @@ -167,7 +167,4 @@ int sof_intel_board_set_dai_link(struct device *dev, struct snd_soc_card *card, struct sof_card_private * sof_intel_board_get_ctx(struct device *dev, unsigned long board_quirk); -struct snd_soc_dai *get_codec_dai_by_name(struct snd_soc_pcm_runtime *rtd, - const char * const dai_name[], int num_dais); - #endif /* __SOF_INTEL_BOARD_HELPERS_H */ diff --git a/sound/soc/intel/boards/sof_sdw.c b/sound/soc/intel/boards/sof_sdw.c index e2c1822b185f..45732884e310 100644 --- a/sound/soc/intel/boards/sof_sdw.c +++ b/sound/soc/intel/boards/sof_sdw.c @@ -514,6 +514,24 @@ static struct snd_soc_dai_link_component platform_component[] = { } }; +struct snd_soc_dai *get_codec_dai_by_name(struct snd_soc_pcm_runtime *rtd, + const char * const dai_name[], + int num_dais) +{ + struct snd_soc_dai *dai; + int index; + int i; + + for (index = 0; index < num_dais; index++) + for_each_rtd_codec_dais(rtd, i, dai) + if (strstr(dai->name, dai_name[index])) { + dev_dbg(rtd->card->dev, "get dai %s\n", dai->name); + return dai; + } + + return NULL; +} + /* these wrappers are only needed to avoid typecast compilation errors */ int sdw_startup(struct snd_pcm_substream *substream) { diff --git a/sound/soc/intel/boards/sof_sdw_common.h b/sound/soc/intel/boards/sof_sdw_common.h index b1d57034361c..a04cbab9bc70 100644 --- a/sound/soc/intel/boards/sof_sdw_common.h +++ b/sound/soc/intel/boards/sof_sdw_common.h @@ -107,6 +107,10 @@ struct mc_private { extern unsigned long sof_sdw_quirk; +struct snd_soc_dai *get_codec_dai_by_name(struct snd_soc_pcm_runtime *rtd, + const char * const dai_name[], + int num_dais); + int sdw_startup(struct snd_pcm_substream *substream); int sdw_prepare(struct snd_pcm_substream *substream); int sdw_trigger(struct snd_pcm_substream *substream, int cmd); diff --git a/sound/soc/intel/boards/sof_sdw_cs42l42.c b/sound/soc/intel/boards/sof_sdw_cs42l42.c index 0dc297f7de01..b999f4e7901a 100644 --- a/sound/soc/intel/boards/sof_sdw_cs42l42.c +++ b/sound/soc/intel/boards/sof_sdw_cs42l42.c @@ -15,7 +15,6 @@ #include #include #include -#include "sof_board_helpers.h" #include "sof_sdw_common.h" static const struct snd_soc_dapm_widget cs42l42_widgets[] = { diff --git a/sound/soc/intel/boards/sof_sdw_rt5682.c b/sound/soc/intel/boards/sof_sdw_rt5682.c index 6b008a5a343b..f812aea64322 100644 --- a/sound/soc/intel/boards/sof_sdw_rt5682.c +++ b/sound/soc/intel/boards/sof_sdw_rt5682.c @@ -15,7 +15,6 @@ #include #include #include -#include "sof_board_helpers.h" #include "sof_sdw_common.h" static const struct snd_soc_dapm_widget rt5682_widgets[] = { diff --git a/sound/soc/intel/boards/sof_sdw_rt700.c b/sound/soc/intel/boards/sof_sdw_rt700.c index 88e785a54b16..a2648c900e74 100644 --- a/sound/soc/intel/boards/sof_sdw_rt700.c +++ b/sound/soc/intel/boards/sof_sdw_rt700.c @@ -13,7 +13,6 @@ #include #include #include -#include "sof_board_helpers.h" #include "sof_sdw_common.h" static const struct snd_soc_dapm_widget rt700_widgets[] = { diff --git a/sound/soc/intel/boards/sof_sdw_rt711.c b/sound/soc/intel/boards/sof_sdw_rt711.c index cdd1587b246c..9762c48ba7a9 100644 --- a/sound/soc/intel/boards/sof_sdw_rt711.c +++ b/sound/soc/intel/boards/sof_sdw_rt711.c @@ -15,7 +15,6 @@ #include #include #include -#include "sof_board_helpers.h" #include "sof_sdw_common.h" /* diff --git a/sound/soc/intel/boards/sof_sdw_rt712_sdca.c b/sound/soc/intel/boards/sof_sdw_rt712_sdca.c index ebb4b58c198b..9c898c7286af 100644 --- a/sound/soc/intel/boards/sof_sdw_rt712_sdca.c +++ b/sound/soc/intel/boards/sof_sdw_rt712_sdca.c @@ -13,7 +13,6 @@ #include #include #include -#include "sof_board_helpers.h" #include "sof_sdw_common.h" static const struct snd_soc_dapm_widget rt712_spk_widgets[] = { diff --git a/sound/soc/intel/boards/sof_sdw_rt_sdca_jack_common.c b/sound/soc/intel/boards/sof_sdw_rt_sdca_jack_common.c index 5253d8332780..fe59a144efef 100644 --- a/sound/soc/intel/boards/sof_sdw_rt_sdca_jack_common.c +++ b/sound/soc/intel/boards/sof_sdw_rt_sdca_jack_common.c @@ -15,7 +15,6 @@ #include #include #include -#include "sof_board_helpers.h" #include "sof_sdw_common.h" /* diff --git a/sound/soc/intel/boards/sof_ssp_common.h b/sound/soc/intel/boards/sof_ssp_common.h index d24888bc99fd..ff84154ce60a 100644 --- a/sound/soc/intel/boards/sof_ssp_common.h +++ b/sound/soc/intel/boards/sof_ssp_common.h @@ -68,13 +68,6 @@ enum sof_ssp_codec { enum sof_ssp_codec sof_ssp_detect_codec_type(struct device *dev); enum sof_ssp_codec sof_ssp_detect_amp_type(struct device *dev); -#if IS_ENABLED(CONFIG_SND_SOC_INTEL_SOF_SSP_COMMON) const char *sof_ssp_get_codec_name(enum sof_ssp_codec codec_type); -#else -static inline const char *sof_ssp_get_codec_name(enum sof_ssp_codec codec_type) -{ - return NULL; -} -#endif #endif /* __SOF_SSP_COMMON_H */ -- cgit v1.2.3 From d36bfa329ae6d94e435d11960936023c03df0d64 Mon Sep 17 00:00:00 2001 From: Charles Keepax Date: Tue, 26 Mar 2024 11:04:02 -0500 Subject: ASoC: Intel: sof_sdw: Move flags to private struct Move the flags ignore_pch_dmic and append_dai_type into the drivers private structure rather than passing them around between functions. Reviewed-by: Bard Liao Signed-off-by: Charles Keepax Signed-off-by: Pierre-Louis Bossart Link: https://msgid.link/r/20240326160429.13560-8-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/intel/boards/sof_sdw.c | 21 +++++++-------------- sound/soc/intel/boards/sof_sdw_common.h | 2 ++ 2 files changed, 9 insertions(+), 14 deletions(-) diff --git a/sound/soc/intel/boards/sof_sdw.c b/sound/soc/intel/boards/sof_sdw.c index 45732884e310..5557db68a002 100644 --- a/sound/soc/intel/boards/sof_sdw.c +++ b/sound/soc/intel/boards/sof_sdw.c @@ -1463,10 +1463,7 @@ static int create_sdw_dailink(struct snd_soc_card *card, int *link_index, struct snd_soc_dai_link *dai_links, int sdw_be_num, const struct snd_soc_acpi_link_adr *adr_link, struct snd_soc_codec_conf **codec_conf, - int *be_id, bool *ignore_pch_dmic, - bool append_dai_type, - int adr_index, - int dai_index) + int *be_id, int adr_index, int dai_index) { struct mc_private *ctx = snd_soc_card_get_drvdata(card); struct device *dev = card->dev; @@ -1549,8 +1546,7 @@ static int create_sdw_dailink(struct snd_soc_card *card, int *link_index, if (!codec_info) return -EINVAL; - if (codec_info->ignore_pch_dmic) - *ignore_pch_dmic = true; + ctx->ignore_pch_dmic |= codec_info->ignore_pch_dmic; for_each_pcm_streams(stream) { char *name, *cpu_name; @@ -1572,7 +1568,7 @@ static int create_sdw_dailink(struct snd_soc_card *card, int *link_index, } /* create stream name according to first link id */ - if (append_dai_type) { + if (ctx->append_dai_type) { name = devm_kasprintf(dev, GFP_KERNEL, sdw_stream_name[stream + 2], cpu_dai_id[0], type_strings[codec_info->dais[dai_index].dai_type]); @@ -1647,8 +1643,6 @@ static int sof_card_dai_links_create(struct snd_soc_card *card) struct snd_soc_codec_conf *codec_conf; struct sof_sdw_codec_info *codec_info; struct sof_sdw_codec_info *ssp_info; - bool append_dai_type = false; - bool ignore_pch_dmic = false; int codec_conf_num = 0; bool group_generated[SDW_MAX_GROUPS] = { }; struct snd_soc_dai_link *dai_links; @@ -1732,7 +1726,7 @@ static int sof_card_dai_links_create(struct snd_soc_card *card) if (!codec_info) return -EINVAL; if (codec_info->dai_num > 1) { - append_dai_type = true; + ctx->append_dai_type = true; goto out; } for (j = 0; j < i; j++) { @@ -1740,7 +1734,7 @@ static int sof_card_dai_links_create(struct snd_soc_card *card) SDW_PART_ID(adr_link->adr_d[j].adr)) || (SDW_MFG_ID(adr_link->adr_d[i].adr) != SDW_MFG_ID(adr_link->adr_d[j].adr))) { - append_dai_type = true; + ctx->append_dai_type = true; goto out; } } @@ -1771,8 +1765,7 @@ out: ret = create_sdw_dailink(card, &link_index, dai_links, sdw_be_num, adr_link, &codec_conf, ¤t_be_id, - &ignore_pch_dmic, - append_dai_type, i, j); + i, j); if (ret < 0) { dev_err(dev, "failed to create dai link %d\n", link_index); return ret; @@ -1825,7 +1818,7 @@ SSP: DMIC: /* dmic */ if (dmic_num > 0) { - if (ignore_pch_dmic) { + if (ctx->ignore_pch_dmic) { dev_warn(dev, "Ignoring PCH DMIC\n"); goto HDMI; } diff --git a/sound/soc/intel/boards/sof_sdw_common.h b/sound/soc/intel/boards/sof_sdw_common.h index a04cbab9bc70..1daf98a5849f 100644 --- a/sound/soc/intel/boards/sof_sdw_common.h +++ b/sound/soc/intel/boards/sof_sdw_common.h @@ -103,6 +103,8 @@ struct mc_private { struct device *amp_dev1, *amp_dev2; /* To store SDW Pin index for each SoundWire link */ unsigned int sdw_pin_index[SDW_MAX_LINKS]; + bool append_dai_type; + bool ignore_pch_dmic; }; extern unsigned long sof_sdw_quirk; -- cgit v1.2.3 From c577b747b9a0ad32047dcfa01d0ea7e2441cf590 Mon Sep 17 00:00:00 2001 From: Charles Keepax Date: Tue, 26 Mar 2024 11:04:03 -0500 Subject: ASoC: Intel: sof_sdw: Only pass dai_link pointer around Rather than passing around a pointer to the dai_link array and an index into this array, simply pass a pointer to the current dai_link. Also move the DAI link pointer sanity check to the end of the DAI link creation, and change it to a warn on. This check should only be hit if there is a serious bug in the machine driver, so checking it on each iteration is excessive. Reviewed-by: Bard Liao Signed-off-by: Charles Keepax Signed-off-by: Pierre-Louis Bossart Link: https://msgid.link/r/20240326160429.13560-9-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/intel/boards/sof_sdw.c | 62 +++++++++++++++++++--------------------- 1 file changed, 29 insertions(+), 33 deletions(-) diff --git a/sound/soc/intel/boards/sof_sdw.c b/sound/soc/intel/boards/sof_sdw.c index 5557db68a002..0ffa6e36dbed 100644 --- a/sound/soc/intel/boards/sof_sdw.c +++ b/sound/soc/intel/boards/sof_sdw.c @@ -1459,8 +1459,8 @@ static int sof_sdw_rtd_init(struct snd_soc_pcm_runtime *rtd) static const char * const type_strings[] = {"SimpleJack", "SmartAmp", "SmartMic"}; -static int create_sdw_dailink(struct snd_soc_card *card, int *link_index, - struct snd_soc_dai_link *dai_links, int sdw_be_num, +static int create_sdw_dailink(struct snd_soc_card *card, + struct snd_soc_dai_link **dai_links, const struct snd_soc_acpi_link_adr *adr_link, struct snd_soc_codec_conf **codec_conf, int *be_id, int adr_index, int dai_index) @@ -1597,35 +1597,28 @@ static int create_sdw_dailink(struct snd_soc_card *card, int *link_index, cpus[k].dai_name = cpu_name; } - /* - * We create sdw dai links at first stage, so link index should - * not be larger than sdw_be_num - */ - if (*link_index >= sdw_be_num) { - dev_err(dev, "invalid dai link index %d\n", *link_index); - return -EINVAL; - } - playback = (stream == SNDRV_PCM_STREAM_PLAYBACK); capture = (stream == SNDRV_PCM_STREAM_CAPTURE); - init_dai_link(dev, dai_links + *link_index, be_id, name, - playback, capture, cpus, cpu_dai_num, codecs, codec_num, + init_dai_link(dev, *dai_links, be_id, name, playback, capture, + cpus, cpu_dai_num, codecs, codec_num, sof_sdw_rtd_init, &sdw_ops); /* * SoundWire DAILINKs use 'stream' functions and Bank Switch operations * based on wait_for_completion(), tag them as 'nonatomic'. */ - dai_links[*link_index].nonatomic = true; - dai_links[*link_index].ch_maps = sdw_codec_ch_maps; + (*dai_links)->nonatomic = true; + (*dai_links)->ch_maps = sdw_codec_ch_maps; - ret = set_codec_init_func(card, adr_link, dai_links + (*link_index)++, + ret = set_codec_init_func(card, adr_link, *dai_links, playback, group_id, adr_index, dai_index); if (ret < 0) { dev_err(dev, "failed to init codec 0x%x\n", codec_info->part_id); return ret; } + + (*dai_links)++; } return 0; @@ -1646,7 +1639,7 @@ static int sof_card_dai_links_create(struct snd_soc_card *card) int codec_conf_num = 0; bool group_generated[SDW_MAX_GROUPS] = { }; struct snd_soc_dai_link *dai_links; - int num_links, link_index = 0; + int num_links; char *name, *cpu_dai_name; char *codec_name, *codec_dai_name; int i, j, be_id = 0; @@ -1703,6 +1696,8 @@ static int sof_card_dai_links_create(struct snd_soc_card *card) if (!codec_conf) return -ENOMEM; + card->dai_link = dai_links; + card->num_links = num_links; card->codec_conf = codec_conf; card->num_configs = codec_conf_num; @@ -1762,12 +1757,13 @@ out: for (j = 0; j < codec_info->dai_num ; j++) { int current_be_id; - ret = create_sdw_dailink(card, &link_index, dai_links, - sdw_be_num, adr_link, + ret = create_sdw_dailink(card, &dai_links, adr_link, &codec_conf, ¤t_be_id, i, j); if (ret < 0) { - dev_err(dev, "failed to create dai link %d\n", link_index); + dev_err(dev, + "failed to create dai link %d on 0x%x\n", + j, codec_info->part_id); return ret; } @@ -1800,19 +1796,18 @@ SSP: playback = ssp_info->dais[0].direction[SNDRV_PCM_STREAM_PLAYBACK]; capture = ssp_info->dais[0].direction[SNDRV_PCM_STREAM_CAPTURE]; - ret = init_simple_dai_link(dev, dai_links + link_index, &be_id, name, + ret = init_simple_dai_link(dev, dai_links, &be_id, name, playback, capture, cpu_dai_name, codec_name, ssp_info->dais[0].dai_name, NULL, ssp_info->ops); if (ret) return ret; - ret = ssp_info->dais[0].init(card, NULL, dai_links + link_index, - ssp_info, 0); + ret = ssp_info->dais[0].init(card, NULL, dai_links, ssp_info, 0); if (ret < 0) return ret; - link_index++; + dai_links++; } DMIC: @@ -1823,16 +1818,16 @@ DMIC: goto HDMI; } - ret = init_simple_dai_link(dev, dai_links + link_index, &be_id, "dmic01", + ret = init_simple_dai_link(dev, dai_links, &be_id, "dmic01", 0, 1, // DMIC only supports capture "DMIC01 Pin", "dmic-codec", "dmic-hifi", sof_sdw_dmic_init, NULL); if (ret) return ret; - link_index++; + dai_links++; - ret = init_simple_dai_link(dev, dai_links + link_index, &be_id, "dmic16k", + ret = init_simple_dai_link(dev, dai_links, &be_id, "dmic16k", 0, 1, // DMIC only supports capture "DMIC16k Pin", "dmic-codec", "dmic-hifi", /* don't call sof_sdw_dmic_init() twice */ @@ -1840,7 +1835,7 @@ DMIC: if (ret) return ret; - link_index++; + dai_links++; } HDMI: @@ -1858,14 +1853,14 @@ HDMI: codec_dai_name = "snd-soc-dummy-dai"; } - ret = init_simple_dai_link(dev, dai_links + link_index, &be_id, name, + ret = init_simple_dai_link(dev, dai_links, &be_id, name, 1, 0, // HDMI only supports playback cpu_dai_name, codec_name, codec_dai_name, i == 0 ? sof_sdw_hdmi_init : NULL, NULL); if (ret) return ret; - link_index++; + dai_links++; } if (sof_sdw_quirk & SOF_SSP_BT_OFFLOAD_PRESENT) { @@ -1875,15 +1870,16 @@ HDMI: name = devm_kasprintf(dev, GFP_KERNEL, "SSP%d-BT", port); cpu_dai_name = devm_kasprintf(dev, GFP_KERNEL, "SSP%d Pin", port); - ret = init_simple_dai_link(dev, dai_links + link_index, &be_id, name, + ret = init_simple_dai_link(dev, dai_links, &be_id, name, 1, 1, cpu_dai_name, snd_soc_dummy_dlc.name, snd_soc_dummy_dlc.dai_name, NULL, NULL); if (ret) return ret; + + dai_links++; } - card->dai_link = dai_links; - card->num_links = num_links; + WARN_ON(dai_links != card->dai_link + card->num_links); return 0; } -- cgit v1.2.3 From 2132dbc1a99480bddb995170abaa3c3e1cf8681d Mon Sep 17 00:00:00 2001 From: Charles Keepax Date: Tue, 26 Mar 2024 11:04:04 -0500 Subject: ASoC: Intel: sof_sdw: Use for_each_set_bit Rather than open coding a loop to process each bit use for_each_set_bit. Reviewed-by: Bard Liao Signed-off-by: Charles Keepax Signed-off-by: Pierre-Louis Bossart Link: https://msgid.link/r/20240326160429.13560-10-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/intel/boards/sof_sdw.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/sound/soc/intel/boards/sof_sdw.c b/sound/soc/intel/boards/sof_sdw.c index 0ffa6e36dbed..a12283d3e1cc 100644 --- a/sound/soc/intel/boards/sof_sdw.c +++ b/sound/soc/intel/boards/sof_sdw.c @@ -5,6 +5,7 @@ * sof_sdw - ASOC Machine driver for Intel SoundWire platforms */ +#include #include #include #include @@ -1644,7 +1645,7 @@ static int sof_card_dai_links_create(struct snd_soc_card *card) char *codec_name, *codec_dai_name; int i, j, be_id = 0; int hdmi_num; - int ssp_mask; + unsigned long ssp_mask; int ret; ret = get_dailink_info(dev, adr_link, &sdw_be_num, &codec_conf_num); @@ -1782,12 +1783,10 @@ SSP: if (!ssp_num) goto DMIC; - for (i = 0, j = 0; ssp_mask; i++, ssp_mask >>= 1) { + j = 0; + for_each_set_bit(i, &ssp_mask, BITS_PER_TYPE(ssp_mask)) { int playback, capture; - if (!(ssp_mask & 0x1)) - continue; - name = devm_kasprintf(dev, GFP_KERNEL, "SSP%d-Codec", i); cpu_dai_name = devm_kasprintf(dev, GFP_KERNEL, "SSP%d Pin", i); codec_name = devm_kasprintf(dev, GFP_KERNEL, "i2c-%s:0%d", -- cgit v1.2.3 From 4d96a7f000f04e8041606f074dec5cb21bb4824d Mon Sep 17 00:00:00 2001 From: Charles Keepax Date: Tue, 26 Mar 2024 11:04:05 -0500 Subject: ASoC: Intel: sof_sdw: Factor out SSP DAI creation Factor out the creation of the SSP DAI links into a helper function. No functional change. Reviewed-by: Bard Liao Signed-off-by: Charles Keepax Signed-off-by: Pierre-Louis Bossart Link: https://msgid.link/r/20240326160429.13560-11-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/intel/boards/sof_sdw.c | 63 +++++++++++++++++++++++----------------- 1 file changed, 37 insertions(+), 26 deletions(-) diff --git a/sound/soc/intel/boards/sof_sdw.c b/sound/soc/intel/boards/sof_sdw.c index a12283d3e1cc..9980652c901b 100644 --- a/sound/soc/intel/boards/sof_sdw.c +++ b/sound/soc/intel/boards/sof_sdw.c @@ -1625,6 +1625,40 @@ static int create_sdw_dailink(struct snd_soc_card *card, return 0; } +static int create_ssp_dailinks(struct snd_soc_card *card, + struct snd_soc_dai_link **dai_links, int *be_id, + struct sof_sdw_codec_info *ssp_info, + unsigned long ssp_mask) +{ + struct device *dev = card->dev; + int i, j = 0; + int ret; + + for_each_set_bit(i, &ssp_mask, BITS_PER_TYPE(ssp_mask)) { + char *name = devm_kasprintf(dev, GFP_KERNEL, "SSP%d-Codec", i); + char *cpu_dai_name = devm_kasprintf(dev, GFP_KERNEL, "SSP%d Pin", i); + char *codec_name = devm_kasprintf(dev, GFP_KERNEL, "i2c-%s:0%d", + ssp_info->acpi_id, j++); + int playback = ssp_info->dais[0].direction[SNDRV_PCM_STREAM_PLAYBACK]; + int capture = ssp_info->dais[0].direction[SNDRV_PCM_STREAM_CAPTURE]; + + ret = init_simple_dai_link(dev, *dai_links, be_id, name, + playback, capture, cpu_dai_name, + codec_name, ssp_info->dais[0].dai_name, + NULL, ssp_info->ops); + if (ret) + return ret; + + ret = ssp_info->dais[0].init(card, NULL, *dai_links, ssp_info, 0); + if (ret < 0) + return ret; + + (*dai_links)++; + } + + return 0; +} + static int sof_card_dai_links_create(struct snd_soc_card *card) { struct device *dev = card->dev; @@ -1780,36 +1814,13 @@ out: SSP: /* SSP */ - if (!ssp_num) - goto DMIC; - - j = 0; - for_each_set_bit(i, &ssp_mask, BITS_PER_TYPE(ssp_mask)) { - int playback, capture; - - name = devm_kasprintf(dev, GFP_KERNEL, "SSP%d-Codec", i); - cpu_dai_name = devm_kasprintf(dev, GFP_KERNEL, "SSP%d Pin", i); - codec_name = devm_kasprintf(dev, GFP_KERNEL, "i2c-%s:0%d", - ssp_info->acpi_id, j++); - - playback = ssp_info->dais[0].direction[SNDRV_PCM_STREAM_PLAYBACK]; - capture = ssp_info->dais[0].direction[SNDRV_PCM_STREAM_CAPTURE]; - - ret = init_simple_dai_link(dev, dai_links, &be_id, name, - playback, capture, cpu_dai_name, - codec_name, ssp_info->dais[0].dai_name, - NULL, ssp_info->ops); + if (ssp_num) { + ret = create_ssp_dailinks(card, &dai_links, &be_id, + ssp_info, ssp_mask); if (ret) return ret; - - ret = ssp_info->dais[0].init(card, NULL, dai_links, ssp_info, 0); - if (ret < 0) - return ret; - - dai_links++; } -DMIC: /* dmic */ if (dmic_num > 0) { if (ctx->ignore_pch_dmic) { -- cgit v1.2.3 From c2473a0e50f74b1ea9cc0070048d932d9b57c3ac Mon Sep 17 00:00:00 2001 From: Charles Keepax Date: Tue, 26 Mar 2024 11:04:06 -0500 Subject: ASoC: Intel: sof_sdw: Factor out DMIC DAI creation. Factor out the creation of the DMIC DAI links into a helper function. No functional change. Reviewed-by: Bard Liao Signed-off-by: Charles Keepax Signed-off-by: Pierre-Louis Bossart Link: https://msgid.link/r/20240326160429.13560-12-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/intel/boards/sof_sdw.c | 53 ++++++++++++++++++++++++---------------- 1 file changed, 32 insertions(+), 21 deletions(-) diff --git a/sound/soc/intel/boards/sof_sdw.c b/sound/soc/intel/boards/sof_sdw.c index 9980652c901b..5571c9e85dd7 100644 --- a/sound/soc/intel/boards/sof_sdw.c +++ b/sound/soc/intel/boards/sof_sdw.c @@ -1659,6 +1659,34 @@ static int create_ssp_dailinks(struct snd_soc_card *card, return 0; } +static int create_dmic_dailinks(struct snd_soc_card *card, + struct snd_soc_dai_link **dai_links, int *be_id) +{ + struct device *dev = card->dev; + int ret; + + ret = init_simple_dai_link(dev, *dai_links, be_id, "dmic01", + 0, 1, // DMIC only supports capture + "DMIC01 Pin", "dmic-codec", "dmic-hifi", + sof_sdw_dmic_init, NULL); + if (ret) + return ret; + + (*dai_links)++; + + ret = init_simple_dai_link(dev, *dai_links, be_id, "dmic16k", + 0, 1, // DMIC only supports capture + "DMIC16k Pin", "dmic-codec", "dmic-hifi", + /* don't call sof_sdw_dmic_init() twice */ + NULL, NULL); + if (ret) + return ret; + + (*dai_links)++; + + return 0; +} + static int sof_card_dai_links_create(struct snd_soc_card *card) { struct device *dev = card->dev; @@ -1825,30 +1853,13 @@ SSP: if (dmic_num > 0) { if (ctx->ignore_pch_dmic) { dev_warn(dev, "Ignoring PCH DMIC\n"); - goto HDMI; + } else { + ret = create_dmic_dailinks(card, &dai_links, &be_id); + if (ret) + return ret; } - - ret = init_simple_dai_link(dev, dai_links, &be_id, "dmic01", - 0, 1, // DMIC only supports capture - "DMIC01 Pin", "dmic-codec", "dmic-hifi", - sof_sdw_dmic_init, NULL); - if (ret) - return ret; - - dai_links++; - - ret = init_simple_dai_link(dev, dai_links, &be_id, "dmic16k", - 0, 1, // DMIC only supports capture - "DMIC16k Pin", "dmic-codec", "dmic-hifi", - /* don't call sof_sdw_dmic_init() twice */ - NULL, NULL); - if (ret) - return ret; - - dai_links++; } -HDMI: /* HDMI */ for (i = 0; i < hdmi_num; i++) { name = devm_kasprintf(dev, GFP_KERNEL, "iDisp%d", i + 1); -- cgit v1.2.3 From 914c43ab50f49656f378e748f894f9532ed19a26 Mon Sep 17 00:00:00 2001 From: Charles Keepax Date: Tue, 26 Mar 2024 11:04:07 -0500 Subject: ASoC: Intel: sof_sdw: Factor out HDMI DAI creation Factor out the creation of the HDMI DAI links into a helper function. No functional change. Reviewed-by: Bard Liao Signed-off-by: Charles Keepax Signed-off-by: Pierre-Louis Bossart Link: https://msgid.link/r/20240326160429.13560-13-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/intel/boards/sof_sdw.c | 61 +++++++++++++++++++++++++--------------- 1 file changed, 38 insertions(+), 23 deletions(-) diff --git a/sound/soc/intel/boards/sof_sdw.c b/sound/soc/intel/boards/sof_sdw.c index 5571c9e85dd7..7dc3559bf988 100644 --- a/sound/soc/intel/boards/sof_sdw.c +++ b/sound/soc/intel/boards/sof_sdw.c @@ -1687,6 +1687,41 @@ static int create_dmic_dailinks(struct snd_soc_card *card, return 0; } +static int create_hdmi_dailinks(struct snd_soc_card *card, + struct snd_soc_dai_link **dai_links, int *be_id, + int hdmi_num) +{ + struct device *dev = card->dev; + struct mc_private *ctx = snd_soc_card_get_drvdata(card); + int i, ret; + + for (i = 0; i < hdmi_num; i++) { + char *name = devm_kasprintf(dev, GFP_KERNEL, "iDisp%d", i + 1); + char *cpu_dai_name = devm_kasprintf(dev, GFP_KERNEL, "iDisp%d Pin", i + 1); + char *codec_name, *codec_dai_name; + + if (ctx->hdmi.idisp_codec) { + codec_name = "ehdaudio0D2"; + codec_dai_name = devm_kasprintf(dev, GFP_KERNEL, + "intel-hdmi-hifi%d", i + 1); + } else { + codec_name = "snd-soc-dummy"; + codec_dai_name = "snd-soc-dummy-dai"; + } + + ret = init_simple_dai_link(dev, *dai_links, be_id, name, + 1, 0, // HDMI only supports playback + cpu_dai_name, codec_name, codec_dai_name, + i == 0 ? sof_sdw_hdmi_init : NULL, NULL); + if (ret) + return ret; + + (*dai_links)++; + } + + return 0; +} + static int sof_card_dai_links_create(struct snd_soc_card *card) { struct device *dev = card->dev; @@ -1704,7 +1739,6 @@ static int sof_card_dai_links_create(struct snd_soc_card *card) struct snd_soc_dai_link *dai_links; int num_links; char *name, *cpu_dai_name; - char *codec_name, *codec_dai_name; int i, j, be_id = 0; int hdmi_num; unsigned long ssp_mask; @@ -1861,28 +1895,9 @@ SSP: } /* HDMI */ - for (i = 0; i < hdmi_num; i++) { - name = devm_kasprintf(dev, GFP_KERNEL, "iDisp%d", i + 1); - cpu_dai_name = devm_kasprintf(dev, GFP_KERNEL, "iDisp%d Pin", i + 1); - - if (ctx->hdmi.idisp_codec) { - codec_name = "ehdaudio0D2"; - codec_dai_name = devm_kasprintf(dev, GFP_KERNEL, - "intel-hdmi-hifi%d", i + 1); - } else { - codec_name = "snd-soc-dummy"; - codec_dai_name = "snd-soc-dummy-dai"; - } - - ret = init_simple_dai_link(dev, dai_links, &be_id, name, - 1, 0, // HDMI only supports playback - cpu_dai_name, codec_name, codec_dai_name, - i == 0 ? sof_sdw_hdmi_init : NULL, NULL); - if (ret) - return ret; - - dai_links++; - } + ret = create_hdmi_dailinks(card, &dai_links, &be_id, hdmi_num); + if (ret) + return ret; if (sof_sdw_quirk & SOF_SSP_BT_OFFLOAD_PRESENT) { int port = (sof_sdw_quirk & SOF_BT_OFFLOAD_SSP_MASK) >> -- cgit v1.2.3 From 0e2c1dd08607de04912b963f5df470d6a6969496 Mon Sep 17 00:00:00 2001 From: Charles Keepax Date: Tue, 26 Mar 2024 11:04:08 -0500 Subject: ASoC: Intel: sof_sdw: Factor out BlueTooth DAI creation Factor out the creation of the BlueTooth DAI links into a helper function. No functional change. Reviewed-by: Bard Liao Signed-off-by: Charles Keepax Signed-off-by: Pierre-Louis Bossart Link: https://msgid.link/r/20240326160429.13560-14-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/intel/boards/sof_sdw.c | 35 +++++++++++++++++++++++------------ 1 file changed, 23 insertions(+), 12 deletions(-) diff --git a/sound/soc/intel/boards/sof_sdw.c b/sound/soc/intel/boards/sof_sdw.c index 7dc3559bf988..6e2e934e1246 100644 --- a/sound/soc/intel/boards/sof_sdw.c +++ b/sound/soc/intel/boards/sof_sdw.c @@ -1722,6 +1722,27 @@ static int create_hdmi_dailinks(struct snd_soc_card *card, return 0; } +static int create_bt_dailinks(struct snd_soc_card *card, + struct snd_soc_dai_link **dai_links, int *be_id) +{ + struct device *dev = card->dev; + int port = (sof_sdw_quirk & SOF_BT_OFFLOAD_SSP_MASK) >> + SOF_BT_OFFLOAD_SSP_SHIFT; + char *name = devm_kasprintf(dev, GFP_KERNEL, "SSP%d-BT", port); + char *cpu_dai_name = devm_kasprintf(dev, GFP_KERNEL, "SSP%d Pin", port); + int ret; + + ret = init_simple_dai_link(dev, *dai_links, be_id, name, + 1, 1, cpu_dai_name, snd_soc_dummy_dlc.name, + snd_soc_dummy_dlc.dai_name, NULL, NULL); + if (ret) + return ret; + + (*dai_links)++; + + return 0; +} + static int sof_card_dai_links_create(struct snd_soc_card *card) { struct device *dev = card->dev; @@ -1738,7 +1759,6 @@ static int sof_card_dai_links_create(struct snd_soc_card *card) bool group_generated[SDW_MAX_GROUPS] = { }; struct snd_soc_dai_link *dai_links; int num_links; - char *name, *cpu_dai_name; int i, j, be_id = 0; int hdmi_num; unsigned long ssp_mask; @@ -1899,20 +1919,11 @@ SSP: if (ret) return ret; + /* BT */ if (sof_sdw_quirk & SOF_SSP_BT_OFFLOAD_PRESENT) { - int port = (sof_sdw_quirk & SOF_BT_OFFLOAD_SSP_MASK) >> - SOF_BT_OFFLOAD_SSP_SHIFT; - - name = devm_kasprintf(dev, GFP_KERNEL, "SSP%d-BT", port); - cpu_dai_name = devm_kasprintf(dev, GFP_KERNEL, "SSP%d Pin", port); - - ret = init_simple_dai_link(dev, dai_links, &be_id, name, - 1, 1, cpu_dai_name, snd_soc_dummy_dlc.name, - snd_soc_dummy_dlc.dai_name, NULL, NULL); + ret = create_bt_dailinks(card, &dai_links, &be_id); if (ret) return ret; - - dai_links++; } WARN_ON(dai_links != card->dai_link + card->num_links); -- cgit v1.2.3 From b48f238585a49983ae51f77d6494bcfcaad8f217 Mon Sep 17 00:00:00 2001 From: Charles Keepax Date: Tue, 26 Mar 2024 11:04:09 -0500 Subject: ASoC: Intel: sof_sdw: Factor out codec name generation In preparation for future refactoring pull out a helper specifically for generating the codec name. Reviewed-by: Bard Liao Signed-off-by: Charles Keepax Signed-off-by: Pierre-Louis Bossart Link: https://msgid.link/r/20240326160429.13560-15-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/intel/boards/sof_sdw.c | 47 +++++++++++++++++++++++----------------- 1 file changed, 27 insertions(+), 20 deletions(-) diff --git a/sound/soc/intel/boards/sof_sdw.c b/sound/soc/intel/boards/sof_sdw.c index 6e2e934e1246..1253a2dc33d2 100644 --- a/sound/soc/intel/boards/sof_sdw.c +++ b/sound/soc/intel/boards/sof_sdw.c @@ -1283,12 +1283,37 @@ static bool is_unique_device(const struct snd_soc_acpi_link_adr *adr_link, return true; } +static const char *get_codec_name(struct device *dev, + const struct sof_sdw_codec_info *codec_info, + const struct snd_soc_acpi_link_adr *adr_link, + int adr_index) +{ + u64 adr = adr_link->adr_d[adr_index].adr; + unsigned int sdw_version = SDW_VERSION(adr); + unsigned int link_id = SDW_DISCO_LINK_ID(adr); + unsigned int unique_id = SDW_UNIQUE_ID(adr); + unsigned int mfg_id = SDW_MFG_ID(adr); + unsigned int part_id = SDW_PART_ID(adr); + unsigned int class_id = SDW_CLASS_ID(adr); + + if (codec_info->codec_name) + return devm_kstrdup(dev, codec_info->codec_name, GFP_KERNEL); + else if (is_unique_device(adr_link, sdw_version, mfg_id, part_id, + class_id, adr_index)) + return devm_kasprintf(dev, GFP_KERNEL, "sdw:0:%01x:%04x:%04x:%02x", + link_id, mfg_id, part_id, class_id); + else + return devm_kasprintf(dev, GFP_KERNEL, "sdw:0:%01x:%04x:%04x:%02x:%01x", + link_id, mfg_id, part_id, class_id, unique_id); + + return NULL; +} + static int fill_sdw_codec_dlc(struct device *dev, const struct snd_soc_acpi_link_adr *adr_link, struct snd_soc_dai_link_component *codec, int adr_index, int dai_index) { - unsigned int sdw_version, unique_id, mfg_id, link_id, part_id, class_id; u64 adr = adr_link->adr_d[adr_index].adr; struct sof_sdw_codec_info *codec_info; @@ -1296,25 +1321,7 @@ static int fill_sdw_codec_dlc(struct device *dev, if (!codec_info) return -EINVAL; - sdw_version = SDW_VERSION(adr); - link_id = SDW_DISCO_LINK_ID(adr); - unique_id = SDW_UNIQUE_ID(adr); - mfg_id = SDW_MFG_ID(adr); - part_id = SDW_PART_ID(adr); - class_id = SDW_CLASS_ID(adr); - - if (codec_info->codec_name) - codec->name = devm_kstrdup(dev, codec_info->codec_name, GFP_KERNEL); - else if (is_unique_device(adr_link, sdw_version, mfg_id, part_id, - class_id, adr_index)) - codec->name = devm_kasprintf(dev, GFP_KERNEL, - "sdw:0:%01x:%04x:%04x:%02x", link_id, - mfg_id, part_id, class_id); - else - codec->name = devm_kasprintf(dev, GFP_KERNEL, - "sdw:0:%01x:%04x:%04x:%02x:%01x", link_id, - mfg_id, part_id, class_id, unique_id); - + codec->name = get_codec_name(dev, codec_info, adr_link, adr_index); if (!codec->name) return -ENOMEM; -- cgit v1.2.3 From aa238217d69b15edc709887248eec5c01370b453 Mon Sep 17 00:00:00 2001 From: Balamurugan C Date: Tue, 26 Mar 2024 11:04:10 -0500 Subject: ASoC: Intel: soc-acpi-intel-arl-match: Add rt711 sdca codec support Adding rt711 sdca codec support for arl boards. Reviewed-by: Bard Liao Reviewed-by: Chao Song Signed-off-by: Balamurugan C Signed-off-by: Pierre-Louis Bossart Link: https://msgid.link/r/20240326160429.13560-16-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/intel/common/soc-acpi-intel-arl-match.c | 24 +++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/sound/soc/intel/common/soc-acpi-intel-arl-match.c b/sound/soc/intel/common/soc-acpi-intel-arl-match.c index e52797aae6e6..79d26e0f2c28 100644 --- a/sound/soc/intel/common/soc-acpi-intel-arl-match.c +++ b/sound/soc/intel/common/soc-acpi-intel-arl-match.c @@ -24,6 +24,15 @@ static const struct snd_soc_acpi_adr_device rt711_0_adr[] = { } }; +static const struct snd_soc_acpi_adr_device rt711_sdca_0_adr[] = { + { + .adr = 0x000030025D071101ull, + .num_endpoints = 1, + .endpoints = &single_endpoint, + .name_prefix = "rt711" + } +}; + static const struct snd_soc_acpi_link_adr arl_rvp[] = { { .mask = BIT(0), @@ -33,6 +42,15 @@ static const struct snd_soc_acpi_link_adr arl_rvp[] = { {} }; +static const struct snd_soc_acpi_link_adr arl_sdca_rvp[] = { + { + .mask = BIT(0), + .num_adr = ARRAY_SIZE(rt711_sdca_0_adr), + .adr_d = rt711_sdca_0_adr, + }, + {} +}; + struct snd_soc_acpi_mach snd_soc_acpi_intel_arl_machines[] = { {}, }; @@ -46,6 +64,12 @@ struct snd_soc_acpi_mach snd_soc_acpi_intel_arl_sdw_machines[] = { .drv_name = "sof_sdw", .sof_tplg_filename = "sof-arl-rt711.tplg", }, + { + .link_mask = 0x1, /* link0 required */ + .links = arl_sdca_rvp, + .drv_name = "sof_sdw", + .sof_tplg_filename = "sof-arl-rt711-l0.tplg", + }, {}, }; EXPORT_SYMBOL_GPL(snd_soc_acpi_intel_arl_sdw_machines); -- cgit v1.2.3 From 17750bc6519f7fb4905e63e3855e4e32b01f9419 Mon Sep 17 00:00:00 2001 From: Charles Keepax Date: Tue, 26 Mar 2024 11:04:11 -0500 Subject: ASoC: Intel: sof_sdw: Remove no longer supported quirk The SOF_SDW_NO_AGGREGATION quirk is mostly for debug and no longer works correctly with the current state of the machine driver. Remove it from the code and add an error message if someone uses it. Reviewed-by: Bard Liao Signed-off-by: Charles Keepax Signed-off-by: Pierre-Louis Bossart Link: https://msgid.link/r/20240326160429.13560-17-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/intel/boards/sof_sdw.c | 12 ++++-------- sound/soc/intel/boards/sof_sdw_common.h | 1 + 2 files changed, 5 insertions(+), 8 deletions(-) diff --git a/sound/soc/intel/boards/sof_sdw.c b/sound/soc/intel/boards/sof_sdw.c index 1253a2dc33d2..fdedc32291f0 100644 --- a/sound/soc/intel/boards/sof_sdw.c +++ b/sound/soc/intel/boards/sof_sdw.c @@ -36,7 +36,7 @@ static void log_quirks(struct device *dev) dev_dbg(dev, "SSP port %ld\n", SOF_SSP_GET_PORT(sof_sdw_quirk)); if (sof_sdw_quirk & SOF_SDW_NO_AGGREGATION) - dev_dbg(dev, "quirk SOF_SDW_NO_AGGREGATION enabled\n"); + dev_err(dev, "quirk SOF_SDW_NO_AGGREGATION enabled but no longer supported\n"); } static int sof_sdw_quirk_cb(const struct dmi_system_id *id) @@ -1136,11 +1136,9 @@ static int get_dailink_info(struct device *dev, int *sdw_be_num, int *codecs_num) { bool group_visited[SDW_MAX_GROUPS]; - bool no_aggregation; int i; int j; - no_aggregation = sof_sdw_quirk & SOF_SDW_NO_AGGREGATION; *sdw_be_num = 0; if (!adr_link) @@ -1187,7 +1185,7 @@ static int get_dailink_info(struct device *dev, continue; /* count BE for each non-aggregated slave or group */ - if (!endpoint->aggregated || no_aggregation || + if (!endpoint->aggregated || !group_visited[endpoint->group_id]) (*sdw_be_num)++; } @@ -1393,10 +1391,9 @@ static int get_slave_info(const struct snd_soc_acpi_link_adr *adr_link, int *codec_num, unsigned int *group_id, int adr_index) { - bool no_aggregation = sof_sdw_quirk & SOF_SDW_NO_AGGREGATION; int i; - if (!adr_link->adr_d[adr_index].endpoints->aggregated || no_aggregation) { + if (!adr_link->adr_d[adr_index].endpoints->aggregated) { cpu_dai_id[0] = ffs(adr_link->mask) - 1; *cpu_dai_num = 1; *codec_num = 1; @@ -1758,7 +1755,6 @@ static int sof_card_dai_links_create(struct snd_soc_card *card) struct mc_private *ctx = snd_soc_card_get_drvdata(card); struct snd_soc_acpi_mach_params *mach_params = &mach->mach_params; const struct snd_soc_acpi_link_adr *adr_link = mach_params->links; - bool aggregation = !(sof_sdw_quirk & SOF_SDW_NO_AGGREGATION); struct snd_soc_codec_conf *codec_conf; struct sof_sdw_codec_info *codec_info; struct sof_sdw_codec_info *ssp_info; @@ -1896,7 +1892,7 @@ out: be_id = current_be_id; } - if (aggregation && endpoint->aggregated) + if (endpoint->aggregated) group_generated[endpoint->group_id] = true; } } diff --git a/sound/soc/intel/boards/sof_sdw_common.h b/sound/soc/intel/boards/sof_sdw_common.h index 1daf98a5849f..e21ef79126b2 100644 --- a/sound/soc/intel/boards/sof_sdw_common.h +++ b/sound/soc/intel/boards/sof_sdw_common.h @@ -50,6 +50,7 @@ enum { #define SOF_SDW_PCH_DMIC BIT(6) #define SOF_SSP_PORT(x) (((x) & GENMASK(5, 0)) << 7) #define SOF_SSP_GET_PORT(quirk) (((quirk) >> 7) & GENMASK(5, 0)) +/* Deprecated and no longer supported by the code */ #define SOF_SDW_NO_AGGREGATION BIT(14) /* BT audio offload: reserve 3 bits for future */ -- cgit v1.2.3 From 8166bdd2c560e59e9a6ec0c868b996294d8428d1 Mon Sep 17 00:00:00 2001 From: Charles Keepax Date: Tue, 26 Mar 2024 11:04:12 -0500 Subject: ASoC: intel: soc-acpi: Add missing cs42l43 endpoints Currently the cs42l43 just specifies a single endpoint, as the current machine driver only looks at the first endpoint specified. Future refactoring will process all endpoints, as such proper specification should be added for all the cs42l43 endpoints. Reviewed-by: Bard Liao Signed-off-by: Charles Keepax Signed-off-by: Pierre-Louis Bossart Link: https://msgid.link/r/20240326160429.13560-18-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/intel/common/soc-acpi-intel-mtl-match.c | 25 +++++++++++++++++++++-- sound/soc/intel/common/soc-acpi-intel-tgl-match.c | 25 +++++++++++++++++++++-- 2 files changed, 46 insertions(+), 4 deletions(-) diff --git a/sound/soc/intel/common/soc-acpi-intel-mtl-match.c b/sound/soc/intel/common/soc-acpi-intel-mtl-match.c index e9a5da079089..e06efc5b1457 100644 --- a/sound/soc/intel/common/soc-acpi-intel-mtl-match.c +++ b/sound/soc/intel/common/soc-acpi-intel-mtl-match.c @@ -338,11 +338,32 @@ static const struct snd_soc_acpi_link_adr mtl_712_only[] = { {} }; +static const struct snd_soc_acpi_endpoint cs42l43_endpoints[] = { + { /* Jack Playback Endpoint */ + .num = 0, + .aggregated = 0, + .group_position = 0, + .group_id = 0, + }, + { /* DMIC Capture Endpoint */ + .num = 1, + .aggregated = 0, + .group_position = 0, + .group_id = 0, + }, + { /* Jack Capture Endpoint */ + .num = 2, + .aggregated = 0, + .group_position = 0, + .group_id = 0, + }, +}; + static const struct snd_soc_acpi_adr_device cs42l43_0_adr[] = { { .adr = 0x00003001FA424301ull, - .num_endpoints = 1, - .endpoints = &single_endpoint, + .num_endpoints = ARRAY_SIZE(cs42l43_endpoints), + .endpoints = cs42l43_endpoints, .name_prefix = "cs42l43" } }; diff --git a/sound/soc/intel/common/soc-acpi-intel-tgl-match.c b/sound/soc/intel/common/soc-acpi-intel-tgl-match.c index 0fba0a60d9c7..007f1ac2327a 100644 --- a/sound/soc/intel/common/soc-acpi-intel-tgl-match.c +++ b/sound/soc/intel/common/soc-acpi-intel-tgl-match.c @@ -414,11 +414,32 @@ static const struct snd_soc_acpi_link_adr tgl_712_only[] = { {} }; +static const struct snd_soc_acpi_endpoint cs42l43_endpoints[] = { + { /* Jack Playback Endpoint */ + .num = 0, + .aggregated = 0, + .group_position = 0, + .group_id = 0, + }, + { /* DMIC Capture Endpoint */ + .num = 1, + .aggregated = 0, + .group_position = 0, + .group_id = 0, + }, + { /* Jack Capture Endpoint */ + .num = 2, + .aggregated = 0, + .group_position = 0, + .group_id = 0, + }, +}; + static const struct snd_soc_acpi_adr_device cs42l43_3_adr[] = { { .adr = 0x00033001FA424301ull, - .num_endpoints = 1, - .endpoints = &single_endpoint, + .num_endpoints = ARRAY_SIZE(cs42l43_endpoints), + .endpoints = cs42l43_endpoints, .name_prefix = "cs42l43" } }; -- cgit v1.2.3 From 27fd36aefa0013bea1cf6948e2e825e9b8cff97a Mon Sep 17 00:00:00 2001 From: Charles Keepax Date: Tue, 26 Mar 2024 11:04:13 -0500 Subject: ASoC: Intel: sof-sdw: Add new code for parsing the snd_soc_acpi structs The current machine driver code has a lot of loops parsing through the ACPI structs (snd_soc_acpi_link_adr, snd_soc_acpi_adr_device, snd_soc_acpi_endpoint), this makes it hard to understand exactly what information is being extracted and for what purposes. As well as being slightly inefficient, as the same information is looked up multiple times. There are also some issues with the handling of multiple endpoints on a single device, only the first of the snd_soc_acpi_endpoint structures is currently fully processed by the driver. This means doing things like aggregating the second endpoint on a device with another device are not currently possible. Add new parsing code that will count the devices and endpoints, parse them into an intermediate datastructure, and then use that to create the DAI links. This patch does not actually utilise the results of the parsing, items will be moved across in the following patches. This parsing is based around two new structures which are temporarily allocated whilst parsing. Firstly, sof_sdw_endpoint, which represents a specific endpoint for audio on a device and is more or less directly equivalent to snd_soc_acpi_endpoint. Secondly, sof_sdw_dailink which represents a DAI link and contains a linked list of one or more sof_sdw_endpoints. A single trip through the snd_soc_acpi data structures is used to populate these. One important point to note here is the use of the num field in snd_soc_acpi_endpoint to address sof_sdw_dai_info array in the sof_sdw_codec_info struct. This expects a one to one mapping between endpoints on a device and dai infos. It would be fine for a specific system to not specify an endpoint for all of the dai infos available, but two endpoints mapping to the same dai info would make not sense. Reviewed-by: Bard Liao Signed-off-by: Charles Keepax Signed-off-by: Pierre-Louis Bossart Link: https://msgid.link/r/20240326160429.13560-19-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/intel/boards/sof_sdw.c | 220 ++++++++++++++++++++++++++++++++++++--- 1 file changed, 206 insertions(+), 14 deletions(-) diff --git a/sound/soc/intel/boards/sof_sdw.c b/sound/soc/intel/boards/sof_sdw.c index fdedc32291f0..15bf8fbb3be9 100644 --- a/sound/soc/intel/boards/sof_sdw.c +++ b/sound/soc/intel/boards/sof_sdw.c @@ -1462,8 +1462,161 @@ static int sof_sdw_rtd_init(struct snd_soc_pcm_runtime *rtd) return 0; } +struct sof_sdw_endpoint { + struct list_head list; + + u32 link_mask; + const char *codec_name; + + const struct snd_soc_acpi_link_adr *adr_link; + struct sof_sdw_codec_info *codec_info; + const struct sof_sdw_dai_info *dai_info; +}; + +struct sof_sdw_dailink { + bool initialised; + + u8 group_id; + u32 link_mask[SNDRV_PCM_STREAM_LAST + 1]; + int num_devs[SNDRV_PCM_STREAM_LAST + 1]; + struct list_head endpoints; +}; + static const char * const type_strings[] = {"SimpleJack", "SmartAmp", "SmartMic"}; +static int count_sdw_endpoints(struct snd_soc_card *card, int *num_devs, int *num_ends) +{ + struct device *dev = card->dev; + struct snd_soc_acpi_mach *mach = dev_get_platdata(dev); + struct snd_soc_acpi_mach_params *mach_params = &mach->mach_params; + const struct snd_soc_acpi_link_adr *adr_link; + int i; + + for (adr_link = mach_params->links; adr_link->num_adr; adr_link++) { + *num_devs += adr_link->num_adr; + + for (i = 0; i < adr_link->num_adr; i++) + *num_ends += adr_link->adr_d[i].num_endpoints; + } + + dev_dbg(dev, "Found %d devices with %d endpoints\n", *num_devs, *num_ends); + + return 0; +} + +static struct sof_sdw_dailink *find_dailink(struct sof_sdw_dailink *dailinks, + const struct snd_soc_acpi_endpoint *new) +{ + while (dailinks->initialised) { + if (new->aggregated && dailinks->group_id == new->group_id) + return dailinks; + + dailinks++; + } + + INIT_LIST_HEAD(&dailinks->endpoints); + dailinks->group_id = new->group_id; + dailinks->initialised = true; + + return dailinks; +} + +static int parse_sdw_endpoints(struct snd_soc_card *card, + struct sof_sdw_dailink *sof_dais, + struct sof_sdw_endpoint *sof_ends) +{ + struct device *dev = card->dev; + struct snd_soc_acpi_mach *mach = dev_get_platdata(dev); + struct snd_soc_acpi_mach_params *mach_params = &mach->mach_params; + const struct snd_soc_acpi_link_adr *adr_link; + struct sof_sdw_endpoint *sof_end = sof_ends; + int num_dais = 0; + int i, j; + + for (adr_link = mach_params->links; adr_link->num_adr; adr_link++) { + if (!is_power_of_2(adr_link->mask)) { + dev_err(dev, "link with multiple mask bits: 0x%x\n", + adr_link->mask); + return -EINVAL; + } + + for (i = 0; i < adr_link->num_adr; i++) { + const struct snd_soc_acpi_adr_device *adr_dev = &adr_link->adr_d[i]; + struct sof_sdw_codec_info *codec_info; + const char *codec_name; + + if (!adr_dev->name_prefix) { + dev_err(dev, "codec 0x%llx does not have a name prefix\n", + adr_dev->adr); + return -EINVAL; + } + + codec_info = find_codec_info_part(adr_dev->adr); + if (!codec_info) + return -EINVAL; + + codec_name = get_codec_name(dev, codec_info, adr_link, i); + if (!codec_name) + return -ENOMEM; + + for (j = 0; j < adr_dev->num_endpoints; j++) { + const struct snd_soc_acpi_endpoint *adr_end; + const struct sof_sdw_dai_info *dai_info; + struct sof_sdw_dailink *sof_dai; + int stream; + + adr_end = &adr_dev->endpoints[j]; + dai_info = &codec_info->dais[adr_end->num]; + sof_dai = find_dailink(sof_dais, adr_end); + + dev_dbg(dev, + "Add dev: %d, 0x%llx end: %d, %s, %c/%c to %s: %d\n", + ffs(adr_link->mask) - 1, adr_dev->adr, + adr_end->num, type_strings[dai_info->dai_type], + dai_info->direction[SNDRV_PCM_STREAM_PLAYBACK] ? 'P' : '-', + dai_info->direction[SNDRV_PCM_STREAM_CAPTURE] ? 'C' : '-', + adr_end->aggregated ? "group" : "solo", + adr_end->group_id); + + if (adr_end->num >= codec_info->dai_num) { + dev_err(dev, + "%d is too many endpoints for codec: 0x%x\n", + adr_end->num, codec_info->part_id); + return -EINVAL; + } + + for_each_pcm_streams(stream) { + if (dai_info->direction[stream] && + dai_info->dailink[stream] < 0) { + dev_err(dev, + "Invalid dailink id %d for codec: 0x%x\n", + dai_info->dailink[stream], + codec_info->part_id); + return -EINVAL; + } + + if (dai_info->direction[stream]) { + num_dais += !sof_dai->num_devs[stream]; + sof_dai->num_devs[stream]++; + sof_dai->link_mask[stream] |= adr_link->mask; + } + } + + list_add_tail(&sof_end->list, &sof_dai->endpoints); + + sof_end->link_mask = adr_link->mask; + sof_end->codec_name = codec_name; + sof_end->adr_link = adr_link; + sof_end->codec_info = codec_info; + sof_end->dai_info = dai_info; + sof_end++; + } + } + } + + return num_dais; +} + static int create_sdw_dailink(struct snd_soc_card *card, struct snd_soc_dai_link **dai_links, const struct snd_soc_acpi_link_adr *adr_link, @@ -1758,7 +1911,11 @@ static int sof_card_dai_links_create(struct snd_soc_card *card) struct snd_soc_codec_conf *codec_conf; struct sof_sdw_codec_info *codec_info; struct sof_sdw_codec_info *ssp_info; + struct sof_sdw_endpoint *sof_ends; + struct sof_sdw_dailink *sof_dais; int codec_conf_num = 0; + int num_devs = 0; + int num_ends = 0; bool group_generated[SDW_MAX_GROUPS] = { }; struct snd_soc_dai_link *dai_links; int num_links; @@ -1767,10 +1924,32 @@ static int sof_card_dai_links_create(struct snd_soc_card *card) unsigned long ssp_mask; int ret; + ret = count_sdw_endpoints(card, &num_devs, &num_ends); + if (ret < 0) { + dev_err(dev, "failed to count devices/endpoints: %d\n", ret); + return ret; + } + + /* One per DAI link, worst case is a DAI link for every endpoint */ + sof_dais = kcalloc(num_ends, sizeof(*sof_dais), GFP_KERNEL); + if (!sof_dais) + return -ENOMEM; + + /* One per endpoint, ie. each DAI on each codec/amp */ + sof_ends = kcalloc(num_ends, sizeof(*sof_ends), GFP_KERNEL); + if (!sof_ends) { + ret = -ENOMEM; + goto err_dai; + } + + ret = parse_sdw_endpoints(card, sof_dais, sof_ends); + if (ret < 0) + goto err_end; + ret = get_dailink_info(dev, adr_link, &sdw_be_num, &codec_conf_num); if (ret < 0) { dev_err(dev, "failed to get sdw link info %d\n", ret); - return ret; + goto err_end; } /* @@ -1807,14 +1986,18 @@ static int sof_card_dai_links_create(struct snd_soc_card *card) /* allocate BE dailinks */ num_links = sdw_be_num + ssp_num + dmic_num + hdmi_num + bt_num; dai_links = devm_kcalloc(dev, num_links, sizeof(*dai_links), GFP_KERNEL); - if (!dai_links) - return -ENOMEM; + if (!dai_links) { + ret = -ENOMEM; + goto err_end; + } /* allocate codec conf, will be populated when dailinks are created */ codec_conf = devm_kcalloc(dev, codec_conf_num, sizeof(*codec_conf), GFP_KERNEL); - if (!codec_conf) - return -ENOMEM; + if (!codec_conf) { + ret = -ENOMEM; + goto err_end; + } card->dai_link = dai_links; card->num_links = num_links; @@ -1838,8 +2021,10 @@ static int sof_card_dai_links_create(struct snd_soc_card *card) for (i = 0; i < adr_link->num_adr; i++) { /* find codec info to get dai_num */ codec_info = find_codec_info_part(adr_link->adr_d[i].adr); - if (!codec_info) - return -EINVAL; + if (!codec_info) { + ret = -EINVAL; + goto err_end; + } if (codec_info->dai_num > 1) { ctx->append_dai_type = true; goto out; @@ -1871,8 +2056,10 @@ out: /* find codec info to get dai_num */ codec_info = find_codec_info_part(adr_link->adr_d[i].adr); - if (!codec_info) - return -EINVAL; + if (!codec_info) { + ret = -EINVAL; + goto err_end; + } for (j = 0; j < codec_info->dai_num ; j++) { int current_be_id; @@ -1903,7 +2090,7 @@ SSP: ret = create_ssp_dailinks(card, &dai_links, &be_id, ssp_info, ssp_mask); if (ret) - return ret; + goto err_end; } /* dmic */ @@ -1913,25 +2100,30 @@ SSP: } else { ret = create_dmic_dailinks(card, &dai_links, &be_id); if (ret) - return ret; + goto err_end; } } /* HDMI */ ret = create_hdmi_dailinks(card, &dai_links, &be_id, hdmi_num); if (ret) - return ret; + goto err_end; /* BT */ if (sof_sdw_quirk & SOF_SSP_BT_OFFLOAD_PRESENT) { ret = create_bt_dailinks(card, &dai_links, &be_id); if (ret) - return ret; + goto err_end; } WARN_ON(dai_links != card->dai_link + card->num_links); - return 0; +err_end: + kfree(sof_ends); +err_dai: + kfree(sof_dais); + + return ret; } static int sof_sdw_card_late_probe(struct snd_soc_card *card) -- cgit v1.2.3 From 0d7b9880db92e1eb07bdd4dc097e574512b894a9 Mon Sep 17 00:00:00 2001 From: Charles Keepax Date: Tue, 26 Mar 2024 11:04:14 -0500 Subject: ASoC: Intel: sof_sdw: Move counting and codec_conf to new parsing Use the output of the new snd_soc_acpi struct parsing for the purposes of counting the number of SoundWire DAI links and physical devices attached to the SoundWire. These counts are already returned by the parser so those can just be used directly. But the population of the codec_conf structures, is moved from the old parsing code over to the new. As the two parsers currently co-exist it is better to not have them both attempt to modify the same structures. Reviewed-by: Bard Liao Signed-off-by: Charles Keepax Signed-off-by: Pierre-Louis Bossart Link: https://msgid.link/r/20240326160429.13560-20-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/intel/boards/sof_sdw.c | 124 +++++++-------------------------------- 1 file changed, 22 insertions(+), 102 deletions(-) diff --git a/sound/soc/intel/boards/sof_sdw.c b/sound/soc/intel/boards/sof_sdw.c index 15bf8fbb3be9..0566ab843c2e 100644 --- a/sound/soc/intel/boards/sof_sdw.c +++ b/sound/soc/intel/boards/sof_sdw.c @@ -1126,79 +1126,6 @@ static struct sof_sdw_codec_info *find_codec_info_dai(const char *dai_name, return NULL; } -/* - * get BE dailink number and CPU DAI number based on sdw link adr. - * Since some sdw slaves may be aggregated, the CPU DAI number - * may be larger than the number of BE dailinks. - */ -static int get_dailink_info(struct device *dev, - const struct snd_soc_acpi_link_adr *adr_link, - int *sdw_be_num, int *codecs_num) -{ - bool group_visited[SDW_MAX_GROUPS]; - int i; - int j; - - *sdw_be_num = 0; - - if (!adr_link) - return -EINVAL; - - for (i = 0; i < SDW_MAX_GROUPS; i++) - group_visited[i] = false; - - for (; adr_link->num_adr; adr_link++) { - const struct snd_soc_acpi_endpoint *endpoint; - struct sof_sdw_codec_info *codec_info; - int stream; - u64 adr; - - /* make sure the link mask has a single bit set */ - if (!is_power_of_2(adr_link->mask)) - return -EINVAL; - - for (i = 0; i < adr_link->num_adr; i++) { - adr = adr_link->adr_d[i].adr; - codec_info = find_codec_info_part(adr); - if (!codec_info) - return -EINVAL; - - *codecs_num += codec_info->dai_num; - - if (!adr_link->adr_d[i].name_prefix) { - dev_err(dev, "codec 0x%llx does not have a name prefix\n", - adr_link->adr_d[i].adr); - return -EINVAL; - } - - endpoint = adr_link->adr_d[i].endpoints; - if (endpoint->aggregated && !endpoint->group_id) { - dev_err(dev, "invalid group id on link %x\n", - adr_link->mask); - return -EINVAL; - } - - for (j = 0; j < codec_info->dai_num; j++) { - /* count DAI number for playback and capture */ - for_each_pcm_streams(stream) { - if (!codec_info->dais[j].direction[stream]) - continue; - - /* count BE for each non-aggregated slave or group */ - if (!endpoint->aggregated || - !group_visited[endpoint->group_id]) - (*sdw_be_num)++; - } - } - - if (endpoint->aggregated) - group_visited[endpoint->group_id] = true; - } - } - - return 0; -} - static void init_dai_link(struct device *dev, struct snd_soc_dai_link *dai_links, int *be_id, char *name, int playback, int capture, struct snd_soc_dai_link_component *cpus, int cpus_num, @@ -1528,6 +1455,7 @@ static int parse_sdw_endpoints(struct snd_soc_card *card, struct device *dev = card->dev; struct snd_soc_acpi_mach *mach = dev_get_platdata(dev); struct snd_soc_acpi_mach_params *mach_params = &mach->mach_params; + struct snd_soc_codec_conf *codec_conf = card->codec_conf; const struct snd_soc_acpi_link_adr *adr_link; struct sof_sdw_endpoint *sof_end = sof_ends; int num_dais = 0; @@ -1559,6 +1487,13 @@ static int parse_sdw_endpoints(struct snd_soc_card *card, if (!codec_name) return -ENOMEM; + codec_conf->dlc.name = codec_name; + codec_conf->name_prefix = adr_dev->name_prefix; + codec_conf++; + + dev_dbg(dev, "Adding prefix %s for %s\n", + adr_dev->name_prefix, codec_name); + for (j = 0; j < adr_dev->num_endpoints; j++) { const struct snd_soc_acpi_endpoint *adr_end; const struct sof_sdw_dai_info *dai_info; @@ -1614,13 +1549,14 @@ static int parse_sdw_endpoints(struct snd_soc_card *card, } } + WARN_ON(codec_conf != card->codec_conf + card->num_configs); + return num_dais; } static int create_sdw_dailink(struct snd_soc_card *card, struct snd_soc_dai_link **dai_links, const struct snd_soc_acpi_link_adr *adr_link, - struct snd_soc_codec_conf **codec_conf, int *be_id, int adr_index, int dai_index) { struct mc_private *ctx = snd_soc_card_get_drvdata(card); @@ -1672,26 +1608,16 @@ static int create_sdw_dailink(struct snd_soc_card *card, endpoints->group_id != group_id)) continue; - /* sanity check */ - if (*codec_conf >= card->codec_conf + card->num_configs) { - dev_err(dev, "codec_conf array overflowed\n"); - return -EINVAL; - } - ret = fill_sdw_codec_dlc(dev, adr_link_next, &codecs[codec_dlc_index], j, dai_index); if (ret) return ret; - (*codec_conf)->dlc = codecs[codec_dlc_index]; - (*codec_conf)->name_prefix = adr_link_next->adr_d[j].name_prefix; - sdw_codec_ch_maps[codec_dlc_index].cpu = i; sdw_codec_ch_maps[codec_dlc_index].codec = codec_dlc_index; codec_dlc_index++; - (*codec_conf)++; } j = 0; @@ -1913,7 +1839,6 @@ static int sof_card_dai_links_create(struct snd_soc_card *card) struct sof_sdw_codec_info *ssp_info; struct sof_sdw_endpoint *sof_ends; struct sof_sdw_dailink *sof_dais; - int codec_conf_num = 0; int num_devs = 0; int num_ends = 0; bool group_generated[SDW_MAX_GROUPS] = { }; @@ -1942,15 +1867,21 @@ static int sof_card_dai_links_create(struct snd_soc_card *card) goto err_dai; } + /* will be populated when acpi endpoints are parsed */ + codec_conf = devm_kcalloc(dev, num_devs, sizeof(*codec_conf), GFP_KERNEL); + if (!codec_conf) { + ret = -ENOMEM; + goto err_end; + } + + card->codec_conf = codec_conf; + card->num_configs = num_devs; + ret = parse_sdw_endpoints(card, sof_dais, sof_ends); if (ret < 0) goto err_end; - ret = get_dailink_info(dev, adr_link, &sdw_be_num, &codec_conf_num); - if (ret < 0) { - dev_err(dev, "failed to get sdw link info %d\n", ret); - goto err_end; - } + sdw_be_num = ret; /* * on generic tgl platform, I2S or sdw mode is supported @@ -1991,18 +1922,8 @@ static int sof_card_dai_links_create(struct snd_soc_card *card) goto err_end; } - /* allocate codec conf, will be populated when dailinks are created */ - codec_conf = devm_kcalloc(dev, codec_conf_num, sizeof(*codec_conf), - GFP_KERNEL); - if (!codec_conf) { - ret = -ENOMEM; - goto err_end; - } - card->dai_link = dai_links; card->num_links = num_links; - card->codec_conf = codec_conf; - card->num_configs = codec_conf_num; /* SDW */ if (!sdw_be_num) @@ -2065,8 +1986,7 @@ out: int current_be_id; ret = create_sdw_dailink(card, &dai_links, adr_link, - &codec_conf, ¤t_be_id, - i, j); + ¤t_be_id, i, j); if (ret < 0) { dev_err(dev, "failed to create dai link %d on 0x%x\n", -- cgit v1.2.3 From 22f2a5e71030c5da938c4d3c50f2159582ee2362 Mon Sep 17 00:00:00 2001 From: Charles Keepax Date: Tue, 26 Mar 2024 11:04:15 -0500 Subject: ASoC: Intel: sof_sdw: Move ignore_pch_dmic to new parsing Trivial move of the handling of ignore_pch_dmic over to the new parsing code. Reviewed-by: Bard Liao Signed-off-by: Charles Keepax Signed-off-by: Pierre-Louis Bossart Link: https://msgid.link/r/20240326160429.13560-21-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/intel/boards/sof_sdw.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/sound/soc/intel/boards/sof_sdw.c b/sound/soc/intel/boards/sof_sdw.c index 0566ab843c2e..cda759ee6345 100644 --- a/sound/soc/intel/boards/sof_sdw.c +++ b/sound/soc/intel/boards/sof_sdw.c @@ -1453,6 +1453,7 @@ static int parse_sdw_endpoints(struct snd_soc_card *card, struct sof_sdw_endpoint *sof_ends) { struct device *dev = card->dev; + struct mc_private *ctx = snd_soc_card_get_drvdata(card); struct snd_soc_acpi_mach *mach = dev_get_platdata(dev); struct snd_soc_acpi_mach_params *mach_params = &mach->mach_params; struct snd_soc_codec_conf *codec_conf = card->codec_conf; @@ -1483,6 +1484,8 @@ static int parse_sdw_endpoints(struct snd_soc_card *card, if (!codec_info) return -EINVAL; + ctx->ignore_pch_dmic |= codec_info->ignore_pch_dmic; + codec_name = get_codec_name(dev, codec_info, adr_link, i); if (!codec_name) return -ENOMEM; @@ -1630,8 +1633,6 @@ static int create_sdw_dailink(struct snd_soc_card *card, if (!codec_info) return -EINVAL; - ctx->ignore_pch_dmic |= codec_info->ignore_pch_dmic; - for_each_pcm_streams(stream) { char *name, *cpu_name; int playback, capture; -- cgit v1.2.3 From 13e698e8ee70cebfcaead8188e77d3e90f94498d Mon Sep 17 00:00:00 2001 From: Charles Keepax Date: Tue, 26 Mar 2024 11:04:16 -0500 Subject: ASoC: Intel: sof_sdw: Move append_dai_type to new parsing append_dai_type should be set to true in any situation that would result in multiple DAI links existing on a single SoundWire bus, because the legacy naming used only the bus number to make things unique. The current code handles this by looking for codecs with multiple dai_info structs and looking for buses that include multiple types of device on them. The first of these assumes that all DAIs on a given device would be in use. The second, with dissimilar aggregation now being supported, isn't really an accurate check either since those devices could be aggregated into a single DAI link. Move the handling for this flag over to the new parsing code and simplify things a little by looking directly for SoundWire links that will contain multiple DAI links to set the flag. These changes should not cause any change in behaviour for any currently supported systems. Reviewed-by: Bard Liao Signed-off-by: Charles Keepax Signed-off-by: Pierre-Louis Bossart Link: https://msgid.link/r/20240326160429.13560-22-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/intel/boards/sof_sdw.c | 36 +++++------------------------------- 1 file changed, 5 insertions(+), 31 deletions(-) diff --git a/sound/soc/intel/boards/sof_sdw.c b/sound/soc/intel/boards/sof_sdw.c index cda759ee6345..89ce77961634 100644 --- a/sound/soc/intel/boards/sof_sdw.c +++ b/sound/soc/intel/boards/sof_sdw.c @@ -1463,6 +1463,8 @@ static int parse_sdw_endpoints(struct snd_soc_card *card, int i, j; for (adr_link = mach_params->links; adr_link->num_adr; adr_link++) { + int num_link_dailinks = 0; + if (!is_power_of_2(adr_link->mask)) { dev_err(dev, "link with multiple mask bits: 0x%x\n", adr_link->mask); @@ -1540,6 +1542,7 @@ static int parse_sdw_endpoints(struct snd_soc_card *card, } } + num_link_dailinks += !!list_empty(&sof_dai->endpoints); list_add_tail(&sof_end->list, &sof_dai->endpoints); sof_end->link_mask = adr_link->mask; @@ -1550,6 +1553,8 @@ static int parse_sdw_endpoints(struct snd_soc_card *card, sof_end++; } } + + ctx->append_dai_type |= (num_link_dailinks > 1); } WARN_ON(codec_conf != card->codec_conf + card->num_configs); @@ -1933,37 +1938,6 @@ static int sof_card_dai_links_create(struct snd_soc_card *card) for (i = 0; i < SDW_MAX_LINKS; i++) ctx->sdw_pin_index[i] = SDW_INTEL_BIDIR_PDI_BASE; - for (; adr_link->num_adr; adr_link++) { - /* - * If there are two or more different devices on the same sdw link, we have to - * append the codec type to the dai link name to prevent duplicated dai link name. - * The same type devices on the same sdw link will be in the same - * snd_soc_acpi_adr_device array. They won't be described in different adr_links. - */ - for (i = 0; i < adr_link->num_adr; i++) { - /* find codec info to get dai_num */ - codec_info = find_codec_info_part(adr_link->adr_d[i].adr); - if (!codec_info) { - ret = -EINVAL; - goto err_end; - } - if (codec_info->dai_num > 1) { - ctx->append_dai_type = true; - goto out; - } - for (j = 0; j < i; j++) { - if ((SDW_PART_ID(adr_link->adr_d[i].adr) != - SDW_PART_ID(adr_link->adr_d[j].adr)) || - (SDW_MFG_ID(adr_link->adr_d[i].adr) != - SDW_MFG_ID(adr_link->adr_d[j].adr))) { - ctx->append_dai_type = true; - goto out; - } - } - } - } -out: - /* generate DAI links by each sdw link */ for (adr_link = mach_params->links ; adr_link->num_adr; adr_link++) { for (i = 0; i < adr_link->num_adr; i++) { -- cgit v1.2.3 From 5f14d70b7f6e9deb97893d5c09dd0986e92b7021 Mon Sep 17 00:00:00 2001 From: Charles Keepax Date: Tue, 26 Mar 2024 11:04:17 -0500 Subject: ASoC: Intel: sof_sdw: Move generation of DAI links to new parsing The only part left using the old parsing code is now the generation of the actual DAI links. Move this generation over to being based on the new parsing, which allows the removal of the last of the old parsing code. The new DAI link generation is a simple matter of creating a new DAI link for each sof_sdw_dailink struct, and adding a cpu, a codec, and a mapping for each sof_sdw_endpoint contained in that sof_sdw_dailink. Note that the CPUs can be inferred as the endpoint list is iterated, because the endpoints were added into the list sorted by link. Reviewed-by: Bard Liao Signed-off-by: Charles Keepax Signed-off-by: Pierre-Louis Bossart Link: https://msgid.link/r/20240326160429.13560-23-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/intel/boards/sof_sdw.c | 340 +++++++++------------------------------ 1 file changed, 78 insertions(+), 262 deletions(-) diff --git a/sound/soc/intel/boards/sof_sdw.c b/sound/soc/intel/boards/sof_sdw.c index 89ce77961634..9f1c49df9cd2 100644 --- a/sound/soc/intel/boards/sof_sdw.c +++ b/sound/soc/intel/boards/sof_sdw.c @@ -1234,129 +1234,6 @@ static const char *get_codec_name(struct device *dev, return NULL; } -static int fill_sdw_codec_dlc(struct device *dev, - const struct snd_soc_acpi_link_adr *adr_link, - struct snd_soc_dai_link_component *codec, - int adr_index, int dai_index) -{ - u64 adr = adr_link->adr_d[adr_index].adr; - struct sof_sdw_codec_info *codec_info; - - codec_info = find_codec_info_part(adr); - if (!codec_info) - return -EINVAL; - - codec->name = get_codec_name(dev, codec_info, adr_link, adr_index); - if (!codec->name) - return -ENOMEM; - - codec->dai_name = codec_info->dais[dai_index].dai_name; - - return 0; -} - -static int set_codec_init_func(struct snd_soc_card *card, - const struct snd_soc_acpi_link_adr *adr_link, - struct snd_soc_dai_link *dai_links, - bool playback, int group_id, int adr_index, int dai_index) -{ - int i = adr_index; - - do { - /* - * Initialize the codec. If codec is part of an aggregated - * group (group_id>0), initialize all codecs belonging to - * same group. - * The first link should start with adr_link->adr_d[adr_index] - * because that is the device that we want to initialize and - * we should end immediately if it is not aggregated (group_id=0) - */ - for ( ; i < adr_link->num_adr; i++) { - struct sof_sdw_codec_info *codec_info; - - codec_info = find_codec_info_part(adr_link->adr_d[i].adr); - if (!codec_info) - return -EINVAL; - - /* The group_id is > 0 iff the codec is aggregated */ - if (adr_link->adr_d[i].endpoints->group_id != group_id) - continue; - - if (codec_info->dais[dai_index].init) - codec_info->dais[dai_index].init(card, - adr_link, - dai_links, - codec_info, - playback); - if (!group_id) - return 0; - } - - i = 0; - adr_link++; - } while (adr_link->mask); - - return 0; -} - -/* - * check endpoint status in slaves and gather link ID for all slaves in - * the same group to generate different CPU DAI. Now only support - * one sdw link with all slaves set with only single group id. - * - * one slave on one sdw link with aggregated = 0 - * one sdw BE DAI <---> one-cpu DAI <---> one-codec DAI - * - * two or more slaves on one sdw link with aggregated = 0 - * one sdw BE DAI <---> one-cpu DAI <---> multi-codec DAIs - * - * multiple links with multiple slaves with aggregated = 1 - * one sdw BE DAI <---> 1 .. N CPU DAIs <----> 1 .. N codec DAIs - */ -static int get_slave_info(const struct snd_soc_acpi_link_adr *adr_link, - struct device *dev, int *cpu_dai_id, int *cpu_dai_num, - int *codec_num, unsigned int *group_id, - int adr_index) -{ - int i; - - if (!adr_link->adr_d[adr_index].endpoints->aggregated) { - cpu_dai_id[0] = ffs(adr_link->mask) - 1; - *cpu_dai_num = 1; - *codec_num = 1; - *group_id = 0; - return 0; - } - - *codec_num = 0; - *cpu_dai_num = 0; - *group_id = adr_link->adr_d[adr_index].endpoints->group_id; - - /* Count endpoints with the same group_id in the adr_link */ - for (; adr_link && adr_link->num_adr; adr_link++) { - unsigned int link_codecs = 0; - - for (i = 0; i < adr_link->num_adr; i++) { - if (adr_link->adr_d[i].endpoints->aggregated && - adr_link->adr_d[i].endpoints->group_id == *group_id) - link_codecs++; - } - - if (link_codecs) { - *codec_num += link_codecs; - - if (*cpu_dai_num >= SDW_MAX_CPU_DAIS) { - dev_err(dev, "cpu_dai_id array overflowed\n"); - return -EINVAL; - } - - cpu_dai_id[(*cpu_dai_num)++] = ffs(adr_link->mask) - 1; - } - } - - return 0; -} - static int sof_sdw_rtd_init(struct snd_soc_pcm_runtime *rtd) { struct sof_sdw_codec_info *codec_info; @@ -1563,135 +1440,102 @@ static int parse_sdw_endpoints(struct snd_soc_card *card, } static int create_sdw_dailink(struct snd_soc_card *card, + struct sof_sdw_dailink *sof_dai, struct snd_soc_dai_link **dai_links, - const struct snd_soc_acpi_link_adr *adr_link, - int *be_id, int adr_index, int dai_index) + int *be_id) { - struct mc_private *ctx = snd_soc_card_get_drvdata(card); struct device *dev = card->dev; - const struct snd_soc_acpi_link_adr *adr_link_next; - struct snd_soc_dai_link_ch_map *sdw_codec_ch_maps; - struct snd_soc_dai_link_component *codecs; - struct snd_soc_dai_link_component *cpus; - struct sof_sdw_codec_info *codec_info; - int cpu_dai_id[SDW_MAX_CPU_DAIS]; - int cpu_dai_num; - unsigned int group_id; - int codec_dlc_index = 0; - int codec_num; + struct mc_private *ctx = snd_soc_card_get_drvdata(card); + struct sof_sdw_endpoint *sof_end; int stream; - int i = 0; - int j, k; - int ret; - - ret = get_slave_info(adr_link, dev, cpu_dai_id, &cpu_dai_num, &codec_num, - &group_id, adr_index); - if (ret) - return ret; - - codecs = devm_kcalloc(dev, codec_num, sizeof(*codecs), GFP_KERNEL); - if (!codecs) - return -ENOMEM; - - sdw_codec_ch_maps = devm_kcalloc(dev, codec_num, - sizeof(*sdw_codec_ch_maps), GFP_KERNEL); - if (!sdw_codec_ch_maps) - return -ENOMEM; - - /* generate codec name on different links in the same group */ - j = adr_index; - for (adr_link_next = adr_link; adr_link_next && adr_link_next->num_adr && - i < cpu_dai_num; adr_link_next++) { - /* skip the link excluded by this processed group */ - if (cpu_dai_id[i] != ffs(adr_link_next->mask) - 1) - continue; - - /* j reset after loop, adr_index only applies to first link */ - for (; j < adr_link_next->num_adr && codec_dlc_index < codec_num; j++) { - const struct snd_soc_acpi_endpoint *endpoints; - - endpoints = adr_link_next->adr_d[j].endpoints; - - if (group_id && (!endpoints->aggregated || - endpoints->group_id != group_id)) - continue; - - ret = fill_sdw_codec_dlc(dev, adr_link_next, - &codecs[codec_dlc_index], - j, dai_index); - if (ret) - return ret; - - sdw_codec_ch_maps[codec_dlc_index].cpu = i; - sdw_codec_ch_maps[codec_dlc_index].codec = codec_dlc_index; - - codec_dlc_index++; - } - j = 0; - - /* check next link to create codec dai in the processed group */ - i++; - } - - /* find codec info to create BE DAI */ - codec_info = find_codec_info_part(adr_link->adr_d[adr_index].adr); - if (!codec_info) - return -EINVAL; for_each_pcm_streams(stream) { - char *name, *cpu_name; - int playback, capture; static const char * const sdw_stream_name[] = { "SDW%d-Playback", "SDW%d-Capture", "SDW%d-Playback-%s", "SDW%d-Capture-%s", }; + struct snd_soc_dai_link_ch_map *codec_maps; + struct snd_soc_dai_link_component *codecs; + struct snd_soc_dai_link_component *cpus; + int num_cpus = hweight32(sof_dai->link_mask[stream]); + int num_codecs = sof_dai->num_devs[stream]; + int playback, capture; + int cur_link = 0; + int i = 0, j = 0; + char *name; - if (!codec_info->dais[dai_index].direction[stream]) + if (!sof_dai->num_devs[stream]) continue; - *be_id = codec_info->dais[dai_index].dailink[stream]; + sof_end = list_first_entry(&sof_dai->endpoints, + struct sof_sdw_endpoint, list); + + *be_id = sof_end->dai_info->dailink[stream]; if (*be_id < 0) { dev_err(dev, "Invalid dailink id %d\n", *be_id); return -EINVAL; } /* create stream name according to first link id */ - if (ctx->append_dai_type) { + if (ctx->append_dai_type) name = devm_kasprintf(dev, GFP_KERNEL, - sdw_stream_name[stream + 2], cpu_dai_id[0], - type_strings[codec_info->dais[dai_index].dai_type]); - } else { + sdw_stream_name[stream + 2], + ffs(sof_end->link_mask) - 1, + type_strings[sof_end->dai_info->dai_type]); + else name = devm_kasprintf(dev, GFP_KERNEL, - sdw_stream_name[stream], cpu_dai_id[0]); - } + sdw_stream_name[stream], + ffs(sof_end->link_mask) - 1); if (!name) return -ENOMEM; - cpus = devm_kcalloc(dev, cpu_dai_num, sizeof(*cpus), GFP_KERNEL); + cpus = devm_kcalloc(dev, num_cpus, sizeof(*cpus), GFP_KERNEL); if (!cpus) return -ENOMEM; - /* - * generate CPU DAI name base on the sdw link ID and - * PIN ID with offset of 2 according to sdw dai driver. - */ - for (k = 0; k < cpu_dai_num; k++) { - cpu_name = devm_kasprintf(dev, GFP_KERNEL, - "SDW%d Pin%d", cpu_dai_id[k], - ctx->sdw_pin_index[cpu_dai_id[k]]++); - if (!cpu_name) - return -ENOMEM; + codecs = devm_kcalloc(dev, num_codecs, sizeof(*codecs), GFP_KERNEL); + if (!codecs) + return -ENOMEM; + + codec_maps = devm_kcalloc(dev, num_codecs, sizeof(*codec_maps), GFP_KERNEL); + if (!codec_maps) + return -ENOMEM; + + list_for_each_entry(sof_end, &sof_dai->endpoints, list) { + if (!sof_end->dai_info->direction[stream]) + continue; + + if (cur_link != sof_end->link_mask) { + int link_num = ffs(sof_end->link_mask) - 1; + int pin_num = ctx->sdw_pin_index[link_num]++; + + cur_link = sof_end->link_mask; - cpus[k].dai_name = cpu_name; + cpus[i].dai_name = devm_kasprintf(dev, GFP_KERNEL, + "SDW%d Pin%d", + link_num, pin_num); + if (!cpus[i].dai_name) + return -ENOMEM; + i++; + } + + codec_maps[j].cpu = i - 1; + codec_maps[j].codec = j; + + codecs[j].name = sof_end->codec_name; + codecs[j].dai_name = sof_end->dai_info->dai_name; + j++; } + WARN_ON(i != num_cpus || j != num_codecs); + playback = (stream == SNDRV_PCM_STREAM_PLAYBACK); capture = (stream == SNDRV_PCM_STREAM_CAPTURE); init_dai_link(dev, *dai_links, be_id, name, playback, capture, - cpus, cpu_dai_num, codecs, codec_num, + cpus, num_cpus, codecs, num_codecs, sof_sdw_rtd_init, &sdw_ops); /* @@ -1699,13 +1543,14 @@ static int create_sdw_dailink(struct snd_soc_card *card, * based on wait_for_completion(), tag them as 'nonatomic'. */ (*dai_links)->nonatomic = true; - (*dai_links)->ch_maps = sdw_codec_ch_maps; - - ret = set_codec_init_func(card, adr_link, *dai_links, - playback, group_id, adr_index, dai_index); - if (ret < 0) { - dev_err(dev, "failed to init codec 0x%x\n", codec_info->part_id); - return ret; + (*dai_links)->ch_maps = codec_maps; + + list_for_each_entry(sof_end, &sof_dai->endpoints, list) { + if (sof_end->dai_info->init) + sof_end->dai_info->init(card, sof_end->adr_link, + *dai_links, + sof_end->codec_info, + playback); } (*dai_links)++; @@ -1839,18 +1684,15 @@ static int sof_card_dai_links_create(struct snd_soc_card *card) int sdw_be_num = 0, ssp_num = 0, dmic_num = 0, bt_num = 0; struct mc_private *ctx = snd_soc_card_get_drvdata(card); struct snd_soc_acpi_mach_params *mach_params = &mach->mach_params; - const struct snd_soc_acpi_link_adr *adr_link = mach_params->links; struct snd_soc_codec_conf *codec_conf; - struct sof_sdw_codec_info *codec_info; struct sof_sdw_codec_info *ssp_info; struct sof_sdw_endpoint *sof_ends; struct sof_sdw_dailink *sof_dais; int num_devs = 0; int num_ends = 0; - bool group_generated[SDW_MAX_GROUPS] = { }; struct snd_soc_dai_link *dai_links; int num_links; - int i, j, be_id = 0; + int i, be_id = 0; int hdmi_num; unsigned long ssp_mask; int ret; @@ -1939,44 +1781,18 @@ static int sof_card_dai_links_create(struct snd_soc_card *card) ctx->sdw_pin_index[i] = SDW_INTEL_BIDIR_PDI_BASE; /* generate DAI links by each sdw link */ - for (adr_link = mach_params->links ; adr_link->num_adr; adr_link++) { - for (i = 0; i < adr_link->num_adr; i++) { - const struct snd_soc_acpi_endpoint *endpoint; - - endpoint = adr_link->adr_d[i].endpoints; - - /* this group has been generated */ - if (endpoint->aggregated && - group_generated[endpoint->group_id]) - continue; - - /* find codec info to get dai_num */ - codec_info = find_codec_info_part(adr_link->adr_d[i].adr); - if (!codec_info) { - ret = -EINVAL; - goto err_end; - } + while (sof_dais->initialised) { + int current_be_id; - for (j = 0; j < codec_info->dai_num ; j++) { - int current_be_id; - - ret = create_sdw_dailink(card, &dai_links, adr_link, - ¤t_be_id, i, j); - if (ret < 0) { - dev_err(dev, - "failed to create dai link %d on 0x%x\n", - j, codec_info->part_id); - return ret; - } + ret = create_sdw_dailink(card, sof_dais, &dai_links, ¤t_be_id); + if (ret) + goto err_end; - /* Update the be_id to match the highest ID used for SDW link */ - if (be_id < current_be_id) - be_id = current_be_id; - } + /* Update the be_id to match the highest ID used for SDW link */ + if (be_id < current_be_id) + be_id = current_be_id; - if (endpoint->aggregated) - group_generated[endpoint->group_id] = true; - } + sof_dais++; } SSP: -- cgit v1.2.3 From 59bf457d80551003a06d32f5c3d1da7f64a3d420 Mon Sep 17 00:00:00 2001 From: Charles Keepax Date: Tue, 26 Mar 2024 11:04:18 -0500 Subject: ASoC: intel: sof_sdw: Factor out SoundWire DAI creation Factor out the creation of the SoundWire DAI links into a helper function. No functional change. Reviewed-by: Bard Liao Signed-off-by: Charles Keepax Signed-off-by: Pierre-Louis Bossart Link: https://msgid.link/r/20240326160429.13560-24-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/intel/boards/sof_sdw.c | 50 +++++++++++++++++++++++++--------------- 1 file changed, 31 insertions(+), 19 deletions(-) diff --git a/sound/soc/intel/boards/sof_sdw.c b/sound/soc/intel/boards/sof_sdw.c index 9f1c49df9cd2..3e6a758c98ab 100644 --- a/sound/soc/intel/boards/sof_sdw.c +++ b/sound/soc/intel/boards/sof_sdw.c @@ -1559,6 +1559,34 @@ static int create_sdw_dailink(struct snd_soc_card *card, return 0; } +static int create_sdw_dailinks(struct snd_soc_card *card, + struct snd_soc_dai_link **dai_links, int *be_id, + struct sof_sdw_dailink *sof_dais) +{ + struct mc_private *ctx = snd_soc_card_get_drvdata(card); + int ret, i; + + for (i = 0; i < SDW_MAX_LINKS; i++) + ctx->sdw_pin_index[i] = SDW_INTEL_BIDIR_PDI_BASE; + + /* generate DAI links by each sdw link */ + while (sof_dais->initialised) { + int current_be_id; + + ret = create_sdw_dailink(card, sof_dais, dai_links, ¤t_be_id); + if (ret) + return ret; + + /* Update the be_id to match the highest ID used for SDW link */ + if (*be_id < current_be_id) + *be_id = current_be_id; + + sof_dais++; + } + + return 0; +} + static int create_ssp_dailinks(struct snd_soc_card *card, struct snd_soc_dai_link **dai_links, int *be_id, struct sof_sdw_codec_info *ssp_info, @@ -1692,7 +1720,7 @@ static int sof_card_dai_links_create(struct snd_soc_card *card) int num_ends = 0; struct snd_soc_dai_link *dai_links; int num_links; - int i, be_id = 0; + int be_id = 0; int hdmi_num; unsigned long ssp_mask; int ret; @@ -1774,28 +1802,12 @@ static int sof_card_dai_links_create(struct snd_soc_card *card) card->num_links = num_links; /* SDW */ - if (!sdw_be_num) - goto SSP; - - for (i = 0; i < SDW_MAX_LINKS; i++) - ctx->sdw_pin_index[i] = SDW_INTEL_BIDIR_PDI_BASE; - - /* generate DAI links by each sdw link */ - while (sof_dais->initialised) { - int current_be_id; - - ret = create_sdw_dailink(card, sof_dais, &dai_links, ¤t_be_id); + if (sdw_be_num) { + ret = create_sdw_dailinks(card, &dai_links, &be_id, sof_dais); if (ret) goto err_end; - - /* Update the be_id to match the highest ID used for SDW link */ - if (be_id < current_be_id) - be_id = current_be_id; - - sof_dais++; } -SSP: /* SSP */ if (ssp_num) { ret = create_ssp_dailinks(card, &dai_links, &be_id, -- cgit v1.2.3 From bee2fe44679f1e6a5332d7f78587ccca4109919f Mon Sep 17 00:00:00 2001 From: Bard Liao Date: Tue, 26 Mar 2024 11:04:19 -0500 Subject: ASoC: Intel: sof_sdw: use generic rtd_init function for Realtek SDW DMICs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The only thing that the rt_xxx_rtd_init() functions do is to set card->components. And we can set card->components with name_prefix as rt712_sdca_dmic_rtd_init() does. And sof_sdw_rtd_init() will always select the first dai with the given dai->name from codec_info_list[]. Unfortunately, we have different codecs with the same dai name. For example, dai name of rt715 and rt715-sdca are both "rt715-aif2". Using a generic rtd_init allow sof_sdw_rtd_init() run the rtd_init() callback from a similar codec dai. Fixes: 8266c73126b7 ("ASoC: Intel: sof_sdw: add common sdw dai link init") Reviewed-by: Chao Song Reviewed-by: Péter Ujfalusi Signed-off-by: Bard Liao Signed-off-by: Pierre-Louis Bossart Link: https://msgid.link/r/20240326160429.13560-25-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/intel/boards/Makefile | 1 + sound/soc/intel/boards/sof_sdw.c | 12 ++++---- sound/soc/intel/boards/sof_sdw_common.h | 1 + sound/soc/intel/boards/sof_sdw_rt_dmic.c | 52 ++++++++++++++++++++++++++++++++ 4 files changed, 60 insertions(+), 6 deletions(-) create mode 100644 sound/soc/intel/boards/sof_sdw_rt_dmic.c diff --git a/sound/soc/intel/boards/Makefile b/sound/soc/intel/boards/Makefile index bbf796a5f7ba..08cfd4baecdd 100644 --- a/sound/soc/intel/boards/Makefile +++ b/sound/soc/intel/boards/Makefile @@ -42,6 +42,7 @@ snd-soc-sof-sdw-objs += sof_sdw.o \ sof_sdw_rt711.o sof_sdw_rt_sdca_jack_common.o \ sof_sdw_rt712_sdca.o sof_sdw_rt715.o \ sof_sdw_rt715_sdca.o sof_sdw_rt722_sdca.o \ + sof_sdw_rt_dmic.o \ sof_sdw_cs42l42.o sof_sdw_cs42l43.o \ sof_sdw_cs_amp.o \ sof_sdw_dmic.o \ diff --git a/sound/soc/intel/boards/sof_sdw.c b/sound/soc/intel/boards/sof_sdw.c index 3e6a758c98ab..0e376cb0ce0b 100644 --- a/sound/soc/intel/boards/sof_sdw.c +++ b/sound/soc/intel/boards/sof_sdw.c @@ -749,7 +749,7 @@ static struct sof_sdw_codec_info codec_info_list[] = { .dai_name = "rt712-sdca-dmic-aif1", .dai_type = SOF_SDW_DAI_TYPE_MIC, .dailink = {SDW_UNUSED_DAI_ID, SDW_DMIC_DAI_ID}, - .rtd_init = rt712_sdca_dmic_rtd_init, + .rtd_init = rt_dmic_rtd_init, }, }, .dai_num = 1, @@ -779,7 +779,7 @@ static struct sof_sdw_codec_info codec_info_list[] = { .dai_name = "rt712-sdca-dmic-aif1", .dai_type = SOF_SDW_DAI_TYPE_MIC, .dailink = {SDW_UNUSED_DAI_ID, SDW_DMIC_DAI_ID}, - .rtd_init = rt712_sdca_dmic_rtd_init, + .rtd_init = rt_dmic_rtd_init, }, }, .dai_num = 1, @@ -841,7 +841,7 @@ static struct sof_sdw_codec_info codec_info_list[] = { .dai_name = "rt715-aif2", .dai_type = SOF_SDW_DAI_TYPE_MIC, .dailink = {SDW_UNUSED_DAI_ID, SDW_DMIC_DAI_ID}, - .rtd_init = rt715_sdca_rtd_init, + .rtd_init = rt_dmic_rtd_init, }, }, .dai_num = 1, @@ -856,7 +856,7 @@ static struct sof_sdw_codec_info codec_info_list[] = { .dai_name = "rt715-aif2", .dai_type = SOF_SDW_DAI_TYPE_MIC, .dailink = {SDW_UNUSED_DAI_ID, SDW_DMIC_DAI_ID}, - .rtd_init = rt715_sdca_rtd_init, + .rtd_init = rt_dmic_rtd_init, }, }, .dai_num = 1, @@ -871,7 +871,7 @@ static struct sof_sdw_codec_info codec_info_list[] = { .dai_name = "rt715-aif2", .dai_type = SOF_SDW_DAI_TYPE_MIC, .dailink = {SDW_UNUSED_DAI_ID, SDW_DMIC_DAI_ID}, - .rtd_init = rt715_rtd_init, + .rtd_init = rt_dmic_rtd_init, }, }, .dai_num = 1, @@ -886,7 +886,7 @@ static struct sof_sdw_codec_info codec_info_list[] = { .dai_name = "rt715-aif2", .dai_type = SOF_SDW_DAI_TYPE_MIC, .dailink = {SDW_UNUSED_DAI_ID, SDW_DMIC_DAI_ID}, - .rtd_init = rt715_rtd_init, + .rtd_init = rt_dmic_rtd_init, }, }, .dai_num = 1, diff --git a/sound/soc/intel/boards/sof_sdw_common.h b/sound/soc/intel/boards/sof_sdw_common.h index e21ef79126b2..decaed97fa74 100644 --- a/sound/soc/intel/boards/sof_sdw_common.h +++ b/sound/soc/intel/boards/sof_sdw_common.h @@ -197,6 +197,7 @@ int rt712_sdca_dmic_rtd_init(struct snd_soc_pcm_runtime *rtd); int rt712_spk_rtd_init(struct snd_soc_pcm_runtime *rtd); int rt715_rtd_init(struct snd_soc_pcm_runtime *rtd); int rt715_sdca_rtd_init(struct snd_soc_pcm_runtime *rtd); +int rt_dmic_rtd_init(struct snd_soc_pcm_runtime *rtd); int rt_amp_spk_rtd_init(struct snd_soc_pcm_runtime *rtd); int rt_sdca_jack_rtd_init(struct snd_soc_pcm_runtime *rtd); diff --git a/sound/soc/intel/boards/sof_sdw_rt_dmic.c b/sound/soc/intel/boards/sof_sdw_rt_dmic.c new file mode 100644 index 000000000000..9091f5b5c648 --- /dev/null +++ b/sound/soc/intel/boards/sof_sdw_rt_dmic.c @@ -0,0 +1,52 @@ +// SPDX-License-Identifier: GPL-2.0-only +// Copyright (c) 2024 Intel Corporation + +/* + * sof_sdw_rt_dmic - Helpers to handle Realtek SDW DMIC from generic machine driver + */ + +#include +#include +#include +#include +#include "sof_board_helpers.h" +#include "sof_sdw_common.h" + +static const char * const dmics[] = { + "rt715", + "rt712-sdca-dmic", +}; + +int rt_dmic_rtd_init(struct snd_soc_pcm_runtime *rtd) +{ + struct snd_soc_card *card = rtd->card; + struct snd_soc_component *component; + struct snd_soc_dai *codec_dai; + char *mic_name; + + codec_dai = get_codec_dai_by_name(rtd, dmics, ARRAY_SIZE(dmics)); + if (!codec_dai) + return -EINVAL; + + component = codec_dai->component; + + /* + * rt715-sdca (aka rt714) is a special case that uses different name in card->components + * and component->name_prefix. + */ + if (!strcmp(component->name_prefix, "rt714")) + mic_name = devm_kasprintf(card->dev, GFP_KERNEL, "rt715-sdca"); + else + mic_name = devm_kasprintf(card->dev, GFP_KERNEL, "%s", component->name_prefix); + + card->components = devm_kasprintf(card->dev, GFP_KERNEL, + "%s mic:%s", card->components, + mic_name); + if (!card->components) + return -ENOMEM; + + dev_dbg(card->dev, "card->components: %s\n", card->components); + + return 0; +} +MODULE_IMPORT_NS(SND_SOC_INTEL_SOF_BOARD_HELPERS); -- cgit v1.2.3 From 45bbc14fb94698b43636ec18d0df2440934139e7 Mon Sep 17 00:00:00 2001 From: Bard Liao Date: Tue, 26 Mar 2024 11:04:20 -0500 Subject: ASoC: Intel: sof_sdw: remove unused rt dmic rtd_init MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Some Realtek SDW DMIC codecs use the generic rt_dmic_rtd_init callback now. Remove unused rtd_init callbacks. Reviewed-by: Chao Song Reviewed-by: Péter Ujfalusi Signed-off-by: Bard Liao Signed-off-by: Pierre-Louis Bossart Link: https://msgid.link/r/20240326160429.13560-26-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/intel/boards/Makefile | 3 +-- sound/soc/intel/boards/sof_sdw_common.h | 3 --- sound/soc/intel/boards/sof_sdw_rt712_sdca.c | 24 ------------------------ sound/soc/intel/boards/sof_sdw_rt715.c | 26 -------------------------- sound/soc/intel/boards/sof_sdw_rt715_sdca.c | 26 -------------------------- 5 files changed, 1 insertion(+), 81 deletions(-) delete mode 100644 sound/soc/intel/boards/sof_sdw_rt715.c delete mode 100644 sound/soc/intel/boards/sof_sdw_rt715_sdca.c diff --git a/sound/soc/intel/boards/Makefile b/sound/soc/intel/boards/Makefile index 08cfd4baecdd..8f711be46c43 100644 --- a/sound/soc/intel/boards/Makefile +++ b/sound/soc/intel/boards/Makefile @@ -40,8 +40,7 @@ snd-soc-sof-sdw-objs += sof_sdw.o \ sof_sdw_maxim.o sof_sdw_rt_amp.o \ sof_sdw_rt5682.o sof_sdw_rt700.o \ sof_sdw_rt711.o sof_sdw_rt_sdca_jack_common.o \ - sof_sdw_rt712_sdca.o sof_sdw_rt715.o \ - sof_sdw_rt715_sdca.o sof_sdw_rt722_sdca.o \ + sof_sdw_rt712_sdca.o sof_sdw_rt722_sdca.o \ sof_sdw_rt_dmic.o \ sof_sdw_cs42l42.o sof_sdw_cs42l43.o \ sof_sdw_cs_amp.o \ diff --git a/sound/soc/intel/boards/sof_sdw_common.h b/sound/soc/intel/boards/sof_sdw_common.h index decaed97fa74..84715d9ca942 100644 --- a/sound/soc/intel/boards/sof_sdw_common.h +++ b/sound/soc/intel/boards/sof_sdw_common.h @@ -193,10 +193,7 @@ int maxim_spk_rtd_init(struct snd_soc_pcm_runtime *rtd); int rt5682_rtd_init(struct snd_soc_pcm_runtime *rtd); int rt700_rtd_init(struct snd_soc_pcm_runtime *rtd); int rt711_rtd_init(struct snd_soc_pcm_runtime *rtd); -int rt712_sdca_dmic_rtd_init(struct snd_soc_pcm_runtime *rtd); int rt712_spk_rtd_init(struct snd_soc_pcm_runtime *rtd); -int rt715_rtd_init(struct snd_soc_pcm_runtime *rtd); -int rt715_sdca_rtd_init(struct snd_soc_pcm_runtime *rtd); int rt_dmic_rtd_init(struct snd_soc_pcm_runtime *rtd); int rt_amp_spk_rtd_init(struct snd_soc_pcm_runtime *rtd); int rt_sdca_jack_rtd_init(struct snd_soc_pcm_runtime *rtd); diff --git a/sound/soc/intel/boards/sof_sdw_rt712_sdca.c b/sound/soc/intel/boards/sof_sdw_rt712_sdca.c index 9c898c7286af..0c4cd4cdbd45 100644 --- a/sound/soc/intel/boards/sof_sdw_rt712_sdca.c +++ b/sound/soc/intel/boards/sof_sdw_rt712_sdca.c @@ -66,27 +66,3 @@ int rt712_spk_rtd_init(struct snd_soc_pcm_runtime *rtd) return ret; } -static const char * const dmics[] = { - "rt712-sdca-dmic" -}; - -int rt712_sdca_dmic_rtd_init(struct snd_soc_pcm_runtime *rtd) -{ - struct snd_soc_card *card = rtd->card; - struct snd_soc_dai *codec_dai; - struct snd_soc_component *component; - - codec_dai = get_codec_dai_by_name(rtd, dmics, ARRAY_SIZE(dmics)); - if (!codec_dai) - return -EINVAL; - - component = codec_dai->component; - card->components = devm_kasprintf(card->dev, GFP_KERNEL, - "%s mic:%s", - card->components, component->name_prefix); - if (!card->components) - return -ENOMEM; - - return 0; -} -MODULE_IMPORT_NS(SND_SOC_INTEL_SOF_BOARD_HELPERS); diff --git a/sound/soc/intel/boards/sof_sdw_rt715.c b/sound/soc/intel/boards/sof_sdw_rt715.c deleted file mode 100644 index b5a886cd595d..000000000000 --- a/sound/soc/intel/boards/sof_sdw_rt715.c +++ /dev/null @@ -1,26 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -// Copyright (c) 2020 Intel Corporation - -/* - * sof_sdw_rt715 - Helpers to handle RT715 from generic machine driver - */ - -#include -#include -#include -#include -#include "sof_sdw_common.h" - -int rt715_rtd_init(struct snd_soc_pcm_runtime *rtd) -{ - struct snd_soc_card *card = rtd->card; - - card->components = devm_kasprintf(card->dev, GFP_KERNEL, - "%s mic:rt715", - card->components); - if (!card->components) - return -ENOMEM; - - return 0; -} - diff --git a/sound/soc/intel/boards/sof_sdw_rt715_sdca.c b/sound/soc/intel/boards/sof_sdw_rt715_sdca.c deleted file mode 100644 index 4b37a8a6dd2e..000000000000 --- a/sound/soc/intel/boards/sof_sdw_rt715_sdca.c +++ /dev/null @@ -1,26 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -// Copyright (c) 2020 Intel Corporation - -/* - * sof_sdw_rt715_sdca - Helpers to handle RT715-SDCA from generic machine driver - */ - -#include -#include -#include -#include -#include "sof_sdw_common.h" - -int rt715_sdca_rtd_init(struct snd_soc_pcm_runtime *rtd) -{ - struct snd_soc_card *card = rtd->card; - - card->components = devm_kasprintf(card->dev, GFP_KERNEL, - "%s mic:rt715-sdca", - card->components); - if (!card->components) - return -ENOMEM; - - return 0; -} - -- cgit v1.2.3 From 266c9b27cb0a2c11de5956ee4bd7e1266d0baa36 Mon Sep 17 00:00:00 2001 From: Bard Liao Date: Tue, 26 Mar 2024 11:04:21 -0500 Subject: ASoC: Intel: sof_sdw_rt722_sdca: set rtd_init in codec_info_list[] MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add rt722 into rt_sdca_jack_rtd_init() supported list, and set rtd_init callback directly in codec_info_list[]. No need to use a init callback to set the rtd_init callback. Besides, sof_sdw_rt_sdca_jack_init() doesn't set .rtd_init anymore. Reviewed-by: Chao Song Reviewed-by: Péter Ujfalusi Signed-off-by: Bard Liao Signed-off-by: Pierre-Louis Bossart Link: https://msgid.link/r/20240326160429.13560-27-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/intel/boards/sof_sdw.c | 5 +++-- sound/soc/intel/boards/sof_sdw_common.h | 14 ++---------- sound/soc/intel/boards/sof_sdw_rt722_sdca.c | 26 ++-------------------- .../soc/intel/boards/sof_sdw_rt_sdca_jack_common.c | 2 +- 4 files changed, 8 insertions(+), 39 deletions(-) diff --git a/sound/soc/intel/boards/sof_sdw.c b/sound/soc/intel/boards/sof_sdw.c index 0e376cb0ce0b..bb8429a83467 100644 --- a/sound/soc/intel/boards/sof_sdw.c +++ b/sound/soc/intel/boards/sof_sdw.c @@ -902,6 +902,7 @@ static struct sof_sdw_codec_info codec_info_list[] = { .dailink = {SDW_JACK_OUT_DAI_ID, SDW_JACK_IN_DAI_ID}, .init = sof_sdw_rt_sdca_jack_init, .exit = sof_sdw_rt_sdca_jack_exit, + .rtd_init = rt_sdca_jack_rtd_init, }, { .direction = {true, false}, @@ -909,14 +910,14 @@ static struct sof_sdw_codec_info codec_info_list[] = { .dai_type = SOF_SDW_DAI_TYPE_AMP, /* No feedback capability is provided by rt722-sdca codec driver*/ .dailink = {SDW_AMP_OUT_DAI_ID, SDW_UNUSED_DAI_ID}, - .init = sof_sdw_rt722_spk_init, + .rtd_init = rt722_spk_rtd_init, }, { .direction = {false, true}, .dai_name = "rt722-sdca-aif3", .dai_type = SOF_SDW_DAI_TYPE_MIC, .dailink = {SDW_UNUSED_DAI_ID, SDW_DMIC_DAI_ID}, - .init = sof_sdw_rt722_sdca_dmic_init, + .rtd_init = rt722_sdca_dmic_rtd_init, }, }, .dai_num = 3, diff --git a/sound/soc/intel/boards/sof_sdw_common.h b/sound/soc/intel/boards/sof_sdw_common.h index 84715d9ca942..315b2a298195 100644 --- a/sound/soc/intel/boards/sof_sdw_common.h +++ b/sound/soc/intel/boards/sof_sdw_common.h @@ -157,18 +157,6 @@ int sof_sdw_rt_amp_init(struct snd_soc_card *card, bool playback); int sof_sdw_rt_amp_exit(struct snd_soc_card *card, struct snd_soc_dai_link *dai_link); -/* RT722-SDCA support */ -int sof_sdw_rt722_spk_init(struct snd_soc_card *card, - const struct snd_soc_acpi_link_adr *link, - struct snd_soc_dai_link *dai_links, - struct sof_sdw_codec_info *info, - bool playback); -int sof_sdw_rt722_sdca_dmic_init(struct snd_soc_card *card, - const struct snd_soc_acpi_link_adr *link, - struct snd_soc_dai_link *dai_links, - struct sof_sdw_codec_info *info, - bool playback); - /* MAXIM codec support */ int sof_sdw_maxim_init(struct snd_soc_card *card, const struct snd_soc_acpi_link_adr *link, @@ -194,6 +182,8 @@ int rt5682_rtd_init(struct snd_soc_pcm_runtime *rtd); int rt700_rtd_init(struct snd_soc_pcm_runtime *rtd); int rt711_rtd_init(struct snd_soc_pcm_runtime *rtd); int rt712_spk_rtd_init(struct snd_soc_pcm_runtime *rtd); +int rt722_spk_rtd_init(struct snd_soc_pcm_runtime *rtd); +int rt722_sdca_dmic_rtd_init(struct snd_soc_pcm_runtime *rtd); int rt_dmic_rtd_init(struct snd_soc_pcm_runtime *rtd); int rt_amp_spk_rtd_init(struct snd_soc_pcm_runtime *rtd); int rt_sdca_jack_rtd_init(struct snd_soc_pcm_runtime *rtd); diff --git a/sound/soc/intel/boards/sof_sdw_rt722_sdca.c b/sound/soc/intel/boards/sof_sdw_rt722_sdca.c index fe3a2bff95bc..4947d16c70db 100644 --- a/sound/soc/intel/boards/sof_sdw_rt722_sdca.c +++ b/sound/soc/intel/boards/sof_sdw_rt722_sdca.c @@ -27,7 +27,7 @@ static const struct snd_kcontrol_new rt722_spk_controls[] = { SOC_DAPM_PIN_SWITCH("Speaker"), }; -static int rt722_spk_init(struct snd_soc_pcm_runtime *rtd) +int rt722_spk_rtd_init(struct snd_soc_pcm_runtime *rtd) { struct snd_soc_card *card = rtd->card; int ret; @@ -59,18 +59,7 @@ static int rt722_spk_init(struct snd_soc_pcm_runtime *rtd) return ret; } -int sof_sdw_rt722_spk_init(struct snd_soc_card *card, - const struct snd_soc_acpi_link_adr *link, - struct snd_soc_dai_link *dai_links, - struct sof_sdw_codec_info *info, - bool playback) -{ - dai_links->init = rt722_spk_init; - - return 0; -} - -static int rt722_sdca_dmic_rtd_init(struct snd_soc_pcm_runtime *rtd) +int rt722_sdca_dmic_rtd_init(struct snd_soc_pcm_runtime *rtd) { struct snd_soc_card *card = rtd->card; struct snd_soc_dai *codec_dai = snd_soc_rtd_to_codec(rtd, 0); @@ -84,14 +73,3 @@ static int rt722_sdca_dmic_rtd_init(struct snd_soc_pcm_runtime *rtd) return 0; } - -int sof_sdw_rt722_sdca_dmic_init(struct snd_soc_card *card, - const struct snd_soc_acpi_link_adr *link, - struct snd_soc_dai_link *dai_links, - struct sof_sdw_codec_info *info, - bool playback) -{ - dai_links->init = rt722_sdca_dmic_rtd_init; - - return 0; -} diff --git a/sound/soc/intel/boards/sof_sdw_rt_sdca_jack_common.c b/sound/soc/intel/boards/sof_sdw_rt_sdca_jack_common.c index fe59a144efef..006771485486 100644 --- a/sound/soc/intel/boards/sof_sdw_rt_sdca_jack_common.c +++ b/sound/soc/intel/boards/sof_sdw_rt_sdca_jack_common.c @@ -85,7 +85,7 @@ static struct snd_soc_jack_pin rt_sdca_jack_pins[] = { }; static const char * const jack_codecs[] = { - "rt711", "rt712", "rt713" + "rt711", "rt712", "rt713", "rt722" }; int rt_sdca_jack_rtd_init(struct snd_soc_pcm_runtime *rtd) -- cgit v1.2.3 From df19c6cd0fd0418b779f9c627b159d7ab77bff71 Mon Sep 17 00:00:00 2001 From: Bard Liao Date: Tue, 26 Mar 2024 11:04:22 -0500 Subject: ASoC: Intel: sof_sdw_rt722_sdca: use rt_dmic_rtd_init MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit rt_dmic_rtd_init() can be used for rt722 dmic, too. Reviewed-by: Chao Song Reviewed-by: Péter Ujfalusi Signed-off-by: Bard Liao Signed-off-by: Pierre-Louis Bossart Link: https://msgid.link/r/20240326160429.13560-28-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/intel/boards/sof_sdw.c | 2 +- sound/soc/intel/boards/sof_sdw_common.h | 1 - sound/soc/intel/boards/sof_sdw_rt722_sdca.c | 14 -------------- sound/soc/intel/boards/sof_sdw_rt_dmic.c | 1 + 4 files changed, 2 insertions(+), 16 deletions(-) diff --git a/sound/soc/intel/boards/sof_sdw.c b/sound/soc/intel/boards/sof_sdw.c index bb8429a83467..3874da8d7fe4 100644 --- a/sound/soc/intel/boards/sof_sdw.c +++ b/sound/soc/intel/boards/sof_sdw.c @@ -917,7 +917,7 @@ static struct sof_sdw_codec_info codec_info_list[] = { .dai_name = "rt722-sdca-aif3", .dai_type = SOF_SDW_DAI_TYPE_MIC, .dailink = {SDW_UNUSED_DAI_ID, SDW_DMIC_DAI_ID}, - .rtd_init = rt722_sdca_dmic_rtd_init, + .rtd_init = rt_dmic_rtd_init, }, }, .dai_num = 3, diff --git a/sound/soc/intel/boards/sof_sdw_common.h b/sound/soc/intel/boards/sof_sdw_common.h index 315b2a298195..2132d3fc42f8 100644 --- a/sound/soc/intel/boards/sof_sdw_common.h +++ b/sound/soc/intel/boards/sof_sdw_common.h @@ -183,7 +183,6 @@ int rt700_rtd_init(struct snd_soc_pcm_runtime *rtd); int rt711_rtd_init(struct snd_soc_pcm_runtime *rtd); int rt712_spk_rtd_init(struct snd_soc_pcm_runtime *rtd); int rt722_spk_rtd_init(struct snd_soc_pcm_runtime *rtd); -int rt722_sdca_dmic_rtd_init(struct snd_soc_pcm_runtime *rtd); int rt_dmic_rtd_init(struct snd_soc_pcm_runtime *rtd); int rt_amp_spk_rtd_init(struct snd_soc_pcm_runtime *rtd); int rt_sdca_jack_rtd_init(struct snd_soc_pcm_runtime *rtd); diff --git a/sound/soc/intel/boards/sof_sdw_rt722_sdca.c b/sound/soc/intel/boards/sof_sdw_rt722_sdca.c index 4947d16c70db..e5c2a36e400b 100644 --- a/sound/soc/intel/boards/sof_sdw_rt722_sdca.c +++ b/sound/soc/intel/boards/sof_sdw_rt722_sdca.c @@ -59,17 +59,3 @@ int rt722_spk_rtd_init(struct snd_soc_pcm_runtime *rtd) return ret; } -int rt722_sdca_dmic_rtd_init(struct snd_soc_pcm_runtime *rtd) -{ - struct snd_soc_card *card = rtd->card; - struct snd_soc_dai *codec_dai = snd_soc_rtd_to_codec(rtd, 0); - struct snd_soc_component *component = codec_dai->component; - - card->components = devm_kasprintf(card->dev, GFP_KERNEL, - "%s mic:%s", - card->components, component->name_prefix); - if (!card->components) - return -ENOMEM; - - return 0; -} diff --git a/sound/soc/intel/boards/sof_sdw_rt_dmic.c b/sound/soc/intel/boards/sof_sdw_rt_dmic.c index 9091f5b5c648..5aec8422656c 100644 --- a/sound/soc/intel/boards/sof_sdw_rt_dmic.c +++ b/sound/soc/intel/boards/sof_sdw_rt_dmic.c @@ -15,6 +15,7 @@ static const char * const dmics[] = { "rt715", "rt712-sdca-dmic", + "rt722-sdca", }; int rt_dmic_rtd_init(struct snd_soc_pcm_runtime *rtd) -- cgit v1.2.3 From 13112a34d83e0b3c925ff9818e0819ad2fe97e42 Mon Sep 17 00:00:00 2001 From: Bard Liao Date: Tue, 26 Mar 2024 11:04:23 -0500 Subject: ASoC: rt715-sdca: rename dai name with rt715-sdca prefix MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The dai name are the same as rt715 codec. Rename them with rt715-sdca prefix allow machine driver to distinguish rt715 and rt715-sdca from dai name. Reviewed-by: Chao Song Reviewed-by: Péter Ujfalusi Signed-off-by: Bard Liao Signed-off-by: Pierre-Louis Bossart Link: https://msgid.link/r/20240326160429.13560-29-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/codecs/rt715-sdca.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/soc/codecs/rt715-sdca.c b/sound/soc/codecs/rt715-sdca.c index 4533eedd7e18..cee46db79d73 100644 --- a/sound/soc/codecs/rt715-sdca.c +++ b/sound/soc/codecs/rt715-sdca.c @@ -933,7 +933,7 @@ static const struct snd_soc_dai_ops rt715_sdca_ops = { static struct snd_soc_dai_driver rt715_sdca_dai[] = { { - .name = "rt715-aif1", + .name = "rt715-sdca-aif1", .id = RT715_AIF1, .capture = { .stream_name = "DP6 Capture", @@ -945,7 +945,7 @@ static struct snd_soc_dai_driver rt715_sdca_dai[] = { .ops = &rt715_sdca_ops, }, { - .name = "rt715-aif2", + .name = "rt715-sdca-aif2", .id = RT715_AIF2, .capture = { .stream_name = "DP4 Capture", -- cgit v1.2.3 From a2e620e4ac87c80e0987bd74c0c345b0da02b33e Mon Sep 17 00:00:00 2001 From: Bard Liao Date: Tue, 26 Mar 2024 11:04:24 -0500 Subject: ASoC: Intel: sof_sdw: change rt715-sdca dai name MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit As rt715-sdca dai name has been changed in codec driver, we should change it in machine driver, too. Changing the dai name in codec_info_list[] also help sof_sdw_rtd_init() to run .rtd_init() from the same codec. Reviewed-by: Chao Song Reviewed-by: Péter Ujfalusi Signed-off-by: Bard Liao Signed-off-by: Pierre-Louis Bossart Link: https://msgid.link/r/20240326160429.13560-30-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/intel/boards/sof_sdw.c | 4 ++-- sound/soc/intel/boards/sof_sdw_rt_dmic.c | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/sound/soc/intel/boards/sof_sdw.c b/sound/soc/intel/boards/sof_sdw.c index 3874da8d7fe4..1816ec5dd580 100644 --- a/sound/soc/intel/boards/sof_sdw.c +++ b/sound/soc/intel/boards/sof_sdw.c @@ -838,7 +838,7 @@ static struct sof_sdw_codec_info codec_info_list[] = { .dais = { { .direction = {false, true}, - .dai_name = "rt715-aif2", + .dai_name = "rt715-sdca-aif2", .dai_type = SOF_SDW_DAI_TYPE_MIC, .dailink = {SDW_UNUSED_DAI_ID, SDW_DMIC_DAI_ID}, .rtd_init = rt_dmic_rtd_init, @@ -853,7 +853,7 @@ static struct sof_sdw_codec_info codec_info_list[] = { .dais = { { .direction = {false, true}, - .dai_name = "rt715-aif2", + .dai_name = "rt715-sdca-aif2", .dai_type = SOF_SDW_DAI_TYPE_MIC, .dailink = {SDW_UNUSED_DAI_ID, SDW_DMIC_DAI_ID}, .rtd_init = rt_dmic_rtd_init, diff --git a/sound/soc/intel/boards/sof_sdw_rt_dmic.c b/sound/soc/intel/boards/sof_sdw_rt_dmic.c index 5aec8422656c..2f7ed9b31e79 100644 --- a/sound/soc/intel/boards/sof_sdw_rt_dmic.c +++ b/sound/soc/intel/boards/sof_sdw_rt_dmic.c @@ -14,6 +14,7 @@ static const char * const dmics[] = { "rt715", + "rt715-sdca", "rt712-sdca-dmic", "rt722-sdca", }; -- cgit v1.2.3 From aac976aa3c6a37175eec9d3eb912cd92aa8c3a0b Mon Sep 17 00:00:00 2001 From: Bard Liao Date: Tue, 26 Mar 2024 11:04:25 -0500 Subject: ASoC: Intel: change cs35l56 name_prefix To use sequential amp numbers. I,e, AMP1, AMP2, AMP3, AMP4 Reviewed-by: Chao Song Signed-off-by: Bard Liao Signed-off-by: Pierre-Louis Bossart Link: https://msgid.link/r/20240326160429.13560-31-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/intel/common/soc-acpi-intel-mtl-match.c | 4 ++-- sound/soc/intel/common/soc-acpi-intel-tgl-match.c | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/sound/soc/intel/common/soc-acpi-intel-mtl-match.c b/sound/soc/intel/common/soc-acpi-intel-mtl-match.c index e06efc5b1457..7e53266d831d 100644 --- a/sound/soc/intel/common/soc-acpi-intel-mtl-match.c +++ b/sound/soc/intel/common/soc-acpi-intel-mtl-match.c @@ -373,13 +373,13 @@ static const struct snd_soc_acpi_adr_device cs35l56_1_adr[] = { .adr = 0x00013701FA355601ull, .num_endpoints = 1, .endpoints = &spk_r_endpoint, - .name_prefix = "AMP8" + .name_prefix = "AMP3" }, { .adr = 0x00013601FA355601ull, .num_endpoints = 1, .endpoints = &spk_3_endpoint, - .name_prefix = "AMP7" + .name_prefix = "AMP4" } }; diff --git a/sound/soc/intel/common/soc-acpi-intel-tgl-match.c b/sound/soc/intel/common/soc-acpi-intel-tgl-match.c index 007f1ac2327a..0cef3d788a5b 100644 --- a/sound/soc/intel/common/soc-acpi-intel-tgl-match.c +++ b/sound/soc/intel/common/soc-acpi-intel-tgl-match.c @@ -464,13 +464,13 @@ static const struct snd_soc_acpi_adr_device cs35l56_1_adr[] = { .adr = 0x00013701FA355601ull, .num_endpoints = 1, .endpoints = &spk_l_endpoint, - .name_prefix = "AMP8" + .name_prefix = "AMP3" }, { .adr = 0x00013601FA355601ull, .num_endpoints = 1, .endpoints = &spk_2_endpoint, - .name_prefix = "AMP7" + .name_prefix = "AMP4" } }; -- cgit v1.2.3 From 84aa440e02f3b44e927e274b9946b4c79608de43 Mon Sep 17 00:00:00 2001 From: Charles Keepax Date: Tue, 26 Mar 2024 11:04:26 -0500 Subject: ASoC: Intel: sof_sdw: Don't pass acpi_link_adr to init functions There is no need to pass the snd_soc_acpi_link_adr structure to the init functions, it conveys no specific information about the codec. Remove this parameter from the callbacks Reviewed-by: Bard Liao Signed-off-by: Charles Keepax Signed-off-by: Pierre-Louis Bossart Link: https://msgid.link/r/20240326160429.13560-32-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/intel/boards/sof_sdw.c | 7 ++----- sound/soc/intel/boards/sof_sdw_common.h | 6 ------ sound/soc/intel/boards/sof_sdw_cs_amp.c | 1 - sound/soc/intel/boards/sof_sdw_maxim.c | 1 - sound/soc/intel/boards/sof_sdw_rt711.c | 1 - sound/soc/intel/boards/sof_sdw_rt_amp.c | 1 - sound/soc/intel/boards/sof_sdw_rt_sdca_jack_common.c | 1 - 7 files changed, 2 insertions(+), 16 deletions(-) diff --git a/sound/soc/intel/boards/sof_sdw.c b/sound/soc/intel/boards/sof_sdw.c index 1816ec5dd580..f3167e3498e0 100644 --- a/sound/soc/intel/boards/sof_sdw.c +++ b/sound/soc/intel/boards/sof_sdw.c @@ -1273,7 +1273,6 @@ struct sof_sdw_endpoint { u32 link_mask; const char *codec_name; - const struct snd_soc_acpi_link_adr *adr_link; struct sof_sdw_codec_info *codec_info; const struct sof_sdw_dai_info *dai_info; }; @@ -1425,7 +1424,6 @@ static int parse_sdw_endpoints(struct snd_soc_card *card, sof_end->link_mask = adr_link->mask; sof_end->codec_name = codec_name; - sof_end->adr_link = adr_link; sof_end->codec_info = codec_info; sof_end->dai_info = dai_info; sof_end++; @@ -1548,8 +1546,7 @@ static int create_sdw_dailink(struct snd_soc_card *card, list_for_each_entry(sof_end, &sof_dai->endpoints, list) { if (sof_end->dai_info->init) - sof_end->dai_info->init(card, sof_end->adr_link, - *dai_links, + sof_end->dai_info->init(card, *dai_links, sof_end->codec_info, playback); } @@ -1612,7 +1609,7 @@ static int create_ssp_dailinks(struct snd_soc_card *card, if (ret) return ret; - ret = ssp_info->dais[0].init(card, NULL, *dai_links, ssp_info, 0); + ret = ssp_info->dais[0].init(card, *dai_links, ssp_info, 0); if (ret < 0) return ret; diff --git a/sound/soc/intel/boards/sof_sdw_common.h b/sound/soc/intel/boards/sof_sdw_common.h index 2132d3fc42f8..8d8c2ca68a7f 100644 --- a/sound/soc/intel/boards/sof_sdw_common.h +++ b/sound/soc/intel/boards/sof_sdw_common.h @@ -74,7 +74,6 @@ struct sof_sdw_dai_info { const int dai_type; const int dailink[2]; /* dailink id for each direction */ int (*init)(struct snd_soc_card *card, - const struct snd_soc_acpi_link_adr *link, struct snd_soc_dai_link *dai_links, struct sof_sdw_codec_info *info, bool playback); @@ -132,7 +131,6 @@ int sof_sdw_dmic_init(struct snd_soc_pcm_runtime *rtd); /* RT711 support */ int sof_sdw_rt711_init(struct snd_soc_card *card, - const struct snd_soc_acpi_link_adr *link, struct snd_soc_dai_link *dai_links, struct sof_sdw_codec_info *info, bool playback); @@ -140,7 +138,6 @@ int sof_sdw_rt711_exit(struct snd_soc_card *card, struct snd_soc_dai_link *dai_l /* RT711-SDCA support */ int sof_sdw_rt_sdca_jack_init(struct snd_soc_card *card, - const struct snd_soc_acpi_link_adr *link, struct snd_soc_dai_link *dai_links, struct sof_sdw_codec_info *info, bool playback); @@ -151,7 +148,6 @@ extern struct snd_soc_ops sof_sdw_rt1308_i2s_ops; /* generic amp support */ int sof_sdw_rt_amp_init(struct snd_soc_card *card, - const struct snd_soc_acpi_link_adr *link, struct snd_soc_dai_link *dai_links, struct sof_sdw_codec_info *info, bool playback); @@ -159,14 +155,12 @@ int sof_sdw_rt_amp_exit(struct snd_soc_card *card, struct snd_soc_dai_link *dai_ /* MAXIM codec support */ int sof_sdw_maxim_init(struct snd_soc_card *card, - const struct snd_soc_acpi_link_adr *link, struct snd_soc_dai_link *dai_links, struct sof_sdw_codec_info *info, bool playback); /* CS AMP support */ int sof_sdw_cs_amp_init(struct snd_soc_card *card, - const struct snd_soc_acpi_link_adr *link, struct snd_soc_dai_link *dai_links, struct sof_sdw_codec_info *info, bool playback); diff --git a/sound/soc/intel/boards/sof_sdw_cs_amp.c b/sound/soc/intel/boards/sof_sdw_cs_amp.c index 56cf75bc6cc4..e29a586ce7c0 100644 --- a/sound/soc/intel/boards/sof_sdw_cs_amp.c +++ b/sound/soc/intel/boards/sof_sdw_cs_amp.c @@ -57,7 +57,6 @@ int cs_spk_rtd_init(struct snd_soc_pcm_runtime *rtd) } int sof_sdw_cs_amp_init(struct snd_soc_card *card, - const struct snd_soc_acpi_link_adr *link, struct snd_soc_dai_link *dai_links, struct sof_sdw_codec_info *info, bool playback) diff --git a/sound/soc/intel/boards/sof_sdw_maxim.c b/sound/soc/intel/boards/sof_sdw_maxim.c index 034730432671..432e5112415a 100644 --- a/sound/soc/intel/boards/sof_sdw_maxim.c +++ b/sound/soc/intel/boards/sof_sdw_maxim.c @@ -139,7 +139,6 @@ static int mx8373_sdw_late_probe(struct snd_soc_card *card) } int sof_sdw_maxim_init(struct snd_soc_card *card, - const struct snd_soc_acpi_link_adr *link, struct snd_soc_dai_link *dai_links, struct sof_sdw_codec_info *info, bool playback) diff --git a/sound/soc/intel/boards/sof_sdw_rt711.c b/sound/soc/intel/boards/sof_sdw_rt711.c index 9762c48ba7a9..7e54fc5cbe09 100644 --- a/sound/soc/intel/boards/sof_sdw_rt711.c +++ b/sound/soc/intel/boards/sof_sdw_rt711.c @@ -158,7 +158,6 @@ int sof_sdw_rt711_exit(struct snd_soc_card *card, struct snd_soc_dai_link *dai_l } int sof_sdw_rt711_init(struct snd_soc_card *card, - const struct snd_soc_acpi_link_adr *link, struct snd_soc_dai_link *dai_links, struct sof_sdw_codec_info *info, bool playback) diff --git a/sound/soc/intel/boards/sof_sdw_rt_amp.c b/sound/soc/intel/boards/sof_sdw_rt_amp.c index 202edab95000..1b415708500e 100644 --- a/sound/soc/intel/boards/sof_sdw_rt_amp.c +++ b/sound/soc/intel/boards/sof_sdw_rt_amp.c @@ -281,7 +281,6 @@ int sof_sdw_rt_amp_exit(struct snd_soc_card *card, struct snd_soc_dai_link *dai_ } int sof_sdw_rt_amp_init(struct snd_soc_card *card, - const struct snd_soc_acpi_link_adr *link, struct snd_soc_dai_link *dai_links, struct sof_sdw_codec_info *info, bool playback) diff --git a/sound/soc/intel/boards/sof_sdw_rt_sdca_jack_common.c b/sound/soc/intel/boards/sof_sdw_rt_sdca_jack_common.c index 006771485486..85c09513bc35 100644 --- a/sound/soc/intel/boards/sof_sdw_rt_sdca_jack_common.c +++ b/sound/soc/intel/boards/sof_sdw_rt_sdca_jack_common.c @@ -191,7 +191,6 @@ int sof_sdw_rt_sdca_jack_exit(struct snd_soc_card *card, struct snd_soc_dai_link } int sof_sdw_rt_sdca_jack_init(struct snd_soc_card *card, - const struct snd_soc_acpi_link_adr *link, struct snd_soc_dai_link *dai_links, struct sof_sdw_codec_info *info, bool playback) -- cgit v1.2.3 From 36f307d296ad15e3d679d6567112b9ec4c30babc Mon Sep 17 00:00:00 2001 From: Charles Keepax Date: Tue, 26 Mar 2024 11:04:27 -0500 Subject: ASoC: Intel: sof_sdw: Remove redundant initialisations Unspecified fields are by default initialised to zero, remove redundant init pointer initialisations. Reviewed-by: Bard Liao Signed-off-by: Charles Keepax Signed-off-by: Pierre-Louis Bossart Link: https://msgid.link/r/20240326160429.13560-33-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/intel/boards/sof_sdw.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/sound/soc/intel/boards/sof_sdw.c b/sound/soc/intel/boards/sof_sdw.c index f3167e3498e0..5a7014d82d6c 100644 --- a/sound/soc/intel/boards/sof_sdw.c +++ b/sound/soc/intel/boards/sof_sdw.c @@ -1026,7 +1026,6 @@ static struct sof_sdw_codec_info codec_info_list[] = { .dai_name = "sdw-mockup-aif1", .dai_type = SOF_SDW_DAI_TYPE_JACK, .dailink = {SDW_JACK_OUT_DAI_ID, SDW_JACK_IN_DAI_ID}, - .init = NULL, }, }, .dai_num = 1, @@ -1040,7 +1039,6 @@ static struct sof_sdw_codec_info codec_info_list[] = { .dai_name = "sdw-mockup-aif1", .dai_type = SOF_SDW_DAI_TYPE_JACK, .dailink = {SDW_JACK_OUT_DAI_ID, SDW_JACK_IN_DAI_ID}, - .init = NULL, }, }, .dai_num = 1, @@ -1054,7 +1052,6 @@ static struct sof_sdw_codec_info codec_info_list[] = { .dai_name = "sdw-mockup-aif1", .dai_type = SOF_SDW_DAI_TYPE_AMP, .dailink = {SDW_AMP_OUT_DAI_ID, SDW_AMP_IN_DAI_ID}, - .init = NULL, }, }, .dai_num = 1, @@ -1068,7 +1065,6 @@ static struct sof_sdw_codec_info codec_info_list[] = { .direction = {false, true}, .dai_type = SOF_SDW_DAI_TYPE_MIC, .dailink = {SDW_UNUSED_DAI_ID, SDW_DMIC_DAI_ID}, - .init = NULL, }, }, .dai_num = 1, -- cgit v1.2.3 From 9c09bef69fe9376953348bb367c869f3d16c758c Mon Sep 17 00:00:00 2001 From: Charles Keepax Date: Tue, 26 Mar 2024 11:04:28 -0500 Subject: ASoC: Intel: sof_sdw: Add quirk for optional codec speakers Some codecs have speaker drivers that may or may not be used in a given system. Add a quirk (SOF_CODEC_SPKR) that defines if a system uses the codec speaker, this is kept generic such that any codec with such a speaker DAI can reuse the quirk. For implementation of this, add a quirk field into the sof_sdw_dai_info structure. This field is not used to specify if a system uses a particular quirk, that is still done through the sof_sdw_quirk variable, this field is used to flag a DAI as conditional on a certain quirk. This means the DAI will only be included in the card if sof_sdw_quirk and the DAI quirk field have a matching set bit. Reviewed-by: Bard Liao Signed-off-by: Charles Keepax Signed-off-by: Pierre-Louis Bossart Link: https://msgid.link/r/20240326160429.13560-34-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/intel/boards/sof_sdw.c | 5 +++++ sound/soc/intel/boards/sof_sdw_common.h | 3 +++ 2 files changed, 8 insertions(+) diff --git a/sound/soc/intel/boards/sof_sdw.c b/sound/soc/intel/boards/sof_sdw.c index 5a7014d82d6c..4fc15f597e28 100644 --- a/sound/soc/intel/boards/sof_sdw.c +++ b/sound/soc/intel/boards/sof_sdw.c @@ -37,6 +37,8 @@ static void log_quirks(struct device *dev) SOF_SSP_GET_PORT(sof_sdw_quirk)); if (sof_sdw_quirk & SOF_SDW_NO_AGGREGATION) dev_err(dev, "quirk SOF_SDW_NO_AGGREGATION enabled but no longer supported\n"); + if (sof_sdw_quirk & SOF_CODEC_SPKR) + dev_dbg(dev, "quirk SOF_CODEC_SPKR enabled\n"); } static int sof_sdw_quirk_cb(const struct dmi_system_id *id) @@ -1382,6 +1384,9 @@ static int parse_sdw_endpoints(struct snd_soc_card *card, dai_info = &codec_info->dais[adr_end->num]; sof_dai = find_dailink(sof_dais, adr_end); + if (dai_info->quirk && !(dai_info->quirk & sof_sdw_quirk)) + continue; + dev_dbg(dev, "Add dev: %d, 0x%llx end: %d, %s, %c/%c to %s: %d\n", ffs(adr_link->mask) - 1, adr_dev->adr, diff --git a/sound/soc/intel/boards/sof_sdw_common.h b/sound/soc/intel/boards/sof_sdw_common.h index 8d8c2ca68a7f..81181627b406 100644 --- a/sound/soc/intel/boards/sof_sdw_common.h +++ b/sound/soc/intel/boards/sof_sdw_common.h @@ -52,6 +52,8 @@ enum { #define SOF_SSP_GET_PORT(quirk) (((quirk) >> 7) & GENMASK(5, 0)) /* Deprecated and no longer supported by the code */ #define SOF_SDW_NO_AGGREGATION BIT(14) +/* If a CODEC has an optional speaker output, this quirk will enable it */ +#define SOF_CODEC_SPKR BIT(15) /* BT audio offload: reserve 3 bits for future */ #define SOF_BT_OFFLOAD_SSP_SHIFT 15 @@ -80,6 +82,7 @@ struct sof_sdw_dai_info { int (*exit)(struct snd_soc_card *card, struct snd_soc_dai_link *dai_link); int (*rtd_init)(struct snd_soc_pcm_runtime *rtd); bool rtd_init_done; /* Indicate that the rtd_init callback is done */ + unsigned long quirk; }; struct sof_sdw_codec_info { -- cgit v1.2.3 From 59ffeb15b2f7b44cf934fd778dc0d98a35aa6a84 Mon Sep 17 00:00:00 2001 From: Charles Keepax Date: Tue, 26 Mar 2024 11:04:29 -0500 Subject: ASoC: Intel: sof_sdw: Add support for cs42l43 optional speaker output Add support for the optional speaker output on the cs42l43, this uses the new SOF_CODEC_SPKR quirk to conditional include the speaker DAI link. It is worth noting that currently no systems are included that utilise this feature, but the feature is added as several systems are on the horizon. As part of this SOF_SDW_MAX_DAI_NUM must be increased, it is currently 3 but cs42l43 will now have 4 DAI links. This value is increased to 8 to give some head room for future devices. Reviewed-by: Bard Liao Signed-off-by: Charles Keepax Signed-off-by: Pierre-Louis Bossart Link: https://msgid.link/r/20240326160429.13560-35-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/intel/boards/sof_sdw.c | 11 ++++- sound/soc/intel/boards/sof_sdw_common.h | 9 +++- sound/soc/intel/boards/sof_sdw_cs42l43.c | 50 +++++++++++++++++++++++ sound/soc/intel/common/soc-acpi-intel-mtl-match.c | 6 +++ sound/soc/intel/common/soc-acpi-intel-tgl-match.c | 6 +++ 5 files changed, 80 insertions(+), 2 deletions(-) diff --git a/sound/soc/intel/boards/sof_sdw.c b/sound/soc/intel/boards/sof_sdw.c index 4fc15f597e28..b94835448b1b 100644 --- a/sound/soc/intel/boards/sof_sdw.c +++ b/sound/soc/intel/boards/sof_sdw.c @@ -1016,8 +1016,17 @@ static struct sof_sdw_codec_info codec_info_list[] = { .dai_type = SOF_SDW_DAI_TYPE_JACK, .dailink = {SDW_UNUSED_DAI_ID, SDW_JACK_IN_DAI_ID}, }, + { + .direction = {true, false}, + .dai_name = "cs42l43-dp6", + .dai_type = SOF_SDW_DAI_TYPE_AMP, + .dailink = {SDW_AMP_OUT_DAI_ID, SDW_UNUSED_DAI_ID}, + .init = sof_sdw_cs42l43_spk_init, + .rtd_init = cs42l43_spk_rtd_init, + .quirk = SOF_CODEC_SPKR, + }, }, - .dai_num = 3, + .dai_num = 4, }, { .part_id = 0xaaaa, /* generic codec mockup */ diff --git a/sound/soc/intel/boards/sof_sdw_common.h b/sound/soc/intel/boards/sof_sdw_common.h index 81181627b406..8468487a6bd6 100644 --- a/sound/soc/intel/boards/sof_sdw_common.h +++ b/sound/soc/intel/boards/sof_sdw_common.h @@ -66,7 +66,7 @@ enum { #define SOF_SDW_DAI_TYPE_AMP 1 #define SOF_SDW_DAI_TYPE_MIC 2 -#define SOF_SDW_MAX_DAI_NUM 3 +#define SOF_SDW_MAX_DAI_NUM 8 struct sof_sdw_codec_info; @@ -162,6 +162,12 @@ int sof_sdw_maxim_init(struct snd_soc_card *card, struct sof_sdw_codec_info *info, bool playback); +/* CS42L43 support */ +int sof_sdw_cs42l43_spk_init(struct snd_soc_card *card, + struct snd_soc_dai_link *dai_links, + struct sof_sdw_codec_info *info, + bool playback); + /* CS AMP support */ int sof_sdw_cs_amp_init(struct snd_soc_card *card, struct snd_soc_dai_link *dai_links, @@ -172,6 +178,7 @@ int sof_sdw_cs_amp_init(struct snd_soc_card *card, int cs42l42_rtd_init(struct snd_soc_pcm_runtime *rtd); int cs42l43_hs_rtd_init(struct snd_soc_pcm_runtime *rtd); +int cs42l43_spk_rtd_init(struct snd_soc_pcm_runtime *rtd); int cs42l43_dmic_rtd_init(struct snd_soc_pcm_runtime *rtd); int cs_spk_rtd_init(struct snd_soc_pcm_runtime *rtd); int maxim_spk_rtd_init(struct snd_soc_pcm_runtime *rtd); diff --git a/sound/soc/intel/boards/sof_sdw_cs42l43.c b/sound/soc/intel/boards/sof_sdw_cs42l43.c index a9b6edac2ecd..5361249f0f53 100644 --- a/sound/soc/intel/boards/sof_sdw_cs42l43.c +++ b/sound/soc/intel/boards/sof_sdw_cs42l43.c @@ -30,6 +30,17 @@ static const struct snd_soc_dapm_route cs42l43_hs_map[] = { { "cs42l43 ADC1_IN1_N", NULL, "Headset Mic" }, }; +static const struct snd_soc_dapm_widget cs42l43_spk_widgets[] = { + SND_SOC_DAPM_SPK("Speaker", NULL), +}; + +static const struct snd_soc_dapm_route cs42l43_spk_map[] = { + { "Speaker", NULL, "cs42l43 AMP1_OUT_P", }, + { "Speaker", NULL, "cs42l43 AMP1_OUT_N", }, + { "Speaker", NULL, "cs42l43 AMP2_OUT_P", }, + { "Speaker", NULL, "cs42l43 AMP2_OUT_N", }, +}; + static const struct snd_soc_dapm_widget cs42l43_dmic_widgets[] = { SND_SOC_DAPM_MIC("DMIC", NULL), }; @@ -108,6 +119,45 @@ int cs42l43_hs_rtd_init(struct snd_soc_pcm_runtime *rtd) return ret; } +int cs42l43_spk_rtd_init(struct snd_soc_pcm_runtime *rtd) +{ + struct snd_soc_card *card = rtd->card; + int ret; + + card->components = devm_kasprintf(card->dev, GFP_KERNEL, "%s spk:cs42l43-spk", + card->components); + if (!card->components) + return -ENOMEM; + + ret = snd_soc_dapm_new_controls(&card->dapm, cs42l43_spk_widgets, + ARRAY_SIZE(cs42l43_spk_widgets)); + if (ret) { + dev_err(card->dev, "cs42l43 speaker widgets addition failed: %d\n", ret); + return ret; + } + + ret = snd_soc_dapm_add_routes(&card->dapm, cs42l43_spk_map, + ARRAY_SIZE(cs42l43_spk_map)); + if (ret) + dev_err(card->dev, "cs42l43 speaker map addition failed: %d\n", ret); + + return ret; +} + +int sof_sdw_cs42l43_spk_init(struct snd_soc_card *card, + struct snd_soc_dai_link *dai_links, + struct sof_sdw_codec_info *info, + bool playback) +{ + /* Do init on playback link only. */ + if (!playback) + return 0; + + info->amp_num++; + + return 0; +} + int cs42l43_dmic_rtd_init(struct snd_soc_pcm_runtime *rtd) { struct snd_soc_card *card = rtd->card; diff --git a/sound/soc/intel/common/soc-acpi-intel-mtl-match.c b/sound/soc/intel/common/soc-acpi-intel-mtl-match.c index 7e53266d831d..27d1313e6686 100644 --- a/sound/soc/intel/common/soc-acpi-intel-mtl-match.c +++ b/sound/soc/intel/common/soc-acpi-intel-mtl-match.c @@ -357,6 +357,12 @@ static const struct snd_soc_acpi_endpoint cs42l43_endpoints[] = { .group_position = 0, .group_id = 0, }, + { /* Speaker Playback Endpoint */ + .num = 3, + .aggregated = 0, + .group_position = 0, + .group_id = 0, + }, }; static const struct snd_soc_acpi_adr_device cs42l43_0_adr[] = { diff --git a/sound/soc/intel/common/soc-acpi-intel-tgl-match.c b/sound/soc/intel/common/soc-acpi-intel-tgl-match.c index 0cef3d788a5b..77226d1eb1cf 100644 --- a/sound/soc/intel/common/soc-acpi-intel-tgl-match.c +++ b/sound/soc/intel/common/soc-acpi-intel-tgl-match.c @@ -433,6 +433,12 @@ static const struct snd_soc_acpi_endpoint cs42l43_endpoints[] = { .group_position = 0, .group_id = 0, }, + { /* Speaker Playback Endpoint */ + .num = 3, + .aggregated = 0, + .group_position = 0, + .group_id = 0, + }, }; static const struct snd_soc_acpi_adr_device cs42l43_3_adr[] = { -- cgit v1.2.3 From 7b95ee0db7e0a7f99077f1b926323c7bf0d2e8f8 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Tue, 26 Mar 2024 19:09:48 +0200 Subject: ASoC: soc-jack: Get rid of legacy GPIO support No more users. Signed-off-by: Andy Shevchenko Link: https://msgid.link/r/20240326171134.1414462-1-andriy.shevchenko@linux.intel.com Signed-off-by: Mark Brown --- include/sound/soc-jack.h | 2 -- sound/soc/generic/simple-card-utils.c | 2 -- sound/soc/soc-jack.c | 23 ++++------------------- 3 files changed, 4 insertions(+), 23 deletions(-) diff --git a/include/sound/soc-jack.h b/include/sound/soc-jack.h index a0abb1ee5110..3a81d4b8ca8a 100644 --- a/include/sound/soc-jack.h +++ b/include/sound/soc-jack.h @@ -44,7 +44,6 @@ struct snd_soc_jack_zone { /** * struct snd_soc_jack_gpio - Describes a gpio pin for jack detection * - * @gpio: legacy gpio number * @idx: gpio descriptor index within the function of the GPIO * consumer device * @gpiod_dev: GPIO consumer device @@ -59,7 +58,6 @@ struct snd_soc_jack_zone { * ADC). */ struct snd_soc_jack_gpio { - unsigned int gpio; unsigned int idx; struct device *gpiod_dev; const char *name; diff --git a/sound/soc/generic/simple-card-utils.c b/sound/soc/generic/simple-card-utils.c index 81077d16d22f..b4876b4f259d 100644 --- a/sound/soc/generic/simple-card-utils.c +++ b/sound/soc/generic/simple-card-utils.c @@ -752,8 +752,6 @@ int simple_util_init_jack(struct snd_soc_card *card, if (!prefix) prefix = ""; - sjack->gpio.gpio = -ENOENT; - if (is_hp) { snprintf(prop, sizeof(prop), "%shp-det", prefix); pin_name = pin ? pin : "Headphones"; diff --git a/sound/soc/soc-jack.c b/sound/soc/soc-jack.c index b2cc13b9c77b..63971396b708 100644 --- a/sound/soc/soc-jack.c +++ b/sound/soc/soc-jack.c @@ -8,7 +8,6 @@ #include #include -#include #include #include #include @@ -345,21 +344,9 @@ int snd_soc_jack_add_gpios(struct snd_soc_jack *jack, int count, goto undo; } } else { - /* legacy GPIO number */ - if (!gpio_is_valid(gpios[i].gpio)) { - dev_err(jack->card->dev, - "ASoC: Invalid gpio %d\n", - gpios[i].gpio); - ret = -EINVAL; - goto undo; - } - - ret = gpio_request_one(gpios[i].gpio, GPIOF_IN, - gpios[i].name); - if (ret) - goto undo; - - gpios[i].desc = gpio_to_desc(gpios[i].gpio); + dev_err(jack->card->dev, "ASoC: Invalid gpio at index %d\n", i); + ret = -EINVAL; + goto undo; } got_gpio: INIT_DELAYED_WORK(&gpios[i].work, gpio_work); @@ -373,7 +360,7 @@ got_gpio: gpios[i].name, &gpios[i]); if (ret < 0) - goto err; + goto undo; if (gpios[i].wake) { ret = irq_set_irq_wake(gpiod_to_irq(gpios[i].desc), 1); @@ -401,8 +388,6 @@ got_gpio: devres_add(jack->card->dev, tbl); return 0; -err: - gpio_free(gpios[i].gpio); undo: jack_free_gpios(jack, i, gpios); devres_free(tbl); -- cgit v1.2.3 From b7c59b038c656214f56432867056997c2e0fc268 Mon Sep 17 00:00:00 2001 From: Yuquan Wang Date: Mon, 18 Mar 2024 10:29:28 +0800 Subject: cxl/mem: Fix for the index of Clear Event Record Handle The dev_dbg info for Clear Event Records mailbox command would report the handle of the next record to clear not the current one. This was because the index 'i' had incremented before printing the current handle value. Fixes: 6ebe28f9ec72 ("cxl/mem: Read, trace, and clear events on driver load") Signed-off-by: Yuquan Wang Reviewed-by: Jonathan Cameron Reviewed-by: Dan Williams Reviewed-by: Fan Ni Signed-off-by: Dave Jiang --- drivers/cxl/core/mbox.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/cxl/core/mbox.c b/drivers/cxl/core/mbox.c index 9adda4795eb7..50146161887d 100644 --- a/drivers/cxl/core/mbox.c +++ b/drivers/cxl/core/mbox.c @@ -915,7 +915,7 @@ static int cxl_clear_event_record(struct cxl_memdev_state *mds, payload->handles[i++] = gen->hdr.handle; dev_dbg(mds->cxlds.dev, "Event log '%d': Clearing %u\n", log, - le16_to_cpu(payload->handles[i])); + le16_to_cpu(payload->handles[i - 1])); if (i == max_handles) { payload->nr_recs = i; -- cgit v1.2.3 From 5c88a9ccd4c431d58b532e4158b6999a8350062c Mon Sep 17 00:00:00 2001 From: Dave Jiang Date: Tue, 19 Mar 2024 11:15:08 -0700 Subject: cxl/core/regs: Fix usage of map->reg_type in cxl_decode_regblock() before assigned In the error path, map->reg_type is being used for kernel warning before its value is setup. Found by code inspection. Exposure to user is wrong reg_type being emitted via kernel log. Use a local var for reg_type and retrieve value for usage. Fixes: 6c7f4f1e51c2 ("cxl/core/regs: Make cxl_map_{component, device}_regs() device generic") Reviewed-by: Dan Williams Reviewed-by: Davidlohr Bueso Signed-off-by: Dave Jiang --- drivers/cxl/core/regs.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/cxl/core/regs.c b/drivers/cxl/core/regs.c index 372786f80955..3c42f984eeaf 100644 --- a/drivers/cxl/core/regs.c +++ b/drivers/cxl/core/regs.c @@ -271,6 +271,7 @@ EXPORT_SYMBOL_NS_GPL(cxl_map_device_regs, CXL); static bool cxl_decode_regblock(struct pci_dev *pdev, u32 reg_lo, u32 reg_hi, struct cxl_register_map *map) { + u8 reg_type = FIELD_GET(CXL_DVSEC_REG_LOCATOR_BLOCK_ID_MASK, reg_lo); int bar = FIELD_GET(CXL_DVSEC_REG_LOCATOR_BIR_MASK, reg_lo); u64 offset = ((u64)reg_hi << 32) | (reg_lo & CXL_DVSEC_REG_LOCATOR_BLOCK_OFF_LOW_MASK); @@ -278,11 +279,11 @@ static bool cxl_decode_regblock(struct pci_dev *pdev, u32 reg_lo, u32 reg_hi, if (offset > pci_resource_len(pdev, bar)) { dev_warn(&pdev->dev, "BAR%d: %pr: too small (offset: %pa, type: %d)\n", bar, - &pdev->resource[bar], &offset, map->reg_type); + &pdev->resource[bar], &offset, reg_type); return false; } - map->reg_type = FIELD_GET(CXL_DVSEC_REG_LOCATOR_BLOCK_ID_MASK, reg_lo); + map->reg_type = reg_type; map->resource = pci_resource_start(pdev, bar) + offset; map->max_size = pci_resource_len(pdev, bar) - offset; return true; -- cgit v1.2.3 From 559aebe45a054a479fdbd2a3dfba999ffd73cc9d Mon Sep 17 00:00:00 2001 From: Ondrej Jirman Date: Wed, 27 Mar 2024 09:05:34 +0100 Subject: ASoC: sun8i-codec: Fix build with CONFIG_SND_JACK_INPUT_DEV disabled When CONFIG_SND_JACK_INPUT_DEV is disabled, struct snd_jack doesn't have 'type' field. We can't rely on this field being always present, so store the jack_type in the codec driver itself. Signed-off-by: Ondrej Jirman Reported-by: kernel test robot Closes: https://lore.kernel.org/oe-kbuild-all/202403261243.kcXCPAYs-lkp@intel.com/ Link: https://msgid.link/r/20240327080542.3649840-1-megi@xff.cz Signed-off-by: Mark Brown --- sound/soc/sunxi/sun8i-codec.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/sound/soc/sunxi/sun8i-codec.c b/sound/soc/sunxi/sun8i-codec.c index 43795362fed0..b5dafb749c3f 100644 --- a/sound/soc/sunxi/sun8i-codec.c +++ b/sound/soc/sunxi/sun8i-codec.c @@ -232,6 +232,7 @@ struct sun8i_codec { struct delayed_work jack_work; int jack_irq; int jack_status; + int jack_type; int jack_last_sample; ktime_t jack_hbias_ready; struct mutex jack_mutex; @@ -1352,7 +1353,6 @@ static void sun8i_codec_jack_work(struct work_struct *work) struct sun8i_codec *scodec = container_of(work, struct sun8i_codec, jack_work.work); unsigned int mdata; - int type_mask = scodec->jack->jack->type; int type; guard(mutex)(&scodec->jack_mutex); @@ -1363,7 +1363,7 @@ static void sun8i_codec_jack_work(struct work_struct *work) scodec->jack_last_sample = -1; - if (type_mask & SND_JACK_MICROPHONE) { + if (scodec->jack_type & SND_JACK_MICROPHONE) { /* * If we were in disconnected state, we enable HBIAS and * wait 600ms before reading initial HDATA value. @@ -1376,7 +1376,7 @@ static void sun8i_codec_jack_work(struct work_struct *work) scodec->jack_status = SUN8I_JACK_STATUS_WAITING_HBIAS; } else { snd_soc_jack_report(scodec->jack, SND_JACK_HEADPHONE, - type_mask); + scodec->jack_type); scodec->jack_status = SUN8I_JACK_STATUS_CONNECTED; } } else if (scodec->jack_status == SUN8I_JACK_STATUS_WAITING_HBIAS) { @@ -1417,17 +1417,17 @@ static void sun8i_codec_jack_work(struct work_struct *work) if (type == SND_JACK_HEADPHONE) sun8i_codec_set_hmic_bias(scodec, false); - snd_soc_jack_report(scodec->jack, type, type_mask); + snd_soc_jack_report(scodec->jack, type, scodec->jack_type); scodec->jack_status = SUN8I_JACK_STATUS_CONNECTED; } else if (scodec->jack_status == SUN8I_JACK_STATUS_CONNECTED) { if (scodec->last_hmic_irq != SUN8I_HMIC_STS_JACK_OUT_IRQ_ST) return; scodec->jack_status = SUN8I_JACK_STATUS_DISCONNECTED; - if (type_mask & SND_JACK_MICROPHONE) + if (scodec->jack_type & SND_JACK_MICROPHONE) sun8i_codec_set_hmic_bias(scodec, false); - snd_soc_jack_report(scodec->jack, 0, type_mask); + snd_soc_jack_report(scodec->jack, 0, scodec->jack_type); } } @@ -1491,7 +1491,7 @@ static irqreturn_t sun8i_codec_jack_irq(int irq, void *dev_id) if (scodec->jack_last_sample >= 0 && scodec->jack_last_sample == value) snd_soc_jack_report(scodec->jack, type, - scodec->jack->jack->type); + scodec->jack_type); scodec->jack_last_sample = value; } -- cgit v1.2.3 From 3cf5abf2860bc538620fc3dfca06f403964b787b Mon Sep 17 00:00:00 2001 From: Manivannan Sadhasivam Date: Tue, 26 Mar 2024 14:21:30 +0530 Subject: MAINTAINERS: Drop Gustavo Pimentel as PCI DWC Maintainer Gustavo Pimentel seems to have left Synopsys, so his email is bouncing. And there is no indication from him expressing willingless to continue contributing to the driver. Drop him from the MAINTAINERS entry and add a CREDITS entry. Link: https://lore.kernel.org/r/20240326085130.12487-1-manivannan.sadhasivam@linaro.org Signed-off-by: Manivannan Sadhasivam [bhelgaas: add CREDITS entry] Signed-off-by: Bjorn Helgaas --- CREDITS | 4 ++++ MAINTAINERS | 1 - 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/CREDITS b/CREDITS index c55c5a0ee4ff..0107047f807b 100644 --- a/CREDITS +++ b/CREDITS @@ -3146,6 +3146,10 @@ S: Triftstra=DFe 55 S: 13353 Berlin S: Germany +N: Gustavo Pimental +E: gustavo.pimentel@synopsys.com +D: PCI driver for Synopsys DesignWare + N: Emanuel Pirker E: epirker@edu.uni-klu.ac.at D: AIC5800 IEEE 1394, RAW I/O on 1394 diff --git a/MAINTAINERS b/MAINTAINERS index aa3b947fb080..f61540722269 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -16966,7 +16966,6 @@ F: drivers/pci/controller/dwc/pci-exynos.c PCI DRIVER FOR SYNOPSYS DESIGNWARE M: Jingoo Han -M: Gustavo Pimentel M: Manivannan Sadhasivam L: linux-pci@vger.kernel.org S: Maintained -- cgit v1.2.3 From c335412ced27459b6ce71e812344a0bbaf43ab6a Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Wed, 27 Mar 2024 18:44:36 +0100 Subject: ASoC: loongson: i2s/pci: drop driver owner assignment PCI core in pci_register_driver() already sets the .owner, so driver does not need to. Signed-off-by: Krzysztof Kozlowski Reviewed-by: Pierre-Louis Bossart Link: https://msgid.link/r/20240327-module-owner-var-v1-1-86d5002ba6dc@linaro.org Signed-off-by: Mark Brown --- sound/soc/loongson/loongson_i2s_pci.c | 1 - 1 file changed, 1 deletion(-) diff --git a/sound/soc/loongson/loongson_i2s_pci.c b/sound/soc/loongson/loongson_i2s_pci.c index fa90361865c6..ec18b122cd79 100644 --- a/sound/soc/loongson/loongson_i2s_pci.c +++ b/sound/soc/loongson/loongson_i2s_pci.c @@ -160,7 +160,6 @@ static struct pci_driver loongson_i2s_driver = { .id_table = loongson_i2s_ids, .probe = loongson_i2s_pci_probe, .driver = { - .owner = THIS_MODULE, .pm = pm_sleep_ptr(&loongson_i2s_pm), }, }; -- cgit v1.2.3 From 8a4836231c98bde3fa49ad657c09342d2d7e27a7 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Wed, 27 Mar 2024 18:44:37 +0100 Subject: ASoC: tlv320aic32x4-spi: drop driver owner assignment Core in spi_register_driver() already sets the .owner, so driver does not need to. Signed-off-by: Krzysztof Kozlowski Reviewed-by: Pierre-Louis Bossart Link: https://msgid.link/r/20240327-module-owner-var-v1-2-86d5002ba6dc@linaro.org Signed-off-by: Mark Brown --- sound/soc/codecs/tlv320aic32x4-spi.c | 1 - 1 file changed, 1 deletion(-) diff --git a/sound/soc/codecs/tlv320aic32x4-spi.c b/sound/soc/codecs/tlv320aic32x4-spi.c index d5976c91766e..92246243ff94 100644 --- a/sound/soc/codecs/tlv320aic32x4-spi.c +++ b/sound/soc/codecs/tlv320aic32x4-spi.c @@ -56,7 +56,6 @@ MODULE_DEVICE_TABLE(of, aic32x4_of_id); static struct spi_driver aic32x4_spi_driver = { .driver = { .name = "tlv320aic32x4", - .owner = THIS_MODULE, .of_match_table = aic32x4_of_id, }, .probe = aic32x4_spi_probe, -- cgit v1.2.3 From 54b8a522e67a8dfe135867c00f9fa297f0841c92 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Wed, 27 Mar 2024 18:44:38 +0100 Subject: ASoC: tlv320aic3x-spi: drop driver owner assignment Core in spi_register_driver() already sets the .owner, so driver does not need to. Signed-off-by: Krzysztof Kozlowski Reviewed-by: Pierre-Louis Bossart Link: https://msgid.link/r/20240327-module-owner-var-v1-3-86d5002ba6dc@linaro.org Signed-off-by: Mark Brown --- sound/soc/codecs/tlv320aic3x-spi.c | 1 - 1 file changed, 1 deletion(-) diff --git a/sound/soc/codecs/tlv320aic3x-spi.c b/sound/soc/codecs/tlv320aic3x-spi.c index deed6ec7e081..f8c1c16eaa0e 100644 --- a/sound/soc/codecs/tlv320aic3x-spi.c +++ b/sound/soc/codecs/tlv320aic3x-spi.c @@ -63,7 +63,6 @@ MODULE_DEVICE_TABLE(of, aic3x_of_id); static struct spi_driver aic3x_spi_driver = { .driver = { .name = "tlv320aic3x", - .owner = THIS_MODULE, .of_match_table = aic3x_of_id, }, .probe = aic3x_spi_probe, -- cgit v1.2.3 From fe2065d645445dc2de61d9b336c41113759eef8a Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Wed, 27 Mar 2024 18:44:39 +0100 Subject: ASoC: max98373-sdw: drop driver owner assignment Core in sdw_register_driver() already sets the .owner, so driver does not need to. Signed-off-by: Krzysztof Kozlowski Reviewed-by: Pierre-Louis Bossart Link: https://msgid.link/r/20240327-module-owner-var-v1-4-86d5002ba6dc@linaro.org Signed-off-by: Mark Brown --- sound/soc/codecs/max98373-sdw.c | 1 - 1 file changed, 1 deletion(-) diff --git a/sound/soc/codecs/max98373-sdw.c b/sound/soc/codecs/max98373-sdw.c index 383e551f3bc7..26860882fd91 100644 --- a/sound/soc/codecs/max98373-sdw.c +++ b/sound/soc/codecs/max98373-sdw.c @@ -872,7 +872,6 @@ MODULE_DEVICE_TABLE(sdw, max98373_id); static struct sdw_driver max98373_sdw_driver = { .driver = { .name = "max98373", - .owner = THIS_MODULE, .of_match_table = of_match_ptr(max98373_of_match), .acpi_match_table = ACPI_PTR(max98373_acpi_match), .pm = &max98373_pm, -- cgit v1.2.3 From d95c19aa2ca60010bb1976399b5a822ff165a8ef Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Wed, 27 Mar 2024 18:44:40 +0100 Subject: ASoC: rt1017-sdca-sdw: drop driver owner assignment Core in sdw_register_driver() already sets the .owner, so driver does not need to. Signed-off-by: Krzysztof Kozlowski Reviewed-by: Pierre-Louis Bossart Link: https://msgid.link/r/20240327-module-owner-var-v1-5-86d5002ba6dc@linaro.org Signed-off-by: Mark Brown --- sound/soc/codecs/rt1017-sdca-sdw.c | 1 - 1 file changed, 1 deletion(-) diff --git a/sound/soc/codecs/rt1017-sdca-sdw.c b/sound/soc/codecs/rt1017-sdca-sdw.c index 4dbbd8bdaaac..7c8103a0d562 100644 --- a/sound/soc/codecs/rt1017-sdca-sdw.c +++ b/sound/soc/codecs/rt1017-sdca-sdw.c @@ -809,7 +809,6 @@ static const struct dev_pm_ops rt1017_sdca_pm = { static struct sdw_driver rt1017_sdca_sdw_driver = { .driver = { .name = "rt1017-sdca", - .owner = THIS_MODULE, .pm = &rt1017_sdca_pm, }, .probe = rt1017_sdca_sdw_probe, -- cgit v1.2.3 From b982047530d7a29eb68d42acaa19f249ac6ae5a7 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Wed, 27 Mar 2024 18:44:41 +0100 Subject: ASoC: rt1308-sdw: drop driver owner assignment Core in sdw_register_driver() already sets the .owner, so driver does not need to. Signed-off-by: Krzysztof Kozlowski Reviewed-by: Pierre-Louis Bossart Link: https://msgid.link/r/20240327-module-owner-var-v1-6-86d5002ba6dc@linaro.org Signed-off-by: Mark Brown --- sound/soc/codecs/rt1308-sdw.c | 1 - 1 file changed, 1 deletion(-) diff --git a/sound/soc/codecs/rt1308-sdw.c b/sound/soc/codecs/rt1308-sdw.c index 63d4abf964d4..563df483a466 100644 --- a/sound/soc/codecs/rt1308-sdw.c +++ b/sound/soc/codecs/rt1308-sdw.c @@ -804,7 +804,6 @@ static const struct dev_pm_ops rt1308_pm = { static struct sdw_driver rt1308_sdw_driver = { .driver = { .name = "rt1308", - .owner = THIS_MODULE, .pm = &rt1308_pm, }, .probe = rt1308_sdw_probe, -- cgit v1.2.3 From 7d5a2656626a6fbf573bde981c1550428a261cf2 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Wed, 27 Mar 2024 18:44:42 +0100 Subject: ASoC: rt1316-sdw: drop driver owner assignment Core in sdw_register_driver() already sets the .owner, so driver does not need to. Signed-off-by: Krzysztof Kozlowski Reviewed-by: Pierre-Louis Bossart Link: https://msgid.link/r/20240327-module-owner-var-v1-7-86d5002ba6dc@linaro.org Signed-off-by: Mark Brown --- sound/soc/codecs/rt1316-sdw.c | 1 - 1 file changed, 1 deletion(-) diff --git a/sound/soc/codecs/rt1316-sdw.c b/sound/soc/codecs/rt1316-sdw.c index 47511f70119a..aa7c0ca66877 100644 --- a/sound/soc/codecs/rt1316-sdw.c +++ b/sound/soc/codecs/rt1316-sdw.c @@ -781,7 +781,6 @@ static const struct dev_pm_ops rt1316_pm = { static struct sdw_driver rt1316_sdw_driver = { .driver = { .name = "rt1316-sdca", - .owner = THIS_MODULE, .pm = &rt1316_pm, }, .probe = rt1316_sdw_probe, -- cgit v1.2.3 From 3b7859dec834e96e8e833d2b2f2b4434e0e3b286 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Wed, 27 Mar 2024 18:44:43 +0100 Subject: ASoC: rt1318-sdw: drop driver owner assignment Core in sdw_register_driver() already sets the .owner, so driver does not need to. Signed-off-by: Krzysztof Kozlowski Reviewed-by: Pierre-Louis Bossart Link: https://msgid.link/r/20240327-module-owner-var-v1-8-86d5002ba6dc@linaro.org Signed-off-by: Mark Brown --- sound/soc/codecs/rt1318-sdw.c | 1 - 1 file changed, 1 deletion(-) diff --git a/sound/soc/codecs/rt1318-sdw.c b/sound/soc/codecs/rt1318-sdw.c index ff364bde4a08..3f6c7c25967f 100644 --- a/sound/soc/codecs/rt1318-sdw.c +++ b/sound/soc/codecs/rt1318-sdw.c @@ -855,7 +855,6 @@ static const struct dev_pm_ops rt1318_pm = { static struct sdw_driver rt1318_sdw_driver = { .driver = { .name = "rt1318-sdca", - .owner = THIS_MODULE, .pm = &rt1318_pm, }, .probe = rt1318_sdw_probe, -- cgit v1.2.3 From e140dfeb1028ef49c34ae238863398c2c7e792f0 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Wed, 27 Mar 2024 18:44:44 +0100 Subject: ASoC: rt5682-sdw: drop driver owner assignment Core in sdw_register_driver() already sets the .owner, so driver does not need to. Signed-off-by: Krzysztof Kozlowski Reviewed-by: Pierre-Louis Bossart Link: https://msgid.link/r/20240327-module-owner-var-v1-9-86d5002ba6dc@linaro.org Signed-off-by: Mark Brown --- sound/soc/codecs/rt5682-sdw.c | 1 - 1 file changed, 1 deletion(-) diff --git a/sound/soc/codecs/rt5682-sdw.c b/sound/soc/codecs/rt5682-sdw.c index e67c2e19cb1a..43737d5cedd0 100644 --- a/sound/soc/codecs/rt5682-sdw.c +++ b/sound/soc/codecs/rt5682-sdw.c @@ -798,7 +798,6 @@ static const struct dev_pm_ops rt5682_pm = { static struct sdw_driver rt5682_sdw_driver = { .driver = { .name = "rt5682", - .owner = THIS_MODULE, .pm = &rt5682_pm, }, .probe = rt5682_sdw_probe, -- cgit v1.2.3 From 554bec0c52dc6b6bbd605aa09462d15e9c41575b Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Wed, 27 Mar 2024 18:44:45 +0100 Subject: ASoC: rt700-sdw: drop driver owner assignment Core in sdw_register_driver() already sets the .owner, so driver does not need to. Signed-off-by: Krzysztof Kozlowski Reviewed-by: Pierre-Louis Bossart Link: https://msgid.link/r/20240327-module-owner-var-v1-10-86d5002ba6dc@linaro.org Signed-off-by: Mark Brown --- sound/soc/codecs/rt700-sdw.c | 1 - 1 file changed, 1 deletion(-) diff --git a/sound/soc/codecs/rt700-sdw.c b/sound/soc/codecs/rt700-sdw.c index 52c33d56b143..24cb895b759f 100644 --- a/sound/soc/codecs/rt700-sdw.c +++ b/sound/soc/codecs/rt700-sdw.c @@ -558,7 +558,6 @@ static const struct dev_pm_ops rt700_pm = { static struct sdw_driver rt700_sdw_driver = { .driver = { .name = "rt700", - .owner = THIS_MODULE, .pm = &rt700_pm, }, .probe = rt700_sdw_probe, -- cgit v1.2.3 From 852298a5e1ce7e72cb3c491bce3bca7262f6ef16 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Wed, 27 Mar 2024 18:44:46 +0100 Subject: ASoC: rt711-sdca-sdw: drop driver owner assignment Core in sdw_register_driver() already sets the .owner, so driver does not need to. Signed-off-by: Krzysztof Kozlowski Reviewed-by: Pierre-Louis Bossart Link: https://msgid.link/r/20240327-module-owner-var-v1-11-86d5002ba6dc@linaro.org Signed-off-by: Mark Brown --- sound/soc/codecs/rt711-sdca-sdw.c | 1 - 1 file changed, 1 deletion(-) diff --git a/sound/soc/codecs/rt711-sdca-sdw.c b/sound/soc/codecs/rt711-sdca-sdw.c index 935e597022d3..a7aa69495a7b 100644 --- a/sound/soc/codecs/rt711-sdca-sdw.c +++ b/sound/soc/codecs/rt711-sdca-sdw.c @@ -474,7 +474,6 @@ static const struct dev_pm_ops rt711_sdca_pm = { static struct sdw_driver rt711_sdca_sdw_driver = { .driver = { .name = "rt711-sdca", - .owner = THIS_MODULE, .pm = &rt711_sdca_pm, }, .probe = rt711_sdca_sdw_probe, -- cgit v1.2.3 From 37dc3531c56b86143b69576c4b56434d8bfcbf59 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Wed, 27 Mar 2024 18:44:47 +0100 Subject: ASoC: rt711-sdw: drop driver owner assignment Core in sdw_register_driver() already sets the .owner, so driver does not need to. Signed-off-by: Krzysztof Kozlowski Reviewed-by: Pierre-Louis Bossart Link: https://msgid.link/r/20240327-module-owner-var-v1-12-86d5002ba6dc@linaro.org Signed-off-by: Mark Brown --- sound/soc/codecs/rt711-sdw.c | 1 - 1 file changed, 1 deletion(-) diff --git a/sound/soc/codecs/rt711-sdw.c b/sound/soc/codecs/rt711-sdw.c index 3f5773310ae8..0d587f48439a 100644 --- a/sound/soc/codecs/rt711-sdw.c +++ b/sound/soc/codecs/rt711-sdw.c @@ -569,7 +569,6 @@ static const struct dev_pm_ops rt711_pm = { static struct sdw_driver rt711_sdw_driver = { .driver = { .name = "rt711", - .owner = THIS_MODULE, .pm = &rt711_pm, }, .probe = rt711_sdw_probe, -- cgit v1.2.3 From e50d2fbb6371f4d8482f5e4e112155278db6fc34 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Wed, 27 Mar 2024 18:44:48 +0100 Subject: ASoC: rt712-sdca-dmic: drop driver owner assignment Core in sdw_register_driver() already sets the .owner, so driver does not need to. Signed-off-by: Krzysztof Kozlowski Reviewed-by: Pierre-Louis Bossart Link: https://msgid.link/r/20240327-module-owner-var-v1-13-86d5002ba6dc@linaro.org Signed-off-by: Mark Brown --- sound/soc/codecs/rt712-sdca-dmic.c | 1 - 1 file changed, 1 deletion(-) diff --git a/sound/soc/codecs/rt712-sdca-dmic.c b/sound/soc/codecs/rt712-sdca-dmic.c index 0926b26619bd..0e4d7cbdc951 100644 --- a/sound/soc/codecs/rt712-sdca-dmic.c +++ b/sound/soc/codecs/rt712-sdca-dmic.c @@ -976,7 +976,6 @@ static int rt712_sdca_dmic_sdw_remove(struct sdw_slave *slave) static struct sdw_driver rt712_sdca_dmic_sdw_driver = { .driver = { .name = "rt712-sdca-dmic", - .owner = THIS_MODULE, .pm = &rt712_sdca_dmic_pm, }, .probe = rt712_sdca_dmic_sdw_probe, -- cgit v1.2.3 From 7c00f1706e4b9ac02fdfb2a6b93b4487cbcefd3d Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Wed, 27 Mar 2024 18:44:49 +0100 Subject: ASoC: rt712-sdca-sdw: drop driver owner assignment Core in sdw_register_driver() already sets the .owner, so driver does not need to. Signed-off-by: Krzysztof Kozlowski Reviewed-by: Pierre-Louis Bossart Link: https://msgid.link/r/20240327-module-owner-var-v1-14-86d5002ba6dc@linaro.org Signed-off-by: Mark Brown --- sound/soc/codecs/rt712-sdca-sdw.c | 1 - 1 file changed, 1 deletion(-) diff --git a/sound/soc/codecs/rt712-sdca-sdw.c b/sound/soc/codecs/rt712-sdca-sdw.c index 01ac555cd79b..f04e11980591 100644 --- a/sound/soc/codecs/rt712-sdca-sdw.c +++ b/sound/soc/codecs/rt712-sdca-sdw.c @@ -474,7 +474,6 @@ static const struct dev_pm_ops rt712_sdca_pm = { static struct sdw_driver rt712_sdca_sdw_driver = { .driver = { .name = "rt712-sdca", - .owner = THIS_MODULE, .pm = &rt712_sdca_pm, }, .probe = rt712_sdca_sdw_probe, -- cgit v1.2.3 From d4f501e2926e32be76c0c564a634f06edef768bf Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Wed, 27 Mar 2024 18:44:50 +0100 Subject: ASoC: rt715-sdca-sdw: drop driver owner assignment Core in sdw_register_driver() already sets the .owner, so driver does not need to. Signed-off-by: Krzysztof Kozlowski Reviewed-by: Pierre-Louis Bossart Link: https://msgid.link/r/20240327-module-owner-var-v1-15-86d5002ba6dc@linaro.org Signed-off-by: Mark Brown --- sound/soc/codecs/rt715-sdca-sdw.c | 1 - 1 file changed, 1 deletion(-) diff --git a/sound/soc/codecs/rt715-sdca-sdw.c b/sound/soc/codecs/rt715-sdca-sdw.c index ab54a67a27eb..08db815d3c8e 100644 --- a/sound/soc/codecs/rt715-sdca-sdw.c +++ b/sound/soc/codecs/rt715-sdca-sdw.c @@ -270,7 +270,6 @@ static const struct dev_pm_ops rt715_pm = { static struct sdw_driver rt715_sdw_driver = { .driver = { .name = "rt715-sdca", - .owner = THIS_MODULE, .pm = &rt715_pm, }, .probe = rt715_sdca_sdw_probe, -- cgit v1.2.3 From eb9e0757976fdf34b65d70c7d25a7f0d3d1ecea9 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Wed, 27 Mar 2024 18:44:51 +0100 Subject: ASoC: rt715-sdw: drop driver owner assignment Core in sdw_register_driver() already sets the .owner, so driver does not need to. Signed-off-by: Krzysztof Kozlowski Reviewed-by: Pierre-Louis Bossart Link: https://msgid.link/r/20240327-module-owner-var-v1-16-86d5002ba6dc@linaro.org Signed-off-by: Mark Brown --- sound/soc/codecs/rt715-sdw.c | 1 - 1 file changed, 1 deletion(-) diff --git a/sound/soc/codecs/rt715-sdw.c b/sound/soc/codecs/rt715-sdw.c index 21f37babd148..823b9cacc3e2 100644 --- a/sound/soc/codecs/rt715-sdw.c +++ b/sound/soc/codecs/rt715-sdw.c @@ -577,7 +577,6 @@ static const struct dev_pm_ops rt715_pm = { static struct sdw_driver rt715_sdw_driver = { .driver = { .name = "rt715", - .owner = THIS_MODULE, .pm = &rt715_pm, }, .probe = rt715_sdw_probe, -- cgit v1.2.3 From 8c70ce6108cda5c36b9c4e66b1fd7dc8ded2a7d6 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Wed, 27 Mar 2024 18:44:52 +0100 Subject: ASoC: rt722-sdca-sdw: drop driver owner assignment Core in sdw_register_driver() already sets the .owner, so driver does not need to. Signed-off-by: Krzysztof Kozlowski Reviewed-by: Pierre-Louis Bossart Link: https://msgid.link/r/20240327-module-owner-var-v1-17-86d5002ba6dc@linaro.org Signed-off-by: Mark Brown --- sound/soc/codecs/rt722-sdca-sdw.c | 1 - 1 file changed, 1 deletion(-) diff --git a/sound/soc/codecs/rt722-sdca-sdw.c b/sound/soc/codecs/rt722-sdca-sdw.c index eb76f4c675b6..27af5f883c08 100644 --- a/sound/soc/codecs/rt722-sdca-sdw.c +++ b/sound/soc/codecs/rt722-sdca-sdw.c @@ -503,7 +503,6 @@ static const struct dev_pm_ops rt722_sdca_pm = { static struct sdw_driver rt722_sdca_sdw_driver = { .driver = { .name = "rt722-sdca", - .owner = THIS_MODULE, .pm = &rt722_sdca_pm, }, .probe = rt722_sdca_sdw_probe, -- cgit v1.2.3 From 29580cd7b9c6f975e88597ca66a001b16b97bae9 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Wed, 27 Mar 2024 18:44:53 +0100 Subject: ASoC: sdw-mockup: drop driver owner assignment Core in sdw_register_driver() already sets the .owner, so driver does not need to. Signed-off-by: Krzysztof Kozlowski Reviewed-by: Pierre-Louis Bossart Link: https://msgid.link/r/20240327-module-owner-var-v1-18-86d5002ba6dc@linaro.org Signed-off-by: Mark Brown --- sound/soc/codecs/sdw-mockup.c | 1 - 1 file changed, 1 deletion(-) diff --git a/sound/soc/codecs/sdw-mockup.c b/sound/soc/codecs/sdw-mockup.c index 5498ff027c58..574c08b14f0c 100644 --- a/sound/soc/codecs/sdw-mockup.c +++ b/sound/soc/codecs/sdw-mockup.c @@ -262,7 +262,6 @@ MODULE_DEVICE_TABLE(sdw, sdw_mockup_id); static struct sdw_driver sdw_mockup_sdw_driver = { .driver = { .name = "sdw-mockup", - .owner = THIS_MODULE, }, .probe = sdw_mockup_sdw_probe, .remove = sdw_mockup_sdw_remove, -- cgit v1.2.3 From 94a944a8c4f9e0de87cc9c5bdf8861ae2f64d874 Mon Sep 17 00:00:00 2001 From: Brent Lu Date: Wed, 27 Mar 2024 11:23:51 -0500 Subject: ASoC: Intel: ssp-common: relocate source file Moving ssp-common source and header files from sound/soc/intel/boards directory to sound/soc/intel/common directory and rename the source file. Keep file content unchanged for tracking purpose. Reviewed-by: Bard Liao Signed-off-by: Brent Lu Signed-off-by: Pierre-Louis Bossart Link: https://msgid.link/r/20240327162408.63953-2-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/intel/boards/Makefile | 3 - sound/soc/intel/boards/sof_board_helpers.h | 2 +- sound/soc/intel/boards/sof_cirrus_common.h | 2 +- sound/soc/intel/boards/sof_maxim_common.h | 2 +- sound/soc/intel/boards/sof_nuvoton_common.h | 2 +- sound/soc/intel/boards/sof_realtek_common.h | 2 +- sound/soc/intel/boards/sof_ssp_common.c | 122 --------------------- sound/soc/intel/boards/sof_ssp_common.h | 73 ------------ sound/soc/intel/common/Makefile | 3 + sound/soc/intel/common/soc-acpi-intel-ssp-common.c | 122 +++++++++++++++++++++ sound/soc/intel/common/sof_ssp_common.h | 73 ++++++++++++ 11 files changed, 203 insertions(+), 203 deletions(-) delete mode 100644 sound/soc/intel/boards/sof_ssp_common.c delete mode 100644 sound/soc/intel/boards/sof_ssp_common.h create mode 100644 sound/soc/intel/common/soc-acpi-intel-ssp-common.c create mode 100644 sound/soc/intel/common/sof_ssp_common.h diff --git a/sound/soc/intel/boards/Makefile b/sound/soc/intel/boards/Makefile index 8f711be46c43..a93b658ed672 100644 --- a/sound/soc/intel/boards/Makefile +++ b/sound/soc/intel/boards/Makefile @@ -101,8 +101,5 @@ obj-$(CONFIG_SND_SOC_INTEL_SOF_CIRRUS_COMMON) += snd-soc-intel-sof-cirrus-common snd-soc-intel-sof-nuvoton-common-objs += sof_nuvoton_common.o obj-$(CONFIG_SND_SOC_INTEL_SOF_NUVOTON_COMMON) += snd-soc-intel-sof-nuvoton-common.o -snd-soc-intel-sof-ssp-common-objs += sof_ssp_common.o -obj-$(CONFIG_SND_SOC_INTEL_SOF_SSP_COMMON) += snd-soc-intel-sof-ssp-common.o - snd-soc-intel-sof-board-helpers-objs += sof_board_helpers.o obj-$(CONFIG_SND_SOC_INTEL_SOF_BOARD_HELPERS) += snd-soc-intel-sof-board-helpers.o diff --git a/sound/soc/intel/boards/sof_board_helpers.h b/sound/soc/intel/boards/sof_board_helpers.h index b6a83ca14fa8..bd5c48cd0649 100644 --- a/sound/soc/intel/boards/sof_board_helpers.h +++ b/sound/soc/intel/boards/sof_board_helpers.h @@ -8,7 +8,7 @@ #include #include "sof_hdmi_common.h" -#include "sof_ssp_common.h" +#include "../common/sof_ssp_common.h" /* * Common board quirks: from bit 8 to 31, LSB 8 bits reserved for machine diff --git a/sound/soc/intel/boards/sof_cirrus_common.h b/sound/soc/intel/boards/sof_cirrus_common.h index d4ecf8d023d1..445621466f05 100644 --- a/sound/soc/intel/boards/sof_cirrus_common.h +++ b/sound/soc/intel/boards/sof_cirrus_common.h @@ -9,7 +9,7 @@ #define __SOF_CIRRUS_COMMON_H #include -#include "sof_ssp_common.h" +#include "../common/sof_ssp_common.h" /* * Cirrus Logic CS35L41/CS35L53 diff --git a/sound/soc/intel/boards/sof_maxim_common.h b/sound/soc/intel/boards/sof_maxim_common.h index fe0212fbad8e..63054bcd287b 100644 --- a/sound/soc/intel/boards/sof_maxim_common.h +++ b/sound/soc/intel/boards/sof_maxim_common.h @@ -11,7 +11,7 @@ #define __SOF_MAXIM_COMMON_H #include -#include "sof_ssp_common.h" +#include "../common/sof_ssp_common.h" /* * Maxim MAX98373 diff --git a/sound/soc/intel/boards/sof_nuvoton_common.h b/sound/soc/intel/boards/sof_nuvoton_common.h index 53a84f9a67c0..af2e58b1d393 100644 --- a/sound/soc/intel/boards/sof_nuvoton_common.h +++ b/sound/soc/intel/boards/sof_nuvoton_common.h @@ -9,7 +9,7 @@ #define __SOF_NUVOTON_COMMON_H #include -#include "sof_ssp_common.h" +#include "../common/sof_ssp_common.h" /* * Nuvoton NAU8318 diff --git a/sound/soc/intel/boards/sof_realtek_common.h b/sound/soc/intel/boards/sof_realtek_common.h index e3fa2924c1c1..99b23d96521a 100644 --- a/sound/soc/intel/boards/sof_realtek_common.h +++ b/sound/soc/intel/boards/sof_realtek_common.h @@ -11,7 +11,7 @@ #define __SOF_REALTEK_COMMON_H #include -#include "sof_ssp_common.h" +#include "../common/sof_ssp_common.h" /* * Realtek ALC1011 diff --git a/sound/soc/intel/boards/sof_ssp_common.c b/sound/soc/intel/boards/sof_ssp_common.c deleted file mode 100644 index 96072790e9c0..000000000000 --- a/sound/soc/intel/boards/sof_ssp_common.c +++ /dev/null @@ -1,122 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -// -// Copyright(c) 2023 Intel Corporation. All rights reserved. - -#include -#include -#include "sof_ssp_common.h" - -/* - * Codec probe function - */ -#define CODEC_MAP_ENTRY(n, h, t) \ - { \ - .name = n, \ - .acpi_hid = h, \ - .codec_type = t, \ - } - -struct codec_map { - const char *name; - const char *acpi_hid; - enum sof_ssp_codec codec_type; -}; - -static const struct codec_map codecs[] = { - /* Cirrus Logic */ - CODEC_MAP_ENTRY("CS42L42", CS42L42_ACPI_HID, CODEC_CS42L42), - - /* Dialog */ - CODEC_MAP_ENTRY("DA7219", DA7219_ACPI_HID, CODEC_DA7219), - - /* Everest */ - CODEC_MAP_ENTRY("ES8316", ES8316_ACPI_HID, CODEC_ES8316), - CODEC_MAP_ENTRY("ES8326", ES8326_ACPI_HID, CODEC_ES8326), - CODEC_MAP_ENTRY("ES8336", ES8336_ACPI_HID, CODEC_ES8336), - - /* Nuvoton */ - CODEC_MAP_ENTRY("NAU8825", NAU8825_ACPI_HID, CODEC_NAU8825), - - /* Realtek */ - CODEC_MAP_ENTRY("RT5650", RT5650_ACPI_HID, CODEC_RT5650), - CODEC_MAP_ENTRY("RT5682", RT5682_ACPI_HID, CODEC_RT5682), - CODEC_MAP_ENTRY("RT5682S", RT5682S_ACPI_HID, CODEC_RT5682S), -}; - -static const struct codec_map amps[] = { - /* Cirrus Logic */ - CODEC_MAP_ENTRY("CS35L41", CS35L41_ACPI_HID, CODEC_CS35L41), - - /* Maxim */ - CODEC_MAP_ENTRY("MAX98357A", MAX_98357A_ACPI_HID, CODEC_MAX98357A), - CODEC_MAP_ENTRY("MAX98360A", MAX_98360A_ACPI_HID, CODEC_MAX98360A), - CODEC_MAP_ENTRY("MAX98373", MAX_98373_ACPI_HID, CODEC_MAX98373), - CODEC_MAP_ENTRY("MAX98390", MAX_98390_ACPI_HID, CODEC_MAX98390), - - /* Nuvoton */ - CODEC_MAP_ENTRY("NAU8318", NAU8318_ACPI_HID, CODEC_NAU8318), - - /* Realtek */ - CODEC_MAP_ENTRY("RT1011", RT1011_ACPI_HID, CODEC_RT1011), - CODEC_MAP_ENTRY("RT1015", RT1015_ACPI_HID, CODEC_RT1015), - CODEC_MAP_ENTRY("RT1015P", RT1015P_ACPI_HID, CODEC_RT1015P), - CODEC_MAP_ENTRY("RT1019P", RT1019P_ACPI_HID, CODEC_RT1019P), - CODEC_MAP_ENTRY("RT1308", RT1308_ACPI_HID, CODEC_RT1308), -}; - -enum sof_ssp_codec sof_ssp_detect_codec_type(struct device *dev) -{ - int i; - - for (i = 0; i < ARRAY_SIZE(codecs); i++) { - if (!acpi_dev_present(codecs[i].acpi_hid, NULL, -1)) - continue; - - dev_dbg(dev, "codec %s found\n", codecs[i].name); - return codecs[i].codec_type; - } - - return CODEC_NONE; -} -EXPORT_SYMBOL_NS(sof_ssp_detect_codec_type, SND_SOC_INTEL_SOF_SSP_COMMON); - -enum sof_ssp_codec sof_ssp_detect_amp_type(struct device *dev) -{ - int i; - - for (i = 0; i < ARRAY_SIZE(amps); i++) { - if (!acpi_dev_present(amps[i].acpi_hid, NULL, -1)) - continue; - - dev_dbg(dev, "amp %s found\n", amps[i].name); - return amps[i].codec_type; - } - - return CODEC_NONE; -} -EXPORT_SYMBOL_NS(sof_ssp_detect_amp_type, SND_SOC_INTEL_SOF_SSP_COMMON); - -const char *sof_ssp_get_codec_name(enum sof_ssp_codec codec_type) -{ - int i; - - for (i = 0; i < ARRAY_SIZE(codecs); i++) { - if (codecs[i].codec_type != codec_type) - continue; - - return codecs[i].name; - } - for (i = 0; i < ARRAY_SIZE(amps); i++) { - if (amps[i].codec_type != codec_type) - continue; - - return amps[i].name; - } - - return NULL; -} -EXPORT_SYMBOL_NS(sof_ssp_get_codec_name, SND_SOC_INTEL_SOF_SSP_COMMON); - -MODULE_DESCRIPTION("ASoC Intel SOF Common Machine Driver Helpers"); -MODULE_AUTHOR("Brent Lu "); -MODULE_LICENSE("GPL"); diff --git a/sound/soc/intel/boards/sof_ssp_common.h b/sound/soc/intel/boards/sof_ssp_common.h deleted file mode 100644 index ff84154ce60a..000000000000 --- a/sound/soc/intel/boards/sof_ssp_common.h +++ /dev/null @@ -1,73 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-only */ -/* - * Copyright(c) 2023 Intel Corporation. - */ - -#ifndef __SOF_SSP_COMMON_H -#define __SOF_SSP_COMMON_H - -/* Cirrus Logic */ -#define CS35L41_ACPI_HID "CSC3541" -#define CS42L42_ACPI_HID "10134242" - -/* Dialog */ -#define DA7219_ACPI_HID "DLGS7219" - -/* Everest */ -#define ES8316_ACPI_HID "ESSX8316" -#define ES8326_ACPI_HID "ESSX8326" -#define ES8336_ACPI_HID "ESSX8336" - -#define MAX_98357A_ACPI_HID "MX98357A" -#define MAX_98360A_ACPI_HID "MX98360A" -#define MAX_98373_ACPI_HID "MX98373" -#define MAX_98390_ACPI_HID "MX98390" - -/* Nuvoton */ -#define NAU8318_ACPI_HID "NVTN2012" -#define NAU8825_ACPI_HID "10508825" - -/* Realtek */ -#define RT1011_ACPI_HID "10EC1011" -#define RT1015_ACPI_HID "10EC1015" -#define RT1015P_ACPI_HID "RTL1015" -#define RT1019P_ACPI_HID "RTL1019" -#define RT1308_ACPI_HID "10EC1308" -#define RT5650_ACPI_HID "10EC5650" -#define RT5682_ACPI_HID "10EC5682" -#define RT5682S_ACPI_HID "RTL5682" - -enum sof_ssp_codec { - CODEC_NONE, - - /* headphone codec */ - CODEC_CS42L42, - CODEC_DA7219, - CODEC_ES8316, - CODEC_ES8326, - CODEC_ES8336, - CODEC_NAU8825, - CODEC_RT5650, - CODEC_RT5682, - CODEC_RT5682S, - - /* speaker amplifier */ - CODEC_CS35L41, - CODEC_MAX98357A, - CODEC_MAX98360A, - CODEC_MAX98373, - CODEC_MAX98390, - CODEC_NAU8318, - CODEC_RT1011, - CODEC_RT1015, - CODEC_RT1015P, - CODEC_RT1019P, - CODEC_RT1308, -}; - -enum sof_ssp_codec sof_ssp_detect_codec_type(struct device *dev); -enum sof_ssp_codec sof_ssp_detect_amp_type(struct device *dev); - -const char *sof_ssp_get_codec_name(enum sof_ssp_codec codec_type); - -#endif /* __SOF_SSP_COMMON_H */ diff --git a/sound/soc/intel/common/Makefile b/sound/soc/intel/common/Makefile index f7370e5b4e9e..15c8a64368c5 100644 --- a/sound/soc/intel/common/Makefile +++ b/sound/soc/intel/common/Makefile @@ -17,3 +17,6 @@ snd-soc-acpi-intel-match-objs := soc-acpi-intel-byt-match.o soc-acpi-intel-cht-m obj-$(CONFIG_SND_SOC_INTEL_SST) += snd-soc-sst-dsp.o snd-soc-sst-ipc.o obj-$(CONFIG_SND_SOC_ACPI_INTEL_MATCH) += snd-soc-acpi-intel-match.o + +snd-soc-intel-sof-ssp-common-objs += soc-acpi-intel-ssp-common.o +obj-$(CONFIG_SND_SOC_INTEL_SOF_SSP_COMMON) += snd-soc-intel-sof-ssp-common.o diff --git a/sound/soc/intel/common/soc-acpi-intel-ssp-common.c b/sound/soc/intel/common/soc-acpi-intel-ssp-common.c new file mode 100644 index 000000000000..96072790e9c0 --- /dev/null +++ b/sound/soc/intel/common/soc-acpi-intel-ssp-common.c @@ -0,0 +1,122 @@ +// SPDX-License-Identifier: GPL-2.0-only +// +// Copyright(c) 2023 Intel Corporation. All rights reserved. + +#include +#include +#include "sof_ssp_common.h" + +/* + * Codec probe function + */ +#define CODEC_MAP_ENTRY(n, h, t) \ + { \ + .name = n, \ + .acpi_hid = h, \ + .codec_type = t, \ + } + +struct codec_map { + const char *name; + const char *acpi_hid; + enum sof_ssp_codec codec_type; +}; + +static const struct codec_map codecs[] = { + /* Cirrus Logic */ + CODEC_MAP_ENTRY("CS42L42", CS42L42_ACPI_HID, CODEC_CS42L42), + + /* Dialog */ + CODEC_MAP_ENTRY("DA7219", DA7219_ACPI_HID, CODEC_DA7219), + + /* Everest */ + CODEC_MAP_ENTRY("ES8316", ES8316_ACPI_HID, CODEC_ES8316), + CODEC_MAP_ENTRY("ES8326", ES8326_ACPI_HID, CODEC_ES8326), + CODEC_MAP_ENTRY("ES8336", ES8336_ACPI_HID, CODEC_ES8336), + + /* Nuvoton */ + CODEC_MAP_ENTRY("NAU8825", NAU8825_ACPI_HID, CODEC_NAU8825), + + /* Realtek */ + CODEC_MAP_ENTRY("RT5650", RT5650_ACPI_HID, CODEC_RT5650), + CODEC_MAP_ENTRY("RT5682", RT5682_ACPI_HID, CODEC_RT5682), + CODEC_MAP_ENTRY("RT5682S", RT5682S_ACPI_HID, CODEC_RT5682S), +}; + +static const struct codec_map amps[] = { + /* Cirrus Logic */ + CODEC_MAP_ENTRY("CS35L41", CS35L41_ACPI_HID, CODEC_CS35L41), + + /* Maxim */ + CODEC_MAP_ENTRY("MAX98357A", MAX_98357A_ACPI_HID, CODEC_MAX98357A), + CODEC_MAP_ENTRY("MAX98360A", MAX_98360A_ACPI_HID, CODEC_MAX98360A), + CODEC_MAP_ENTRY("MAX98373", MAX_98373_ACPI_HID, CODEC_MAX98373), + CODEC_MAP_ENTRY("MAX98390", MAX_98390_ACPI_HID, CODEC_MAX98390), + + /* Nuvoton */ + CODEC_MAP_ENTRY("NAU8318", NAU8318_ACPI_HID, CODEC_NAU8318), + + /* Realtek */ + CODEC_MAP_ENTRY("RT1011", RT1011_ACPI_HID, CODEC_RT1011), + CODEC_MAP_ENTRY("RT1015", RT1015_ACPI_HID, CODEC_RT1015), + CODEC_MAP_ENTRY("RT1015P", RT1015P_ACPI_HID, CODEC_RT1015P), + CODEC_MAP_ENTRY("RT1019P", RT1019P_ACPI_HID, CODEC_RT1019P), + CODEC_MAP_ENTRY("RT1308", RT1308_ACPI_HID, CODEC_RT1308), +}; + +enum sof_ssp_codec sof_ssp_detect_codec_type(struct device *dev) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(codecs); i++) { + if (!acpi_dev_present(codecs[i].acpi_hid, NULL, -1)) + continue; + + dev_dbg(dev, "codec %s found\n", codecs[i].name); + return codecs[i].codec_type; + } + + return CODEC_NONE; +} +EXPORT_SYMBOL_NS(sof_ssp_detect_codec_type, SND_SOC_INTEL_SOF_SSP_COMMON); + +enum sof_ssp_codec sof_ssp_detect_amp_type(struct device *dev) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(amps); i++) { + if (!acpi_dev_present(amps[i].acpi_hid, NULL, -1)) + continue; + + dev_dbg(dev, "amp %s found\n", amps[i].name); + return amps[i].codec_type; + } + + return CODEC_NONE; +} +EXPORT_SYMBOL_NS(sof_ssp_detect_amp_type, SND_SOC_INTEL_SOF_SSP_COMMON); + +const char *sof_ssp_get_codec_name(enum sof_ssp_codec codec_type) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(codecs); i++) { + if (codecs[i].codec_type != codec_type) + continue; + + return codecs[i].name; + } + for (i = 0; i < ARRAY_SIZE(amps); i++) { + if (amps[i].codec_type != codec_type) + continue; + + return amps[i].name; + } + + return NULL; +} +EXPORT_SYMBOL_NS(sof_ssp_get_codec_name, SND_SOC_INTEL_SOF_SSP_COMMON); + +MODULE_DESCRIPTION("ASoC Intel SOF Common Machine Driver Helpers"); +MODULE_AUTHOR("Brent Lu "); +MODULE_LICENSE("GPL"); diff --git a/sound/soc/intel/common/sof_ssp_common.h b/sound/soc/intel/common/sof_ssp_common.h new file mode 100644 index 000000000000..ff84154ce60a --- /dev/null +++ b/sound/soc/intel/common/sof_ssp_common.h @@ -0,0 +1,73 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright(c) 2023 Intel Corporation. + */ + +#ifndef __SOF_SSP_COMMON_H +#define __SOF_SSP_COMMON_H + +/* Cirrus Logic */ +#define CS35L41_ACPI_HID "CSC3541" +#define CS42L42_ACPI_HID "10134242" + +/* Dialog */ +#define DA7219_ACPI_HID "DLGS7219" + +/* Everest */ +#define ES8316_ACPI_HID "ESSX8316" +#define ES8326_ACPI_HID "ESSX8326" +#define ES8336_ACPI_HID "ESSX8336" + +#define MAX_98357A_ACPI_HID "MX98357A" +#define MAX_98360A_ACPI_HID "MX98360A" +#define MAX_98373_ACPI_HID "MX98373" +#define MAX_98390_ACPI_HID "MX98390" + +/* Nuvoton */ +#define NAU8318_ACPI_HID "NVTN2012" +#define NAU8825_ACPI_HID "10508825" + +/* Realtek */ +#define RT1011_ACPI_HID "10EC1011" +#define RT1015_ACPI_HID "10EC1015" +#define RT1015P_ACPI_HID "RTL1015" +#define RT1019P_ACPI_HID "RTL1019" +#define RT1308_ACPI_HID "10EC1308" +#define RT5650_ACPI_HID "10EC5650" +#define RT5682_ACPI_HID "10EC5682" +#define RT5682S_ACPI_HID "RTL5682" + +enum sof_ssp_codec { + CODEC_NONE, + + /* headphone codec */ + CODEC_CS42L42, + CODEC_DA7219, + CODEC_ES8316, + CODEC_ES8326, + CODEC_ES8336, + CODEC_NAU8825, + CODEC_RT5650, + CODEC_RT5682, + CODEC_RT5682S, + + /* speaker amplifier */ + CODEC_CS35L41, + CODEC_MAX98357A, + CODEC_MAX98360A, + CODEC_MAX98373, + CODEC_MAX98390, + CODEC_NAU8318, + CODEC_RT1011, + CODEC_RT1015, + CODEC_RT1015P, + CODEC_RT1019P, + CODEC_RT1308, +}; + +enum sof_ssp_codec sof_ssp_detect_codec_type(struct device *dev); +enum sof_ssp_codec sof_ssp_detect_amp_type(struct device *dev); + +const char *sof_ssp_get_codec_name(enum sof_ssp_codec codec_type); + +#endif /* __SOF_SSP_COMMON_H */ -- cgit v1.2.3 From bd1222ad1746ab4325b982c720c7099c78c7b731 Mon Sep 17 00:00:00 2001 From: Brent Lu Date: Wed, 27 Mar 2024 11:23:52 -0500 Subject: ASoC: Intel: ssp-common: relocate header file Moving ssp-common header file from sound/soc/intel/common directory to include/sound directory and rename the file. Keep file content unchanged for tracking purpose. Reviewed-by: Bard Liao Signed-off-by: Brent Lu Signed-off-by: Pierre-Louis Bossart Link: https://msgid.link/r/20240327162408.63953-3-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- include/sound/soc-acpi-intel-ssp-common.h | 73 ++++++++++++++++++++++ sound/soc/intel/boards/sof_board_helpers.h | 2 +- sound/soc/intel/boards/sof_cirrus_common.h | 2 +- sound/soc/intel/boards/sof_maxim_common.h | 2 +- sound/soc/intel/boards/sof_nuvoton_common.h | 2 +- sound/soc/intel/boards/sof_realtek_common.h | 2 +- sound/soc/intel/common/soc-acpi-intel-ssp-common.c | 2 +- sound/soc/intel/common/sof_ssp_common.h | 73 ---------------------- 8 files changed, 79 insertions(+), 79 deletions(-) create mode 100644 include/sound/soc-acpi-intel-ssp-common.h delete mode 100644 sound/soc/intel/common/sof_ssp_common.h diff --git a/include/sound/soc-acpi-intel-ssp-common.h b/include/sound/soc-acpi-intel-ssp-common.h new file mode 100644 index 000000000000..ff84154ce60a --- /dev/null +++ b/include/sound/soc-acpi-intel-ssp-common.h @@ -0,0 +1,73 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright(c) 2023 Intel Corporation. + */ + +#ifndef __SOF_SSP_COMMON_H +#define __SOF_SSP_COMMON_H + +/* Cirrus Logic */ +#define CS35L41_ACPI_HID "CSC3541" +#define CS42L42_ACPI_HID "10134242" + +/* Dialog */ +#define DA7219_ACPI_HID "DLGS7219" + +/* Everest */ +#define ES8316_ACPI_HID "ESSX8316" +#define ES8326_ACPI_HID "ESSX8326" +#define ES8336_ACPI_HID "ESSX8336" + +#define MAX_98357A_ACPI_HID "MX98357A" +#define MAX_98360A_ACPI_HID "MX98360A" +#define MAX_98373_ACPI_HID "MX98373" +#define MAX_98390_ACPI_HID "MX98390" + +/* Nuvoton */ +#define NAU8318_ACPI_HID "NVTN2012" +#define NAU8825_ACPI_HID "10508825" + +/* Realtek */ +#define RT1011_ACPI_HID "10EC1011" +#define RT1015_ACPI_HID "10EC1015" +#define RT1015P_ACPI_HID "RTL1015" +#define RT1019P_ACPI_HID "RTL1019" +#define RT1308_ACPI_HID "10EC1308" +#define RT5650_ACPI_HID "10EC5650" +#define RT5682_ACPI_HID "10EC5682" +#define RT5682S_ACPI_HID "RTL5682" + +enum sof_ssp_codec { + CODEC_NONE, + + /* headphone codec */ + CODEC_CS42L42, + CODEC_DA7219, + CODEC_ES8316, + CODEC_ES8326, + CODEC_ES8336, + CODEC_NAU8825, + CODEC_RT5650, + CODEC_RT5682, + CODEC_RT5682S, + + /* speaker amplifier */ + CODEC_CS35L41, + CODEC_MAX98357A, + CODEC_MAX98360A, + CODEC_MAX98373, + CODEC_MAX98390, + CODEC_NAU8318, + CODEC_RT1011, + CODEC_RT1015, + CODEC_RT1015P, + CODEC_RT1019P, + CODEC_RT1308, +}; + +enum sof_ssp_codec sof_ssp_detect_codec_type(struct device *dev); +enum sof_ssp_codec sof_ssp_detect_amp_type(struct device *dev); + +const char *sof_ssp_get_codec_name(enum sof_ssp_codec codec_type); + +#endif /* __SOF_SSP_COMMON_H */ diff --git a/sound/soc/intel/boards/sof_board_helpers.h b/sound/soc/intel/boards/sof_board_helpers.h index bd5c48cd0649..34ea974c8493 100644 --- a/sound/soc/intel/boards/sof_board_helpers.h +++ b/sound/soc/intel/boards/sof_board_helpers.h @@ -7,8 +7,8 @@ #define __SOF_INTEL_BOARD_HELPERS_H #include +#include #include "sof_hdmi_common.h" -#include "../common/sof_ssp_common.h" /* * Common board quirks: from bit 8 to 31, LSB 8 bits reserved for machine diff --git a/sound/soc/intel/boards/sof_cirrus_common.h b/sound/soc/intel/boards/sof_cirrus_common.h index 445621466f05..1c87637b9ef7 100644 --- a/sound/soc/intel/boards/sof_cirrus_common.h +++ b/sound/soc/intel/boards/sof_cirrus_common.h @@ -9,7 +9,7 @@ #define __SOF_CIRRUS_COMMON_H #include -#include "../common/sof_ssp_common.h" +#include /* * Cirrus Logic CS35L41/CS35L53 diff --git a/sound/soc/intel/boards/sof_maxim_common.h b/sound/soc/intel/boards/sof_maxim_common.h index 63054bcd287b..8886f985de68 100644 --- a/sound/soc/intel/boards/sof_maxim_common.h +++ b/sound/soc/intel/boards/sof_maxim_common.h @@ -11,7 +11,7 @@ #define __SOF_MAXIM_COMMON_H #include -#include "../common/sof_ssp_common.h" +#include /* * Maxim MAX98373 diff --git a/sound/soc/intel/boards/sof_nuvoton_common.h b/sound/soc/intel/boards/sof_nuvoton_common.h index af2e58b1d393..8a0f283260e7 100644 --- a/sound/soc/intel/boards/sof_nuvoton_common.h +++ b/sound/soc/intel/boards/sof_nuvoton_common.h @@ -9,7 +9,7 @@ #define __SOF_NUVOTON_COMMON_H #include -#include "../common/sof_ssp_common.h" +#include /* * Nuvoton NAU8318 diff --git a/sound/soc/intel/boards/sof_realtek_common.h b/sound/soc/intel/boards/sof_realtek_common.h index 99b23d96521a..289e85b61660 100644 --- a/sound/soc/intel/boards/sof_realtek_common.h +++ b/sound/soc/intel/boards/sof_realtek_common.h @@ -11,7 +11,7 @@ #define __SOF_REALTEK_COMMON_H #include -#include "../common/sof_ssp_common.h" +#include /* * Realtek ALC1011 diff --git a/sound/soc/intel/common/soc-acpi-intel-ssp-common.c b/sound/soc/intel/common/soc-acpi-intel-ssp-common.c index 96072790e9c0..37758f4e3f32 100644 --- a/sound/soc/intel/common/soc-acpi-intel-ssp-common.c +++ b/sound/soc/intel/common/soc-acpi-intel-ssp-common.c @@ -4,7 +4,7 @@ #include #include -#include "sof_ssp_common.h" +#include /* * Codec probe function diff --git a/sound/soc/intel/common/sof_ssp_common.h b/sound/soc/intel/common/sof_ssp_common.h deleted file mode 100644 index ff84154ce60a..000000000000 --- a/sound/soc/intel/common/sof_ssp_common.h +++ /dev/null @@ -1,73 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-only */ -/* - * Copyright(c) 2023 Intel Corporation. - */ - -#ifndef __SOF_SSP_COMMON_H -#define __SOF_SSP_COMMON_H - -/* Cirrus Logic */ -#define CS35L41_ACPI_HID "CSC3541" -#define CS42L42_ACPI_HID "10134242" - -/* Dialog */ -#define DA7219_ACPI_HID "DLGS7219" - -/* Everest */ -#define ES8316_ACPI_HID "ESSX8316" -#define ES8326_ACPI_HID "ESSX8326" -#define ES8336_ACPI_HID "ESSX8336" - -#define MAX_98357A_ACPI_HID "MX98357A" -#define MAX_98360A_ACPI_HID "MX98360A" -#define MAX_98373_ACPI_HID "MX98373" -#define MAX_98390_ACPI_HID "MX98390" - -/* Nuvoton */ -#define NAU8318_ACPI_HID "NVTN2012" -#define NAU8825_ACPI_HID "10508825" - -/* Realtek */ -#define RT1011_ACPI_HID "10EC1011" -#define RT1015_ACPI_HID "10EC1015" -#define RT1015P_ACPI_HID "RTL1015" -#define RT1019P_ACPI_HID "RTL1019" -#define RT1308_ACPI_HID "10EC1308" -#define RT5650_ACPI_HID "10EC5650" -#define RT5682_ACPI_HID "10EC5682" -#define RT5682S_ACPI_HID "RTL5682" - -enum sof_ssp_codec { - CODEC_NONE, - - /* headphone codec */ - CODEC_CS42L42, - CODEC_DA7219, - CODEC_ES8316, - CODEC_ES8326, - CODEC_ES8336, - CODEC_NAU8825, - CODEC_RT5650, - CODEC_RT5682, - CODEC_RT5682S, - - /* speaker amplifier */ - CODEC_CS35L41, - CODEC_MAX98357A, - CODEC_MAX98360A, - CODEC_MAX98373, - CODEC_MAX98390, - CODEC_NAU8318, - CODEC_RT1011, - CODEC_RT1015, - CODEC_RT1015P, - CODEC_RT1019P, - CODEC_RT1308, -}; - -enum sof_ssp_codec sof_ssp_detect_codec_type(struct device *dev); -enum sof_ssp_codec sof_ssp_detect_amp_type(struct device *dev); - -const char *sof_ssp_get_codec_name(enum sof_ssp_codec codec_type); - -#endif /* __SOF_SSP_COMMON_H */ -- cgit v1.2.3 From a17fea3880aea23fd8821ff0660268a680e0326b Mon Sep 17 00:00:00 2001 From: Brent Lu Date: Wed, 27 Mar 2024 11:23:53 -0500 Subject: ASoC: Intel: ssp-common: naming convention change As we moved ssp-common files to new locations with new names, changing the naming convention from sof_ssp_ to snd_soc_acpi_intel_. Reviewed-by: Pierre-Louis Bossart Signed-off-by: Brent Lu Signed-off-by: Pierre-Louis Bossart Link: https://msgid.link/r/20240327162408.63953-4-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- include/sound/soc-acpi-intel-ssp-common.h | 17 ++++++++++------- sound/soc/intel/boards/sof_board_helpers.c | 13 +++++++------ sound/soc/intel/boards/sof_board_helpers.h | 4 ++-- sound/soc/intel/common/soc-acpi-intel-ssp-common.c | 17 ++++++++++------- 4 files changed, 29 insertions(+), 22 deletions(-) diff --git a/include/sound/soc-acpi-intel-ssp-common.h b/include/sound/soc-acpi-intel-ssp-common.h index ff84154ce60a..b568cda11051 100644 --- a/include/sound/soc-acpi-intel-ssp-common.h +++ b/include/sound/soc-acpi-intel-ssp-common.h @@ -3,8 +3,8 @@ * Copyright(c) 2023 Intel Corporation. */ -#ifndef __SOF_SSP_COMMON_H -#define __SOF_SSP_COMMON_H +#ifndef __LINUX_SND_SOC_ACPI_INTEL_SSP_COMMON_H +#define __LINUX_SND_SOC_ACPI_INTEL_SSP_COMMON_H /* Cirrus Logic */ #define CS35L41_ACPI_HID "CSC3541" @@ -37,7 +37,7 @@ #define RT5682_ACPI_HID "10EC5682" #define RT5682S_ACPI_HID "RTL5682" -enum sof_ssp_codec { +enum snd_soc_acpi_intel_codec { CODEC_NONE, /* headphone codec */ @@ -65,9 +65,12 @@ enum sof_ssp_codec { CODEC_RT1308, }; -enum sof_ssp_codec sof_ssp_detect_codec_type(struct device *dev); -enum sof_ssp_codec sof_ssp_detect_amp_type(struct device *dev); +enum snd_soc_acpi_intel_codec +snd_soc_acpi_intel_detect_codec_type(struct device *dev); +enum snd_soc_acpi_intel_codec +snd_soc_acpi_intel_detect_amp_type(struct device *dev); -const char *sof_ssp_get_codec_name(enum sof_ssp_codec codec_type); +const char * +snd_soc_acpi_intel_get_codec_name(enum snd_soc_acpi_intel_codec codec_type); -#endif /* __SOF_SSP_COMMON_H */ +#endif /* __LINUX_SND_SOC_ACPI_INTEL_SSP_COMMON_H */ diff --git a/sound/soc/intel/boards/sof_board_helpers.c b/sound/soc/intel/boards/sof_board_helpers.c index 586600680e84..8819ab5694bf 100644 --- a/sound/soc/intel/boards/sof_board_helpers.c +++ b/sound/soc/intel/boards/sof_board_helpers.c @@ -103,13 +103,13 @@ static struct snd_soc_dai_link_component platform_component[] = { }; static int set_ssp_codec_link(struct device *dev, struct snd_soc_dai_link *link, - int be_id, enum sof_ssp_codec codec_type, + int be_id, enum snd_soc_acpi_intel_codec codec_type, int ssp_codec) { struct snd_soc_dai_link_component *cpus; dev_dbg(dev, "link %d: ssp codec %s, ssp %d\n", be_id, - sof_ssp_get_codec_name(codec_type), ssp_codec); + snd_soc_acpi_intel_get_codec_name(codec_type), ssp_codec); /* link name */ link->name = devm_kasprintf(dev, GFP_KERNEL, "SSP%d-Codec", ssp_codec); @@ -259,12 +259,13 @@ static int set_idisp_hdmi_link(struct device *dev, struct snd_soc_dai_link *link } static int set_ssp_amp_link(struct device *dev, struct snd_soc_dai_link *link, - int be_id, enum sof_ssp_codec amp_type, int ssp_amp) + int be_id, enum snd_soc_acpi_intel_codec amp_type, + int ssp_amp) { struct snd_soc_dai_link_component *cpus; dev_dbg(dev, "link %d: ssp amp %s, ssp %d\n", be_id, - sof_ssp_get_codec_name(amp_type), ssp_amp); + snd_soc_acpi_intel_get_codec_name(amp_type), ssp_amp); /* link name */ link->name = devm_kasprintf(dev, GFP_KERNEL, "SSP%d-Codec", ssp_amp); @@ -598,8 +599,8 @@ sof_intel_board_get_ctx(struct device *dev, unsigned long board_quirk) if (!ctx) return NULL; - ctx->codec_type = sof_ssp_detect_codec_type(dev); - ctx->amp_type = sof_ssp_detect_amp_type(dev); + ctx->codec_type = snd_soc_acpi_intel_detect_codec_type(dev); + ctx->amp_type = snd_soc_acpi_intel_detect_amp_type(dev); ctx->dmic_be_num = 2; ctx->hdmi_num = (board_quirk & SOF_NUM_IDISP_HDMI_MASK) >> diff --git a/sound/soc/intel/boards/sof_board_helpers.h b/sound/soc/intel/boards/sof_board_helpers.h index 34ea974c8493..644f6b4a1b7b 100644 --- a/sound/soc/intel/boards/sof_board_helpers.h +++ b/sound/soc/intel/boards/sof_board_helpers.h @@ -132,8 +132,8 @@ struct sof_card_private { struct snd_soc_jack headset_jack; struct sof_hdmi_private hdmi; - enum sof_ssp_codec codec_type; - enum sof_ssp_codec amp_type; + enum snd_soc_acpi_intel_codec codec_type; + enum snd_soc_acpi_intel_codec amp_type; int dmic_be_num; int hdmi_num; diff --git a/sound/soc/intel/common/soc-acpi-intel-ssp-common.c b/sound/soc/intel/common/soc-acpi-intel-ssp-common.c index 37758f4e3f32..716243a4fc9a 100644 --- a/sound/soc/intel/common/soc-acpi-intel-ssp-common.c +++ b/sound/soc/intel/common/soc-acpi-intel-ssp-common.c @@ -19,7 +19,7 @@ struct codec_map { const char *name; const char *acpi_hid; - enum sof_ssp_codec codec_type; + enum snd_soc_acpi_intel_codec codec_type; }; static const struct codec_map codecs[] = { @@ -64,7 +64,8 @@ static const struct codec_map amps[] = { CODEC_MAP_ENTRY("RT1308", RT1308_ACPI_HID, CODEC_RT1308), }; -enum sof_ssp_codec sof_ssp_detect_codec_type(struct device *dev) +enum snd_soc_acpi_intel_codec +snd_soc_acpi_intel_detect_codec_type(struct device *dev) { int i; @@ -78,9 +79,10 @@ enum sof_ssp_codec sof_ssp_detect_codec_type(struct device *dev) return CODEC_NONE; } -EXPORT_SYMBOL_NS(sof_ssp_detect_codec_type, SND_SOC_INTEL_SOF_SSP_COMMON); +EXPORT_SYMBOL_NS(snd_soc_acpi_intel_detect_codec_type, SND_SOC_INTEL_SOF_SSP_COMMON); -enum sof_ssp_codec sof_ssp_detect_amp_type(struct device *dev) +enum snd_soc_acpi_intel_codec +snd_soc_acpi_intel_detect_amp_type(struct device *dev) { int i; @@ -94,9 +96,10 @@ enum sof_ssp_codec sof_ssp_detect_amp_type(struct device *dev) return CODEC_NONE; } -EXPORT_SYMBOL_NS(sof_ssp_detect_amp_type, SND_SOC_INTEL_SOF_SSP_COMMON); +EXPORT_SYMBOL_NS(snd_soc_acpi_intel_detect_amp_type, SND_SOC_INTEL_SOF_SSP_COMMON); -const char *sof_ssp_get_codec_name(enum sof_ssp_codec codec_type) +const char * +snd_soc_acpi_intel_get_codec_name(enum snd_soc_acpi_intel_codec codec_type) { int i; @@ -115,7 +118,7 @@ const char *sof_ssp_get_codec_name(enum sof_ssp_codec codec_type) return NULL; } -EXPORT_SYMBOL_NS(sof_ssp_get_codec_name, SND_SOC_INTEL_SOF_SSP_COMMON); +EXPORT_SYMBOL_NS(snd_soc_acpi_intel_get_codec_name, SND_SOC_INTEL_SOF_SSP_COMMON); MODULE_DESCRIPTION("ASoC Intel SOF Common Machine Driver Helpers"); MODULE_AUTHOR("Brent Lu "); -- cgit v1.2.3 From e1ff45518fbe73c09c3d0dbe8bd5284bb3d25dc3 Mon Sep 17 00:00:00 2001 From: Brent Lu Date: Wed, 27 Mar 2024 11:23:54 -0500 Subject: ASoC: Intel: ssp-common: module name change As we applied new naming convention to functions and structures, changing module name as well to reflect the new naming. Reviewed-by: Bard Liao Signed-off-by: Brent Lu Signed-off-by: Pierre-Louis Bossart Link: https://msgid.link/r/20240327162408.63953-5-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/intel/Kconfig | 6 ++++++ sound/soc/intel/boards/Kconfig | 13 +++++-------- sound/soc/intel/boards/sof_board_helpers.c | 2 +- sound/soc/intel/common/Makefile | 4 ++-- sound/soc/intel/common/soc-acpi-intel-ssp-common.c | 6 +++--- 5 files changed, 17 insertions(+), 14 deletions(-) diff --git a/sound/soc/intel/Kconfig b/sound/soc/intel/Kconfig index 4b9e498e3303..e17d1a517567 100644 --- a/sound/soc/intel/Kconfig +++ b/sound/soc/intel/Kconfig @@ -197,6 +197,12 @@ config SND_SOC_ACPI_INTEL_MATCH # this option controls the compilation of ACPI matching tables and # helpers and is not meant to be selected by the user. +config SND_SOC_ACPI_INTEL_SSP_COMMON + tristate + select SND_SOC_ACPI if ACPI + # this option provides helpers to detect codec type and is not meant + # to be selected by the user. + endif ## SND_SOC_INTEL_SST_TOPLEVEL || SND_SOC_SOF_INTEL_TOPLEVEL config SND_SOC_INTEL_KEEMBAY diff --git a/sound/soc/intel/boards/Kconfig b/sound/soc/intel/boards/Kconfig index b7a6ac4b6c0c..4d6ef68da130 100644 --- a/sound/soc/intel/boards/Kconfig +++ b/sound/soc/intel/boards/Kconfig @@ -41,9 +41,6 @@ config SND_SOC_INTEL_SOF_CIRRUS_COMMON config SND_SOC_INTEL_SOF_NUVOTON_COMMON tristate -config SND_SOC_INTEL_SOF_SSP_COMMON - tristate - config SND_SOC_INTEL_SOF_BOARD_HELPERS tristate @@ -503,7 +500,7 @@ config SND_SOC_INTEL_SOF_RT5682_MACH select SND_SOC_INTEL_SOF_BOARD_HELPERS select SND_SOC_INTEL_SOF_MAXIM_COMMON select SND_SOC_INTEL_SOF_REALTEK_COMMON - select SND_SOC_INTEL_SOF_SSP_COMMON + select SND_SOC_ACPI_INTEL_SSP_COMMON help This adds support for ASoC machine driver for SOF platforms with rt5650 or rt5682 codec. @@ -521,7 +518,7 @@ config SND_SOC_INTEL_SOF_CS42L42_MACH select SND_SOC_INTEL_HDA_DSP_COMMON select SND_SOC_INTEL_SOF_BOARD_HELPERS select SND_SOC_INTEL_SOF_MAXIM_COMMON - select SND_SOC_INTEL_SOF_SSP_COMMON + select SND_SOC_ACPI_INTEL_SSP_COMMON help This adds support for ASoC machine driver for SOF platforms with cs42l42 codec. @@ -574,7 +571,7 @@ config SND_SOC_INTEL_SOF_NAU8825_MACH select SND_SOC_INTEL_SOF_MAXIM_COMMON select SND_SOC_INTEL_SOF_NUVOTON_COMMON select SND_SOC_INTEL_SOF_REALTEK_COMMON - select SND_SOC_INTEL_SOF_SSP_COMMON + select SND_SOC_ACPI_INTEL_SSP_COMMON help This adds support for ASoC machine driver for SOF platforms with nau8825 codec. @@ -626,7 +623,7 @@ config SND_SOC_INTEL_SOF_DA7219_MACH select SND_SOC_DMIC select SND_SOC_INTEL_SOF_BOARD_HELPERS select SND_SOC_INTEL_SOF_MAXIM_COMMON - select SND_SOC_INTEL_SOF_SSP_COMMON + select SND_SOC_ACPI_INTEL_SSP_COMMON help This adds support for ASoC machine driver for SOF platforms with Dialog DA7219 I2S audio codec. @@ -646,7 +643,7 @@ config SND_SOC_INTEL_SOF_SSP_AMP_MACH select SND_SOC_INTEL_SOF_BOARD_HELPERS select SND_SOC_INTEL_SOF_REALTEK_COMMON select SND_SOC_INTEL_SOF_CIRRUS_COMMON - select SND_SOC_INTEL_SOF_SSP_COMMON + select SND_SOC_ACPI_INTEL_SSP_COMMON help This adds support for ASoC machine driver for SOF platforms with RT1308/CS35L41 I2S audio codec. diff --git a/sound/soc/intel/boards/sof_board_helpers.c b/sound/soc/intel/boards/sof_board_helpers.c index 8819ab5694bf..ba5be5423626 100644 --- a/sound/soc/intel/boards/sof_board_helpers.c +++ b/sound/soc/intel/boards/sof_board_helpers.c @@ -635,4 +635,4 @@ MODULE_DESCRIPTION("ASoC Intel SOF Machine Driver Board Helpers"); MODULE_AUTHOR("Brent Lu "); MODULE_LICENSE("GPL"); MODULE_IMPORT_NS(SND_SOC_INTEL_HDA_DSP_COMMON); -MODULE_IMPORT_NS(SND_SOC_INTEL_SOF_SSP_COMMON); +MODULE_IMPORT_NS(SND_SOC_ACPI_INTEL_SSP_COMMON); diff --git a/sound/soc/intel/common/Makefile b/sound/soc/intel/common/Makefile index 15c8a64368c5..dcd552d815a2 100644 --- a/sound/soc/intel/common/Makefile +++ b/sound/soc/intel/common/Makefile @@ -18,5 +18,5 @@ snd-soc-acpi-intel-match-objs := soc-acpi-intel-byt-match.o soc-acpi-intel-cht-m obj-$(CONFIG_SND_SOC_INTEL_SST) += snd-soc-sst-dsp.o snd-soc-sst-ipc.o obj-$(CONFIG_SND_SOC_ACPI_INTEL_MATCH) += snd-soc-acpi-intel-match.o -snd-soc-intel-sof-ssp-common-objs += soc-acpi-intel-ssp-common.o -obj-$(CONFIG_SND_SOC_INTEL_SOF_SSP_COMMON) += snd-soc-intel-sof-ssp-common.o +snd-soc-acpi-intel-ssp-common-objs += soc-acpi-intel-ssp-common.o +obj-$(CONFIG_SND_SOC_ACPI_INTEL_SSP_COMMON) += snd-soc-acpi-intel-ssp-common.o diff --git a/sound/soc/intel/common/soc-acpi-intel-ssp-common.c b/sound/soc/intel/common/soc-acpi-intel-ssp-common.c index 716243a4fc9a..40b68c20a12a 100644 --- a/sound/soc/intel/common/soc-acpi-intel-ssp-common.c +++ b/sound/soc/intel/common/soc-acpi-intel-ssp-common.c @@ -79,7 +79,7 @@ snd_soc_acpi_intel_detect_codec_type(struct device *dev) return CODEC_NONE; } -EXPORT_SYMBOL_NS(snd_soc_acpi_intel_detect_codec_type, SND_SOC_INTEL_SOF_SSP_COMMON); +EXPORT_SYMBOL_NS(snd_soc_acpi_intel_detect_codec_type, SND_SOC_ACPI_INTEL_SSP_COMMON); enum snd_soc_acpi_intel_codec snd_soc_acpi_intel_detect_amp_type(struct device *dev) @@ -96,7 +96,7 @@ snd_soc_acpi_intel_detect_amp_type(struct device *dev) return CODEC_NONE; } -EXPORT_SYMBOL_NS(snd_soc_acpi_intel_detect_amp_type, SND_SOC_INTEL_SOF_SSP_COMMON); +EXPORT_SYMBOL_NS(snd_soc_acpi_intel_detect_amp_type, SND_SOC_ACPI_INTEL_SSP_COMMON); const char * snd_soc_acpi_intel_get_codec_name(enum snd_soc_acpi_intel_codec codec_type) @@ -118,7 +118,7 @@ snd_soc_acpi_intel_get_codec_name(enum snd_soc_acpi_intel_codec codec_type) return NULL; } -EXPORT_SYMBOL_NS(snd_soc_acpi_intel_get_codec_name, SND_SOC_INTEL_SOF_SSP_COMMON); +EXPORT_SYMBOL_NS(snd_soc_acpi_intel_get_codec_name, SND_SOC_ACPI_INTEL_SSP_COMMON); MODULE_DESCRIPTION("ASoC Intel SOF Common Machine Driver Helpers"); MODULE_AUTHOR("Brent Lu "); -- cgit v1.2.3 From fe2365c298b51dd08def916a3339a84ec2a1fd42 Mon Sep 17 00:00:00 2001 From: Brent Lu Date: Wed, 27 Mar 2024 11:23:55 -0500 Subject: ASoC: Intel: ssp-common: delete module Moving all code to snd-soc-acpi-intel-match module and remove the snd-soc-acpi-intel-ssp-common module. Reviewed-by: Bard Liao Signed-off-by: Brent Lu Signed-off-by: Pierre-Louis Bossart Link: https://msgid.link/r/20240327162408.63953-6-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/intel/Kconfig | 6 ------ sound/soc/intel/boards/Kconfig | 10 +++++----- sound/soc/intel/boards/sof_board_helpers.c | 2 +- sound/soc/intel/common/Makefile | 5 ++--- sound/soc/intel/common/soc-acpi-intel-ssp-common.c | 6 +++--- 5 files changed, 11 insertions(+), 18 deletions(-) diff --git a/sound/soc/intel/Kconfig b/sound/soc/intel/Kconfig index e17d1a517567..4b9e498e3303 100644 --- a/sound/soc/intel/Kconfig +++ b/sound/soc/intel/Kconfig @@ -197,12 +197,6 @@ config SND_SOC_ACPI_INTEL_MATCH # this option controls the compilation of ACPI matching tables and # helpers and is not meant to be selected by the user. -config SND_SOC_ACPI_INTEL_SSP_COMMON - tristate - select SND_SOC_ACPI if ACPI - # this option provides helpers to detect codec type and is not meant - # to be selected by the user. - endif ## SND_SOC_INTEL_SST_TOPLEVEL || SND_SOC_SOF_INTEL_TOPLEVEL config SND_SOC_INTEL_KEEMBAY diff --git a/sound/soc/intel/boards/Kconfig b/sound/soc/intel/boards/Kconfig index 4d6ef68da130..9f4a85513702 100644 --- a/sound/soc/intel/boards/Kconfig +++ b/sound/soc/intel/boards/Kconfig @@ -500,7 +500,7 @@ config SND_SOC_INTEL_SOF_RT5682_MACH select SND_SOC_INTEL_SOF_BOARD_HELPERS select SND_SOC_INTEL_SOF_MAXIM_COMMON select SND_SOC_INTEL_SOF_REALTEK_COMMON - select SND_SOC_ACPI_INTEL_SSP_COMMON + select SND_SOC_ACPI_INTEL_MATCH help This adds support for ASoC machine driver for SOF platforms with rt5650 or rt5682 codec. @@ -518,7 +518,7 @@ config SND_SOC_INTEL_SOF_CS42L42_MACH select SND_SOC_INTEL_HDA_DSP_COMMON select SND_SOC_INTEL_SOF_BOARD_HELPERS select SND_SOC_INTEL_SOF_MAXIM_COMMON - select SND_SOC_ACPI_INTEL_SSP_COMMON + select SND_SOC_ACPI_INTEL_MATCH help This adds support for ASoC machine driver for SOF platforms with cs42l42 codec. @@ -571,7 +571,7 @@ config SND_SOC_INTEL_SOF_NAU8825_MACH select SND_SOC_INTEL_SOF_MAXIM_COMMON select SND_SOC_INTEL_SOF_NUVOTON_COMMON select SND_SOC_INTEL_SOF_REALTEK_COMMON - select SND_SOC_ACPI_INTEL_SSP_COMMON + select SND_SOC_ACPI_INTEL_MATCH help This adds support for ASoC machine driver for SOF platforms with nau8825 codec. @@ -623,7 +623,7 @@ config SND_SOC_INTEL_SOF_DA7219_MACH select SND_SOC_DMIC select SND_SOC_INTEL_SOF_BOARD_HELPERS select SND_SOC_INTEL_SOF_MAXIM_COMMON - select SND_SOC_ACPI_INTEL_SSP_COMMON + select SND_SOC_ACPI_INTEL_MATCH help This adds support for ASoC machine driver for SOF platforms with Dialog DA7219 I2S audio codec. @@ -643,7 +643,7 @@ config SND_SOC_INTEL_SOF_SSP_AMP_MACH select SND_SOC_INTEL_SOF_BOARD_HELPERS select SND_SOC_INTEL_SOF_REALTEK_COMMON select SND_SOC_INTEL_SOF_CIRRUS_COMMON - select SND_SOC_ACPI_INTEL_SSP_COMMON + select SND_SOC_ACPI_INTEL_MATCH help This adds support for ASoC machine driver for SOF platforms with RT1308/CS35L41 I2S audio codec. diff --git a/sound/soc/intel/boards/sof_board_helpers.c b/sound/soc/intel/boards/sof_board_helpers.c index ba5be5423626..eb140e13153f 100644 --- a/sound/soc/intel/boards/sof_board_helpers.c +++ b/sound/soc/intel/boards/sof_board_helpers.c @@ -635,4 +635,4 @@ MODULE_DESCRIPTION("ASoC Intel SOF Machine Driver Board Helpers"); MODULE_AUTHOR("Brent Lu "); MODULE_LICENSE("GPL"); MODULE_IMPORT_NS(SND_SOC_INTEL_HDA_DSP_COMMON); -MODULE_IMPORT_NS(SND_SOC_ACPI_INTEL_SSP_COMMON); +MODULE_IMPORT_NS(SND_SOC_ACPI_INTEL_MATCH); diff --git a/sound/soc/intel/common/Makefile b/sound/soc/intel/common/Makefile index dcd552d815a2..a86457674726 100644 --- a/sound/soc/intel/common/Makefile +++ b/sound/soc/intel/common/Makefile @@ -15,8 +15,7 @@ snd-soc-acpi-intel-match-objs := soc-acpi-intel-byt-match.o soc-acpi-intel-cht-m soc-acpi-intel-hda-match.o \ soc-acpi-intel-sdw-mockup-match.o +snd-soc-acpi-intel-match-objs += soc-acpi-intel-ssp-common.o + obj-$(CONFIG_SND_SOC_INTEL_SST) += snd-soc-sst-dsp.o snd-soc-sst-ipc.o obj-$(CONFIG_SND_SOC_ACPI_INTEL_MATCH) += snd-soc-acpi-intel-match.o - -snd-soc-acpi-intel-ssp-common-objs += soc-acpi-intel-ssp-common.o -obj-$(CONFIG_SND_SOC_ACPI_INTEL_SSP_COMMON) += snd-soc-acpi-intel-ssp-common.o diff --git a/sound/soc/intel/common/soc-acpi-intel-ssp-common.c b/sound/soc/intel/common/soc-acpi-intel-ssp-common.c index 40b68c20a12a..68da7260fb1d 100644 --- a/sound/soc/intel/common/soc-acpi-intel-ssp-common.c +++ b/sound/soc/intel/common/soc-acpi-intel-ssp-common.c @@ -79,7 +79,7 @@ snd_soc_acpi_intel_detect_codec_type(struct device *dev) return CODEC_NONE; } -EXPORT_SYMBOL_NS(snd_soc_acpi_intel_detect_codec_type, SND_SOC_ACPI_INTEL_SSP_COMMON); +EXPORT_SYMBOL_NS(snd_soc_acpi_intel_detect_codec_type, SND_SOC_ACPI_INTEL_MATCH); enum snd_soc_acpi_intel_codec snd_soc_acpi_intel_detect_amp_type(struct device *dev) @@ -96,7 +96,7 @@ snd_soc_acpi_intel_detect_amp_type(struct device *dev) return CODEC_NONE; } -EXPORT_SYMBOL_NS(snd_soc_acpi_intel_detect_amp_type, SND_SOC_ACPI_INTEL_SSP_COMMON); +EXPORT_SYMBOL_NS(snd_soc_acpi_intel_detect_amp_type, SND_SOC_ACPI_INTEL_MATCH); const char * snd_soc_acpi_intel_get_codec_name(enum snd_soc_acpi_intel_codec codec_type) @@ -118,7 +118,7 @@ snd_soc_acpi_intel_get_codec_name(enum snd_soc_acpi_intel_codec codec_type) return NULL; } -EXPORT_SYMBOL_NS(snd_soc_acpi_intel_get_codec_name, SND_SOC_ACPI_INTEL_SSP_COMMON); +EXPORT_SYMBOL_NS(snd_soc_acpi_intel_get_codec_name, SND_SOC_ACPI_INTEL_MATCH); MODULE_DESCRIPTION("ASoC Intel SOF Common Machine Driver Helpers"); MODULE_AUTHOR("Brent Lu "); -- cgit v1.2.3 From 2e723a79ec609871116d216309c1b89d2f61b713 Mon Sep 17 00:00:00 2001 From: Brent Lu Date: Wed, 27 Mar 2024 11:23:56 -0500 Subject: ASoC: Intel: ssp-common: get codec tplg suffix function Add helper functions to get tplg suffix string for specific headphone codec or speaker amplifier. The string could be used to compose the default topology file name for specific headphone codec and speaker amplifier combination. Reviewed-by: Bard Liao Signed-off-by: Brent Lu Signed-off-by: Pierre-Louis Bossart Link: https://msgid.link/r/20240327162408.63953-7-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- include/sound/soc-acpi-intel-ssp-common.h | 5 ++ sound/soc/intel/common/soc-acpi-intel-ssp-common.c | 76 ++++++++++++++++------ 2 files changed, 60 insertions(+), 21 deletions(-) diff --git a/include/sound/soc-acpi-intel-ssp-common.h b/include/sound/soc-acpi-intel-ssp-common.h index b568cda11051..b4597c8dac78 100644 --- a/include/sound/soc-acpi-intel-ssp-common.h +++ b/include/sound/soc-acpi-intel-ssp-common.h @@ -73,4 +73,9 @@ snd_soc_acpi_intel_detect_amp_type(struct device *dev); const char * snd_soc_acpi_intel_get_codec_name(enum snd_soc_acpi_intel_codec codec_type); +const char * +snd_soc_acpi_intel_get_codec_tplg_suffix(enum snd_soc_acpi_intel_codec codec_type); +const char * +snd_soc_acpi_intel_get_amp_tplg_suffix(enum snd_soc_acpi_intel_codec codec_type); + #endif /* __LINUX_SND_SOC_ACPI_INTEL_SSP_COMMON_H */ diff --git a/sound/soc/intel/common/soc-acpi-intel-ssp-common.c b/sound/soc/intel/common/soc-acpi-intel-ssp-common.c index 68da7260fb1d..a887f019afe2 100644 --- a/sound/soc/intel/common/soc-acpi-intel-ssp-common.c +++ b/sound/soc/intel/common/soc-acpi-intel-ssp-common.c @@ -9,59 +9,61 @@ /* * Codec probe function */ -#define CODEC_MAP_ENTRY(n, h, t) \ +#define CODEC_MAP_ENTRY(n, s, h, t) \ { \ .name = n, \ + .tplg_suffix = s, \ .acpi_hid = h, \ .codec_type = t, \ } struct codec_map { const char *name; + const char *tplg_suffix; const char *acpi_hid; enum snd_soc_acpi_intel_codec codec_type; }; static const struct codec_map codecs[] = { /* Cirrus Logic */ - CODEC_MAP_ENTRY("CS42L42", CS42L42_ACPI_HID, CODEC_CS42L42), + CODEC_MAP_ENTRY("CS42L42", "cs42l42", CS42L42_ACPI_HID, CODEC_CS42L42), /* Dialog */ - CODEC_MAP_ENTRY("DA7219", DA7219_ACPI_HID, CODEC_DA7219), + CODEC_MAP_ENTRY("DA7219", "da7219", DA7219_ACPI_HID, CODEC_DA7219), /* Everest */ - CODEC_MAP_ENTRY("ES8316", ES8316_ACPI_HID, CODEC_ES8316), - CODEC_MAP_ENTRY("ES8326", ES8326_ACPI_HID, CODEC_ES8326), - CODEC_MAP_ENTRY("ES8336", ES8336_ACPI_HID, CODEC_ES8336), + CODEC_MAP_ENTRY("ES8316", "es8336", ES8316_ACPI_HID, CODEC_ES8316), + CODEC_MAP_ENTRY("ES8326", "es8336", ES8326_ACPI_HID, CODEC_ES8326), + CODEC_MAP_ENTRY("ES8336", "es8336", ES8336_ACPI_HID, CODEC_ES8336), /* Nuvoton */ - CODEC_MAP_ENTRY("NAU8825", NAU8825_ACPI_HID, CODEC_NAU8825), + CODEC_MAP_ENTRY("NAU8825", "nau8825", NAU8825_ACPI_HID, CODEC_NAU8825), /* Realtek */ - CODEC_MAP_ENTRY("RT5650", RT5650_ACPI_HID, CODEC_RT5650), - CODEC_MAP_ENTRY("RT5682", RT5682_ACPI_HID, CODEC_RT5682), - CODEC_MAP_ENTRY("RT5682S", RT5682S_ACPI_HID, CODEC_RT5682S), + CODEC_MAP_ENTRY("RT5650", "rt5650", RT5650_ACPI_HID, CODEC_RT5650), + CODEC_MAP_ENTRY("RT5682", "rt5682", RT5682_ACPI_HID, CODEC_RT5682), + CODEC_MAP_ENTRY("RT5682S", "rt5682", RT5682S_ACPI_HID, CODEC_RT5682S), }; static const struct codec_map amps[] = { /* Cirrus Logic */ - CODEC_MAP_ENTRY("CS35L41", CS35L41_ACPI_HID, CODEC_CS35L41), + CODEC_MAP_ENTRY("CS35L41", "cs35l41", CS35L41_ACPI_HID, CODEC_CS35L41), /* Maxim */ - CODEC_MAP_ENTRY("MAX98357A", MAX_98357A_ACPI_HID, CODEC_MAX98357A), - CODEC_MAP_ENTRY("MAX98360A", MAX_98360A_ACPI_HID, CODEC_MAX98360A), - CODEC_MAP_ENTRY("MAX98373", MAX_98373_ACPI_HID, CODEC_MAX98373), - CODEC_MAP_ENTRY("MAX98390", MAX_98390_ACPI_HID, CODEC_MAX98390), + CODEC_MAP_ENTRY("MAX98357A", "max98357a", MAX_98357A_ACPI_HID, CODEC_MAX98357A), + CODEC_MAP_ENTRY("MAX98360A", "max98360a", MAX_98360A_ACPI_HID, CODEC_MAX98360A), + CODEC_MAP_ENTRY("MAX98373", "max98373", MAX_98373_ACPI_HID, CODEC_MAX98373), + CODEC_MAP_ENTRY("MAX98390", "max98390", MAX_98390_ACPI_HID, CODEC_MAX98390), /* Nuvoton */ - CODEC_MAP_ENTRY("NAU8318", NAU8318_ACPI_HID, CODEC_NAU8318), + CODEC_MAP_ENTRY("NAU8318", "nau8318", NAU8318_ACPI_HID, CODEC_NAU8318), /* Realtek */ - CODEC_MAP_ENTRY("RT1011", RT1011_ACPI_HID, CODEC_RT1011), - CODEC_MAP_ENTRY("RT1015", RT1015_ACPI_HID, CODEC_RT1015), - CODEC_MAP_ENTRY("RT1015P", RT1015P_ACPI_HID, CODEC_RT1015P), - CODEC_MAP_ENTRY("RT1019P", RT1019P_ACPI_HID, CODEC_RT1019P), - CODEC_MAP_ENTRY("RT1308", RT1308_ACPI_HID, CODEC_RT1308), + CODEC_MAP_ENTRY("RT1011", "rt1011", RT1011_ACPI_HID, CODEC_RT1011), + CODEC_MAP_ENTRY("RT1015", "rt1015", RT1015_ACPI_HID, CODEC_RT1015), + CODEC_MAP_ENTRY("RT1015P", "rt1015", RT1015P_ACPI_HID, CODEC_RT1015P), + CODEC_MAP_ENTRY("RT1019P", "rt1019", RT1019P_ACPI_HID, CODEC_RT1019P), + CODEC_MAP_ENTRY("RT1308", "rt1308", RT1308_ACPI_HID, CODEC_RT1308), }; enum snd_soc_acpi_intel_codec @@ -120,6 +122,38 @@ snd_soc_acpi_intel_get_codec_name(enum snd_soc_acpi_intel_codec codec_type) } EXPORT_SYMBOL_NS(snd_soc_acpi_intel_get_codec_name, SND_SOC_ACPI_INTEL_MATCH); +const char * +snd_soc_acpi_intel_get_codec_tplg_suffix(enum snd_soc_acpi_intel_codec codec_type) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(codecs); i++) { + if (codecs[i].codec_type != codec_type) + continue; + + return codecs[i].tplg_suffix; + } + + return NULL; +} +EXPORT_SYMBOL_NS(snd_soc_acpi_intel_get_codec_tplg_suffix, SND_SOC_ACPI_INTEL_MATCH); + +const char * +snd_soc_acpi_intel_get_amp_tplg_suffix(enum snd_soc_acpi_intel_codec codec_type) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(amps); i++) { + if (amps[i].codec_type != codec_type) + continue; + + return amps[i].tplg_suffix; + } + + return NULL; +} +EXPORT_SYMBOL_NS(snd_soc_acpi_intel_get_amp_tplg_suffix, SND_SOC_ACPI_INTEL_MATCH); + MODULE_DESCRIPTION("ASoC Intel SOF Common Machine Driver Helpers"); MODULE_AUTHOR("Brent Lu "); MODULE_LICENSE("GPL"); -- cgit v1.2.3 From 1504a768f6045157437693fbfb50ae63ca86ec61 Mon Sep 17 00:00:00 2001 From: Brent Lu Date: Wed, 27 Mar 2024 11:23:57 -0500 Subject: ASoC: SOF: Intel: support tplg suffix detection Add new flags to tplg_quirk_mask to detect and append codec/amplifier tplg suffix to topology file name at runtime. With this feature we could implement an enumeration entry for all boards which implement same headphone codec regardless the speaker amplifier type. Reviewed-by: Bard Liao Signed-off-by: Brent Lu Signed-off-by: Pierre-Louis Bossart Link: https://msgid.link/r/20240327162408.63953-8-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- include/sound/soc-acpi.h | 12 +++++++ sound/soc/sof/intel/hda.c | 82 +++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 94 insertions(+) diff --git a/include/sound/soc-acpi.h b/include/sound/soc-acpi.h index 23d6d6bfb073..1d8f35ca1d6f 100644 --- a/include/sound/soc-acpi.h +++ b/include/sound/soc-acpi.h @@ -151,6 +151,18 @@ struct snd_soc_acpi_link_adr { */ #define SND_SOC_ACPI_TPLG_INTEL_DMIC_NUMBER BIT(2) +/* + * when set the speaker amplifier name suffix (i.e. "-max98360a") will be + * appended to topology file name + */ +#define SND_SOC_ACPI_TPLG_INTEL_AMP_NAME BIT(3) + +/* + * when set the headphone codec name suffix (i.e. "-rt5682") will be appended to + * topology file name + */ +#define SND_SOC_ACPI_TPLG_INTEL_CODEC_NAME BIT(4) + /** * snd_soc_acpi_mach: ACPI-based machine descriptor. Most of the fields are * related to the hardware, except for the firmware and topology file names. diff --git a/sound/soc/sof/intel/hda.c b/sound/soc/sof/intel/hda.c index 7fe72b065451..e26b8fd682e5 100644 --- a/sound/soc/sof/intel/hda.c +++ b/sound/soc/sof/intel/hda.c @@ -24,6 +24,7 @@ #include #include #include +#include #include #include #include @@ -1676,13 +1677,36 @@ void hda_set_mach_params(struct snd_soc_acpi_mach *mach, mach_params->dai_drivers = desc->ops->drv; } +static int check_tplg_quirk_mask(struct snd_soc_acpi_mach *mach) +{ + u32 dmic_ssp_quirk; + u32 codec_amp_name_quirk; + + /* + * In current implementation dmic and ssp quirks are designed for es8336 + * machine driver and could not be mixed with codec name and amp name + * quirks. + */ + dmic_ssp_quirk = mach->tplg_quirk_mask & + (SND_SOC_ACPI_TPLG_INTEL_DMIC_NUMBER | SND_SOC_ACPI_TPLG_INTEL_SSP_NUMBER); + codec_amp_name_quirk = mach->tplg_quirk_mask & + (SND_SOC_ACPI_TPLG_INTEL_AMP_NAME | SND_SOC_ACPI_TPLG_INTEL_CODEC_NAME); + + if (dmic_ssp_quirk && codec_amp_name_quirk) + return -EINVAL; + + return 0; +} + struct snd_soc_acpi_mach *hda_machine_select(struct snd_sof_dev *sdev) { u32 interface_mask = hda_get_interface_mask(sdev); struct snd_sof_pdata *sof_pdata = sdev->pdata; const struct sof_dev_desc *desc = sof_pdata->desc; struct snd_soc_acpi_mach *mach = NULL; + enum snd_soc_acpi_intel_codec codec_type; const char *tplg_filename; + const char *tplg_suffix; /* Try I2S or DMIC if it is supported */ if (interface_mask & (BIT(SOF_DAI_INTEL_SSP) | BIT(SOF_DAI_INTEL_DMIC))) @@ -1701,6 +1725,17 @@ struct snd_soc_acpi_mach *hda_machine_select(struct snd_sof_dev *sdev) tplg_fixup = true; } + /* + * Checking quirk mask integrity; some quirk flags could not be + * set concurrently. + */ + if (tplg_fixup && + check_tplg_quirk_mask(mach)) { + dev_err(sdev->dev, "Invalid tplg quirk mask 0x%x\n", + mach->tplg_quirk_mask); + return NULL; + } + /* report to machine driver if any DMICs are found */ mach->mach_params.dmic_num = check_dmic_num(sdev); @@ -1775,6 +1810,52 @@ struct snd_soc_acpi_mach *hda_machine_select(struct snd_sof_dev *sdev) } } + codec_type = snd_soc_acpi_intel_detect_amp_type(sdev->dev); + + if (tplg_fixup && + mach->tplg_quirk_mask & SND_SOC_ACPI_TPLG_INTEL_AMP_NAME && + codec_type != CODEC_NONE) { + tplg_suffix = snd_soc_acpi_intel_get_amp_tplg_suffix(codec_type); + if (!tplg_suffix) { + dev_err(sdev->dev, "no tplg suffix found, amp %d\n", + codec_type); + return NULL; + } + + tplg_filename = devm_kasprintf(sdev->dev, GFP_KERNEL, + "%s-%s", + sof_pdata->tplg_filename, + tplg_suffix); + if (!tplg_filename) + return NULL; + + sof_pdata->tplg_filename = tplg_filename; + add_extension = true; + } + + codec_type = snd_soc_acpi_intel_detect_codec_type(sdev->dev); + + if (tplg_fixup && + mach->tplg_quirk_mask & SND_SOC_ACPI_TPLG_INTEL_CODEC_NAME && + codec_type != CODEC_NONE) { + tplg_suffix = snd_soc_acpi_intel_get_codec_tplg_suffix(codec_type); + if (!tplg_suffix) { + dev_err(sdev->dev, "no tplg suffix found, codec %d\n", + codec_type); + return NULL; + } + + tplg_filename = devm_kasprintf(sdev->dev, GFP_KERNEL, + "%s-%s", + sof_pdata->tplg_filename, + tplg_suffix); + if (!tplg_filename) + return NULL; + + sof_pdata->tplg_filename = tplg_filename; + add_extension = true; + } + if (tplg_fixup && add_extension) { tplg_filename = devm_kasprintf(sdev->dev, GFP_KERNEL, "%s%s", @@ -1842,3 +1923,4 @@ MODULE_IMPORT_NS(SND_INTEL_SOUNDWIRE_ACPI); MODULE_IMPORT_NS(SOUNDWIRE_INTEL_INIT); MODULE_IMPORT_NS(SOUNDWIRE_INTEL); MODULE_IMPORT_NS(SND_SOC_SOF_HDA_MLINK); +MODULE_IMPORT_NS(SND_SOC_ACPI_INTEL_MATCH); -- cgit v1.2.3 From 1934906b26bf8d1bd798fa11bf7058bf380101a0 Mon Sep 17 00:00:00 2001 From: Brent Lu Date: Wed, 27 Mar 2024 11:23:58 -0500 Subject: ASoC: Intel: sof_nau8825: mach cleanup for adl boards Add a common entry in enumeration table for all nau8825 boards with/without speaker amplifier. All other adl_nau8825_def entries become redundant so get removed. Reviewed-by: Bard Liao Signed-off-by: Brent Lu Signed-off-by: Pierre-Louis Bossart Link: https://msgid.link/r/20240327162408.63953-9-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/intel/common/soc-acpi-intel-adl-match.c | 54 +++++------------------ 1 file changed, 11 insertions(+), 43 deletions(-) diff --git a/sound/soc/intel/common/soc-acpi-intel-adl-match.c b/sound/soc/intel/common/soc-acpi-intel-adl-match.c index 7ce8aade07d7..f8b8864b5ec6 100644 --- a/sound/soc/intel/common/soc-acpi-intel-adl-match.c +++ b/sound/soc/intel/common/soc-acpi-intel-adl-match.c @@ -7,6 +7,7 @@ #include #include +#include static const struct snd_soc_acpi_codecs essx_83x6 = { .num_codecs = 3, @@ -467,11 +468,6 @@ static const struct snd_soc_acpi_codecs adl_rt5682_rt5682s_hp = { .codecs = {"10EC5682", "RTL5682"}, }; -static const struct snd_soc_acpi_codecs adl_rt1015p_amp = { - .num_codecs = 1, - .codecs = {"RTL1015"} -}; - static const struct snd_soc_acpi_codecs adl_rt1019p_amp = { .num_codecs = 1, .codecs = {"RTL1019"} @@ -487,11 +483,6 @@ static const struct snd_soc_acpi_codecs adl_lt6911_hdmi = { .codecs = {"INTC10B0"} }; -static const struct snd_soc_acpi_codecs adl_nau8318_amp = { - .num_codecs = 1, - .codecs = {"NVTN2012"} -}; - static struct snd_soc_acpi_codecs adl_rt5650_amp = { .num_codecs = 1, .codecs = {"10EC5650"} @@ -526,20 +517,6 @@ struct snd_soc_acpi_mach snd_soc_acpi_intel_adl_machines[] = { .quirk_data = &adl_rt1019p_amp, .sof_tplg_filename = "sof-adl-rt1019-nau8825.tplg", }, - { - .id = "10508825", - .drv_name = "adl_nau8825_def", - .machine_quirk = snd_soc_acpi_codec_list, - .quirk_data = &adl_max98373_amp, - .sof_tplg_filename = "sof-adl-max98373-nau8825.tplg", - }, - { - .id = "10508825", - .drv_name = "adl_nau8825_def", - .machine_quirk = snd_soc_acpi_codec_list, - .quirk_data = &adl_max98360a_amp, - .sof_tplg_filename = "sof-adl-max98360a-nau8825.tplg", - }, { .comp_ids = &adl_rt5682_rt5682s_hp, .drv_name = "adl_rt5682_def", @@ -547,25 +524,6 @@ struct snd_soc_acpi_mach snd_soc_acpi_intel_adl_machines[] = { .quirk_data = &adl_rt1019p_amp, .sof_tplg_filename = "sof-adl-rt1019-rt5682.tplg", }, - { - .id = "10508825", - .drv_name = "adl_nau8825_def", - .machine_quirk = snd_soc_acpi_codec_list, - .quirk_data = &adl_rt1015p_amp, - .sof_tplg_filename = "sof-adl-rt1015-nau8825.tplg", - }, - { - .id = "10508825", - .drv_name = "adl_nau8825_def", - .machine_quirk = snd_soc_acpi_codec_list, - .quirk_data = &adl_nau8318_amp, - .sof_tplg_filename = "sof-adl-nau8318-nau8825.tplg", - }, - { - .id = "10508825", - .drv_name = "adl_nau8825_def", - .sof_tplg_filename = "sof-adl-nau8825.tplg", - }, { .comp_ids = &adl_rt5682_rt5682s_hp, .drv_name = "adl_rt5682_def", @@ -621,6 +579,16 @@ struct snd_soc_acpi_mach snd_soc_acpi_intel_adl_machines[] = { .quirk_data = &adl_max98360a_amp, .sof_tplg_filename = "sof-adl-max98360a-da7219.tplg", }, + /* place boards for each headphone codec: sof driver will complete the + * tplg name and machine driver will detect the amp type + */ + { + .id = NAU8825_ACPI_HID, + .drv_name = "adl_nau8825_def", + .sof_tplg_filename = "sof-adl", /* the tplg suffix is added at run time */ + .tplg_quirk_mask = SND_SOC_ACPI_TPLG_INTEL_AMP_NAME | + SND_SOC_ACPI_TPLG_INTEL_CODEC_NAME, + }, /* place amp-only boards in the end of table */ { .id = "CSC3541", -- cgit v1.2.3 From 3822d41469fc20fdff0d83b20324b382ee7bd0e7 Mon Sep 17 00:00:00 2001 From: Brent Lu Date: Wed, 27 Mar 2024 11:23:59 -0500 Subject: ASoC: Intel: sof_nau8825: mach cleanup for rpl boards Add a common entry in enumeration table for all nau8825 boards with/without speaker amplifier. All other rpl_nau8825_def entries become redundant so get removed. Reviewed-by: Bard Liao Signed-off-by: Brent Lu Signed-off-by: Pierre-Louis Bossart Link: https://msgid.link/r/20240327162408.63953-10-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/intel/common/soc-acpi-intel-rpl-match.c | 43 +++++++---------------- 1 file changed, 12 insertions(+), 31 deletions(-) diff --git a/sound/soc/intel/common/soc-acpi-intel-rpl-match.c b/sound/soc/intel/common/soc-acpi-intel-rpl-match.c index 77c917897c8d..44be9077b4e0 100644 --- a/sound/soc/intel/common/soc-acpi-intel-rpl-match.c +++ b/sound/soc/intel/common/soc-acpi-intel-rpl-match.c @@ -7,6 +7,7 @@ #include #include +#include static const struct snd_soc_acpi_endpoint single_endpoint = { .num = 0, @@ -365,21 +366,11 @@ static const struct snd_soc_acpi_codecs rpl_max98360a_amp = { .codecs = {"MX98360A"}, }; -static const struct snd_soc_acpi_codecs rpl_max98373_amp = { - .num_codecs = 1, - .codecs = {"MX98373"} -}; - static const struct snd_soc_acpi_codecs rpl_lt6911_hdmi = { .num_codecs = 1, .codecs = {"INTC10B0"} }; -static const struct snd_soc_acpi_codecs rpl_nau8318_amp = { - .num_codecs = 1, - .codecs = {"NVTN2012"} -}; - static const struct snd_soc_acpi_codecs rpl_rt1019p_amp = { .num_codecs = 1, .codecs = {"RTL1019"} @@ -400,27 +391,6 @@ struct snd_soc_acpi_mach snd_soc_acpi_intel_rpl_machines[] = { .quirk_data = &rpl_max98360a_amp, .sof_tplg_filename = "sof-rpl-max98360a-rt5682.tplg", }, - { - .id = "10508825", - .drv_name = "rpl_nau8825_def", - .machine_quirk = snd_soc_acpi_codec_list, - .quirk_data = &rpl_max98373_amp, - .sof_tplg_filename = "sof-rpl-max98373-nau8825.tplg", - }, - { - .id = "10508825", - .drv_name = "rpl_nau8825_def", - .machine_quirk = snd_soc_acpi_codec_list, - .quirk_data = &rpl_max98360a_amp, - .sof_tplg_filename = "sof-rpl-max98360a-nau8825.tplg", - }, - { - .id = "10508825", - .drv_name = "rpl_nau8825_def", - .machine_quirk = snd_soc_acpi_codec_list, - .quirk_data = &rpl_nau8318_amp, - .sof_tplg_filename = "sof-rpl-nau8318-nau8825.tplg", - }, { .comp_ids = &rpl_rt5682_hp, .drv_name = "rpl_rt5682_def", @@ -450,6 +420,17 @@ struct snd_soc_acpi_mach snd_soc_acpi_intel_rpl_machines[] = { SND_SOC_ACPI_TPLG_INTEL_SSP_MSB | SND_SOC_ACPI_TPLG_INTEL_DMIC_NUMBER, }, + /* place boards for each headphone codec: sof driver will complete the + * tplg name and machine driver will detect the amp type + */ + { + .id = NAU8825_ACPI_HID, + .drv_name = "rpl_nau8825_def", + .sof_tplg_filename = "sof-rpl", /* the tplg suffix is added at run time */ + .tplg_quirk_mask = SND_SOC_ACPI_TPLG_INTEL_AMP_NAME | + SND_SOC_ACPI_TPLG_INTEL_CODEC_NAME, + }, + /* place amp-only boards in the end of table */ { .id = "INTC10B0", .drv_name = "rpl_lt6911_hdmi_ssp", -- cgit v1.2.3 From d5dd7f4fc0b5633fc9fb665803f5e95d564c7331 Mon Sep 17 00:00:00 2001 From: Brent Lu Date: Wed, 27 Mar 2024 11:24:00 -0500 Subject: ASoC: Intel: sof_nau8825: add mtl_nau8825_def for mtl boards Add the board config mtl_nau8825_def to nau8825 machine driver for all mtl boards using default SSP port allocation (headphone codec on SSP2, speaker amplifiers on SSP0, and BT offload on SSP1). Reviewed-by: Bard Liao Signed-off-by: Brent Lu Signed-off-by: Pierre-Louis Bossart Link: https://msgid.link/r/20240327162408.63953-11-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/intel/boards/sof_nau8825.c | 7 +++++++ sound/soc/intel/common/soc-acpi-intel-mtl-match.c | 11 +++++++++++ 2 files changed, 18 insertions(+) diff --git a/sound/soc/intel/boards/sof_nau8825.c b/sound/soc/intel/boards/sof_nau8825.c index 23fe8b4015cc..fe5f9e8dd652 100644 --- a/sound/soc/intel/boards/sof_nau8825.c +++ b/sound/soc/intel/boards/sof_nau8825.c @@ -319,6 +319,13 @@ static const struct platform_device_id board_ids[] = { SOF_SSP_PORT_BT_OFFLOAD(2) | SOF_BT_OFFLOAD_PRESENT), }, + { + .name = "mtl_nau8825_def", + .driver_data = (kernel_ulong_t)(SOF_SSP_PORT_CODEC(2) | + SOF_SSP_PORT_AMP(0) | + SOF_SSP_PORT_BT_OFFLOAD(1) | + SOF_BT_OFFLOAD_PRESENT), + }, { } }; MODULE_DEVICE_TABLE(platform, board_ids); diff --git a/sound/soc/intel/common/soc-acpi-intel-mtl-match.c b/sound/soc/intel/common/soc-acpi-intel-mtl-match.c index 27d1313e6686..0125e81af9e1 100644 --- a/sound/soc/intel/common/soc-acpi-intel-mtl-match.c +++ b/sound/soc/intel/common/soc-acpi-intel-mtl-match.c @@ -8,6 +8,7 @@ #include #include +#include #include "soc-acpi-intel-sdw-mockup-match.h" static const struct snd_soc_acpi_codecs mtl_max98357a_amp = { @@ -89,6 +90,16 @@ struct snd_soc_acpi_mach snd_soc_acpi_intel_mtl_machines[] = { .quirk_data = &mtl_rt5650_amp, .sof_tplg_filename = "sof-mtl-rt5650.tplg", }, + /* place boards for each headphone codec: sof driver will complete the + * tplg name and machine driver will detect the amp type + */ + { + .id = NAU8825_ACPI_HID, + .drv_name = "mtl_nau8825_def", + .sof_tplg_filename = "sof-mtl", /* the tplg suffix is added at run time */ + .tplg_quirk_mask = SND_SOC_ACPI_TPLG_INTEL_AMP_NAME | + SND_SOC_ACPI_TPLG_INTEL_CODEC_NAME, + }, /* place amp-only boards in the end of table */ { .id = "INTC10B0", -- cgit v1.2.3 From 4b95706b4a25c239aa7a7d7feb455c364c181db2 Mon Sep 17 00:00:00 2001 From: Brent Lu Date: Wed, 27 Mar 2024 11:24:01 -0500 Subject: ASoC: Intel: sof_rt5682: mach cleanup for tgl boards Add a common entry in enumeration table for all rt5682 boards with/without speaker amplifier. All other tgl_rt5682_def entries become redundant so get removed. Reviewed-by: Bard Liao Signed-off-by: Brent Lu Signed-off-by: Pierre-Louis Bossart Link: https://msgid.link/r/20240327162408.63953-12-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/intel/common/soc-acpi-intel-tgl-match.c | 50 ++++++----------------- 1 file changed, 13 insertions(+), 37 deletions(-) diff --git a/sound/soc/intel/common/soc-acpi-intel-tgl-match.c b/sound/soc/intel/common/soc-acpi-intel-tgl-match.c index 77226d1eb1cf..161ba532d270 100644 --- a/sound/soc/intel/common/soc-acpi-intel-tgl-match.c +++ b/sound/soc/intel/common/soc-acpi-intel-tgl-match.c @@ -8,6 +8,7 @@ #include #include +#include #include "soc-acpi-intel-sdw-mockup-match.h" static const struct snd_soc_acpi_codecs essx_83x6 = { @@ -15,11 +16,6 @@ static const struct snd_soc_acpi_codecs essx_83x6 = { .codecs = { "ESSX8316", "ESSX8326", "ESSX8336"}, }; -static const struct snd_soc_acpi_codecs tgl_codecs = { - .num_codecs = 1, - .codecs = {"MX98357A"} -}; - static const struct snd_soc_acpi_endpoint single_endpoint = { .num = 0, .aggregated = 0, @@ -499,19 +495,9 @@ static const struct snd_soc_acpi_link_adr tgl_cs42l43_cs35l56[] = { {} }; -static const struct snd_soc_acpi_codecs tgl_max98373_amp = { - .num_codecs = 1, - .codecs = {"MX98373"} -}; - -static const struct snd_soc_acpi_codecs tgl_rt1011_amp = { - .num_codecs = 1, - .codecs = {"10EC1011"} -}; - static const struct snd_soc_acpi_codecs tgl_rt5682_rt5682s_hp = { .num_codecs = 2, - .codecs = {"10EC5682", "RTL5682"}, + .codecs = {RT5682_ACPI_HID, RT5682S_ACPI_HID}, }; static const struct snd_soc_acpi_codecs tgl_lt6911_hdmi = { @@ -520,27 +506,6 @@ static const struct snd_soc_acpi_codecs tgl_lt6911_hdmi = { }; struct snd_soc_acpi_mach snd_soc_acpi_intel_tgl_machines[] = { - { - .comp_ids = &tgl_rt5682_rt5682s_hp, - .drv_name = "tgl_rt5682_def", - .machine_quirk = snd_soc_acpi_codec_list, - .quirk_data = &tgl_codecs, - .sof_tplg_filename = "sof-tgl-max98357a-rt5682.tplg", - }, - { - .comp_ids = &tgl_rt5682_rt5682s_hp, - .drv_name = "tgl_rt5682_def", - .machine_quirk = snd_soc_acpi_codec_list, - .quirk_data = &tgl_max98373_amp, - .sof_tplg_filename = "sof-tgl-max98373-rt5682.tplg", - }, - { - .comp_ids = &tgl_rt5682_rt5682s_hp, - .drv_name = "tgl_rt5682_def", - .machine_quirk = snd_soc_acpi_codec_list, - .quirk_data = &tgl_rt1011_amp, - .sof_tplg_filename = "sof-tgl-rt1011-rt5682.tplg", - }, { .comp_ids = &essx_83x6, .drv_name = "sof-essx8336", @@ -549,6 +514,17 @@ struct snd_soc_acpi_mach snd_soc_acpi_intel_tgl_machines[] = { SND_SOC_ACPI_TPLG_INTEL_SSP_MSB | SND_SOC_ACPI_TPLG_INTEL_DMIC_NUMBER, }, + /* place boards for each headphone codec: sof driver will complete the + * tplg name and machine driver will detect the amp type + */ + { + .comp_ids = &tgl_rt5682_rt5682s_hp, + .drv_name = "tgl_rt5682_def", + .sof_tplg_filename = "sof-tgl", /* the tplg suffix is added at run time */ + .tplg_quirk_mask = SND_SOC_ACPI_TPLG_INTEL_AMP_NAME | + SND_SOC_ACPI_TPLG_INTEL_CODEC_NAME, + }, + /* place amp-only boards in the end of table */ { .id = "10EC1308", .drv_name = "tgl_rt1308_hdmi_ssp", -- cgit v1.2.3 From 34f256537685437122c4d326266739dd3b3678c6 Mon Sep 17 00:00:00 2001 From: Brent Lu Date: Wed, 27 Mar 2024 11:24:02 -0500 Subject: ASoC: Intel: sof_rt5682: mach cleanup for adl boards Add two common entries in enumeration table for all rt5682/rt5650 boards with/without speaker amplifier. All other adl_rt5682_def entries become redundant so get removed. Reviewed-by: Bard Liao Signed-off-by: Brent Lu Signed-off-by: Pierre-Louis Bossart Link: https://msgid.link/r/20240327162408.63953-13-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/intel/common/soc-acpi-intel-adl-match.c | 71 +++++------------------ 1 file changed, 15 insertions(+), 56 deletions(-) diff --git a/sound/soc/intel/common/soc-acpi-intel-adl-match.c b/sound/soc/intel/common/soc-acpi-intel-adl-match.c index f8b8864b5ec6..9ac9310dd2be 100644 --- a/sound/soc/intel/common/soc-acpi-intel-adl-match.c +++ b/sound/soc/intel/common/soc-acpi-intel-adl-match.c @@ -448,11 +448,6 @@ static const struct snd_soc_acpi_link_adr adl_chromebook_base[] = { {} }; -static const struct snd_soc_acpi_codecs adl_max98373_amp = { - .num_codecs = 1, - .codecs = {"MX98373"} -}; - static const struct snd_soc_acpi_codecs adl_max98357a_amp = { .num_codecs = 1, .codecs = {"MX98357A"} @@ -465,7 +460,7 @@ static const struct snd_soc_acpi_codecs adl_max98360a_amp = { static const struct snd_soc_acpi_codecs adl_rt5682_rt5682s_hp = { .num_codecs = 2, - .codecs = {"10EC5682", "RTL5682"}, + .codecs = {RT5682_ACPI_HID, RT5682S_ACPI_HID}, }; static const struct snd_soc_acpi_codecs adl_rt1019p_amp = { @@ -473,29 +468,12 @@ static const struct snd_soc_acpi_codecs adl_rt1019p_amp = { .codecs = {"RTL1019"} }; -static const struct snd_soc_acpi_codecs adl_max98390_amp = { - .num_codecs = 1, - .codecs = {"MX98390"} -}; - static const struct snd_soc_acpi_codecs adl_lt6911_hdmi = { .num_codecs = 1, .codecs = {"INTC10B0"} }; -static struct snd_soc_acpi_codecs adl_rt5650_amp = { - .num_codecs = 1, - .codecs = {"10EC5650"} -}; - struct snd_soc_acpi_mach snd_soc_acpi_intel_adl_machines[] = { - { - .comp_ids = &adl_rt5682_rt5682s_hp, - .drv_name = "adl_rt5682_def", - .machine_quirk = snd_soc_acpi_codec_list, - .quirk_data = &adl_max98373_amp, - .sof_tplg_filename = "sof-adl-max98373-rt5682.tplg", - }, { .comp_ids = &adl_rt5682_rt5682s_hp, .drv_name = "adl_mx98357_rt5682", @@ -503,13 +481,6 @@ struct snd_soc_acpi_mach snd_soc_acpi_intel_adl_machines[] = { .quirk_data = &adl_max98357a_amp, .sof_tplg_filename = "sof-adl-max98357a-rt5682.tplg", }, - { - .comp_ids = &adl_rt5682_rt5682s_hp, - .drv_name = "adl_rt5682_def", - .machine_quirk = snd_soc_acpi_codec_list, - .quirk_data = &adl_max98360a_amp, - .sof_tplg_filename = "sof-adl-max98360a-rt5682.tplg", - }, { .id = "10508825", .drv_name = "adl_rt1019p_8825", @@ -517,20 +488,6 @@ struct snd_soc_acpi_mach snd_soc_acpi_intel_adl_machines[] = { .quirk_data = &adl_rt1019p_amp, .sof_tplg_filename = "sof-adl-rt1019-nau8825.tplg", }, - { - .comp_ids = &adl_rt5682_rt5682s_hp, - .drv_name = "adl_rt5682_def", - .machine_quirk = snd_soc_acpi_codec_list, - .quirk_data = &adl_rt1019p_amp, - .sof_tplg_filename = "sof-adl-rt1019-rt5682.tplg", - }, - { - .comp_ids = &adl_rt5682_rt5682s_hp, - .drv_name = "adl_rt5682_def", - .machine_quirk = snd_soc_acpi_codec_list, - .quirk_data = &adl_max98390_amp, - .sof_tplg_filename = "sof-adl-max98390-rt5682.tplg", - }, { .comp_ids = &adl_rt5682_rt5682s_hp, .drv_name = "adl_rt5682_c1_h02", @@ -538,11 +495,6 @@ struct snd_soc_acpi_mach snd_soc_acpi_intel_adl_machines[] = { .quirk_data = &adl_lt6911_hdmi, .sof_tplg_filename = "sof-adl-rt5682-ssp1-hdmi-ssp02.tplg", }, - { - .comp_ids = &adl_rt5682_rt5682s_hp, - .drv_name = "adl_rt5682_def", - .sof_tplg_filename = "sof-adl-rt5682.tplg", - }, { .id = "10134242", .drv_name = "adl_mx98360a_cs4242", @@ -565,13 +517,6 @@ struct snd_soc_acpi_mach snd_soc_acpi_intel_adl_machines[] = { SND_SOC_ACPI_TPLG_INTEL_SSP_MSB | SND_SOC_ACPI_TPLG_INTEL_DMIC_NUMBER, }, - { - .id = "10EC5650", - .drv_name = "adl_rt5682_def", - .machine_quirk = snd_soc_acpi_codec_list, - .quirk_data = &adl_rt5650_amp, - .sof_tplg_filename = "sof-adl-rt5650.tplg", - }, { .id = "DLGS7219", .drv_name = "adl_da7219_def", @@ -589,6 +534,20 @@ struct snd_soc_acpi_mach snd_soc_acpi_intel_adl_machines[] = { .tplg_quirk_mask = SND_SOC_ACPI_TPLG_INTEL_AMP_NAME | SND_SOC_ACPI_TPLG_INTEL_CODEC_NAME, }, + { + .id = RT5650_ACPI_HID, + .drv_name = "adl_rt5682_def", + .sof_tplg_filename = "sof-adl", /* the tplg suffix is added at run time */ + .tplg_quirk_mask = SND_SOC_ACPI_TPLG_INTEL_AMP_NAME | + SND_SOC_ACPI_TPLG_INTEL_CODEC_NAME, + }, + { + .comp_ids = &adl_rt5682_rt5682s_hp, + .drv_name = "adl_rt5682_def", + .sof_tplg_filename = "sof-adl", /* the tplg suffix is added at run time */ + .tplg_quirk_mask = SND_SOC_ACPI_TPLG_INTEL_AMP_NAME | + SND_SOC_ACPI_TPLG_INTEL_CODEC_NAME, + }, /* place amp-only boards in the end of table */ { .id = "CSC3541", -- cgit v1.2.3 From 7b24d86c845ce3b1c7bdd9175cd7c51aefe9ba46 Mon Sep 17 00:00:00 2001 From: Brent Lu Date: Wed, 27 Mar 2024 11:24:03 -0500 Subject: ASoC: Intel: sof_rt5682: mach cleanup for rpl boards Add two common entries in enumeration table for all rt5682/rt5650 boards with/without speaker amplifier. All other rpl_rt5682_def entries become redundant so get removed. Reviewed-by: Bard Liao Signed-off-by: Brent Lu Signed-off-by: Pierre-Louis Bossart Link: https://msgid.link/r/20240327162408.63953-14-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/intel/common/soc-acpi-intel-rpl-match.c | 40 +++++++++-------------- 1 file changed, 15 insertions(+), 25 deletions(-) diff --git a/sound/soc/intel/common/soc-acpi-intel-rpl-match.c b/sound/soc/intel/common/soc-acpi-intel-rpl-match.c index 44be9077b4e0..e28a21667780 100644 --- a/sound/soc/intel/common/soc-acpi-intel-rpl-match.c +++ b/sound/soc/intel/common/soc-acpi-intel-rpl-match.c @@ -348,7 +348,7 @@ static const struct snd_soc_acpi_link_adr rplp_crb[] = { static const struct snd_soc_acpi_codecs rpl_rt5682_hp = { .num_codecs = 2, - .codecs = {"10EC5682", "RTL5682"}, + .codecs = {RT5682_ACPI_HID, RT5682S_ACPI_HID}, }; static const struct snd_soc_acpi_codecs rpl_essx_83x6 = { @@ -371,11 +371,6 @@ static const struct snd_soc_acpi_codecs rpl_lt6911_hdmi = { .codecs = {"INTC10B0"} }; -static const struct snd_soc_acpi_codecs rpl_rt1019p_amp = { - .num_codecs = 1, - .codecs = {"RTL1019"} -}; - struct snd_soc_acpi_mach snd_soc_acpi_intel_rpl_machines[] = { { .comp_ids = &rpl_rt5682_hp, @@ -384,20 +379,6 @@ struct snd_soc_acpi_mach snd_soc_acpi_intel_rpl_machines[] = { .quirk_data = &rpl_max98357a_amp, .sof_tplg_filename = "sof-rpl-max98357a-rt5682.tplg", }, - { - .comp_ids = &rpl_rt5682_hp, - .drv_name = "rpl_rt5682_def", - .machine_quirk = snd_soc_acpi_codec_list, - .quirk_data = &rpl_max98360a_amp, - .sof_tplg_filename = "sof-rpl-max98360a-rt5682.tplg", - }, - { - .comp_ids = &rpl_rt5682_hp, - .drv_name = "rpl_rt5682_def", - .machine_quirk = snd_soc_acpi_codec_list, - .quirk_data = &rpl_rt1019p_amp, - .sof_tplg_filename = "sof-rpl-rt1019-rt5682.tplg", - }, { .comp_ids = &rpl_rt5682_hp, .drv_name = "rpl_rt5682_c1_h02", @@ -430,6 +411,20 @@ struct snd_soc_acpi_mach snd_soc_acpi_intel_rpl_machines[] = { .tplg_quirk_mask = SND_SOC_ACPI_TPLG_INTEL_AMP_NAME | SND_SOC_ACPI_TPLG_INTEL_CODEC_NAME, }, + { + .id = RT5650_ACPI_HID, + .drv_name = "rpl_rt5682_def", + .sof_tplg_filename = "sof-rpl", /* the tplg suffix is added at run time */ + .tplg_quirk_mask = SND_SOC_ACPI_TPLG_INTEL_AMP_NAME | + SND_SOC_ACPI_TPLG_INTEL_CODEC_NAME, + }, + { + .comp_ids = &rpl_rt5682_hp, + .drv_name = "rpl_rt5682_def", + .sof_tplg_filename = "sof-rpl", /* the tplg suffix is added at run time */ + .tplg_quirk_mask = SND_SOC_ACPI_TPLG_INTEL_AMP_NAME | + SND_SOC_ACPI_TPLG_INTEL_CODEC_NAME, + }, /* place amp-only boards in the end of table */ { .id = "INTC10B0", @@ -443,11 +438,6 @@ struct snd_soc_acpi_mach snd_soc_acpi_intel_rpl_machines[] = { .quirk_data = &rpl_max98360a_amp, .sof_tplg_filename = "sof-rpl-max98360a-da7219.tplg", }, - { - .id = "10EC5650", - .drv_name = "rpl_rt5682_def", - .sof_tplg_filename = "sof-rpl-rt5650.tplg", - }, {}, }; EXPORT_SYMBOL_GPL(snd_soc_acpi_intel_rpl_machines); -- cgit v1.2.3 From a2e678fe951c3820db705a2cb20ec0a32d752033 Mon Sep 17 00:00:00 2001 From: Brent Lu Date: Wed, 27 Mar 2024 11:24:04 -0500 Subject: ASoC: Intel: sof_rt5682: mach cleanup for mtl boards Add two common entries in enumeration table for all rt5682/rt5650 boards with/without speaker amplifier. All other mtl_rt5682_def entries become redundant so get removed. Reviewed-by: Bard Liao Signed-off-by: Brent Lu Signed-off-by: Pierre-Louis Bossart Link: https://msgid.link/r/20240327162408.63953-15-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/intel/common/soc-acpi-intel-mtl-match.c | 40 +++++++++-------------- 1 file changed, 15 insertions(+), 25 deletions(-) diff --git a/sound/soc/intel/common/soc-acpi-intel-mtl-match.c b/sound/soc/intel/common/soc-acpi-intel-mtl-match.c index 0125e81af9e1..7f422848a3ba 100644 --- a/sound/soc/intel/common/soc-acpi-intel-mtl-match.c +++ b/sound/soc/intel/common/soc-acpi-intel-mtl-match.c @@ -21,14 +21,9 @@ static const struct snd_soc_acpi_codecs mtl_max98360a_amp = { .codecs = {"MX98360A"} }; -static const struct snd_soc_acpi_codecs mtl_rt1019p_amp = { - .num_codecs = 1, - .codecs = {"RTL1019"} -}; - static const struct snd_soc_acpi_codecs mtl_rt5682_rt5682s_hp = { .num_codecs = 2, - .codecs = {"10EC5682", "RTL5682"}, + .codecs = {RT5682_ACPI_HID, RT5682S_ACPI_HID}, }; static const struct snd_soc_acpi_codecs mtl_essx_83x6 = { @@ -41,11 +36,6 @@ static const struct snd_soc_acpi_codecs mtl_lt6911_hdmi = { .codecs = {"INTC10B0"} }; -static const struct snd_soc_acpi_codecs mtl_rt5650_amp = { - .num_codecs = 1, - .codecs = {"10EC5650"} -}; - struct snd_soc_acpi_mach snd_soc_acpi_intel_mtl_machines[] = { { .comp_ids = &mtl_rt5682_rt5682s_hp, @@ -61,13 +51,6 @@ struct snd_soc_acpi_mach snd_soc_acpi_intel_mtl_machines[] = { .quirk_data = &mtl_max98360a_amp, .sof_tplg_filename = "sof-mtl-max98360a-rt5682.tplg", }, - { - .comp_ids = &mtl_rt5682_rt5682s_hp, - .drv_name = "mtl_rt5682_def", - .machine_quirk = snd_soc_acpi_codec_list, - .quirk_data = &mtl_rt1019p_amp, - .sof_tplg_filename = "sof-mtl-rt1019-rt5682.tplg", - }, { .comp_ids = &mtl_essx_83x6, .drv_name = "mtl_es83x6_c1_h02", @@ -83,13 +66,6 @@ struct snd_soc_acpi_mach snd_soc_acpi_intel_mtl_machines[] = { SND_SOC_ACPI_TPLG_INTEL_SSP_MSB | SND_SOC_ACPI_TPLG_INTEL_DMIC_NUMBER, }, - { - .id = "10EC5650", - .drv_name = "mtl_rt5682_def", - .machine_quirk = snd_soc_acpi_codec_list, - .quirk_data = &mtl_rt5650_amp, - .sof_tplg_filename = "sof-mtl-rt5650.tplg", - }, /* place boards for each headphone codec: sof driver will complete the * tplg name and machine driver will detect the amp type */ @@ -100,6 +76,20 @@ struct snd_soc_acpi_mach snd_soc_acpi_intel_mtl_machines[] = { .tplg_quirk_mask = SND_SOC_ACPI_TPLG_INTEL_AMP_NAME | SND_SOC_ACPI_TPLG_INTEL_CODEC_NAME, }, + { + .id = RT5650_ACPI_HID, + .drv_name = "mtl_rt5682_def", + .sof_tplg_filename = "sof-mtl", /* the tplg suffix is added at run time */ + .tplg_quirk_mask = SND_SOC_ACPI_TPLG_INTEL_AMP_NAME | + SND_SOC_ACPI_TPLG_INTEL_CODEC_NAME, + }, + { + .comp_ids = &mtl_rt5682_rt5682s_hp, + .drv_name = "mtl_rt5682_def", + .sof_tplg_filename = "sof-mtl", /* the tplg suffix is added at run time */ + .tplg_quirk_mask = SND_SOC_ACPI_TPLG_INTEL_AMP_NAME | + SND_SOC_ACPI_TPLG_INTEL_CODEC_NAME, + }, /* place amp-only boards in the end of table */ { .id = "INTC10B0", -- cgit v1.2.3 From 2872f3b5df54ac14adc5ea62241312d66bd001ba Mon Sep 17 00:00:00 2001 From: Brent Lu Date: Wed, 27 Mar 2024 11:24:05 -0500 Subject: ASoC: Intel: sof_cs42l42: board id cleanup for adl boards Introduce "adl_cs42l42_def" for adl boards which implement headphone codec on SSP0 and speaker amplifiers on SSP1. Reviewed-by: Bard Liao Signed-off-by: Brent Lu Signed-off-by: Pierre-Louis Bossart Link: https://msgid.link/r/20240327162408.63953-16-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/intel/boards/sof_cs42l42.c | 2 +- sound/soc/intel/common/soc-acpi-intel-adl-match.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/soc/intel/boards/sof_cs42l42.c b/sound/soc/intel/boards/sof_cs42l42.c index 40ecfeaa1d26..8a2833a0e3c5 100644 --- a/sound/soc/intel/boards/sof_cs42l42.c +++ b/sound/soc/intel/boards/sof_cs42l42.c @@ -263,7 +263,7 @@ static const struct platform_device_id board_ids[] = { SOF_SSP_PORT_AMP(1)), }, { - .name = "adl_mx98360a_cs4242", + .name = "adl_cs42l42_def", .driver_data = (kernel_ulong_t)(SOF_SSP_PORT_CODEC(0) | SOF_SSP_PORT_AMP(1) | SOF_NUM_IDISP_HDMI(4) | diff --git a/sound/soc/intel/common/soc-acpi-intel-adl-match.c b/sound/soc/intel/common/soc-acpi-intel-adl-match.c index 9ac9310dd2be..7977a6fb9a5c 100644 --- a/sound/soc/intel/common/soc-acpi-intel-adl-match.c +++ b/sound/soc/intel/common/soc-acpi-intel-adl-match.c @@ -497,7 +497,7 @@ struct snd_soc_acpi_mach snd_soc_acpi_intel_adl_machines[] = { }, { .id = "10134242", - .drv_name = "adl_mx98360a_cs4242", + .drv_name = "adl_cs42l42_def", .machine_quirk = snd_soc_acpi_codec_list, .quirk_data = &adl_max98360a_amp, .sof_tplg_filename = "sof-adl-max98360a-cs42l42.tplg", -- cgit v1.2.3 From ae33c9134d6e1a88c2e49422aee1474c03a53233 Mon Sep 17 00:00:00 2001 From: Brent Lu Date: Wed, 27 Mar 2024 11:24:06 -0500 Subject: ASoC: Intel: sof_cs42l42: mach cleanup for adl boards Add a common entry in enumeration table for all cs42l42 boards with/without speaker amplifier. All other adl_cs42l42_def entries become redundant so get removed. Reviewed-by: Bard Liao Signed-off-by: Brent Lu Signed-off-by: Pierre-Louis Bossart Link: https://msgid.link/r/20240327162408.63953-17-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/intel/common/soc-acpi-intel-adl-match.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/sound/soc/intel/common/soc-acpi-intel-adl-match.c b/sound/soc/intel/common/soc-acpi-intel-adl-match.c index 7977a6fb9a5c..1ea2d9c582ee 100644 --- a/sound/soc/intel/common/soc-acpi-intel-adl-match.c +++ b/sound/soc/intel/common/soc-acpi-intel-adl-match.c @@ -495,13 +495,6 @@ struct snd_soc_acpi_mach snd_soc_acpi_intel_adl_machines[] = { .quirk_data = &adl_lt6911_hdmi, .sof_tplg_filename = "sof-adl-rt5682-ssp1-hdmi-ssp02.tplg", }, - { - .id = "10134242", - .drv_name = "adl_cs42l42_def", - .machine_quirk = snd_soc_acpi_codec_list, - .quirk_data = &adl_max98360a_amp, - .sof_tplg_filename = "sof-adl-max98360a-cs42l42.tplg", - }, { .comp_ids = &essx_83x6, .drv_name = "adl_es83x6_c1_h02", @@ -527,6 +520,13 @@ struct snd_soc_acpi_mach snd_soc_acpi_intel_adl_machines[] = { /* place boards for each headphone codec: sof driver will complete the * tplg name and machine driver will detect the amp type */ + { + .id = CS42L42_ACPI_HID, + .drv_name = "adl_cs42l42_def", + .sof_tplg_filename = "sof-adl", /* the tplg suffix is added at run time */ + .tplg_quirk_mask = SND_SOC_ACPI_TPLG_INTEL_AMP_NAME | + SND_SOC_ACPI_TPLG_INTEL_CODEC_NAME, + }, { .id = NAU8825_ACPI_HID, .drv_name = "adl_nau8825_def", -- cgit v1.2.3 From 6d90e02ae8aa6bedf77110075e7eef3f24f6a8a3 Mon Sep 17 00:00:00 2001 From: Brent Lu Date: Wed, 27 Mar 2024 11:24:07 -0500 Subject: ASoC: Intel: sof_cs42l42: add rpl_cs42l42_def for rpl boards Add the board config rpl_cs42l42_def to cs42l42 machine driver for all rpl boards using default SSP port allocation (headphone codec on SSP0, speaker amplifiers on SSP1, and BT offload on SSP2). Reviewed-by: Bard Liao Signed-off-by: Brent Lu Signed-off-by: Pierre-Louis Bossart Link: https://msgid.link/r/20240327162408.63953-18-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/intel/boards/sof_cs42l42.c | 8 ++++++++ sound/soc/intel/common/soc-acpi-intel-rpl-match.c | 7 +++++++ 2 files changed, 15 insertions(+) diff --git a/sound/soc/intel/boards/sof_cs42l42.c b/sound/soc/intel/boards/sof_cs42l42.c index 8a2833a0e3c5..3fc76184bdb3 100644 --- a/sound/soc/intel/boards/sof_cs42l42.c +++ b/sound/soc/intel/boards/sof_cs42l42.c @@ -270,6 +270,14 @@ static const struct platform_device_id board_ids[] = { SOF_BT_OFFLOAD_PRESENT | SOF_SSP_PORT_BT_OFFLOAD(2)), }, + { + .name = "rpl_cs42l42_def", + .driver_data = (kernel_ulong_t)(SOF_SSP_PORT_CODEC(0) | + SOF_SSP_PORT_AMP(1) | + SOF_NUM_IDISP_HDMI(4) | + SOF_BT_OFFLOAD_PRESENT | + SOF_SSP_PORT_BT_OFFLOAD(2)), + }, { } }; MODULE_DEVICE_TABLE(platform, board_ids); diff --git a/sound/soc/intel/common/soc-acpi-intel-rpl-match.c b/sound/soc/intel/common/soc-acpi-intel-rpl-match.c index e28a21667780..34588db6138a 100644 --- a/sound/soc/intel/common/soc-acpi-intel-rpl-match.c +++ b/sound/soc/intel/common/soc-acpi-intel-rpl-match.c @@ -404,6 +404,13 @@ struct snd_soc_acpi_mach snd_soc_acpi_intel_rpl_machines[] = { /* place boards for each headphone codec: sof driver will complete the * tplg name and machine driver will detect the amp type */ + { + .id = CS42L42_ACPI_HID, + .drv_name = "rpl_cs42l42_def", + .sof_tplg_filename = "sof-rpl", /* the tplg suffix is added at run time */ + .tplg_quirk_mask = SND_SOC_ACPI_TPLG_INTEL_AMP_NAME | + SND_SOC_ACPI_TPLG_INTEL_CODEC_NAME, + }, { .id = NAU8825_ACPI_HID, .drv_name = "rpl_nau8825_def", -- cgit v1.2.3 From 57ad033ce09d4d0c866ac558fc3c4cf53cfb2599 Mon Sep 17 00:00:00 2001 From: Brent Lu Date: Wed, 27 Mar 2024 11:24:08 -0500 Subject: ASoC: Intel: sof_cs42l42: add mtl_cs42l42_def for mtl boards Add the board config mtl_cs42l42_def to cs42l42 machine driver for all mtl boards using default SSP port allocation (headphone codec on SSP2, speaker amplifiers on SSP0, and BT offload on SSP1). Reviewed-by: Bard Liao Signed-off-by: Brent Lu Signed-off-by: Pierre-Louis Bossart Link: https://msgid.link/r/20240327162408.63953-19-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/intel/boards/sof_cs42l42.c | 7 +++++++ sound/soc/intel/common/soc-acpi-intel-mtl-match.c | 7 +++++++ 2 files changed, 14 insertions(+) diff --git a/sound/soc/intel/boards/sof_cs42l42.c b/sound/soc/intel/boards/sof_cs42l42.c index 3fc76184bdb3..f4fee2ee0d63 100644 --- a/sound/soc/intel/boards/sof_cs42l42.c +++ b/sound/soc/intel/boards/sof_cs42l42.c @@ -278,6 +278,13 @@ static const struct platform_device_id board_ids[] = { SOF_BT_OFFLOAD_PRESENT | SOF_SSP_PORT_BT_OFFLOAD(2)), }, + { + .name = "mtl_cs42l42_def", + .driver_data = (kernel_ulong_t)(SOF_SSP_PORT_CODEC(2) | + SOF_SSP_PORT_AMP(0) | + SOF_BT_OFFLOAD_PRESENT | + SOF_SSP_PORT_BT_OFFLOAD(1)), + }, { } }; MODULE_DEVICE_TABLE(platform, board_ids); diff --git a/sound/soc/intel/common/soc-acpi-intel-mtl-match.c b/sound/soc/intel/common/soc-acpi-intel-mtl-match.c index 7f422848a3ba..75935b454e5d 100644 --- a/sound/soc/intel/common/soc-acpi-intel-mtl-match.c +++ b/sound/soc/intel/common/soc-acpi-intel-mtl-match.c @@ -69,6 +69,13 @@ struct snd_soc_acpi_mach snd_soc_acpi_intel_mtl_machines[] = { /* place boards for each headphone codec: sof driver will complete the * tplg name and machine driver will detect the amp type */ + { + .id = CS42L42_ACPI_HID, + .drv_name = "mtl_cs42l42_def", + .sof_tplg_filename = "sof-mtl", /* the tplg suffix is added at run time */ + .tplg_quirk_mask = SND_SOC_ACPI_TPLG_INTEL_AMP_NAME | + SND_SOC_ACPI_TPLG_INTEL_CODEC_NAME, + }, { .id = NAU8825_ACPI_HID, .drv_name = "mtl_nau8825_def", -- cgit v1.2.3 From cd25e15e57e68a6b18dc9323047fe9c68b99290b Mon Sep 17 00:00:00 2001 From: Joakim Sindholt Date: Mon, 18 Mar 2024 12:22:31 +0100 Subject: fs/9p: only translate RWX permissions for plain 9P2000 Garbage in plain 9P2000's perm bits is allowed through, which causes it to be able to set (among others) the suid bit. This was presumably not the intent since the unix extended bits are handled explicitly and conditionally on .u. Signed-off-by: Joakim Sindholt Signed-off-by: Eric Van Hensbergen --- fs/9p/vfs_inode.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/9p/vfs_inode.c b/fs/9p/vfs_inode.c index b01b1bbf2493..9612fdb563a3 100644 --- a/fs/9p/vfs_inode.c +++ b/fs/9p/vfs_inode.c @@ -83,7 +83,7 @@ static int p9mode2perm(struct v9fs_session_info *v9ses, int res; int mode = stat->mode; - res = mode & S_IALLUGO; + res = mode & 0777; /* S_IRWXUGO */ if (v9fs_proto_dotu(v9ses)) { if ((mode & P9_DMSETUID) == P9_DMSETUID) res |= S_ISUID; -- cgit v1.2.3 From 87de39e70503e04ddb58965520b15eb9efa7eef3 Mon Sep 17 00:00:00 2001 From: Joakim Sindholt Date: Mon, 18 Mar 2024 12:22:33 +0100 Subject: fs/9p: translate O_TRUNC into OTRUNC This one hits both 9P2000 and .u as it appears v9fs has never translated the O_TRUNC flag. Signed-off-by: Joakim Sindholt Signed-off-by: Eric Van Hensbergen --- fs/9p/vfs_inode.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/fs/9p/vfs_inode.c b/fs/9p/vfs_inode.c index 9612fdb563a3..c5b4d3631c47 100644 --- a/fs/9p/vfs_inode.c +++ b/fs/9p/vfs_inode.c @@ -178,6 +178,9 @@ int v9fs_uflags2omode(int uflags, int extended) break; } + if (uflags & O_TRUNC) + ret |= P9_OTRUNC; + if (extended) { if (uflags & O_EXCL) ret |= P9_OEXCL; -- cgit v1.2.3 From 4e5d208cc9bd5fbc95d536fa223b4b14c37b8ca8 Mon Sep 17 00:00:00 2001 From: Joakim Sindholt Date: Mon, 18 Mar 2024 12:22:34 +0100 Subject: fs/9p: fix the cache always being enabled on files with qid flags I'm not sure why this check was ever here. After updating to 6.6 I suddenly found caching had been turned on by default and neither cache=none nor the new directio would turn it off. After walking through the new code very manually I realized that it's because the caching has to be, in effect, turned off explicitly by setting P9L_DIRECT and whenever a file has a flag, in my case QTAPPEND, it doesn't get set. Setting aside QTDIR which seems to ignore the new fid->mode entirely, the rest of these either should be subject to the same cache rules as every other QTFILE or perhaps very explicitly not cached in the case of QTAUTH. Signed-off-by: Joakim Sindholt Signed-off-by: Eric Van Hensbergen --- fs/9p/fid.h | 3 --- 1 file changed, 3 deletions(-) diff --git a/fs/9p/fid.h b/fs/9p/fid.h index 29281b7c3887..0d6138bee2a3 100644 --- a/fs/9p/fid.h +++ b/fs/9p/fid.h @@ -49,9 +49,6 @@ static inline struct p9_fid *v9fs_fid_clone(struct dentry *dentry) static inline void v9fs_fid_add_modes(struct p9_fid *fid, unsigned int s_flags, unsigned int s_cache, unsigned int f_flags) { - if (fid->qid.type != P9_QTFILE) - return; - if ((!s_cache) || ((fid->qid.version == 0) && !(s_flags & V9FS_IGNORE_QV)) || (s_flags & V9FS_DIRECT_IO) || (f_flags & O_DIRECT)) { -- cgit v1.2.3 From 2e4c003b3672085267a358ebf82129b4e08dd64f Mon Sep 17 00:00:00 2001 From: Seven Lee Date: Wed, 27 Mar 2024 15:57:54 +0800 Subject: ASoC: dt-bindings: Added schema for "nuvoton,nau8325" Add a DT schema for describing nau8325 audio amplifiers. The key features are as follows: - Low SPK_VDD Quiescent Current - Gain Setting with 2-wire interface - Powerful Stereo Class-D Amplifier - Low Output Noise - Low Current Shutdown Mode - Click-and Pop Suppression More resources : https://www.nuvoton.com/products/smart-home-audio/audio-amplifiers/class-d-series/nau8325yg/ Signed-off-by: Seven Lee Reviewed-by: Rob Herring Link: https://msgid.link/r/20240327075755.3410381-2-wtli@nuvoton.com Signed-off-by: Mark Brown --- .../devicetree/bindings/sound/nuvoton,nau8325.yaml | 80 ++++++++++++++++++++++ 1 file changed, 80 insertions(+) create mode 100644 Documentation/devicetree/bindings/sound/nuvoton,nau8325.yaml diff --git a/Documentation/devicetree/bindings/sound/nuvoton,nau8325.yaml b/Documentation/devicetree/bindings/sound/nuvoton,nau8325.yaml new file mode 100644 index 000000000000..979be0d336da --- /dev/null +++ b/Documentation/devicetree/bindings/sound/nuvoton,nau8325.yaml @@ -0,0 +1,80 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/sound/nuvoton,nau8325.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: NAU8325 audio Amplifier + +maintainers: + - Seven Lee + +allOf: + - $ref: dai-common.yaml# + +properties: + compatible: + const: nuvoton,nau8325 + + reg: + maxItems: 1 + + nuvoton,vref-impedance-ohms: + description: + The vref impedance to be used in ohms. Middle of voltage enables + Tie-Off selection options. Due to the high impedance of the VREF + pin, it is important to use a low-leakage capacitor. + + enum: [0, 25000, 125000, 2500] + + nuvoton,dac-vref-microvolt: + description: + The DAC vref to be used in voltage. DAC reference voltage setting. Can + be used for minor tuning of the output level. Since the VDDA is range + between 1.62 to 1.98 voltage, the typical value for design is 1.8V. After + the minor tuning, the final microvolt are as the below. + + enum: [1800000, 2700000, 2880000, 3060000] + + nuvoton,alc-enable: + description: + Enable digital automatic level control (ALC) function. + type: boolean + + nuvoton,clock-detection-disable: + description: + When clock detection is enabled, it will detect whether MCLK + and FS are within the range. MCLK range is from 2.048MHz to 24.576MHz. + FS range is from 8kHz to 96kHz. And also needs to detect the ratio + MCLK_SRC/LRCK of 256, 400 or 500, and needs to detect the BCLK + to make sure data is present. There needs to be at least 8 BCLK + cycles per Frame Sync. + type: boolean + + nuvoton,clock-det-data: + description: + Request clock detection to require 2048 non-zero samples before enabling + the audio paths. If set then non-zero samples is required, otherwise it + doesn't matter. + type: boolean + +required: + - compatible + - reg + +unevaluatedProperties: false + +examples: + - | + i2c { + #address-cells = <1>; + #size-cells = <0>; + codec@21 { + compatible = "nuvoton,nau8325"; + reg = <0x21>; + nuvoton,vref-impedance-ohms = <125000>; + nuvoton,dac-vref-microvolt = <2880000>; + nuvoton,alc-enable; + nuvoton,clock-det-data; + }; + }; -- cgit v1.2.3 From c0a3873b9938bfaa77bd337cad33266a50a6583f Mon Sep 17 00:00:00 2001 From: Seven Lee Date: Wed, 27 Mar 2024 15:57:55 +0800 Subject: ASoC: nau8325: new driver The driver is for amplifiers NAU8325 of Nuvoton Technology Corporation. The NAU8325 is a stereo high efficiency filter-free Class-D audio amplifier, which is capable of driving a 4ohm load with up to 3W output power. Signed-off-by: Seven Lee Link: https://msgid.link/r/20240327075755.3410381-3-wtli@nuvoton.com Signed-off-by: Mark Brown --- sound/soc/codecs/nau8325.c | 893 +++++++++++++++++++++++++++++++++++++++++++++ sound/soc/codecs/nau8325.h | 391 ++++++++++++++++++++ 2 files changed, 1284 insertions(+) create mode 100644 sound/soc/codecs/nau8325.c create mode 100644 sound/soc/codecs/nau8325.h diff --git a/sound/soc/codecs/nau8325.c b/sound/soc/codecs/nau8325.c new file mode 100644 index 000000000000..a00a30364c89 --- /dev/null +++ b/sound/soc/codecs/nau8325.c @@ -0,0 +1,893 @@ +// SPDX-License-Identifier: GPL-2.0-only +// +// nau8325.c -- Nuvoton NAU8325 audio codec driver +// +// Copyright 2023 Nuvoton Technology Crop. +// Author: Seven Lee +// David Lin +// + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "nau8325.h" + +/* Range of Master Clock MCLK (Hz) */ +#define MASTER_CLK_MAX 49152000 +#define MASTER_CLK_MIN 2048000 + +/* scaling for MCLK source */ +#define CLK_PROC_BYPASS (-1) + +/* the maximum CLK_DAC */ +#define CLK_DA_AD_MAX 6144000 + +/* from MCLK input */ +#define MCLK_SRC 4 + +static const struct nau8325_src_attr mclk_n1_div[] = { + { 1, 0x0 }, + { 2, 0x1 }, + { 3, 0x2 }, +}; + +/* over sampling rate */ +static const struct nau8325_osr_attr osr_dac_sel[] = { + { 64, 2 }, /* OSR 64, SRC 1/4 */ + { 256, 0 }, /* OSR 256, SRC 1 */ + { 128, 1 }, /* OSR 128, SRC 1/2 */ + { 0, 0 }, + { 32, 3 }, /* OSR 32, SRC 1/8 */ +}; + +static const struct nau8325_src_attr mclk_n2_div[] = { + { 0, 0x0 }, + { 1, 0x1 }, + { 2, 0x2 }, + { 3, 0x3 }, + { 4, 0x4 }, +}; + +static const struct nau8325_src_attr mclk_n3_mult[] = { + { 0, 0x1 }, + { 1, 0x2 }, + { 2, 0x3 }, + { 3, 0x4 }, +}; + +/* Sample Rate and MCLK_SRC selections */ +static const struct nau8325_srate_attr target_srate_table[] = { + /* { FS, range, max, { MCLK source }} */ + { 48000, 2, true, { 12288000, 19200000, 24000000 } }, + { 16000, 1, false, { 4096000, 6400000, 8000000 } }, + { 8000, 0, false, { 2048000, 3200000, 4000000 }}, + { 44100, 2, true, { 11289600, 17640000, 22050000 }}, + { 64000, 3, false, { 16384000, 25600000, 32000000 } }, + { 96000, 3, true, { 24576000, 38400000, 48000000 } }, + { 12000, 0, true, { 3072000, 4800000, 6000000 } }, + { 24000, 1, true, { 6144000, 9600000, 12000000 } }, + { 32000, 2, false, { 8192000, 12800000, 16000000 } }, +}; + +static const struct reg_default nau8325_reg_defaults[] = { + { NAU8325_R00_HARDWARE_RST, 0x0000 }, + { NAU8325_R01_SOFTWARE_RST, 0x0000 }, + { NAU8325_R03_CLK_CTRL, 0x0000 }, + { NAU8325_R04_ENA_CTRL, 0x0000 }, + { NAU8325_R05_INTERRUPT_CTRL, 0x007f }, + { NAU8325_R09_IRQOUT, 0x0000 }, + { NAU8325_R0A_IO_CTRL, 0x0000 }, + { NAU8325_R0B_PDM_CTRL, 0x0000 }, + { NAU8325_R0C_TDM_CTRL, 0x0000 }, + { NAU8325_R0D_I2S_PCM_CTRL1, 0x000a }, + { NAU8325_R0E_I2S_PCM_CTRL2, 0x0000 }, + { NAU8325_R0F_L_TIME_SLOT, 0x0000 }, + { NAU8325_R10_R_TIME_SLOT, 0x0000 }, + { NAU8325_R11_HPF_CTRL, 0x0000 }, + { NAU8325_R12_MUTE_CTRL, 0x0000 }, + { NAU8325_R13_DAC_VOLUME, 0xf3f3 }, + { NAU8325_R29_DAC_CTRL1, 0x0081 }, + { NAU8325_R2A_DAC_CTRL2, 0x0000 }, + { NAU8325_R2C_ALC_CTRL1, 0x000e }, + { NAU8325_R2D_ALC_CTRL2, 0x8400 }, + { NAU8325_R2E_ALC_CTRL3, 0x0000 }, + { NAU8325_R2F_ALC_CTRL4, 0x003f }, + { NAU8325_R40_CLK_DET_CTRL, 0xa801 }, + { NAU8325_R50_MIXER_CTRL, 0x0000 }, + { NAU8325_R55_MISC_CTRL, 0x0000 }, + { NAU8325_R60_BIAS_ADJ, 0x0000 }, + { NAU8325_R61_ANALOG_CONTROL_1, 0x0000 }, + { NAU8325_R62_ANALOG_CONTROL_2, 0x0000 }, + { NAU8325_R63_ANALOG_CONTROL_3, 0x0000 }, + { NAU8325_R64_ANALOG_CONTROL_4, 0x0000 }, + { NAU8325_R65_ANALOG_CONTROL_5, 0x0000 }, + { NAU8325_R66_ANALOG_CONTROL_6, 0x0000 }, + { NAU8325_R69_CLIP_CTRL, 0x0000 }, + { NAU8325_R73_RDAC, 0x0008 }, +}; + +static bool nau8325_readable_reg(struct device *dev, unsigned int reg) +{ + switch (reg) { + case NAU8325_R02_DEVICE_ID ... NAU8325_R06_INT_CLR_STATUS: + case NAU8325_R09_IRQOUT ... NAU8325_R13_DAC_VOLUME: + case NAU8325_R1D_DEBUG_READ1: + case NAU8325_R1F_DEBUG_READ2: + case NAU8325_R22_DEBUG_READ3: + case NAU8325_R29_DAC_CTRL1 ... NAU8325_R2A_DAC_CTRL2: + case NAU8325_R2C_ALC_CTRL1 ... NAU8325_R2F_ALC_CTRL4: + case NAU8325_R40_CLK_DET_CTRL: + case NAU8325_R49_TEST_STATUS ... NAU8325_R4A_ANALOG_READ: + case NAU8325_R50_MIXER_CTRL: + case NAU8325_R55_MISC_CTRL: + case NAU8325_R60_BIAS_ADJ ... NAU8325_R66_ANALOG_CONTROL_6: + case NAU8325_R69_CLIP_CTRL: + case NAU8325_R73_RDAC: + return true; + default: + return false; + } +} + +static bool nau8325_writeable_reg(struct device *dev, unsigned int reg) +{ + switch (reg) { + case NAU8325_R00_HARDWARE_RST: + case NAU8325_R03_CLK_CTRL ... NAU8325_R06_INT_CLR_STATUS: + case NAU8325_R09_IRQOUT ... NAU8325_R13_DAC_VOLUME: + case NAU8325_R29_DAC_CTRL1 ... NAU8325_R2A_DAC_CTRL2: + case NAU8325_R2C_ALC_CTRL1 ... NAU8325_R2F_ALC_CTRL4: + case NAU8325_R40_CLK_DET_CTRL: + case NAU8325_R50_MIXER_CTRL: + case NAU8325_R55_MISC_CTRL: + case NAU8325_R60_BIAS_ADJ ... NAU8325_R66_ANALOG_CONTROL_6: + case NAU8325_R69_CLIP_CTRL: + case NAU8325_R73_RDAC: + return true; + default: + return false; + } +} + +static bool nau8325_volatile_reg(struct device *dev, unsigned int reg) +{ + switch (reg) { + case NAU8325_R00_HARDWARE_RST ... NAU8325_R02_DEVICE_ID: + case NAU8325_R06_INT_CLR_STATUS: + case NAU8325_R1D_DEBUG_READ1: + case NAU8325_R1F_DEBUG_READ2: + case NAU8325_R22_DEBUG_READ3: + case NAU8325_R4A_ANALOG_READ: + return true; + default: + return false; + } +} + +static const char * const nau8325_dac_oversampl[] = { + "64", "256", "128", "", "32" }; + +static const struct soc_enum nau8325_dac_oversampl_enum = + SOC_ENUM_SINGLE(NAU8325_R29_DAC_CTRL1, NAU8325_DAC_OVERSAMPLE_SFT, + ARRAY_SIZE(nau8325_dac_oversampl), + nau8325_dac_oversampl); + +static const DECLARE_TLV_DB_MINMAX_MUTE(dac_vol_tlv, -8000, 600); + +static const struct snd_kcontrol_new nau8325_snd_controls[] = { + SOC_ENUM("DAC Oversampling Rate", nau8325_dac_oversampl_enum), + SOC_DOUBLE_TLV("Speaker Volume", NAU8325_R13_DAC_VOLUME, + NAU8325_DAC_VOLUME_L_SFT, NAU8325_DAC_VOLUME_R_SFT, + NAU8325_DAC_VOLUME_R_EN, 0, dac_vol_tlv), + SOC_SINGLE("ALC Max Gain", NAU8325_R2C_ALC_CTRL1, + NAU8325_ALC_MAXGAIN_SFT, NAU8325_ALC_MAXGAIN_MAX, 0), + SOC_SINGLE("ALC Min Gain", NAU8325_R2C_ALC_CTRL1, + NAU8325_ALC_MINGAIN_SFT, NAU8325_ALC_MINGAIN_MAX, 0), + SOC_SINGLE("ALC Decay Timer", NAU8325_R2D_ALC_CTRL2, + NAU8325_ALC_DCY_SFT, NAU8325_ALC_DCY_MAX, 0), + SOC_SINGLE("ALC Attack Timer", NAU8325_R2D_ALC_CTRL2, + NAU8325_ALC_ATK_SFT, NAU8325_ALC_ATK_MAX, 0), + SOC_SINGLE("ALC Hold Time", NAU8325_R2D_ALC_CTRL2, + NAU8325_ALC_HLD_SFT, NAU8325_ALC_HLD_MAX, 0), + SOC_SINGLE("ALC Target Level", NAU8325_R2D_ALC_CTRL2, + NAU8325_ALC_LVL_SFT, NAU8325_ALC_LVL_MAX, 0), + SOC_SINGLE("ALC Enable Switch", NAU8325_R2E_ALC_CTRL3, + NAU8325_ALC_EN_SFT, 1, 0), +}; + +static int nau8325_dac_event(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, int event) +{ + struct snd_soc_component *component = + snd_soc_dapm_to_component(w->dapm); + struct nau8325 *nau8325 = snd_soc_component_get_drvdata(component); + + switch (event) { + case SND_SOC_DAPM_POST_PMU: + regmap_update_bits(nau8325->regmap, NAU8325_R12_MUTE_CTRL, + NAU8325_SOFT_MUTE, 0); + msleep(30); + break; + case SND_SOC_DAPM_PRE_PMD: + /* Soft mute the output to prevent the pop noise. */ + regmap_update_bits(nau8325->regmap, NAU8325_R12_MUTE_CTRL, + NAU8325_SOFT_MUTE, NAU8325_SOFT_MUTE); + msleep(30); + break; + default: + return -EINVAL; + } + + return 0; +} + +static int nau8325_powerup_event(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, int event) +{ + struct snd_soc_component *component = + snd_soc_dapm_to_component(w->dapm); + struct nau8325 *nau8325 = snd_soc_component_get_drvdata(component); + + if (nau8325->clock_detection) + return 0; + + switch (event) { + case SND_SOC_DAPM_POST_PMU: + regmap_update_bits(nau8325->regmap, NAU8325_R40_CLK_DET_CTRL, + NAU8325_PWRUP_DFT, NAU8325_PWRUP_DFT); + break; + case SND_SOC_DAPM_POST_PMD: + regmap_update_bits(nau8325->regmap, NAU8325_R40_CLK_DET_CTRL, + NAU8325_PWRUP_DFT, 0); + break; + default: + return -EINVAL; + } + + return 0; +} + +static const struct snd_soc_dapm_widget nau8325_dapm_widgets[] = { + SND_SOC_DAPM_SUPPLY("Power Up", SND_SOC_NOPM, 0, 0, + nau8325_powerup_event, SND_SOC_DAPM_POST_PMU | + SND_SOC_DAPM_POST_PMD), + SND_SOC_DAPM_DAC_E("DACL", NULL, NAU8325_R04_ENA_CTRL, + NAU8325_DAC_LEFT_CH_EN_SFT, 0, nau8325_dac_event, + SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD), + SND_SOC_DAPM_DAC_E("DACR", NULL, NAU8325_R04_ENA_CTRL, + NAU8325_DAC_RIGHT_CH_EN_SFT, 0, nau8325_dac_event, + SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD), + SND_SOC_DAPM_AIF_IN("AIFRX", "Playback", 0, SND_SOC_NOPM, 0, 0), + + SND_SOC_DAPM_OUTPUT("SPKL"), + SND_SOC_DAPM_OUTPUT("SPKR"), +}; + +static const struct snd_soc_dapm_route nau8325_dapm_routes[] = { + { "DACL", NULL, "Power Up" }, + { "DACR", NULL, "Power Up" }, + + { "DACL", NULL, "AIFRX" }, + { "DACR", NULL, "AIFRX" }, + { "SPKL", NULL, "DACL" }, + { "SPKR", NULL, "DACR" }, +}; + +static int nau8325_srate_clk_apply(struct nau8325 *nau8325, + const struct nau8325_srate_attr *srate_table, + int n1_sel, int mclk_mult_sel, int n2_sel) +{ + if (!srate_table || n2_sel < 0 || n2_sel >= ARRAY_SIZE(mclk_n2_div) || + n1_sel < 0 || n1_sel >= ARRAY_SIZE(mclk_n1_div)) { + dev_dbg(nau8325->dev, "The CLK isn't supported."); + return -EINVAL; + } + + regmap_update_bits(nau8325->regmap, NAU8325_R40_CLK_DET_CTRL, + NAU8325_REG_SRATE_MASK | NAU8325_REG_DIV_MAX, + (srate_table->range << NAU8325_REG_SRATE_SFT) | + (srate_table->max ? NAU8325_REG_DIV_MAX : 0)); + regmap_update_bits(nau8325->regmap, NAU8325_R03_CLK_CTRL, + NAU8325_MCLK_SRC_MASK, mclk_n2_div[n2_sel].val); + regmap_update_bits(nau8325->regmap, NAU8325_R03_CLK_CTRL, + NAU8325_CLK_MUL_SRC_MASK, + mclk_n1_div[n1_sel].val << NAU8325_CLK_MUL_SRC_SFT); + + if (mclk_mult_sel != CLK_PROC_BYPASS) { + regmap_update_bits(nau8325->regmap, NAU8325_R03_CLK_CTRL, + NAU8325_MCLK_SEL_MASK, + mclk_n3_mult[mclk_mult_sel].val << + NAU8325_MCLK_SEL_SFT); + } else { + regmap_update_bits(nau8325->regmap, NAU8325_R03_CLK_CTRL, + NAU8325_MCLK_SEL_MASK, 0); + } + + switch (mclk_mult_sel) { + case 2: + regmap_update_bits(nau8325->regmap, NAU8325_R65_ANALOG_CONTROL_5, + NAU8325_MCLK4XEN_EN, NAU8325_MCLK4XEN_EN); + break; + case 3: + regmap_update_bits(nau8325->regmap, NAU8325_R65_ANALOG_CONTROL_5, + NAU8325_MCLK4XEN_EN | NAU8325_MCLK8XEN_EN, + NAU8325_MCLK4XEN_EN | NAU8325_MCLK8XEN_EN); + break; + default: + regmap_update_bits(nau8325->regmap, NAU8325_R65_ANALOG_CONTROL_5, + NAU8325_MCLK4XEN_EN | NAU8325_MCLK8XEN_EN, 0); + break; + } + + return 0; +} + +static int nau8325_clksrc_n2(struct nau8325 *nau8325, + const struct nau8325_srate_attr *srate_table, + int mclk, int *n2_sel) +{ + int i, mclk_src, ratio; + + ratio = NAU8325_MCLK_FS_RATIO_NUM; + for (i = 0; i < ARRAY_SIZE(mclk_n2_div); i++) { + mclk_src = mclk >> mclk_n2_div[i].param; + if (srate_table->mclk_src[NAU8325_MCLK_FS_RATIO_256] == mclk_src) { + ratio = NAU8325_MCLK_FS_RATIO_256; + break; + } else if (srate_table->mclk_src[NAU8325_MCLK_FS_RATIO_400] == mclk_src) { + ratio = NAU8325_MCLK_FS_RATIO_400; + break; + } else if (srate_table->mclk_src[NAU8325_MCLK_FS_RATIO_500] == mclk_src) { + ratio = NAU8325_MCLK_FS_RATIO_500; + break; + } + } + if (ratio != NAU8325_MCLK_FS_RATIO_NUM) + *n2_sel = i; + + return ratio; +} + +static const struct nau8325_srate_attr *target_srate_attribute(int srate) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(target_srate_table); i++) + if (target_srate_table[i].fs == srate) + break; + + if (i == ARRAY_SIZE(target_srate_table)) + goto proc_err; + + return &target_srate_table[i]; + +proc_err: + return NULL; +} + +static int nau8325_clksrc_choose(struct nau8325 *nau8325, + const struct nau8325_srate_attr **srate_table, + int *n1_sel, int *mult_sel, int *n2_sel) +{ + int i, j, mclk, mclk_max, ratio, ratio_sel, n2_max; + + if (!nau8325->mclk || !nau8325->fs) + goto proc_err; + + /* select sampling rate and MCLK_SRC */ + *srate_table = target_srate_attribute(nau8325->fs); + if (!*srate_table) + goto proc_err; + + /* First check clock from MCLK directly, decide N2 for MCLK_SRC. + * If not good, consider 1/N1 and Multiplier. + */ + ratio = nau8325_clksrc_n2(nau8325, *srate_table, nau8325->mclk, n2_sel); + if (ratio != NAU8325_MCLK_FS_RATIO_NUM) { + *n1_sel = 0; + *mult_sel = CLK_PROC_BYPASS; + *n2_sel = MCLK_SRC; + goto proc_done; + } + + /* Get MCLK_SRC through 1/N, Multiplier, and then 1/N2. */ + mclk_max = 0; + for (i = 0; i < ARRAY_SIZE(mclk_n1_div); i++) { + for (j = 0; j < ARRAY_SIZE(mclk_n3_mult); j++) { + mclk = nau8325->mclk << mclk_n3_mult[j].param; + mclk = mclk / mclk_n1_div[i].param; + ratio = nau8325_clksrc_n2(nau8325, + *srate_table, mclk, n2_sel); + if (ratio != NAU8325_MCLK_FS_RATIO_NUM && + (mclk_max < mclk || i > *n1_sel)) { + mclk_max = mclk; + n2_max = *n2_sel; + *n1_sel = i; + *mult_sel = j; + ratio_sel = ratio; + goto proc_done; + } + } + } + if (mclk_max) { + *n2_sel = n2_max; + ratio = ratio_sel; + goto proc_done; + } + +proc_err: + dev_dbg(nau8325->dev, "The MCLK %d is invalid. It can't get MCLK_SRC of 256/400/500 FS (%d)", + nau8325->mclk, nau8325->fs); + return -EINVAL; +proc_done: + dev_dbg(nau8325->dev, "nau8325->fs=%d,range=0x%x, %s, (n1,mu,n2,dmu):(%d,%d,%d), MCLK_SRC=%uHz (%d)", + nau8325->fs, (*srate_table)->range, + (*srate_table)->max ? "MAX" : "MIN", + *n1_sel == CLK_PROC_BYPASS ? + CLK_PROC_BYPASS : mclk_n1_div[*n1_sel].param, + *mult_sel == CLK_PROC_BYPASS ? + CLK_PROC_BYPASS : 1 << mclk_n3_mult[*mult_sel].param, + 1 << mclk_n2_div[*n2_sel].param, + (*srate_table)->mclk_src[ratio], + (*srate_table)->mclk_src[ratio] / nau8325->fs); + + return 0; +} + +static int nau8325_clock_config(struct nau8325 *nau8325) +{ + const struct nau8325_srate_attr *srate_table; + int ret, n1_sel, mult_sel, n2_sel; + + ret = nau8325_clksrc_choose(nau8325, &srate_table, + &n1_sel, &mult_sel, &n2_sel); + if (ret) + goto err; + + ret = nau8325_srate_clk_apply(nau8325, srate_table, + n1_sel, mult_sel, n2_sel); + if (ret) + goto err; + + return 0; +err: + return ret; +} + +static const struct nau8325_osr_attr *nau8325_get_osr(struct nau8325 *nau8325) +{ + unsigned int osr; + + regmap_read(nau8325->regmap, NAU8325_R29_DAC_CTRL1, &osr); + osr &= NAU8325_DAC_OVERSAMPLE_MASK; + if (osr >= ARRAY_SIZE(osr_dac_sel)) + return NULL; + + return &osr_dac_sel[osr]; +} + +static int nau8325_dai_startup(struct snd_pcm_substream *substream, + struct snd_soc_dai *dai) +{ + struct snd_soc_component *component = dai->component; + struct nau8325 *nau8325 = snd_soc_component_get_drvdata(component); + const struct nau8325_osr_attr *osr; + + osr = nau8325_get_osr(nau8325); + if (!osr || !osr->osr) + return -EINVAL; + + return snd_pcm_hw_constraint_minmax(substream->runtime, + SNDRV_PCM_HW_PARAM_RATE, + 0, CLK_DA_AD_MAX / osr->osr); +} + +static int nau8325_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params, + struct snd_soc_dai *dai) +{ + struct snd_soc_component *component = dai->component; + struct nau8325 *nau8325 = snd_soc_component_get_drvdata(component); + unsigned int val_len = 0; + const struct nau8325_osr_attr *osr; + int ret; + + nau8325->fs = params_rate(params); + osr = nau8325_get_osr(nau8325); + if (!osr || !osr->osr || nau8325->fs * osr->osr > CLK_DA_AD_MAX) { + ret = -EINVAL; + goto err; + } + regmap_update_bits(nau8325->regmap, NAU8325_R03_CLK_CTRL, + NAU8325_CLK_DAC_SRC_MASK, + osr->clk_src << NAU8325_CLK_DAC_SRC_SFT); + + ret = nau8325_clock_config(nau8325); + if (ret) + goto err; + + switch (params_width(params)) { + case 16: + val_len |= NAU8325_I2S_DL_16; + break; + case 20: + val_len |= NAU8325_I2S_DL_20; + break; + case 24: + val_len |= NAU8325_I2S_DL_24; + break; + case 32: + val_len |= NAU8325_I2S_DL_32; + break; + default: + ret = -EINVAL; + goto err; + } + + regmap_update_bits(nau8325->regmap, NAU8325_R0D_I2S_PCM_CTRL1, + NAU8325_I2S_DL_MASK, val_len); + + return 0; + +err: + return ret; +} + +static int nau8325_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) +{ + struct snd_soc_component *component = dai->component; + struct nau8325 *nau8325 = snd_soc_component_get_drvdata(component); + unsigned int ctrl1_val = 0; + + switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { + case SND_SOC_DAIFMT_CBC_CFC: + break; + default: + return -EINVAL; + } + + switch (fmt & SND_SOC_DAIFMT_INV_MASK) { + case SND_SOC_DAIFMT_NB_NF: + break; + case SND_SOC_DAIFMT_IB_NF: + ctrl1_val |= NAU8325_I2S_BP_INV; + break; + default: + return -EINVAL; + } + + switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { + case SND_SOC_DAIFMT_I2S: + ctrl1_val |= NAU8325_I2S_DF_I2S; + break; + case SND_SOC_DAIFMT_LEFT_J: + ctrl1_val |= NAU8325_I2S_DF_LEFT; + break; + case SND_SOC_DAIFMT_RIGHT_J: + ctrl1_val |= NAU8325_I2S_DF_RIGTH; + break; + case SND_SOC_DAIFMT_DSP_A: + ctrl1_val |= NAU8325_I2S_DF_PCM_AB; + break; + case SND_SOC_DAIFMT_DSP_B: + ctrl1_val |= NAU8325_I2S_DF_PCM_AB; + ctrl1_val |= NAU8325_I2S_PCMB_EN; + break; + default: + return -EINVAL; + } + + regmap_update_bits(nau8325->regmap, NAU8325_R0D_I2S_PCM_CTRL1, + NAU8325_I2S_DF_MASK | NAU8325_I2S_BP_MASK | + NAU8325_I2S_PCMB_EN, ctrl1_val); + + return 0; +} + +static int nau8325_set_sysclk(struct snd_soc_component *component, int clk_id, + int source, unsigned int freq, int dir) +{ + struct nau8325 *nau8325 = snd_soc_component_get_drvdata(component); + + if (freq < MASTER_CLK_MIN || freq > MASTER_CLK_MAX) { + dev_dbg(nau8325->dev, "MCLK exceeds the range, MCLK:%d", freq); + return -EINVAL; + } + + nau8325->mclk = freq; + dev_dbg(nau8325->dev, "MCLK %dHz", nau8325->mclk); + + return 0; +} + +static const struct snd_soc_component_driver nau8325_component_driver = { + .set_sysclk = nau8325_set_sysclk, + .suspend_bias_off = true, + .controls = nau8325_snd_controls, + .num_controls = ARRAY_SIZE(nau8325_snd_controls), + .dapm_widgets = nau8325_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(nau8325_dapm_widgets), + .dapm_routes = nau8325_dapm_routes, + .num_dapm_routes = ARRAY_SIZE(nau8325_dapm_routes), +}; + +static const struct snd_soc_dai_ops nau8325_dai_ops = { + .startup = nau8325_dai_startup, + .hw_params = nau8325_hw_params, + .set_fmt = nau8325_set_fmt, +}; + +#define NAU8325_RATES SNDRV_PCM_RATE_8000_96000 +#define NAU8325_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE \ + | SNDRV_PCM_FMTBIT_S24_3LE) + +static struct snd_soc_dai_driver nau8325_dai = { + .name = NAU8325_CODEC_DAI, + .playback = { + .stream_name = "Playback", + .channels_min = 1, + .channels_max = 2, + .rates = NAU8325_RATES, + .formats = NAU8325_FORMATS, + }, + .ops = &nau8325_dai_ops, +}; + +static const struct regmap_config nau8325_regmap_config = { + .reg_bits = NAU8325_REG_ADDR_LEN, + .val_bits = NAU8325_REG_DATA_LEN, + + .max_register = NAU8325_REG_MAX, + .readable_reg = nau8325_readable_reg, + .writeable_reg = nau8325_writeable_reg, + .volatile_reg = nau8325_volatile_reg, + + .cache_type = REGCACHE_RBTREE, + .reg_defaults = nau8325_reg_defaults, + .num_reg_defaults = ARRAY_SIZE(nau8325_reg_defaults), +}; + +static void nau8325_reset_chip(struct regmap *regmap) +{ + regmap_write(regmap, NAU8325_R00_HARDWARE_RST, 0x0001); + regmap_write(regmap, NAU8325_R00_HARDWARE_RST, 0x0000); +} + +static void nau8325_init_regs(struct nau8325 *nau8325) +{ + struct regmap *regmap = nau8325->regmap; + struct device *dev = nau8325->dev; + + /* set ALC parameters */ + regmap_update_bits(regmap, NAU8325_R2C_ALC_CTRL1, + NAU8325_ALC_MAXGAIN_MASK, + 0x7 << NAU8325_ALC_MAXGAIN_SFT); + regmap_update_bits(regmap, NAU8325_R2D_ALC_CTRL2, + NAU8325_ALC_DCY_MASK | NAU8325_ALC_ATK_MASK | + NAU8325_ALC_HLD_MASK, (0x5 << NAU8325_ALC_DCY_SFT) | + (0x3 << NAU8325_ALC_ATK_SFT) | + (0x5 << NAU8325_ALC_HLD_SFT)); + /* Enable ALC to avoid signal distortion when battery low. */ + if (nau8325->alc_enable) + regmap_update_bits(regmap, NAU8325_R2E_ALC_CTRL3, + NAU8325_ALC_EN, NAU8325_ALC_EN); + if (nau8325->clock_detection) + regmap_update_bits(regmap, NAU8325_R40_CLK_DET_CTRL, + NAU8325_CLKPWRUP_DIS | + NAU8325_PWRUP_DFT, 0); + else + regmap_update_bits(regmap, NAU8325_R40_CLK_DET_CTRL, + NAU8325_CLKPWRUP_DIS | NAU8325_PWRUP_DFT, + NAU8325_CLKPWRUP_DIS); + if (nau8325->clock_det_data) + regmap_update_bits(regmap, NAU8325_R40_CLK_DET_CTRL, + NAU8325_APWRUP_EN, NAU8325_APWRUP_EN); + else + regmap_update_bits(regmap, NAU8325_R40_CLK_DET_CTRL, + NAU8325_APWRUP_EN, 0); + + /* DAC Reference Voltage Setting */ + switch (nau8325->dac_vref_microvolt) { + case 1800000: + regmap_update_bits(regmap, NAU8325_R73_RDAC, + NAU8325_DACVREFSEL_MASK, 0 << NAU8325_DACVREFSEL_SFT); + break; + case 2700000: + regmap_update_bits(regmap, NAU8325_R73_RDAC, + NAU8325_DACVREFSEL_MASK, 1 << NAU8325_DACVREFSEL_SFT); + break; + case 2880000: + regmap_update_bits(regmap, NAU8325_R73_RDAC, + NAU8325_DACVREFSEL_MASK, 2 << NAU8325_DACVREFSEL_SFT); + break; + case 3060000: + regmap_update_bits(regmap, NAU8325_R73_RDAC, + NAU8325_DACVREFSEL_MASK, 3 << NAU8325_DACVREFSEL_SFT); + break; + default: + dev_dbg(dev, "Invalid dac-vref-microvolt %d", nau8325->dac_vref_microvolt); + + } + + /* DAC Reference Voltage Decoupling Capacitors. */ + regmap_update_bits(regmap, NAU8325_R63_ANALOG_CONTROL_3, + NAU8325_CLASSD_COARSE_GAIN_MASK, 0x4); + /* Auto-Att Min Gain 0dB, Class-D N Driver Slew Rate -25%. */ + regmap_update_bits(regmap, NAU8325_R64_ANALOG_CONTROL_4, + NAU8325_CLASSD_SLEWN_MASK, 0x7); + + /* VMID Tieoff (VMID Resistor Selection) */ + switch (nau8325->vref_impedance_ohms) { + case 0: + regmap_update_bits(regmap, NAU8325_R60_BIAS_ADJ, + NAU8325_BIAS_VMID_SEL_MASK, 0 << NAU8325_BIAS_VMID_SEL_SFT); + break; + case 25000: + regmap_update_bits(regmap, NAU8325_R60_BIAS_ADJ, + NAU8325_BIAS_VMID_SEL_MASK, 1 << NAU8325_BIAS_VMID_SEL_SFT); + break; + case 125000: + regmap_update_bits(regmap, NAU8325_R60_BIAS_ADJ, + NAU8325_BIAS_VMID_SEL_MASK, 2 << NAU8325_BIAS_VMID_SEL_SFT); + break; + case 2500: + regmap_update_bits(regmap, NAU8325_R60_BIAS_ADJ, + NAU8325_BIAS_VMID_SEL_MASK, 3 << NAU8325_BIAS_VMID_SEL_SFT); + break; + default: + dev_dbg(dev, "Invalid vref-impedance-ohms %d", nau8325->vref_impedance_ohms); + } + + + /* enable VMID, BIAS, DAC, DCA CLOCK, Voltage/Current Amps + */ + regmap_update_bits(regmap, NAU8325_R61_ANALOG_CONTROL_1, + NAU8325_DACEN_MASK | NAU8325_DACCLKEN_MASK | + NAU8325_DACEN_R_MASK | NAU8325_DACCLKEN_R_MASK | + NAU8325_CLASSDEN_MASK | NAU8325_VMDFSTENB_MASK | + NAU8325_BIASEN_MASK | NAU8325_VMIDEN_MASK, + (0x1 << NAU8325_DACEN_SFT) | + (0x1 << NAU8325_DACCLKEN_SFT) | + (0x1 << NAU8325_DACEN_R_SFT) | + (0x1 << NAU8325_DACCLKEN_R_SFT) | + (0x1 << NAU8325_CLASSDEN_SFT) | + (0x1 << NAU8325_VMDFSTENB_SFT) | + (0x1 << NAU8325_BIASEN_SFT) | 0x3); + + /* Enable ALC to avoid signal distortion when battery low. */ + if (nau8325->alc_enable) + regmap_update_bits(regmap, NAU8325_R2E_ALC_CTRL3, + NAU8325_ALC_EN, NAU8325_ALC_EN); + if (nau8325->clock_det_data) + regmap_update_bits(regmap, NAU8325_R40_CLK_DET_CTRL, + NAU8325_APWRUP_EN, NAU8325_APWRUP_EN); + else + regmap_update_bits(regmap, NAU8325_R40_CLK_DET_CTRL, + NAU8325_APWRUP_EN, 0); + if (nau8325->clock_detection) + regmap_update_bits(regmap, NAU8325_R40_CLK_DET_CTRL, + NAU8325_CLKPWRUP_DIS | + NAU8325_PWRUP_DFT, 0); + else + regmap_update_bits(regmap, NAU8325_R40_CLK_DET_CTRL, + NAU8325_CLKPWRUP_DIS | NAU8325_PWRUP_DFT, + NAU8325_CLKPWRUP_DIS); + regmap_update_bits(regmap, NAU8325_R29_DAC_CTRL1, + NAU8325_DAC_OVERSAMPLE_MASK, + NAU8325_DAC_OVERSAMPLE_128); +} + +static void nau8325_print_device_properties(struct nau8325 *nau8325) +{ + struct device *dev = nau8325->dev; + + dev_dbg(dev, "vref-impedance-ohms: %d", nau8325->vref_impedance_ohms); + dev_dbg(dev, "dac-vref-microvolt: %d", nau8325->dac_vref_microvolt); + dev_dbg(dev, "alc-enable: %d", nau8325->alc_enable); + dev_dbg(dev, "clock-det-data: %d", nau8325->clock_det_data); + dev_dbg(dev, "clock-detection-disable: %d", nau8325->clock_detection); +} + +static int nau8325_read_device_properties(struct device *dev, + struct nau8325 *nau8325) +{ + int ret; + + nau8325->alc_enable = + device_property_read_bool(dev, "nuvoton,alc-enable"); + nau8325->clock_det_data = + device_property_read_bool(dev, "nuvoton,clock-det-data"); + nau8325->clock_detection = + !device_property_read_bool(dev, "nuvoton,clock-detection-disable"); + + ret = device_property_read_u32(dev, "nuvoton,vref-impedance-ohms", + &nau8325->vref_impedance_ohms); + if (ret) + nau8325->vref_impedance_ohms = 125000; + ret = device_property_read_u32(dev, "nuvoton,dac-vref-microvolt", + &nau8325->dac_vref_microvolt); + if (ret) + nau8325->dac_vref_microvolt = 2880000; + + return 0; +} + +static int nau8325_i2c_probe(struct i2c_client *i2c, + const struct i2c_device_id *id) +{ + struct device *dev = &i2c->dev; + struct nau8325 *nau8325 = dev_get_platdata(dev); + int ret, value; + + if (!nau8325) { + nau8325 = devm_kzalloc(dev, sizeof(*nau8325), GFP_KERNEL); + if (!nau8325) { + ret = -ENOMEM; + goto err; + } + ret = nau8325_read_device_properties(dev, nau8325); + if (ret) + goto err; + } + i2c_set_clientdata(i2c, nau8325); + + nau8325->regmap = devm_regmap_init_i2c(i2c, &nau8325_regmap_config); + if (IS_ERR(nau8325->regmap)) { + ret = PTR_ERR(nau8325->regmap); + goto err; + } + nau8325->dev = dev; + nau8325_print_device_properties(nau8325); + + nau8325_reset_chip(nau8325->regmap); + ret = regmap_read(nau8325->regmap, NAU8325_R02_DEVICE_ID, &value); + if (ret) { + dev_dbg(dev, "Failed to read device id (%d)", ret); + goto err; + } + nau8325_init_regs(nau8325); + + ret = devm_snd_soc_register_component(dev, &nau8325_component_driver, + &nau8325_dai, 1); +err: + return ret; +} + +static const struct i2c_device_id nau8325_i2c_ids[] = { + { "nau8325", 0 }, + { } +}; +MODULE_DEVICE_TABLE(i2c, nau8325_i2c_ids); + +#ifdef CONFIG_OF +static const struct of_device_id nau8325_of_ids[] = { + { .compatible = "nuvoton,nau8325", }, + {} +}; +MODULE_DEVICE_TABLE(of, nau8325_of_ids); +#endif + +static struct i2c_driver nau8325_i2c_driver = { + .driver = { + .name = "nau8325", + .of_match_table = of_match_ptr(nau8325_of_ids), + }, + .probe = nau8325_i2c_probe, + .id_table = nau8325_i2c_ids, +}; +module_i2c_driver(nau8325_i2c_driver); + +MODULE_DESCRIPTION("ASoC NAU8325 driver"); +MODULE_AUTHOR("Seven Lee "); +MODULE_AUTHOR("David Lin "); +MODULE_LICENSE("GPL"); diff --git a/sound/soc/codecs/nau8325.h b/sound/soc/codecs/nau8325.h new file mode 100644 index 000000000000..0d173b66a4d4 --- /dev/null +++ b/sound/soc/codecs/nau8325.h @@ -0,0 +1,391 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * nau8325.h -- Nuvoton NAU8325 audio codec driver + * + * Copyright 2023 Nuvoton Technology Crop. + * Author: Seven Lee + * David Lin + */ + +#ifndef __NAU8325_H__ +#define __NAU8325_H__ + +#define NAU8325_R00_HARDWARE_RST 0x00 +#define NAU8325_R01_SOFTWARE_RST 0x01 +#define NAU8325_R02_DEVICE_ID 0x02 +#define NAU8325_R03_CLK_CTRL 0x03 +#define NAU8325_R04_ENA_CTRL 0x04 +#define NAU8325_R05_INTERRUPT_CTRL 0x05 +#define NAU8325_R06_INT_CLR_STATUS 0x06 +#define NAU8325_R09_IRQOUT 0x09 +#define NAU8325_R0A_IO_CTRL 0x0a +#define NAU8325_R0B_PDM_CTRL 0x0b +#define NAU8325_R0C_TDM_CTRL 0x0c +#define NAU8325_R0D_I2S_PCM_CTRL1 0x0d +#define NAU8325_R0E_I2S_PCM_CTRL2 0x0e +#define NAU8325_R0F_L_TIME_SLOT 0x0f +#define NAU8325_R10_R_TIME_SLOT 0x10 +#define NAU8325_R11_HPF_CTRL 0x11 +#define NAU8325_R12_MUTE_CTRL 0x12 +#define NAU8325_R13_DAC_VOLUME 0x13 +#define NAU8325_R1D_DEBUG_READ1 0x1d +#define NAU8325_R1F_DEBUG_READ2 0x1f +#define NAU8325_R22_DEBUG_READ3 0x22 +#define NAU8325_R29_DAC_CTRL1 0x29 +#define NAU8325_R2A_DAC_CTRL2 0x2a +#define NAU8325_R2C_ALC_CTRL1 0x2c +#define NAU8325_R2D_ALC_CTRL2 0x2d +#define NAU8325_R2E_ALC_CTRL3 0x2e +#define NAU8325_R2F_ALC_CTRL4 0x2f +#define NAU8325_R40_CLK_DET_CTRL 0x40 +#define NAU8325_R49_TEST_STATUS 0x49 +#define NAU8325_R4A_ANALOG_READ 0x4a +#define NAU8325_R50_MIXER_CTRL 0x50 +#define NAU8325_R55_MISC_CTRL 0x55 +#define NAU8325_R60_BIAS_ADJ 0x60 +#define NAU8325_R61_ANALOG_CONTROL_1 0x61 +#define NAU8325_R62_ANALOG_CONTROL_2 0x62 +#define NAU8325_R63_ANALOG_CONTROL_3 0x63 +#define NAU8325_R64_ANALOG_CONTROL_4 0x64 +#define NAU8325_R65_ANALOG_CONTROL_5 0x65 +#define NAU8325_R66_ANALOG_CONTROL_6 0x66 +#define NAU8325_R69_CLIP_CTRL 0x69 +#define NAU8325_R73_RDAC 0x73 +#define NAU8325_REG_MAX NAU8325_R73_RDAC + +/* 16-bit control register address, and 16-bits control register data */ +#define NAU8325_REG_ADDR_LEN 16 +#define NAU8325_REG_DATA_LEN 16 + +/* CLK_CTRL (0x03) */ +#define NAU8325_CLK_DAC_SRC_SFT 12 +#define NAU8325_CLK_DAC_SRC_MASK (0x3 << NAU8325_CLK_DAC_SRC_SFT) +#define NAU8325_CLK_MUL_SRC_SFT 6 +#define NAU8325_CLK_MUL_SRC_MASK (0x3 << NAU8325_CLK_MUL_SRC_SFT) +#define NAU8325_MCLK_SEL_SFT 3 +#define NAU8325_MCLK_SEL_MASK (0x7 << NAU8325_MCLK_SEL_SFT) +#define NAU8325_MCLK_SRC_MASK 0x7 + +/* ENA_CTRL (0x04) */ +#define NAU8325_DAC_LEFT_CH_EN_SFT 3 +#define NAU8325_DAC_LEFT_CH_EN (0x1 << NAU8325_DAC_LEFT_CH_EN_SFT) +#define NAU8325_DAC_RIGHT_CH_EN_SFT 2 +#define NAU8325_DAC_RIGHT_CH_EN (0x1 << NAU8325_DAC_RIGHT_CH_EN_SFT) + +/* INTERRUPT_CTRL (0x05) */ +#define NAU8325_ARP_DWN_INT_SFT 12 +#define NAU8325_ARP_DWN_INT_MASK (0x1 << NAU8325_ARP_DWN_INT_SFT) +#define NAU8325_CLIP_INT_SFT 11 +#define NAU8325_CLIP_INT_MASK (0x1 << NAU8325_CLIP_INT_SFT) +#define NAU8325_LVD_INT_SFT 10 +#define NAU8325_LVD_INT_MASK (0x1 << NAU8325_LVD_INT_SFT) +#define NAU8325_PWR_INT_DIS_SFT 8 +#define NAU8325_PWR_INT_DIS (0x1 << NAU8325_PWR_INT_DIS_SFT) +#define NAU8325_OCP_OTP_SHTDWN_INT_SFT 4 +#define NAU8325_OCP_OTP_SHTDWN_INT_MASK (0x1 << NAU8325_OCP_OTP_SHTDWN_INT_SFT) +#define NAU8325_CLIP_INT_DIS_SFT 3 +#define NAU8325_CLIP_INT_DIS (0x1 << NAU8325_CLIP_INT_DIS_SFT) +#define NAU8325_LVD_INT_DIS_SFT 2 +#define NAU8325_LVD_INT_DIS (0x1 << NAU8325_LVD_INT_DIS_SFT) +#define NAU8325_PWR_INT_MASK 0x1 + +/* INT_CLR_STATUS (0x06) */ +#define NAU8325_INT_STATUS_MASK 0x7f + +/* IRQOUT (0x9) */ +#define NAU8325_IRQOUT_SEL_SEF 12 +#define NAU8325_IRQOUT_SEL_MASK (0xf << NAU8325_IRQOUT_SEL_SEF) +#define NAU8325_DEM_DITH_SFT 7 +#define NAU8325_DEM_DITH_EN (0x1 << NAU8325_DEM_DITH_SFT) +#define NAU8325_GAINZI3_SFT 5 +#define NAU8325_GAINZI3_MASK (0x1 << NAU8325_GAINZI3_SFT) +#define NAU8325_GAINZI2_MASK 0x1f + +/* IO_CTRL (0x0a) */ +#define NAU8325_IRQ_PL_SFT 15 +#define NAU8325_IRQ_PL_ACT_HIGH (0x1 << NAU8325_IRQ_PL_SFT) +#define NAU8325_IRQ_PS_SFT 14 +#define NAU8325_IRQ_PS_UP (0x1 << NAU8325_IRQ_PS_SFT) +#define NAU8325_IRQ_PE_SFT 13 +#define NAU8325_IRQ_PE_EN (0x1 << NAU8325_IRQ_PE_SFT) +#define NAU8325_IRQ_DS_SFT 12 +#define NAU8325_IRQ_DS_HIGH (0x1 << NAU8325_IRQ_DS_SFT) +#define NAU8325_IRQ_OUTPUT_SFT 11 +#define NAU8325_IRQ_OUTPUT_EN (0x1 << NAU8325_IRQ_OUTPUT_SFT) +#define NAU8325_IRQ_PIN_DEBUG_SFT 10 +#define NAU8325_IRQ_PIN_DEBUG_EN (0x1 << NAU8325_IRQ_PIN_DEBUG_SFT) + +/* PDM_CTRL (0x0b) */ +#define NAU8325_PDM_LCH_EDGE_SFT 1 +#define NAU8325_PDM_LCH_EDGE__MASK (0x1 << NAU8325_PDM_LCH_EDGE_SFT) +#define NAU8325_PDM_MODE_EN 0x1 + +/* TDM_CTRL (0x0c) */ +#define NAU8325_TDM_SFT 15 +#define NAU8325_TDM_EN (0x1 << NAU8325_TDM_SFT) +#define NAU8325_PCM_OFFSET_CTRL_SFT 14 +#define NAU8325_PCM_OFFSET_CTRL_EN (0x1 << NAU8325_PCM_OFFSET_CTRL_SFT) +#define NAU8325_DAC_LEFT_SFT 6 +#define NAU8325_NAU8325_DAC_LEFT_MASK (0x7 << NAU8325_DAC_LEFT_SFT) +#define NAU8325_DAC_RIGHT_SFT 3 +#define NAU8325_DAC_RIGHT_MASK (0x7 << NAU8325_DAC_RIGHT_SFT) + +/* I2S_PCM_CTRL1 (0x0d) */ +#define NAU8325_DACCM_CTL_SFT 14 +#define NAU8325_DACCM_CTL_MASK (0x3 << NAU8325_DACCM_CTL_SFT) +#define NAU8325_CMB8_0_SFT 10 +#define NAU8325_CMB8_0_MASK (0x1 << NAU8325_CMB8_0_SFT) +#define NAU8325_UA_OFFSET_SFT 9 +#define NAU8325_UA_OFFSET_MASK (0x1 << NAU8325_UA_OFFSET_SFT) +#define NAU8325_I2S_BP_SFT 7 +#define NAU8325_I2S_BP_MASK (0x1 << NAU8325_I2S_BP_SFT) +#define NAU8325_I2S_BP_INV (0x1 << NAU8325_I2S_BP_SFT) +#define NAU8325_I2S_PCMB_SFT 6 +#define NAU8325_I2S_PCMB_EN (0x1 << NAU8325_I2S_PCMB_SFT) +#define NAU8325_I2S_DACPSHS0_SFT 5 +#define NAU8325_I2S_DACPSHS0_MASK (0x1 << NAU8325_I2S_DACPSHS0_SFT) +#define NAU8325_I2S_DL_SFT 2 +#define NAU8325_I2S_DL_MASK (0x3 << NAU8325_I2S_DL_SFT) +#define NAU8325_I2S_DL_32 (0x3 << NAU8325_I2S_DL_SFT) +#define NAU8325_I2S_DL_24 (0x2 << NAU8325_I2S_DL_SFT) +#define NAU8325_I2S_DL_20 (0x1 << NAU8325_I2S_DL_SFT) +#define NAU8325_I2S_DL_16 (0x0 << NAU8325_I2S_DL_SFT) +#define NAU8325_I2S_DF_MASK 0x3 +#define NAU8325_I2S_DF_RIGTH 0x0 +#define NAU8325_I2S_DF_LEFT 0x1 +#define NAU8325_I2S_DF_I2S 0x2 +#define NAU8325_I2S_DF_PCM_AB 0x3 + +/* I2S_PCM_CTRL2 (0x0e) */ +#define NAU8325_PCM_TS_SFT 10 +#define NAU8325_PCM_TS_EN (0x1 << NAU8325_PCM_TS_SFT) +#define NAU8325_PCM8BIT0_SFT 8 +#define NAU8325_PCM8BIT0_MASK (0x1 << NAU8325_PCM8BIT0_SFT) + +/* L_TIME_SLOT (0x0f)*/ +#define NAU8325_SHORT_FS_DET_SFT 13 +#define NAU8325_SHORT_FS_DET_DIS (0x1 << NAU8325_SHORT_FS_DET_SFT) +#define NAU8325_TSLOT_L0_MASK 0x3ff + +/* R_TIME_SLOT (0x10)*/ +#define NAU8325_TSLOT_R0_MASK 0x3ff + +/* HPF_CTRL (0x11)*/ +#define NAU8325_DAC_HPF_SFT 15 +#define NAU8325_DAC_HPF_EN (0x1 << NAU8325_DAC_HPF_SFT) +#define NAU8325_DAC_HPF_APP_SFT 14 +#define NAU8325_DAC_HPF_APP_MASK (0x1 << NAU8325_DAC_HPF_APP_SFT) +#define NAU8325_DAC_HPF_FCUT_SFT 11 +#define NAU8325_DAC_HPF_FCUT_MASK (0x7 << NAU8325_DAC_HPF_FCUT_SFT) + +/* MUTE_CTRL (0x12)*/ +#define NAU8325_SOFT_MUTE_SFT 15 +#define NAU8325_SOFT_MUTE (0x1 << NAU8325_SOFT_MUTE_SFT) +#define NAU8325_DAC_ZC_SFT 8 +#define NAU8325_DAC_ZC_EN (0x1 << NAU8325_DAC_ZC_SFT) +#define NAU8325_UNMUTE_CTL_SFT 6 +#define NAU8325_UNMUTE_CTL_MASK (0x3 << NAU8325_UNMUTE_CTL_SFT) +#define NAU8325_ANA_MUTE_SFT 4 +#define NAU8325_ANA_MUTE_MASK (0x3 << NAU8325_ANA_MUTE_SFT) +#define NAU8325_AUTO_MUTE_SFT 3 +#define NAU8325_AUTO_MUTE_DIS (0x1 << NAU8325_AUTO_MUTE_SFT) + +/* DAC_VOLUME (0x13) */ +#define NAU8325_DAC_VOLUME_L_SFT 8 +#define NAU8325_DAC_VOLUME_L_EN (0xff << NAU8325_DAC_VOLUME_L_SFT) +#define NAU8325_DAC_VOLUME_R_SFT 0 +#define NAU8325_DAC_VOLUME_R_EN (0xff << NAU8325_DAC_VOLUME_R_SFT) +#define NAU8325_DAC_VOL_MAX 0xff + +/* DEBUG_READ1 (0x1d)*/ +#define NAU8325_OSR100_MASK (0x1 << 6) +#define NAU8325_MIPS500_MASK (0x1 << 5) +#define NAU8325_SHUTDWNDRVR_R_MASK (0x1 << 4) +#define NAU8325_SHUTDWNDRVR_L_MASK (0x1 << 3) +#define NAU8325_MUTEB_MASK (0x1 << 2) +#define NAU8325_PDOSCB_MASK (0x1 << 1) +#define NAU8325_POWERDOWN1B_D_MASK 0x1 + +/* DEBUG_READ2 (0x1f)*/ +#define NAU8325_R_CHANNEL_Vol_SFT 8 +#define NAU8325_R_CHANNEL_Vol_MASK (0xff << NAU8325_R_CHANNEL_Vol_SFT) +#define NAU8325_L_CHANNEL_Vol_MASK 0xff + +/* DEBUG_READ3(0x22)*/ +#define NAU8325_PGAL_GAIN_MASK (0x3f << 7) +#define NAU8325_CLIP_MASK (0x1 << 6) +#define NAU8325_SCAN_MODE_MASK (0x1 << 5) +#define NAU8325_SDB_MASK (0x1 << 4) +#define NAU8325_TALARM_MASK (0x1 << 3) +#define NAU8325_SHORTR_MASK (0x1 << 2) +#define NAU8325_SHORTL_MASK (0x1 << 1) +#define NAU8325_TMDET_MASK 0x1 + +/* DAC_CTRL1 (0x29) */ +#define NAU8325_DAC_OVERSAMPLE_SFT 0 +#define NAU8325_DAC_OVERSAMPLE_MASK 0x7 +#define NAU8325_DAC_OVERSAMPLE_256 1 +#define NAU8325_DAC_OVERSAMPLE_128 2 +#define NAU8325_DAC_OVERSAMPLE_64 0 +#define NAU8325_DAC_OVERSAMPLE_32 4 + +/* ALC_CTRL1 (0x2c) */ +#define NAU8325_ALC_MAXGAIN_SFT 5 +#define NAU8325_ALC_MAXGAIN_MAX 0x7 +#define NAU8325_ALC_MAXGAIN_MASK (0x7 << NAU8325_ALC_MAXGAIN_SFT) +#define NAU8325_ALC_MINGAIN_MAX 4 +#define NAU8325_ALC_MINGAIN_SFT 1 +#define NAU8325_ALC_MINGAIN_MASK (0x7 << NAU8325_ALC_MINGAIN_SFT) + +/* ALC_CTRL2 (0x2d) */ +#define NAU8325_ALC_DCY_SFT 12 +#define NAU8325_ALC_DCY_MAX 0xb +#define NAU8325_ALC_DCY_MASK (0xf << NAU8325_ALC_DCY_SFT) +#define NAU8325_ALC_ATK_SFT 8 +#define NAU8325_ALC_ATK_MAX 0xb +#define NAU8325_ALC_ATK_MASK (0xf << NAU8325_ALC_ATK_SFT) +#define NAU8325_ALC_HLD_SFT 4 +#define NAU8325_ALC_HLD_MAX 0xa +#define NAU8325_ALC_HLD_MASK (0xf << NAU8325_ALC_HLD_SFT) +#define NAU8325_ALC_LVL_SFT 0 +#define NAU8325_ALC_LVL_MAX 0xf +#define NAU8325_ALC_LVL_MASK 0xf + +/* ALC_CTRL3 (0x2e) */ +#define NAU8325_ALC_EN_SFT 15 +#define NAU8325_ALC_EN (0x1 << NAU8325_ALC_EN_SFT) + +/* TEMP_COMP_CTRL (0x30) */ +#define NAU8325_TEMP_COMP_ACT2_MASK 0xff + +/* LPF_CTRL (0x33) */ +#define NAU8325_LPF_IN1_EN_SFT 15 +#define NAU8325_LPF_IN1_EN (0x1 << NAU8325_LPF_IN1_EN_SFT) +#define NAU8325_LPF_IN1_TC_SFT 11 +#define NAU8325_LPF_IN1_TC_MASK (0xf << NAU8325_LPF_IN1_TC_SFT) +#define NAU8325_LPF_IN2_EN_SFT 10 +#define NAU8325_LPF_IN2_EN (0x1 << NAU8325_LPF_IN2_EN_SFT) +#define NAU8325_LPF_IN2_TC_SFT 6 +#define NAU8325_LPF_IN2_TC_MASK (0xf << NAU8325_LPF_IN2_TC_SFT) + +/* CLK_DET_CTRL (0x40) */ +#define NAU8325_APWRUP_SFT 15 +#define NAU8325_APWRUP_EN (0x1 << NAU8325_APWRUP_SFT) +#define NAU8325_CLKPWRUP_SFT 14 +#define NAU8325_CLKPWRUP_DIS (0x1 << NAU8325_CLKPWRUP_SFT) +#define NAU8325_PWRUP_DFT_SFT 13 +#define NAU8325_PWRUP_DFT (0x1 << NAU8325_PWRUP_DFT_SFT) +#define NAU8325_REG_SRATE_SFT 10 +#define NAU8325_REG_SRATE_MASK (0x7 << NAU8325_REG_SRATE_SFT) +#define NAU8325_REG_ALT_SRATE_SFT 9 +#define NAU8325_REG_ALT_SRATE_EN (0x1 << NAU8325_REG_ALT_SRATE_SFT) +#define NAU8325_REG_DIV_MAX 0x1 + +/* BIAS_ADJ (0x60) */ +#define NAU8325_BIAS_VMID_SEL_SFT 4 +#define NAU8325_BIAS_VMID_SEL_MASK (0x3 << NAU8325_BIAS_VMID_SEL_SFT) + +/* ANALOG_CONTROL_1 (0x61) */ +#define NAU8325_VMDFSTENB_SFT 14 +#define NAU8325_VMDFSTENB_MASK (0x3 << NAU8325_VMDFSTENB_SFT) +#define NAU8325_CLASSDEN_SFT 12 +#define NAU8325_CLASSDEN_MASK (0x3 << NAU8325_CLASSDEN_SFT) +#define NAU8325_DACCLKEN_R_SFT 10 +#define NAU8325_DACCLKEN_R_MASK (0x3 << NAU8325_DACCLKEN_R_SFT) +#define NAU8325_DACEN_R_SFT 8 +#define NAU8325_DACEN_R_MASK (0x3 << NAU8325_DACEN_R_SFT) +#define NAU8325_DACCLKEN_SFT 6 +#define NAU8325_DACCLKEN_MASK (0x3 << NAU8325_DACCLKEN_SFT) +#define NAU8325_DACEN_SFT 4 +#define NAU8325_DACEN_MASK (0x3 << NAU8325_DACEN_SFT) +#define NAU8325_BIASEN_SFT 2 +#define NAU8325_BIASEN_MASK (0x3 << NAU8325_BIASEN_SFT) +#define NAU8325_VMIDEN_MASK 0x3 + +/* ANALOG_CONTROL_2 (0x62) */ +#define NAU8325_PWMMOD_SFT 14 +#define NAU8325_PWMMOD_MASK (0x1 << NAU8325_PWMMOD_SFT) +#define NAU8325_DACTEST_SFT 6 +#define NAU8325_DACTEST_MASK (0x3 << NAU8325_DACTEST_SFT) +#define NAU8325_DACREFCAP_SFT 4 +#define NAU8325_DACREFCAP_MASK (0x3 << NAU8325_DACREFCAP_SFT) + +/* ANALOG_CONTROL_3 (0x63) */ +#define NAU8325_POWER_DOWN_L_SFT 12 +#define NAU8325_POWER_DOWN_L_MASK (0x3 << NAU8325_POWER_DOWN_L_SFT) +#define NAU8325_POWER_DOWN_R_SFT 11 +#define NAU8325_POWER_DOWN_R_MASK (0x3 << NAU8325_DACREFCAP_SFT) +#define NAU8325_CLASSD_FINE_SFT 5 +#define NAU8325_CLASSD_FINE_MASK (0x3 << NAU8325_CLASSD_FINE_SFT) +#define NAU8325_CLASSD_COARSE_GAIN_MASK 0xf + +/* ANALOG_CONTROL_4 (0x64) */ +#define NAU8325_CLASSD_OCPN_SFT 12 +#define NAU8325_CLASSD_OCPN_MASK (0xf << NAU8325_CLASSD_OCPN_SFT) +#define NAU8325_CLASSD_OCPP_SFT 8 +#define NAU8325_CLASSD_OCPP_MASK (0xf << NAU8325_CLASSD_OCPP_SFT) +#define NAU8325_CLASSD_SLEWN_MASK 0xff + +/* ANALOG_CONTROL_5 (0x65) */ +#define NAU8325_MCLK_RANGE_SFT 2 +#define NAU8325_MCLK_RANGE_EN (0x1 << NAU8325_MCLK_RANGE_SFT) +#define NAU8325_MCLK8XEN_SFT 1 +#define NAU8325_MCLK8XEN_EN (0x1 << NAU8325_MCLK8XEN_SFT) +#define NAU8325_MCLK4XEN_EN 0x1 + +/* ANALOG_CONTROL_6 (0x66) */ +#define NAU8325_VBATLOW_SFT 4 +#define NAU8325_VBATLOW_MASK (0x1 << NAU8325_VBATLOW_SFT) +#define NAU8325_VDDSPK_LIM_SFT 3 +#define NAU8325_VDDSPK_LIM_EN (0x1 << NAU8325_VDDSPK_LIM_SFT) +#define NAU8325_VDDSPK_LIM_MASK 0x7 + +/* CLIP_CTRL (0x69)*/ +#define NAU8325_ANTI_CLIP_SFT 4 +#define NAU8325_ANTI_CLIP_EN (0x1 << NAU8325_ANTI_CLIP_SFT) + +/* RDAC (0x73) */ +#define NAU8325_CLK_DAC_DELAY_SFT 4 +#define NAU8325_CLK_DAC_DELAY_EN (0x7 << NAU8325_CLK_DAC_DELAY_SFT) +#define NAU8325_DACVREFSEL_SFT 2 +#define NAU8325_DACVREFSEL_MASK (0x3 << NAU8325_DACVREFSEL_SFT) + +#define NAU8325_CODEC_DAI "nau8325-hifi" + +struct nau8325 { + struct device *dev; + struct regmap *regmap; + int mclk; + int fs; + int vref_impedance_ohms; + int dac_vref_microvolt; + int clock_detection; + int clock_det_data; + int alc_enable; +}; + +struct nau8325_src_attr { + int param; + unsigned int val; +}; + +enum { + NAU8325_MCLK_FS_RATIO_256, + NAU8325_MCLK_FS_RATIO_400, + NAU8325_MCLK_FS_RATIO_500, + NAU8325_MCLK_FS_RATIO_NUM, +}; + +struct nau8325_srate_attr { + int fs; + int range; + bool max; + unsigned int mclk_src[NAU8325_MCLK_FS_RATIO_NUM]; +}; + +struct nau8325_osr_attr { + unsigned int osr; + unsigned int clk_src; +}; + +#endif /* __NAU8325_H__ */ -- cgit v1.2.3 From 9b21531866fced634bcc7fca33667c7ef258433f Mon Sep 17 00:00:00 2001 From: Frank Li Date: Thu, 28 Mar 2024 10:51:33 -0400 Subject: ASoC: dt-bindings: fsl,imx-asrc/spdif: Add power-domains property Add power-domains property for asrc and spdif since fsl,imx8qm-asrc/spdif and fsl,imx8qxp-asrc/spdif require 'power-domains'. Set 'power-domains' as required property for compatible string fsl,imx8qm-asrc/spdif and fsl,imx8qxp-asrc/spdif. Acked-by: Conor Dooley Signed-off-by: Frank Li Link: https://msgid.link/r/20240328-asrc_8qxp-v8-1-801cd6bb5be2@nxp.com Signed-off-by: Mark Brown --- Documentation/devicetree/bindings/sound/fsl,imx-asrc.yaml | 14 ++++++++++++++ Documentation/devicetree/bindings/sound/fsl,spdif.yaml | 15 +++++++++++++++ 2 files changed, 29 insertions(+) diff --git a/Documentation/devicetree/bindings/sound/fsl,imx-asrc.yaml b/Documentation/devicetree/bindings/sound/fsl,imx-asrc.yaml index bfef2fcb75b1..76aa1f248488 100644 --- a/Documentation/devicetree/bindings/sound/fsl,imx-asrc.yaml +++ b/Documentation/devicetree/bindings/sound/fsl,imx-asrc.yaml @@ -74,6 +74,9 @@ properties: - const: asrck_f - const: spba + power-domains: + maxItems: 1 + fsl,asrc-rate: $ref: /schemas/types.yaml#/definitions/uint32 description: The mutual sample rate used by DPCM Back Ends @@ -131,6 +134,17 @@ allOf: properties: fsl,asrc-clk-map: false + - if: + properties: + compatible: + contains: + enum: + - fsl,imx8qm-asrc + - fsl,imx8qxp-asrc + then: + required: + - power-domains + additionalProperties: false examples: diff --git a/Documentation/devicetree/bindings/sound/fsl,spdif.yaml b/Documentation/devicetree/bindings/sound/fsl,spdif.yaml index 1d64e8337aa4..56f8c0c8afde 100644 --- a/Documentation/devicetree/bindings/sound/fsl,spdif.yaml +++ b/Documentation/devicetree/bindings/sound/fsl,spdif.yaml @@ -86,6 +86,9 @@ properties: registers. Set this flag for HCDs with big endian descriptors and big endian registers. + power-domains: + maxItems: 1 + required: - compatible - reg @@ -97,6 +100,18 @@ required: additionalProperties: false +allOf: + - if: + properties: + compatible: + contains: + enum: + - fsl,imx8qm-spdif + - fsl,imx8qxp-spdif + then: + required: + - power-domains + examples: - | spdif@2004000 { -- cgit v1.2.3 From 82330327ce03889f20072cef5167499d51cdf260 Mon Sep 17 00:00:00 2001 From: Frank Li Date: Thu, 28 Mar 2024 10:51:34 -0400 Subject: ASoC: dt-bindings: fsl,imx-asrc: update max interrupt numbers fsl,imx8qxp-spdif and fsl,imx8qm-spdif have 2 interrupts. Other platforms have 1 interrupt. Increase max interrupt number to 2 and add restriction for platforms except i.MX8QXP and i.MX8QM. Reviewed-by: Rob Herring Signed-off-by: Frank Li Link: https://msgid.link/r/20240328-asrc_8qxp-v8-2-801cd6bb5be2@nxp.com Signed-off-by: Mark Brown --- .../devicetree/bindings/sound/fsl,spdif.yaml | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/Documentation/devicetree/bindings/sound/fsl,spdif.yaml b/Documentation/devicetree/bindings/sound/fsl,spdif.yaml index 56f8c0c8afde..204f361cea27 100644 --- a/Documentation/devicetree/bindings/sound/fsl,spdif.yaml +++ b/Documentation/devicetree/bindings/sound/fsl,spdif.yaml @@ -31,7 +31,10 @@ properties: maxItems: 1 interrupts: - maxItems: 1 + minItems: 1 + items: + - description: Combined or receive interrupt + - description: Transmit interrupt dmas: items: @@ -101,6 +104,21 @@ required: additionalProperties: false allOf: + - if: + properties: + compatible: + enum: + - fsl,imx8qm-spdif + - fsl,imx8qxp-spdif + then: + properties: + interrupts: + minItems: 2 + else: + properties: + interrupts: + maxItems: 1 + - if: properties: compatible: -- cgit v1.2.3 From 7b5f2072657a9041cbaf4ba139f672be11694ca3 Mon Sep 17 00:00:00 2001 From: Frank Li Date: Thu, 28 Mar 2024 10:51:35 -0400 Subject: ASoC: dt-bindings: fsl-sai: allow only one dma-names Some sai only connect one direction dma (rx/tx) in SOC. For example: imx8qxp sai5 only connect tx dma channel. So allow only one "rx" or "tx" for dma-names. Remove description under dmas because no user use index to get dma channel. All user use 'dma-names' to get correct dma channel. dma-names already in 'required' list. Reviewed-by: Rob Herring Signed-off-by: Frank Li Link: https://msgid.link/r/20240328-asrc_8qxp-v8-3-801cd6bb5be2@nxp.com Signed-off-by: Mark Brown --- Documentation/devicetree/bindings/sound/fsl,sai.yaml | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/Documentation/devicetree/bindings/sound/fsl,sai.yaml b/Documentation/devicetree/bindings/sound/fsl,sai.yaml index 2456d958adee..a5d9c246cc47 100644 --- a/Documentation/devicetree/bindings/sound/fsl,sai.yaml +++ b/Documentation/devicetree/bindings/sound/fsl,sai.yaml @@ -81,14 +81,12 @@ properties: dmas: minItems: 1 - items: - - description: DMA controller phandle and request line for RX - - description: DMA controller phandle and request line for TX + maxItems: 2 dma-names: minItems: 1 items: - - const: rx + - enum: [ rx, tx ] - const: tx interrupts: -- cgit v1.2.3 From ea60ab95723f5738e7737b56dda95e6feefa5b50 Mon Sep 17 00:00:00 2001 From: Aleksandr Mishin Date: Thu, 28 Mar 2024 20:33:37 +0300 Subject: ASoC: kirkwood: Fix potential NULL dereference In kirkwood_dma_hw_params() mv_mbus_dram_info() returns NULL if CONFIG_PLAT_ORION macro is not defined. Fix this bug by adding NULL check. Found by Linux Verification Center (linuxtesting.org) with SVACE. Fixes: bb6a40fc5a83 ("ASoC: kirkwood: Fix reference to PCM buffer address") Signed-off-by: Aleksandr Mishin Link: https://msgid.link/r/20240328173337.21406-1-amishin@t-argos.ru Signed-off-by: Mark Brown --- sound/soc/kirkwood/kirkwood-dma.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/sound/soc/kirkwood/kirkwood-dma.c b/sound/soc/kirkwood/kirkwood-dma.c index dd2f806526c1..ef00792e1d49 100644 --- a/sound/soc/kirkwood/kirkwood-dma.c +++ b/sound/soc/kirkwood/kirkwood-dma.c @@ -182,6 +182,9 @@ static int kirkwood_dma_hw_params(struct snd_soc_component *component, const struct mbus_dram_target_info *dram = mv_mbus_dram_info(); unsigned long addr = substream->runtime->dma_addr; + if (!dram) + return 0; + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) kirkwood_dma_conf_mbus_windows(priv->io, KIRKWOOD_PLAYBACK_WIN, addr, dram); -- cgit v1.2.3 From 7a84602297d36617dbdadeba55a2567031e5165b Mon Sep 17 00:00:00 2001 From: Jeff Layton Date: Tue, 19 Mar 2024 12:34:45 -0400 Subject: 9p: explicitly deny setlease attempts 9p is a remote network protocol, and it doesn't support asynchronous notifications from the server. Ensure that we don't hand out any leases since we can't guarantee they'll be broken when a file's contents change. Signed-off-by: Jeff Layton Signed-off-by: Eric Van Hensbergen --- fs/9p/vfs_file.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/fs/9p/vfs_file.c b/fs/9p/vfs_file.c index abdbbaee5184..348cc90bf9c5 100644 --- a/fs/9p/vfs_file.c +++ b/fs/9p/vfs_file.c @@ -520,6 +520,7 @@ const struct file_operations v9fs_file_operations = { .splice_read = v9fs_file_splice_read, .splice_write = iter_file_splice_write, .fsync = v9fs_file_fsync, + .setlease = simple_nosetlease, }; const struct file_operations v9fs_file_operations_dotl = { @@ -534,4 +535,5 @@ const struct file_operations v9fs_file_operations_dotl = { .splice_read = v9fs_file_splice_read, .splice_write = iter_file_splice_write, .fsync = v9fs_file_fsync_dotl, + .setlease = simple_nosetlease, }; -- cgit v1.2.3 From 7f1dd39aedfccf60772328c5b88d56dbd39954c3 Mon Sep 17 00:00:00 2001 From: Uwe Kleine-König Date: Wed, 27 Mar 2024 08:33:10 +0100 Subject: clk: Provide !COMMON_CLK dummy for devm_clk_rate_exclusive_get() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit To be able to compile drivers using devm_clk_rate_exclusive_get() also on platforms without the common clk framework, add a dummy implementation that does the same as clk_rate_exclusive_get() in that case (i.e. nothing). Reported-by: kernel test robot Closes: https://lore.kernel.org/oe-kbuild-all/202403270305.ydvX9xq1-lkp@intel.com/ Fixes: b0cde62e4c54 ("clk: Add a devm variant of clk_rate_exclusive_get()") Signed-off-by: Uwe Kleine-König Link: https://lore.kernel.org/r/20240327073310.520950-2-u.kleine-koenig@pengutronix.de Signed-off-by: Stephen Boyd --- include/linux/clk.h | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/include/linux/clk.h b/include/linux/clk.h index 00623f4de5e1..0fa56d672532 100644 --- a/include/linux/clk.h +++ b/include/linux/clk.h @@ -286,6 +286,11 @@ static inline int clk_rate_exclusive_get(struct clk *clk) return 0; } +static inline int devm_clk_rate_exclusive_get(struct device *dev, struct clk *clk) +{ + return 0; +} + static inline void clk_rate_exclusive_put(struct clk *clk) {} #endif -- cgit v1.2.3 From c90847bcbfb65d0f1c48fcc73a2b3a2d4ceac6a1 Mon Sep 17 00:00:00 2001 From: Samuel Holland Date: Tue, 26 Mar 2024 22:45:24 -0700 Subject: cache: sifive_ccache: Partially convert to a platform driver Commit 8ec99b033147 ("irqchip/sifive-plic: Convert PLIC driver into a platform driver") broke ccache initialization because the PLIC IRQ domain is no longer available during an arch_initcall: [ 0.087229] irq: no irq domain found for interrupt-controller@c000000 ! [ 0.087255] CCACHE: Could not request IRQ 0 Fix this by moving the IRQ handling code to a platform driver. Fixes: 8ec99b033147 ("irqchip/sifive-plic: Convert PLIC driver into a platform driver") Signed-off-by: Samuel Holland Tested-by: Geert Uytterhoeven Signed-off-by: Conor Dooley --- drivers/cache/sifive_ccache.c | 72 +++++++++++++++++++++++++++---------------- 1 file changed, 46 insertions(+), 26 deletions(-) diff --git a/drivers/cache/sifive_ccache.c b/drivers/cache/sifive_ccache.c index 89ed6cd6b059..e9cc8b4786fb 100644 --- a/drivers/cache/sifive_ccache.c +++ b/drivers/cache/sifive_ccache.c @@ -15,6 +15,8 @@ #include #include #include +#include +#include #include #include #include @@ -247,13 +249,49 @@ static irqreturn_t ccache_int_handler(int irq, void *device) return IRQ_HANDLED; } +static int sifive_ccache_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + unsigned long quirks; + int intr_num, rc; + + quirks = (unsigned long)device_get_match_data(dev); + + intr_num = platform_irq_count(pdev); + if (!intr_num) + return dev_err_probe(dev, -ENODEV, "No interrupts property\n"); + + for (int i = 0; i < intr_num; i++) { + if (i == DATA_UNCORR && (quirks & QUIRK_BROKEN_DATA_UNCORR)) + continue; + + g_irq[i] = platform_get_irq(pdev, i); + if (g_irq[i] < 0) + return g_irq[i]; + + rc = devm_request_irq(dev, g_irq[i], ccache_int_handler, 0, "ccache_ecc", NULL); + if (rc) + return dev_err_probe(dev, rc, "Could not request IRQ %d\n", g_irq[i]); + } + + return 0; +} + +static struct platform_driver sifive_ccache_driver = { + .probe = sifive_ccache_probe, + .driver = { + .name = "sifive_ccache", + .of_match_table = sifive_ccache_ids, + }, +}; + static int __init sifive_ccache_init(void) { struct device_node *np; struct resource res; - int i, rc, intr_num; const struct of_device_id *match; unsigned long quirks; + int rc; np = of_find_matching_node_and_match(NULL, sifive_ccache_ids, &match); if (!np) @@ -277,28 +315,6 @@ static int __init sifive_ccache_init(void) goto err_unmap; } - intr_num = of_property_count_u32_elems(np, "interrupts"); - if (!intr_num) { - pr_err("No interrupts property\n"); - rc = -ENODEV; - goto err_unmap; - } - - for (i = 0; i < intr_num; i++) { - g_irq[i] = irq_of_parse_and_map(np, i); - - if (i == DATA_UNCORR && (quirks & QUIRK_BROKEN_DATA_UNCORR)) - continue; - - rc = request_irq(g_irq[i], ccache_int_handler, 0, "ccache_ecc", - NULL); - if (rc) { - pr_err("Could not request IRQ %d\n", g_irq[i]); - goto err_free_irq; - } - } - of_node_put(np); - #ifdef CONFIG_RISCV_NONSTANDARD_CACHE_OPS if (quirks & QUIRK_NONSTANDARD_CACHE_OPS) { riscv_cbom_block_size = SIFIVE_CCACHE_LINE_SIZE; @@ -315,11 +331,15 @@ static int __init sifive_ccache_init(void) #ifdef CONFIG_DEBUG_FS setup_sifive_debug(); #endif + + rc = platform_driver_register(&sifive_ccache_driver); + if (rc) + goto err_unmap; + + of_node_put(np); + return 0; -err_free_irq: - while (--i >= 0) - free_irq(g_irq[i], NULL); err_unmap: iounmap(ccache_base); err_node_put: -- cgit v1.2.3 From 8cb10cba124c4798b6cb333245ecdc8dde78aeae Mon Sep 17 00:00:00 2001 From: Tim Harvey Date: Wed, 28 Feb 2024 12:02:15 -0800 Subject: arm64: dts: freescale: imx8mp-venice-gw72xx-2x: fix USB vbus regulator When using usb-conn-gpio to control USB role and VBUS, the vbus-supply property must be present in the usb-conn-gpio node. Additionally it should not be present in the phy node as that isn't what controls vbus and will upset the use count. This resolves an issue where VBUS is enabled with OTG in peripheral mode. Fixes: ad9a12f7a522 ("arm64: dts: imx8mp-venice: Fix USB connector description") Signed-off-by: Tim Harvey Signed-off-by: Shawn Guo --- arch/arm64/boot/dts/freescale/imx8mp-venice-gw72xx.dtsi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm64/boot/dts/freescale/imx8mp-venice-gw72xx.dtsi b/arch/arm64/boot/dts/freescale/imx8mp-venice-gw72xx.dtsi index 41c79d2ebdd6..f24b14744799 100644 --- a/arch/arm64/boot/dts/freescale/imx8mp-venice-gw72xx.dtsi +++ b/arch/arm64/boot/dts/freescale/imx8mp-venice-gw72xx.dtsi @@ -14,6 +14,7 @@ pinctrl-0 = <&pinctrl_usbcon1>; type = "micro"; label = "otg"; + vbus-supply = <®_usb1_vbus>; id-gpios = <&gpio3 21 GPIO_ACTIVE_HIGH>; port { @@ -183,7 +184,6 @@ }; &usb3_phy0 { - vbus-supply = <®_usb1_vbus>; status = "okay"; }; -- cgit v1.2.3 From 6f8e0aca838e163e81fde176e945161d50679339 Mon Sep 17 00:00:00 2001 From: Tim Harvey Date: Wed, 28 Feb 2024 12:02:16 -0800 Subject: arm64: dts: freescale: imx8mp-venice-gw73xx-2x: fix USB vbus regulator When using usb-conn-gpio to control USB role and VBUS, the vbus-supply property must be present in the usb-conn-gpio node. Additionally it should not be present in the phy node as that isn't what controls vbus and will upset the use count. This resolves an issue where VBUS is enabled with OTG in peripheral mode. Fixes: ad9a12f7a522 ("arm64: dts: imx8mp-venice: Fix USB connector description") Signed-off-by: Tim Harvey Signed-off-by: Shawn Guo --- arch/arm64/boot/dts/freescale/imx8mp-venice-gw73xx.dtsi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm64/boot/dts/freescale/imx8mp-venice-gw73xx.dtsi b/arch/arm64/boot/dts/freescale/imx8mp-venice-gw73xx.dtsi index d5c400b355af..f5491a608b2f 100644 --- a/arch/arm64/boot/dts/freescale/imx8mp-venice-gw73xx.dtsi +++ b/arch/arm64/boot/dts/freescale/imx8mp-venice-gw73xx.dtsi @@ -14,6 +14,7 @@ pinctrl-0 = <&pinctrl_usbcon1>; type = "micro"; label = "otg"; + vbus-supply = <®_usb1_vbus>; id-gpios = <&gpio3 21 GPIO_ACTIVE_HIGH>; port { @@ -202,7 +203,6 @@ }; &usb3_phy0 { - vbus-supply = <®_usb1_vbus>; status = "okay"; }; -- cgit v1.2.3 From 302b84e84d108b878efc56ebfea09474159be56b Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Thu, 28 Mar 2024 16:07:23 -0500 Subject: Revert "PCI: Mark LSI FW643 to avoid bus reset" This reverts commit 29a43dc130ce65d365a8ea9e1cc4bc51005a353e. 29a43dc130ce ("PCI: Mark LSI FW643 to avoid bus reset") by Edmund was based on the assumption that the LSI / Agere FW643 has a defect such that it can't recover after a Secondary Bus Reset (SBR). But Takashi Sakamoto reported that SBR works fine on this same FW643 device in an AMD Ryzen 5 2400G system, so apparently there is some other aspect of Edmund's system that accounts for the issue. The down side of 29a43dc130ce is that when the FW643 is assigned to a VM, avoiding the SBR means we leak data out of the VM. Revert 29a43dc130ce until we figure out a better solution. In the meantime, we can use the sysfs "reset_method" interface to restrict the available reset methods. Link: https://lore.kernel.org/r/20240328212302.1582483-1-helgaas@kernel.org Fixes: 29a43dc130ce ("PCI: Mark LSI FW643 to avoid bus reset") Reported-by: Takashi Sakamoto Link: https://lore.kernel.org/r/20240325012135.36861-1-o-takashi@sakamocchi.jp Signed-off-by: Bjorn Helgaas Reviewed-by: Takashi Sakamoto --- drivers/pci/quirks.c | 8 -------- 1 file changed, 8 deletions(-) diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c index bf4833221816..eff7f5df08e2 100644 --- a/drivers/pci/quirks.c +++ b/drivers/pci/quirks.c @@ -3765,14 +3765,6 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_ATHEROS, 0x003e, quirk_no_bus_reset); */ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_CAVIUM, 0xa100, quirk_no_bus_reset); -/* - * Apparently the LSI / Agere FW643 can't recover after a Secondary Bus - * Reset and requires a power-off or suspend/resume and rescan. Prevent - * use of that reset. - */ -DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_ATT, 0x5900, quirk_no_bus_reset); -DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_ATT, 0x5901, quirk_no_bus_reset); - /* * Some TI KeyStone C667X devices do not support bus/hot reset. The PCIESS * automatically disables LTSSM when Secondary Bus Reset is received and -- cgit v1.2.3 From b1f532a3b1e6d2e5559c7ace49322922637a28aa Mon Sep 17 00:00:00 2001 From: Sven Eckelmann Date: Mon, 12 Feb 2024 13:58:33 +0100 Subject: batman-adv: Avoid infinite loop trying to resize local TT If the MTU of one of an attached interface becomes too small to transmit the local translation table then it must be resized to fit inside all fragments (when enabled) or a single packet. But if the MTU becomes too low to transmit even the header + the VLAN specific part then the resizing of the local TT will never succeed. This can for example happen when the usable space is 110 bytes and 11 VLANs are on top of batman-adv. In this case, at least 116 byte would be needed. There will just be an endless spam of batman_adv: batadv0: Forced to purge local tt entries to fit new maximum fragment MTU (110) in the log but the function will never finish. Problem here is that the timeout will be halved all the time and will then stagnate at 0 and therefore never be able to reduce the table even more. There are other scenarios possible with a similar result. The number of BATADV_TT_CLIENT_NOPURGE entries in the local TT can for example be too high to fit inside a packet. Such a scenario can therefore happen also with only a single VLAN + 7 non-purgable addresses - requiring at least 120 bytes. While this should be handled proactively when: * interface with too low MTU is added * VLAN is added * non-purgeable local mac is added * MTU of an attached interface is reduced * fragmentation setting gets disabled (which most likely requires dropping attached interfaces) not all of these scenarios can be prevented because batman-adv is only consuming events without the the possibility to prevent these actions (non-purgable MAC address added, MTU of an attached interface is reduced). It is therefore necessary to also make sure that the code is able to handle also the situations when there were already incompatible system configuration are present. Cc: stable@vger.kernel.org Fixes: a19d3d85e1b8 ("batman-adv: limit local translation table max size") Reported-by: syzbot+a6a4b5bb3da165594cff@syzkaller.appspotmail.com Signed-off-by: Sven Eckelmann Signed-off-by: Simon Wunderlich --- net/batman-adv/translation-table.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/batman-adv/translation-table.c b/net/batman-adv/translation-table.c index b95c36765d04..2243cec18ecc 100644 --- a/net/batman-adv/translation-table.c +++ b/net/batman-adv/translation-table.c @@ -3948,7 +3948,7 @@ void batadv_tt_local_resize_to_mtu(struct net_device *soft_iface) spin_lock_bh(&bat_priv->tt.commit_lock); - while (true) { + while (timeout) { table_size = batadv_tt_local_table_transmit_size(bat_priv); if (packet_size_max >= table_size) break; -- cgit v1.2.3 From 0640f47b742667fca6aac174f7cd62b6c2c7532c Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Wed, 13 Mar 2024 17:43:05 +0100 Subject: drm/msm/dp: fix runtime PM leak on disconnect Make sure to put the runtime PM usage count (and suspend) also when receiving a disconnect event while in the ST_MAINLINK_READY state. This specifically avoids leaking a runtime PM usage count on every disconnect with display servers that do not automatically enable external displays when receiving a hotplug notification. Fixes: 5814b8bf086a ("drm/msm/dp: incorporate pm_runtime framework into DP driver") Cc: stable@vger.kernel.org # 6.8 Cc: Kuogee Hsieh Signed-off-by: Johan Hovold Reviewed-by: Abhinav Kumar Patchwork: https://patchwork.freedesktop.org/patch/582744/ Link: https://lore.kernel.org/r/20240313164306.23133-2-johan+linaro@kernel.org Signed-off-by: Abhinav Kumar --- drivers/gpu/drm/msm/dp/dp_display.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/gpu/drm/msm/dp/dp_display.c b/drivers/gpu/drm/msm/dp/dp_display.c index d80f89581760..ffa785ec641a 100644 --- a/drivers/gpu/drm/msm/dp/dp_display.c +++ b/drivers/gpu/drm/msm/dp/dp_display.c @@ -629,6 +629,7 @@ static int dp_hpd_unplug_handle(struct dp_display_private *dp, u32 data) dp_display_host_phy_exit(dp); dp->hpd_state = ST_DISCONNECTED; dp_display_notify_disconnect(&dp->dp_display.pdev->dev); + pm_runtime_put_sync(&pdev->dev); mutex_unlock(&dp->event_mutex); return 0; } -- cgit v1.2.3 From e86750b01a1560f198e4b3e21bb3f78bfd5bb2c3 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Wed, 13 Mar 2024 17:43:06 +0100 Subject: drm/msm/dp: fix runtime PM leak on connect failure Make sure to balance the runtime PM usage counter (and suspend) before returning on connect failures (e.g. DPCD read failures after a spurious connect event or if link training fails). Fixes: 5814b8bf086a ("drm/msm/dp: incorporate pm_runtime framework into DP driver") Cc: stable@vger.kernel.org # 6.8 Cc: Kuogee Hsieh Signed-off-by: Johan Hovold Reviewed-by: Abhinav Kumar Patchwork: https://patchwork.freedesktop.org/patch/582746/ Link: https://lore.kernel.org/r/20240313164306.23133-3-johan+linaro@kernel.org Signed-off-by: Abhinav Kumar --- drivers/gpu/drm/msm/dp/dp_display.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/gpu/drm/msm/dp/dp_display.c b/drivers/gpu/drm/msm/dp/dp_display.c index ffa785ec641a..2ed40bd0acb6 100644 --- a/drivers/gpu/drm/msm/dp/dp_display.c +++ b/drivers/gpu/drm/msm/dp/dp_display.c @@ -572,6 +572,7 @@ static int dp_hpd_plug_handle(struct dp_display_private *dp, u32 data) ret = dp_display_usbpd_configure_cb(&pdev->dev); if (ret) { /* link train failed */ dp->hpd_state = ST_DISCONNECTED; + pm_runtime_put_sync(&pdev->dev); } else { dp->hpd_state = ST_MAINLINK_READY; } -- cgit v1.2.3 From c588f7d67044d6d59ef92d75a970b64929984d89 Mon Sep 17 00:00:00 2001 From: Stephen Boyd Date: Mon, 25 Mar 2024 14:08:09 -0700 Subject: drm/msm: Add newlines to some debug prints These debug prints are missing newlines, leading to multiple messages being printed on one line and hard to read logs. Add newlines to have the debug prints on separate lines. The DBG macro used to add a newline, but I missed that while migrating to drm_dbg wrappers. Fixes: 7cb017db1896 ("drm/msm: Move FB debug prints to drm_dbg_state()") Fixes: 721c6e0c6aed ("drm/msm: Move vblank debug prints to drm_dbg_vbl()") Signed-off-by: Stephen Boyd Reviewed-by: Dmitry Baryshkov Reviewed-by: Abhinav Kumar Patchwork: https://patchwork.freedesktop.org/patch/584769/ Link: https://lore.kernel.org/r/20240325210810.1340820-1-swboyd@chromium.org Signed-off-by: Abhinav Kumar --- drivers/gpu/drm/msm/msm_fb.c | 6 +++--- drivers/gpu/drm/msm/msm_kms.c | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/msm/msm_fb.c b/drivers/gpu/drm/msm/msm_fb.c index e3f61c39df69..80166f702a0d 100644 --- a/drivers/gpu/drm/msm/msm_fb.c +++ b/drivers/gpu/drm/msm/msm_fb.c @@ -89,7 +89,7 @@ int msm_framebuffer_prepare(struct drm_framebuffer *fb, for (i = 0; i < n; i++) { ret = msm_gem_get_and_pin_iova(fb->obj[i], aspace, &msm_fb->iova[i]); - drm_dbg_state(fb->dev, "FB[%u]: iova[%d]: %08llx (%d)", + drm_dbg_state(fb->dev, "FB[%u]: iova[%d]: %08llx (%d)\n", fb->base.id, i, msm_fb->iova[i], ret); if (ret) return ret; @@ -176,7 +176,7 @@ static struct drm_framebuffer *msm_framebuffer_init(struct drm_device *dev, const struct msm_format *format; int ret, i, n; - drm_dbg_state(dev, "create framebuffer: mode_cmd=%p (%dx%d@%4.4s)", + drm_dbg_state(dev, "create framebuffer: mode_cmd=%p (%dx%d@%4.4s)\n", mode_cmd, mode_cmd->width, mode_cmd->height, (char *)&mode_cmd->pixel_format); @@ -232,7 +232,7 @@ static struct drm_framebuffer *msm_framebuffer_init(struct drm_device *dev, refcount_set(&msm_fb->dirtyfb, 1); - drm_dbg_state(dev, "create: FB ID: %d (%p)", fb->base.id, fb); + drm_dbg_state(dev, "create: FB ID: %d (%p)\n", fb->base.id, fb); return fb; diff --git a/drivers/gpu/drm/msm/msm_kms.c b/drivers/gpu/drm/msm/msm_kms.c index 84c21ec2ceea..af6a6fcb1173 100644 --- a/drivers/gpu/drm/msm/msm_kms.c +++ b/drivers/gpu/drm/msm/msm_kms.c @@ -149,7 +149,7 @@ int msm_crtc_enable_vblank(struct drm_crtc *crtc) struct msm_kms *kms = priv->kms; if (!kms) return -ENXIO; - drm_dbg_vbl(dev, "crtc=%u", crtc->base.id); + drm_dbg_vbl(dev, "crtc=%u\n", crtc->base.id); return vblank_ctrl_queue_work(priv, crtc, true); } @@ -160,7 +160,7 @@ void msm_crtc_disable_vblank(struct drm_crtc *crtc) struct msm_kms *kms = priv->kms; if (!kms) return; - drm_dbg_vbl(dev, "crtc=%u", crtc->base.id); + drm_dbg_vbl(dev, "crtc=%u\n", crtc->base.id); vblank_ctrl_queue_work(priv, crtc, false); } -- cgit v1.2.3 From 4f3b77ae5ff5b5ba9d99c5d5450db388dbee5107 Mon Sep 17 00:00:00 2001 From: Dmitry Baryshkov Date: Thu, 14 Mar 2024 03:10:41 +0200 Subject: drm/msm/dpu: don't allow overriding data from catalog The data from catalog is marked as const, so it is a part of the RO segment. Allowing userspace to write to it through debugfs can cause protection faults. Set debugfs file mode to read-only for debug entries corresponding to perf_cfg coming from catalog. Fixes: abda0d925f9c ("drm/msm/dpu: Mark various data tables as const") Signed-off-by: Dmitry Baryshkov Reviewed-by: Abhinav Kumar Patchwork: https://patchwork.freedesktop.org/patch/582844/ Link: https://lore.kernel.org/r/20240314-dpu-perf-rework-v3-1-79fa4e065574@linaro.org Signed-off-by: Abhinav Kumar --- drivers/gpu/drm/msm/disp/dpu1/dpu_core_perf.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_core_perf.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_core_perf.c index ef871239adb2..68fae048a9a8 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_core_perf.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_core_perf.c @@ -459,15 +459,15 @@ int dpu_core_perf_debugfs_init(struct dpu_kms *dpu_kms, struct dentry *parent) &perf->core_clk_rate); debugfs_create_u32("enable_bw_release", 0600, entry, (u32 *)&perf->enable_bw_release); - debugfs_create_u32("threshold_low", 0600, entry, + debugfs_create_u32("threshold_low", 0400, entry, (u32 *)&perf->perf_cfg->max_bw_low); - debugfs_create_u32("threshold_high", 0600, entry, + debugfs_create_u32("threshold_high", 0400, entry, (u32 *)&perf->perf_cfg->max_bw_high); - debugfs_create_u32("min_core_ib", 0600, entry, + debugfs_create_u32("min_core_ib", 0400, entry, (u32 *)&perf->perf_cfg->min_core_ib); - debugfs_create_u32("min_llcc_ib", 0600, entry, + debugfs_create_u32("min_llcc_ib", 0400, entry, (u32 *)&perf->perf_cfg->min_llcc_ib); - debugfs_create_u32("min_dram_ib", 0600, entry, + debugfs_create_u32("min_dram_ib", 0400, entry, (u32 *)&perf->perf_cfg->min_dram_ib); debugfs_create_file("perf_mode", 0600, entry, (u32 *)perf, &dpu_core_perf_mode_fops); -- cgit v1.2.3 From ee15c8bf5d77a306614bdefe33828310662dee05 Mon Sep 17 00:00:00 2001 From: Kuogee Hsieh Date: Fri, 29 Mar 2024 12:46:26 -0700 Subject: drm/msm/dp: assign correct DP controller ID to x1e80100 interface table At current x1e80100 interface table, interface #3 is wrongly connected to DP controller #0 and interface #4 wrongly connected to DP controller #2. Fix this problem by connect Interface #3 to DP controller #0 and interface #4 connect to DP controller #1. Also add interface #6, #7 and #8 connections to DP controller to complete x1e80100 interface table. Changs in V3: -- add v2 changes log Changs in V2: -- add x1e80100 to subject -- add Fixes Fixes: e3b1f369db5a ("drm/msm/dpu: Add X1E80100 support") Signed-off-by: Kuogee Hsieh Reviewed-by: Abhinav Kumar Reviewed-by: Abel Vesa Patchwork: https://patchwork.freedesktop.org/patch/585549/ Link: https://lore.kernel.org/r/1711741586-9037-1-git-send-email-quic_khsieh@quicinc.com Signed-off-by: Abhinav Kumar --- .../drm/msm/disp/dpu1/catalog/dpu_9_2_x1e80100.h | 34 ++++++++++++++++++++-- 1 file changed, 31 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_9_2_x1e80100.h b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_9_2_x1e80100.h index 9a9f7092c526..a3e60ac70689 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_9_2_x1e80100.h +++ b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_9_2_x1e80100.h @@ -324,6 +324,7 @@ static const struct dpu_wb_cfg x1e80100_wb[] = { }, }; +/* TODO: INTF 3, 8 and 7 are used for MST, marked as INTF_NONE for now */ static const struct dpu_intf_cfg x1e80100_intf[] = { { .name = "intf_0", .id = INTF_0, @@ -358,8 +359,8 @@ static const struct dpu_intf_cfg x1e80100_intf[] = { .name = "intf_3", .id = INTF_3, .base = 0x37000, .len = 0x280, .features = INTF_SC7280_MASK, - .type = INTF_DP, - .controller_id = MSM_DP_CONTROLLER_1, + .type = INTF_NONE, + .controller_id = MSM_DP_CONTROLLER_0, /* pair with intf_0 for DP MST */ .prog_fetch_lines_worst_case = 24, .intr_underrun = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 30), .intr_vsync = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 31), @@ -368,7 +369,7 @@ static const struct dpu_intf_cfg x1e80100_intf[] = { .base = 0x38000, .len = 0x280, .features = INTF_SC7280_MASK, .type = INTF_DP, - .controller_id = MSM_DP_CONTROLLER_2, + .controller_id = MSM_DP_CONTROLLER_1, .prog_fetch_lines_worst_case = 24, .intr_underrun = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 20), .intr_vsync = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 21), @@ -381,6 +382,33 @@ static const struct dpu_intf_cfg x1e80100_intf[] = { .prog_fetch_lines_worst_case = 24, .intr_underrun = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 22), .intr_vsync = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 23), + }, { + .name = "intf_6", .id = INTF_6, + .base = 0x3A000, .len = 0x280, + .features = INTF_SC7280_MASK, + .type = INTF_DP, + .controller_id = MSM_DP_CONTROLLER_2, + .prog_fetch_lines_worst_case = 24, + .intr_underrun = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 17), + .intr_vsync = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 16), + }, { + .name = "intf_7", .id = INTF_7, + .base = 0x3b000, .len = 0x280, + .features = INTF_SC7280_MASK, + .type = INTF_NONE, + .controller_id = MSM_DP_CONTROLLER_2, /* pair with intf_6 for DP MST */ + .prog_fetch_lines_worst_case = 24, + .intr_underrun = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 18), + .intr_vsync = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 19), + }, { + .name = "intf_8", .id = INTF_8, + .base = 0x3c000, .len = 0x280, + .features = INTF_SC7280_MASK, + .type = INTF_NONE, + .controller_id = MSM_DP_CONTROLLER_1, /* pair with intf_4 for DP MST */ + .prog_fetch_lines_worst_case = 24, + .intr_underrun = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 12), + .intr_vsync = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 13), }, }; -- cgit v1.2.3 From 481047d7e8391d3842ae59025806531cdad710d9 Mon Sep 17 00:00:00 2001 From: "Yanjun.Zhu" Date: Thu, 14 Mar 2024 07:51:40 +0100 Subject: RDMA/rxe: Fix the problem "mutex_destroy missing" When a mutex lock is not used any more, the function mutex_destroy should be called to mark the mutex lock uninitialized. Fixes: 8700e3e7c485 ("Soft RoCE driver") Signed-off-by: Yanjun.Zhu Link: https://lore.kernel.org/r/20240314065140.27468-1-yanjun.zhu@linux.dev Reviewed-by: Daisuke Matsuda Signed-off-by: Leon Romanovsky --- drivers/infiniband/sw/rxe/rxe.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/infiniband/sw/rxe/rxe.c b/drivers/infiniband/sw/rxe/rxe.c index ae466e72fc43..255677bc12b2 100644 --- a/drivers/infiniband/sw/rxe/rxe.c +++ b/drivers/infiniband/sw/rxe/rxe.c @@ -33,6 +33,8 @@ void rxe_dealloc(struct ib_device *ib_dev) if (rxe->tfm) crypto_free_shash(rxe->tfm); + + mutex_destroy(&rxe->usdev_lock); } /* initialize rxe device parameters */ -- cgit v1.2.3 From b68e1acb5834ed1a2ad42d9d002815a8bae7c0b6 Mon Sep 17 00:00:00 2001 From: Mark Zhang Date: Fri, 22 Mar 2024 13:20:49 +0200 Subject: RDMA/cm: Print the old state when cm_destroy_id gets timeout The old state is helpful for debugging, as the current state is always IB_CM_IDLE when timeout happens. Fixes: 96d9cbe2f2ff ("RDMA/cm: add timeout to cm_destroy_id wait") Signed-off-by: Mark Zhang Link: https://lore.kernel.org/r/20240322112049.2022994-1-markzhang@nvidia.com Signed-off-by: Leon Romanovsky --- drivers/infiniband/core/cm.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/drivers/infiniband/core/cm.c b/drivers/infiniband/core/cm.c index bf0df6ee4f78..07fb8d3c037f 100644 --- a/drivers/infiniband/core/cm.c +++ b/drivers/infiniband/core/cm.c @@ -1026,23 +1026,26 @@ static void cm_reset_to_idle(struct cm_id_private *cm_id_priv) } } -static noinline void cm_destroy_id_wait_timeout(struct ib_cm_id *cm_id) +static noinline void cm_destroy_id_wait_timeout(struct ib_cm_id *cm_id, + enum ib_cm_state old_state) { struct cm_id_private *cm_id_priv; cm_id_priv = container_of(cm_id, struct cm_id_private, id); - pr_err("%s: cm_id=%p timed out. state=%d refcnt=%d\n", __func__, - cm_id, cm_id->state, refcount_read(&cm_id_priv->refcount)); + pr_err("%s: cm_id=%p timed out. state %d -> %d, refcnt=%d\n", __func__, + cm_id, old_state, cm_id->state, refcount_read(&cm_id_priv->refcount)); } static void cm_destroy_id(struct ib_cm_id *cm_id, int err) { struct cm_id_private *cm_id_priv; + enum ib_cm_state old_state; struct cm_work *work; int ret; cm_id_priv = container_of(cm_id, struct cm_id_private, id); spin_lock_irq(&cm_id_priv->lock); + old_state = cm_id->state; retest: switch (cm_id->state) { case IB_CM_LISTEN: @@ -1151,7 +1154,7 @@ retest: msecs_to_jiffies( CM_DESTROY_ID_WAIT_TIMEOUT)); if (!ret) /* timeout happened */ - cm_destroy_id_wait_timeout(cm_id); + cm_destroy_id_wait_timeout(cm_id, old_state); } while (!ret); while ((work = cm_dequeue_work(cm_id_priv)) != NULL) -- cgit v1.2.3 From 8844f467d6a58dc915f241e81c46e0c126f8c070 Mon Sep 17 00:00:00 2001 From: Dmitry Baryshkov Date: Sat, 30 Mar 2024 05:53:22 +0200 Subject: drm/msm/dpu: make error messages at dpu_core_irq_register_callback() more sensible There is little point in using %ps to print a value known to be NULL. On the other hand it makes sense to print the callback symbol in the 'invalid IRQ' message. Correct those two error messages to make more sense. Fixes: 6893199183f8 ("drm/msm/dpu: stop using raw IRQ indices in the kernel output") Signed-off-by: Dmitry Baryshkov Reviewed-by: Marijn Suijten Reviewed-by: Abhinav Kumar Patchwork: https://patchwork.freedesktop.org/patch/585565/ Link: https://lore.kernel.org/r/20240330-dpu-irq-messages-v1-1-9ce782ae35f9@linaro.org Signed-off-by: Abhinav Kumar --- drivers/gpu/drm/msm/disp/dpu1/dpu_hw_interrupts.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_interrupts.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_interrupts.c index 946dd0135dff..6a0a74832fb6 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_interrupts.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_interrupts.c @@ -525,14 +525,14 @@ int dpu_core_irq_register_callback(struct dpu_kms *dpu_kms, int ret; if (!irq_cb) { - DPU_ERROR("invalid IRQ=[%d, %d] irq_cb:%ps\n", - DPU_IRQ_REG(irq_idx), DPU_IRQ_BIT(irq_idx), irq_cb); + DPU_ERROR("IRQ=[%d, %d] NULL callback\n", + DPU_IRQ_REG(irq_idx), DPU_IRQ_BIT(irq_idx)); return -EINVAL; } if (!dpu_core_irq_is_valid(irq_idx)) { - DPU_ERROR("invalid IRQ=[%d, %d]\n", - DPU_IRQ_REG(irq_idx), DPU_IRQ_BIT(irq_idx)); + DPU_ERROR("invalid IRQ=[%d, %d] irq_cb:%ps\n", + DPU_IRQ_REG(irq_idx), DPU_IRQ_BIT(irq_idx), irq_cb); return -EINVAL; } -- cgit v1.2.3 From cd49cca222bc5532105a1f20bff6ae60d7bf7713 Mon Sep 17 00:00:00 2001 From: Abhinav Kumar Date: Wed, 6 Mar 2024 11:35:15 -0800 Subject: drm/msm/dp: fix typo in dp_display_handle_port_status_changed() Fix the typo in the name of dp_display_handle_port_status_changed(). Fixes: c58eb1b54fee ("drm/msm/dp: fix connect/disconnect handled at irq_hpd") Signed-off-by: Abhinav Kumar Reviewed-by: Dmitry Baryshkov Patchwork: https://patchwork.freedesktop.org/patch/581746/ Link: https://lore.kernel.org/r/20240306193515.455388-1-quic_abhinavk@quicinc.com --- drivers/gpu/drm/msm/dp/dp_display.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/msm/dp/dp_display.c b/drivers/gpu/drm/msm/dp/dp_display.c index 2ed40bd0acb6..9575d4b80c29 100644 --- a/drivers/gpu/drm/msm/dp/dp_display.c +++ b/drivers/gpu/drm/msm/dp/dp_display.c @@ -468,7 +468,7 @@ static void dp_display_handle_video_request(struct dp_display_private *dp) } } -static int dp_display_handle_port_ststus_changed(struct dp_display_private *dp) +static int dp_display_handle_port_status_changed(struct dp_display_private *dp) { int rc = 0; @@ -525,7 +525,7 @@ static int dp_display_usbpd_attention_cb(struct device *dev) drm_dbg_dp(dp->drm_dev, "hpd_state=%d sink_request=%d\n", dp->hpd_state, sink_request); if (sink_request & DS_PORT_STATUS_CHANGED) - rc = dp_display_handle_port_ststus_changed(dp); + rc = dp_display_handle_port_status_changed(dp); else rc = dp_display_handle_irq_hpd(dp); } -- cgit v1.2.3 From be1b7acb929137e3943fe380671242beb485190c Mon Sep 17 00:00:00 2001 From: Dmitry Baryshkov Date: Tue, 2 Apr 2024 05:57:15 +0300 Subject: dt-bindings: display/msm: sm8150-mdss: add DP node As Qualcomm SM8150 got support for the DisplayPort, add displayport@ node as a valid child to the MDSS node. Fixes: 88806318e2c2 ("dt-bindings: display: msm: dp: declare compatible string for sm8150") Reviewed-by: Krzysztof Kozlowski Signed-off-by: Dmitry Baryshkov Patchwork: https://patchwork.freedesktop.org/patch/586156/ Link: https://lore.kernel.org/r/20240402-fd-fix-schema-v3-1-817ea6ddf775@linaro.org Signed-off-by: Abhinav Kumar --- .../devicetree/bindings/display/msm/qcom,sm8150-mdss.yaml | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/Documentation/devicetree/bindings/display/msm/qcom,sm8150-mdss.yaml b/Documentation/devicetree/bindings/display/msm/qcom,sm8150-mdss.yaml index c0d6a4fdff97..e6dc5494baee 100644 --- a/Documentation/devicetree/bindings/display/msm/qcom,sm8150-mdss.yaml +++ b/Documentation/devicetree/bindings/display/msm/qcom,sm8150-mdss.yaml @@ -53,6 +53,15 @@ patternProperties: compatible: const: qcom,sm8150-dpu + "^displayport-controller@[0-9a-f]+$": + type: object + additionalProperties: true + + properties: + compatible: + contains: + const: qcom,sm8150-dp + "^dsi@[0-9a-f]+$": type: object additionalProperties: true -- cgit v1.2.3 From c032cdd48b29549e8283c2fea99e7d91ddefebf7 Mon Sep 17 00:00:00 2001 From: Mika Westerberg Date: Tue, 26 Mar 2024 10:58:15 +0200 Subject: thunderbolt: Do not create DisplayPort tunnels on adapters of the same router Probably due to a firmware bug Dell TB16 dock announces that one of its DisplayPort adapters is actually DP IN. Now this is possible and used with some external GPUs but not likely in this case as we are dealing with a dock. Anyways the problem is that the driver tries to create a DisplayPort tunnel between adapters of the same router which then shows to user that there is no picture on the display (because there are no available DP OUT adapters on the dock anymore). Fix this by not creating DisplayPort tunnels between adapters that are on the same router. Closes: https://gitlab.freedesktop.org/drm/intel/-/issues/10265 Fixes: 274baf695b08 ("thunderbolt: Add DP IN added last in the head of the list of DP resources") Cc: Gil Fine Cc: stable@vger.kernel.org Signed-off-by: Mika Westerberg --- drivers/thunderbolt/tb.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/drivers/thunderbolt/tb.c b/drivers/thunderbolt/tb.c index c5ce7a694b27..360cb95f39aa 100644 --- a/drivers/thunderbolt/tb.c +++ b/drivers/thunderbolt/tb.c @@ -1801,6 +1801,12 @@ static struct tb_port *tb_find_dp_out(struct tb *tb, struct tb_port *in) continue; } + /* Needs to be on different routers */ + if (in->sw == port->sw) { + tb_port_dbg(port, "skipping DP OUT on same router\n"); + continue; + } + tb_port_dbg(port, "DP OUT available\n"); /* -- cgit v1.2.3 From c6ddd6e7b166532a0816825442ff60f70aed9647 Mon Sep 17 00:00:00 2001 From: Frank Li Date: Fri, 22 Mar 2024 12:47:05 -0400 Subject: arm64: dts: imx8-ss-conn: fix usdhc wrong lpcg clock order The actual clock show wrong frequency: echo on >/sys/devices/platform/bus\@5b000000/5b010000.mmc/power/control cat /sys/kernel/debug/mmc0/ios clock: 200000000 Hz actual clock: 166000000 Hz ^^^^^^^^^ ..... According to sdhc0_lpcg: clock-controller@5b200000 { compatible = "fsl,imx8qxp-lpcg"; reg = <0x5b200000 0x10000>; #clock-cells = <1>; clocks = <&clk IMX_SC_R_SDHC_0 IMX_SC_PM_CLK_PER>, <&conn_ipg_clk>, <&conn_axi_clk>; clock-indices = , , ; clock-output-names = "sdhc0_lpcg_per_clk", "sdhc0_lpcg_ipg_clk", "sdhc0_lpcg_ahb_clk"; power-domains = <&pd IMX_SC_R_SDHC_0>; } "per_clk" should be IMX_LPCG_CLK_0 instead of IMX_LPCG_CLK_5. After correct clocks order: echo on >/sys/devices/platform/bus\@5b000000/5b010000.mmc/power/control cat /sys/kernel/debug/mmc0/ios clock: 200000000 Hz actual clock: 198000000 Hz ^^^^^^^^ ... Fixes: 16c4ea7501b1 ("arm64: dts: imx8: switch to new lpcg clock binding") Signed-off-by: Frank Li Signed-off-by: Shawn Guo --- arch/arm64/boot/dts/freescale/imx8-ss-conn.dtsi | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/arch/arm64/boot/dts/freescale/imx8-ss-conn.dtsi b/arch/arm64/boot/dts/freescale/imx8-ss-conn.dtsi index 3c42240e78e2..af2259e99796 100644 --- a/arch/arm64/boot/dts/freescale/imx8-ss-conn.dtsi +++ b/arch/arm64/boot/dts/freescale/imx8-ss-conn.dtsi @@ -67,8 +67,8 @@ conn_subsys: bus@5b000000 { interrupts = ; reg = <0x5b010000 0x10000>; clocks = <&sdhc0_lpcg IMX_LPCG_CLK_4>, - <&sdhc0_lpcg IMX_LPCG_CLK_0>, - <&sdhc0_lpcg IMX_LPCG_CLK_5>; + <&sdhc0_lpcg IMX_LPCG_CLK_5>, + <&sdhc0_lpcg IMX_LPCG_CLK_0>; clock-names = "ipg", "ahb", "per"; power-domains = <&pd IMX_SC_R_SDHC_0>; status = "disabled"; @@ -78,8 +78,8 @@ conn_subsys: bus@5b000000 { interrupts = ; reg = <0x5b020000 0x10000>; clocks = <&sdhc1_lpcg IMX_LPCG_CLK_4>, - <&sdhc1_lpcg IMX_LPCG_CLK_0>, - <&sdhc1_lpcg IMX_LPCG_CLK_5>; + <&sdhc1_lpcg IMX_LPCG_CLK_5>, + <&sdhc1_lpcg IMX_LPCG_CLK_0>; clock-names = "ipg", "ahb", "per"; power-domains = <&pd IMX_SC_R_SDHC_1>; fsl,tuning-start-tap = <20>; @@ -91,8 +91,8 @@ conn_subsys: bus@5b000000 { interrupts = ; reg = <0x5b030000 0x10000>; clocks = <&sdhc2_lpcg IMX_LPCG_CLK_4>, - <&sdhc2_lpcg IMX_LPCG_CLK_0>, - <&sdhc2_lpcg IMX_LPCG_CLK_5>; + <&sdhc2_lpcg IMX_LPCG_CLK_5>, + <&sdhc2_lpcg IMX_LPCG_CLK_0>; clock-names = "ipg", "ahb", "per"; power-domains = <&pd IMX_SC_R_SDHC_2>; status = "disabled"; -- cgit v1.2.3 From b91695b50d5b5c7c6a2cae08637b0a119cec0e12 Mon Sep 17 00:00:00 2001 From: Fabio Estevam Date: Mon, 25 Mar 2024 09:14:04 -0300 Subject: ARM: dts: imx7-mba7: Use 'no-mmc' property 'no-emmc' is not a valid property. The original intention was to use the 'no-mmc' property. Change it accordingly to fix the following dt-schema warning: imx7s-mba7.dtb: mmc@30b40000: Unevaluated properties are not allowed ('no-emmc' was unexpected) Fixes: d430a7e0e181 ("ARM: dts: imx7-mba7: restrict usdhc interface modes") Signed-off-by: Fabio Estevam Reviewed-by: Alexander Stein Signed-off-by: Shawn Guo --- arch/arm/boot/dts/nxp/imx/imx7-mba7.dtsi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/boot/dts/nxp/imx/imx7-mba7.dtsi b/arch/arm/boot/dts/nxp/imx/imx7-mba7.dtsi index 1235a71c6abe..52869e68f833 100644 --- a/arch/arm/boot/dts/nxp/imx/imx7-mba7.dtsi +++ b/arch/arm/boot/dts/nxp/imx/imx7-mba7.dtsi @@ -666,7 +666,7 @@ bus-width = <4>; no-1-8-v; no-sdio; - no-emmc; + no-mmc; status = "okay"; }; -- cgit v1.2.3 From 08ea486a61451189b190c7b89e406b889cf693fa Mon Sep 17 00:00:00 2001 From: Richard Fitzgerald Date: Mon, 1 Apr 2024 10:02:08 +0000 Subject: ALSA: control: Introduce snd_ctl_find_id_mixer_locked() Adds wrapper function snd_ctl_find_id_mixer_locked(). This is identical to snd_ctl_find_id_mixer() except that it can be called from code that is already holding controls_rwsem. Signed-off-by: Richard Fitzgerald Reviewed-by: Takashi Iwai Link: https://msgid.link/r/20240401100210.61277-2-rf@opensource.cirrus.com Signed-off-by: Mark Brown --- include/sound/control.h | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/include/sound/control.h b/include/sound/control.h index 9a4f4f7138da..c1659036c4a7 100644 --- a/include/sound/control.h +++ b/include/sound/control.h @@ -167,6 +167,29 @@ snd_ctl_find_id_mixer(struct snd_card *card, const char *name) return snd_ctl_find_id(card, &id); } +/** + * snd_ctl_find_id_mixer_locked - find the control instance with the given name string + * @card: the card instance + * @name: the name string + * + * Finds the control instance with the given name and + * @SNDRV_CTL_ELEM_IFACE_MIXER. Other fields are set to zero. + * + * This is merely a wrapper to snd_ctl_find_id_locked(). + * The caller must down card->controls_rwsem before calling this function. + * + * Return: The pointer of the instance if found, or %NULL if not. + */ +static inline struct snd_kcontrol * +snd_ctl_find_id_mixer_locked(struct snd_card *card, const char *name) +{ + struct snd_ctl_elem_id id = {}; + + id.iface = SNDRV_CTL_ELEM_IFACE_MIXER; + strscpy(id.name, name, sizeof(id.name)); + return snd_ctl_find_id_locked(card, &id); +} + int snd_ctl_create(struct snd_card *card); int snd_ctl_register_ioctl(snd_kctl_ioctl_func_t fcn); -- cgit v1.2.3 From 897cc72b08374c1224a9ded03c82dfc8e41f80c2 Mon Sep 17 00:00:00 2001 From: Richard Fitzgerald Date: Mon, 1 Apr 2024 10:02:09 +0000 Subject: ASoC: soc-card: Use snd_ctl_find_id_mixer() instead of open-coding Use the snd_ctl_find_id_mixer[_locked]() wrapper in snd_soc_card_get_kcontrol[_locked]() instead of open-coding a custom list walk of the card controls list. Signed-off-by: Richard Fitzgerald Reviewed-by: Takashi Iwai Link: https://msgid.link/r/20240401100210.61277-3-rf@opensource.cirrus.com Signed-off-by: Mark Brown --- sound/soc/soc-card.c | 21 ++++----------------- 1 file changed, 4 insertions(+), 17 deletions(-) diff --git a/sound/soc/soc-card.c b/sound/soc/soc-card.c index 8a2f163da6bc..0a3104d4ad23 100644 --- a/sound/soc/soc-card.c +++ b/sound/soc/soc-card.c @@ -32,33 +32,20 @@ static inline int _soc_card_ret(struct snd_soc_card *card, struct snd_kcontrol *snd_soc_card_get_kcontrol_locked(struct snd_soc_card *soc_card, const char *name) { - struct snd_card *card = soc_card->snd_card; - struct snd_kcontrol *kctl; - - /* must be held read or write */ - lockdep_assert_held(&card->controls_rwsem); - if (unlikely(!name)) return NULL; - list_for_each_entry(kctl, &card->controls, list) - if (!strncmp(kctl->id.name, name, sizeof(kctl->id.name))) - return kctl; - return NULL; + return snd_ctl_find_id_mixer_locked(soc_card->snd_card, name); } EXPORT_SYMBOL_GPL(snd_soc_card_get_kcontrol_locked); struct snd_kcontrol *snd_soc_card_get_kcontrol(struct snd_soc_card *soc_card, const char *name) { - struct snd_card *card = soc_card->snd_card; - struct snd_kcontrol *kctl; - - down_read(&card->controls_rwsem); - kctl = snd_soc_card_get_kcontrol_locked(soc_card, name); - up_read(&card->controls_rwsem); + if (unlikely(!name)) + return NULL; - return kctl; + return snd_ctl_find_id_mixer(soc_card->snd_card, name); } EXPORT_SYMBOL_GPL(snd_soc_card_get_kcontrol); -- cgit v1.2.3 From ef7784e41db73f3d31ce545227ebba4483479a26 Mon Sep 17 00:00:00 2001 From: Richard Fitzgerald Date: Mon, 1 Apr 2024 10:02:10 +0000 Subject: ASoC: soc-card: Add KUnit test case for snd_soc_card_get_kcontrol Add a new snd-soc-card KUnit test with a simple test case for snd_soc_card_get_kcontrol() and snd_soc_card_get_kcontrol_locked(). Signed-off-by: Richard Fitzgerald Reviewed-by: Takashi Iwai Link: https://msgid.link/r/20240401100210.61277-4-rf@opensource.cirrus.com Signed-off-by: Mark Brown --- sound/soc/Kconfig | 8 ++ sound/soc/Makefile | 4 + sound/soc/soc-card-test.c | 184 ++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 196 insertions(+) create mode 100644 sound/soc/soc-card-test.c diff --git a/sound/soc/Kconfig b/sound/soc/Kconfig index 439fa631c342..a52afb423b46 100644 --- a/sound/soc/Kconfig +++ b/sound/soc/Kconfig @@ -66,6 +66,14 @@ config SND_SOC_TOPOLOGY_KUNIT_TEST userspace applications such as pulseaudio, to prevent unnecessary problems. +config SND_SOC_CARD_KUNIT_TEST + tristate "KUnit tests for SoC card" + depends on KUNIT + default KUNIT_ALL_TESTS + help + If you want to perform tests on ALSA SoC card functions say Y here. + If unsure, say N. + config SND_SOC_UTILS_KUNIT_TEST tristate "KUnit tests for SoC utils" depends on KUNIT diff --git a/sound/soc/Makefile b/sound/soc/Makefile index 8376fdb217ed..f90f5300b36e 100644 --- a/sound/soc/Makefile +++ b/sound/soc/Makefile @@ -12,6 +12,10 @@ ifneq ($(CONFIG_SND_SOC_TOPOLOGY_KUNIT_TEST),) obj-$(CONFIG_SND_SOC_TOPOLOGY_KUNIT_TEST) += soc-topology-test.o endif +ifneq ($(CONFIG_SND_SOC_CARD_KUNIT_TEST),) +obj-$(CONFIG_SND_SOC_CARD_KUNIT_TEST) += soc-card-test.o +endif + ifneq ($(CONFIG_SND_SOC_UTILS_KUNIT_TEST),) # snd-soc-test-objs := soc-utils-test.o obj-$(CONFIG_SND_SOC_UTILS_KUNIT_TEST) += soc-utils-test.o diff --git a/sound/soc/soc-card-test.c b/sound/soc/soc-card-test.c new file mode 100644 index 000000000000..075c52fe82e5 --- /dev/null +++ b/sound/soc/soc-card-test.c @@ -0,0 +1,184 @@ +// SPDX-License-Identifier: GPL-2.0-only +// Copyright (C) 2024 Cirrus Logic, Inc. and +// Cirrus Logic International Semiconductor Ltd. + +#include +#include +#include +#include +#include +#include + +struct soc_card_test_priv { + struct device *card_dev; + struct snd_soc_card *card; +}; + +static const struct snd_kcontrol_new test_card_controls[] = { + SOC_SINGLE("Fee", SND_SOC_NOPM, 0, 1, 0), + SOC_SINGLE("Fi", SND_SOC_NOPM, 1, 1, 0), + SOC_SINGLE("Fo", SND_SOC_NOPM, 2, 1, 0), + SOC_SINGLE("Fum", SND_SOC_NOPM, 3, 1, 0), + SOC_SINGLE("Left Fee", SND_SOC_NOPM, 4, 1, 0), + SOC_SINGLE("Right Fee", SND_SOC_NOPM, 5, 1, 0), + SOC_SINGLE("Left Fi", SND_SOC_NOPM, 6, 1, 0), + SOC_SINGLE("Right Fi", SND_SOC_NOPM, 7, 1, 0), + SOC_SINGLE("Left Fo", SND_SOC_NOPM, 8, 1, 0), + SOC_SINGLE("Right Fo", SND_SOC_NOPM, 9, 1, 0), + SOC_SINGLE("Left Fum", SND_SOC_NOPM, 10, 1, 0), + SOC_SINGLE("Right Fum", SND_SOC_NOPM, 11, 1, 0), +}; + +static void test_snd_soc_card_get_kcontrol(struct kunit *test) +{ + struct soc_card_test_priv *priv = test->priv; + struct snd_soc_card *card = priv->card; + struct snd_kcontrol *kc; + struct soc_mixer_control *mc; + int i, ret; + + ret = snd_soc_add_card_controls(card, test_card_controls, ARRAY_SIZE(test_card_controls)); + KUNIT_ASSERT_EQ(test, ret, 0); + + /* Look up every control */ + for (i = 0; i < ARRAY_SIZE(test_card_controls); ++i) { + kc = snd_soc_card_get_kcontrol(card, test_card_controls[i].name); + KUNIT_EXPECT_NOT_ERR_OR_NULL_MSG(test, kc, "Failed to find '%s'\n", + test_card_controls[i].name); + if (!kc) + continue; + + /* Test that it is the correct control */ + mc = (struct soc_mixer_control *)kc->private_value; + KUNIT_EXPECT_EQ_MSG(test, mc->shift, i, "For '%s'\n", test_card_controls[i].name); + } + + /* Test some names that should not be found */ + kc = snd_soc_card_get_kcontrol(card, "None"); + KUNIT_EXPECT_NULL(test, kc); + + kc = snd_soc_card_get_kcontrol(card, "Left None"); + KUNIT_EXPECT_NULL(test, kc); + + kc = snd_soc_card_get_kcontrol(card, "Left"); + KUNIT_EXPECT_NULL(test, kc); + + kc = snd_soc_card_get_kcontrol(card, NULL); + KUNIT_EXPECT_NULL(test, kc); +} + +static void test_snd_soc_card_get_kcontrol_locked(struct kunit *test) +{ + struct soc_card_test_priv *priv = test->priv; + struct snd_soc_card *card = priv->card; + struct snd_kcontrol *kc, *kcw; + struct soc_mixer_control *mc; + int i, ret; + + ret = snd_soc_add_card_controls(card, test_card_controls, ARRAY_SIZE(test_card_controls)); + KUNIT_ASSERT_EQ(test, ret, 0); + + /* Look up every control */ + for (i = 0; i < ARRAY_SIZE(test_card_controls); ++i) { + down_read(&card->snd_card->controls_rwsem); + kc = snd_soc_card_get_kcontrol_locked(card, test_card_controls[i].name); + up_read(&card->snd_card->controls_rwsem); + KUNIT_EXPECT_NOT_ERR_OR_NULL_MSG(test, kc, "Failed to find '%s'\n", + test_card_controls[i].name); + if (!kc) + continue; + + /* Test that it is the correct control */ + mc = (struct soc_mixer_control *)kc->private_value; + KUNIT_EXPECT_EQ_MSG(test, mc->shift, i, "For '%s'\n", test_card_controls[i].name); + + down_write(&card->snd_card->controls_rwsem); + kcw = snd_soc_card_get_kcontrol_locked(card, test_card_controls[i].name); + up_write(&card->snd_card->controls_rwsem); + KUNIT_EXPECT_NOT_ERR_OR_NULL_MSG(test, kcw, "Failed to find '%s'\n", + test_card_controls[i].name); + + KUNIT_EXPECT_PTR_EQ(test, kc, kcw); + } + + /* Test some names that should not be found */ + down_read(&card->snd_card->controls_rwsem); + kc = snd_soc_card_get_kcontrol_locked(card, "None"); + up_read(&card->snd_card->controls_rwsem); + KUNIT_EXPECT_NULL(test, kc); + + down_read(&card->snd_card->controls_rwsem); + kc = snd_soc_card_get_kcontrol_locked(card, "Left None"); + up_read(&card->snd_card->controls_rwsem); + KUNIT_EXPECT_NULL(test, kc); + + down_read(&card->snd_card->controls_rwsem); + kc = snd_soc_card_get_kcontrol_locked(card, "Left"); + up_read(&card->snd_card->controls_rwsem); + KUNIT_EXPECT_NULL(test, kc); + + down_read(&card->snd_card->controls_rwsem); + kc = snd_soc_card_get_kcontrol_locked(card, NULL); + up_read(&card->snd_card->controls_rwsem); + KUNIT_EXPECT_NULL(test, kc); +} + +static int soc_card_test_case_init(struct kunit *test) +{ + struct soc_card_test_priv *priv; + int ret; + + priv = kunit_kzalloc(test, sizeof(*priv), GFP_KERNEL); + if (!priv) + return -ENOMEM; + + test->priv = priv; + + priv->card_dev = kunit_device_register(test, "sound-soc-card-test"); + priv->card_dev = get_device(priv->card_dev); + if (!priv->card_dev) + return -ENODEV; + + priv->card = kunit_kzalloc(test, sizeof(*priv->card), GFP_KERNEL); + if (!priv->card) + return -ENOMEM; + + priv->card->name = "soc-card-test"; + priv->card->dev = priv->card_dev; + priv->card->owner = THIS_MODULE; + + ret = snd_soc_register_card(priv->card); + if (!ret) + return ret; + + return 0; +} + +static void soc_card_test_case_exit(struct kunit *test) +{ + struct soc_card_test_priv *priv = test->priv; + + if (priv->card) + snd_soc_unregister_card(priv->card); + + if (priv->card_dev) + put_device(priv->card_dev); +} + +static struct kunit_case soc_card_test_cases[] = { + KUNIT_CASE(test_snd_soc_card_get_kcontrol), + KUNIT_CASE(test_snd_soc_card_get_kcontrol_locked), + {} +}; + +static struct kunit_suite soc_card_test_suite = { + .name = "soc-card", + .test_cases = soc_card_test_cases, + .init = soc_card_test_case_init, + .exit = soc_card_test_case_exit, +}; + +kunit_test_suites(&soc_card_test_suite); + +MODULE_DESCRIPTION("ASoC soc-card KUnit test"); +MODULE_LICENSE("GPL"); -- cgit v1.2.3 From 35aaed1bc3c32c52b7fda525cd7bd19998035518 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Tue, 2 Apr 2024 02:23:54 +0000 Subject: ASoC: rsnd: cleanup regmap table R-Car Sound is using almost same register mapping on each generation, therefore we can share it. Here indicates some memo/comments. SSI/SSIU/SCU have multi channels (SSI0 - SSI9 etc), but ADG is single, so, we don't need to have multi channel settings for it - rsnd_gen_regmap_init(..., 10, ..ADG, ...); + rsnd_gen_regmap_init(..., 1, ..ADG, ...); Gen4 added new SSI_BUSIF, but it is not used Gen4 calls rsnd_gen_regmap_init() for SDMC, but the address is calculated by rsnd_gen4_dma_addr(). It needs physical address, but other info are not needed. use NULL conf for it. - rsnd_gen_regmap_init(..., 10, ..SDMC, conf_sdmc); + rsnd_gen_regmap_init(..., 1, ..SDMC, conf_null); Gen4 have only SSI0/SSIU0, we don't need to have multi channel settings. - rsnd_gen_regmap_init(..., 10, ..SSI, ...); + rsnd_gen_regmap_init(..., 1, ..SSI, ...); SSI_MODE2 address is different between Gen2/3 and Gen4, but it is not used on Gen4. Thus we can share same regmap table. Gen2/3 : 0x808 Gen4 : 0xa0c Signed-off-by: Kuninori Morimoto Tested-by: Khanh Le Link: https://msgid.link/r/871q7obiyt.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/sh/rcar/gen.c | 517 +++++++++++++++++++++-------------------------- sound/soc/sh/rcar/rsnd.h | 1 - 2 files changed, 226 insertions(+), 292 deletions(-) diff --git a/sound/soc/sh/rcar/gen.c b/sound/soc/sh/rcar/gen.c index 86bdecc24956..e566712e5234 100644 --- a/sound/soc/sh/rcar/gen.c +++ b/sound/soc/sh/rcar/gen.c @@ -215,70 +215,220 @@ static int _rsnd_gen_regmap_init(struct rsnd_priv *priv, return 0; } +/* + * (A) : Gen4 is 0xa0c, but it is not used. + * see + * rsnd_ssiu_init() + */ +static const struct rsnd_regmap_field_conf conf_common_ssiu[] = { + RSND_GEN_S_REG(SSI_MODE0, 0x800), + RSND_GEN_S_REG(SSI_MODE1, 0x804), + RSND_GEN_S_REG(SSI_MODE2, 0x808), // (A) + RSND_GEN_S_REG(SSI_CONTROL, 0x810), + RSND_GEN_S_REG(SSI_SYS_STATUS0, 0x840), + RSND_GEN_S_REG(SSI_SYS_STATUS1, 0x844), + RSND_GEN_S_REG(SSI_SYS_STATUS2, 0x848), + RSND_GEN_S_REG(SSI_SYS_STATUS3, 0x84c), + RSND_GEN_S_REG(SSI_SYS_STATUS4, 0x880), + RSND_GEN_S_REG(SSI_SYS_STATUS5, 0x884), + RSND_GEN_S_REG(SSI_SYS_STATUS6, 0x888), + RSND_GEN_S_REG(SSI_SYS_STATUS7, 0x88c), + RSND_GEN_S_REG(SSI_SYS_INT_ENABLE0, 0x850), + RSND_GEN_S_REG(SSI_SYS_INT_ENABLE1, 0x854), + RSND_GEN_S_REG(SSI_SYS_INT_ENABLE2, 0x858), + RSND_GEN_S_REG(SSI_SYS_INT_ENABLE3, 0x85c), + RSND_GEN_S_REG(SSI_SYS_INT_ENABLE4, 0x890), + RSND_GEN_S_REG(SSI_SYS_INT_ENABLE5, 0x894), + RSND_GEN_S_REG(SSI_SYS_INT_ENABLE6, 0x898), + RSND_GEN_S_REG(SSI_SYS_INT_ENABLE7, 0x89c), + RSND_GEN_S_REG(HDMI0_SEL, 0x9e0), + RSND_GEN_S_REG(HDMI1_SEL, 0x9e4), + RSND_GEN_M_REG(SSI_BUSIF0_MODE, 0x0, 0x80), + RSND_GEN_M_REG(SSI_BUSIF0_ADINR, 0x4, 0x80), + RSND_GEN_M_REG(SSI_BUSIF0_DALIGN, 0x8, 0x80), + RSND_GEN_M_REG(SSI_BUSIF1_MODE, 0x20, 0x80), + RSND_GEN_M_REG(SSI_BUSIF1_ADINR, 0x24, 0x80), + RSND_GEN_M_REG(SSI_BUSIF1_DALIGN, 0x28, 0x80), + RSND_GEN_M_REG(SSI_BUSIF2_MODE, 0x40, 0x80), + RSND_GEN_M_REG(SSI_BUSIF2_ADINR, 0x44, 0x80), + RSND_GEN_M_REG(SSI_BUSIF2_DALIGN, 0x48, 0x80), + RSND_GEN_M_REG(SSI_BUSIF3_MODE, 0x60, 0x80), + RSND_GEN_M_REG(SSI_BUSIF3_ADINR, 0x64, 0x80), + RSND_GEN_M_REG(SSI_BUSIF3_DALIGN, 0x68, 0x80), + RSND_GEN_M_REG(SSI_BUSIF4_MODE, 0x500, 0x80), + RSND_GEN_M_REG(SSI_BUSIF4_ADINR, 0x504, 0x80), + RSND_GEN_M_REG(SSI_BUSIF4_DALIGN, 0x508, 0x80), + RSND_GEN_M_REG(SSI_BUSIF5_MODE, 0x520, 0x80), + RSND_GEN_M_REG(SSI_BUSIF5_ADINR, 0x524, 0x80), + RSND_GEN_M_REG(SSI_BUSIF5_DALIGN, 0x528, 0x80), + RSND_GEN_M_REG(SSI_BUSIF6_MODE, 0x540, 0x80), + RSND_GEN_M_REG(SSI_BUSIF6_ADINR, 0x544, 0x80), + RSND_GEN_M_REG(SSI_BUSIF6_DALIGN, 0x548, 0x80), + RSND_GEN_M_REG(SSI_BUSIF7_MODE, 0x560, 0x80), + RSND_GEN_M_REG(SSI_BUSIF7_ADINR, 0x564, 0x80), + RSND_GEN_M_REG(SSI_BUSIF7_DALIGN, 0x568, 0x80), + RSND_GEN_M_REG(SSI_MODE, 0xc, 0x80), + RSND_GEN_M_REG(SSI_CTRL, 0x10, 0x80), + RSND_GEN_M_REG(SSI_INT_ENABLE, 0x18, 0x80), + RSND_GEN_S_REG(SSI9_BUSIF0_MODE, 0x48c), + RSND_GEN_S_REG(SSI9_BUSIF0_ADINR, 0x484), + RSND_GEN_S_REG(SSI9_BUSIF0_DALIGN, 0x488), + RSND_GEN_S_REG(SSI9_BUSIF1_MODE, 0x4a0), + RSND_GEN_S_REG(SSI9_BUSIF1_ADINR, 0x4a4), + RSND_GEN_S_REG(SSI9_BUSIF1_DALIGN, 0x4a8), + RSND_GEN_S_REG(SSI9_BUSIF2_MODE, 0x4c0), + RSND_GEN_S_REG(SSI9_BUSIF2_ADINR, 0x4c4), + RSND_GEN_S_REG(SSI9_BUSIF2_DALIGN, 0x4c8), + RSND_GEN_S_REG(SSI9_BUSIF3_MODE, 0x4e0), + RSND_GEN_S_REG(SSI9_BUSIF3_ADINR, 0x4e4), + RSND_GEN_S_REG(SSI9_BUSIF3_DALIGN, 0x4e8), + RSND_GEN_S_REG(SSI9_BUSIF4_MODE, 0xd80), + RSND_GEN_S_REG(SSI9_BUSIF4_ADINR, 0xd84), + RSND_GEN_S_REG(SSI9_BUSIF4_DALIGN, 0xd88), + RSND_GEN_S_REG(SSI9_BUSIF5_MODE, 0xda0), + RSND_GEN_S_REG(SSI9_BUSIF5_ADINR, 0xda4), + RSND_GEN_S_REG(SSI9_BUSIF5_DALIGN, 0xda8), + RSND_GEN_S_REG(SSI9_BUSIF6_MODE, 0xdc0), + RSND_GEN_S_REG(SSI9_BUSIF6_ADINR, 0xdc4), + RSND_GEN_S_REG(SSI9_BUSIF6_DALIGN, 0xdc8), + RSND_GEN_S_REG(SSI9_BUSIF7_MODE, 0xde0), + RSND_GEN_S_REG(SSI9_BUSIF7_ADINR, 0xde4), + RSND_GEN_S_REG(SSI9_BUSIF7_DALIGN, 0xde8), +}; + +static const struct rsnd_regmap_field_conf conf_common_scu[] = { + RSND_GEN_M_REG(SRC_I_BUSIF_MODE, 0x0, 0x20), + RSND_GEN_M_REG(SRC_O_BUSIF_MODE, 0x4, 0x20), + RSND_GEN_M_REG(SRC_BUSIF_DALIGN, 0x8, 0x20), + RSND_GEN_M_REG(SRC_ROUTE_MODE0, 0xc, 0x20), + RSND_GEN_M_REG(SRC_CTRL, 0x10, 0x20), + RSND_GEN_M_REG(SRC_INT_ENABLE0, 0x18, 0x20), + RSND_GEN_M_REG(CMD_BUSIF_MODE, 0x184, 0x20), + RSND_GEN_M_REG(CMD_BUSIF_DALIGN, 0x188, 0x20), + RSND_GEN_M_REG(CMD_ROUTE_SLCT, 0x18c, 0x20), + RSND_GEN_M_REG(CMD_CTRL, 0x190, 0x20), + RSND_GEN_S_REG(SCU_SYS_STATUS0, 0x1c8), + RSND_GEN_S_REG(SCU_SYS_INT_EN0, 0x1cc), + RSND_GEN_S_REG(SCU_SYS_STATUS1, 0x1d0), + RSND_GEN_S_REG(SCU_SYS_INT_EN1, 0x1d4), + RSND_GEN_M_REG(SRC_SWRSR, 0x200, 0x40), + RSND_GEN_M_REG(SRC_SRCIR, 0x204, 0x40), + RSND_GEN_M_REG(SRC_ADINR, 0x214, 0x40), + RSND_GEN_M_REG(SRC_IFSCR, 0x21c, 0x40), + RSND_GEN_M_REG(SRC_IFSVR, 0x220, 0x40), + RSND_GEN_M_REG(SRC_SRCCR, 0x224, 0x40), + RSND_GEN_M_REG(SRC_BSDSR, 0x22c, 0x40), + RSND_GEN_M_REG(SRC_BSISR, 0x238, 0x40), + RSND_GEN_M_REG(CTU_SWRSR, 0x500, 0x100), + RSND_GEN_M_REG(CTU_CTUIR, 0x504, 0x100), + RSND_GEN_M_REG(CTU_ADINR, 0x508, 0x100), + RSND_GEN_M_REG(CTU_CPMDR, 0x510, 0x100), + RSND_GEN_M_REG(CTU_SCMDR, 0x514, 0x100), + RSND_GEN_M_REG(CTU_SV00R, 0x518, 0x100), + RSND_GEN_M_REG(CTU_SV01R, 0x51c, 0x100), + RSND_GEN_M_REG(CTU_SV02R, 0x520, 0x100), + RSND_GEN_M_REG(CTU_SV03R, 0x524, 0x100), + RSND_GEN_M_REG(CTU_SV04R, 0x528, 0x100), + RSND_GEN_M_REG(CTU_SV05R, 0x52c, 0x100), + RSND_GEN_M_REG(CTU_SV06R, 0x530, 0x100), + RSND_GEN_M_REG(CTU_SV07R, 0x534, 0x100), + RSND_GEN_M_REG(CTU_SV10R, 0x538, 0x100), + RSND_GEN_M_REG(CTU_SV11R, 0x53c, 0x100), + RSND_GEN_M_REG(CTU_SV12R, 0x540, 0x100), + RSND_GEN_M_REG(CTU_SV13R, 0x544, 0x100), + RSND_GEN_M_REG(CTU_SV14R, 0x548, 0x100), + RSND_GEN_M_REG(CTU_SV15R, 0x54c, 0x100), + RSND_GEN_M_REG(CTU_SV16R, 0x550, 0x100), + RSND_GEN_M_REG(CTU_SV17R, 0x554, 0x100), + RSND_GEN_M_REG(CTU_SV20R, 0x558, 0x100), + RSND_GEN_M_REG(CTU_SV21R, 0x55c, 0x100), + RSND_GEN_M_REG(CTU_SV22R, 0x560, 0x100), + RSND_GEN_M_REG(CTU_SV23R, 0x564, 0x100), + RSND_GEN_M_REG(CTU_SV24R, 0x568, 0x100), + RSND_GEN_M_REG(CTU_SV25R, 0x56c, 0x100), + RSND_GEN_M_REG(CTU_SV26R, 0x570, 0x100), + RSND_GEN_M_REG(CTU_SV27R, 0x574, 0x100), + RSND_GEN_M_REG(CTU_SV30R, 0x578, 0x100), + RSND_GEN_M_REG(CTU_SV31R, 0x57c, 0x100), + RSND_GEN_M_REG(CTU_SV32R, 0x580, 0x100), + RSND_GEN_M_REG(CTU_SV33R, 0x584, 0x100), + RSND_GEN_M_REG(CTU_SV34R, 0x588, 0x100), + RSND_GEN_M_REG(CTU_SV35R, 0x58c, 0x100), + RSND_GEN_M_REG(CTU_SV36R, 0x590, 0x100), + RSND_GEN_M_REG(CTU_SV37R, 0x594, 0x100), + RSND_GEN_M_REG(MIX_SWRSR, 0xd00, 0x40), + RSND_GEN_M_REG(MIX_MIXIR, 0xd04, 0x40), + RSND_GEN_M_REG(MIX_ADINR, 0xd08, 0x40), + RSND_GEN_M_REG(MIX_MIXMR, 0xd10, 0x40), + RSND_GEN_M_REG(MIX_MVPDR, 0xd14, 0x40), + RSND_GEN_M_REG(MIX_MDBAR, 0xd18, 0x40), + RSND_GEN_M_REG(MIX_MDBBR, 0xd1c, 0x40), + RSND_GEN_M_REG(MIX_MDBCR, 0xd20, 0x40), + RSND_GEN_M_REG(MIX_MDBDR, 0xd24, 0x40), + RSND_GEN_M_REG(MIX_MDBER, 0xd28, 0x40), + RSND_GEN_M_REG(DVC_SWRSR, 0xe00, 0x100), + RSND_GEN_M_REG(DVC_DVUIR, 0xe04, 0x100), + RSND_GEN_M_REG(DVC_ADINR, 0xe08, 0x100), + RSND_GEN_M_REG(DVC_DVUCR, 0xe10, 0x100), + RSND_GEN_M_REG(DVC_ZCMCR, 0xe14, 0x100), + RSND_GEN_M_REG(DVC_VRCTR, 0xe18, 0x100), + RSND_GEN_M_REG(DVC_VRPDR, 0xe1c, 0x100), + RSND_GEN_M_REG(DVC_VRDBR, 0xe20, 0x100), + RSND_GEN_M_REG(DVC_VOL0R, 0xe28, 0x100), + RSND_GEN_M_REG(DVC_VOL1R, 0xe2c, 0x100), + RSND_GEN_M_REG(DVC_VOL2R, 0xe30, 0x100), + RSND_GEN_M_REG(DVC_VOL3R, 0xe34, 0x100), + RSND_GEN_M_REG(DVC_VOL4R, 0xe38, 0x100), + RSND_GEN_M_REG(DVC_VOL5R, 0xe3c, 0x100), + RSND_GEN_M_REG(DVC_VOL6R, 0xe40, 0x100), + RSND_GEN_M_REG(DVC_VOL7R, 0xe44, 0x100), + RSND_GEN_M_REG(DVC_DVUER, 0xe48, 0x100), +}; + +static const struct rsnd_regmap_field_conf conf_common_adg[] = { + RSND_GEN_S_REG(BRRA, 0x00), + RSND_GEN_S_REG(BRRB, 0x04), + RSND_GEN_S_REG(BRGCKR, 0x08), + RSND_GEN_S_REG(AUDIO_CLK_SEL0, 0x0c), + RSND_GEN_S_REG(AUDIO_CLK_SEL1, 0x10), + RSND_GEN_S_REG(AUDIO_CLK_SEL2, 0x14), + RSND_GEN_S_REG(DIV_EN, 0x30), + RSND_GEN_S_REG(SRCIN_TIMSEL0, 0x34), + RSND_GEN_S_REG(SRCIN_TIMSEL1, 0x38), + RSND_GEN_S_REG(SRCIN_TIMSEL2, 0x3c), + RSND_GEN_S_REG(SRCIN_TIMSEL3, 0x40), + RSND_GEN_S_REG(SRCIN_TIMSEL4, 0x44), + RSND_GEN_S_REG(SRCOUT_TIMSEL0, 0x48), + RSND_GEN_S_REG(SRCOUT_TIMSEL1, 0x4c), + RSND_GEN_S_REG(SRCOUT_TIMSEL2, 0x50), + RSND_GEN_S_REG(SRCOUT_TIMSEL3, 0x54), + RSND_GEN_S_REG(SRCOUT_TIMSEL4, 0x58), + RSND_GEN_S_REG(CMDOUT_TIMSEL, 0x5c), +}; + +static const struct rsnd_regmap_field_conf conf_common_ssi[] = { + RSND_GEN_M_REG(SSICR, 0x00, 0x40), + RSND_GEN_M_REG(SSISR, 0x04, 0x40), + RSND_GEN_M_REG(SSITDR, 0x08, 0x40), + RSND_GEN_M_REG(SSIRDR, 0x0c, 0x40), + RSND_GEN_M_REG(SSIWSR, 0x20, 0x40), +}; + /* * Gen4 */ static int rsnd_gen4_probe(struct rsnd_priv *priv) { - static const struct rsnd_regmap_field_conf conf_ssiu[] = { - RSND_GEN_S_REG(SSI_SYS_INT_ENABLE0, 0x850), - RSND_GEN_S_REG(SSI_SYS_INT_ENABLE2, 0x858), - RSND_GEN_S_REG(SSI_SYS_INT_ENABLE4, 0x890), - RSND_GEN_S_REG(SSI_SYS_INT_ENABLE6, 0x898), - RSND_GEN_S_REG(SSI_SYS_STATUS0, 0x840), - RSND_GEN_S_REG(SSI_SYS_STATUS2, 0x848), - RSND_GEN_S_REG(SSI_SYS_STATUS4, 0x880), - RSND_GEN_S_REG(SSI_SYS_STATUS6, 0x888), - - RSND_GEN_S_REG(SSI_BUSIF0_MODE, 0x0), - RSND_GEN_S_REG(SSI_BUSIF0_ADINR, 0x4), - RSND_GEN_S_REG(SSI_BUSIF0_DALIGN, 0x8), - RSND_GEN_S_REG(SSI_BUSIF1_MODE, 0x20), - RSND_GEN_S_REG(SSI_BUSIF1_ADINR, 0x24), - RSND_GEN_S_REG(SSI_BUSIF1_DALIGN, 0x28), - RSND_GEN_S_REG(SSI_BUSIF2_MODE, 0x40), - RSND_GEN_S_REG(SSI_BUSIF2_ADINR, 0x44), - RSND_GEN_S_REG(SSI_BUSIF2_DALIGN, 0x48), - RSND_GEN_S_REG(SSI_BUSIF3_MODE, 0x60), - RSND_GEN_S_REG(SSI_BUSIF3_ADINR, 0x64), - RSND_GEN_S_REG(SSI_BUSIF3_DALIGN, 0x68), - RSND_GEN_S_REG(SSI_BUSIF4_MODE, 0x500), - RSND_GEN_S_REG(SSI_BUSIF4_ADINR, 0x504), - RSND_GEN_S_REG(SSI_BUSIF4_DALIGN, 0x508), - RSND_GEN_S_REG(SSI_BUSIF5_MODE, 0x520), - RSND_GEN_S_REG(SSI_BUSIF5_ADINR, 0x524), - RSND_GEN_S_REG(SSI_BUSIF5_DALIGN, 0x528), - RSND_GEN_S_REG(SSI_BUSIF6_MODE, 0x540), - RSND_GEN_S_REG(SSI_BUSIF6_ADINR, 0x544), - RSND_GEN_S_REG(SSI_BUSIF6_DALIGN, 0x548), - RSND_GEN_S_REG(SSI_BUSIF7_MODE, 0x560), - RSND_GEN_S_REG(SSI_BUSIF7_ADINR, 0x564), - RSND_GEN_S_REG(SSI_BUSIF7_DALIGN, 0x568), - RSND_GEN_S_REG(SSI_CTRL, 0x010), - RSND_GEN_S_REG(SSI_INT_ENABLE, 0x018), - RSND_GEN_S_REG(SSI_MODE, 0x00c), - RSND_GEN_S_REG(SSI_MODE2, 0xa0c), - }; - static const struct rsnd_regmap_field_conf conf_adg[] = { - RSND_GEN_S_REG(BRRA, 0x00), - RSND_GEN_S_REG(BRRB, 0x04), - RSND_GEN_S_REG(BRGCKR, 0x08), - RSND_GEN_S_REG(AUDIO_CLK_SEL0, 0x0c), - }; - static const struct rsnd_regmap_field_conf conf_ssi[] = { - RSND_GEN_S_REG(SSICR, 0x00), - RSND_GEN_S_REG(SSISR, 0x04), - RSND_GEN_S_REG(SSITDR, 0x08), - RSND_GEN_S_REG(SSIRDR, 0x0c), - RSND_GEN_S_REG(SSIWSR, 0x20), - }; - static const struct rsnd_regmap_field_conf conf_sdmc[] = { - RSND_GEN_M_REG(SSI_BUSIF, 0x0, 0x8000), - }; - int ret_adg = rsnd_gen_regmap_init(priv, 10, RSND_GEN4_ADG, "adg", conf_adg); - int ret_ssiu = rsnd_gen_regmap_init(priv, 10, RSND_GEN4_SSIU, "ssiu", conf_ssiu); - int ret_ssi = rsnd_gen_regmap_init(priv, 10, RSND_GEN4_SSI, "ssi", conf_ssi); - int ret_sdmc = rsnd_gen_regmap_init(priv, 10, RSND_GEN4_SDMC, "sdmc", conf_sdmc); + struct rsnd_regmap_field_conf conf_null[] = { }; + + /* + * ssiu: SSIU0 + * ssi : SSI0 + */ + int ret_ssiu = rsnd_gen_regmap_init(priv, 1, RSND_GEN4_SSIU, "ssiu", conf_common_ssiu); + int ret_ssi = rsnd_gen_regmap_init(priv, 1, RSND_GEN4_SSI, "ssi", conf_common_ssi); + int ret_adg = rsnd_gen_regmap_init(priv, 1, RSND_GEN4_ADG, "adg", conf_common_adg); + int ret_sdmc = rsnd_gen_regmap_init(priv, 1, RSND_GEN4_SDMC, "sdmc", conf_null); return ret_adg | ret_ssiu | ret_ssi | ret_sdmc; } @@ -288,215 +438,17 @@ static int rsnd_gen4_probe(struct rsnd_priv *priv) */ static int rsnd_gen2_probe(struct rsnd_priv *priv) { - static const struct rsnd_regmap_field_conf conf_ssiu[] = { - RSND_GEN_S_REG(SSI_MODE0, 0x800), - RSND_GEN_S_REG(SSI_MODE1, 0x804), - RSND_GEN_S_REG(SSI_MODE2, 0x808), - RSND_GEN_S_REG(SSI_CONTROL, 0x810), - RSND_GEN_S_REG(SSI_SYS_STATUS0, 0x840), - RSND_GEN_S_REG(SSI_SYS_STATUS1, 0x844), - RSND_GEN_S_REG(SSI_SYS_STATUS2, 0x848), - RSND_GEN_S_REG(SSI_SYS_STATUS3, 0x84c), - RSND_GEN_S_REG(SSI_SYS_STATUS4, 0x880), - RSND_GEN_S_REG(SSI_SYS_STATUS5, 0x884), - RSND_GEN_S_REG(SSI_SYS_STATUS6, 0x888), - RSND_GEN_S_REG(SSI_SYS_STATUS7, 0x88c), - RSND_GEN_S_REG(SSI_SYS_INT_ENABLE0, 0x850), - RSND_GEN_S_REG(SSI_SYS_INT_ENABLE1, 0x854), - RSND_GEN_S_REG(SSI_SYS_INT_ENABLE2, 0x858), - RSND_GEN_S_REG(SSI_SYS_INT_ENABLE3, 0x85c), - RSND_GEN_S_REG(SSI_SYS_INT_ENABLE4, 0x890), - RSND_GEN_S_REG(SSI_SYS_INT_ENABLE5, 0x894), - RSND_GEN_S_REG(SSI_SYS_INT_ENABLE6, 0x898), - RSND_GEN_S_REG(SSI_SYS_INT_ENABLE7, 0x89c), - RSND_GEN_S_REG(HDMI0_SEL, 0x9e0), - RSND_GEN_S_REG(HDMI1_SEL, 0x9e4), - - /* FIXME: it needs SSI_MODE2/3 in the future */ - RSND_GEN_M_REG(SSI_BUSIF0_MODE, 0x0, 0x80), - RSND_GEN_M_REG(SSI_BUSIF0_ADINR, 0x4, 0x80), - RSND_GEN_M_REG(SSI_BUSIF0_DALIGN, 0x8, 0x80), - RSND_GEN_M_REG(SSI_BUSIF1_MODE, 0x20, 0x80), - RSND_GEN_M_REG(SSI_BUSIF1_ADINR, 0x24, 0x80), - RSND_GEN_M_REG(SSI_BUSIF1_DALIGN, 0x28, 0x80), - RSND_GEN_M_REG(SSI_BUSIF2_MODE, 0x40, 0x80), - RSND_GEN_M_REG(SSI_BUSIF2_ADINR, 0x44, 0x80), - RSND_GEN_M_REG(SSI_BUSIF2_DALIGN, 0x48, 0x80), - RSND_GEN_M_REG(SSI_BUSIF3_MODE, 0x60, 0x80), - RSND_GEN_M_REG(SSI_BUSIF3_ADINR, 0x64, 0x80), - RSND_GEN_M_REG(SSI_BUSIF3_DALIGN, 0x68, 0x80), - RSND_GEN_M_REG(SSI_BUSIF4_MODE, 0x500, 0x80), - RSND_GEN_M_REG(SSI_BUSIF4_ADINR, 0x504, 0x80), - RSND_GEN_M_REG(SSI_BUSIF4_DALIGN, 0x508, 0x80), - RSND_GEN_M_REG(SSI_BUSIF5_MODE, 0x520, 0x80), - RSND_GEN_M_REG(SSI_BUSIF5_ADINR, 0x524, 0x80), - RSND_GEN_M_REG(SSI_BUSIF5_DALIGN, 0x528, 0x80), - RSND_GEN_M_REG(SSI_BUSIF6_MODE, 0x540, 0x80), - RSND_GEN_M_REG(SSI_BUSIF6_ADINR, 0x544, 0x80), - RSND_GEN_M_REG(SSI_BUSIF6_DALIGN, 0x548, 0x80), - RSND_GEN_M_REG(SSI_BUSIF7_MODE, 0x560, 0x80), - RSND_GEN_M_REG(SSI_BUSIF7_ADINR, 0x564, 0x80), - RSND_GEN_M_REG(SSI_BUSIF7_DALIGN, 0x568, 0x80), - RSND_GEN_M_REG(SSI_MODE, 0xc, 0x80), - RSND_GEN_M_REG(SSI_CTRL, 0x10, 0x80), - RSND_GEN_M_REG(SSI_INT_ENABLE, 0x18, 0x80), - RSND_GEN_S_REG(SSI9_BUSIF0_MODE, 0x48c), - RSND_GEN_S_REG(SSI9_BUSIF0_ADINR, 0x484), - RSND_GEN_S_REG(SSI9_BUSIF0_DALIGN, 0x488), - RSND_GEN_S_REG(SSI9_BUSIF1_MODE, 0x4a0), - RSND_GEN_S_REG(SSI9_BUSIF1_ADINR, 0x4a4), - RSND_GEN_S_REG(SSI9_BUSIF1_DALIGN, 0x4a8), - RSND_GEN_S_REG(SSI9_BUSIF2_MODE, 0x4c0), - RSND_GEN_S_REG(SSI9_BUSIF2_ADINR, 0x4c4), - RSND_GEN_S_REG(SSI9_BUSIF2_DALIGN, 0x4c8), - RSND_GEN_S_REG(SSI9_BUSIF3_MODE, 0x4e0), - RSND_GEN_S_REG(SSI9_BUSIF3_ADINR, 0x4e4), - RSND_GEN_S_REG(SSI9_BUSIF3_DALIGN, 0x4e8), - RSND_GEN_S_REG(SSI9_BUSIF4_MODE, 0xd80), - RSND_GEN_S_REG(SSI9_BUSIF4_ADINR, 0xd84), - RSND_GEN_S_REG(SSI9_BUSIF4_DALIGN, 0xd88), - RSND_GEN_S_REG(SSI9_BUSIF5_MODE, 0xda0), - RSND_GEN_S_REG(SSI9_BUSIF5_ADINR, 0xda4), - RSND_GEN_S_REG(SSI9_BUSIF5_DALIGN, 0xda8), - RSND_GEN_S_REG(SSI9_BUSIF6_MODE, 0xdc0), - RSND_GEN_S_REG(SSI9_BUSIF6_ADINR, 0xdc4), - RSND_GEN_S_REG(SSI9_BUSIF6_DALIGN, 0xdc8), - RSND_GEN_S_REG(SSI9_BUSIF7_MODE, 0xde0), - RSND_GEN_S_REG(SSI9_BUSIF7_ADINR, 0xde4), - RSND_GEN_S_REG(SSI9_BUSIF7_DALIGN, 0xde8), - }; - - static const struct rsnd_regmap_field_conf conf_scu[] = { - RSND_GEN_M_REG(SRC_I_BUSIF_MODE,0x0, 0x20), - RSND_GEN_M_REG(SRC_O_BUSIF_MODE,0x4, 0x20), - RSND_GEN_M_REG(SRC_BUSIF_DALIGN,0x8, 0x20), - RSND_GEN_M_REG(SRC_ROUTE_MODE0, 0xc, 0x20), - RSND_GEN_M_REG(SRC_CTRL, 0x10, 0x20), - RSND_GEN_M_REG(SRC_INT_ENABLE0, 0x18, 0x20), - RSND_GEN_M_REG(CMD_BUSIF_MODE, 0x184, 0x20), - RSND_GEN_M_REG(CMD_BUSIF_DALIGN,0x188, 0x20), - RSND_GEN_M_REG(CMD_ROUTE_SLCT, 0x18c, 0x20), - RSND_GEN_M_REG(CMD_CTRL, 0x190, 0x20), - RSND_GEN_S_REG(SCU_SYS_STATUS0, 0x1c8), - RSND_GEN_S_REG(SCU_SYS_INT_EN0, 0x1cc), - RSND_GEN_S_REG(SCU_SYS_STATUS1, 0x1d0), - RSND_GEN_S_REG(SCU_SYS_INT_EN1, 0x1d4), - RSND_GEN_M_REG(SRC_SWRSR, 0x200, 0x40), - RSND_GEN_M_REG(SRC_SRCIR, 0x204, 0x40), - RSND_GEN_M_REG(SRC_ADINR, 0x214, 0x40), - RSND_GEN_M_REG(SRC_IFSCR, 0x21c, 0x40), - RSND_GEN_M_REG(SRC_IFSVR, 0x220, 0x40), - RSND_GEN_M_REG(SRC_SRCCR, 0x224, 0x40), - RSND_GEN_M_REG(SRC_BSDSR, 0x22c, 0x40), - RSND_GEN_M_REG(SRC_BSISR, 0x238, 0x40), - RSND_GEN_M_REG(CTU_SWRSR, 0x500, 0x100), - RSND_GEN_M_REG(CTU_CTUIR, 0x504, 0x100), - RSND_GEN_M_REG(CTU_ADINR, 0x508, 0x100), - RSND_GEN_M_REG(CTU_CPMDR, 0x510, 0x100), - RSND_GEN_M_REG(CTU_SCMDR, 0x514, 0x100), - RSND_GEN_M_REG(CTU_SV00R, 0x518, 0x100), - RSND_GEN_M_REG(CTU_SV01R, 0x51c, 0x100), - RSND_GEN_M_REG(CTU_SV02R, 0x520, 0x100), - RSND_GEN_M_REG(CTU_SV03R, 0x524, 0x100), - RSND_GEN_M_REG(CTU_SV04R, 0x528, 0x100), - RSND_GEN_M_REG(CTU_SV05R, 0x52c, 0x100), - RSND_GEN_M_REG(CTU_SV06R, 0x530, 0x100), - RSND_GEN_M_REG(CTU_SV07R, 0x534, 0x100), - RSND_GEN_M_REG(CTU_SV10R, 0x538, 0x100), - RSND_GEN_M_REG(CTU_SV11R, 0x53c, 0x100), - RSND_GEN_M_REG(CTU_SV12R, 0x540, 0x100), - RSND_GEN_M_REG(CTU_SV13R, 0x544, 0x100), - RSND_GEN_M_REG(CTU_SV14R, 0x548, 0x100), - RSND_GEN_M_REG(CTU_SV15R, 0x54c, 0x100), - RSND_GEN_M_REG(CTU_SV16R, 0x550, 0x100), - RSND_GEN_M_REG(CTU_SV17R, 0x554, 0x100), - RSND_GEN_M_REG(CTU_SV20R, 0x558, 0x100), - RSND_GEN_M_REG(CTU_SV21R, 0x55c, 0x100), - RSND_GEN_M_REG(CTU_SV22R, 0x560, 0x100), - RSND_GEN_M_REG(CTU_SV23R, 0x564, 0x100), - RSND_GEN_M_REG(CTU_SV24R, 0x568, 0x100), - RSND_GEN_M_REG(CTU_SV25R, 0x56c, 0x100), - RSND_GEN_M_REG(CTU_SV26R, 0x570, 0x100), - RSND_GEN_M_REG(CTU_SV27R, 0x574, 0x100), - RSND_GEN_M_REG(CTU_SV30R, 0x578, 0x100), - RSND_GEN_M_REG(CTU_SV31R, 0x57c, 0x100), - RSND_GEN_M_REG(CTU_SV32R, 0x580, 0x100), - RSND_GEN_M_REG(CTU_SV33R, 0x584, 0x100), - RSND_GEN_M_REG(CTU_SV34R, 0x588, 0x100), - RSND_GEN_M_REG(CTU_SV35R, 0x58c, 0x100), - RSND_GEN_M_REG(CTU_SV36R, 0x590, 0x100), - RSND_GEN_M_REG(CTU_SV37R, 0x594, 0x100), - RSND_GEN_M_REG(MIX_SWRSR, 0xd00, 0x40), - RSND_GEN_M_REG(MIX_MIXIR, 0xd04, 0x40), - RSND_GEN_M_REG(MIX_ADINR, 0xd08, 0x40), - RSND_GEN_M_REG(MIX_MIXMR, 0xd10, 0x40), - RSND_GEN_M_REG(MIX_MVPDR, 0xd14, 0x40), - RSND_GEN_M_REG(MIX_MDBAR, 0xd18, 0x40), - RSND_GEN_M_REG(MIX_MDBBR, 0xd1c, 0x40), - RSND_GEN_M_REG(MIX_MDBCR, 0xd20, 0x40), - RSND_GEN_M_REG(MIX_MDBDR, 0xd24, 0x40), - RSND_GEN_M_REG(MIX_MDBER, 0xd28, 0x40), - RSND_GEN_M_REG(DVC_SWRSR, 0xe00, 0x100), - RSND_GEN_M_REG(DVC_DVUIR, 0xe04, 0x100), - RSND_GEN_M_REG(DVC_ADINR, 0xe08, 0x100), - RSND_GEN_M_REG(DVC_DVUCR, 0xe10, 0x100), - RSND_GEN_M_REG(DVC_ZCMCR, 0xe14, 0x100), - RSND_GEN_M_REG(DVC_VRCTR, 0xe18, 0x100), - RSND_GEN_M_REG(DVC_VRPDR, 0xe1c, 0x100), - RSND_GEN_M_REG(DVC_VRDBR, 0xe20, 0x100), - RSND_GEN_M_REG(DVC_VOL0R, 0xe28, 0x100), - RSND_GEN_M_REG(DVC_VOL1R, 0xe2c, 0x100), - RSND_GEN_M_REG(DVC_VOL2R, 0xe30, 0x100), - RSND_GEN_M_REG(DVC_VOL3R, 0xe34, 0x100), - RSND_GEN_M_REG(DVC_VOL4R, 0xe38, 0x100), - RSND_GEN_M_REG(DVC_VOL5R, 0xe3c, 0x100), - RSND_GEN_M_REG(DVC_VOL6R, 0xe40, 0x100), - RSND_GEN_M_REG(DVC_VOL7R, 0xe44, 0x100), - RSND_GEN_M_REG(DVC_DVUER, 0xe48, 0x100), - }; - static const struct rsnd_regmap_field_conf conf_adg[] = { - RSND_GEN_S_REG(BRRA, 0x00), - RSND_GEN_S_REG(BRRB, 0x04), - RSND_GEN_S_REG(BRGCKR, 0x08), - RSND_GEN_S_REG(AUDIO_CLK_SEL0, 0x0c), - RSND_GEN_S_REG(AUDIO_CLK_SEL1, 0x10), - RSND_GEN_S_REG(AUDIO_CLK_SEL2, 0x14), - RSND_GEN_S_REG(DIV_EN, 0x30), - RSND_GEN_S_REG(SRCIN_TIMSEL0, 0x34), - RSND_GEN_S_REG(SRCIN_TIMSEL1, 0x38), - RSND_GEN_S_REG(SRCIN_TIMSEL2, 0x3c), - RSND_GEN_S_REG(SRCIN_TIMSEL3, 0x40), - RSND_GEN_S_REG(SRCIN_TIMSEL4, 0x44), - RSND_GEN_S_REG(SRCOUT_TIMSEL0, 0x48), - RSND_GEN_S_REG(SRCOUT_TIMSEL1, 0x4c), - RSND_GEN_S_REG(SRCOUT_TIMSEL2, 0x50), - RSND_GEN_S_REG(SRCOUT_TIMSEL3, 0x54), - RSND_GEN_S_REG(SRCOUT_TIMSEL4, 0x58), - RSND_GEN_S_REG(CMDOUT_TIMSEL, 0x5c), - }; - static const struct rsnd_regmap_field_conf conf_ssi[] = { - RSND_GEN_M_REG(SSICR, 0x00, 0x40), - RSND_GEN_M_REG(SSISR, 0x04, 0x40), - RSND_GEN_M_REG(SSITDR, 0x08, 0x40), - RSND_GEN_M_REG(SSIRDR, 0x0c, 0x40), - RSND_GEN_M_REG(SSIWSR, 0x20, 0x40), - }; - int ret_ssiu; - int ret_scu; - int ret_adg; - int ret_ssi; - - ret_ssiu = rsnd_gen_regmap_init(priv, 10, RSND_GEN2_SSIU, "ssiu", conf_ssiu); - ret_scu = rsnd_gen_regmap_init(priv, 10, RSND_GEN2_SCU, "scu", conf_scu); - ret_adg = rsnd_gen_regmap_init(priv, 10, RSND_GEN2_ADG, "adg", conf_adg); - ret_ssi = rsnd_gen_regmap_init(priv, 10, RSND_GEN2_SSI, "ssi", conf_ssi); - if (ret_ssiu < 0 || - ret_scu < 0 || - ret_adg < 0 || - ret_ssi < 0) - return ret_ssiu | ret_scu | ret_adg | ret_ssi; - - return 0; + /* + * ssi : SSI0 - SSI9 + * ssiu: SSIU0 - SSIU9 + * scu : SRC0 - SRC9 etc + */ + int ret_ssi = rsnd_gen_regmap_init(priv, 10, RSND_GEN2_SSI, "ssi", conf_common_ssi); + int ret_ssiu = rsnd_gen_regmap_init(priv, 10, RSND_GEN2_SSIU, "ssiu", conf_common_ssiu); + int ret_scu = rsnd_gen_regmap_init(priv, 10, RSND_GEN2_SCU, "scu", conf_common_scu); + int ret_adg = rsnd_gen_regmap_init(priv, 1, RSND_GEN2_ADG, "adg", conf_common_adg); + + return ret_ssi | ret_ssiu | ret_scu | ret_adg; } /* @@ -505,30 +457,13 @@ static int rsnd_gen2_probe(struct rsnd_priv *priv) static int rsnd_gen1_probe(struct rsnd_priv *priv) { - static const struct rsnd_regmap_field_conf conf_adg[] = { - RSND_GEN_S_REG(BRRA, 0x00), - RSND_GEN_S_REG(BRRB, 0x04), - RSND_GEN_S_REG(BRGCKR, 0x08), - RSND_GEN_S_REG(AUDIO_CLK_SEL0, 0x0c), - RSND_GEN_S_REG(AUDIO_CLK_SEL1, 0x10), - }; - static const struct rsnd_regmap_field_conf conf_ssi[] = { - RSND_GEN_M_REG(SSICR, 0x00, 0x40), - RSND_GEN_M_REG(SSISR, 0x04, 0x40), - RSND_GEN_M_REG(SSITDR, 0x08, 0x40), - RSND_GEN_M_REG(SSIRDR, 0x0c, 0x40), - RSND_GEN_M_REG(SSIWSR, 0x20, 0x40), - }; - int ret_adg; - int ret_ssi; - - ret_adg = rsnd_gen_regmap_init(priv, 9, RSND_GEN1_ADG, "adg", conf_adg); - ret_ssi = rsnd_gen_regmap_init(priv, 9, RSND_GEN1_SSI, "ssi", conf_ssi); - if (ret_adg < 0 || - ret_ssi < 0) - return ret_adg | ret_ssi; + /* + * ssi : SSI0 - SSI8 + */ + int ret_ssi = rsnd_gen_regmap_init(priv, 9, RSND_GEN1_SSI, "ssi", conf_common_ssi); + int ret_adg = rsnd_gen_regmap_init(priv, 1, RSND_GEN1_ADG, "adg", conf_common_adg); - return 0; + return ret_adg | ret_ssi; } /* diff --git a/sound/soc/sh/rcar/rsnd.h b/sound/soc/sh/rcar/rsnd.h index da716b1f52e4..e063286cc328 100644 --- a/sound/soc/sh/rcar/rsnd.h +++ b/sound/soc/sh/rcar/rsnd.h @@ -200,7 +200,6 @@ enum rsnd_reg { SSI_SYS_INT_ENABLE5, SSI_SYS_INT_ENABLE6, SSI_SYS_INT_ENABLE7, - SSI_BUSIF, HDMI0_SEL, HDMI1_SEL, SSI9_BUSIF0_MODE, -- cgit v1.2.3 From 6e4e5432942a57f4c3e6a5a4a97a4d1a164dca61 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Tue, 2 Apr 2024 02:24:01 +0000 Subject: ASoC: rsnd: don't get resource from ID All SoC has reg-name, no need to support getting resource from ID any more. Remove it. To get physical address for DMA settings, it still need to know the index, but it is no longer fixed. This patch tidyup it. Signed-off-by: Kuninori Morimoto Link: https://msgid.link/r/87zfuca4e6.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/sh/rcar/cmd.c | 2 +- sound/soc/sh/rcar/ctu.c | 2 +- sound/soc/sh/rcar/dma.c | 6 +++--- sound/soc/sh/rcar/dvc.c | 2 +- sound/soc/sh/rcar/gen.c | 22 ++++++++++------------ sound/soc/sh/rcar/mix.c | 2 +- sound/soc/sh/rcar/rsnd.h | 19 +++++-------------- sound/soc/sh/rcar/src.c | 6 +++--- sound/soc/sh/rcar/ssi.c | 2 +- sound/soc/sh/rcar/ssiu.c | 2 +- 10 files changed, 27 insertions(+), 38 deletions(-) diff --git a/sound/soc/sh/rcar/cmd.c b/sound/soc/sh/rcar/cmd.c index 329e6ab1b222..ec086d8e4d44 100644 --- a/sound/soc/sh/rcar/cmd.c +++ b/sound/soc/sh/rcar/cmd.c @@ -119,7 +119,7 @@ static void rsnd_cmd_debug_info(struct seq_file *m, struct rsnd_dai_stream *io, struct rsnd_mod *mod) { - rsnd_debugfs_mod_reg_show(m, mod, RSND_GEN2_SCU, + rsnd_debugfs_mod_reg_show(m, mod, RSND_BASE_SCU, 0x180 + rsnd_mod_id_raw(mod) * 0x20, 0x30); } #define DEBUG_INFO .debug_info = rsnd_cmd_debug_info diff --git a/sound/soc/sh/rcar/ctu.c b/sound/soc/sh/rcar/ctu.c index e39eb2ac7e95..a35fc5ef8770 100644 --- a/sound/soc/sh/rcar/ctu.c +++ b/sound/soc/sh/rcar/ctu.c @@ -284,7 +284,7 @@ static void rsnd_ctu_debug_info(struct seq_file *m, struct rsnd_dai_stream *io, struct rsnd_mod *mod) { - rsnd_debugfs_mod_reg_show(m, mod, RSND_GEN2_SCU, + rsnd_debugfs_mod_reg_show(m, mod, RSND_BASE_SCU, 0x500 + rsnd_mod_id_raw(mod) * 0x100, 0x100); } #define DEBUG_INFO .debug_info = rsnd_ctu_debug_info diff --git a/sound/soc/sh/rcar/dma.c b/sound/soc/sh/rcar/dma.c index 1c494e521463..7b499eee5080 100644 --- a/sound/soc/sh/rcar/dma.c +++ b/sound/soc/sh/rcar/dma.c @@ -585,8 +585,8 @@ rsnd_gen2_dma_addr(struct rsnd_dai_stream *io, { struct rsnd_priv *priv = rsnd_io_to_priv(io); struct device *dev = rsnd_priv_to_dev(priv); - phys_addr_t ssi_reg = rsnd_gen_get_phy_addr(priv, RSND_GEN2_SSI); - phys_addr_t src_reg = rsnd_gen_get_phy_addr(priv, RSND_GEN2_SCU); + phys_addr_t ssi_reg = rsnd_gen_get_phy_addr(priv, RSND_BASE_SSI); + phys_addr_t src_reg = rsnd_gen_get_phy_addr(priv, RSND_BASE_SCU); int is_ssi = !!(rsnd_io_to_mod_ssi(io) == mod) || !!(rsnd_io_to_mod_ssiu(io) == mod); int use_src = !!rsnd_io_to_mod_src(io); @@ -666,7 +666,7 @@ rsnd_gen4_dma_addr(struct rsnd_dai_stream *io, struct rsnd_mod *mod, int is_play, int is_from) { struct rsnd_priv *priv = rsnd_io_to_priv(io); - phys_addr_t addr = rsnd_gen_get_phy_addr(priv, RSND_GEN4_SDMC); + phys_addr_t addr = rsnd_gen_get_phy_addr(priv, RSND_BASE_SDMC); int id = rsnd_mod_id(mod); int busif = rsnd_mod_id_sub(mod); diff --git a/sound/soc/sh/rcar/dvc.c b/sound/soc/sh/rcar/dvc.c index 16befcbc312c..f349d6ab9fe5 100644 --- a/sound/soc/sh/rcar/dvc.c +++ b/sound/soc/sh/rcar/dvc.c @@ -294,7 +294,7 @@ static void rsnd_dvc_debug_info(struct seq_file *m, struct rsnd_dai_stream *io, struct rsnd_mod *mod) { - rsnd_debugfs_mod_reg_show(m, mod, RSND_GEN2_SCU, + rsnd_debugfs_mod_reg_show(m, mod, RSND_BASE_SCU, 0xe00 + rsnd_mod_id(mod) * 0x100, 0x60); } #define DEBUG_INFO .debug_info = rsnd_dvc_debug_info diff --git a/sound/soc/sh/rcar/gen.c b/sound/soc/sh/rcar/gen.c index e566712e5234..d1f20cde66be 100644 --- a/sound/soc/sh/rcar/gen.c +++ b/sound/soc/sh/rcar/gen.c @@ -177,8 +177,6 @@ static int _rsnd_gen_regmap_init(struct rsnd_priv *priv, regc.name = name; res = platform_get_resource_byname(pdev, IORESOURCE_MEM, name); - if (!res) - res = platform_get_resource(pdev, IORESOURCE_MEM, reg_id); if (!res) return -ENODEV; @@ -425,10 +423,10 @@ static int rsnd_gen4_probe(struct rsnd_priv *priv) * ssiu: SSIU0 * ssi : SSI0 */ - int ret_ssiu = rsnd_gen_regmap_init(priv, 1, RSND_GEN4_SSIU, "ssiu", conf_common_ssiu); - int ret_ssi = rsnd_gen_regmap_init(priv, 1, RSND_GEN4_SSI, "ssi", conf_common_ssi); - int ret_adg = rsnd_gen_regmap_init(priv, 1, RSND_GEN4_ADG, "adg", conf_common_adg); - int ret_sdmc = rsnd_gen_regmap_init(priv, 1, RSND_GEN4_SDMC, "sdmc", conf_null); + int ret_ssiu = rsnd_gen_regmap_init(priv, 1, RSND_BASE_SSIU, "ssiu", conf_common_ssiu); + int ret_ssi = rsnd_gen_regmap_init(priv, 1, RSND_BASE_SSI, "ssi", conf_common_ssi); + int ret_adg = rsnd_gen_regmap_init(priv, 1, RSND_BASE_ADG, "adg", conf_common_adg); + int ret_sdmc = rsnd_gen_regmap_init(priv, 1, RSND_BASE_SDMC, "sdmc", conf_null); return ret_adg | ret_ssiu | ret_ssi | ret_sdmc; } @@ -443,10 +441,10 @@ static int rsnd_gen2_probe(struct rsnd_priv *priv) * ssiu: SSIU0 - SSIU9 * scu : SRC0 - SRC9 etc */ - int ret_ssi = rsnd_gen_regmap_init(priv, 10, RSND_GEN2_SSI, "ssi", conf_common_ssi); - int ret_ssiu = rsnd_gen_regmap_init(priv, 10, RSND_GEN2_SSIU, "ssiu", conf_common_ssiu); - int ret_scu = rsnd_gen_regmap_init(priv, 10, RSND_GEN2_SCU, "scu", conf_common_scu); - int ret_adg = rsnd_gen_regmap_init(priv, 1, RSND_GEN2_ADG, "adg", conf_common_adg); + int ret_ssi = rsnd_gen_regmap_init(priv, 10, RSND_BASE_SSI, "ssi", conf_common_ssi); + int ret_ssiu = rsnd_gen_regmap_init(priv, 10, RSND_BASE_SSIU, "ssiu", conf_common_ssiu); + int ret_scu = rsnd_gen_regmap_init(priv, 10, RSND_BASE_SCU, "scu", conf_common_scu); + int ret_adg = rsnd_gen_regmap_init(priv, 1, RSND_BASE_ADG, "adg", conf_common_adg); return ret_ssi | ret_ssiu | ret_scu | ret_adg; } @@ -460,8 +458,8 @@ static int rsnd_gen1_probe(struct rsnd_priv *priv) /* * ssi : SSI0 - SSI8 */ - int ret_ssi = rsnd_gen_regmap_init(priv, 9, RSND_GEN1_SSI, "ssi", conf_common_ssi); - int ret_adg = rsnd_gen_regmap_init(priv, 1, RSND_GEN1_ADG, "adg", conf_common_adg); + int ret_ssi = rsnd_gen_regmap_init(priv, 9, RSND_BASE_SSI, "ssi", conf_common_ssi); + int ret_adg = rsnd_gen_regmap_init(priv, 1, RSND_BASE_ADG, "adg", conf_common_adg); return ret_adg | ret_ssi; } diff --git a/sound/soc/sh/rcar/mix.c b/sound/soc/sh/rcar/mix.c index 1de0e085804c..e724103a2e8d 100644 --- a/sound/soc/sh/rcar/mix.c +++ b/sound/soc/sh/rcar/mix.c @@ -259,7 +259,7 @@ static void rsnd_mix_debug_info(struct seq_file *m, struct rsnd_dai_stream *io, struct rsnd_mod *mod) { - rsnd_debugfs_mod_reg_show(m, mod, RSND_GEN2_SCU, + rsnd_debugfs_mod_reg_show(m, mod, RSND_BASE_SCU, 0xd00 + rsnd_mod_id(mod) * 0x40, 0x30); } #define DEBUG_INFO .debug_info = rsnd_mix_debug_info diff --git a/sound/soc/sh/rcar/rsnd.h b/sound/soc/sh/rcar/rsnd.h index e063286cc328..45cf21320280 100644 --- a/sound/soc/sh/rcar/rsnd.h +++ b/sound/soc/sh/rcar/rsnd.h @@ -20,20 +20,11 @@ #include #include -#define RSND_GEN1_SRU 0 -#define RSND_GEN1_ADG 1 -#define RSND_GEN1_SSI 2 - -#define RSND_GEN2_SCU 0 -#define RSND_GEN2_ADG 1 -#define RSND_GEN2_SSIU 2 -#define RSND_GEN2_SSI 3 - -#define RSND_GEN4_ADG 0 -#define RSND_GEN4_SSIU 1 -#define RSND_GEN4_SSI 2 -#define RSND_GEN4_SDMC 3 - +#define RSND_BASE_ADG 0 +#define RSND_BASE_SSI 1 +#define RSND_BASE_SSIU 2 +#define RSND_BASE_SCU 3 // for Gen2/Gen3 +#define RSND_BASE_SDMC 3 // for Gen4 reuse #define RSND_BASE_MAX 4 /* diff --git a/sound/soc/sh/rcar/src.c b/sound/soc/sh/rcar/src.c index 3241a1bdc9ea..8822d50b6d86 100644 --- a/sound/soc/sh/rcar/src.c +++ b/sound/soc/sh/rcar/src.c @@ -606,13 +606,13 @@ static void rsnd_src_debug_info(struct seq_file *m, struct rsnd_dai_stream *io, struct rsnd_mod *mod) { - rsnd_debugfs_mod_reg_show(m, mod, RSND_GEN2_SCU, + rsnd_debugfs_mod_reg_show(m, mod, RSND_BASE_SCU, rsnd_mod_id(mod) * 0x20, 0x20); seq_puts(m, "\n"); - rsnd_debugfs_mod_reg_show(m, mod, RSND_GEN2_SCU, + rsnd_debugfs_mod_reg_show(m, mod, RSND_BASE_SCU, 0x1c0, 0x20); seq_puts(m, "\n"); - rsnd_debugfs_mod_reg_show(m, mod, RSND_GEN2_SCU, + rsnd_debugfs_mod_reg_show(m, mod, RSND_BASE_SCU, 0x200 + rsnd_mod_id(mod) * 0x40, 0x40); } #define DEBUG_INFO .debug_info = rsnd_src_debug_info diff --git a/sound/soc/sh/rcar/ssi.c b/sound/soc/sh/rcar/ssi.c index 0a46aa1975fa..8d2a86383ae0 100644 --- a/sound/soc/sh/rcar/ssi.c +++ b/sound/soc/sh/rcar/ssi.c @@ -1049,7 +1049,7 @@ static void rsnd_ssi_debug_info(struct seq_file *m, seq_printf(m, "chan: %d\n", ssi->chan); seq_printf(m, "user: %d\n", ssi->usrcnt); - rsnd_debugfs_mod_reg_show(m, mod, RSND_GEN2_SSI, + rsnd_debugfs_mod_reg_show(m, mod, RSND_BASE_SSI, rsnd_mod_id(mod) * 0x40, 0x40); } #define DEBUG_INFO .debug_info = rsnd_ssi_debug_info diff --git a/sound/soc/sh/rcar/ssiu.c b/sound/soc/sh/rcar/ssiu.c index 17bd8cc86dd0..665e8b2db579 100644 --- a/sound/soc/sh/rcar/ssiu.c +++ b/sound/soc/sh/rcar/ssiu.c @@ -413,7 +413,7 @@ static void rsnd_ssiu_debug_info(struct seq_file *m, struct rsnd_dai_stream *io, struct rsnd_mod *mod) { - rsnd_debugfs_mod_reg_show(m, mod, RSND_GEN2_SSIU, + rsnd_debugfs_mod_reg_show(m, mod, RSND_BASE_SSIU, rsnd_mod_id(mod) * 0x80, 0x80); } #define DEBUG_INFO .debug_info = rsnd_ssiu_debug_info -- cgit v1.2.3 From 0b8ef53e120981c218ba037dddda98f414af2207 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Tue, 2 Apr 2024 02:24:09 +0000 Subject: ASoC: rsnd: rename rsnd_is_e3() to rsnd_is_gen3_e3() Renesas Sound driver is using rsnd_is_genX() macro to handling difference. We can use "grep rsnd_is_gen" to find-out difference for each SoC except rsnd_is_e3(). Let's put same rule for E3 as well. Signed-off-by: Kuninori Morimoto Link: https://msgid.link/r/87y19wa4dy.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/sh/rcar/rsnd.h | 2 +- sound/soc/sh/rcar/src.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/soc/sh/rcar/rsnd.h b/sound/soc/sh/rcar/rsnd.h index 45cf21320280..ff294aa2d640 100644 --- a/sound/soc/sh/rcar/rsnd.h +++ b/sound/soc/sh/rcar/rsnd.h @@ -703,7 +703,7 @@ struct rsnd_priv { #define rsnd_is_gen2(priv) (((priv)->flags & RSND_GEN_MASK) == RSND_GEN2) #define rsnd_is_gen3(priv) (((priv)->flags & RSND_GEN_MASK) == RSND_GEN3) #define rsnd_is_gen4(priv) (((priv)->flags & RSND_GEN_MASK) == RSND_GEN4) -#define rsnd_is_e3(priv) (((priv)->flags & \ +#define rsnd_is_gen3_e3(priv) (((priv)->flags & \ (RSND_GEN_MASK | RSND_SOC_MASK)) == \ (RSND_GEN3 | RSND_SOC_E)) diff --git a/sound/soc/sh/rcar/src.c b/sound/soc/sh/rcar/src.c index 8822d50b6d86..431e6d195b09 100644 --- a/sound/soc/sh/rcar/src.c +++ b/sound/soc/sh/rcar/src.c @@ -310,7 +310,7 @@ static void rsnd_src_set_convert_rate(struct rsnd_dai_stream *io, /* * E3 need to overwrite */ - if (rsnd_is_e3(priv)) + if (rsnd_is_gen3_e3(priv)) switch (rsnd_mod_id(mod)) { case 0: case 4: -- cgit v1.2.3 From 5be0e7f7f275aa5f05d8708db021cef0fed749d1 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Tue, 2 Apr 2024 02:24:15 +0000 Subject: ASoC: rsnd: R-Car Gen1/Gen2 exception Renesas Sound driver is using rsnd_is_genX() macro to handling difference. We can use "grep rsnd_is_gen" to find-out difference for each SoC today. In general, driver uses flag to handling SoC difference. But in Renesas Sound case, the differences are very specific, if you try to make it general, the code will become be very complicated. Some of them can use flag to handling, but we can find-out all diffence by using "grep rsnd_is_gen" today. It is not so good, but not so bad so far. So we will keep current style for a while. This patch cares Gen1/Gen2 exception by using negative handling to makes no more update for this part when we support Gen5 or later. - if (rsnd_is_gen3() || rsnd_is_gen4() || rsnd_is_gen5() || ...) + if (!rsnd_is_gen1() && !rsnd_is_gen2()) Signed-off-by: Kuninori Morimoto Link: https://msgid.link/r/87wmpga4ds.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/sh/rcar/core.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/soc/sh/rcar/core.c b/sound/soc/sh/rcar/core.c index 0b1aa23c1189..6bc7027ed4db 100644 --- a/sound/soc/sh/rcar/core.c +++ b/sound/soc/sh/rcar/core.c @@ -1512,7 +1512,7 @@ static int rsnd_dai_probe(struct rsnd_priv *priv) continue; for_each_endpoint_of_node(ports, dai_np) { __rsnd_dai_probe(priv, dai_np, dai_np, 0, dai_i); - if (rsnd_is_gen3(priv) || rsnd_is_gen4(priv)) { + if (!rsnd_is_gen1(priv) && !rsnd_is_gen2(priv)) { rdai = rsnd_rdai_get(priv, dai_i); rsnd_parse_connect_graph(priv, &rdai->playback, dai_np); @@ -1531,7 +1531,7 @@ static int rsnd_dai_probe(struct rsnd_priv *priv) for_each_child_of_node(node, dai_np) { __rsnd_dai_probe(priv, dai_np, np, dai_i, dai_i); - if (rsnd_is_gen3(priv) || rsnd_is_gen4(priv)) { + if (!rsnd_is_gen1(priv) && !rsnd_is_gen2(priv)) { rdai = rsnd_rdai_get(priv, dai_i); rsnd_parse_connect_simple(priv, &rdai->playback, dai_np); -- cgit v1.2.3 From 07f6232ff1c9909cd87e42020c91b265a58918da Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Tue, 2 Apr 2024 02:24:22 +0000 Subject: ASoC: rsnd: no exception for SCU R-Car Gen1 and Gen4 doesn't have SCU, and current driver checks Gen1 (only) on each devices (A). But these drivers are assuming it might be not enabled after that (B). /* This driver doesn't support Gen1 at this point */ (A) if (rsnd_is_gen1(priv)) return 0; (B) node = rsnd_src_of_node(priv); if (!node) return 0; /* not used is not error */ Gen4 DT doesn't have these device settings. (A) check doesn't work for it, but (B) check handling it. Gen1 DT doesn't have these device settings either, and (A) is handling it, but (B) only is very enough. (A) is no longer needed. This patch removes (A) Signed-off-by: Kuninori Morimoto Link: https://msgid.link/r/87v850a4dl.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/sh/rcar/cmd.c | 4 ---- sound/soc/sh/rcar/ctu.c | 4 ---- sound/soc/sh/rcar/dvc.c | 4 ---- sound/soc/sh/rcar/mix.c | 4 ---- sound/soc/sh/rcar/src.c | 4 ---- 5 files changed, 20 deletions(-) diff --git a/sound/soc/sh/rcar/cmd.c b/sound/soc/sh/rcar/cmd.c index ec086d8e4d44..8d9a1e345a22 100644 --- a/sound/soc/sh/rcar/cmd.c +++ b/sound/soc/sh/rcar/cmd.c @@ -157,10 +157,6 @@ int rsnd_cmd_probe(struct rsnd_priv *priv) struct rsnd_cmd *cmd; int i, nr; - /* This driver doesn't support Gen1 at this point */ - if (rsnd_is_gen1(priv)) - return 0; - /* same number as DVC */ nr = priv->dvc_nr; if (!nr) diff --git a/sound/soc/sh/rcar/ctu.c b/sound/soc/sh/rcar/ctu.c index a35fc5ef8770..a26ec7b780cd 100644 --- a/sound/soc/sh/rcar/ctu.c +++ b/sound/soc/sh/rcar/ctu.c @@ -323,10 +323,6 @@ int rsnd_ctu_probe(struct rsnd_priv *priv) char name[CTU_NAME_SIZE]; int i, nr, ret; - /* This driver doesn't support Gen1 at this point */ - if (rsnd_is_gen1(priv)) - return 0; - node = rsnd_ctu_of_node(priv); if (!node) return 0; /* not used is not error */ diff --git a/sound/soc/sh/rcar/dvc.c b/sound/soc/sh/rcar/dvc.c index f349d6ab9fe5..da91dd301aab 100644 --- a/sound/soc/sh/rcar/dvc.c +++ b/sound/soc/sh/rcar/dvc.c @@ -331,10 +331,6 @@ int rsnd_dvc_probe(struct rsnd_priv *priv) char name[RSND_DVC_NAME_SIZE]; int i, nr, ret; - /* This driver doesn't support Gen1 at this point */ - if (rsnd_is_gen1(priv)) - return 0; - node = rsnd_dvc_of_node(priv); if (!node) return 0; /* not used is not error */ diff --git a/sound/soc/sh/rcar/mix.c b/sound/soc/sh/rcar/mix.c index e724103a2e8d..024d91cc8748 100644 --- a/sound/soc/sh/rcar/mix.c +++ b/sound/soc/sh/rcar/mix.c @@ -295,10 +295,6 @@ int rsnd_mix_probe(struct rsnd_priv *priv) char name[MIX_NAME_SIZE]; int i, nr, ret; - /* This driver doesn't support Gen1 at this point */ - if (rsnd_is_gen1(priv)) - return 0; - node = rsnd_mix_of_node(priv); if (!node) return 0; /* not used is not error */ diff --git a/sound/soc/sh/rcar/src.c b/sound/soc/sh/rcar/src.c index 431e6d195b09..e7f86db0d94c 100644 --- a/sound/soc/sh/rcar/src.c +++ b/sound/soc/sh/rcar/src.c @@ -652,10 +652,6 @@ int rsnd_src_probe(struct rsnd_priv *priv) char name[RSND_SRC_NAME_SIZE]; int i, nr, ret; - /* This driver doesn't support Gen1 at this point */ - if (rsnd_is_gen1(priv)) - return 0; - node = rsnd_src_of_node(priv); if (!node) return 0; /* not used is not error */ -- cgit v1.2.3 From 91ebd32eee6cd7714b49ca4463a0f315bc26ce0e Mon Sep 17 00:00:00 2001 From: Seven Lee Date: Mon, 1 Apr 2024 18:47:53 +0800 Subject: ASoC: nau8325: Revise soc_enum structure definition. This patch is modified nau8325_dac_oversampl_enum enumerated. Use SOC_VALUE_ENUM instead to hide empty (presumably invalid) options. Signed-off-by: Seven Lee Link: https://msgid.link/r/20240401104753.3432507-1-wtli@nuvoton.com Signed-off-by: Mark Brown --- sound/soc/codecs/nau8325.c | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/sound/soc/codecs/nau8325.c b/sound/soc/codecs/nau8325.c index a00a30364c89..d65f73144597 100644 --- a/sound/soc/codecs/nau8325.c +++ b/sound/soc/codecs/nau8325.c @@ -174,13 +174,20 @@ static bool nau8325_volatile_reg(struct device *dev, unsigned int reg) } } -static const char * const nau8325_dac_oversampl[] = { - "64", "256", "128", "", "32" }; +static const char * const nau8325_dac_oversampl_texts[] = { + "64", "256", "128", "32", +}; + +static const unsigned int nau8325_dac_oversampl_values[] = { + 0, 1, 2, 4, +}; static const struct soc_enum nau8325_dac_oversampl_enum = - SOC_ENUM_SINGLE(NAU8325_R29_DAC_CTRL1, NAU8325_DAC_OVERSAMPLE_SFT, - ARRAY_SIZE(nau8325_dac_oversampl), - nau8325_dac_oversampl); + SOC_VALUE_ENUM_SINGLE(NAU8325_R29_DAC_CTRL1, + NAU8325_DAC_OVERSAMPLE_SFT, 0x7, + ARRAY_SIZE(nau8325_dac_oversampl_texts), + nau8325_dac_oversampl_texts, + nau8325_dac_oversampl_values); static const DECLARE_TLV_DB_MINMAX_MUTE(dac_vol_tlv, -8000, 600); -- cgit v1.2.3 From af133562d5aff41fcdbe51f1a504ae04788b5fc0 Mon Sep 17 00:00:00 2001 From: Petr Tesarik Date: Mon, 25 Mar 2024 09:31:04 +0100 Subject: swiotlb: extend buffer pre-padding to alloc_align_mask if necessary Allow a buffer pre-padding of up to alloc_align_mask, even if it requires allocating additional IO TLB slots. If the allocation alignment is bigger than IO_TLB_SIZE and min_align_mask covers any non-zero bits in the original address between IO_TLB_SIZE and alloc_align_mask, these bits are not preserved in the swiotlb buffer address. To fix this case, increase the allocation size and use a larger offset within the allocated buffer. As a result, extra padding slots may be allocated before the mapping start address. Leave orig_addr in these padding slots initialized to INVALID_PHYS_ADDR. These slots do not correspond to any CPU buffer, so attempts to sync the data should be ignored. The padding slots should be automatically released when the buffer is unmapped. However, swiotlb_tbl_unmap_single() takes only the address of the DMA buffer slot, not the first padding slot. Save the number of padding slots in struct io_tlb_slot and use it to adjust the slot index in swiotlb_release_slots(), so all allocated slots are properly freed. Fixes: 2fd4fa5d3fb5 ("swiotlb: Fix alignment checks when both allocation and DMA masks are present") Link: https://lore.kernel.org/linux-iommu/20240311210507.217daf8b@meshulam.tesarici.cz/ Signed-off-by: Petr Tesarik Reviewed-by: Michael Kelley Tested-by: Michael Kelley Signed-off-by: Christoph Hellwig --- kernel/dma/swiotlb.c | 59 ++++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 46 insertions(+), 13 deletions(-) diff --git a/kernel/dma/swiotlb.c b/kernel/dma/swiotlb.c index 86fe172b5958..d7a8cb93ef2d 100644 --- a/kernel/dma/swiotlb.c +++ b/kernel/dma/swiotlb.c @@ -69,11 +69,14 @@ * @alloc_size: Size of the allocated buffer. * @list: The free list describing the number of free entries available * from each index. + * @pad_slots: Number of preceding padding slots. Valid only in the first + * allocated non-padding slot. */ struct io_tlb_slot { phys_addr_t orig_addr; size_t alloc_size; - unsigned int list; + unsigned short list; + unsigned short pad_slots; }; static bool swiotlb_force_bounce; @@ -287,6 +290,7 @@ static void swiotlb_init_io_tlb_pool(struct io_tlb_pool *mem, phys_addr_t start, mem->nslabs - i); mem->slots[i].orig_addr = INVALID_PHYS_ADDR; mem->slots[i].alloc_size = 0; + mem->slots[i].pad_slots = 0; } memset(vaddr, 0, bytes); @@ -821,12 +825,30 @@ void swiotlb_dev_init(struct device *dev) #endif } -/* - * Return the offset into a iotlb slot required to keep the device happy. +/** + * swiotlb_align_offset() - Get required offset into an IO TLB allocation. + * @dev: Owning device. + * @align_mask: Allocation alignment mask. + * @addr: DMA address. + * + * Return the minimum offset from the start of an IO TLB allocation which is + * required for a given buffer address and allocation alignment to keep the + * device happy. + * + * First, the address bits covered by min_align_mask must be identical in the + * original address and the bounce buffer address. High bits are preserved by + * choosing a suitable IO TLB slot, but bits below IO_TLB_SHIFT require extra + * padding bytes before the bounce buffer. + * + * Second, @align_mask specifies which bits of the first allocated slot must + * be zero. This may require allocating additional padding slots, and then the + * offset (in bytes) from the first such padding slot is returned. */ -static unsigned int swiotlb_align_offset(struct device *dev, u64 addr) +static unsigned int swiotlb_align_offset(struct device *dev, + unsigned int align_mask, u64 addr) { - return addr & dma_get_min_align_mask(dev) & (IO_TLB_SIZE - 1); + return addr & dma_get_min_align_mask(dev) & + (align_mask | (IO_TLB_SIZE - 1)); } /* @@ -847,7 +869,7 @@ static void swiotlb_bounce(struct device *dev, phys_addr_t tlb_addr, size_t size return; tlb_offset = tlb_addr & (IO_TLB_SIZE - 1); - orig_addr_offset = swiotlb_align_offset(dev, orig_addr); + orig_addr_offset = swiotlb_align_offset(dev, 0, orig_addr); if (tlb_offset < orig_addr_offset) { dev_WARN_ONCE(dev, 1, "Access before mapping start detected. orig offset %u, requested offset %u.\n", @@ -1005,7 +1027,7 @@ static int swiotlb_search_pool_area(struct device *dev, struct io_tlb_pool *pool unsigned long max_slots = get_max_slots(boundary_mask); unsigned int iotlb_align_mask = dma_get_min_align_mask(dev); unsigned int nslots = nr_slots(alloc_size), stride; - unsigned int offset = swiotlb_align_offset(dev, orig_addr); + unsigned int offset = swiotlb_align_offset(dev, 0, orig_addr); unsigned int index, slots_checked, count = 0, i; unsigned long flags; unsigned int slot_base; @@ -1328,11 +1350,12 @@ phys_addr_t swiotlb_tbl_map_single(struct device *dev, phys_addr_t orig_addr, unsigned long attrs) { struct io_tlb_mem *mem = dev->dma_io_tlb_mem; - unsigned int offset = swiotlb_align_offset(dev, orig_addr); + unsigned int offset; struct io_tlb_pool *pool; unsigned int i; int index; phys_addr_t tlb_addr; + unsigned short pad_slots; if (!mem || !mem->nslabs) { dev_warn_ratelimited(dev, @@ -1349,6 +1372,7 @@ phys_addr_t swiotlb_tbl_map_single(struct device *dev, phys_addr_t orig_addr, return (phys_addr_t)DMA_MAPPING_ERROR; } + offset = swiotlb_align_offset(dev, alloc_align_mask, orig_addr); index = swiotlb_find_slots(dev, orig_addr, alloc_size + offset, alloc_align_mask, &pool); if (index == -1) { @@ -1364,6 +1388,10 @@ phys_addr_t swiotlb_tbl_map_single(struct device *dev, phys_addr_t orig_addr, * This is needed when we sync the memory. Then we sync the buffer if * needed. */ + pad_slots = offset >> IO_TLB_SHIFT; + offset &= (IO_TLB_SIZE - 1); + index += pad_slots; + pool->slots[index].pad_slots = pad_slots; for (i = 0; i < nr_slots(alloc_size + offset); i++) pool->slots[index + i].orig_addr = slot_addr(orig_addr, i); tlb_addr = slot_addr(pool->start, index) + offset; @@ -1384,13 +1412,17 @@ static void swiotlb_release_slots(struct device *dev, phys_addr_t tlb_addr) { struct io_tlb_pool *mem = swiotlb_find_pool(dev, tlb_addr); unsigned long flags; - unsigned int offset = swiotlb_align_offset(dev, tlb_addr); - int index = (tlb_addr - offset - mem->start) >> IO_TLB_SHIFT; - int nslots = nr_slots(mem->slots[index].alloc_size + offset); - int aindex = index / mem->area_nslabs; - struct io_tlb_area *area = &mem->areas[aindex]; + unsigned int offset = swiotlb_align_offset(dev, 0, tlb_addr); + int index, nslots, aindex; + struct io_tlb_area *area; int count, i; + index = (tlb_addr - offset - mem->start) >> IO_TLB_SHIFT; + index -= mem->slots[index].pad_slots; + nslots = nr_slots(mem->slots[index].alloc_size + offset); + aindex = index / mem->area_nslabs; + area = &mem->areas[aindex]; + /* * Return the buffer to the free list by setting the corresponding * entries to indicate the number of contiguous entries available. @@ -1413,6 +1445,7 @@ static void swiotlb_release_slots(struct device *dev, phys_addr_t tlb_addr) mem->slots[i].list = ++count; mem->slots[i].orig_addr = INVALID_PHYS_ADDR; mem->slots[i].alloc_size = 0; + mem->slots[i].pad_slots = 0; } /* -- cgit v1.2.3 From e8068f2d756d57a5206fa3180ade365a8c12ed85 Mon Sep 17 00:00:00 2001 From: Michael Kelley Date: Tue, 26 Mar 2024 20:45:48 -0700 Subject: swiotlb: fix swiotlb_bounce() to do partial sync's correctly In current code, swiotlb_bounce() may do partial sync's correctly in some circumstances, but may incorrectly fail in other circumstances. The failure cases require both of these to be true: 1) swiotlb_align_offset() returns a non-zero "offset" value 2) the tlb_addr of the partial sync area points into the first "offset" bytes of the _second_ or subsequent swiotlb slot allocated for the mapping Code added in commit 868c9ddc182b ("swiotlb: add overflow checks to swiotlb_bounce") attempts to WARN on the invalid case where tlb_addr points into the first "offset" bytes of the _first_ allocated slot. But there's no way for swiotlb_bounce() to distinguish the first slot from the second and subsequent slots, so the WARN can be triggered incorrectly when #2 above is true. Related, current code calculates an adjustment to the orig_addr stored in the swiotlb slot. The adjustment compensates for the difference in the tlb_addr used for the partial sync vs. the tlb_addr for the full mapping. The adjustment is stored in the local variable tlb_offset. But when #1 and #2 above are true, it's valid for this adjustment to be negative. In such case the arithmetic to adjust orig_addr produces the wrong result due to tlb_offset being declared as unsigned. Fix these problems by removing the over-constraining validations added in 868c9ddc182b. Change the declaration of tlb_offset to be signed instead of unsigned so the adjustment arithmetic works correctly. Tested with a test-only hack to how swiotlb_tbl_map_single() calls swiotlb_bounce(). Instead of calling swiotlb_bounce() just once for the entire mapped area, do a loop with each iteration doing only a 128 byte partial sync until the entire mapped area is sync'ed. Then with swiotlb=force on the kernel boot line, run a variety of raw disk writes followed by read and verification of all bytes of the written data. The storage device has DMA min_align_mask set, and the writes are done with a variety of original buffer memory address alignments and overall buffer sizes. For many of the combinations, current code triggers the WARN statements, or the data verification fails. With the fixes, no WARNs occur and all verifications pass. Fixes: 5f89468e2f06 ("swiotlb: manipulate orig_addr when tlb_addr has offset") Fixes: 868c9ddc182b ("swiotlb: add overflow checks to swiotlb_bounce") Signed-off-by: Michael Kelley Dominique Martinet Signed-off-by: Christoph Hellwig --- kernel/dma/swiotlb.c | 30 +++++++++++++----------------- 1 file changed, 13 insertions(+), 17 deletions(-) diff --git a/kernel/dma/swiotlb.c b/kernel/dma/swiotlb.c index d7a8cb93ef2d..d57c8837c813 100644 --- a/kernel/dma/swiotlb.c +++ b/kernel/dma/swiotlb.c @@ -863,27 +863,23 @@ static void swiotlb_bounce(struct device *dev, phys_addr_t tlb_addr, size_t size size_t alloc_size = mem->slots[index].alloc_size; unsigned long pfn = PFN_DOWN(orig_addr); unsigned char *vaddr = mem->vaddr + tlb_addr - mem->start; - unsigned int tlb_offset, orig_addr_offset; + int tlb_offset; if (orig_addr == INVALID_PHYS_ADDR) return; - tlb_offset = tlb_addr & (IO_TLB_SIZE - 1); - orig_addr_offset = swiotlb_align_offset(dev, 0, orig_addr); - if (tlb_offset < orig_addr_offset) { - dev_WARN_ONCE(dev, 1, - "Access before mapping start detected. orig offset %u, requested offset %u.\n", - orig_addr_offset, tlb_offset); - return; - } - - tlb_offset -= orig_addr_offset; - if (tlb_offset > alloc_size) { - dev_WARN_ONCE(dev, 1, - "Buffer overflow detected. Allocation size: %zu. Mapping size: %zu+%u.\n", - alloc_size, size, tlb_offset); - return; - } + /* + * It's valid for tlb_offset to be negative. This can happen when the + * "offset" returned by swiotlb_align_offset() is non-zero, and the + * tlb_addr is pointing within the first "offset" bytes of the second + * or subsequent slots of the allocated swiotlb area. While it's not + * valid for tlb_addr to be pointing within the first "offset" bytes + * of the first slot, there's no way to check for such an error since + * this function can't distinguish the first slot from the second and + * subsequent slots. + */ + tlb_offset = (tlb_addr & (IO_TLB_SIZE - 1)) - + swiotlb_align_offset(dev, 0, orig_addr); orig_addr += tlb_offset; alloc_size -= tlb_offset; -- cgit v1.2.3 From a1255ccab8ecee89905ddb12161139b0d878a7f2 Mon Sep 17 00:00:00 2001 From: Dexuan Cui Date: Fri, 29 Mar 2024 12:28:09 -0700 Subject: swiotlb: do not set total_used to 0 in swiotlb_create_debugfs_files() Sometimes the readout of /sys/kernel/debug/swiotlb/io_tlb_used and io_tlb_used_hiwater can be a huge number (e.g. 18446744073709551615), which is actually a negative number if we use "%ld" to print the number. When swiotlb_create_default_debugfs() is running from late_initcall, mem->total_used may already be non-zero, because the storage driver may have already started to perform I/O operations: if the storage driver is built-in, its probe() callback is called before late_initcall. swiotlb_create_debugfs_files() should not blindly set mem->total_used and mem->used_hiwater to 0; actually it doesn't have to initialize the fields at all, because the fields, as part of the global struct io_tlb_default_mem, have been implicitly initialized to zero. Also don't explicitly set mem->transient_nslabs to 0. Fixes: 8b0977ecc8b3 ("swiotlb: track and report io_tlb_used high water marks in debugfs") Fixes: 02e765697038 ("swiotlb: add debugfs to track swiotlb transient pool usage") Signed-off-by: Dexuan Cui Reviewed-by: Michael Kelley Reviewed-by: ZhangPeng Reviewed-by: Petr Tesarik Signed-off-by: Christoph Hellwig --- kernel/dma/swiotlb.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/kernel/dma/swiotlb.c b/kernel/dma/swiotlb.c index d57c8837c813..a5e0dfc44d24 100644 --- a/kernel/dma/swiotlb.c +++ b/kernel/dma/swiotlb.c @@ -1676,9 +1676,6 @@ DEFINE_DEBUGFS_ATTRIBUTE(fops_io_tlb_hiwater, io_tlb_hiwater_get, static void swiotlb_create_debugfs_files(struct io_tlb_mem *mem, const char *dirname) { - atomic_long_set(&mem->total_used, 0); - atomic_long_set(&mem->used_hiwater, 0); - mem->debugfs = debugfs_create_dir(dirname, io_tlb_default_mem.debugfs); if (!mem->nslabs) return; @@ -1689,7 +1686,6 @@ static void swiotlb_create_debugfs_files(struct io_tlb_mem *mem, debugfs_create_file("io_tlb_used_hiwater", 0600, mem->debugfs, mem, &fops_io_tlb_hiwater); #ifdef CONFIG_SWIOTLB_DYNAMIC - atomic_long_set(&mem->transient_nslabs, 0); debugfs_create_file("io_tlb_transient_nslabs", 0400, mem->debugfs, mem, &fops_io_tlb_transient_used); #endif -- cgit v1.2.3 From f690cdcc01a5b549715fefe22a98962e7672516b Mon Sep 17 00:00:00 2001 From: Yong Zhi Date: Tue, 2 Apr 2024 09:59:56 -0500 Subject: ASoC: SOF: ipc4-loader: save FW version info to debugfs To check loaded FW version: $ hexdump -C /sys/kernel/debug/sof/fw_version 00000000 02 00 07 00 63 00 01 00 00 00 00 00 00 00 00 00 |....c...........| Reviewed-by: Ranjani Sridharan Reviewed-by: Bard Liao Signed-off-by: Yong Zhi Signed-off-by: Pierre-Louis Bossart Link: https://msgid.link/r/20240402145959.172619-2-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/ipc4-loader.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/sound/soc/sof/ipc4-loader.c b/sound/soc/sof/ipc4-loader.c index c79479afa8d0..641c4f24cca9 100644 --- a/sound/soc/sof/ipc4-loader.c +++ b/sound/soc/sof/ipc4-loader.c @@ -80,6 +80,14 @@ static ssize_t sof_ipc4_fw_parse_ext_man(struct snd_sof_dev *sdev, dev_dbg(sdev->dev, "Header length: %u, module count: %u\n", fw_header->len, fw_header->num_module_entries); + /* copy the fw_version of basefw into debugfs at first boot */ + if (fw == sdev->basefw.fw) { + sdev->fw_version.major = fw_header->major_version; + sdev->fw_version.minor = fw_header->minor_version; + sdev->fw_version.micro = fw_header->hotfix_version; + sdev->fw_version.build = fw_header->build_version; + } + fw_lib->modules = devm_kmalloc_array(sdev->dev, fw_header->num_module_entries, sizeof(*fw_module), GFP_KERNEL); if (!fw_lib->modules) -- cgit v1.2.3 From dbb6ca68b55ddf23d0b6de782c7641624a285fc2 Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Tue, 2 Apr 2024 09:59:57 -0500 Subject: ASoC: SOF: amd: acp-loader: abort firmware download on write error cppcheck reports this issue: sound/soc/sof/amd/acp-loader.c:299:6: style: Variable 'ret' is reassigned a value before the old one has been used. [redundantAssignment] ret = request_firmware(&adata->fw_dbin, fw_filename, sdev->dev); ^ sound/soc/sof/amd/acp-loader.c:289:6: note: ret is assigned ret = snd_sof_dsp_block_write(sdev, SOF_FW_BLK_TYPE_IRAM, 0, ^ sound/soc/sof/amd/acp-loader.c:299:6: note: ret is overwritten ret = request_firmware(&adata->fw_dbin, fw_filename, sdev->dev); ^ This behavior is probably unintentional, there's no reason to return an error for the DRAM but not the IRAM. Signed-off-by: Pierre-Louis Bossart Reviewed-by: Bard Liao Link: https://msgid.link/r/20240402145959.172619-3-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/amd/acp-loader.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sound/soc/sof/amd/acp-loader.c b/sound/soc/sof/amd/acp-loader.c index aad904839b81..2d5e58846499 100644 --- a/sound/soc/sof/amd/acp-loader.c +++ b/sound/soc/sof/amd/acp-loader.c @@ -289,6 +289,8 @@ int acp_sof_load_signed_firmware(struct snd_sof_dev *sdev) ret = snd_sof_dsp_block_write(sdev, SOF_FW_BLK_TYPE_IRAM, 0, (void *)sdev->basefw.fw->data, sdev->basefw.fw->size); + if (ret < 0) + return ret; fw_filename = kasprintf(GFP_KERNEL, "%s/%s", plat_data->fw_filename_prefix, -- cgit v1.2.3 From 458e3870507f7ebd26a2f5c7e925d5b31a873114 Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Tue, 2 Apr 2024 09:59:58 -0500 Subject: ASoC: SOF: ipc4-priv: align prototype and function declaration Somehow instance_id and id were mixed. Align on instance_id for consistency. Signed-off-by: Pierre-Louis Bossart Reviewed-by: Bard Liao Link: https://msgid.link/r/20240402145959.172619-4-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/ipc4-priv.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/sof/ipc4-priv.h b/sound/soc/sof/ipc4-priv.h index f3b908b093f9..85e8cf91aab9 100644 --- a/sound/soc/sof/ipc4-priv.h +++ b/sound/soc/sof/ipc4-priv.h @@ -112,7 +112,7 @@ extern const struct sof_ipc_tplg_control_ops tplg_ipc4_control_ops; extern const struct sof_ipc_pcm_ops ipc4_pcm_ops; extern const struct sof_ipc_fw_tracing_ops ipc4_mtrace_ops; -int sof_ipc4_set_pipeline_state(struct snd_sof_dev *sdev, u32 id, u32 state); +int sof_ipc4_set_pipeline_state(struct snd_sof_dev *sdev, u32 instance_id, u32 state); int sof_ipc4_mtrace_update_pos(struct snd_sof_dev *sdev, int core); int sof_ipc4_query_fw_configuration(struct snd_sof_dev *sdev); -- cgit v1.2.3 From c143cfe4f87070f11d7550b38f72625b51bf229f Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Tue, 2 Apr 2024 09:59:59 -0500 Subject: ASoC: SOF: ipc4-topology: remove shadowed variable Cppcheck reports this: sound/soc/sof/ipc4-topology.c:569:23: style: Local variable 'sdev' shadows outer variable [shadowVariable] struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp); ^ sound/soc/sof/ipc4-topology.c:512:22: note: Shadowed declaration struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp); ^ sound/soc/sof/ipc4-topology.c:569:23: note: Shadow variable struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp); ^ Remove shadowed variable. Signed-off-by: Pierre-Louis Bossart Reviewed-by: Bard Liao Link: https://msgid.link/r/20240402145959.172619-5-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/ipc4-topology.c | 1 - 1 file changed, 1 deletion(-) diff --git a/sound/soc/sof/ipc4-topology.c b/sound/soc/sof/ipc4-topology.c index da4a83afb87a..651bff2122a3 100644 --- a/sound/soc/sof/ipc4-topology.c +++ b/sound/soc/sof/ipc4-topology.c @@ -566,7 +566,6 @@ static int sof_ipc4_widget_setup_comp_dai(struct snd_sof_widget *swidget) switch (ipc4_copier->dai_type) { case SOF_DAI_INTEL_ALH: { - struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp); struct sof_ipc4_alh_configuration_blob *blob; struct snd_soc_dapm_path *p; struct snd_sof_widget *w; -- cgit v1.2.3 From 831045513c8a2ef14c3cf39b33d1ccedf588c4a8 Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Tue, 2 Apr 2024 10:18:12 -0500 Subject: ASoC: SOF: Intel: hda-dai: fix channel map configuration for aggregated dailink The existing code derives the channel map used to program the HDaudio link DMA from the hw_params, but that is not quite right in the case of aggregation. The code in soc-pcm.c splits the hw_params depending on the codec_ch_map, and we need to reconstruct the channel-map to insert the data in the right places. This issue is seen only on amplifier feedback capture where the data from the second amplifier was replaced by that of the first amplifier. Note that the loop iterator of the macro for_each_rtd_cpu_dais() is reused in a following loop. This is different to all existing usages of that macro, hence the use of a boolean flag to avoid an access to an uninitialized variable. Fixes: 2960ee5c4814 ("ASoC: SOF: Intel: hda-dai: add helpers for SoundWire callbacks") Reviewed-by: Bard Liao Reviewed-by: Rander Wang Signed-off-by: Pierre-Louis Bossart Link: https://msgid.link/r/20240402151828.175002-2-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/intel/hda-dai.c | 31 +++++++++++++++++++++++++++++-- 1 file changed, 29 insertions(+), 2 deletions(-) diff --git a/sound/soc/sof/intel/hda-dai.c b/sound/soc/sof/intel/hda-dai.c index c1682bcdb5a6..6a39ca632f55 100644 --- a/sound/soc/sof/intel/hda-dai.c +++ b/sound/soc/sof/intel/hda-dai.c @@ -439,10 +439,17 @@ int sdw_hda_dai_hw_params(struct snd_pcm_substream *substream, int link_id) { struct snd_soc_dapm_widget *w = snd_soc_dai_get_widget(cpu_dai, substream->stream); + struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream); const struct hda_dai_widget_dma_ops *ops; + struct snd_soc_dai_link_ch_map *ch_maps; struct hdac_ext_stream *hext_stream; + struct snd_soc_dai *dai; struct snd_sof_dev *sdev; + bool cpu_dai_found = false; + int cpu_dai_id; + int ch_mask; int ret; + int j; ret = non_hda_dai_hw_params(substream, params, cpu_dai); if (ret < 0) { @@ -457,9 +464,29 @@ int sdw_hda_dai_hw_params(struct snd_pcm_substream *substream, if (!hext_stream) return -ENODEV; - /* in the case of SoundWire we need to program the PCMSyCM registers */ + /* + * in the case of SoundWire we need to program the PCMSyCM registers. In case + * of aggregated devices, we need to define the channel mask for each sublink + * by reconstructing the split done in soc-pcm.c + */ + for_each_rtd_cpu_dais(rtd, cpu_dai_id, dai) { + if (dai == cpu_dai) { + cpu_dai_found = true; + break; + } + } + + if (!cpu_dai_found) + return -ENODEV; + + ch_mask = 0; + for_each_link_ch_maps(rtd->dai_link, j, ch_maps) { + if (ch_maps->cpu == cpu_dai_id) + ch_mask |= ch_maps->ch_mask; + } + ret = hdac_bus_eml_sdw_map_stream_ch(sof_to_bus(sdev), link_id, cpu_dai->id, - GENMASK(params_channels(params) - 1, 0), + ch_mask, hdac_stream(hext_stream)->stream_tag, substream->stream); if (ret < 0) { -- cgit v1.2.3 From 24b1f93df400e1ab1731e7bcb320e693a6a73792 Mon Sep 17 00:00:00 2001 From: Bard Liao Date: Tue, 2 Apr 2024 10:18:13 -0500 Subject: Revert "ASoC: SOF: Intel: hda-dai-ops: reset device count for SoundWire DAIs" This reverts commit 699e146d9ebf42ee2a5d4e4e28f7a49c4aef0105. Don't reset device_count as we will use the multi-gateway firmware configuration. Signed-off-by: Bard Liao Signed-off-by: Pierre-Louis Bossart Link: https://msgid.link/r/20240402151828.175002-3-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/intel/hda-dai-ops.c | 24 +----------------------- 1 file changed, 1 insertion(+), 23 deletions(-) diff --git a/sound/soc/sof/intel/hda-dai-ops.c b/sound/soc/sof/intel/hda-dai-ops.c index c50ca9e72d37..d3e168ad1180 100644 --- a/sound/soc/sof/intel/hda-dai-ops.c +++ b/sound/soc/sof/intel/hda-dai-ops.c @@ -435,28 +435,6 @@ out: return ret; } -static struct hdac_ext_stream *sdw_hda_ipc4_get_hext_stream(struct snd_sof_dev *sdev, - struct snd_soc_dai *cpu_dai, - struct snd_pcm_substream *substream) -{ - struct snd_soc_dapm_widget *w = snd_soc_dai_get_widget(cpu_dai, substream->stream); - struct snd_sof_widget *swidget = w->dobj.private; - struct snd_sof_dai *dai = swidget->private; - struct sof_ipc4_copier *ipc4_copier = dai->private; - struct sof_ipc4_alh_configuration_blob *blob; - - blob = (struct sof_ipc4_alh_configuration_blob *)ipc4_copier->copier_config; - - /* - * Starting with ACE_2_0, re-setting the device_count is mandatory to avoid using - * the multi-gateway firmware configuration. The DMA hardware can take care of - * multiple links without needing any firmware assistance - */ - blob->alh_cfg.device_count = 1; - - return hda_ipc4_get_hext_stream(sdev, cpu_dai, substream); -} - static const struct hda_dai_widget_dma_ops hda_ipc4_dma_ops = { .get_hext_stream = hda_ipc4_get_hext_stream, .assign_hext_stream = hda_assign_hext_stream, @@ -498,7 +476,7 @@ static const struct hda_dai_widget_dma_ops dmic_ipc4_dma_ops = { }; static const struct hda_dai_widget_dma_ops sdw_ipc4_dma_ops = { - .get_hext_stream = sdw_hda_ipc4_get_hext_stream, + .get_hext_stream = hda_ipc4_get_hext_stream, .assign_hext_stream = hda_assign_hext_stream, .release_hext_stream = hda_release_hext_stream, .setup_hext_stream = hda_setup_hext_stream, -- cgit v1.2.3 From 1d0fb3d0c30749779cdd88be98761b17ebfe5590 Mon Sep 17 00:00:00 2001 From: Bard Liao Date: Tue, 2 Apr 2024 10:18:14 -0500 Subject: Revert "ASoC: SOF: Intel: hda-dai-ops: only allocate/release streams for first CPU DAI" This reverts commit f8ba62ac863c33fc0d8ac3f1270985c2b77f4377. The SoundWire aggregated solution was to use one DMA on multiple links. But, the solution changed to use one DMA for each link. It means that we should assign HDaudio stream_tag for each cpu_dai. Signed-off-by: Bard Liao Signed-off-by: Pierre-Louis Bossart Link: https://msgid.link/r/20240402151828.175002-4-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/intel/hda-dai-ops.c | 17 ++--------------- 1 file changed, 2 insertions(+), 15 deletions(-) diff --git a/sound/soc/sof/intel/hda-dai-ops.c b/sound/soc/sof/intel/hda-dai-ops.c index d3e168ad1180..1afdb06499a3 100644 --- a/sound/soc/sof/intel/hda-dai-ops.c +++ b/sound/soc/sof/intel/hda-dai-ops.c @@ -145,17 +145,9 @@ static struct hdac_ext_stream *hda_assign_hext_stream(struct snd_sof_dev *sdev, struct snd_soc_dai *cpu_dai, struct snd_pcm_substream *substream) { - struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream); - struct snd_soc_dai *dai; struct hdac_ext_stream *hext_stream; - /* only allocate a stream_tag for the first DAI in the dailink */ - dai = snd_soc_rtd_to_cpu(rtd, 0); - if (dai == cpu_dai) - hext_stream = hda_link_stream_assign(sof_to_bus(sdev), substream); - else - hext_stream = snd_soc_dai_get_dma_data(dai, substream); - + hext_stream = hda_link_stream_assign(sof_to_bus(sdev), substream); if (!hext_stream) return NULL; @@ -168,14 +160,9 @@ static void hda_release_hext_stream(struct snd_sof_dev *sdev, struct snd_soc_dai struct snd_pcm_substream *substream) { struct hdac_ext_stream *hext_stream = hda_get_hext_stream(sdev, cpu_dai, substream); - struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream); - struct snd_soc_dai *dai; - /* only release a stream_tag for the first DAI in the dailink */ - dai = snd_soc_rtd_to_cpu(rtd, 0); - if (dai == cpu_dai) - snd_hdac_ext_stream_release(hext_stream, HDAC_EXT_STREAM_TYPE_LINK); snd_soc_dai_set_dma_data(cpu_dai, substream, NULL); + snd_hdac_ext_stream_release(hext_stream, HDAC_EXT_STREAM_TYPE_LINK); } static void hda_setup_hext_stream(struct snd_sof_dev *sdev, struct hdac_ext_stream *hext_stream, -- cgit v1.2.3 From e9c6b118de1afc1d32a4eb3bc9f3d114d4fe0f1a Mon Sep 17 00:00:00 2001 From: Bard Liao Date: Tue, 2 Apr 2024 10:18:15 -0500 Subject: ASoC: SOF: make dma_config_tlv be an array Each stream needs a dma_config_tlv. We will handle multi dma_config_tlv in the follow up commits. Signed-off-by: Bard Liao Signed-off-by: Pierre-Louis Bossart Link: https://msgid.link/r/20240402151828.175002-5-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/intel/hda-dai.c | 2 +- sound/soc/sof/ipc4-topology.c | 25 ++++++++++++------------- sound/soc/sof/ipc4-topology.h | 2 +- 3 files changed, 14 insertions(+), 15 deletions(-) diff --git a/sound/soc/sof/intel/hda-dai.c b/sound/soc/sof/intel/hda-dai.c index 6a39ca632f55..01c544b7e046 100644 --- a/sound/soc/sof/intel/hda-dai.c +++ b/sound/soc/sof/intel/hda-dai.c @@ -392,7 +392,7 @@ static int non_hda_dai_hw_params(struct snd_pcm_substream *substream, /* configure TLV */ ipc4_copier = widget_to_copier(w); - dma_config_tlv = &ipc4_copier->dma_config_tlv; + dma_config_tlv = &ipc4_copier->dma_config_tlv[0]; dma_config_tlv->type = SOF_IPC4_GTW_DMA_CONFIG_ID; /* dma_config_priv_size is zero */ dma_config_tlv->length = sizeof(dma_config_tlv->dma_config); diff --git a/sound/soc/sof/ipc4-topology.c b/sound/soc/sof/ipc4-topology.c index da4a83afb87a..1e9276b9b35c 100644 --- a/sound/soc/sof/ipc4-topology.c +++ b/sound/soc/sof/ipc4-topology.c @@ -1454,6 +1454,7 @@ sof_ipc4_prepare_copier_module(struct snd_sof_widget *swidget, u32 deep_buffer_dma_ms = 0; int output_fmt_index; bool single_output_format; + int i; dev_dbg(sdev->dev, "copier %s, type %d", swidget->widget->name, swidget->id); @@ -1679,7 +1680,6 @@ sof_ipc4_prepare_copier_module(struct snd_sof_widget *swidget, u32 ch_map; u32 step; u32 mask; - int i; blob = (struct sof_ipc4_alh_configuration_blob *)ipc4_copier->copier_config; @@ -1789,19 +1789,18 @@ sof_ipc4_prepare_copier_module(struct snd_sof_widget *swidget, gtw_cfg_config_length = copier_data->gtw_cfg.config_length * 4; ipc_size = sizeof(*copier_data) + gtw_cfg_config_length; - if (ipc4_copier->dma_config_tlv.type == SOF_IPC4_GTW_DMA_CONFIG_ID && - ipc4_copier->dma_config_tlv.length) { - dma_config_tlv_size = sizeof(ipc4_copier->dma_config_tlv) + - ipc4_copier->dma_config_tlv.dma_config.dma_priv_config_size; - - /* paranoia check on TLV size/length */ - if (dma_config_tlv_size != ipc4_copier->dma_config_tlv.length + - sizeof(uint32_t) * 2) { - dev_err(sdev->dev, "Invalid configuration, TLV size %d length %d\n", - dma_config_tlv_size, ipc4_copier->dma_config_tlv.length); - return -EINVAL; - } + dma_config_tlv_size = 0; + for (i = 0; i < SOF_IPC4_DMA_DEVICE_MAX_COUNT; i++) { + if (ipc4_copier->dma_config_tlv[i].type != SOF_IPC4_GTW_DMA_CONFIG_ID) + continue; + dma_config_tlv_size += ipc4_copier->dma_config_tlv[i].length; + dma_config_tlv_size += + ipc4_copier->dma_config_tlv[i].dma_config.dma_priv_config_size; + dma_config_tlv_size += (sizeof(ipc4_copier->dma_config_tlv[i]) - + sizeof(ipc4_copier->dma_config_tlv[i].dma_config)); + } + if (dma_config_tlv_size) { ipc_size += dma_config_tlv_size; /* we also need to increase the size at the gtw level */ diff --git a/sound/soc/sof/ipc4-topology.h b/sound/soc/sof/ipc4-topology.h index dce174a190dd..aa5122c3721d 100644 --- a/sound/soc/sof/ipc4-topology.h +++ b/sound/soc/sof/ipc4-topology.h @@ -313,7 +313,7 @@ struct sof_ipc4_copier { struct sof_ipc4_gtw_attributes *gtw_attr; u32 dai_type; int dai_index; - struct sof_ipc4_dma_config_tlv dma_config_tlv; + struct sof_ipc4_dma_config_tlv dma_config_tlv[SOF_IPC4_DMA_DEVICE_MAX_COUNT]; }; /** -- cgit v1.2.3 From 8fa10a243600ca8bd92fdc871100deb308fca5f1 Mon Sep 17 00:00:00 2001 From: Bard Liao Date: Tue, 2 Apr 2024 10:18:16 -0500 Subject: ASoC: SOF: Intel: hda-dai: set lowest N bits in ch_mask We always use the lowest N channels of stream. So, set ch_mask to GENMASK(params_channels(params) - 1, 0). Signed-off-by: Bard Liao Signed-off-by: Pierre-Louis Bossart Link: https://msgid.link/r/20240402151828.175002-6-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/intel/hda-dai.c | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/sound/soc/sof/intel/hda-dai.c b/sound/soc/sof/intel/hda-dai.c index 01c544b7e046..810d2997794f 100644 --- a/sound/soc/sof/intel/hda-dai.c +++ b/sound/soc/sof/intel/hda-dai.c @@ -441,7 +441,6 @@ int sdw_hda_dai_hw_params(struct snd_pcm_substream *substream, struct snd_soc_dapm_widget *w = snd_soc_dai_get_widget(cpu_dai, substream->stream); struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream); const struct hda_dai_widget_dma_ops *ops; - struct snd_soc_dai_link_ch_map *ch_maps; struct hdac_ext_stream *hext_stream; struct snd_soc_dai *dai; struct snd_sof_dev *sdev; @@ -449,7 +448,6 @@ int sdw_hda_dai_hw_params(struct snd_pcm_substream *substream, int cpu_dai_id; int ch_mask; int ret; - int j; ret = non_hda_dai_hw_params(substream, params, cpu_dai); if (ret < 0) { @@ -479,11 +477,7 @@ int sdw_hda_dai_hw_params(struct snd_pcm_substream *substream, if (!cpu_dai_found) return -ENODEV; - ch_mask = 0; - for_each_link_ch_maps(rtd->dai_link, j, ch_maps) { - if (ch_maps->cpu == cpu_dai_id) - ch_mask |= ch_maps->ch_mask; - } + ch_mask = GENMASK(params_channels(params) - 1, 0); ret = hdac_bus_eml_sdw_map_stream_ch(sof_to_bus(sdev), link_id, cpu_dai->id, ch_mask, -- cgit v1.2.3 From 17386cb1b48b0d85f69b21ae13d5408d67180e30 Mon Sep 17 00:00:00 2001 From: Bard Liao Date: Tue, 2 Apr 2024 10:18:17 -0500 Subject: ASoC: SOF: Intel: hda-dai: set dma_stream_channel_map device sof_ipc4_dma_config_tlv{} is required for ACE2.x. The patch follow the convention to set the dma_stream_channel_map.mapping device as "link_id << 8 | pdi_id". And the mapping in sof_ipc4_alh_configuration_blob{} should be the same as dma_stream_channel_map.mapping in sof_ipc4_dma_config{}. The purposes of device id is to map DMA tlv. Signed-off-by: Bard Liao Signed-off-by: Pierre-Louis Bossart Link: https://msgid.link/r/20240402151828.175002-7-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/intel/hda-dai.c | 36 ++++++++++++++++++++++++++++++++++-- sound/soc/sof/ipc4-topology.c | 13 +++++++++++++ 2 files changed, 47 insertions(+), 2 deletions(-) diff --git a/sound/soc/sof/intel/hda-dai.c b/sound/soc/sof/intel/hda-dai.c index 810d2997794f..de71e1595a78 100644 --- a/sound/soc/sof/intel/hda-dai.c +++ b/sound/soc/sof/intel/hda-dai.c @@ -346,6 +346,7 @@ static int non_hda_dai_hw_params(struct snd_pcm_substream *substream, struct snd_soc_dai *cpu_dai) { struct snd_soc_dapm_widget *w = snd_soc_dai_get_widget(cpu_dai, substream->stream); + struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream); struct sof_ipc4_dma_config_tlv *dma_config_tlv; const struct hda_dai_widget_dma_ops *ops; struct sof_ipc4_dma_config *dma_config; @@ -353,6 +354,8 @@ static int non_hda_dai_hw_params(struct snd_pcm_substream *substream, struct hdac_ext_stream *hext_stream; struct hdac_stream *hstream; struct snd_sof_dev *sdev; + struct snd_soc_dai *dai; + int cpu_dai_id; int stream_id; int ret; @@ -392,7 +395,12 @@ static int non_hda_dai_hw_params(struct snd_pcm_substream *substream, /* configure TLV */ ipc4_copier = widget_to_copier(w); - dma_config_tlv = &ipc4_copier->dma_config_tlv[0]; + for_each_rtd_cpu_dais(rtd, cpu_dai_id, dai) { + if (dai == cpu_dai) + break; + } + + dma_config_tlv = &ipc4_copier->dma_config_tlv[cpu_dai_id]; dma_config_tlv->type = SOF_IPC4_GTW_DMA_CONFIG_ID; /* dma_config_priv_size is zero */ dma_config_tlv->length = sizeof(dma_config_tlv->dma_config); @@ -403,7 +411,11 @@ static int non_hda_dai_hw_params(struct snd_pcm_substream *substream, dma_config->pre_allocated_by_host = 1; dma_config->dma_channel_id = stream_id - 1; dma_config->stream_id = stream_id; - dma_config->dma_stream_channel_map.device_count = 0; /* mapping not used */ + /* + * Currently we use a DMA for each device in ALH blob. The device will + * be copied in sof_ipc4_prepare_copier_module. + */ + dma_config->dma_stream_channel_map.device_count = 1; dma_config->dma_priv_config_size = 0; skip_tlv: @@ -440,7 +452,10 @@ int sdw_hda_dai_hw_params(struct snd_pcm_substream *substream, { struct snd_soc_dapm_widget *w = snd_soc_dai_get_widget(cpu_dai, substream->stream); struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream); + struct sof_ipc4_dma_config_tlv *dma_config_tlv; const struct hda_dai_widget_dma_ops *ops; + struct sof_ipc4_dma_config *dma_config; + struct sof_ipc4_copier *ipc4_copier; struct hdac_ext_stream *hext_stream; struct snd_soc_dai *dai; struct snd_sof_dev *sdev; @@ -448,6 +463,7 @@ int sdw_hda_dai_hw_params(struct snd_pcm_substream *substream, int cpu_dai_id; int ch_mask; int ret; + int i; ret = non_hda_dai_hw_params(substream, params, cpu_dai); if (ret < 0) { @@ -489,6 +505,22 @@ int sdw_hda_dai_hw_params(struct snd_pcm_substream *substream, return ret; } + ipc4_copier = widget_to_copier(w); + dma_config_tlv = &ipc4_copier->dma_config_tlv[cpu_dai_id]; + dma_config = &dma_config_tlv->dma_config; + dma_config->dma_stream_channel_map.mapping[0].device = link_id << 8 | cpu_dai->id; + dma_config->dma_stream_channel_map.mapping[0].channel_mask = ch_mask; + + /* + * copy the dma_config_tlv to all ipc4_copier in the same link. Because only one copier + * will be handled in sof_ipc4_prepare_copier_module. + */ + for_each_rtd_cpu_dais(rtd, i, dai) { + w = snd_soc_dai_get_widget(dai, substream->stream); + ipc4_copier = widget_to_copier(w); + memcpy(&ipc4_copier->dma_config_tlv[cpu_dai_id], dma_config_tlv, + sizeof(*dma_config_tlv)); + } return 0; } diff --git a/sound/soc/sof/ipc4-topology.c b/sound/soc/sof/ipc4-topology.c index 1e9276b9b35c..cca5d43e5fd8 100644 --- a/sound/soc/sof/ipc4-topology.c +++ b/sound/soc/sof/ipc4-topology.c @@ -1672,6 +1672,7 @@ sof_ipc4_prepare_copier_module(struct snd_sof_widget *swidget, */ if (ipc4_copier->dai_type == SOF_DAI_INTEL_ALH) { struct sof_ipc4_alh_configuration_blob *blob; + struct sof_ipc4_dma_config *dma_config; struct sof_ipc4_copier_data *alh_data; struct sof_ipc4_copier *alh_copier; struct snd_sof_widget *w; @@ -1711,6 +1712,18 @@ sof_ipc4_prepare_copier_module(struct snd_sof_widget *swidget, alh_copier = (struct sof_ipc4_copier *)dai->private; alh_data = &alh_copier->data; blob->alh_cfg.mapping[i].device = alh_data->gtw_cfg.node_id; + + /* + * The mapping[i] device in ALH blob should be the same as the + * dma_config_tlv[i] mapping device if a dma_config_tlv is present. + * The device id will be used for DMA tlv mapping purposes. + */ + if (ipc4_copier->dma_config_tlv[i].length) { + dma_config = &ipc4_copier->dma_config_tlv[i].dma_config; + blob->alh_cfg.mapping[i].device = + dma_config->dma_stream_channel_map.mapping[0].device; + } + /* * Set the same channel mask for playback as the audio data is * duplicated for all speakers. For capture, split the channels -- cgit v1.2.3 From 58f32cb7011a8a15b18f35e4c0ee044aa98e365b Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Tue, 2 Apr 2024 10:18:18 -0500 Subject: ASoC: SOF: Intel: hda-dai: add helpers to set dai config We need to be able to set the dai config differently for SoundWire. Reviewed-by: Ranjani Sridharan Reviewed-by: Bard Liao Signed-off-by: Pierre-Louis Bossart Link: https://msgid.link/r/20240402151828.175002-8-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/intel/hda-dai.c | 51 ++++++++++++++++++++++++++++++++----------- 1 file changed, 38 insertions(+), 13 deletions(-) diff --git a/sound/soc/sof/intel/hda-dai.c b/sound/soc/sof/intel/hda-dai.c index de71e1595a78..c48ac931753c 100644 --- a/sound/soc/sof/intel/hda-dai.c +++ b/sound/soc/sof/intel/hda-dai.c @@ -221,15 +221,15 @@ static int __maybe_unused hda_dai_hw_free(struct snd_pcm_substream *substream, return hda_link_dma_cleanup(substream, hext_stream, cpu_dai); } -static int __maybe_unused hda_dai_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *params, - struct snd_soc_dai *dai) +static int __maybe_unused hda_dai_hw_params_data(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params, + struct snd_soc_dai *dai, + struct snd_sof_dai_config_data *data, + unsigned int flags) { struct snd_soc_dapm_widget *w = snd_soc_dai_get_widget(dai, substream->stream); const struct hda_dai_widget_dma_ops *ops = hda_dai_get_ops(substream, dai); struct hdac_ext_stream *hext_stream; - struct snd_sof_dai_config_data data = { 0 }; - unsigned int flags = SOF_DAI_CONFIG_FLAGS_HW_PARAMS; struct snd_sof_dev *sdev = widget_to_sdev(w); int ret; @@ -249,9 +249,19 @@ static int __maybe_unused hda_dai_hw_params(struct snd_pcm_substream *substream, hext_stream = ops->get_hext_stream(sdev, dai, substream); flags |= SOF_DAI_CONFIG_FLAGS_2_STEP_STOP << SOF_DAI_CONFIG_FLAGS_QUIRK_SHIFT; - data.dai_data = hdac_stream(hext_stream)->stream_tag - 1; + data->dai_data = hdac_stream(hext_stream)->stream_tag - 1; + + return hda_dai_config(w, flags, data); +} + +static int __maybe_unused hda_dai_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params, + struct snd_soc_dai *dai) +{ + struct snd_sof_dai_config_data data = { 0 }; + unsigned int flags = SOF_DAI_CONFIG_FLAGS_HW_PARAMS; - return hda_dai_config(w, flags, &data); + return hda_dai_hw_params_data(substream, params, dai, &data, flags); } /* @@ -341,9 +351,11 @@ static struct sof_ipc4_copier *widget_to_copier(struct snd_soc_dapm_widget *w) return ipc4_copier; } -static int non_hda_dai_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *params, - struct snd_soc_dai *cpu_dai) +static int non_hda_dai_hw_params_data(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params, + struct snd_soc_dai *cpu_dai, + struct snd_sof_dai_config_data *data, + unsigned int flags) { struct snd_soc_dapm_widget *w = snd_soc_dai_get_widget(cpu_dai, substream->stream); struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream); @@ -366,9 +378,9 @@ static int non_hda_dai_hw_params(struct snd_pcm_substream *substream, } /* use HDaudio stream handling */ - ret = hda_dai_hw_params(substream, params, cpu_dai); + ret = hda_dai_hw_params_data(substream, params, cpu_dai, data, flags); if (ret < 0) { - dev_err(cpu_dai->dev, "%s: hda_dai_hw_params failed: %d\n", __func__, ret); + dev_err(cpu_dai->dev, "%s: hda_dai_hw_params_data failed: %d\n", __func__, ret); return ret; } @@ -422,6 +434,16 @@ skip_tlv: return 0; } +static int non_hda_dai_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params, + struct snd_soc_dai *cpu_dai) +{ + struct snd_sof_dai_config_data data = { 0 }; + unsigned int flags = SOF_DAI_CONFIG_FLAGS_HW_PARAMS; + + return non_hda_dai_hw_params_data(substream, params, cpu_dai, &data, flags); +} + static int non_hda_dai_prepare(struct snd_pcm_substream *substream, struct snd_soc_dai *cpu_dai) { @@ -453,6 +475,8 @@ int sdw_hda_dai_hw_params(struct snd_pcm_substream *substream, struct snd_soc_dapm_widget *w = snd_soc_dai_get_widget(cpu_dai, substream->stream); struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream); struct sof_ipc4_dma_config_tlv *dma_config_tlv; + struct snd_sof_dai_config_data data = { 0 }; + unsigned int flags = SOF_DAI_CONFIG_FLAGS_HW_PARAMS; const struct hda_dai_widget_dma_ops *ops; struct sof_ipc4_dma_config *dma_config; struct sof_ipc4_copier *ipc4_copier; @@ -465,7 +489,8 @@ int sdw_hda_dai_hw_params(struct snd_pcm_substream *substream, int ret; int i; - ret = non_hda_dai_hw_params(substream, params, cpu_dai); + data.dai_index = (link_id << 8) | cpu_dai->id; + ret = non_hda_dai_hw_params_data(substream, params, cpu_dai, &data, flags); if (ret < 0) { dev_err(cpu_dai->dev, "%s: non_hda_dai_hw_params failed %d\n", __func__, ret); return ret; -- cgit v1.2.3 From 219271481e8965e80ee425cdc2db85230a333a97 Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Tue, 2 Apr 2024 10:18:19 -0500 Subject: ASoC: SOF: Intel: set the DMA TLV device as dai_index We've already defined the value for dai_index, let's use it instead of open-coding the same thing. No functionality change. Reviewed-by: Ranjani Sridharan Reviewed-by: Bard Liao Signed-off-by: Pierre-Louis Bossart Link: https://msgid.link/r/20240402151828.175002-9-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/intel/hda-dai.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/sof/intel/hda-dai.c b/sound/soc/sof/intel/hda-dai.c index c48ac931753c..86efcbe8f0d8 100644 --- a/sound/soc/sof/intel/hda-dai.c +++ b/sound/soc/sof/intel/hda-dai.c @@ -533,7 +533,7 @@ int sdw_hda_dai_hw_params(struct snd_pcm_substream *substream, ipc4_copier = widget_to_copier(w); dma_config_tlv = &ipc4_copier->dma_config_tlv[cpu_dai_id]; dma_config = &dma_config_tlv->dma_config; - dma_config->dma_stream_channel_map.mapping[0].device = link_id << 8 | cpu_dai->id; + dma_config->dma_stream_channel_map.mapping[0].device = data.dai_index; dma_config->dma_stream_channel_map.mapping[0].channel_mask = ch_mask; /* -- cgit v1.2.3 From 8bc3b56cac748f6ef6a4b96c906007a546e7fb5a Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Tue, 2 Apr 2024 10:18:20 -0500 Subject: ASoC: SOF: Intel: hda: extend signature of sdw_hda_dai_hw_params() Add intel_alh_id to set the expected gateway node_id in a follow-up patch. Reviewed-by: Ranjani Sridharan Reviewed-by: Bard Liao Signed-off-by: Pierre-Louis Bossart Link: https://msgid.link/r/20240402151828.175002-10-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/intel/hda-dai.c | 3 ++- sound/soc/sof/intel/hda.c | 3 ++- sound/soc/sof/intel/hda.h | 3 ++- 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/sound/soc/sof/intel/hda-dai.c b/sound/soc/sof/intel/hda-dai.c index 86efcbe8f0d8..5e3229c8fe13 100644 --- a/sound/soc/sof/intel/hda-dai.c +++ b/sound/soc/sof/intel/hda-dai.c @@ -470,7 +470,8 @@ static const struct snd_soc_dai_ops dmic_dai_ops = { int sdw_hda_dai_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params, struct snd_soc_dai *cpu_dai, - int link_id) + int link_id, + int intel_alh_id) { struct snd_soc_dapm_widget *w = snd_soc_dai_get_widget(cpu_dai, substream->stream); struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream); diff --git a/sound/soc/sof/intel/hda.c b/sound/soc/sof/intel/hda.c index e26b8fd682e5..63f1cf3b915f 100644 --- a/sound/soc/sof/intel/hda.c +++ b/sound/soc/sof/intel/hda.c @@ -159,7 +159,8 @@ static int sdw_ace2x_params_stream(struct device *dev, return sdw_hda_dai_hw_params(params_data->substream, params_data->hw_params, params_data->dai, - params_data->link_id); + params_data->link_id, + params_data->alh_stream_id); } static int sdw_ace2x_free_stream(struct device *dev, diff --git a/sound/soc/sof/intel/hda.h b/sound/soc/sof/intel/hda.h index b36eb7c78913..3bf7427dc918 100644 --- a/sound/soc/sof/intel/hda.h +++ b/sound/soc/sof/intel/hda.h @@ -844,7 +844,8 @@ static inline bool hda_common_check_sdw_irq(struct snd_sof_dev *sdev) int sdw_hda_dai_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params, struct snd_soc_dai *cpu_dai, - int link_id); + int link_id, + int intel_alh_id); int sdw_hda_dai_hw_free(struct snd_pcm_substream *substream, struct snd_soc_dai *cpu_dai, -- cgit v1.2.3 From a936456d4bce27edc1a18dab270c657e9c07590c Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Tue, 2 Apr 2024 10:18:21 -0500 Subject: ASoC: SOF: IPC4: extend dai_data with node_id The node_id value needs to be handled specifically for ALH. Reviewed-by: Ranjani Sridharan Reviewed-by: Bard Liao Signed-off-by: Pierre-Louis Bossart Link: https://msgid.link/r/20240402151828.175002-11-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/intel/hda-dai.c | 1 + sound/soc/sof/intel/hda.c | 1 + sound/soc/sof/ipc4-topology.c | 8 ++++++-- sound/soc/sof/sof-audio.h | 1 + 4 files changed, 9 insertions(+), 2 deletions(-) diff --git a/sound/soc/sof/intel/hda-dai.c b/sound/soc/sof/intel/hda-dai.c index 5e3229c8fe13..86c2325e5949 100644 --- a/sound/soc/sof/intel/hda-dai.c +++ b/sound/soc/sof/intel/hda-dai.c @@ -491,6 +491,7 @@ int sdw_hda_dai_hw_params(struct snd_pcm_substream *substream, int i; data.dai_index = (link_id << 8) | cpu_dai->id; + data.dai_node_id = intel_alh_id; ret = non_hda_dai_hw_params_data(substream, params, cpu_dai, &data, flags); if (ret < 0) { dev_err(cpu_dai->dev, "%s: non_hda_dai_hw_params failed %d\n", __func__, ret); diff --git a/sound/soc/sof/intel/hda.c b/sound/soc/sof/intel/hda.c index 63f1cf3b915f..ae1a38f20bdb 100644 --- a/sound/soc/sof/intel/hda.c +++ b/sound/soc/sof/intel/hda.c @@ -145,6 +145,7 @@ static int sdw_params_stream(struct device *dev, data.dai_index = (params_data->link_id << 8) | d->id; data.dai_data = params_data->alh_stream_id; + data.dai_node_id = data.dai_data; return hda_dai_config(w, SOF_DAI_CONFIG_FLAGS_HW_PARAMS, &data); } diff --git a/sound/soc/sof/ipc4-topology.c b/sound/soc/sof/ipc4-topology.c index cca5d43e5fd8..0368ef6d0807 100644 --- a/sound/soc/sof/ipc4-topology.c +++ b/sound/soc/sof/ipc4-topology.c @@ -2825,7 +2825,11 @@ static int sof_ipc4_dai_config(struct snd_sof_dev *sdev, struct snd_sof_widget * case SOF_DAI_INTEL_HDA: gtw_attr = ipc4_copier->gtw_attr; gtw_attr->lp_buffer_alloc = pipeline->lp_mode; - fallthrough; + if (flags & SOF_DAI_CONFIG_FLAGS_HW_PARAMS) { + copier_data->gtw_cfg.node_id &= ~SOF_IPC4_NODE_INDEX_MASK; + copier_data->gtw_cfg.node_id |= SOF_IPC4_NODE_INDEX(data->dai_data); + } + break; case SOF_DAI_INTEL_ALH: /* * Do not clear the node ID when this op is invoked with @@ -2834,7 +2838,7 @@ static int sof_ipc4_dai_config(struct snd_sof_dev *sdev, struct snd_sof_widget * */ if (flags & SOF_DAI_CONFIG_FLAGS_HW_PARAMS) { copier_data->gtw_cfg.node_id &= ~SOF_IPC4_NODE_INDEX_MASK; - copier_data->gtw_cfg.node_id |= SOF_IPC4_NODE_INDEX(data->dai_data); + copier_data->gtw_cfg.node_id |= SOF_IPC4_NODE_INDEX(data->dai_node_id); } break; case SOF_DAI_INTEL_DMIC: diff --git a/sound/soc/sof/sof-audio.h b/sound/soc/sof/sof-audio.h index 9ea2ac5adac7..fd664d5586f0 100644 --- a/sound/soc/sof/sof-audio.h +++ b/sound/soc/sof/sof-audio.h @@ -91,6 +91,7 @@ struct snd_sof_pcm; struct snd_sof_dai_config_data { int dai_index; int dai_data; /* contains DAI-specific information */ + int dai_node_id; /* contains DAI-specific information for Gateway configuration */ }; /** -- cgit v1.2.3 From 2ac9e09ba0e874deeba13c3259dc18f22b622311 Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Tue, 2 Apr 2024 10:18:22 -0500 Subject: ASoC: SOF: Intel: hda: move helper to static inline MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit To allow using widget_to_sdev() in other files, move it as static inline in shared header file. Reviewed-by: Rander Wang Reviewed-by: Péter Ujfalusi Signed-off-by: Pierre-Louis Bossart Link: https://msgid.link/r/20240402151828.175002-12-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/intel/hda-dai.c | 8 -------- sound/soc/sof/intel/hda.h | 8 ++++++++ 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/sound/soc/sof/intel/hda-dai.c b/sound/soc/sof/intel/hda-dai.c index 86c2325e5949..3f2fd84907d2 100644 --- a/sound/soc/sof/intel/hda-dai.c +++ b/sound/soc/sof/intel/hda-dai.c @@ -29,14 +29,6 @@ static bool hda_use_tplg_nhlt; module_param_named(sof_use_tplg_nhlt, hda_use_tplg_nhlt, bool, 0444); MODULE_PARM_DESC(sof_use_tplg_nhlt, "SOF topology nhlt override"); -static struct snd_sof_dev *widget_to_sdev(struct snd_soc_dapm_widget *w) -{ - struct snd_sof_widget *swidget = w->dobj.private; - struct snd_soc_component *component = swidget->scomp; - - return snd_soc_component_get_drvdata(component); -} - int hda_dai_config(struct snd_soc_dapm_widget *w, unsigned int flags, struct snd_sof_dai_config_data *data) { diff --git a/sound/soc/sof/intel/hda.h b/sound/soc/sof/intel/hda.h index 3bf7427dc918..f530a05cfc92 100644 --- a/sound/soc/sof/intel/hda.h +++ b/sound/soc/sof/intel/hda.h @@ -1000,4 +1000,12 @@ int hda_dai_config(struct snd_soc_dapm_widget *w, unsigned int flags, int hda_link_dma_cleanup(struct snd_pcm_substream *substream, struct hdac_ext_stream *hext_stream, struct snd_soc_dai *cpu_dai); +static inline struct snd_sof_dev *widget_to_sdev(struct snd_soc_dapm_widget *w) +{ + struct snd_sof_widget *swidget = w->dobj.private; + struct snd_soc_component *component = swidget->scomp; + + return snd_soc_component_get_drvdata(component); +} + #endif -- cgit v1.2.3 From bfe9225455c032c9dd5637047760cf59562e599f Mon Sep 17 00:00:00 2001 From: Ranjani Sridharan Date: Tue, 2 Apr 2024 10:18:23 -0500 Subject: ASoC: SOF: Intel: hda: Clear Soundwire node ID during BE DAI hw_free MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When an xrun happens, the BE DAI hw_params doesn't get invoked before the stream restarts with a prepare. In this case, clearing the node ID when the DAI widget is freed and unprepared will result in an error when it is re-initialized. In order to avoid this, move the code to clear the node ID to the BE DAI hw_free op to keep it balanced with the BE DAI hw_params. Reviewed-by: Rander Wang Reviewed-by: Péter Ujfalusi Signed-off-by: Ranjani Sridharan Signed-off-by: Pierre-Louis Bossart Link: https://msgid.link/r/20240402151828.175002-13-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/intel/hda.c | 24 ++++++++++++++++++++++++ sound/soc/sof/ipc4-topology.c | 4 ---- 2 files changed, 24 insertions(+), 4 deletions(-) diff --git a/sound/soc/sof/intel/hda.c b/sound/soc/sof/intel/hda.c index ae1a38f20bdb..2c64c25d6f3b 100644 --- a/sound/soc/sof/intel/hda.c +++ b/sound/soc/sof/intel/hda.c @@ -31,6 +31,7 @@ #include "../sof-audio.h" #include "../sof-pci-dev.h" #include "../ops.h" +#include "../ipc4-topology.h" #include "hda.h" #include "telemetry.h" @@ -150,8 +151,31 @@ static int sdw_params_stream(struct device *dev, return hda_dai_config(w, SOF_DAI_CONFIG_FLAGS_HW_PARAMS, &data); } +static int sdw_params_free(struct device *dev, struct sdw_intel_stream_free_data *free_data) +{ + struct snd_soc_dai *d = free_data->dai; + struct snd_soc_dapm_widget *w = snd_soc_dai_get_widget(d, free_data->substream->stream); + struct snd_sof_dev *sdev = widget_to_sdev(w); + + if (sdev->pdata->ipc_type == SOF_IPC_TYPE_4) { + struct snd_sof_widget *swidget = w->dobj.private; + struct snd_sof_dai *dai = swidget->private; + struct sof_ipc4_copier_data *copier_data; + struct sof_ipc4_copier *ipc4_copier; + + ipc4_copier = dai->private; + copier_data = &ipc4_copier->data; + + /* clear the node ID */ + copier_data->gtw_cfg.node_id &= ~SOF_IPC4_NODE_INDEX_MASK; + } + + return 0; +} + struct sdw_intel_ops sdw_callback = { .params_stream = sdw_params_stream, + .free_stream = sdw_params_free, }; static int sdw_ace2x_params_stream(struct device *dev, diff --git a/sound/soc/sof/ipc4-topology.c b/sound/soc/sof/ipc4-topology.c index 0368ef6d0807..e8a5e9fbd796 100644 --- a/sound/soc/sof/ipc4-topology.c +++ b/sound/soc/sof/ipc4-topology.c @@ -1277,7 +1277,6 @@ static void sof_ipc4_unprepare_copier_module(struct snd_sof_widget *swidget) } if (ipc4_copier->dai_type == SOF_DAI_INTEL_ALH) { - struct sof_ipc4_copier_data *copier_data = &ipc4_copier->data; struct sof_ipc4_alh_configuration_blob *blob; unsigned int group_id; @@ -1287,9 +1286,6 @@ static void sof_ipc4_unprepare_copier_module(struct snd_sof_widget *swidget) ALH_MULTI_GTW_BASE; ida_free(&alh_group_ida, group_id); } - - /* clear the node ID */ - copier_data->gtw_cfg.node_id &= ~SOF_IPC4_NODE_INDEX_MASK; } } -- cgit v1.2.3 From a6f2b279d22894e81b23464620d03da6429d9ab5 Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Tue, 2 Apr 2024 10:18:24 -0500 Subject: ASoC: SOF: sof-audio: revisit sof_pcm_stream_free() error handling and logs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit For some reason the existing code stops on the first error, which potentially leaves the DMA and widgets in a weird state. Change to free-up all resources even in case of errors. Also add a more consistent error handling and logs, with the first error code returned to the caller. Reviewed-by: Rander Wang Reviewed-by: Péter Ujfalusi Signed-off-by: Pierre-Louis Bossart Link: https://msgid.link/r/20240402151828.175002-14-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/sof-audio.c | 28 ++++++++++++++++++++-------- 1 file changed, 20 insertions(+), 8 deletions(-) diff --git a/sound/soc/sof/sof-audio.c b/sound/soc/sof/sof-audio.c index e693dcb475e4..b5ca2861edbd 100644 --- a/sound/soc/sof/sof-audio.c +++ b/sound/soc/sof/sof-audio.c @@ -834,17 +834,21 @@ int sof_pcm_stream_free(struct snd_sof_dev *sdev, struct snd_pcm_substream *subs { const struct sof_ipc_pcm_ops *pcm_ops = sof_ipc_get_ops(sdev, pcm); int ret; + int err = 0; if (spcm->prepared[substream->stream]) { /* stop DMA first if needed */ if (pcm_ops && pcm_ops->platform_stop_during_hw_free) snd_sof_pcm_platform_trigger(sdev, substream, SNDRV_PCM_TRIGGER_STOP); - /* Send PCM_FREE IPC to reset pipeline */ + /* free PCM in the DSP */ if (pcm_ops && pcm_ops->hw_free) { ret = pcm_ops->hw_free(sdev->component, substream); - if (ret < 0) - return ret; + if (ret < 0) { + dev_err(sdev->dev, "%s: pcm_ops hw_free failed %d\n", + __func__, ret); + err = ret; + } } spcm->prepared[substream->stream] = false; @@ -852,17 +856,25 @@ int sof_pcm_stream_free(struct snd_sof_dev *sdev, struct snd_pcm_substream *subs /* reset the DMA */ ret = snd_sof_pcm_platform_hw_free(sdev, substream); - if (ret < 0) - return ret; + if (ret < 0) { + dev_err(sdev->dev, "%s: platform hw free failed %d\n", + __func__, ret); + if (!err) + err = ret; + } /* free widget list */ if (free_widget_list) { ret = sof_widget_list_free(sdev, spcm, dir); - if (ret < 0) - dev_err(sdev->dev, "failed to free widgets during suspend\n"); + if (ret < 0) { + dev_err(sdev->dev, "%s: sof_widget_list_free failed %d\n", + __func__, ret); + if (!err) + err = ret; + } } - return ret; + return err; } /* -- cgit v1.2.3 From bb83ae04d9158276d17640f50c2a1e049100acb6 Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Tue, 2 Apr 2024 10:18:25 -0500 Subject: ASoC: SOF: pcm: simplify sof_pcm_hw_free() with helper MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The same sequence is used twice, use common helper. Reviewed-by: Rander Wang Reviewed-by: Péter Ujfalusi Signed-off-by: Pierre-Louis Bossart Link: https://msgid.link/r/20240402151828.175002-15-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/pcm.c | 32 +++----------------------------- 1 file changed, 3 insertions(+), 29 deletions(-) diff --git a/sound/soc/sof/pcm.c b/sound/soc/sof/pcm.c index 33d576b17647..7b732f31f974 100644 --- a/sound/soc/sof/pcm.c +++ b/sound/soc/sof/pcm.c @@ -196,9 +196,8 @@ static int sof_pcm_hw_free(struct snd_soc_component *component, { struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream); struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(component); - const struct sof_ipc_pcm_ops *pcm_ops = sof_ipc_get_ops(sdev, pcm); struct snd_sof_pcm *spcm; - int ret, err = 0; + int ret; /* nothing to do for BE */ if (rtd->dai_link->no_pcm) @@ -211,36 +210,11 @@ static int sof_pcm_hw_free(struct snd_soc_component *component, dev_dbg(component->dev, "pcm: free stream %d dir %d\n", spcm->pcm.pcm_id, substream->stream); - if (spcm->prepared[substream->stream]) { - /* stop DMA first if needed */ - if (pcm_ops && pcm_ops->platform_stop_during_hw_free) - snd_sof_pcm_platform_trigger(sdev, substream, SNDRV_PCM_TRIGGER_STOP); - - /* free PCM in the DSP */ - if (pcm_ops && pcm_ops->hw_free) { - ret = pcm_ops->hw_free(component, substream); - if (ret < 0) - err = ret; - } - - spcm->prepared[substream->stream] = false; - } - - /* reset DMA */ - ret = snd_sof_pcm_platform_hw_free(sdev, substream); - if (ret < 0) { - dev_err(component->dev, "error: platform hw free failed\n"); - err = ret; - } - - /* free the DAPM widget list */ - ret = sof_widget_list_free(sdev, spcm, substream->stream); - if (ret < 0) - err = ret; + ret = sof_pcm_stream_free(sdev, substream, spcm, substream->stream, true); cancel_work_sync(&spcm->stream[substream->stream].period_elapsed_work); - return err; + return ret; } static int sof_pcm_prepare(struct snd_soc_component *component, -- cgit v1.2.3 From dbc78bce74f5f9057ba02bdc8d1549d24c573900 Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Tue, 2 Apr 2024 10:18:26 -0500 Subject: ASoC: SOF: pcm: add pending_stop state variable MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add a state variable to keep track of delayed stops, in case pcm_ops->platform_stop_during_hw_free is set. This patch should be iso-functionality, possibly removing no-op cases. The main purpose of this new state variable is to prepare a follow-up patch to reset all PCM and DMAs in case of stop/prepare xrun sequences. Reviewed-by: Rander Wang Reviewed-by: Péter Ujfalusi Signed-off-by: Pierre-Louis Bossart Link: https://msgid.link/r/20240402151828.175002-16-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/pcm.c | 11 +++++++++++ sound/soc/sof/sof-audio.c | 1 + sound/soc/sof/sof-audio.h | 1 + 3 files changed, 13 insertions(+) diff --git a/sound/soc/sof/pcm.c b/sound/soc/sof/pcm.c index 7b732f31f974..2e8782dddc80 100644 --- a/sound/soc/sof/pcm.c +++ b/sound/soc/sof/pcm.c @@ -276,6 +276,8 @@ static int sof_pcm_trigger(struct snd_soc_component *component, dev_dbg(component->dev, "pcm: trigger stream %d dir %d cmd %d\n", spcm->pcm.pcm_id, substream->stream, cmd); + spcm->pending_stop[substream->stream] = false; + switch (cmd) { case SNDRV_PCM_TRIGGER_PAUSE_PUSH: ipc_first = true; @@ -345,6 +347,15 @@ static int sof_pcm_trigger(struct snd_soc_component *component, /* invoke platform trigger to stop DMA even if pcm_ops isn't set or if it failed */ if (!pcm_ops || !pcm_ops->platform_stop_during_hw_free) snd_sof_pcm_platform_trigger(sdev, substream, cmd); + + /* + * set the pending_stop flag to indicate that pipeline stop has been delayed. + * This will be used later to stop the pipelines during prepare when recovering + * from xruns. + */ + if (pcm_ops && pcm_ops->platform_stop_during_hw_free && + cmd == SNDRV_PCM_TRIGGER_STOP) + spcm->pending_stop[substream->stream] = true; break; default: break; diff --git a/sound/soc/sof/sof-audio.c b/sound/soc/sof/sof-audio.c index b5ca2861edbd..32fef64ef10d 100644 --- a/sound/soc/sof/sof-audio.c +++ b/sound/soc/sof/sof-audio.c @@ -852,6 +852,7 @@ int sof_pcm_stream_free(struct snd_sof_dev *sdev, struct snd_pcm_substream *subs } spcm->prepared[substream->stream] = false; + spcm->pending_stop[substream->stream] = false; } /* reset the DMA */ diff --git a/sound/soc/sof/sof-audio.h b/sound/soc/sof/sof-audio.h index fd664d5586f0..80a5bd69ef1c 100644 --- a/sound/soc/sof/sof-audio.h +++ b/sound/soc/sof/sof-audio.h @@ -342,6 +342,7 @@ struct snd_sof_pcm { struct list_head list; /* list in sdev pcm list */ struct snd_pcm_hw_params params[2]; bool prepared[2]; /* PCM_PARAMS set successfully */ + bool pending_stop[2]; /* only used if (!pcm_ops->platform_stop_during_hw_free) */ }; struct snd_sof_led_control { -- cgit v1.2.3 From ebd3b3014eebdd490f2c509d79e719fbcc680963 Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Tue, 2 Apr 2024 10:18:27 -0500 Subject: ASoC: SOF: pcm: reset all PCM sources in case of xruns MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit With the delayed stops, the xrun handling is problematic: the applications expects everything to be reset but the firmware and DMA are still in a PAUSED state. This patch makes sure the prepare while pending_stop is set is special-cased. Reviewed-by: Rander Wang Reviewed-by: Péter Ujfalusi Co-developed-by: Ranjani Sridharan Signed-off-by: Ranjani Sridharan Signed-off-by: Pierre-Louis Bossart Link: https://msgid.link/r/20240402151828.175002-17-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/pcm.c | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/sound/soc/sof/pcm.c b/sound/soc/sof/pcm.c index 2e8782dddc80..7b88e24b7701 100644 --- a/sound/soc/sof/pcm.c +++ b/sound/soc/sof/pcm.c @@ -221,6 +221,7 @@ static int sof_pcm_prepare(struct snd_soc_component *component, struct snd_pcm_substream *substream) { struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream); + struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(component); struct snd_sof_pcm *spcm; int ret; @@ -232,8 +233,18 @@ static int sof_pcm_prepare(struct snd_soc_component *component, if (!spcm) return -EINVAL; - if (spcm->prepared[substream->stream]) - return 0; + if (spcm->prepared[substream->stream]) { + if (!spcm->pending_stop[substream->stream]) + return 0; + + /* + * this case should be reached in case of xruns where we absolutely + * want to free-up and reset all PCM/DMA resources + */ + ret = sof_pcm_stream_free(sdev, substream, spcm, substream->stream, true); + if (ret < 0) + return ret; + } dev_dbg(component->dev, "pcm: prepare stream %d dir %d\n", spcm->pcm.pcm_id, substream->stream); -- cgit v1.2.3 From f0caa4fc244ca739ce6d12168aa588c412c81190 Mon Sep 17 00:00:00 2001 From: Ranjani Sridharan Date: Tue, 2 Apr 2024 10:18:28 -0500 Subject: ASoC: SOF: ipc4-topology: Save the ALH DAI index during hw_params MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The node_id for multi-gateway ALH DAI's get overwritten with the group_id during the DAI copier's ipc_prepare op. So, save the ALH dai_index during the BE DAI hw_params in the dai_index field of struct ipc4_copier and use that to set the device ID in the configuration blob. This will avoid errors during copier init after an xrun. Note that the dai_index is typically set in topology for DMIC/SSP, but it's not used for ALH. Reclaiming this dai_index field to store the node_id does not generate a conflict with topology-defined values. Reviewed-by: Rander Wang Reviewed-by: Péter Ujfalusi Signed-off-by: Ranjani Sridharan Signed-off-by: Pierre-Louis Bossart Link: https://msgid.link/r/20240402151828.175002-18-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/intel/hda.c | 1 + sound/soc/sof/ipc4-topology.c | 12 ++++++++++-- sound/soc/sof/ipc4-topology.h | 1 + 3 files changed, 12 insertions(+), 2 deletions(-) diff --git a/sound/soc/sof/intel/hda.c b/sound/soc/sof/intel/hda.c index 2c64c25d6f3b..d38dc43c2f1c 100644 --- a/sound/soc/sof/intel/hda.c +++ b/sound/soc/sof/intel/hda.c @@ -164,6 +164,7 @@ static int sdw_params_free(struct device *dev, struct sdw_intel_stream_free_data struct sof_ipc4_copier *ipc4_copier; ipc4_copier = dai->private; + ipc4_copier->dai_index = 0; copier_data = &ipc4_copier->data; /* clear the node ID */ diff --git a/sound/soc/sof/ipc4-topology.c b/sound/soc/sof/ipc4-topology.c index e8a5e9fbd796..793bca09bbf4 100644 --- a/sound/soc/sof/ipc4-topology.c +++ b/sound/soc/sof/ipc4-topology.c @@ -1700,6 +1700,8 @@ sof_ipc4_prepare_copier_module(struct snd_sof_widget *swidget, */ i = 0; list_for_each_entry(w, &sdev->widget_list, list) { + u32 node_type; + if (w->widget->sname && strcmp(w->widget->sname, swidget->widget->sname)) continue; @@ -1707,7 +1709,10 @@ sof_ipc4_prepare_copier_module(struct snd_sof_widget *swidget, dai = w->private; alh_copier = (struct sof_ipc4_copier *)dai->private; alh_data = &alh_copier->data; - blob->alh_cfg.mapping[i].device = alh_data->gtw_cfg.node_id; + node_type = SOF_IPC4_GET_NODE_TYPE(alh_data->gtw_cfg.node_id); + blob->alh_cfg.mapping[i].device = SOF_IPC4_NODE_TYPE(node_type); + blob->alh_cfg.mapping[i].device |= + SOF_IPC4_NODE_INDEX(alh_copier->dai_index); /* * The mapping[i] device in ALH blob should be the same as the @@ -2830,12 +2835,15 @@ static int sof_ipc4_dai_config(struct snd_sof_dev *sdev, struct snd_sof_widget * /* * Do not clear the node ID when this op is invoked with * SOF_DAI_CONFIG_FLAGS_HW_FREE. It is needed to free the group_ida during - * unprepare. + * unprepare. The node_id for multi-gateway DAI's will be overwritten with the + * group_id during copier's ipc_prepare op. */ if (flags & SOF_DAI_CONFIG_FLAGS_HW_PARAMS) { + ipc4_copier->dai_index = data->dai_node_id; copier_data->gtw_cfg.node_id &= ~SOF_IPC4_NODE_INDEX_MASK; copier_data->gtw_cfg.node_id |= SOF_IPC4_NODE_INDEX(data->dai_node_id); } + break; case SOF_DAI_INTEL_DMIC: case SOF_DAI_INTEL_SSP: diff --git a/sound/soc/sof/ipc4-topology.h b/sound/soc/sof/ipc4-topology.h index aa5122c3721d..6e33208a357f 100644 --- a/sound/soc/sof/ipc4-topology.h +++ b/sound/soc/sof/ipc4-topology.h @@ -45,6 +45,7 @@ #define SOF_IPC4_NODE_INDEX_MASK 0xFF #define SOF_IPC4_NODE_INDEX(x) ((x) & SOF_IPC4_NODE_INDEX_MASK) #define SOF_IPC4_NODE_TYPE(x) ((x) << 8) +#define SOF_IPC4_GET_NODE_TYPE(node_id) ((node_id) >> 8) /* Node ID for SSP type DAI copiers */ #define SOF_IPC4_NODE_INDEX_INTEL_SSP(x) (((x) & 0xf) << 4) -- cgit v1.2.3 From 538d505fde20393bce1e6fb95cec82b56cdd22ef Mon Sep 17 00:00:00 2001 From: Patryk Wlazlyn Date: Mon, 22 Jan 2024 15:22:35 +0100 Subject: tools/power turbostat: Read base_hz and bclk from CPUID.16H if available If MSRs cannot be read, values can be obtained from cpuid. Signed-off-by: Patryk Wlazlyn Signed-off-by: Len Brown --- tools/power/x86/turbostat/turbostat.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/tools/power/x86/turbostat/turbostat.c b/tools/power/x86/turbostat/turbostat.c index a4a40a6e1b95..c35c48b6a99a 100644 --- a/tools/power/x86/turbostat/turbostat.c +++ b/tools/power/x86/turbostat/turbostat.c @@ -5848,6 +5848,15 @@ void process_cpuid() base_mhz = max_mhz = bus_mhz = edx = 0; __cpuid(0x16, base_mhz, max_mhz, bus_mhz, edx); + + bclk = bus_mhz; + + base_hz = base_mhz * 1000000; + has_base_hz = 1; + + if (platform->enable_tsc_tweak) + tsc_tweak = base_hz / tsc_hz; + if (!quiet) fprintf(outf, "CPUID(0x16): base_mhz: %d max_mhz: %d bus_mhz: %d\n", base_mhz, max_mhz, bus_mhz); -- cgit v1.2.3 From b6fe938317eed58e8c687bd5965a956e15fb5828 Mon Sep 17 00:00:00 2001 From: Len Brown Date: Fri, 19 Jan 2024 12:25:42 -0600 Subject: tools/power turbostat: Fix warning upon failed /dev/cpu_dma_latency read Previously a failed read of /dev/cpu_dma_latency erroneously complained turbostat: capget(CAP_SYS_ADMIN) failed, try "# setcap cap_sys_admin=ep ./turbostat This went unnoticed because this file is typically visible to root, and turbostat was typically run as root. Going forward, when a non-root user can run turbostat... Complain about failed read access to this file only if --debug is used. Signed-off-by: Len Brown --- tools/power/x86/turbostat/turbostat.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tools/power/x86/turbostat/turbostat.c b/tools/power/x86/turbostat/turbostat.c index c35c48b6a99a..531f37e5f92a 100644 --- a/tools/power/x86/turbostat/turbostat.c +++ b/tools/power/x86/turbostat/turbostat.c @@ -5545,7 +5545,8 @@ void print_dev_latency(void) fd = open(path, O_RDONLY); if (fd < 0) { - warnx("capget(CAP_SYS_ADMIN) failed, try \"# setcap cap_sys_admin=ep %s\"", progname); + if (debug) + warnx("Read %s failed", path); return; } -- cgit v1.2.3 From 2d2ccd57338779469777d4319152151272994182 Mon Sep 17 00:00:00 2001 From: Len Brown Date: Mon, 5 Feb 2024 15:56:25 -0600 Subject: tools/power turbostat: enhance -D (debug counter dump) output Eliminate redundant debug output for core and package scope counters. Include name and path for all "ADDED" counters. Signed-off-by: Len Brown --- tools/power/x86/turbostat/turbostat.c | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/tools/power/x86/turbostat/turbostat.c b/tools/power/x86/turbostat/turbostat.c index 531f37e5f92a..60432753fe6a 100644 --- a/tools/power/x86/turbostat/turbostat.c +++ b/tools/power/x86/turbostat/turbostat.c @@ -1673,11 +1673,13 @@ int dump_counters(struct thread_data *t, struct core_data *c, struct pkg_data *p outp += sprintf(outp, "SMI: %d\n", t->smi_count); for (i = 0, mp = sys.tp; mp; i++, mp = mp->next) { - outp += sprintf(outp, "tADDED [%d] msr0x%x: %08llX\n", i, mp->msr_num, t->counter[i]); + outp += + sprintf(outp, "tADDED [%d] %8s msr0x%x: %08llX %s\n", i, mp->name, mp->msr_num, + t->counter[i], mp->path); } } - if (c) { + if (c && is_cpu_first_thread_in_core(t, c, p)) { outp += sprintf(outp, "core: %d\n", c->core_id); outp += sprintf(outp, "c3: %016llX\n", c->c3); outp += sprintf(outp, "c6: %016llX\n", c->c6); @@ -1687,12 +1689,14 @@ int dump_counters(struct thread_data *t, struct core_data *c, struct pkg_data *p outp += sprintf(outp, "Joules: %0X\n", c->core_energy); for (i = 0, mp = sys.cp; mp; i++, mp = mp->next) { - outp += sprintf(outp, "cADDED [%d] msr0x%x: %08llX\n", i, mp->msr_num, c->counter[i]); + outp += + sprintf(outp, "cADDED [%d] %8s msr0x%x: %08llX %s\n", i, mp->name, mp->msr_num, + c->counter[i], mp->path); } outp += sprintf(outp, "mc6_us: %016llX\n", c->mc6_us); } - if (p) { + if (p && is_cpu_first_core_in_package(t, c, p)) { outp += sprintf(outp, "package: %d\n", p->package_id); outp += sprintf(outp, "Weighted cores: %016llX\n", p->pkg_wtd_core_c0); @@ -1721,7 +1725,9 @@ int dump_counters(struct thread_data *t, struct core_data *c, struct pkg_data *p outp += sprintf(outp, "PTM: %dC\n", p->pkg_temp_c); for (i = 0, mp = sys.pp; mp; i++, mp = mp->next) { - outp += sprintf(outp, "pADDED [%d] msr0x%x: %08llX\n", i, mp->msr_num, p->counter[i]); + outp += + sprintf(outp, "pADDED [%d] %8s msr0x%x: %08llX %s\n", i, mp->name, mp->msr_num, + p->counter[i], mp->path); } } -- cgit v1.2.3 From 3e4048466c396cff52c6d435156dbcd0571e4381 Mon Sep 17 00:00:00 2001 From: Patryk Wlazlyn Date: Thu, 11 Jan 2024 15:48:09 +0100 Subject: tools/power turbostat: Add --no-msr option Add --no-msr option to allow users to run turbostat without accessing MSRs via the MSR driver. Signed-off-by: Patryk Wlazlyn Reviewed-by: Len Brown Signed-off-by: Len Brown --- tools/power/x86/turbostat/turbostat.8 | 2 + tools/power/x86/turbostat/turbostat.c | 205 ++++++++++++++++++++++++---------- 2 files changed, 151 insertions(+), 56 deletions(-) diff --git a/tools/power/x86/turbostat/turbostat.8 b/tools/power/x86/turbostat/turbostat.8 index 1ba6340d3b3d..28be452fbfe2 100644 --- a/tools/power/x86/turbostat/turbostat.8 +++ b/tools/power/x86/turbostat/turbostat.8 @@ -67,6 +67,8 @@ The column name "all" can be used to enable all disabled-by-default built-in cou .PP \fB--quiet\fP Do not decode and print the system configuration header information. .PP ++\fB--no-msr\fP Disable all the uses of the MSR driver. ++.PP \fB--interval seconds\fP overrides the default 5.0 second measurement interval. .PP \fB--num_iterations num\fP number of the measurement iterations. diff --git a/tools/power/x86/turbostat/turbostat.c b/tools/power/x86/turbostat/turbostat.c index 60432753fe6a..4d5437a9725b 100644 --- a/tools/power/x86/turbostat/turbostat.c +++ b/tools/power/x86/turbostat/turbostat.c @@ -36,6 +36,7 @@ #include #include #include +#include #define UNUSED(x) (void)(x) @@ -265,6 +266,7 @@ unsigned int has_hwp_epp; /* IA32_HWP_REQUEST[bits 31:24] */ unsigned int has_hwp_pkg; /* IA32_HWP_REQUEST_PKG */ unsigned int first_counter_read = 1; int ignore_stdin; +bool no_msr; int get_msr(int cpu, off_t offset, unsigned long long *msr); @@ -1282,13 +1284,36 @@ int get_msr_fd(int cpu) sprintf(pathname, "/dev/cpu/%d/msr", cpu); fd = open(pathname, O_RDONLY); if (fd < 0) - err(-1, "%s open failed, try chown or chmod +r /dev/cpu/*/msr, or run as root", pathname); + err(-1, "%s open failed, try chown or chmod +r /dev/cpu/*/msr, " + "or run with --no-msr, or run as root", pathname); fd_percpu[cpu] = fd; return fd; } +static void bic_disable_msr_access(void) +{ + const unsigned long bic_msrs = + BIC_Avg_MHz | + BIC_Busy | + BIC_Bzy_MHz | + BIC_SMI | + BIC_CPU_c1 | + BIC_CPU_c3 | + BIC_CPU_c6 | + BIC_CPU_c7 | + BIC_Mod_c6 | + BIC_CoreTmp | + BIC_Totl_c0 | + BIC_Any_c0 | + BIC_GFX_c0 | + BIC_CPUGFX | + BIC_Pkgpc2 | BIC_Pkgpc3 | BIC_Pkgpc6 | BIC_Pkgpc7 | BIC_Pkgpc8 | BIC_Pkgpc9 | BIC_Pkgpc10 | BIC_PkgTmp; + + bic_enabled &= ~bic_msrs; +} + static long perf_event_open(struct perf_event_attr *hw_event, pid_t pid, int cpu, int group_fd, unsigned long flags) { return syscall(__NR_perf_event_open, hw_event, pid, cpu, group_fd, flags); @@ -1328,6 +1353,8 @@ int get_msr(int cpu, off_t offset, unsigned long long *msr) { ssize_t retval; + assert(!no_msr); + retval = pread(get_msr_fd(cpu), msr, sizeof(*msr), offset); if (retval != sizeof *msr) @@ -1371,6 +1398,7 @@ void help(void) " Override default 5-second measurement interval\n" " -J, --Joules displays energy in Joules instead of Watts\n" " -l, --list list column headers only\n" + " -M, --no-msr Disable all uses of the MSR driver\n" " -n, --num_iterations num\n" " number of the measurement iterations\n" " -N, --header_iterations num\n" @@ -2597,6 +2625,7 @@ unsigned long long snapshot_sysfs_counter(char *path) int get_mp(int cpu, struct msr_counter *mp, unsigned long long *counterp) { if (mp->msr_num != 0) { + assert(!no_msr); if (get_msr(cpu, mp->msr_num, counterp)) return -1; } else { @@ -2646,6 +2675,9 @@ int get_epb(int cpu) return epb; msr_fallback: + if (no_msr) + return -1; + get_msr(cpu, MSR_IA32_ENERGY_PERF_BIAS, &msr); return msr & 0xf; @@ -2865,7 +2897,7 @@ retry: if (DO_BIC(BIC_CORE_THROT_CNT)) get_core_throt_cnt(cpu, &c->core_throt_cnt); - if (platform->rapl_msrs & RAPL_AMD_F17H) { + if ((platform->rapl_msrs & RAPL_AMD_F17H) && !no_msr) { if (get_msr(cpu, MSR_CORE_ENERGY_STAT, &msr)) return -14; c->core_energy = msr & 0xFFFFFFFF; @@ -2930,41 +2962,44 @@ retry: if (DO_BIC(BIC_SYS_LPI)) p->sys_lpi = cpuidle_cur_sys_lpi_us; - if (platform->rapl_msrs & RAPL_PKG) { - if (get_msr_sum(cpu, MSR_PKG_ENERGY_STATUS, &msr)) - return -13; - p->energy_pkg = msr; - } - if (platform->rapl_msrs & RAPL_CORE_ENERGY_STATUS) { - if (get_msr_sum(cpu, MSR_PP0_ENERGY_STATUS, &msr)) - return -14; - p->energy_cores = msr; - } - if (platform->rapl_msrs & RAPL_DRAM) { - if (get_msr_sum(cpu, MSR_DRAM_ENERGY_STATUS, &msr)) - return -15; - p->energy_dram = msr; - } - if (platform->rapl_msrs & RAPL_GFX) { - if (get_msr_sum(cpu, MSR_PP1_ENERGY_STATUS, &msr)) - return -16; - p->energy_gfx = msr; - } - if (platform->rapl_msrs & RAPL_PKG_PERF_STATUS) { - if (get_msr_sum(cpu, MSR_PKG_PERF_STATUS, &msr)) - return -16; - p->rapl_pkg_perf_status = msr; - } - if (platform->rapl_msrs & RAPL_DRAM_PERF_STATUS) { - if (get_msr_sum(cpu, MSR_DRAM_PERF_STATUS, &msr)) - return -16; - p->rapl_dram_perf_status = msr; - } - if (platform->rapl_msrs & RAPL_AMD_F17H) { - if (get_msr_sum(cpu, MSR_PKG_ENERGY_STAT, &msr)) - return -13; - p->energy_pkg = msr; + if (!no_msr) { + if (platform->rapl_msrs & RAPL_PKG) { + if (get_msr_sum(cpu, MSR_PKG_ENERGY_STATUS, &msr)) + return -13; + p->energy_pkg = msr; + } + if (platform->rapl_msrs & RAPL_CORE_ENERGY_STATUS) { + if (get_msr_sum(cpu, MSR_PP0_ENERGY_STATUS, &msr)) + return -14; + p->energy_cores = msr; + } + if (platform->rapl_msrs & RAPL_DRAM) { + if (get_msr_sum(cpu, MSR_DRAM_ENERGY_STATUS, &msr)) + return -15; + p->energy_dram = msr; + } + if (platform->rapl_msrs & RAPL_GFX) { + if (get_msr_sum(cpu, MSR_PP1_ENERGY_STATUS, &msr)) + return -16; + p->energy_gfx = msr; + } + if (platform->rapl_msrs & RAPL_PKG_PERF_STATUS) { + if (get_msr_sum(cpu, MSR_PKG_PERF_STATUS, &msr)) + return -16; + p->rapl_pkg_perf_status = msr; + } + if (platform->rapl_msrs & RAPL_DRAM_PERF_STATUS) { + if (get_msr_sum(cpu, MSR_DRAM_PERF_STATUS, &msr)) + return -16; + p->rapl_dram_perf_status = msr; + } + if (platform->rapl_msrs & RAPL_AMD_F17H) { + if (get_msr_sum(cpu, MSR_PKG_ENERGY_STAT, &msr)) + return -13; + p->energy_pkg = msr; + } } + if (DO_BIC(BIC_PkgTmp)) { if (get_msr(cpu, MSR_IA32_PACKAGE_THERM_STATUS, &msr)) return -17; @@ -3072,7 +3107,7 @@ void probe_cst_limit(void) unsigned long long msr; int *pkg_cstate_limits; - if (!platform->has_nhm_msrs) + if (!platform->has_nhm_msrs || no_msr) return; switch (platform->cst_limit) { @@ -3116,7 +3151,7 @@ static void dump_platform_info(void) unsigned long long msr; unsigned int ratio; - if (!platform->has_nhm_msrs) + if (!platform->has_nhm_msrs || no_msr) return; get_msr(base_cpu, MSR_PLATFORM_INFO, &msr); @@ -3134,7 +3169,7 @@ static void dump_power_ctl(void) { unsigned long long msr; - if (!platform->has_nhm_msrs) + if (!platform->has_nhm_msrs || no_msr) return; get_msr(base_cpu, MSR_IA32_POWER_CTL, &msr); @@ -3340,7 +3375,7 @@ static void dump_cst_cfg(void) { unsigned long long msr; - if (!platform->has_nhm_msrs) + if (!platform->has_nhm_msrs || no_msr) return; get_msr(base_cpu, MSR_PKG_CST_CONFIG_CONTROL, &msr); @@ -3412,7 +3447,7 @@ void print_irtl(void) { unsigned long long msr; - if (!platform->has_irtl_msrs) + if (!platform->has_irtl_msrs || no_msr) return; if (platform->supported_cstates & PC3) { @@ -4193,6 +4228,8 @@ int get_msr_sum(int cpu, off_t offset, unsigned long long *msr) int ret, idx; unsigned long long msr_cur, msr_last; + assert(!no_msr); + if (!per_cpu_msr_sum) return 1; @@ -4221,6 +4258,8 @@ static int update_msr_sum(struct thread_data *t, struct core_data *c, struct pkg UNUSED(c); UNUSED(p); + assert(!no_msr); + for (i = IDX_PKG_ENERGY; i < IDX_COUNT; i++) { unsigned long long msr_cur, msr_last; off_t offset; @@ -4465,7 +4504,7 @@ void check_permissions(void) sprintf(pathname, "/dev/cpu/%d/msr", base_cpu); if (euidaccess(pathname, R_OK)) { do_exit++; - warn("/dev/cpu/0/msr open failed, try chown or chmod +r /dev/cpu/*/msr"); + warn("/dev/cpu/0/msr open failed, try chown or chmod +r /dev/cpu/*/msr, or run with --no-msr"); } /* if all else fails, thell them to be root */ @@ -4482,7 +4521,7 @@ void probe_bclk(void) unsigned long long msr; unsigned int base_ratio; - if (!platform->has_nhm_msrs) + if (!platform->has_nhm_msrs || no_msr) return; if (platform->bclk_freq == BCLK_100MHZ) @@ -4522,7 +4561,7 @@ static void dump_turbo_ratio_info(void) if (!has_turbo) return; - if (!platform->has_nhm_msrs) + if (!platform->has_nhm_msrs || no_msr) return; if (platform->trl_msrs & TRL_LIMIT2) @@ -4845,6 +4884,9 @@ int print_hwp(struct thread_data *t, struct core_data *c, struct pkg_data *p) UNUSED(c); UNUSED(p); + if (no_msr) + return 0; + if (!has_hwp) return 0; @@ -4931,6 +4973,9 @@ int print_perf_limit(struct thread_data *t, struct core_data *c, struct pkg_data UNUSED(c); UNUSED(p); + if (no_msr) + return 0; + cpu = t->cpu_id; /* per-package */ @@ -5264,7 +5309,7 @@ int print_rapl(struct thread_data *t, struct core_data *c, struct pkg_data *p) */ void probe_rapl(void) { - if (!platform->rapl_msrs) + if (!platform->rapl_msrs || no_msr) return; if (genuine_intel) @@ -5320,7 +5365,7 @@ int set_temperature_target(struct thread_data *t, struct core_data *c, struct pk } /* Temperature Target MSR is Nehalem and newer only */ - if (!platform->has_nhm_msrs) + if (!platform->has_nhm_msrs || no_msr) goto guess; if (get_msr(base_cpu, MSR_IA32_TEMPERATURE_TARGET, &msr)) @@ -5367,6 +5412,9 @@ int print_thermal(struct thread_data *t, struct core_data *c, struct pkg_data *p UNUSED(c); UNUSED(p); + if (no_msr) + return 0; + if (!(do_dts || do_ptm)) return 0; @@ -5464,6 +5512,9 @@ void decode_feature_control_msr(void) { unsigned long long msr; + if (no_msr) + return; + if (!get_msr(base_cpu, MSR_IA32_FEAT_CTL, &msr)) fprintf(outf, "cpu%d: MSR_IA32_FEATURE_CONTROL: 0x%08llx (%sLocked %s)\n", base_cpu, msr, msr & FEAT_CTL_LOCKED ? "" : "UN-", msr & (1 << 18) ? "SGX" : ""); @@ -5473,6 +5524,9 @@ void decode_misc_enable_msr(void) { unsigned long long msr; + if (no_msr) + return; + if (!genuine_intel) return; @@ -5490,6 +5544,9 @@ void decode_misc_feature_control(void) { unsigned long long msr; + if (no_msr) + return; + if (!platform->has_msr_misc_feature_control) return; @@ -5511,6 +5568,9 @@ void decode_misc_pwr_mgmt_msr(void) { unsigned long long msr; + if (no_msr) + return; + if (!platform->has_msr_misc_pwr_mgmt) return; @@ -5530,6 +5590,9 @@ void decode_c6_demotion_policy_msr(void) { unsigned long long msr; + if (no_msr) + return; + if (!platform->has_msr_c6_demotion_policy_config) return; @@ -5626,7 +5689,7 @@ void probe_cstates(void) if (platform->has_msr_module_c6_res_ms) BIC_PRESENT(BIC_Mod_c6); - if (platform->has_ext_cst_msrs) { + if (platform->has_ext_cst_msrs && !no_msr) { BIC_PRESENT(BIC_Totl_c0); BIC_PRESENT(BIC_Any_c0); BIC_PRESENT(BIC_GFX_c0); @@ -5714,10 +5777,12 @@ void process_cpuid() ecx_flags = ecx; edx_flags = edx; - if (get_msr(sched_getcpu(), MSR_IA32_UCODE_REV, &ucode_patch)) - warnx("get_msr(UCODE)"); - else - ucode_patch_valid = true; + if (!no_msr) { + if (get_msr(sched_getcpu(), MSR_IA32_UCODE_REV, &ucode_patch)) + warnx("get_msr(UCODE)"); + else + ucode_patch_valid = true; + } /* * check max extended function levels of CPUID. @@ -5892,7 +5957,7 @@ void probe_pm_features(void) probe_thermal(); - if (platform->has_nhm_msrs) + if (platform->has_nhm_msrs && !no_msr) BIC_PRESENT(BIC_SMI); if (!quiet) @@ -6252,8 +6317,10 @@ void turbostat_init() { setup_all_buffers(true); set_base_cpu(); - check_dev_msr(); - check_permissions(); + if (!no_msr) { + check_dev_msr(); + check_permissions(); + } process_cpuid(); probe_pm_features(); linux_perf_init(); @@ -6370,6 +6437,9 @@ int add_counter(unsigned int msr_num, char *path, char *name, { struct msr_counter *msrp; + if (no_msr && msr_num) + errx(1, "Requested MSR counter 0x%x, but in --no-msr mode", msr_num); + msrp = calloc(1, sizeof(struct msr_counter)); if (msrp == NULL) { perror("calloc"); @@ -6674,6 +6744,7 @@ void cmdline(int argc, char **argv) { "list", no_argument, 0, 'l' }, { "out", required_argument, 0, 'o' }, { "quiet", no_argument, 0, 'q' }, + { "no-msr", no_argument, 0, 'M' }, { "show", required_argument, 0, 's' }, { "Summary", no_argument, 0, 'S' }, { "TCC", required_argument, 0, 'T' }, @@ -6683,7 +6754,22 @@ void cmdline(int argc, char **argv) progname = argv[0]; - while ((opt = getopt_long_only(argc, argv, "+C:c:Dde:hi:Jn:o:qST:v", long_options, &option_index)) != -1) { + /* + * Parse some options early, because they may make other options invalid, + * like adding the MSR counter with --add and at the same time using --no-msr. + */ + while ((opt = getopt_long_only(argc, argv, "M", long_options, &option_index)) != -1) { + switch (opt) { + case 'M': + no_msr = 1; + break; + default: + break; + } + } + optind = 0; + + while ((opt = getopt_long_only(argc, argv, "+C:c:Dde:hi:Jn:o:qMST:v", long_options, &option_index)) != -1) { switch (opt) { case 'a': parse_add_command(optarg); @@ -6741,6 +6827,9 @@ void cmdline(int argc, char **argv) case 'q': quiet = 1; break; + case 'M': + /* Parsed earlier */ + break; case 'n': num_iterations = strtod(optarg, NULL); @@ -6817,6 +6906,9 @@ skip_cgroup_setting: outf = stderr; cmdline(argc, argv); + if (no_msr) + bic_disable_msr_access(); + if (!quiet) { print_version(); print_bootcmd(); @@ -6829,7 +6921,8 @@ skip_cgroup_setting: turbostat_init(); - msr_sum_record(); + if (!no_msr) + msr_sum_record(); /* dump counters and exit */ if (dump_only) -- cgit v1.2.3 From a0e86c90b83c118985260e36490583b5a38d4359 Mon Sep 17 00:00:00 2001 From: Patryk Wlazlyn Date: Thu, 11 Jan 2024 15:58:02 +0100 Subject: tools/power turbostat: Add --no-perf option Add the --no-perf option to allow users to run turbostat without accessing perf. Signed-off-by: Patryk Wlazlyn Reviewed-by: Len Brown Signed-off-by: Len Brown --- tools/power/x86/turbostat/turbostat.8 | 2 ++ tools/power/x86/turbostat/turbostat.c | 25 ++++++++++++++++++++++--- 2 files changed, 24 insertions(+), 3 deletions(-) diff --git a/tools/power/x86/turbostat/turbostat.8 b/tools/power/x86/turbostat/turbostat.8 index 28be452fbfe2..567327b004e6 100644 --- a/tools/power/x86/turbostat/turbostat.8 +++ b/tools/power/x86/turbostat/turbostat.8 @@ -69,6 +69,8 @@ The column name "all" can be used to enable all disabled-by-default built-in cou .PP +\fB--no-msr\fP Disable all the uses of the MSR driver. +.PP ++\fB--no-perf\fP Disable all the uses of the perf API. ++.PP \fB--interval seconds\fP overrides the default 5.0 second measurement interval. .PP \fB--num_iterations num\fP number of the measurement iterations. diff --git a/tools/power/x86/turbostat/turbostat.c b/tools/power/x86/turbostat/turbostat.c index 4d5437a9725b..bad2fec7f342 100644 --- a/tools/power/x86/turbostat/turbostat.c +++ b/tools/power/x86/turbostat/turbostat.c @@ -267,6 +267,7 @@ unsigned int has_hwp_pkg; /* IA32_HWP_REQUEST_PKG */ unsigned int first_counter_read = 1; int ignore_stdin; bool no_msr; +bool no_perf; int get_msr(int cpu, off_t offset, unsigned long long *msr); @@ -1314,8 +1315,17 @@ static void bic_disable_msr_access(void) bic_enabled &= ~bic_msrs; } +static void bic_disable_perf_access(void) +{ + const unsigned long bic_perf = BIC_IPC; + + bic_enabled &= ~bic_perf; +} + static long perf_event_open(struct perf_event_attr *hw_event, pid_t pid, int cpu, int group_fd, unsigned long flags) { + assert(!no_perf); + return syscall(__NR_perf_event_open, hw_event, pid, cpu, group_fd, flags); } @@ -1332,8 +1342,8 @@ static int perf_instr_count_open(int cpu_num) /* counter for cpu_num, including user + kernel and all processes */ fd = perf_event_open(&pea, -1, cpu_num, -1, 0); if (fd == -1) { - warnx("capget(CAP_PERFMON) failed, try \"# setcap cap_sys_admin=ep %s\"", progname); - BIC_NOT_PRESENT(BIC_IPC); + warnx("capget(CAP_PERFMON) failed, try \"# setcap cap_sys_admin=ep %s\" or use --no-perf", progname); + bic_disable_perf_access(); } return fd; @@ -1399,6 +1409,7 @@ void help(void) " -J, --Joules displays energy in Joules instead of Watts\n" " -l, --list list column headers only\n" " -M, --no-msr Disable all uses of the MSR driver\n" + " -P, --no-perf Disable all uses of the perf API\n" " -n, --num_iterations num\n" " number of the measurement iterations\n" " -N, --header_iterations num\n" @@ -6745,6 +6756,7 @@ void cmdline(int argc, char **argv) { "out", required_argument, 0, 'o' }, { "quiet", no_argument, 0, 'q' }, { "no-msr", no_argument, 0, 'M' }, + { "no-perf", no_argument, 0, 'P' }, { "show", required_argument, 0, 's' }, { "Summary", no_argument, 0, 'S' }, { "TCC", required_argument, 0, 'T' }, @@ -6758,11 +6770,14 @@ void cmdline(int argc, char **argv) * Parse some options early, because they may make other options invalid, * like adding the MSR counter with --add and at the same time using --no-msr. */ - while ((opt = getopt_long_only(argc, argv, "M", long_options, &option_index)) != -1) { + while ((opt = getopt_long_only(argc, argv, "MP", long_options, &option_index)) != -1) { switch (opt) { case 'M': no_msr = 1; break; + case 'P': + no_perf = 1; + break; default: break; } @@ -6828,6 +6843,7 @@ void cmdline(int argc, char **argv) quiet = 1; break; case 'M': + case 'P': /* Parsed earlier */ break; case 'n': @@ -6909,6 +6925,9 @@ skip_cgroup_setting: if (no_msr) bic_disable_msr_access(); + if (no_perf) + bic_disable_perf_access(); + if (!quiet) { print_version(); print_bootcmd(); -- cgit v1.2.3 From e48934c9f1048ed4640b60321baf1986d1a470e1 Mon Sep 17 00:00:00 2001 From: Patryk Wlazlyn Date: Thu, 11 Jan 2024 16:42:22 +0100 Subject: tools/power turbostat: Add reading aperf and mperf via perf API By using the perf API we spend less time in between the reads of the counters, resulting in more accurate calculations of the dependent metrics. Using perf API is also usually faster overall, although cache miss, if we get one, is more costly when using perf vs MSR driver. We would fallback to the msr reads if the sysfs isn't there or when in --no-perf mode. Signed-off-by: Patryk Wlazlyn Signed-off-by: Len Brown --- tools/power/x86/turbostat/turbostat.c | 374 +++++++++++++++++++++++++++------- 1 file changed, 301 insertions(+), 73 deletions(-) diff --git a/tools/power/x86/turbostat/turbostat.c b/tools/power/x86/turbostat/turbostat.c index bad2fec7f342..1294c46c2170 100644 --- a/tools/power/x86/turbostat/turbostat.c +++ b/tools/power/x86/turbostat/turbostat.c @@ -59,6 +59,7 @@ enum counter_scope { SCOPE_CPU, SCOPE_CORE, SCOPE_PACKAGE }; enum counter_type { COUNTER_ITEMS, COUNTER_CYCLES, COUNTER_SECONDS, COUNTER_USEC }; enum counter_format { FORMAT_RAW, FORMAT_DELTA, FORMAT_PERCENT }; +enum amperf_source { AMPERF_SOURCE_PERF, AMPERF_SOURCE_MSR }; struct msr_counter { unsigned int msr_num; @@ -207,10 +208,13 @@ unsigned long long bic_present = BIC_USEC | BIC_TOD | BIC_sysfs | BIC_APIC | BIC #define BIC_NOT_PRESENT(COUNTER_BIT) (bic_present &= ~COUNTER_BIT) #define BIC_IS_ENABLED(COUNTER_BIT) (bic_enabled & COUNTER_BIT) +struct amperf_group_fd; + char *proc_stat = "/proc/stat"; FILE *outf; int *fd_percpu; int *fd_instr_count_percpu; +struct amperf_group_fd *fd_amperf_percpu; /* File descriptors for perf group with APERF and MPERF counters. */ struct timeval interval_tv = { 5, 0 }; struct timespec interval_ts = { 5, 0 }; @@ -268,6 +272,7 @@ unsigned int first_counter_read = 1; int ignore_stdin; bool no_msr; bool no_perf; +enum amperf_source amperf_source; int get_msr(int cpu, off_t offset, unsigned long long *msr); @@ -1296,9 +1301,6 @@ int get_msr_fd(int cpu) static void bic_disable_msr_access(void) { const unsigned long bic_msrs = - BIC_Avg_MHz | - BIC_Busy | - BIC_Bzy_MHz | BIC_SMI | BIC_CPU_c1 | BIC_CPU_c3 | @@ -1329,21 +1331,30 @@ static long perf_event_open(struct perf_event_attr *hw_event, pid_t pid, int cpu return syscall(__NR_perf_event_open, hw_event, pid, cpu, group_fd, flags); } -static int perf_instr_count_open(int cpu_num) +static long open_perf_counter_or_fail(int cpu, unsigned int type, unsigned int config, int group_fd, __u64 read_format) { - struct perf_event_attr pea; - int fd; + struct perf_event_attr attr; + const pid_t pid = -1; + const unsigned long flags = 0; + + memset(&attr, 0, sizeof(struct perf_event_attr)); - memset(&pea, 0, sizeof(struct perf_event_attr)); - pea.type = PERF_TYPE_HARDWARE; - pea.size = sizeof(struct perf_event_attr); - pea.config = PERF_COUNT_HW_INSTRUCTIONS; + attr.type = type; + attr.size = sizeof(struct perf_event_attr); + attr.config = config; + attr.disabled = 0; + attr.sample_type = PERF_SAMPLE_IDENTIFIER; + attr.read_format = read_format; - /* counter for cpu_num, including user + kernel and all processes */ - fd = perf_event_open(&pea, -1, cpu_num, -1, 0); + const int fd = perf_event_open(&attr, pid, cpu, group_fd, flags); if (fd == -1) { - warnx("capget(CAP_PERFMON) failed, try \"# setcap cap_sys_admin=ep %s\" or use --no-perf", progname); - bic_disable_perf_access(); + if (errno == EACCES) { + errx(1, "capget(CAP_PERFMON) failed, try \"# setcap cap_sys_admin=ep %s\"" + " or use --no-perf or run as root", progname); + } else { + perror("perf_event_open"); + errx(1, "use --no-perf or run as root"); + } } return fd; @@ -1354,7 +1365,8 @@ int get_instr_count_fd(int cpu) if (fd_instr_count_percpu[cpu]) return fd_instr_count_percpu[cpu]; - fd_instr_count_percpu[cpu] = perf_instr_count_open(cpu); + fd_instr_count_percpu[cpu] = + open_perf_counter_or_fail(cpu, PERF_TYPE_HARDWARE, PERF_COUNT_HW_INSTRUCTIONS, -1, 0); return fd_instr_count_percpu[cpu]; } @@ -2762,6 +2774,175 @@ int get_core_throt_cnt(int cpu, unsigned long long *cnt) return 0; } +struct amperf_group_fd { + int aperf; /* Also the group descriptor */ + int mperf; +}; + +static unsigned int read_perf_counter_info(const char *const path, const char *const parse_format) +{ + int fdmt; + char buf[16]; + unsigned int v; + + fdmt = open(path, O_RDONLY, 0); + if (fdmt == -1) + errx(1, "Failed to read perf counter info %s\n", path); + + if (read(fdmt, buf, sizeof(buf)) <= 0) + return 0; + + buf[sizeof(buf) - 1] = '\0'; + + if (sscanf(buf, parse_format, &v) != 1) + errx(1, "Failed to parse perf counter info %s\n", path); + + close(fdmt); + + return v; +} + +static unsigned read_msr_type(void) +{ + const char *const path = "/sys/bus/event_source/devices/msr/type"; + const char *const format = "%u"; + + return read_perf_counter_info(path, format); +} + +static unsigned read_aperf_config(void) +{ + const char *const path = "/sys/bus/event_source/devices/msr/events/aperf"; + const char *const format = "event=%x"; + + return read_perf_counter_info(path, format); +} + +static unsigned read_mperf_config(void) +{ + const char *const path = "/sys/bus/event_source/devices/msr/events/mperf"; + const char *const format = "event=%x"; + + return read_perf_counter_info(path, format); +} + +static struct amperf_group_fd open_amperf_fd(int cpu) +{ + const unsigned int msr_type = read_msr_type(); + const unsigned int aperf_config = read_aperf_config(); + const unsigned int mperf_config = read_mperf_config(); + struct amperf_group_fd fds = {.aperf = -1,.mperf = -1 }; + + fds.aperf = open_perf_counter_or_fail(cpu, msr_type, aperf_config, -1, PERF_FORMAT_GROUP); + fds.mperf = open_perf_counter_or_fail(cpu, msr_type, mperf_config, fds.aperf, PERF_FORMAT_GROUP); + + return fds; +} + +static int get_amperf_fd(int cpu) +{ + assert(fd_amperf_percpu); + + if (fd_amperf_percpu[cpu].aperf) + return fd_amperf_percpu[cpu].aperf; + + fd_amperf_percpu[cpu] = open_amperf_fd(cpu); + + return fd_amperf_percpu[cpu].aperf; +} + +/* Read APERF, MPERF and TSC using the perf API. */ +static int read_aperf_mperf_tsc_perf(struct thread_data *t, int cpu) +{ + union { + struct { + unsigned long nr_entries; + unsigned long aperf; + unsigned long mperf; + }; + + unsigned long as_array[3]; + } cnt; + + const int fd_amperf = get_amperf_fd(cpu); + + /* + * Read the TSC with rdtsc, because we want the absolute value and not + * the offset from the start of the counter. + */ + t->tsc = rdtsc(); + + const int n = read(fd_amperf, &cnt.as_array[0], sizeof(cnt.as_array)); + if (n != sizeof(cnt.as_array)) + return -2; + + t->aperf = cnt.aperf * aperf_mperf_multiplier; + t->mperf = cnt.mperf * aperf_mperf_multiplier; + + return 0; +} + +/* Read APERF, MPERF and TSC using the MSR driver and rdtsc instruction. */ +static int read_aperf_mperf_tsc_msr(struct thread_data *t, int cpu) +{ + unsigned long long tsc_before, tsc_between, tsc_after, aperf_time, mperf_time; + int aperf_mperf_retry_count = 0; + + /* + * The TSC, APERF and MPERF must be read together for + * APERF/MPERF and MPERF/TSC to give accurate results. + * + * Unfortunately, APERF and MPERF are read by + * individual system call, so delays may occur + * between them. If the time to read them + * varies by a large amount, we re-read them. + */ + + /* + * This initial dummy APERF read has been seen to + * reduce jitter in the subsequent reads. + */ + + if (get_msr(cpu, MSR_IA32_APERF, &t->aperf)) + return -3; + +retry: + t->tsc = rdtsc(); /* re-read close to APERF */ + + tsc_before = t->tsc; + + if (get_msr(cpu, MSR_IA32_APERF, &t->aperf)) + return -3; + + tsc_between = rdtsc(); + + if (get_msr(cpu, MSR_IA32_MPERF, &t->mperf)) + return -4; + + tsc_after = rdtsc(); + + aperf_time = tsc_between - tsc_before; + mperf_time = tsc_after - tsc_between; + + /* + * If the system call latency to read APERF and MPERF + * differ by more than 2x, then try again. + */ + if ((aperf_time > (2 * mperf_time)) || (mperf_time > (2 * aperf_time))) { + aperf_mperf_retry_count++; + if (aperf_mperf_retry_count < 5) + goto retry; + else + warnx("cpu%d jitter %lld %lld", cpu, aperf_time, mperf_time); + } + aperf_mperf_retry_count = 0; + + t->aperf = t->aperf * aperf_mperf_multiplier; + t->mperf = t->mperf * aperf_mperf_multiplier; + + return 0; +} + /* * get_counters(...) * migrate to cpu @@ -2771,7 +2952,6 @@ int get_counters(struct thread_data *t, struct core_data *c, struct pkg_data *p) { int cpu = t->cpu_id; unsigned long long msr; - int aperf_mperf_retry_count = 0; struct msr_counter *mp; int i; @@ -2784,63 +2964,26 @@ int get_counters(struct thread_data *t, struct core_data *c, struct pkg_data *p) if (first_counter_read) get_apic_id(t); -retry: + t->tsc = rdtsc(); /* we are running on local CPU of interest */ if (DO_BIC(BIC_Avg_MHz) || DO_BIC(BIC_Busy) || DO_BIC(BIC_Bzy_MHz) || DO_BIC(BIC_IPC) || soft_c1_residency_display(BIC_Avg_MHz)) { - unsigned long long tsc_before, tsc_between, tsc_after, aperf_time, mperf_time; - - /* - * The TSC, APERF and MPERF must be read together for - * APERF/MPERF and MPERF/TSC to give accurate results. - * - * Unfortunately, APERF and MPERF are read by - * individual system call, so delays may occur - * between them. If the time to read them - * varies by a large amount, we re-read them. - */ - - /* - * This initial dummy APERF read has been seen to - * reduce jitter in the subsequent reads. - */ - - if (get_msr(cpu, MSR_IA32_APERF, &t->aperf)) - return -3; - - t->tsc = rdtsc(); /* re-read close to APERF */ - - tsc_before = t->tsc; - - if (get_msr(cpu, MSR_IA32_APERF, &t->aperf)) - return -3; - - tsc_between = rdtsc(); - - if (get_msr(cpu, MSR_IA32_MPERF, &t->mperf)) - return -4; + int status = -1; - tsc_after = rdtsc(); + assert(!no_perf || !no_msr); - aperf_time = tsc_between - tsc_before; - mperf_time = tsc_after - tsc_between; - - /* - * If the system call latency to read APERF and MPERF - * differ by more than 2x, then try again. - */ - if ((aperf_time > (2 * mperf_time)) || (mperf_time > (2 * aperf_time))) { - aperf_mperf_retry_count++; - if (aperf_mperf_retry_count < 5) - goto retry; - else - warnx("cpu%d jitter %lld %lld", cpu, aperf_time, mperf_time); + switch (amperf_source) { + case AMPERF_SOURCE_PERF: + status = read_aperf_mperf_tsc_perf(t, cpu); + break; + case AMPERF_SOURCE_MSR: + status = read_aperf_mperf_tsc_msr(t, cpu); + break; } - aperf_mperf_retry_count = 0; - t->aperf = t->aperf * aperf_mperf_multiplier; - t->mperf = t->mperf * aperf_mperf_multiplier; + if (status != 0) + return status; } if (DO_BIC(BIC_IPC)) @@ -3516,6 +3659,21 @@ void free_fd_percpu(void) free(fd_percpu); } +void free_fd_amperf_percpu(void) +{ + int i; + + for (i = 0; i < topo.max_cpu_num + 1; ++i) { + if (fd_amperf_percpu[i].mperf != 0) + close(fd_amperf_percpu[i].mperf); + + if (fd_amperf_percpu[i].aperf != 0) + close(fd_amperf_percpu[i].aperf); + } + + free(fd_amperf_percpu); +} + void free_all_buffers(void) { int i; @@ -3557,6 +3715,7 @@ void free_all_buffers(void) outp = NULL; free_fd_percpu(); + free_fd_amperf_percpu(); free(irq_column_2_cpu); free(irqs_per_cpu); @@ -5647,17 +5806,62 @@ void print_dev_latency(void) */ void linux_perf_init(void) { - if (!BIC_IS_ENABLED(BIC_IPC)) - return; - if (access("/proc/sys/kernel/perf_event_paranoid", F_OK)) return; - fd_instr_count_percpu = calloc(topo.max_cpu_num + 1, sizeof(int)); - if (fd_instr_count_percpu == NULL) - err(-1, "calloc fd_instr_count_percpu"); + if (BIC_IS_ENABLED(BIC_IPC) && has_aperf) { + fd_instr_count_percpu = calloc(topo.max_cpu_num + 1, sizeof(int)); + if (fd_instr_count_percpu == NULL) + err(-1, "calloc fd_instr_count_percpu"); + } - BIC_PRESENT(BIC_IPC); + const bool aperf_required = BIC_IS_ENABLED(BIC_Avg_MHz) || BIC_IS_ENABLED(BIC_Busy) || + BIC_IS_ENABLED(BIC_Bzy_MHz) || BIC_IS_ENABLED(BIC_IPC); + if (aperf_required && has_aperf && amperf_source == AMPERF_SOURCE_PERF) { + fd_amperf_percpu = calloc(topo.max_cpu_num + 1, sizeof(*fd_amperf_percpu)); + if (fd_amperf_percpu == NULL) + err(-1, "calloc fd_amperf_percpu"); + } +} + +static int has_amperf_access_via_msr(void) +{ + const int cpu = sched_getcpu(); + unsigned long long dummy; + + if (get_msr(cpu, MSR_IA32_APERF, &dummy)) + return 0; + + if (get_msr(cpu, MSR_IA32_MPERF, &dummy)) + return 0; + + return 1; +} + +static int has_amperf_access_via_perf(void) +{ + if (access("/sys/bus/event_source/devices/msr/type", F_OK)) + return 0; + + if (access("/sys/bus/event_source/devices/msr/events/aperf", F_OK)) + return 0; + + if (access("/sys/bus/event_source/devices/msr/events/mperf", F_OK)) + return 0; + + return 1; +} + +/* Check if we can access APERF and MPERF */ +static int has_amperf_access(void) +{ + if (!no_msr && has_amperf_access_via_msr()) + return 1; + + if (!no_perf && has_amperf_access_via_perf()) + return 1; + + return 0; } void probe_cstates(void) @@ -5845,10 +6049,11 @@ void process_cpuid() __cpuid(0x6, eax, ebx, ecx, edx); has_aperf = ecx & (1 << 0); - if (has_aperf) { + if (has_aperf && has_amperf_access()) { BIC_PRESENT(BIC_Avg_MHz); BIC_PRESENT(BIC_Busy); BIC_PRESENT(BIC_Bzy_MHz); + BIC_PRESENT(BIC_IPC); } do_dts = eax & (1 << 0); if (do_dts) @@ -6324,6 +6529,19 @@ void set_base_cpu(void) err(-ENODEV, "No valid cpus found"); } +static void set_amperf_source(void) +{ + amperf_source = AMPERF_SOURCE_PERF; + + if (no_perf || !has_amperf_access_via_perf()) + amperf_source = AMPERF_SOURCE_MSR; + + if (quiet || !debug) + return; + + fprintf(outf, "aperf/mperf source preference: %s\n", amperf_source == AMPERF_SOURCE_MSR ? "msr" : "perf"); +} + void turbostat_init() { setup_all_buffers(true); @@ -6334,6 +6552,7 @@ void turbostat_init() } process_cpuid(); probe_pm_features(); + set_amperf_source(); linux_perf_init(); for_all_cpus(get_cpu_type, ODD_COUNTERS); @@ -6341,6 +6560,15 @@ void turbostat_init() if (DO_BIC(BIC_IPC)) (void)get_instr_count_fd(base_cpu); + + /* + * If TSC tweak is needed, but couldn't get it, + * disable more BICs, since it can't be reported accurately. + */ + if (platform->enable_tsc_tweak && !has_base_hz) { + bic_enabled &= ~BIC_Busy; + bic_enabled &= ~BIC_Bzy_MHz; + } } int fork_it(char **argv) -- cgit v1.2.3 From 5088741ec805cd249e27c7176ed09bdab164960e Mon Sep 17 00:00:00 2001 From: Patryk Wlazlyn Date: Mon, 15 Jan 2024 19:04:21 +0100 Subject: tools/power turbostat: detect and disable unavailable BICs at runtime To allow unprivileged user to run turbostat seamlessly. Signed-off-by: Patryk Wlazlyn Signed-off-by: Len Brown --- tools/power/x86/turbostat/turbostat.c | 188 ++++++++++++++++++++++------------ 1 file changed, 125 insertions(+), 63 deletions(-) diff --git a/tools/power/x86/turbostat/turbostat.c b/tools/power/x86/turbostat/turbostat.c index 1294c46c2170..30db6e92193a 100644 --- a/tools/power/x86/turbostat/turbostat.c +++ b/tools/power/x86/turbostat/turbostat.c @@ -1317,13 +1317,6 @@ static void bic_disable_msr_access(void) bic_enabled &= ~bic_msrs; } -static void bic_disable_perf_access(void) -{ - const unsigned long bic_perf = BIC_IPC; - - bic_enabled &= ~bic_perf; -} - static long perf_event_open(struct perf_event_attr *hw_event, pid_t pid, int cpu, int group_fd, unsigned long flags) { assert(!no_perf); @@ -1331,12 +1324,14 @@ static long perf_event_open(struct perf_event_attr *hw_event, pid_t pid, int cpu return syscall(__NR_perf_event_open, hw_event, pid, cpu, group_fd, flags); } -static long open_perf_counter_or_fail(int cpu, unsigned int type, unsigned int config, int group_fd, __u64 read_format) +static long open_perf_counter(int cpu, unsigned int type, unsigned int config, int group_fd, __u64 read_format) { struct perf_event_attr attr; const pid_t pid = -1; const unsigned long flags = 0; + assert(!no_perf); + memset(&attr, 0, sizeof(struct perf_event_attr)); attr.type = type; @@ -1347,15 +1342,6 @@ static long open_perf_counter_or_fail(int cpu, unsigned int type, unsigned int c attr.read_format = read_format; const int fd = perf_event_open(&attr, pid, cpu, group_fd, flags); - if (fd == -1) { - if (errno == EACCES) { - errx(1, "capget(CAP_PERFMON) failed, try \"# setcap cap_sys_admin=ep %s\"" - " or use --no-perf or run as root", progname); - } else { - perror("perf_event_open"); - errx(1, "use --no-perf or run as root"); - } - } return fd; } @@ -1365,8 +1351,7 @@ int get_instr_count_fd(int cpu) if (fd_instr_count_percpu[cpu]) return fd_instr_count_percpu[cpu]; - fd_instr_count_percpu[cpu] = - open_perf_counter_or_fail(cpu, PERF_TYPE_HARDWARE, PERF_COUNT_HW_INSTRUCTIONS, -1, 0); + fd_instr_count_percpu[cpu] = open_perf_counter(cpu, PERF_TYPE_HARDWARE, PERF_COUNT_HW_INSTRUCTIONS, -1, 0); return fd_instr_count_percpu[cpu]; } @@ -2833,8 +2818,8 @@ static struct amperf_group_fd open_amperf_fd(int cpu) const unsigned int mperf_config = read_mperf_config(); struct amperf_group_fd fds = {.aperf = -1,.mperf = -1 }; - fds.aperf = open_perf_counter_or_fail(cpu, msr_type, aperf_config, -1, PERF_FORMAT_GROUP); - fds.mperf = open_perf_counter_or_fail(cpu, msr_type, mperf_config, fds.aperf, PERF_FORMAT_GROUP); + fds.aperf = open_perf_counter(cpu, msr_type, aperf_config, -1, PERF_FORMAT_GROUP); + fds.mperf = open_perf_counter(cpu, msr_type, mperf_config, fds.aperf, PERF_FORMAT_GROUP); return fds; } @@ -4509,7 +4494,8 @@ release_msr: /* * set_my_sched_priority(pri) - * return previous + * return previous priority on success + * return value < -20 on failure */ int set_my_sched_priority(int priority) { @@ -4519,16 +4505,16 @@ int set_my_sched_priority(int priority) errno = 0; original_priority = getpriority(PRIO_PROCESS, 0); if (errno && (original_priority == -1)) - err(errno, "getpriority"); + return -21; retval = setpriority(PRIO_PROCESS, 0, priority); if (retval) - errx(retval, "capget(CAP_SYS_NICE) failed,try \"# setcap cap_sys_nice=ep %s\"", progname); + return -21; errno = 0; retval = getpriority(PRIO_PROCESS, 0); if (retval != priority) - err(retval, "getpriority(%d) != setpriority(%d)", retval, priority); + return -21; return original_priority; } @@ -4543,6 +4529,9 @@ void turbostat_loop() /* * elevate own priority for interval mode + * + * ignore on error - we probably don't have permission to set it, but + * it's not a big deal */ set_my_sched_priority(-20); @@ -4628,10 +4617,13 @@ void check_dev_msr() struct stat sb; char pathname[32]; + if (no_msr) + return; + sprintf(pathname, "/dev/cpu/%d/msr", base_cpu); if (stat(pathname, &sb)) if (system("/sbin/modprobe msr > /dev/null 2>&1")) - err(-5, "no /dev/cpu/0/msr, Try \"# modprobe msr\" "); + no_msr = 1; } /* @@ -4643,47 +4635,51 @@ int check_for_cap_sys_rawio(void) { cap_t caps; cap_flag_value_t cap_flag_value; + int ret = 0; caps = cap_get_proc(); if (caps == NULL) - err(-6, "cap_get_proc\n"); + return 1; - if (cap_get_flag(caps, CAP_SYS_RAWIO, CAP_EFFECTIVE, &cap_flag_value)) - err(-6, "cap_get\n"); + if (cap_get_flag(caps, CAP_SYS_RAWIO, CAP_EFFECTIVE, &cap_flag_value)) { + ret = 1; + goto free_and_exit; + } if (cap_flag_value != CAP_SET) { - warnx("capget(CAP_SYS_RAWIO) failed," " try \"# setcap cap_sys_rawio=ep %s\"", progname); - return 1; + ret = 1; + goto free_and_exit; } +free_and_exit: if (cap_free(caps) == -1) err(-6, "cap_free\n"); - return 0; + return ret; } -void check_permissions(void) +void check_msr_permission(void) { - int do_exit = 0; + int failed = 0; char pathname[32]; + if (no_msr) + return; + /* check for CAP_SYS_RAWIO */ - do_exit += check_for_cap_sys_rawio(); + failed += check_for_cap_sys_rawio(); /* test file permissions */ sprintf(pathname, "/dev/cpu/%d/msr", base_cpu); if (euidaccess(pathname, R_OK)) { - do_exit++; - warn("/dev/cpu/0/msr open failed, try chown or chmod +r /dev/cpu/*/msr, or run with --no-msr"); + failed++; } - /* if all else fails, thell them to be root */ - if (do_exit) - if (getuid() != 0) - warnx("... or simply run as root"); - - if (do_exit) - exit(-6); + if (failed) { + warnx("Failed to access %s. Some of the counters may not be available\n" + "\tRun as root to enable them or use %s to disable the access explicitly", pathname, "--no-msr"); + no_msr = 1; + } } void probe_bclk(void) @@ -5800,6 +5796,28 @@ void print_dev_latency(void) close(fd); } +static int has_instr_count_access(void) +{ + int fd; + int has_access; + + if (no_perf) + return 0; + + fd = open_perf_counter(base_cpu, PERF_TYPE_HARDWARE, PERF_COUNT_HW_INSTRUCTIONS, -1, 0); + has_access = fd != -1; + + if (fd != -1) + close(fd); + + if (!has_access) + warnx("Failed to access %s. Some of the counters may not be available\n" + "\tRun as root to enable them or use %s to disable the access explicitly", + "instructions retired perf counter", "--no-perf"); + + return has_access; +} + /* * Linux-perf manages the HW instructions-retired counter * by enabling when requested, and hiding rollover @@ -5826,13 +5844,15 @@ void linux_perf_init(void) static int has_amperf_access_via_msr(void) { - const int cpu = sched_getcpu(); unsigned long long dummy; - if (get_msr(cpu, MSR_IA32_APERF, &dummy)) + if (no_msr) + return 0; + + if (get_msr(base_cpu, MSR_IA32_APERF, &dummy)) return 0; - if (get_msr(cpu, MSR_IA32_MPERF, &dummy)) + if (get_msr(base_cpu, MSR_IA32_MPERF, &dummy)) return 0; return 1; @@ -5840,16 +5860,44 @@ static int has_amperf_access_via_msr(void) static int has_amperf_access_via_perf(void) { - if (access("/sys/bus/event_source/devices/msr/type", F_OK)) - return 0; + struct amperf_group_fd fds; - if (access("/sys/bus/event_source/devices/msr/events/aperf", F_OK)) - return 0; + /* + * Cache the last result, so we don't warn the user multiple times + * + * Negative means cached, no access + * Zero means not cached + * Positive means cached, has access + */ + static int has_access_cached; - if (access("/sys/bus/event_source/devices/msr/events/mperf", F_OK)) + if (no_perf) return 0; - return 1; + if (has_access_cached != 0) + return has_access_cached > 0; + + fds = open_amperf_fd(base_cpu); + has_access_cached = (fds.aperf != -1) && (fds.mperf != -1); + + if (fds.aperf == -1) + warnx("Failed to access %s. Some of the counters may not be available\n" + "\tRun as root to enable them or use %s to disable the access explicitly", + "APERF perf counter", "--no-perf"); + else + close(fds.aperf); + + if (fds.mperf == -1) + warnx("Failed to access %s. Some of the counters may not be available\n" + "\tRun as root to enable them or use %s to disable the access explicitly", + "MPERF perf counter", "--no-perf"); + else + close(fds.mperf); + + if (has_access_cached == 0) + has_access_cached = -1; + + return has_access_cached > 0; } /* Check if we can access APERF and MPERF */ @@ -6542,14 +6590,34 @@ static void set_amperf_source(void) fprintf(outf, "aperf/mperf source preference: %s\n", amperf_source == AMPERF_SOURCE_MSR ? "msr" : "perf"); } +void check_msr_access(void) +{ + check_dev_msr(); + check_msr_permission(); + + if (no_msr) + bic_disable_msr_access(); +} + +void check_perf_access(void) +{ + if (no_perf || !has_instr_count_access()) + bic_enabled &= ~BIC_IPC; + + if (!has_amperf_access()) { + bic_enabled &= ~BIC_Avg_MHz; + bic_enabled &= ~BIC_Busy; + bic_enabled &= ~BIC_Bzy_MHz; + bic_enabled &= ~BIC_IPC; + } +} + void turbostat_init() { setup_all_buffers(true); set_base_cpu(); - if (!no_msr) { - check_dev_msr(); - check_permissions(); - } + check_msr_access(); + check_perf_access(); process_cpuid(); probe_pm_features(); set_amperf_source(); @@ -7150,12 +7218,6 @@ skip_cgroup_setting: outf = stderr; cmdline(argc, argv); - if (no_msr) - bic_disable_msr_access(); - - if (no_perf) - bic_disable_perf_access(); - if (!quiet) { print_version(); print_bootcmd(); -- cgit v1.2.3 From aed48c48fa65abdd584e14f7d0273711bc10d223 Mon Sep 17 00:00:00 2001 From: Patryk Wlazlyn Date: Tue, 30 Jan 2024 23:57:07 +0100 Subject: tools/power turbostat: add early exits for permission checks Checking early if the permissions are even needed gets rid of the warnings about some of them missing. Earlier we issued a warning in case of missing MSR and/or perf permissions, even when user never asked for counters that require those. Signed-off-by: Patryk Wlazlyn Signed-off-by: Len Brown --- tools/power/x86/turbostat/turbostat.c | 66 ++++++++++++++++++++++++++++++++--- 1 file changed, 61 insertions(+), 5 deletions(-) diff --git a/tools/power/x86/turbostat/turbostat.c b/tools/power/x86/turbostat/turbostat.c index 30db6e92193a..e5e01b58992e 100644 --- a/tools/power/x86/turbostat/turbostat.c +++ b/tools/power/x86/turbostat/turbostat.c @@ -5818,6 +5818,14 @@ static int has_instr_count_access(void) return has_access; } +bool is_aperf_access_required(void) +{ + return BIC_IS_ENABLED(BIC_Avg_MHz) + || BIC_IS_ENABLED(BIC_Busy) + || BIC_IS_ENABLED(BIC_Bzy_MHz) + || BIC_IS_ENABLED(BIC_IPC); +} + /* * Linux-perf manages the HW instructions-retired counter * by enabling when requested, and hiding rollover @@ -5833,8 +5841,7 @@ void linux_perf_init(void) err(-1, "calloc fd_instr_count_percpu"); } - const bool aperf_required = BIC_IS_ENABLED(BIC_Avg_MHz) || BIC_IS_ENABLED(BIC_Busy) || - BIC_IS_ENABLED(BIC_Bzy_MHz) || BIC_IS_ENABLED(BIC_IPC); + const bool aperf_required = is_aperf_access_required(); if (aperf_required && has_aperf && amperf_source == AMPERF_SOURCE_PERF) { fd_amperf_percpu = calloc(topo.max_cpu_num + 1, sizeof(*fd_amperf_percpu)); if (fd_amperf_percpu == NULL) @@ -5903,6 +5910,9 @@ static int has_amperf_access_via_perf(void) /* Check if we can access APERF and MPERF */ static int has_amperf_access(void) { + if (!is_aperf_access_required()) + return 0; + if (!no_msr && has_amperf_access_via_msr()) return 1; @@ -6581,7 +6591,8 @@ static void set_amperf_source(void) { amperf_source = AMPERF_SOURCE_PERF; - if (no_perf || !has_amperf_access_via_perf()) + const bool aperf_required = is_aperf_access_required(); + if (no_perf || !aperf_required || !has_amperf_access_via_perf()) amperf_source = AMPERF_SOURCE_MSR; if (quiet || !debug) @@ -6590,8 +6601,51 @@ static void set_amperf_source(void) fprintf(outf, "aperf/mperf source preference: %s\n", amperf_source == AMPERF_SOURCE_MSR ? "msr" : "perf"); } +bool is_msr_access_required(void) +{ + /* TODO: add detection for dynamic counters from add_counter() */ + if (no_msr) + return false; + + return BIC_IS_ENABLED(BIC_SMI) + || BIC_IS_ENABLED(BIC_CPU_c1) + || BIC_IS_ENABLED(BIC_CPU_c3) + || BIC_IS_ENABLED(BIC_CPU_c6) + || BIC_IS_ENABLED(BIC_CPU_c7) + || BIC_IS_ENABLED(BIC_Mod_c6) + || BIC_IS_ENABLED(BIC_CoreTmp) + || BIC_IS_ENABLED(BIC_Totl_c0) + || BIC_IS_ENABLED(BIC_Any_c0) + || BIC_IS_ENABLED(BIC_GFX_c0) + || BIC_IS_ENABLED(BIC_CPUGFX) + || BIC_IS_ENABLED(BIC_Pkgpc3) + || BIC_IS_ENABLED(BIC_Pkgpc6) + || BIC_IS_ENABLED(BIC_Pkgpc2) + || BIC_IS_ENABLED(BIC_Pkgpc7) + || BIC_IS_ENABLED(BIC_Pkgpc8) + || BIC_IS_ENABLED(BIC_Pkgpc9) + || BIC_IS_ENABLED(BIC_Pkgpc10) + || BIC_IS_ENABLED(BIC_CorWatt) + || BIC_IS_ENABLED(BIC_Cor_J) + || BIC_IS_ENABLED(BIC_PkgWatt) + || BIC_IS_ENABLED(BIC_CorWatt) + || BIC_IS_ENABLED(BIC_GFXWatt) + || BIC_IS_ENABLED(BIC_RAMWatt) + || BIC_IS_ENABLED(BIC_Pkg_J) + || BIC_IS_ENABLED(BIC_Cor_J) + || BIC_IS_ENABLED(BIC_GFX_J) + || BIC_IS_ENABLED(BIC_RAM_J) + || BIC_IS_ENABLED(BIC_PKG__) + || BIC_IS_ENABLED(BIC_RAM__) + || BIC_IS_ENABLED(BIC_PkgTmp) + || (is_aperf_access_required() && !has_amperf_access_via_perf()); +} + void check_msr_access(void) { + if (!is_msr_access_required()) + no_msr = 1; + check_dev_msr(); check_msr_permission(); @@ -6601,10 +6655,12 @@ void check_msr_access(void) void check_perf_access(void) { - if (no_perf || !has_instr_count_access()) + const bool intrcount_required = BIC_IS_ENABLED(BIC_IPC); + if (no_perf || !intrcount_required || !has_instr_count_access()) bic_enabled &= ~BIC_IPC; - if (!has_amperf_access()) { + const bool aperf_required = is_aperf_access_required(); + if (!aperf_required || !has_amperf_access()) { bic_enabled &= ~BIC_Avg_MHz; bic_enabled &= ~BIC_Busy; bic_enabled &= ~BIC_Bzy_MHz; -- cgit v1.2.3 From 4a1bb4dad5d16669e841410944e7bc84ef7263fc Mon Sep 17 00:00:00 2001 From: Patryk Wlazlyn Date: Thu, 14 Mar 2024 11:36:55 +0100 Subject: tools/power turbostat: Clear added counters when in no-msr mode If user request --no-msr or is not able to access the MSRs, turbostat should clear all the counters added with --add. Because MSR access permission checks are done after the cmdline is parsed, the decision has to be defered up until the transition into no-msr mode happen. Signed-off-by: Len Brown --- tools/power/x86/turbostat/turbostat.c | 47 ++++++++++++++++++++++++++++++++++- 1 file changed, 46 insertions(+), 1 deletion(-) diff --git a/tools/power/x86/turbostat/turbostat.c b/tools/power/x86/turbostat/turbostat.c index e5e01b58992e..b4a892bf22bf 100644 --- a/tools/power/x86/turbostat/turbostat.c +++ b/tools/power/x86/turbostat/turbostat.c @@ -1160,6 +1160,37 @@ struct sys_counters { struct msr_counter *pp; } sys; +void free_sys_counters(void) +{ + struct msr_counter *p = sys.tp, *pnext = NULL; + while (p) { + pnext = p->next; + free(p); + p = pnext; + } + + p = sys.cp, pnext = NULL; + while (p) { + pnext = p->next; + free(p); + p = pnext; + } + + p = sys.pp, pnext = NULL; + while (p) { + pnext = p->next; + free(p); + p = pnext; + } + + sys.added_thread_counters = 0; + sys.added_core_counters = 0; + sys.added_package_counters = 0; + sys.tp = NULL; + sys.cp = NULL; + sys.pp = NULL; +} + struct system_summary { struct thread_data threads; struct core_data cores; @@ -1315,6 +1346,8 @@ static void bic_disable_msr_access(void) BIC_Pkgpc2 | BIC_Pkgpc3 | BIC_Pkgpc6 | BIC_Pkgpc7 | BIC_Pkgpc8 | BIC_Pkgpc9 | BIC_Pkgpc10 | BIC_PkgTmp; bic_enabled &= ~bic_msrs; + + free_sys_counters(); } static long perf_event_open(struct perf_event_attr *hw_event, pid_t pid, int cpu, int group_fd, unsigned long flags) @@ -6601,12 +6634,24 @@ static void set_amperf_source(void) fprintf(outf, "aperf/mperf source preference: %s\n", amperf_source == AMPERF_SOURCE_MSR ? "msr" : "perf"); } +bool has_added_counters(void) +{ + /* + * It only makes sense to call this after the command line is parsed, + * otherwise sys structure is not populated. + */ + + return sys.added_core_counters | sys.added_thread_counters | sys.added_package_counters; +} + bool is_msr_access_required(void) { - /* TODO: add detection for dynamic counters from add_counter() */ if (no_msr) return false; + if (has_added_counters()) + return true; + return BIC_IS_ENABLED(BIC_SMI) || BIC_IS_ENABLED(BIC_CPU_c1) || BIC_IS_ENABLED(BIC_CPU_c3) -- cgit v1.2.3 From ebf8449caba1df2eb6ba0b465fe15dc06d3b9135 Mon Sep 17 00:00:00 2001 From: Patryk Wlazlyn Date: Thu, 15 Feb 2024 12:50:19 +0100 Subject: tools/power turbostat: Add proper re-initialization for perf file descriptors Signed-off-by: Patryk Wlazlyn Signed-off-by: Len Brown --- tools/power/x86/turbostat/turbostat.c | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/tools/power/x86/turbostat/turbostat.c b/tools/power/x86/turbostat/turbostat.c index b4a892bf22bf..a380829c5890 100644 --- a/tools/power/x86/turbostat/turbostat.c +++ b/tools/power/x86/turbostat/turbostat.c @@ -3669,18 +3669,25 @@ void free_fd_percpu(void) { int i; + if (!fd_percpu) + return; + for (i = 0; i < topo.max_cpu_num + 1; ++i) { if (fd_percpu[i] != 0) close(fd_percpu[i]); } free(fd_percpu); + fd_percpu = NULL; } void free_fd_amperf_percpu(void) { int i; + if (!fd_amperf_percpu) + return; + for (i = 0; i < topo.max_cpu_num + 1; ++i) { if (fd_amperf_percpu[i].mperf != 0) close(fd_amperf_percpu[i].mperf); @@ -3690,6 +3697,21 @@ void free_fd_amperf_percpu(void) } free(fd_amperf_percpu); + fd_amperf_percpu = NULL; +} + +void free_fd_instr_count_percpu(void) +{ + if (!fd_instr_count_percpu) + return; + + for (int i = 0; i < topo.max_cpu_num + 1; ++i) { + if (fd_instr_count_percpu[i] != 0) + close(fd_instr_count_percpu[i]); + } + + free(fd_instr_count_percpu); + fd_instr_count_percpu = NULL; } void free_all_buffers(void) @@ -3733,6 +3755,7 @@ void free_all_buffers(void) outp = NULL; free_fd_percpu(); + free_fd_instr_count_percpu(); free_fd_amperf_percpu(); free(irq_column_2_cpu); @@ -4067,10 +4090,13 @@ static void update_effective_set(bool startup) err(1, "%s: cpu str malformat %s\n", PATH_EFFECTIVE_CPUS, cpu_effective_str); } +void linux_perf_init(void); + void re_initialize(void) { free_all_buffers(); setup_all_buffers(false); + linux_perf_init(); fprintf(outf, "turbostat: re-initialized with num_cpus %d, allowed_cpus %d\n", topo.num_cpus, topo.allowed_cpus); } -- cgit v1.2.3 From 141fb8cd206ace23c02cd2791c6da52c1d77d42a Mon Sep 17 00:00:00 2001 From: Boris Burkov Date: Tue, 19 Mar 2024 10:54:22 -0700 Subject: btrfs: qgroup: correctly model root qgroup rsv in convert We use add_root_meta_rsv and sub_root_meta_rsv to track prealloc and pertrans reservations for subvolumes when quotas are enabled. The convert function does not properly increment pertrans after decrementing prealloc, so the count is not accurate. Note: we check that the fs is not read-only to mirror the logic in qgroup_convert_meta, which checks that before adding to the pertrans rsv. Fixes: 8287475a2055 ("btrfs: qgroup: Use root::qgroup_meta_rsv_* to record qgroup meta reserved space") CC: stable@vger.kernel.org # 6.1+ Reviewed-by: Qu Wenruo Signed-off-by: Boris Burkov Signed-off-by: David Sterba --- fs/btrfs/qgroup.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/fs/btrfs/qgroup.c b/fs/btrfs/qgroup.c index 5f90f0605b12..cf8820ce7aa2 100644 --- a/fs/btrfs/qgroup.c +++ b/fs/btrfs/qgroup.c @@ -4495,6 +4495,8 @@ void btrfs_qgroup_convert_reserved_meta(struct btrfs_root *root, int num_bytes) BTRFS_QGROUP_RSV_META_PREALLOC); trace_qgroup_meta_convert(root, num_bytes); qgroup_convert_meta(fs_info, root->root_key.objectid, num_bytes); + if (!sb_rdonly(fs_info->sb)) + add_root_meta_rsv(root, num_bytes, BTRFS_QGROUP_RSV_META_PERTRANS); } /* -- cgit v1.2.3 From 74e97958121aa1f5854da6effba70143f051b0cd Mon Sep 17 00:00:00 2001 From: Boris Burkov Date: Thu, 21 Mar 2024 10:02:04 -0700 Subject: btrfs: qgroup: fix qgroup prealloc rsv leak in subvolume operations Create subvolume, create snapshot and delete subvolume all use btrfs_subvolume_reserve_metadata() to reserve metadata for the changes done to the parent subvolume's fs tree, which cannot be mediated in the normal way via start_transaction. When quota groups (squota or qgroups) are enabled, this reserves qgroup metadata of type PREALLOC. Once the operation is associated to a transaction, we convert PREALLOC to PERTRANS, which gets cleared in bulk at the end of the transaction. However, the error paths of these three operations were not implementing this lifecycle correctly. They unconditionally converted the PREALLOC to PERTRANS in a generic cleanup step regardless of errors or whether the operation was fully associated to a transaction or not. This resulted in error paths occasionally converting this rsv to PERTRANS without calling record_root_in_trans successfully, which meant that unless that root got recorded in the transaction by some other thread, the end of the transaction would not free that root's PERTRANS, leaking it. Ultimately, this resulted in hitting a WARN in CONFIG_BTRFS_DEBUG builds at unmount for the leaked reservation. The fix is to ensure that every qgroup PREALLOC reservation observes the following properties: 1. any failure before record_root_in_trans is called successfully results in freeing the PREALLOC reservation. 2. after record_root_in_trans, we convert to PERTRANS, and now the transaction owns freeing the reservation. This patch enforces those properties on the three operations. Without it, generic/269 with squotas enabled at mkfs time would fail in ~5-10 runs on my system. With this patch, it ran successfully 1000 times in a row. Fixes: e85fde5162bf ("btrfs: qgroup: fix qgroup meta rsv leak for subvolume operations") CC: stable@vger.kernel.org # 6.1+ Reviewed-by: Qu Wenruo Signed-off-by: Boris Burkov Signed-off-by: David Sterba --- fs/btrfs/inode.c | 13 ++++++++++++- fs/btrfs/ioctl.c | 37 ++++++++++++++++++++++++++++--------- fs/btrfs/root-tree.c | 10 ---------- fs/btrfs/root-tree.h | 2 -- 4 files changed, 40 insertions(+), 22 deletions(-) diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index 37701531eeb1..1f9e74c4161d 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c @@ -4503,6 +4503,7 @@ int btrfs_delete_subvolume(struct btrfs_inode *dir, struct dentry *dentry) struct btrfs_trans_handle *trans; struct btrfs_block_rsv block_rsv; u64 root_flags; + u64 qgroup_reserved = 0; int ret; down_write(&fs_info->subvol_sem); @@ -4547,12 +4548,20 @@ int btrfs_delete_subvolume(struct btrfs_inode *dir, struct dentry *dentry) ret = btrfs_subvolume_reserve_metadata(root, &block_rsv, 5, true); if (ret) goto out_undead; + qgroup_reserved = block_rsv.qgroup_rsv_reserved; trans = btrfs_start_transaction(root, 0); if (IS_ERR(trans)) { ret = PTR_ERR(trans); goto out_release; } + ret = btrfs_record_root_in_trans(trans, root); + if (ret) { + btrfs_abort_transaction(trans, ret); + goto out_end_trans; + } + btrfs_qgroup_convert_reserved_meta(root, qgroup_reserved); + qgroup_reserved = 0; trans->block_rsv = &block_rsv; trans->bytes_reserved = block_rsv.size; @@ -4611,7 +4620,9 @@ out_end_trans: ret = btrfs_end_transaction(trans); inode->i_flags |= S_DEAD; out_release: - btrfs_subvolume_release_metadata(root, &block_rsv); + btrfs_block_rsv_release(fs_info, &block_rsv, (u64)-1, NULL); + if (qgroup_reserved) + btrfs_qgroup_free_meta_prealloc(root, qgroup_reserved); out_undead: if (ret) { spin_lock(&dest->root_item_lock); diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c index 38459a89b27c..5a507237c4fa 100644 --- a/fs/btrfs/ioctl.c +++ b/fs/btrfs/ioctl.c @@ -613,6 +613,7 @@ static noinline int create_subvol(struct mnt_idmap *idmap, int ret; dev_t anon_dev; u64 objectid; + u64 qgroup_reserved = 0; root_item = kzalloc(sizeof(*root_item), GFP_KERNEL); if (!root_item) @@ -650,13 +651,18 @@ static noinline int create_subvol(struct mnt_idmap *idmap, trans_num_items, false); if (ret) goto out_new_inode_args; + qgroup_reserved = block_rsv.qgroup_rsv_reserved; trans = btrfs_start_transaction(root, 0); if (IS_ERR(trans)) { ret = PTR_ERR(trans); - btrfs_subvolume_release_metadata(root, &block_rsv); - goto out_new_inode_args; + goto out_release_rsv; } + ret = btrfs_record_root_in_trans(trans, BTRFS_I(dir)->root); + if (ret) + goto out; + btrfs_qgroup_convert_reserved_meta(root, qgroup_reserved); + qgroup_reserved = 0; trans->block_rsv = &block_rsv; trans->bytes_reserved = block_rsv.size; /* Tree log can't currently deal with an inode which is a new root. */ @@ -767,9 +773,11 @@ static noinline int create_subvol(struct mnt_idmap *idmap, out: trans->block_rsv = NULL; trans->bytes_reserved = 0; - btrfs_subvolume_release_metadata(root, &block_rsv); - btrfs_end_transaction(trans); +out_release_rsv: + btrfs_block_rsv_release(fs_info, &block_rsv, (u64)-1, NULL); + if (qgroup_reserved) + btrfs_qgroup_free_meta_prealloc(root, qgroup_reserved); out_new_inode_args: btrfs_new_inode_args_destroy(&new_inode_args); out_inode: @@ -791,6 +799,8 @@ static int create_snapshot(struct btrfs_root *root, struct inode *dir, struct btrfs_pending_snapshot *pending_snapshot; unsigned int trans_num_items; struct btrfs_trans_handle *trans; + struct btrfs_block_rsv *block_rsv; + u64 qgroup_reserved = 0; int ret; /* We do not support snapshotting right now. */ @@ -827,19 +837,19 @@ static int create_snapshot(struct btrfs_root *root, struct inode *dir, goto free_pending; } - btrfs_init_block_rsv(&pending_snapshot->block_rsv, - BTRFS_BLOCK_RSV_TEMP); + block_rsv = &pending_snapshot->block_rsv; + btrfs_init_block_rsv(block_rsv, BTRFS_BLOCK_RSV_TEMP); /* * 1 to add dir item * 1 to add dir index * 1 to update parent inode item */ trans_num_items = create_subvol_num_items(inherit) + 3; - ret = btrfs_subvolume_reserve_metadata(BTRFS_I(dir)->root, - &pending_snapshot->block_rsv, + ret = btrfs_subvolume_reserve_metadata(BTRFS_I(dir)->root, block_rsv, trans_num_items, false); if (ret) goto free_pending; + qgroup_reserved = block_rsv->qgroup_rsv_reserved; pending_snapshot->dentry = dentry; pending_snapshot->root = root; @@ -852,6 +862,13 @@ static int create_snapshot(struct btrfs_root *root, struct inode *dir, ret = PTR_ERR(trans); goto fail; } + ret = btrfs_record_root_in_trans(trans, BTRFS_I(dir)->root); + if (ret) { + btrfs_end_transaction(trans); + goto fail; + } + btrfs_qgroup_convert_reserved_meta(root, qgroup_reserved); + qgroup_reserved = 0; trans->pending_snapshot = pending_snapshot; @@ -881,7 +898,9 @@ fail: if (ret && pending_snapshot->snap) pending_snapshot->snap->anon_dev = 0; btrfs_put_root(pending_snapshot->snap); - btrfs_subvolume_release_metadata(root, &pending_snapshot->block_rsv); + btrfs_block_rsv_release(fs_info, block_rsv, (u64)-1, NULL); + if (qgroup_reserved) + btrfs_qgroup_free_meta_prealloc(root, qgroup_reserved); free_pending: if (pending_snapshot->anon_dev) free_anon_bdev(pending_snapshot->anon_dev); diff --git a/fs/btrfs/root-tree.c b/fs/btrfs/root-tree.c index 4bb538a372ce..7007f9e0c972 100644 --- a/fs/btrfs/root-tree.c +++ b/fs/btrfs/root-tree.c @@ -548,13 +548,3 @@ int btrfs_subvolume_reserve_metadata(struct btrfs_root *root, } return ret; } - -void btrfs_subvolume_release_metadata(struct btrfs_root *root, - struct btrfs_block_rsv *rsv) -{ - struct btrfs_fs_info *fs_info = root->fs_info; - u64 qgroup_to_release; - - btrfs_block_rsv_release(fs_info, rsv, (u64)-1, &qgroup_to_release); - btrfs_qgroup_convert_reserved_meta(root, qgroup_to_release); -} diff --git a/fs/btrfs/root-tree.h b/fs/btrfs/root-tree.h index 6f929cf3bd49..8f5739e732b9 100644 --- a/fs/btrfs/root-tree.h +++ b/fs/btrfs/root-tree.h @@ -18,8 +18,6 @@ struct btrfs_trans_handle; int btrfs_subvolume_reserve_metadata(struct btrfs_root *root, struct btrfs_block_rsv *rsv, int nitems, bool use_global_rsv); -void btrfs_subvolume_release_metadata(struct btrfs_root *root, - struct btrfs_block_rsv *rsv); int btrfs_add_root_ref(struct btrfs_trans_handle *trans, u64 root_id, u64 ref_id, u64 dirid, u64 sequence, const struct fscrypt_str *name); -- cgit v1.2.3 From 71537e35c324ea6fbd68377a4f26bb93a831ae35 Mon Sep 17 00:00:00 2001 From: Boris Burkov Date: Thu, 21 Mar 2024 10:14:24 -0700 Subject: btrfs: record delayed inode root in transaction When running delayed inode updates, we do not record the inode's root in the transaction, but we do allocate PREALLOC and thus converted PERTRANS space for it. To be sure we free that PERTRANS meta rsv, we must ensure that we record the root in the transaction. Fixes: 4f5427ccce5d ("btrfs: delayed-inode: Use new qgroup meta rsv for delayed inode and item") CC: stable@vger.kernel.org # 6.1+ Reviewed-by: Qu Wenruo Signed-off-by: Boris Burkov Signed-off-by: David Sterba --- fs/btrfs/delayed-inode.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/fs/btrfs/delayed-inode.c b/fs/btrfs/delayed-inode.c index dd6f566a383f..121ab890bd05 100644 --- a/fs/btrfs/delayed-inode.c +++ b/fs/btrfs/delayed-inode.c @@ -1133,6 +1133,9 @@ __btrfs_commit_inode_delayed_items(struct btrfs_trans_handle *trans, if (ret) return ret; + ret = btrfs_record_root_in_trans(trans, node->root); + if (ret) + return ret; ret = btrfs_update_delayed_inode(trans, node->root, path, node); return ret; } -- cgit v1.2.3 From 211de93367304ab395357f8cb12568a4d1e20701 Mon Sep 17 00:00:00 2001 From: Boris Burkov Date: Thu, 21 Mar 2024 10:18:39 -0700 Subject: btrfs: qgroup: convert PREALLOC to PERTRANS after record_root_in_trans The transaction is only able to free PERTRANS reservations for a root once that root has been recorded with the TRANS tag on the roots radix tree. Therefore, until we are sure that this root will get tagged, it isn't safe to convert. Generally, this is not an issue as *some* transaction will likely tag the root before long and this reservation will get freed in that transaction, but technically it could stick around until unmount and result in a warning about leaked metadata reservation space. This path is most exercised by running the generic/269 fstest with CONFIG_BTRFS_DEBUG. Fixes: a6496849671a ("btrfs: fix start transaction qgroup rsv double free") CC: stable@vger.kernel.org # 6.6+ Reviewed-by: Qu Wenruo Signed-off-by: Boris Burkov Signed-off-by: David Sterba --- fs/btrfs/transaction.c | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/fs/btrfs/transaction.c b/fs/btrfs/transaction.c index 46e8426adf4f..1f10082d35d9 100644 --- a/fs/btrfs/transaction.c +++ b/fs/btrfs/transaction.c @@ -745,14 +745,6 @@ again: h->reloc_reserved = reloc_reserved; } - /* - * Now that we have found a transaction to be a part of, convert the - * qgroup reservation from prealloc to pertrans. A different transaction - * can't race in and free our pertrans out from under us. - */ - if (qgroup_reserved) - btrfs_qgroup_convert_reserved_meta(root, qgroup_reserved); - got_it: if (!current->journal_info) current->journal_info = h; @@ -786,8 +778,15 @@ got_it: * not just freed. */ btrfs_end_transaction(h); - return ERR_PTR(ret); + goto reserve_fail; } + /* + * Now that we have found a transaction to be a part of, convert the + * qgroup reservation from prealloc to pertrans. A different transaction + * can't race in and free our pertrans out from under us. + */ + if (qgroup_reserved) + btrfs_qgroup_convert_reserved_meta(root, qgroup_reserved); return h; -- cgit v1.2.3 From 3c6f0c5ecc8910d4ffb0dfe85609ebc0c91c8f34 Mon Sep 17 00:00:00 2001 From: Boris Burkov Date: Tue, 26 Mar 2024 11:55:22 -0700 Subject: btrfs: make btrfs_clear_delalloc_extent() free delalloc reserve Currently, this call site in btrfs_clear_delalloc_extent() only converts the reservation. We are marking it not delalloc, so I don't think it makes sense to keep the rsv around. This is a path where we are not sure to join a transaction, so it leads to incorrect free-ing during umount. Helps with the pass rate of generic/269 and generic/475. Reviewed-by: Qu Wenruo Signed-off-by: Boris Burkov Signed-off-by: David Sterba --- fs/btrfs/inode.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index 1f9e74c4161d..c65fe5de4022 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c @@ -2533,7 +2533,7 @@ void btrfs_clear_delalloc_extent(struct btrfs_inode *inode, */ if (bits & EXTENT_CLEAR_META_RESV && root != fs_info->tree_root) - btrfs_delalloc_release_metadata(inode, len, false); + btrfs_delalloc_release_metadata(inode, len, true); /* For sanity tests. */ if (btrfs_is_testing(fs_info)) -- cgit v1.2.3 From 6e68de0bb0ed59e0554a0c15ede7308c47351e2d Mon Sep 17 00:00:00 2001 From: Boris Burkov Date: Tue, 26 Mar 2024 12:01:28 -0700 Subject: btrfs: always clear PERTRANS metadata during commit It is possible to clear a root's IN_TRANS tag from the radix tree, but not clear its PERTRANS, if there is some error in between. Eliminate that possibility by moving the free up to where we clear the tag. Reviewed-by: Qu Wenruo Signed-off-by: Boris Burkov Signed-off-by: David Sterba --- fs/btrfs/transaction.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/btrfs/transaction.c b/fs/btrfs/transaction.c index 1f10082d35d9..85f359e0e0a7 100644 --- a/fs/btrfs/transaction.c +++ b/fs/btrfs/transaction.c @@ -1494,6 +1494,7 @@ static noinline int commit_fs_roots(struct btrfs_trans_handle *trans) radix_tree_tag_clear(&fs_info->fs_roots_radix, (unsigned long)root->root_key.objectid, BTRFS_ROOT_TRANS_TAG); + btrfs_qgroup_free_meta_all_pertrans(root); spin_unlock(&fs_info->fs_roots_radix_lock); btrfs_free_log(trans, root); @@ -1518,7 +1519,6 @@ static noinline int commit_fs_roots(struct btrfs_trans_handle *trans) if (ret2) return ret2; spin_lock(&fs_info->fs_roots_radix_lock); - btrfs_qgroup_free_meta_all_pertrans(root); } } spin_unlock(&fs_info->fs_roots_radix_lock); -- cgit v1.2.3 From 4189b54220e5af15e948a48524b45d5ea2e5660d Mon Sep 17 00:00:00 2001 From: Shengjiu Wang Date: Mon, 1 Apr 2024 20:54:16 +0800 Subject: ASoC: dt-bindings: fsl-asoc-card: convert to YAML Convert the fsl-asoc-card binding to YAML. When testing dtbs_check, found below compatible strings are not listed in document: fsl,imx-sgtl5000 fsl,imx53-cpuvo-sgtl5000 fsl,imx51-babbage-sgtl5000 fsl,imx53-m53evk-sgtl5000 fsl,imx53-qsb-sgtl5000 fsl,imx53-voipac-sgtl5000 fsl,imx6-armadeus-sgtl5000 fsl,imx6-rex-sgtl5000 fsl,imx6-sabreauto-cs42888 fsl,imx6-wandboard-sgtl5000 fsl,imx6dl-nit6xlite-sgtl5000 fsl,imx6q-ba16-sgtl5000 fsl,imx6q-nitrogen6_max-sgtl5000 fsl,imx6q-nitrogen6_som2-sgtl5000 fsl,imx6q-nitrogen6x-sgtl5000 fsl,imx6q-sabrelite-sgtl5000 fsl,imx6q-sabresd-wm8962 fsl,imx6q-udoo-ac97 fsl,imx6q-ventana-sgtl5000 fsl,imx6sl-evk-wm8962 fsl,imx6sx-sdb-mqs fsl,imx6sx-sdb-wm8962 fsl,imx7d-evk-wm8960 karo,tx53-audio-sgtl5000 tq,imx53-mba53-sgtl5000 So add them in yaml file to pass the test. Also correct the 'dai-format' to 'format' in document. For 'audio-routing', the items are not listed. Because this fsl-asoc-card is generic driver, which supports several codecs, if list all the items, there will be a long list. Signed-off-by: Shengjiu Wang Reviewed-by: Rob Herring Link: https://msgid.link/r/1711976056-19884-3-git-send-email-shengjiu.wang@nxp.com Signed-off-by: Mark Brown --- .../devicetree/bindings/sound/fsl-asoc-card.txt | 117 ------------- .../devicetree/bindings/sound/fsl-asoc-card.yaml | 195 +++++++++++++++++++++ 2 files changed, 195 insertions(+), 117 deletions(-) delete mode 100644 Documentation/devicetree/bindings/sound/fsl-asoc-card.txt create mode 100644 Documentation/devicetree/bindings/sound/fsl-asoc-card.yaml diff --git a/Documentation/devicetree/bindings/sound/fsl-asoc-card.txt b/Documentation/devicetree/bindings/sound/fsl-asoc-card.txt deleted file mode 100644 index 4e8dbc5abfd1..000000000000 --- a/Documentation/devicetree/bindings/sound/fsl-asoc-card.txt +++ /dev/null @@ -1,117 +0,0 @@ -Freescale Generic ASoC Sound Card with ASRC support - -The Freescale Generic ASoC Sound Card can be used, ideally, for all Freescale -SoCs connecting with external CODECs. - -The idea of this generic sound card is a bit like ASoC Simple Card. However, -for Freescale SoCs (especially those released in recent years), most of them -have ASRC (Documentation/devicetree/bindings/sound/fsl,asrc.txt) inside. And -this is a specific feature that might be painstakingly controlled and merged -into the Simple Card. - -So having this generic sound card allows all Freescale SoC users to benefit -from the simplification of a new card support and the capability of the wide -sample rates support through ASRC. - -Note: The card is initially designed for those sound cards who use AC'97, I2S - and PCM DAI formats. However, it'll be also possible to support those non - AC'97/I2S/PCM type sound cards, such as S/PDIF audio and HDMI audio, as - long as the driver has been properly upgraded. - - -The compatible list for this generic sound card currently: - "fsl,imx-audio-ac97" - - "fsl,imx-audio-cs42888" - - "fsl,imx-audio-cs427x" - (compatible with CS4271 and CS4272) - - "fsl,imx-audio-wm8962" - - "fsl,imx-audio-sgtl5000" - (compatible with Documentation/devicetree/bindings/sound/imx-audio-sgtl5000.txt) - - "fsl,imx-audio-wm8960" - - "fsl,imx-audio-mqs" - - "fsl,imx-audio-wm8524" - - "fsl,imx-audio-tlv320aic32x4" - - "fsl,imx-audio-tlv320aic31xx" - - "fsl,imx-audio-si476x" - - "fsl,imx-audio-wm8958" - - "fsl,imx-audio-nau8822" - -Required properties: - - - compatible : Contains one of entries in the compatible list. - - - model : The user-visible name of this sound complex - - - audio-cpu : The phandle of an CPU DAI controller - - - audio-codec : The phandle of an audio codec - -Optional properties: - - - audio-asrc : The phandle of ASRC. It can be absent if there's no - need to add ASRC support via DPCM. - - - audio-routing : A list of the connections between audio components. - Each entry is a pair of strings, the first being the - connection's sink, the second being the connection's - source. There're a few pre-designed board connectors: - * Line Out Jack - * Line In Jack - * Headphone Jack - * Mic Jack - * Ext Spk - * AMIC (stands for Analog Microphone Jack) - * DMIC (stands for Digital Microphone Jack) - - Note: The "Mic Jack" and "AMIC" are redundant while - coexisting in order to support the old bindings - of wm8962 and sgtl5000. - - - hp-det-gpio : The GPIO that detect headphones are plugged in - - mic-det-gpio : The GPIO that detect microphones are plugged in - - bitclock-master : Indicates dai-link bit clock master; for details see simple-card.yaml. - - frame-master : Indicates dai-link frame master; for details see simple-card.yaml. - - dai-format : audio format, for details see simple-card.yaml. - - frame-inversion : dai-link uses frame clock inversion, for details see simple-card.yaml. - - bitclock-inversion : dai-link uses bit clock inversion, for details see simple-card.yaml. - - mclk-id : main clock id, specific for each card configuration. - -Optional unless SSI is selected as a CPU DAI: - - - mux-int-port : The internal port of the i.MX audio muxer (AUDMUX) - - - mux-ext-port : The external port of the i.MX audio muxer - -Example: -sound-cs42888 { - compatible = "fsl,imx-audio-cs42888"; - model = "cs42888-audio"; - audio-cpu = <&esai>; - audio-asrc = <&asrc>; - audio-codec = <&cs42888>; - audio-routing = - "Line Out Jack", "AOUT1L", - "Line Out Jack", "AOUT1R", - "Line Out Jack", "AOUT2L", - "Line Out Jack", "AOUT2R", - "Line Out Jack", "AOUT3L", - "Line Out Jack", "AOUT3R", - "Line Out Jack", "AOUT4L", - "Line Out Jack", "AOUT4R", - "AIN1L", "Line In Jack", - "AIN1R", "Line In Jack", - "AIN2L", "Line In Jack", - "AIN2R", "Line In Jack"; -}; diff --git a/Documentation/devicetree/bindings/sound/fsl-asoc-card.yaml b/Documentation/devicetree/bindings/sound/fsl-asoc-card.yaml new file mode 100644 index 000000000000..42ca39eebd49 --- /dev/null +++ b/Documentation/devicetree/bindings/sound/fsl-asoc-card.yaml @@ -0,0 +1,195 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/sound/fsl-asoc-card.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Freescale Generic ASoC Sound Card with ASRC support + +description: + The Freescale Generic ASoC Sound Card can be used, ideally, + for all Freescale SoCs connecting with external CODECs. + + The idea of this generic sound card is a bit like ASoC Simple Card. + However, for Freescale SoCs (especially those released in recent years), + most of them have ASRC inside. And this is a specific feature that might + be painstakingly controlled and merged into the Simple Card. + + So having this generic sound card allows all Freescale SoC users to + benefit from the simplification of a new card support and the capability + of the wide sample rates support through ASRC. + + Note, The card is initially designed for those sound cards who use AC'97, I2S + and PCM DAI formats. However, it'll be also possible to support those non + AC'97/I2S/PCM type sound cards, such as S/PDIF audio and HDMI audio, as + long as the driver has been properly upgraded. + +maintainers: + - Shengjiu Wang + +properties: + compatible: + oneOf: + - items: + - enum: + - fsl,imx-sgtl5000 + - fsl,imx53-cpuvo-sgtl5000 + - fsl,imx51-babbage-sgtl5000 + - fsl,imx53-m53evk-sgtl5000 + - fsl,imx53-qsb-sgtl5000 + - fsl,imx53-voipac-sgtl5000 + - fsl,imx6-armadeus-sgtl5000 + - fsl,imx6-rex-sgtl5000 + - fsl,imx6-sabreauto-cs42888 + - fsl,imx6-wandboard-sgtl5000 + - fsl,imx6dl-nit6xlite-sgtl5000 + - fsl,imx6q-ba16-sgtl5000 + - fsl,imx6q-nitrogen6_max-sgtl5000 + - fsl,imx6q-nitrogen6_som2-sgtl5000 + - fsl,imx6q-nitrogen6x-sgtl5000 + - fsl,imx6q-sabrelite-sgtl5000 + - fsl,imx6q-sabresd-wm8962 + - fsl,imx6q-udoo-ac97 + - fsl,imx6q-ventana-sgtl5000 + - fsl,imx6sl-evk-wm8962 + - fsl,imx6sx-sdb-mqs + - fsl,imx6sx-sdb-wm8962 + - fsl,imx7d-evk-wm8960 + - karo,tx53-audio-sgtl5000 + - tq,imx53-mba53-sgtl5000 + - enum: + - fsl,imx-audio-ac97 + - fsl,imx-audio-cs42888 + - fsl,imx-audio-mqs + - fsl,imx-audio-sgtl5000 + - fsl,imx-audio-wm8960 + - fsl,imx-audio-wm8962 + - items: + - enum: + - fsl,imx-audio-ac97 + - fsl,imx-audio-cs42888 + - fsl,imx-audio-cs427x + - fsl,imx-audio-mqs + - fsl,imx-audio-nau8822 + - fsl,imx-audio-sgtl5000 + - fsl,imx-audio-si476x + - fsl,imx-audio-tlv320aic31xx + - fsl,imx-audio-tlv320aic32x4 + - fsl,imx-audio-wm8524 + - fsl,imx-audio-wm8960 + - fsl,imx-audio-wm8962 + - fsl,imx-audio-wm8958 + + model: + $ref: /schemas/types.yaml#/definitions/string + description: The user-visible name of this sound complex + + audio-asrc: + $ref: /schemas/types.yaml#/definitions/phandle + description: + The phandle of ASRC. It can be absent if there's no + need to add ASRC support via DPCM. + + audio-codec: + $ref: /schemas/types.yaml#/definitions/phandle + description: The phandle of an audio codec + + audio-cpu: + $ref: /schemas/types.yaml#/definitions/phandle + description: The phandle of an CPU DAI controller + + audio-routing: + $ref: /schemas/types.yaml#/definitions/non-unique-string-array + description: + A list of the connections between audio components. Each entry is a + pair of strings, the first being the connection's sink, the second + being the connection's source. There're a few pre-designed board + connectors. "AMIC" stands for Analog Microphone Jack. + "DMIC" stands for Digital Microphone Jack. The "Mic Jack" and "AMIC" + are redundant while coexisting in order to support the old bindings + of wm8962 and sgtl5000. + + hp-det-gpio: + deprecated: true + maxItems: 1 + description: The GPIO that detect headphones are plugged in + + hp-det-gpios: + maxItems: 1 + description: The GPIO that detect headphones are plugged in + + mic-det-gpio: + deprecated: true + maxItems: 1 + description: The GPIO that detect microphones are plugged in + + mic-det-gpios: + maxItems: 1 + description: The GPIO that detect microphones are plugged in + + bitclock-master: + $ref: simple-card.yaml#/definitions/bitclock-master + description: Indicates dai-link bit clock master. + + frame-master: + $ref: simple-card.yaml#/definitions/frame-master + description: Indicates dai-link frame master. + + format: + $ref: simple-card.yaml#/definitions/format + description: audio format. + + frame-inversion: + $ref: simple-card.yaml#/definitions/frame-inversion + description: dai-link uses frame clock inversion. + + bitclock-inversion: + $ref: simple-card.yaml#/definitions/bitclock-inversion + description: dai-link uses bit clock inversion. + + mclk-id: + $ref: /schemas/types.yaml#/definitions/uint32 + description: main clock id, specific for each card configuration. + + mux-int-port: + $ref: /schemas/types.yaml#/definitions/uint32 + enum: [1, 2, 7] + description: The internal port of the i.MX audio muxer (AUDMUX) + + mux-ext-port: + $ref: /schemas/types.yaml#/definitions/uint32 + enum: [3, 4, 5, 6] + description: The external port of the i.MX audio muxer + + ssi-controller: + $ref: /schemas/types.yaml#/definitions/phandle + description: The phandle of an CPU DAI controller + +required: + - compatible + - model + +unevaluatedProperties: false + +examples: + - | + sound-cs42888 { + compatible = "fsl,imx-audio-cs42888"; + model = "cs42888-audio"; + audio-cpu = <&esai>; + audio-asrc = <&asrc>; + audio-codec = <&cs42888>; + audio-routing = + "Line Out Jack", "AOUT1L", + "Line Out Jack", "AOUT1R", + "Line Out Jack", "AOUT2L", + "Line Out Jack", "AOUT2R", + "Line Out Jack", "AOUT3L", + "Line Out Jack", "AOUT3R", + "Line Out Jack", "AOUT4L", + "Line Out Jack", "AOUT4R", + "AIN1L", "Line In Jack", + "AIN1R", "Line In Jack", + "AIN2L", "Line In Jack", + "AIN2R", "Line In Jack"; + }; -- cgit v1.2.3 From 135f218255b28c5bbf71e9e32a49e5c734cabbe5 Mon Sep 17 00:00:00 2001 From: Fabio Estevam Date: Thu, 28 Mar 2024 12:19:54 -0300 Subject: ARM: dts: imx7s-warp: Pass OV2680 link-frequencies Since commit 63b0cd30b78e ("media: ov2680: Add bus-cfg / endpoint property verification") the ov2680 no longer probes on a imx7s-warp7: ov2680 1-0036: error -EINVAL: supported link freq 330000000 not found ov2680 1-0036: probe with driver ov2680 failed with error -22 Fix it by passing the required 'link-frequencies' property as recommended by: https://www.kernel.org/doc/html/v6.9-rc1/driver-api/media/camera-sensor.html#handling-clocks Cc: stable@vger.kernel.org Fixes: 63b0cd30b78e ("media: ov2680: Add bus-cfg / endpoint property verification") Signed-off-by: Fabio Estevam Signed-off-by: Shawn Guo --- arch/arm/boot/dts/nxp/imx/imx7s-warp.dts | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm/boot/dts/nxp/imx/imx7s-warp.dts b/arch/arm/boot/dts/nxp/imx/imx7s-warp.dts index ba7231b364bb..7bab113ca6da 100644 --- a/arch/arm/boot/dts/nxp/imx/imx7s-warp.dts +++ b/arch/arm/boot/dts/nxp/imx/imx7s-warp.dts @@ -210,6 +210,7 @@ remote-endpoint = <&mipi_from_sensor>; clock-lanes = <0>; data-lanes = <1>; + link-frequencies = /bits/ 64 <330000000>; }; }; }; -- cgit v1.2.3 From 5bd31ab5f79eb6e3bdfa0ca0b57650f9d1604062 Mon Sep 17 00:00:00 2001 From: Shivaprasad G Bhat Date: Thu, 15 Feb 2024 07:52:32 -0600 Subject: powerpc/iommu: Refactor spapr_tce_platform_iommu_attach_dev() The patch makes the iommu_group_get() call only when using it thereby avoiding the unnecessary get & put for domain already being set case. Reviewed-by: Jason Gunthorpe Signed-off-by: Shivaprasad G Bhat Signed-off-by: Michael Ellerman Link: https://msgid.link/170800513841.2411.13524607664262048895.stgit@linux.ibm.com --- arch/powerpc/kernel/iommu.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/arch/powerpc/kernel/iommu.c b/arch/powerpc/kernel/iommu.c index 1185efebf032..29a8c8e18585 100644 --- a/arch/powerpc/kernel/iommu.c +++ b/arch/powerpc/kernel/iommu.c @@ -1285,15 +1285,14 @@ spapr_tce_platform_iommu_attach_dev(struct iommu_domain *platform_domain, struct device *dev) { struct iommu_domain *domain = iommu_get_domain_for_dev(dev); - struct iommu_group *grp = iommu_group_get(dev); struct iommu_table_group *table_group; + struct iommu_group *grp; /* At first attach the ownership is already set */ - if (!domain) { - iommu_group_put(grp); + if (!domain) return 0; - } + grp = iommu_group_get(dev); table_group = iommu_group_get_iommudata(grp); /* * The domain being set to PLATFORM from earlier -- cgit v1.2.3 From 27aa58180473f81990f35238dc8aec40d34c778d Mon Sep 17 00:00:00 2001 From: Amadeusz Sławiński Date: Wed, 3 Apr 2024 11:31:36 +0200 Subject: ASoC: Intel: avs: hdaudio: Use devm_kstrdup_const MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit HDA codec name is constant and we just duplicate it, use const variant of devm_kstrdup to possibly save a bit of memory. Reviewed-by: Cezary Rojewski Signed-off-by: Amadeusz Sławiński Link: https://msgid.link/r/20240403093145.3375857-2-amadeuszx.slawinski@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/intel/avs/boards/hdaudio.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/soc/intel/avs/boards/hdaudio.c b/sound/soc/intel/avs/boards/hdaudio.c index 79b4aca41333..2de703b909c3 100644 --- a/sound/soc/intel/avs/boards/hdaudio.c +++ b/sound/soc/intel/avs/boards/hdaudio.c @@ -54,7 +54,7 @@ static int avs_create_dai_links(struct device *dev, struct hda_codec *codec, int if (!dl[i].cpus->dai_name) return -ENOMEM; - dl[i].codecs->name = devm_kstrdup(dev, cname, GFP_KERNEL); + dl[i].codecs->name = devm_kstrdup_const(dev, cname, GFP_KERNEL); if (!dl[i].codecs->name) return -ENOMEM; @@ -191,7 +191,7 @@ static int avs_hdaudio_probe(struct platform_device *pdev) if (!binder->platforms || !binder->codecs) return -ENOMEM; - binder->codecs->name = devm_kstrdup(dev, dev_name(&codec->core.dev), GFP_KERNEL); + binder->codecs->name = devm_kstrdup_const(dev, dev_name(&codec->core.dev), GFP_KERNEL); if (!binder->codecs->name) return -ENOMEM; -- cgit v1.2.3 From 68a71af3aee2b776a0030e1393864c9501997cbb Mon Sep 17 00:00:00 2001 From: Amadeusz Sławiński Date: Wed, 3 Apr 2024 11:31:37 +0200 Subject: ASoC: Intel: avs: Use devm_kstrdup_const MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit FW name is constant and we just duplicate it, use const variant of devm_kstrdup to possibly save a bit of memory. Reviewed-by: Cezary Rojewski Signed-off-by: Amadeusz Sławiński Link: https://msgid.link/r/20240403093145.3375857-3-amadeuszx.slawinski@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/intel/avs/avs.h | 2 +- sound/soc/intel/avs/utils.c | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/sound/soc/intel/avs/avs.h b/sound/soc/intel/avs/avs.h index f80f79415344..9a02e2b528bc 100644 --- a/sound/soc/intel/avs/avs.h +++ b/sound/soc/intel/avs/avs.h @@ -107,7 +107,7 @@ struct avs_spec { }; struct avs_fw_entry { - char *name; + const char *name; const struct firmware *fw; struct list_head node; diff --git a/sound/soc/intel/avs/utils.c b/sound/soc/intel/avs/utils.c index 82416b86662d..8100c2fa0a7e 100644 --- a/sound/soc/intel/avs/utils.c +++ b/sound/soc/intel/avs/utils.c @@ -250,7 +250,7 @@ int avs_request_firmware(struct avs_dev *adev, const struct firmware **fw_p, con if (!entry) return -ENOMEM; - entry->name = kstrdup(name, GFP_KERNEL); + entry->name = kstrdup_const(name, GFP_KERNEL); if (!entry->name) { kfree(entry); return -ENOMEM; @@ -258,7 +258,7 @@ int avs_request_firmware(struct avs_dev *adev, const struct firmware **fw_p, con ret = request_firmware(&entry->fw, name, adev->dev); if (ret < 0) { - kfree(entry->name); + kfree_const(entry->name); kfree(entry); return ret; } @@ -282,7 +282,7 @@ void avs_release_last_firmware(struct avs_dev *adev) list_del(&entry->node); release_firmware(entry->fw); - kfree(entry->name); + kfree_const(entry->name); kfree(entry); } @@ -296,7 +296,7 @@ void avs_release_firmwares(struct avs_dev *adev) list_for_each_entry_safe(entry, tmp, &adev->fw_list, node) { list_del(&entry->node); release_firmware(entry->fw); - kfree(entry->name); + kfree_const(entry->name); kfree(entry); } } -- cgit v1.2.3 From a3c95efc432ddd18882cfab420cbea14937fb950 Mon Sep 17 00:00:00 2001 From: Amadeusz Sławiński Date: Wed, 3 Apr 2024 11:31:38 +0200 Subject: ASoC: Intel: avs: hdaudio: Constify probing_link MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit probing_link is passed to devm_kmemdup, and is never modified, may as well mark it const. Reviewed-by: Cezary Rojewski Signed-off-by: Amadeusz Sławiński Link: https://msgid.link/r/20240403093145.3375857-4-amadeuszx.slawinski@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/intel/avs/boards/hdaudio.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/intel/avs/boards/hdaudio.c b/sound/soc/intel/avs/boards/hdaudio.c index 2de703b909c3..4433175814f8 100644 --- a/sound/soc/intel/avs/boards/hdaudio.c +++ b/sound/soc/intel/avs/boards/hdaudio.c @@ -155,7 +155,7 @@ static int avs_probing_link_init(struct snd_soc_pcm_runtime *rtm) return 0; } -static struct snd_soc_dai_link probing_link = { +static const struct snd_soc_dai_link probing_link = { .name = "probing-LINK", .id = -1, .nonatomic = 1, -- cgit v1.2.3 From 2dbe7c809841e645a6b9d6d51801d3c594739d93 Mon Sep 17 00:00:00 2001 From: Amadeusz Sławiński Date: Wed, 3 Apr 2024 11:31:39 +0200 Subject: ASoC: Intel: avs: es8336: Constify card_headset_pins MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit card_headset_pins is never modified, mark it const. Reviewed-by: Cezary Rojewski Signed-off-by: Amadeusz Sławiński Link: https://msgid.link/r/20240403093145.3375857-5-amadeuszx.slawinski@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/intel/avs/boards/es8336.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/intel/avs/boards/es8336.c b/sound/soc/intel/avs/boards/es8336.c index 1090082e7d5b..0171806094b4 100644 --- a/sound/soc/intel/avs/boards/es8336.c +++ b/sound/soc/intel/avs/boards/es8336.c @@ -85,7 +85,7 @@ static const struct snd_kcontrol_new card_controls[] = { SOC_DAPM_PIN_SWITCH("Internal Mic"), }; -static struct snd_soc_jack_pin card_headset_pins[] = { +static const struct snd_soc_jack_pin card_headset_pins[] = { { .pin = "Headphone", .mask = SND_JACK_HEADPHONE, -- cgit v1.2.3 From bf400f16a03788ccdb1de1d9bfe9458082f24ef7 Mon Sep 17 00:00:00 2001 From: Amadeusz Sławiński Date: Wed, 3 Apr 2024 11:31:40 +0200 Subject: ASoC: Intel: avs: nau8825: Constify card_headset_pins MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit card_headset_pins is never modified, mark it const. Reviewed-by: Cezary Rojewski Signed-off-by: Amadeusz Sławiński Link: https://msgid.link/r/20240403093145.3375857-6-amadeuszx.slawinski@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/intel/avs/boards/nau8825.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/intel/avs/boards/nau8825.c b/sound/soc/intel/avs/boards/nau8825.c index 1c1e2083f474..cd9e6a6f9212 100644 --- a/sound/soc/intel/avs/boards/nau8825.c +++ b/sound/soc/intel/avs/boards/nau8825.c @@ -67,7 +67,7 @@ static const struct snd_soc_dapm_route card_base_routes[] = { { "Headset Mic", NULL, "Platform Clock" }, }; -static struct snd_soc_jack_pin card_headset_pins[] = { +static const struct snd_soc_jack_pin card_headset_pins[] = { { .pin = "Headphone Jack", .mask = SND_JACK_HEADPHONE, -- cgit v1.2.3 From 130c953a75cc62dd5c73c295bae14197dce46b85 Mon Sep 17 00:00:00 2001 From: Amadeusz Sławiński Date: Wed, 3 Apr 2024 11:31:41 +0200 Subject: ASoC: Intel: avs: rt274: Constify card_headset_pins MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit card_headset_pins is never modified, mark it const. Reviewed-by: Cezary Rojewski Signed-off-by: Amadeusz Sławiński Link: https://msgid.link/r/20240403093145.3375857-7-amadeuszx.slawinski@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/intel/avs/boards/rt274.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/intel/avs/boards/rt274.c b/sound/soc/intel/avs/boards/rt274.c index bfcb8845fd15..4ddc86db43dc 100644 --- a/sound/soc/intel/avs/boards/rt274.c +++ b/sound/soc/intel/avs/boards/rt274.c @@ -75,7 +75,7 @@ static const struct snd_soc_dapm_route card_base_routes[] = { {"MIC", NULL, "Platform Clock"}, }; -static struct snd_soc_jack_pin card_headset_pins[] = { +static const struct snd_soc_jack_pin card_headset_pins[] = { { .pin = "Headphone Jack", .mask = SND_JACK_HEADPHONE, -- cgit v1.2.3 From 682bedc8b0bae52fc5fc95cb3dba6e3d590da653 Mon Sep 17 00:00:00 2001 From: Amadeusz Sławiński Date: Wed, 3 Apr 2024 11:31:42 +0200 Subject: ASoC: Intel: avs: rt286: Constify card_headset_pins MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit card_headset_pins is never modified, mark it const. Reviewed-by: Cezary Rojewski Signed-off-by: Amadeusz Sławiński Link: https://msgid.link/r/20240403093145.3375857-8-amadeuszx.slawinski@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/intel/avs/boards/rt286.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/intel/avs/boards/rt286.c b/sound/soc/intel/avs/boards/rt286.c index 28d7d86b1cc9..88cc30dc429c 100644 --- a/sound/soc/intel/avs/boards/rt286.c +++ b/sound/soc/intel/avs/boards/rt286.c @@ -38,7 +38,7 @@ static const struct snd_soc_dapm_route card_base_routes[] = { {"Speaker", NULL, "SPOL"}, }; -static struct snd_soc_jack_pin card_headset_pins[] = { +static const struct snd_soc_jack_pin card_headset_pins[] = { { .pin = "Headphone Jack", .mask = SND_JACK_HEADPHONE, -- cgit v1.2.3 From 33a886eee711298e799f1f52432e2f5e234cd015 Mon Sep 17 00:00:00 2001 From: Amadeusz Sławiński Date: Wed, 3 Apr 2024 11:31:43 +0200 Subject: ASoC: Intel: avs: rt298: Constify card_headset_pins MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit card_headset_pins is never modified, mark it const. Reviewed-by: Cezary Rojewski Signed-off-by: Amadeusz Sławiński Link: https://msgid.link/r/20240403093145.3375857-9-amadeuszx.slawinski@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/intel/avs/boards/rt298.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/intel/avs/boards/rt298.c b/sound/soc/intel/avs/boards/rt298.c index 80f490b9e118..99ec84920433 100644 --- a/sound/soc/intel/avs/boards/rt298.c +++ b/sound/soc/intel/avs/boards/rt298.c @@ -49,7 +49,7 @@ static const struct snd_soc_dapm_route card_base_routes[] = { {"Speaker", NULL, "SPOL"}, }; -static struct snd_soc_jack_pin card_headset_pins[] = { +static const struct snd_soc_jack_pin card_headset_pins[] = { { .pin = "Headphone Jack", .mask = SND_JACK_HEADPHONE, -- cgit v1.2.3 From a055674868fa9d36f290dba906a76dd45801a37e Mon Sep 17 00:00:00 2001 From: Amadeusz Sławiński Date: Wed, 3 Apr 2024 11:31:44 +0200 Subject: ASoC: Intel: avs: rt5663: Constify card_headset_pins MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit card_headset_pins is never modified, mark it const. Reviewed-by: Cezary Rojewski Signed-off-by: Amadeusz Sławiński Link: https://msgid.link/r/20240403093145.3375857-10-amadeuszx.slawinski@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/intel/avs/boards/rt5663.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/intel/avs/boards/rt5663.c b/sound/soc/intel/avs/boards/rt5663.c index b4762c2a7bf2..4a1be5b229c1 100644 --- a/sound/soc/intel/avs/boards/rt5663.c +++ b/sound/soc/intel/avs/boards/rt5663.c @@ -43,7 +43,7 @@ static const struct snd_soc_dapm_route card_routes[] = { { "IN1N", NULL, "Headset Mic" }, }; -static struct snd_soc_jack_pin card_headset_pins[] = { +static const struct snd_soc_jack_pin card_headset_pins[] = { { .pin = "Headphone Jack", .mask = SND_JACK_HEADPHONE, -- cgit v1.2.3 From 5faf65b5d1e36ec0a1eb3ba8ba2a8b7a779575ce Mon Sep 17 00:00:00 2001 From: Amadeusz Sławiński Date: Wed, 3 Apr 2024 11:31:45 +0200 Subject: ASoC: Intel: avs: rt5682: Constify card_headset_pins MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit card_headset_pins is never modified, mark it const. Reviewed-by: Cezary Rojewski Signed-off-by: Amadeusz Sławiński Link: https://msgid.link/r/20240403093145.3375857-11-amadeuszx.slawinski@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/intel/avs/boards/rt5682.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/intel/avs/boards/rt5682.c b/sound/soc/intel/avs/boards/rt5682.c index 243f979fda98..a672578aa4d6 100644 --- a/sound/soc/intel/avs/boards/rt5682.c +++ b/sound/soc/intel/avs/boards/rt5682.c @@ -80,7 +80,7 @@ static const struct snd_soc_dapm_route card_base_routes[] = { { "IN1P", NULL, "Headset Mic" }, }; -static struct snd_soc_jack_pin card_jack_pins[] = { +static const struct snd_soc_jack_pin card_jack_pins[] = { { .pin = "Headphone Jack", .mask = SND_JACK_HEADPHONE, -- cgit v1.2.3 From bbdf9af261adca039de29e7fc1faff367bf7e9a0 Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Wed, 3 Apr 2024 13:52:04 +0300 Subject: ASoC: SOF: Intel: hda: Create debugfs file to force a clean DSP boot When IMR boot is supported on a platform it is always going to be used to boot the DSP unless some catastrophic event happens. There is no way for a developer to force a clean DSP boot without removing and re-inserting the modules. Create a 'skip_imr_boot' debugfs file which can be used to force the next DSP boot as clean (prune) boot. Signed-off-by: Peter Ujfalusi Reviewed-by: Ranjani Sridharan Reviewed-by: Pierre-Louis Bossart Link: https://msgid.link/r/20240403105210.17949-2-peter.ujfalusi@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/intel/hda-loader.c | 7 ++++++- sound/soc/sof/intel/hda.c | 1 + sound/soc/sof/intel/lnl.c | 7 ++++++- sound/soc/sof/intel/mtl.c | 7 ++++++- 4 files changed, 19 insertions(+), 3 deletions(-) diff --git a/sound/soc/sof/intel/hda-loader.c b/sound/soc/sof/intel/hda-loader.c index b81f231abee3..d5b9209beb5a 100644 --- a/sound/soc/sof/intel/hda-loader.c +++ b/sound/soc/sof/intel/hda-loader.c @@ -15,6 +15,7 @@ * Hardware interface for HDA DSP code loader */ +#include #include #include #include @@ -643,8 +644,12 @@ int hda_dsp_post_fw_run(struct snd_sof_dev *sdev) /* Check if IMR boot is usable */ if (!sof_debug_check_flag(SOF_DBG_IGNORE_D3_PERSISTENT) && (sdev->fw_ready.flags & SOF_IPC_INFO_D3_PERSISTENT || - sdev->pdata->ipc_type == SOF_IPC_TYPE_4)) + sdev->pdata->ipc_type == SOF_IPC_TYPE_4)) { hdev->imrboot_supported = true; + debugfs_create_bool("skip_imr_boot", + 0644, sdev->debugfs_root, + &hdev->skip_imr_boot); + } } hda_sdw_int_enable(sdev, true); diff --git a/sound/soc/sof/intel/hda.c b/sound/soc/sof/intel/hda.c index d38dc43c2f1c..33721e817ef4 100644 --- a/sound/soc/sof/intel/hda.c +++ b/sound/soc/sof/intel/hda.c @@ -19,6 +19,7 @@ #include #include +#include #include #include #include diff --git a/sound/soc/sof/intel/lnl.c b/sound/soc/sof/intel/lnl.c index 7ae017a00184..1365f86b7fb7 100644 --- a/sound/soc/sof/intel/lnl.c +++ b/sound/soc/sof/intel/lnl.c @@ -6,6 +6,7 @@ * Hardware interface for audio DSP on LunarLake. */ +#include #include #include #include @@ -83,8 +84,12 @@ static int lnl_dsp_post_fw_run(struct snd_sof_dev *sdev) struct sof_intel_hda_dev *hda = sdev->pdata->hw_pdata; /* Check if IMR boot is usable */ - if (!sof_debug_check_flag(SOF_DBG_IGNORE_D3_PERSISTENT)) + if (!sof_debug_check_flag(SOF_DBG_IGNORE_D3_PERSISTENT)) { hda->imrboot_supported = true; + debugfs_create_bool("skip_imr_boot", + 0644, sdev->debugfs_root, + &hda->skip_imr_boot); + } } return 0; diff --git a/sound/soc/sof/intel/mtl.c b/sound/soc/sof/intel/mtl.c index df05dc77b8d5..8a55d5a2703e 100644 --- a/sound/soc/sof/intel/mtl.c +++ b/sound/soc/sof/intel/mtl.c @@ -9,6 +9,7 @@ * Hardware interface for audio DSP on Meteorlake. */ +#include #include #include #include @@ -294,8 +295,12 @@ int mtl_dsp_post_fw_run(struct snd_sof_dev *sdev) } /* Check if IMR boot is usable */ - if (!sof_debug_check_flag(SOF_DBG_IGNORE_D3_PERSISTENT)) + if (!sof_debug_check_flag(SOF_DBG_IGNORE_D3_PERSISTENT)) { hdev->imrboot_supported = true; + debugfs_create_bool("skip_imr_boot", + 0644, sdev->debugfs_root, + &hdev->skip_imr_boot); + } } hda_sdw_int_enable(sdev, true); -- cgit v1.2.3 From 1f1b820dc3c65b6883da3130ba3b8624dcbf87db Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Wed, 3 Apr 2024 13:52:05 +0300 Subject: ASoC: SOF: Intel: mtl: Correct rom_status_reg ACE1 architecture changed the place where the ROM updates the status code from the shared SRAM window to HFFLGP1QW0 register for the status and HFFLGP1QW0 + 4 for the error code. The rom_status_reg is not used on MTL because it was wrongly assigned based on older platform convention (SRAM window) and it was giving inconsistent readings. Fixes: 064520e8aeaa ("ASoC: SOF: Intel: Add support for MeteorLake (MTL)") Signed-off-by: Peter Ujfalusi Reviewed-by: Rander Wang Reviewed-by: Kai Vehmanen Reviewed-by: Pierre-Louis Bossart Reviewed-by: Liam Girdwood Link: https://msgid.link/r/20240403105210.17949-3-peter.ujfalusi@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/intel/mtl.c | 4 ++-- sound/soc/sof/intel/mtl.h | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/sound/soc/sof/intel/mtl.c b/sound/soc/sof/intel/mtl.c index 8a55d5a2703e..34a0707086c5 100644 --- a/sound/soc/sof/intel/mtl.c +++ b/sound/soc/sof/intel/mtl.c @@ -746,7 +746,7 @@ const struct sof_intel_dsp_desc mtl_chip_info = { .ipc_ack = MTL_DSP_REG_HFIPCXIDA, .ipc_ack_mask = MTL_DSP_REG_HFIPCXIDA_DONE, .ipc_ctl = MTL_DSP_REG_HFIPCXCTL, - .rom_status_reg = MTL_DSP_ROM_STS, + .rom_status_reg = MTL_DSP_REG_HFFLGPXQWY, .rom_init_timeout = 300, .ssp_count = MTL_SSP_COUNT, .ssp_base_offset = CNL_SSP_BASE_OFFSET, @@ -774,7 +774,7 @@ const struct sof_intel_dsp_desc arl_s_chip_info = { .ipc_ack = MTL_DSP_REG_HFIPCXIDA, .ipc_ack_mask = MTL_DSP_REG_HFIPCXIDA_DONE, .ipc_ctl = MTL_DSP_REG_HFIPCXCTL, - .rom_status_reg = MTL_DSP_ROM_STS, + .rom_status_reg = MTL_DSP_REG_HFFLGPXQWY, .rom_init_timeout = 300, .ssp_count = MTL_SSP_COUNT, .ssp_base_offset = CNL_SSP_BASE_OFFSET, diff --git a/sound/soc/sof/intel/mtl.h b/sound/soc/sof/intel/mtl.h index cc5a1f46fd09..82dd6b8c4859 100644 --- a/sound/soc/sof/intel/mtl.h +++ b/sound/soc/sof/intel/mtl.h @@ -76,8 +76,8 @@ #define MTL_DSP_ROM_STS MTL_SRAM_WINDOW_OFFSET(0) /* ROM status */ #define MTL_DSP_ROM_ERROR (MTL_SRAM_WINDOW_OFFSET(0) + 0x4) /* ROM error code */ -#define MTL_DSP_REG_HFFLGPXQWY 0x163200 /* ROM debug status */ -#define MTL_DSP_REG_HFFLGPXQWY_ERROR 0x163204 /* ROM debug error code */ +#define MTL_DSP_REG_HFFLGPXQWY 0x163200 /* DSP core0 status */ +#define MTL_DSP_REG_HFFLGPXQWY_ERROR 0x163204 /* DSP core0 error */ #define MTL_DSP_REG_HfIMRIS1 0x162088 #define MTL_DSP_REG_HfIMRIS1_IU_MASK BIT(0) -- cgit v1.2.3 From b852574c671a9983dd51c81582c8c5085f3dc382 Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Wed, 3 Apr 2024 13:52:06 +0300 Subject: ASoC: SOF: Intel: lnl: Correct rom_status_reg ACE2 architecture changed the place where the ROM updates the status code from the shared SRAM window (and HFFLGP1QW0 in ACE1) to HFDSC register for the status and HFDEC (HFDSC + 4) for the error code. The rom_status_reg is not used on LNL because it was wrongly assigned based on older platform convention (SRAM window) and it was giving inconsistent readings. Add new header file for lnl specific register definitions. Fixes: 64a63d9914a5 ("ASoC: SOF: Intel: LNL: Add support for Lunarlake platform") Signed-off-by: Peter Ujfalusi Reviewed-by: Rander Wang Reviewed-by: Kai Vehmanen Reviewed-by: Pierre-Louis Bossart Reviewed-by: Liam Girdwood Link: https://msgid.link/r/20240403105210.17949-4-peter.ujfalusi@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/intel/lnl.c | 3 ++- sound/soc/sof/intel/lnl.h | 15 +++++++++++++++ 2 files changed, 17 insertions(+), 1 deletion(-) create mode 100644 sound/soc/sof/intel/lnl.h diff --git a/sound/soc/sof/intel/lnl.c b/sound/soc/sof/intel/lnl.c index 1365f86b7fb7..3a50a299dd33 100644 --- a/sound/soc/sof/intel/lnl.c +++ b/sound/soc/sof/intel/lnl.c @@ -17,6 +17,7 @@ #include "hda-ipc.h" #include "../sof-audio.h" #include "mtl.h" +#include "lnl.h" #include /* LunarLake ops */ @@ -199,7 +200,7 @@ const struct sof_intel_dsp_desc lnl_chip_info = { .ipc_ack = MTL_DSP_REG_HFIPCXIDA, .ipc_ack_mask = MTL_DSP_REG_HFIPCXIDA_DONE, .ipc_ctl = MTL_DSP_REG_HFIPCXCTL, - .rom_status_reg = MTL_DSP_ROM_STS, + .rom_status_reg = LNL_DSP_REG_HFDSC, .rom_init_timeout = 300, .ssp_count = MTL_SSP_COUNT, .d0i3_offset = MTL_HDA_VS_D0I3C, diff --git a/sound/soc/sof/intel/lnl.h b/sound/soc/sof/intel/lnl.h new file mode 100644 index 000000000000..4f4734fe7e08 --- /dev/null +++ b/sound/soc/sof/intel/lnl.h @@ -0,0 +1,15 @@ +/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause) */ +/* + * This file is provided under a dual BSD/GPLv2 license. When using or + * redistributing this file, you may do so under either license. + * + * Copyright(c) 2024 Intel Corporation. All rights reserved. + */ + +#ifndef __SOF_INTEL_LNL_H +#define __SOF_INTEL_LNL_H + +#define LNL_DSP_REG_HFDSC 0x160200 /* DSP core0 status */ +#define LNL_DSP_REG_HFDEC 0x160204 /* DSP core0 error */ + +#endif /* __SOF_INTEL_LNL_H */ -- cgit v1.2.3 From 26187f44aabdf3df7609b7c78724a059c230a2ad Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Wed, 3 Apr 2024 13:52:07 +0300 Subject: ASoC: SOF: Intel: mtl: Disable interrupts when firmware boot failed In case of error during the firmware boot we need to disable the interrupts which were enabled as part of the boot sequence. Fixes: 064520e8aeaa ("ASoC: SOF: Intel: Add support for MeteorLake (MTL)") Signed-off-by: Peter Ujfalusi Reviewed-by: Rander Wang Reviewed-by: Kai Vehmanen Reviewed-by: Pierre-Louis Bossart Reviewed-by: Liam Girdwood Link: https://msgid.link/r/20240403105210.17949-5-peter.ujfalusi@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/intel/mtl.c | 1 + 1 file changed, 1 insertion(+) diff --git a/sound/soc/sof/intel/mtl.c b/sound/soc/sof/intel/mtl.c index 34a0707086c5..044e1cdd46e5 100644 --- a/sound/soc/sof/intel/mtl.c +++ b/sound/soc/sof/intel/mtl.c @@ -508,6 +508,7 @@ err: dump_msg = kasprintf(GFP_KERNEL, "Boot iteration failed: %d/%d", hda->boot_iteration, HDA_FW_BOOT_ATTEMPTS); snd_sof_dsp_dbg_dump(sdev, dump_msg, flags); + mtl_enable_interrupts(sdev, false); mtl_dsp_core_power_down(sdev, SOF_DSP_PRIMARY_CORE); kfree(dump_msg); -- cgit v1.2.3 From 6b1c1c47e76f0161bda2b1ac2e86a219fe70244f Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Wed, 3 Apr 2024 13:52:08 +0300 Subject: ASoC: SOF: Intel: mtl: Implement firmware boot state check With the corrected rom_status_reg values we can now add a check for target boot status for firmware booting. With the check now we can identify failed firmware boots (IMR boots) and we can use the fallback to purge boot the DSP. Fixes: 064520e8aeaa ("ASoC: SOF: Intel: Add support for MeteorLake (MTL)") Signed-off-by: Peter Ujfalusi Reviewed-by: Rander Wang Reviewed-by: Kai Vehmanen Reviewed-by: Pierre-Louis Bossart Reviewed-by: Liam Girdwood Link: https://msgid.link/r/20240403105210.17949-6-peter.ujfalusi@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/intel/mtl.c | 37 ++++++++++++++++++++++++++++++++----- 1 file changed, 32 insertions(+), 5 deletions(-) diff --git a/sound/soc/sof/intel/mtl.c b/sound/soc/sof/intel/mtl.c index 044e1cdd46e5..4c3cfa719571 100644 --- a/sound/soc/sof/intel/mtl.c +++ b/sound/soc/sof/intel/mtl.c @@ -444,7 +444,7 @@ int mtl_dsp_cl_init(struct snd_sof_dev *sdev, int stream_tag, bool imr_boot) { struct sof_intel_hda_dev *hda = sdev->pdata->hw_pdata; const struct sof_intel_dsp_desc *chip = hda->desc; - unsigned int status; + unsigned int status, target_status; u32 ipc_hdr, flags; char *dump_msg; int ret; @@ -490,13 +490,40 @@ int mtl_dsp_cl_init(struct snd_sof_dev *sdev, int stream_tag, bool imr_boot) mtl_enable_ipc_interrupts(sdev); + if (chip->rom_status_reg == MTL_DSP_ROM_STS) { + /* + * Workaround: when the ROM status register is pointing to + * the SRAM window (MTL_DSP_ROM_STS) the platform cannot catch + * ROM_INIT_DONE because of a very short timing window. + * Follow the recommendations and skip target state waiting. + */ + return 0; + } + /* - * ACE workaround: don't wait for ROM INIT. - * The platform cannot catch ROM_INIT_DONE because of a very short - * timing window. Follow the recommendations and skip this part. + * step 7: + * - Cold/Full boot: wait for ROM init to proceed to download the firmware + * - IMR boot: wait for ROM firmware entered (firmware booted up from IMR) */ + if (imr_boot) + target_status = FSR_STATE_FW_ENTERED; + else + target_status = FSR_STATE_INIT_DONE; - return 0; + ret = snd_sof_dsp_read_poll_timeout(sdev, HDA_DSP_BAR, + chip->rom_status_reg, status, + (FSR_TO_STATE_CODE(status) == target_status), + HDA_DSP_REG_POLL_INTERVAL_US, + chip->rom_init_timeout * + USEC_PER_MSEC); + + if (!ret) + return 0; + + if (hda->boot_iteration == HDA_FW_BOOT_ATTEMPTS) + dev_err(sdev->dev, + "%s: timeout with rom_status_reg (%#x) read\n", + __func__, chip->rom_status_reg); err: flags = SOF_DBG_DUMP_PCI | SOF_DBG_DUMP_MBOX | SOF_DBG_DUMP_OPTIONAL; -- cgit v1.2.3 From 3dc2682870ea8f5a7749c069dfc4e0040e69cb5d Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Wed, 3 Apr 2024 13:52:09 +0300 Subject: ASoC: SOF: Intel: hda-dsp/mtl: Add support for ACE ROM state codes The ROM state codes differ between CAVS and ACE architecture, there is a slight overlap. Add the ACE related state defines to mtl.h, introduce new table and use it on case the function is called when running on ACE architecture. Signed-off-by: Peter Ujfalusi Reviewed-by: Rander Wang Reviewed-by: Kai Vehmanen Reviewed-by: Pierre-Louis Bossart Reviewed-by: Liam Girdwood Link: https://msgid.link/r/20240403105210.17949-7-peter.ujfalusi@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/intel/hda.c | 72 +++++++++++++++++++++++++++++++++++++++++++---- sound/soc/sof/intel/hda.h | 2 ++ sound/soc/sof/intel/mtl.h | 44 +++++++++++++++++++++++++++++ 3 files changed, 112 insertions(+), 6 deletions(-) diff --git a/sound/soc/sof/intel/hda.c b/sound/soc/sof/intel/hda.c index 33721e817ef4..2fc10bec7331 100644 --- a/sound/soc/sof/intel/hda.c +++ b/sound/soc/sof/intel/hda.c @@ -35,6 +35,7 @@ #include "../ipc4-topology.h" #include "hda.h" #include "telemetry.h" +#include "mtl.h" #define CREATE_TRACE_POINTS #include @@ -597,7 +598,7 @@ static const struct hda_dsp_msg_code hda_dsp_rom_fw_error_texts[] = { }; #define FSR_ROM_STATE_ENTRY(state) {FSR_STATE_ROM_##state, #state} -static const struct hda_dsp_msg_code fsr_rom_state_names[] = { +static const struct hda_dsp_msg_code cavs_fsr_rom_state_names[] = { FSR_ROM_STATE_ENTRY(INIT), FSR_ROM_STATE_ENTRY(INIT_DONE), FSR_ROM_STATE_ENTRY(CSE_MANIFEST_LOADED), @@ -620,6 +621,58 @@ static const struct hda_dsp_msg_code fsr_rom_state_names[] = { FSR_ROM_STATE_ENTRY(CSE_IPC_DOWN), }; +static const struct hda_dsp_msg_code ace_fsr_rom_state_names[] = { + FSR_ROM_STATE_ENTRY(INIT), + FSR_ROM_STATE_ENTRY(INIT_DONE), + FSR_ROM_STATE_ENTRY(CSE_MANIFEST_LOADED), + FSR_ROM_STATE_ENTRY(FW_MANIFEST_LOADED), + FSR_ROM_STATE_ENTRY(FW_FW_LOADED), + FSR_ROM_STATE_ENTRY(FW_ENTERED), + FSR_ROM_STATE_ENTRY(VERIFY_FEATURE_MASK), + FSR_ROM_STATE_ENTRY(GET_LOAD_OFFSET), + FSR_ROM_STATE_ENTRY(RESET_VECTOR_DONE), + FSR_ROM_STATE_ENTRY(PURGE_BOOT), + FSR_ROM_STATE_ENTRY(RESTORE_BOOT), + FSR_ROM_STATE_ENTRY(FW_ENTRY_POINT), + FSR_ROM_STATE_ENTRY(VALIDATE_PUB_KEY), + FSR_ROM_STATE_ENTRY(POWER_DOWN_HPSRAM), + FSR_ROM_STATE_ENTRY(POWER_DOWN_ULPSRAM), + FSR_ROM_STATE_ENTRY(POWER_UP_ULPSRAM_STACK), + FSR_ROM_STATE_ENTRY(POWER_UP_HPSRAM_DMA), + FSR_ROM_STATE_ENTRY(BEFORE_EP_POINTER_READ), + FSR_ROM_STATE_ENTRY(VALIDATE_MANIFEST), + FSR_ROM_STATE_ENTRY(VALIDATE_FW_MODULE), + FSR_ROM_STATE_ENTRY(PROTECT_IMR_REGION), + FSR_ROM_STATE_ENTRY(PUSH_MODEL_ROUTINE), + FSR_ROM_STATE_ENTRY(PULL_MODEL_ROUTINE), + FSR_ROM_STATE_ENTRY(VALIDATE_PKG_DIR), + FSR_ROM_STATE_ENTRY(VALIDATE_CPD), + FSR_ROM_STATE_ENTRY(VALIDATE_CSS_MAN_HEADER), + FSR_ROM_STATE_ENTRY(VALIDATE_BLOB_SVN), + FSR_ROM_STATE_ENTRY(VERIFY_IFWI_PARTITION), + FSR_ROM_STATE_ENTRY(REMOVE_ACCESS_CONTROL), + FSR_ROM_STATE_ENTRY(AUTH_BYPASS), + FSR_ROM_STATE_ENTRY(AUTH_ENABLED), + FSR_ROM_STATE_ENTRY(INIT_DMA), + FSR_ROM_STATE_ENTRY(PURGE_FW_ENTRY), + FSR_ROM_STATE_ENTRY(PURGE_FW_END), + FSR_ROM_STATE_ENTRY(CLEAN_UP_BSS_DONE), + FSR_ROM_STATE_ENTRY(IMR_RESTORE_ENTRY), + FSR_ROM_STATE_ENTRY(IMR_RESTORE_END), + FSR_ROM_STATE_ENTRY(FW_MANIFEST_IN_DMA_BUFF), + FSR_ROM_STATE_ENTRY(LOAD_CSE_MAN_TO_IMR), + FSR_ROM_STATE_ENTRY(LOAD_FW_MAN_TO_IMR), + FSR_ROM_STATE_ENTRY(LOAD_FW_CODE_TO_IMR), + FSR_ROM_STATE_ENTRY(FW_LOADING_DONE), + FSR_ROM_STATE_ENTRY(FW_CODE_LOADED), + FSR_ROM_STATE_ENTRY(VERIFY_IMAGE_TYPE), + FSR_ROM_STATE_ENTRY(AUTH_API_INIT), + FSR_ROM_STATE_ENTRY(AUTH_API_PROC), + FSR_ROM_STATE_ENTRY(AUTH_API_FIRST_BUSY), + FSR_ROM_STATE_ENTRY(AUTH_API_FIRST_RESULT), + FSR_ROM_STATE_ENTRY(AUTH_API_CLEANUP), +}; + #define FSR_BRINGUP_STATE_ENTRY(state) {FSR_STATE_BRINGUP_##state, #state} static const struct hda_dsp_msg_code fsr_bringup_state_names[] = { FSR_BRINGUP_STATE_ENTRY(INIT), @@ -664,7 +717,7 @@ hda_dsp_get_state_text(u32 code, const struct hda_dsp_msg_code *msg_code, return NULL; } -static void hda_dsp_get_state(struct snd_sof_dev *sdev, const char *level) +void hda_dsp_get_state(struct snd_sof_dev *sdev, const char *level) { const struct sof_intel_dsp_desc *chip = get_chip_info(sdev->pdata); const char *state_text, *error_text, *module_text; @@ -680,12 +733,19 @@ static void hda_dsp_get_state(struct snd_sof_dev *sdev, const char *level) else module_text = fsr_module_names[module]; - if (module == FSR_MOD_BRNGUP) + if (module == FSR_MOD_BRNGUP) { state_text = hda_dsp_get_state_text(state, fsr_bringup_state_names, ARRAY_SIZE(fsr_bringup_state_names)); - else - state_text = hda_dsp_get_state_text(state, fsr_rom_state_names, - ARRAY_SIZE(fsr_rom_state_names)); + } else { + if (chip->hw_ip_version < SOF_INTEL_ACE_1_0) + state_text = hda_dsp_get_state_text(state, + cavs_fsr_rom_state_names, + ARRAY_SIZE(cavs_fsr_rom_state_names)); + else + state_text = hda_dsp_get_state_text(state, + ace_fsr_rom_state_names, + ARRAY_SIZE(ace_fsr_rom_state_names)); + } /* not for us, must be generic sof message */ if (!state_text) { diff --git a/sound/soc/sof/intel/hda.h b/sound/soc/sof/intel/hda.h index f530a05cfc92..88936bff3319 100644 --- a/sound/soc/sof/intel/hda.h +++ b/sound/soc/sof/intel/hda.h @@ -689,6 +689,8 @@ int hda_dsp_ipc_get_window_offset(struct snd_sof_dev *sdev, u32 id); irqreturn_t hda_dsp_ipc_irq_thread(int irq, void *context); int hda_dsp_ipc_cmd_done(struct snd_sof_dev *sdev, int dir); +void hda_dsp_get_state(struct snd_sof_dev *sdev, const char *level); + /* * DSP Code loader. */ diff --git a/sound/soc/sof/intel/mtl.h b/sound/soc/sof/intel/mtl.h index 82dd6b8c4859..9a36484cc621 100644 --- a/sound/soc/sof/intel/mtl.h +++ b/sound/soc/sof/intel/mtl.h @@ -78,6 +78,50 @@ #define MTL_DSP_REG_HFFLGPXQWY 0x163200 /* DSP core0 status */ #define MTL_DSP_REG_HFFLGPXQWY_ERROR 0x163204 /* DSP core0 error */ + +/* FSR status codes */ +#define FSR_STATE_ROM_RESET_VECTOR_DONE 0x8 +#define FSR_STATE_ROM_PURGE_BOOT 0x9 +#define FSR_STATE_ROM_RESTORE_BOOT 0xA +#define FSR_STATE_ROM_FW_ENTRY_POINT 0xB +#define FSR_STATE_ROM_VALIDATE_PUB_KEY 0xC +#define FSR_STATE_ROM_POWER_DOWN_HPSRAM 0xD +#define FSR_STATE_ROM_POWER_DOWN_ULPSRAM 0xE +#define FSR_STATE_ROM_POWER_UP_ULPSRAM_STACK 0xF +#define FSR_STATE_ROM_POWER_UP_HPSRAM_DMA 0x10 +#define FSR_STATE_ROM_BEFORE_EP_POINTER_READ 0x11 +#define FSR_STATE_ROM_VALIDATE_MANIFEST 0x12 +#define FSR_STATE_ROM_VALIDATE_FW_MODULE 0x13 +#define FSR_STATE_ROM_PROTECT_IMR_REGION 0x14 +#define FSR_STATE_ROM_PUSH_MODEL_ROUTINE 0x15 +#define FSR_STATE_ROM_PULL_MODEL_ROUTINE 0x16 +#define FSR_STATE_ROM_VALIDATE_PKG_DIR 0x17 +#define FSR_STATE_ROM_VALIDATE_CPD 0x18 +#define FSR_STATE_ROM_VALIDATE_CSS_MAN_HEADER 0x19 +#define FSR_STATE_ROM_VALIDATE_BLOB_SVN 0x1A +#define FSR_STATE_ROM_VERIFY_IFWI_PARTITION 0x1B +#define FSR_STATE_ROM_REMOVE_ACCESS_CONTROL 0x1C +#define FSR_STATE_ROM_AUTH_BYPASS 0x1D +#define FSR_STATE_ROM_AUTH_ENABLED 0x1E +#define FSR_STATE_ROM_INIT_DMA 0x1F +#define FSR_STATE_ROM_PURGE_FW_ENTRY 0x20 +#define FSR_STATE_ROM_PURGE_FW_END 0x21 +#define FSR_STATE_ROM_CLEAN_UP_BSS_DONE 0x22 +#define FSR_STATE_ROM_IMR_RESTORE_ENTRY 0x23 +#define FSR_STATE_ROM_IMR_RESTORE_END 0x24 +#define FSR_STATE_ROM_FW_MANIFEST_IN_DMA_BUFF 0x25 +#define FSR_STATE_ROM_LOAD_CSE_MAN_TO_IMR 0x26 +#define FSR_STATE_ROM_LOAD_FW_MAN_TO_IMR 0x27 +#define FSR_STATE_ROM_LOAD_FW_CODE_TO_IMR 0x28 +#define FSR_STATE_ROM_FW_LOADING_DONE 0x29 +#define FSR_STATE_ROM_FW_CODE_LOADED 0x2A +#define FSR_STATE_ROM_VERIFY_IMAGE_TYPE 0x2B +#define FSR_STATE_ROM_AUTH_API_INIT 0x2C +#define FSR_STATE_ROM_AUTH_API_PROC 0x2D +#define FSR_STATE_ROM_AUTH_API_FIRST_BUSY 0x2E +#define FSR_STATE_ROM_AUTH_API_FIRST_RESULT 0x2F +#define FSR_STATE_ROM_AUTH_API_CLEANUP 0x30 + #define MTL_DSP_REG_HfIMRIS1 0x162088 #define MTL_DSP_REG_HfIMRIS1_IU_MASK BIT(0) -- cgit v1.2.3 From 40bdf121a3ed91281196068e50789888e4b1d2d2 Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Wed, 3 Apr 2024 13:52:10 +0300 Subject: ASoC: SOF: Intel: mtl: Correct the mtl_dsp_dump output The ROM/firmware state handling has changed between CAVS and ACE architecture: CAVS: ROM and firmware uses the SRAM window for the state and status/error code reporting ACE: ROM code is using two registers to report the state and error while the firmware is using the SRAM window to report states and status/error codes. Use the generic hda_dsp_get_state() to decode ROM state and error codes and print out the firmware state and status/error code only if the SRAM window is accessible - the firmware is booted and the Status readout is not 0xffffffff. Signed-off-by: Peter Ujfalusi Reviewed-by: Rander Wang Reviewed-by: Kai Vehmanen Reviewed-by: Pierre-Louis Bossart Reviewed-by: Liam Girdwood Link: https://msgid.link/r/20240403105210.17949-8-peter.ujfalusi@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/intel/mtl.c | 16 +++++----------- 1 file changed, 5 insertions(+), 11 deletions(-) diff --git a/sound/soc/sof/intel/mtl.c b/sound/soc/sof/intel/mtl.c index 4c3cfa719571..8ff864ae9833 100644 --- a/sound/soc/sof/intel/mtl.c +++ b/sound/soc/sof/intel/mtl.c @@ -310,22 +310,16 @@ int mtl_dsp_post_fw_run(struct snd_sof_dev *sdev) void mtl_dsp_dump(struct snd_sof_dev *sdev, u32 flags) { char *level = (flags & SOF_DBG_DUMP_OPTIONAL) ? KERN_DEBUG : KERN_ERR; - u32 romdbgsts; - u32 romdbgerr; u32 fwsts; u32 fwlec; + hda_dsp_get_state(sdev, level); fwsts = snd_sof_dsp_read(sdev, HDA_DSP_BAR, MTL_DSP_ROM_STS); fwlec = snd_sof_dsp_read(sdev, HDA_DSP_BAR, MTL_DSP_ROM_ERROR); - romdbgsts = snd_sof_dsp_read(sdev, HDA_DSP_BAR, MTL_DSP_REG_HFFLGPXQWY); - romdbgerr = snd_sof_dsp_read(sdev, HDA_DSP_BAR, MTL_DSP_REG_HFFLGPXQWY_ERROR); - - dev_err(sdev->dev, "ROM status: %#x, ROM error: %#x\n", fwsts, fwlec); - dev_err(sdev->dev, "ROM debug status: %#x, ROM debug error: %#x\n", romdbgsts, - romdbgerr); - romdbgsts = snd_sof_dsp_read(sdev, HDA_DSP_BAR, MTL_DSP_REG_HFFLGPXQWY + 0x8 * 3); - dev_printk(level, sdev->dev, "ROM feature bit%s enabled\n", - romdbgsts & BIT(24) ? "" : " not"); + + if (fwsts != 0xffffffff) + dev_err(sdev->dev, "Firmware state: %#x, status/error code: %#x\n", + fwsts, fwlec); sof_ipc4_intel_dump_telemetry_state(sdev, flags); } -- cgit v1.2.3 From 8db8c77059e75a0f418b10ede39dd82a9eb031fa Mon Sep 17 00:00:00 2001 From: Nuno Pereira Date: Mon, 26 Feb 2024 22:39:31 +0000 Subject: HID: nintendo: Fix N64 controller being identified as mouse This patch is regarding the recent addition of support for the NSO controllers to hid-nintendo. All controllers are working correctly with the exception of the N64 controller, which is being identified as a mouse by udev. This results in the joystick controlling the mouse cursor and the controller not being detected by games. The reason for this is because the N64's C buttons have been attributed to BTN_FORWARD, BTN_BACK, BTN_LEFT, BTN_RIGHT, which are buttons typically attributed to mice. This patch changes those buttons to controller buttons, making the controller be correctly identified as such. Signed-off-by: Nuno Pereira Signed-off-by: Jiri Kosina --- drivers/hid/hid-nintendo.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/hid/hid-nintendo.c b/drivers/hid/hid-nintendo.c index ab5953fc2436..80e0f23c1c33 100644 --- a/drivers/hid/hid-nintendo.c +++ b/drivers/hid/hid-nintendo.c @@ -481,10 +481,10 @@ static const struct joycon_ctlr_button_mapping n64con_button_mappings[] = { { BTN_TR, JC_BTN_R, }, { BTN_TR2, JC_BTN_LSTICK, }, /* ZR */ { BTN_START, JC_BTN_PLUS, }, - { BTN_FORWARD, JC_BTN_Y, }, /* C UP */ - { BTN_BACK, JC_BTN_ZR, }, /* C DOWN */ - { BTN_LEFT, JC_BTN_X, }, /* C LEFT */ - { BTN_RIGHT, JC_BTN_MINUS, }, /* C RIGHT */ + { BTN_SELECT, JC_BTN_Y, }, /* C UP */ + { BTN_X, JC_BTN_ZR, }, /* C DOWN */ + { BTN_Y, JC_BTN_X, }, /* C LEFT */ + { BTN_C, JC_BTN_MINUS, }, /* C RIGHT */ { BTN_MODE, JC_BTN_HOME, }, { BTN_Z, JC_BTN_CAP, }, { /* sentinel */ }, -- cgit v1.2.3 From 38d5387b7660476fd7e8e07d16ee436819e3544d Mon Sep 17 00:00:00 2001 From: Luca Ceresoli Date: Wed, 3 Apr 2024 13:03:18 +0200 Subject: ASoC: codecs: rk3308: fix "defined but not used" warning on !OF Building with CONFIG_OF=n triggers: warning: 'rk3308_codec_of_match' defined but not used [-Wunused-const-variable=] warning: unused variable 'rk3308_codec_of_match' [-Wunused-const-variable] Even though OF is needed for probing, fix by declaring as __maybe_unused to still allow building on non-OF configurations for build testing. Fixes: 9fdd7b45da18 ("arm64: defconfig: enable Rockchip RK3308 internal audio codec driver") Reported-by: kernel test robot Closes: https://lore.kernel.org/oe-kbuild-all/202403271905.BYbGJiPi-lkp@intel.com/ Closes: https://lore.kernel.org/oe-kbuild-all/202403271907.0z0uuG5I-lkp@intel.com/ Signed-off-by: Luca Ceresoli Link: https://msgid.link/r/20240403-rk3308-audio-codec-fix-warning-v2-1-816bae4c1dc5@bootlin.com Signed-off-by: Mark Brown --- sound/soc/codecs/rk3308_codec.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/codecs/rk3308_codec.c b/sound/soc/codecs/rk3308_codec.c index 9d3e4691a7b5..74c3836995b1 100644 --- a/sound/soc/codecs/rk3308_codec.c +++ b/sound/soc/codecs/rk3308_codec.c @@ -953,7 +953,7 @@ static int rk3308_codec_platform_probe(struct platform_device *pdev) return 0; } -static const struct of_device_id rk3308_codec_of_match[] = { +static const struct of_device_id __maybe_unused rk3308_codec_of_match[] = { { .compatible = "rockchip,rk3308-codec", }, {}, }; -- cgit v1.2.3 From 03246ade4646653bbc98fa6fa506891a51983259 Mon Sep 17 00:00:00 2001 From: Luca Ceresoli Date: Wed, 3 Apr 2024 13:03:19 +0200 Subject: ASoC: codecs: rk3308: depend on ARM64 || COMPILE_TEST This codec is only known to exist in the RK3308 ARM64 SoC, so depend on it except for compile test cases. Note that the driver won't probe without CONFIG_OF, but ARM64 selects OF already so it is not needed. Suggested-by: Mark Brown Signed-off-by: Luca Ceresoli Link: https://msgid.link/r/20240403-rk3308-audio-codec-fix-warning-v2-2-816bae4c1dc5@bootlin.com Signed-off-by: Mark Brown --- sound/soc/codecs/Kconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig index 1752814fffdd..4e47bb6850aa 100644 --- a/sound/soc/codecs/Kconfig +++ b/sound/soc/codecs/Kconfig @@ -1436,6 +1436,7 @@ config SND_SOC_PEB2466 config SND_SOC_RK3308 tristate "Rockchip RK3308 audio CODEC" + depends on ARM64 || COMPILE_TEST select REGMAP_MMIO help This is a device driver for the audio codec embedded in the -- cgit v1.2.3 From ea36bf1827462e4a52365bf8e3f7d1712c5d9600 Mon Sep 17 00:00:00 2001 From: Kenny Levinsen Date: Tue, 2 Apr 2024 13:10:04 +0200 Subject: HID: i2c-hid: Revert to await reset ACK before reading report descriptor In af93a167eda9, i2c_hid_parse was changed to continue with reading the report descriptor before waiting for reset to be acknowledged. This has lead to two regressions: 1. We fail to handle reset acknowledgment if it happens while reading the report descriptor. The transfer sets I2C_HID_READ_PENDING, which causes the IRQ handler to return without doing anything. This affects both a Wacom touchscreen and a Sensel touchpad. 2. On a Sensel touchpad, reading the report descriptor this quickly after reset results in all zeroes or partial zeroes. The issues were observed on the Lenovo Thinkpad Z16 Gen 2. The change in question was made based on a Microsoft article[0] stating that Windows 8 *may* read the report descriptor in parallel with awaiting reset acknowledgment, intended as a slight reset performance optimization. Perhaps they only do this if reset is not completing quickly enough for their tastes? As the code is not currently ready to read registers in parallel with a pending reset acknowledgment, and as reading quickly breaks the report descriptor on the Sensel touchpad, revert to waiting for reset acknowledgment before proceeding to read the report descriptor. [0]: https://learn.microsoft.com/en-us/windows-hardware/drivers/hid/plug-and-play-support-and-power-management Fixes: af93a167eda9 ("HID: i2c-hid: Move i2c_hid_finish_hwreset() to after reading the report-descriptor") Closes: https://bugzilla.redhat.com/show_bug.cgi?id=2271136 Cc: stable@vger.kernel.org Signed-off-by: Kenny Levinsen Link: https://lore.kernel.org/r/20240331182440.14477-1-kl@kl.wtf [hdegoede@redhat.com Drop no longer necessary abort_reset error exit path] Signed-off-by: Hans de Goede Tested-by: Mark Pearson Signed-off-by: Jiri Kosina --- drivers/hid/i2c-hid/i2c-hid-core.c | 29 ++++++++--------------------- 1 file changed, 8 insertions(+), 21 deletions(-) diff --git a/drivers/hid/i2c-hid/i2c-hid-core.c b/drivers/hid/i2c-hid/i2c-hid-core.c index 1c86c97688e9..d965382196c6 100644 --- a/drivers/hid/i2c-hid/i2c-hid-core.c +++ b/drivers/hid/i2c-hid/i2c-hid-core.c @@ -726,12 +726,15 @@ static int i2c_hid_parse(struct hid_device *hid) mutex_lock(&ihid->reset_lock); do { ret = i2c_hid_start_hwreset(ihid); - if (ret) + if (ret == 0) + ret = i2c_hid_finish_hwreset(ihid); + else msleep(1000); } while (tries-- > 0 && ret); + mutex_unlock(&ihid->reset_lock); if (ret) - goto abort_reset; + return ret; use_override = i2c_hid_get_dmi_hid_report_desc_override(client->name, &rsize); @@ -741,11 +744,8 @@ static int i2c_hid_parse(struct hid_device *hid) i2c_hid_dbg(ihid, "Using a HID report descriptor override\n"); } else { rdesc = kzalloc(rsize, GFP_KERNEL); - - if (!rdesc) { - ret = -ENOMEM; - goto abort_reset; - } + if (!rdesc) + return -ENOMEM; i2c_hid_dbg(ihid, "asking HID report descriptor\n"); @@ -754,23 +754,10 @@ static int i2c_hid_parse(struct hid_device *hid) rdesc, rsize); if (ret) { hid_err(hid, "reading report descriptor failed\n"); - goto abort_reset; + goto out; } } - /* - * Windows directly reads the report-descriptor after sending reset - * and then waits for resets completion afterwards. Some touchpads - * actually wait for the report-descriptor to be read before signalling - * reset completion. - */ - ret = i2c_hid_finish_hwreset(ihid); -abort_reset: - clear_bit(I2C_HID_RESET_PENDING, &ihid->flags); - mutex_unlock(&ihid->reset_lock); - if (ret) - goto out; - i2c_hid_dbg(ihid, "Report Descriptor: %*ph\n", rsize, rdesc); ret = hid_parse_report(hid, rdesc, rsize); -- cgit v1.2.3 From a358f67d16942f3bbc4d6b0e4b65efd5dda1c304 Mon Sep 17 00:00:00 2001 From: Laurentiu Mihalcea Date: Fri, 29 Mar 2024 00:12:00 +0200 Subject: ASoC: SOF: imx: drop usage of the imx8_*_clocks API Currently, the driver has to keep track of all the clocks it uses via an array of "struct clk_bulk_data", which doesn't scale well and is unnecessary. As such, replace the usage of the imx8_*_clocks with "devm_clk_bulk_get_all()" and friends. Signed-off-by: Laurentiu Mihalcea Reviewed-by: Iuliana Prodan Reviewed-by: Pierre-Louis Bossart Reviewed-by: Daniel Baluta Link: https://msgid.link/r/20240328221201.24722-2-laurentiumihalcea111@gmail.com Signed-off-by: Mark Brown --- sound/soc/sof/imx/imx8.c | 41 +++++++++++++++++------------------------ sound/soc/sof/imx/imx8m.c | 40 +++++++++++++++++----------------------- sound/soc/sof/imx/imx8ulp.c | 42 +++++++++++++++++++----------------------- 3 files changed, 53 insertions(+), 70 deletions(-) diff --git a/sound/soc/sof/imx/imx8.c b/sound/soc/sof/imx/imx8.c index 07f51489d6c9..d65e09a927f6 100644 --- a/sound/soc/sof/imx/imx8.c +++ b/sound/soc/sof/imx/imx8.c @@ -41,13 +41,6 @@ #define MBOX_OFFSET 0x800000 #define MBOX_SIZE 0x1000 -/* DSP clocks */ -static struct clk_bulk_data imx8_dsp_clks[] = { - { .id = "ipg" }, - { .id = "ocram" }, - { .id = "core" }, -}; - struct imx8_priv { struct device *dev; struct snd_sof_dev *sdev; @@ -64,7 +57,8 @@ struct imx8_priv { struct device **pd_dev; struct device_link **link; - struct imx_clocks *clks; + struct clk_bulk_data *clks; + int clk_num; }; static int imx8_get_mailbox_offset(struct snd_sof_dev *sdev) @@ -196,10 +190,6 @@ static int imx8_probe(struct snd_sof_dev *sdev) if (!priv) return -ENOMEM; - priv->clks = devm_kzalloc(&pdev->dev, sizeof(*priv->clks), GFP_KERNEL); - if (!priv->clks) - return -ENOMEM; - sdev->num_cores = 1; sdev->pdata->hw_pdata = priv; priv->dev = sdev->dev; @@ -313,17 +303,18 @@ static int imx8_probe(struct snd_sof_dev *sdev) /* set default mailbox offset for FW ready message */ sdev->dsp_box.offset = MBOX_OFFSET; - /* init clocks info */ - priv->clks->dsp_clks = imx8_dsp_clks; - priv->clks->num_dsp_clks = ARRAY_SIZE(imx8_dsp_clks); - - ret = imx8_parse_clocks(sdev, priv->clks); - if (ret < 0) + ret = devm_clk_bulk_get_all(sdev->dev, &priv->clks); + if (ret < 0) { + dev_err(sdev->dev, "failed to fetch clocks: %d\n", ret); goto exit_pdev_unregister; + } + priv->clk_num = ret; - ret = imx8_enable_clocks(sdev, priv->clks); - if (ret < 0) + ret = clk_bulk_prepare_enable(priv->clk_num, priv->clks); + if (ret < 0) { + dev_err(sdev->dev, "failed to enable clocks: %d\n", ret); goto exit_pdev_unregister; + } return 0; @@ -343,7 +334,7 @@ static void imx8_remove(struct snd_sof_dev *sdev) struct imx8_priv *priv = sdev->pdata->hw_pdata; int i; - imx8_disable_clocks(sdev, priv->clks); + clk_bulk_disable_unprepare(priv->clk_num, priv->clks); platform_device_unregister(priv->ipc_dev); for (i = 0; i < priv->num_domains; i++) { @@ -373,7 +364,7 @@ static void imx8_suspend(struct snd_sof_dev *sdev) for (i = 0; i < DSP_MU_CHAN_NUM; i++) imx_dsp_free_channel(priv->dsp_ipc, i); - imx8_disable_clocks(sdev, priv->clks); + clk_bulk_disable_unprepare(priv->clk_num, priv->clks); } static int imx8_resume(struct snd_sof_dev *sdev) @@ -382,9 +373,11 @@ static int imx8_resume(struct snd_sof_dev *sdev) int ret; int i; - ret = imx8_enable_clocks(sdev, priv->clks); - if (ret < 0) + ret = clk_bulk_prepare_enable(priv->clk_num, priv->clks); + if (ret < 0) { + dev_err(sdev->dev, "failed to enable clocks: %d\n", ret); return ret; + } for (i = 0; i < DSP_MU_CHAN_NUM; i++) imx_dsp_request_channel(priv->dsp_ipc, i); diff --git a/sound/soc/sof/imx/imx8m.c b/sound/soc/sof/imx/imx8m.c index 222cd1467da6..3e0b88002b4f 100644 --- a/sound/soc/sof/imx/imx8m.c +++ b/sound/soc/sof/imx/imx8m.c @@ -26,12 +26,6 @@ #define MBOX_OFFSET 0x800000 #define MBOX_SIZE 0x1000 -static struct clk_bulk_data imx8m_dsp_clks[] = { - { .id = "ipg" }, - { .id = "ocram" }, - { .id = "core" }, -}; - /* DAP registers */ #define IMX8M_DAP_DEBUG 0x28800000 #define IMX8M_DAP_DEBUG_SIZE (64 * 1024) @@ -54,7 +48,8 @@ struct imx8m_priv { struct imx_dsp_ipc *dsp_ipc; struct platform_device *ipc_dev; - struct imx_clocks *clks; + struct clk_bulk_data *clks; + int clk_num; void __iomem *dap; struct regmap *regmap; @@ -163,10 +158,6 @@ static int imx8m_probe(struct snd_sof_dev *sdev) if (!priv) return -ENOMEM; - priv->clks = devm_kzalloc(&pdev->dev, sizeof(*priv->clks), GFP_KERNEL); - if (!priv->clks) - return -ENOMEM; - sdev->num_cores = 1; sdev->pdata->hw_pdata = priv; priv->dev = sdev->dev; @@ -250,17 +241,18 @@ static int imx8m_probe(struct snd_sof_dev *sdev) goto exit_pdev_unregister; } - /* init clocks info */ - priv->clks->dsp_clks = imx8m_dsp_clks; - priv->clks->num_dsp_clks = ARRAY_SIZE(imx8m_dsp_clks); - - ret = imx8_parse_clocks(sdev, priv->clks); - if (ret < 0) + ret = devm_clk_bulk_get_all(sdev->dev, &priv->clks); + if (ret < 0) { + dev_err(sdev->dev, "failed to fetch clocks: %d\n", ret); goto exit_pdev_unregister; + } + priv->clk_num = ret; - ret = imx8_enable_clocks(sdev, priv->clks); - if (ret < 0) + ret = clk_bulk_prepare_enable(priv->clk_num, priv->clks); + if (ret < 0) { + dev_err(sdev->dev, "failed to enable clocks: %d\n", ret); goto exit_pdev_unregister; + } return 0; @@ -273,7 +265,7 @@ static void imx8m_remove(struct snd_sof_dev *sdev) { struct imx8m_priv *priv = sdev->pdata->hw_pdata; - imx8_disable_clocks(sdev, priv->clks); + clk_bulk_disable_unprepare(priv->clk_num, priv->clks); platform_device_unregister(priv->ipc_dev); } @@ -336,9 +328,11 @@ static int imx8m_resume(struct snd_sof_dev *sdev) int ret; int i; - ret = imx8_enable_clocks(sdev, priv->clks); - if (ret < 0) + ret = clk_bulk_prepare_enable(priv->clk_num, priv->clks); + if (ret < 0) { + dev_err(sdev->dev, "failed to enable clocks: %d\n", ret); return ret; + } for (i = 0; i < DSP_MU_CHAN_NUM; i++) imx_dsp_request_channel(priv->dsp_ipc, i); @@ -354,7 +348,7 @@ static void imx8m_suspend(struct snd_sof_dev *sdev) for (i = 0; i < DSP_MU_CHAN_NUM; i++) imx_dsp_free_channel(priv->dsp_ipc, i); - imx8_disable_clocks(sdev, priv->clks); + clk_bulk_disable_unprepare(priv->clk_num, priv->clks); } static int imx8m_dsp_runtime_resume(struct snd_sof_dev *sdev) diff --git a/sound/soc/sof/imx/imx8ulp.c b/sound/soc/sof/imx/imx8ulp.c index 7b527ffde488..296fbf11f6d0 100644 --- a/sound/soc/sof/imx/imx8ulp.c +++ b/sound/soc/sof/imx/imx8ulp.c @@ -40,13 +40,6 @@ #define MBOX_OFFSET 0x800000 #define MBOX_SIZE 0x1000 -static struct clk_bulk_data imx8ulp_dsp_clks[] = { - { .id = "core" }, - { .id = "ipg" }, - { .id = "ocram" }, - { .id = "mu" }, -}; - struct imx8ulp_priv { struct device *dev; struct snd_sof_dev *sdev; @@ -56,7 +49,8 @@ struct imx8ulp_priv { struct platform_device *ipc_dev; struct regmap *regmap; - struct imx_clocks *clks; + struct clk_bulk_data *clks; + int clk_num; }; static void imx8ulp_sim_lpav_start(struct imx8ulp_priv *priv) @@ -175,10 +169,6 @@ static int imx8ulp_probe(struct snd_sof_dev *sdev) if (!priv) return -ENOMEM; - priv->clks = devm_kzalloc(&pdev->dev, sizeof(*priv->clks), GFP_KERNEL); - if (!priv->clks) - return -ENOMEM; - sdev->num_cores = 1; sdev->pdata->hw_pdata = priv; priv->dev = sdev->dev; @@ -259,16 +249,18 @@ static int imx8ulp_probe(struct snd_sof_dev *sdev) goto exit_pdev_unregister; } - priv->clks->dsp_clks = imx8ulp_dsp_clks; - priv->clks->num_dsp_clks = ARRAY_SIZE(imx8ulp_dsp_clks); - - ret = imx8_parse_clocks(sdev, priv->clks); - if (ret < 0) + ret = devm_clk_bulk_get_all(sdev->dev, &priv->clks); + if (ret < 0) { + dev_err(sdev->dev, "failed to fetch clocks: %d\n", ret); goto exit_pdev_unregister; + } + priv->clk_num = ret; - ret = imx8_enable_clocks(sdev, priv->clks); - if (ret < 0) + ret = clk_bulk_prepare_enable(priv->clk_num, priv->clks); + if (ret < 0) { + dev_err(sdev->dev, "failed to enable clocks: %d\n", ret); goto exit_pdev_unregister; + } return 0; @@ -282,7 +274,7 @@ static void imx8ulp_remove(struct snd_sof_dev *sdev) { struct imx8ulp_priv *priv = sdev->pdata->hw_pdata; - imx8_disable_clocks(sdev, priv->clks); + clk_bulk_disable_unprepare(priv->clk_num, priv->clks); platform_device_unregister(priv->ipc_dev); } @@ -303,7 +295,7 @@ static int imx8ulp_suspend(struct snd_sof_dev *sdev) for (i = 0; i < DSP_MU_CHAN_NUM; i++) imx_dsp_free_channel(priv->dsp_ipc, i); - imx8_disable_clocks(sdev, priv->clks); + clk_bulk_disable_unprepare(priv->clk_num, priv->clks); return 0; } @@ -311,9 +303,13 @@ static int imx8ulp_suspend(struct snd_sof_dev *sdev) static int imx8ulp_resume(struct snd_sof_dev *sdev) { struct imx8ulp_priv *priv = (struct imx8ulp_priv *)sdev->pdata->hw_pdata; - int i; + int i, ret; - imx8_enable_clocks(sdev, priv->clks); + ret = clk_bulk_prepare_enable(priv->clk_num, priv->clks); + if (ret < 0) { + dev_err(sdev->dev, "failed to enable clocks: %d\n", ret); + return ret; + } for (i = 0; i < DSP_MU_CHAN_NUM; i++) imx_dsp_request_channel(priv->dsp_ipc, i); -- cgit v1.2.3 From e618b8b37aa1dac42f50c87373d71ecc68ead97d Mon Sep 17 00:00:00 2001 From: Laurentiu Mihalcea Date: Fri, 29 Mar 2024 00:12:01 +0200 Subject: ASoC: SOF: imx: remove imx8_*_clocks API Since the i.MX drivers no longer use the imx8_*_clocks API this can be removed. Signed-off-by: Laurentiu Mihalcea Reviewed-by: Iuliana Prodan Reviewed-by: Pierre-Louis Bossart Reviewed-by: Daniel Baluta Link: https://msgid.link/r/20240328221201.24722-3-laurentiumihalcea111@gmail.com Signed-off-by: Mark Brown --- sound/soc/sof/imx/imx-common.c | 24 ------------------------ sound/soc/sof/imx/imx-common.h | 9 --------- 2 files changed, 33 deletions(-) diff --git a/sound/soc/sof/imx/imx-common.c b/sound/soc/sof/imx/imx-common.c index 36e3d414a18f..2981aea123d9 100644 --- a/sound/soc/sof/imx/imx-common.c +++ b/sound/soc/sof/imx/imx-common.c @@ -74,28 +74,4 @@ void imx8_dump(struct snd_sof_dev *sdev, u32 flags) } EXPORT_SYMBOL(imx8_dump); -int imx8_parse_clocks(struct snd_sof_dev *sdev, struct imx_clocks *clks) -{ - int ret; - - ret = devm_clk_bulk_get(sdev->dev, clks->num_dsp_clks, clks->dsp_clks); - if (ret) - dev_err(sdev->dev, "Failed to request DSP clocks\n"); - - return ret; -} -EXPORT_SYMBOL(imx8_parse_clocks); - -int imx8_enable_clocks(struct snd_sof_dev *sdev, struct imx_clocks *clks) -{ - return clk_bulk_prepare_enable(clks->num_dsp_clks, clks->dsp_clks); -} -EXPORT_SYMBOL(imx8_enable_clocks); - -void imx8_disable_clocks(struct snd_sof_dev *sdev, struct imx_clocks *clks) -{ - clk_bulk_disable_unprepare(clks->num_dsp_clks, clks->dsp_clks); -} -EXPORT_SYMBOL(imx8_disable_clocks); - MODULE_LICENSE("Dual BSD/GPL"); diff --git a/sound/soc/sof/imx/imx-common.h b/sound/soc/sof/imx/imx-common.h index ec4b3a5c7496..13d7f3ef675e 100644 --- a/sound/soc/sof/imx/imx-common.h +++ b/sound/soc/sof/imx/imx-common.h @@ -15,13 +15,4 @@ void imx8_get_registers(struct snd_sof_dev *sdev, void imx8_dump(struct snd_sof_dev *sdev, u32 flags); -struct imx_clocks { - struct clk_bulk_data *dsp_clks; - int num_dsp_clks; -}; - -int imx8_parse_clocks(struct snd_sof_dev *sdev, struct imx_clocks *clks); -int imx8_enable_clocks(struct snd_sof_dev *sdev, struct imx_clocks *clks); -void imx8_disable_clocks(struct snd_sof_dev *sdev, struct imx_clocks *clks); - #endif -- cgit v1.2.3 From 1d86c2b3946e69d6b0b93568d312aae6247847c0 Mon Sep 17 00:00:00 2001 From: Frank Li Date: Mon, 1 Apr 2024 18:25:03 -0400 Subject: arm64: dts: imx8-ss-lsio: fix pwm lpcg indices lpcg's arg0 should use clock indices instead of index. pwm0_lpcg: clock-controller@5d400000 { ... // Col1 Col2 clocks = <&clk IMX_SC_R_PWM_0 IMX_SC_PM_CLK_PER>, // 0 0 <&clk IMX_SC_R_PWM_0 IMX_SC_PM_CLK_PER>, // 1 1 <&clk IMX_SC_R_PWM_0 IMX_SC_PM_CLK_PER>, // 2 4 <&lsio_bus_clk>, // 3 5 <&clk IMX_SC_R_PWM_0 IMX_SC_PM_CLK_PER>; // 4 6 clock-indices = , , , , ; }; Col1: index, which existing dts try to get. Col2: actual index in lpcg driver. pwm1 { .... clocks = <&pwm1_lpcg 4>, <&pwm1_lpcg 1>; ^^ ^^ should be: clocks = <&pwm1_lpcg IMX_LPCG_CLK_6>, <&pwm1_lpcg IMX_LPCG_CLK_1>; }; Arg0 is divided by 4 in lpcg driver, so index 0 and 1 will be get by pwm driver, which are same as IMX_LPCG_CLK_6 and IMX_LPCG_CLK_1. Even it can work, but code logic is wrong. Fixed it by use correct indices. Cc: stable@vger.kernel.org Fixes: 23fa99b205ea ("arm64: dts: freescale: imx8-ss-lsio: add support for lsio_pwm0-3") Signed-off-by: Frank Li Signed-off-by: Shawn Guo --- arch/arm64/boot/dts/freescale/imx8-ss-lsio.dtsi | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/arch/arm64/boot/dts/freescale/imx8-ss-lsio.dtsi b/arch/arm64/boot/dts/freescale/imx8-ss-lsio.dtsi index 7e510b21bbac..764c1a08e3b1 100644 --- a/arch/arm64/boot/dts/freescale/imx8-ss-lsio.dtsi +++ b/arch/arm64/boot/dts/freescale/imx8-ss-lsio.dtsi @@ -25,8 +25,8 @@ lsio_subsys: bus@5d000000 { compatible = "fsl,imx27-pwm"; reg = <0x5d000000 0x10000>; clock-names = "ipg", "per"; - clocks = <&pwm0_lpcg 4>, - <&pwm0_lpcg 1>; + clocks = <&pwm0_lpcg IMX_LPCG_CLK_6>, + <&pwm0_lpcg IMX_LPCG_CLK_1>; assigned-clocks = <&clk IMX_SC_R_PWM_0 IMX_SC_PM_CLK_PER>; assigned-clock-rates = <24000000>; #pwm-cells = <3>; @@ -38,8 +38,8 @@ lsio_subsys: bus@5d000000 { compatible = "fsl,imx27-pwm"; reg = <0x5d010000 0x10000>; clock-names = "ipg", "per"; - clocks = <&pwm1_lpcg 4>, - <&pwm1_lpcg 1>; + clocks = <&pwm1_lpcg IMX_LPCG_CLK_6>, + <&pwm1_lpcg IMX_LPCG_CLK_1>; assigned-clocks = <&clk IMX_SC_R_PWM_1 IMX_SC_PM_CLK_PER>; assigned-clock-rates = <24000000>; #pwm-cells = <3>; @@ -51,8 +51,8 @@ lsio_subsys: bus@5d000000 { compatible = "fsl,imx27-pwm"; reg = <0x5d020000 0x10000>; clock-names = "ipg", "per"; - clocks = <&pwm2_lpcg 4>, - <&pwm2_lpcg 1>; + clocks = <&pwm2_lpcg IMX_LPCG_CLK_6>, + <&pwm2_lpcg IMX_LPCG_CLK_1>; assigned-clocks = <&clk IMX_SC_R_PWM_2 IMX_SC_PM_CLK_PER>; assigned-clock-rates = <24000000>; #pwm-cells = <3>; @@ -64,8 +64,8 @@ lsio_subsys: bus@5d000000 { compatible = "fsl,imx27-pwm"; reg = <0x5d030000 0x10000>; clock-names = "ipg", "per"; - clocks = <&pwm3_lpcg 4>, - <&pwm3_lpcg 1>; + clocks = <&pwm3_lpcg IMX_LPCG_CLK_6>, + <&pwm3_lpcg IMX_LPCG_CLK_1>; assigned-clocks = <&clk IMX_SC_R_PWM_3 IMX_SC_PM_CLK_PER>; assigned-clock-rates = <24000000>; #pwm-cells = <3>; -- cgit v1.2.3 From 808e7716edcdb39d3498b9f567ef6017858b49aa Mon Sep 17 00:00:00 2001 From: Frank Li Date: Mon, 1 Apr 2024 18:25:04 -0400 Subject: arm64: dts: imx8-ss-conn: fix usb lpcg indices usb2_lpcg: clock-controller@5b270000 { ... Col1 Col2 clocks = <&conn_ahb_clk>, <&conn_ipg_clk>; // 0 6 clock-indices = , ; // 0 7 ... }; Col1: index, which existing dts try to get. Col2: actual index in lpcg driver. usbotg1: usb@5b0d0000 { ... clocks = <&usb2_lpcg 0>; ^^ Should be: clocks = <&usb2_lpcg IMX_LPCG_CLK_6>; }; usbphy1: usbphy@5b100000 { clocks = <&usb2_lpcg 1>; ^^ SHould be: clocks = <&usb2_lpcg IMX_LPCG_CLK_7>; }; Arg0 is divided by 4 in lpcg driver. So lpcg will do dummy enable. Fix it by use correct clock indices. Cc: stable@vger.kernel.org Fixes: 8065fc937f0f ("arm64: dts: imx8dxl: add usb1 and usb2 support") Signed-off-by: Frank Li Signed-off-by: Shawn Guo --- arch/arm64/boot/dts/freescale/imx8-ss-conn.dtsi | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/arm64/boot/dts/freescale/imx8-ss-conn.dtsi b/arch/arm64/boot/dts/freescale/imx8-ss-conn.dtsi index af2259e99796..4aaf5a0c1ed8 100644 --- a/arch/arm64/boot/dts/freescale/imx8-ss-conn.dtsi +++ b/arch/arm64/boot/dts/freescale/imx8-ss-conn.dtsi @@ -41,7 +41,7 @@ conn_subsys: bus@5b000000 { interrupts = ; fsl,usbphy = <&usbphy1>; fsl,usbmisc = <&usbmisc1 0>; - clocks = <&usb2_lpcg 0>; + clocks = <&usb2_lpcg IMX_LPCG_CLK_6>; ahb-burst-config = <0x0>; tx-burst-size-dword = <0x10>; rx-burst-size-dword = <0x10>; @@ -58,7 +58,7 @@ conn_subsys: bus@5b000000 { usbphy1: usbphy@5b100000 { compatible = "fsl,imx7ulp-usbphy"; reg = <0x5b100000 0x1000>; - clocks = <&usb2_lpcg 1>; + clocks = <&usb2_lpcg IMX_LPCG_CLK_7>; power-domains = <&pd IMX_SC_R_USB_0_PHY>; status = "disabled"; }; -- cgit v1.2.3 From f72b544a514c07d34a0d9d5380f5905b3731e647 Mon Sep 17 00:00:00 2001 From: Frank Li Date: Mon, 1 Apr 2024 18:25:05 -0400 Subject: arm64: dts: imx8-ss-dma: fix spi lpcg indices spi0_lpcg: clock-controller@5a400000 { ... Col0 Col1 clocks = <&clk IMX_SC_R_SPI_0 IMX_SC_PM_CLK_PER>,// 0 1 <&dma_ipg_clk>; // 1 4 clock-indices = , ; }; Col1: index, which existing dts try to get. Col2: actual index in lpcg driver. lpspi0: spi@5a000000 { ... clocks = <&spi0_lpcg 0>, <&spi0_lpcg 1>; ^ ^ Should be: clocks = <&spi0_lpcg IMX_LPCG_CLK_0>, <&spi0_lpcg IMX_LPCG_CLK_4>; }; Arg0 is divided by 4 in lpcg driver. <&spi0_lpcg 0> and <&spi0_lpcg 1> are IMX_SC_PM_CLK_PER. Although code can work, code logic is wrong. It should use IMX_LPCG_CLK_0 and IMX_LPCG_CLK_4 for lpcg arg0. Cc: stable@vger.kernel.org Fixes: c4098885e790 ("arm64: dts: imx8dxl: add lpspi support") Signed-off-by: Frank Li Signed-off-by: Shawn Guo --- arch/arm64/boot/dts/freescale/imx8-ss-dma.dtsi | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/arch/arm64/boot/dts/freescale/imx8-ss-dma.dtsi b/arch/arm64/boot/dts/freescale/imx8-ss-dma.dtsi index cab3468b1875..169cf885c744 100644 --- a/arch/arm64/boot/dts/freescale/imx8-ss-dma.dtsi +++ b/arch/arm64/boot/dts/freescale/imx8-ss-dma.dtsi @@ -28,8 +28,8 @@ dma_subsys: bus@5a000000 { #size-cells = <0>; interrupts = ; interrupt-parent = <&gic>; - clocks = <&spi0_lpcg 0>, - <&spi0_lpcg 1>; + clocks = <&spi0_lpcg IMX_LPCG_CLK_0>, + <&spi0_lpcg IMX_LPCG_CLK_4>; clock-names = "per", "ipg"; assigned-clocks = <&clk IMX_SC_R_SPI_0 IMX_SC_PM_CLK_PER>; assigned-clock-rates = <60000000>; @@ -44,8 +44,8 @@ dma_subsys: bus@5a000000 { #size-cells = <0>; interrupts = ; interrupt-parent = <&gic>; - clocks = <&spi1_lpcg 0>, - <&spi1_lpcg 1>; + clocks = <&spi1_lpcg IMX_LPCG_CLK_0>, + <&spi1_lpcg IMX_LPCG_CLK_4>; clock-names = "per", "ipg"; assigned-clocks = <&clk IMX_SC_R_SPI_1 IMX_SC_PM_CLK_PER>; assigned-clock-rates = <60000000>; @@ -60,8 +60,8 @@ dma_subsys: bus@5a000000 { #size-cells = <0>; interrupts = ; interrupt-parent = <&gic>; - clocks = <&spi2_lpcg 0>, - <&spi2_lpcg 1>; + clocks = <&spi2_lpcg IMX_LPCG_CLK_0>, + <&spi2_lpcg IMX_LPCG_CLK_4>; clock-names = "per", "ipg"; assigned-clocks = <&clk IMX_SC_R_SPI_2 IMX_SC_PM_CLK_PER>; assigned-clock-rates = <60000000>; @@ -76,8 +76,8 @@ dma_subsys: bus@5a000000 { #size-cells = <0>; interrupts = ; interrupt-parent = <&gic>; - clocks = <&spi3_lpcg 0>, - <&spi3_lpcg 1>; + clocks = <&spi3_lpcg IMX_LPCG_CLK_0>, + <&spi3_lpcg IMX_LPCG_CLK_4>; clock-names = "per", "ipg"; assigned-clocks = <&clk IMX_SC_R_SPI_3 IMX_SC_PM_CLK_PER>; assigned-clock-rates = <60000000>; -- cgit v1.2.3 From 9055d87bce7276234173fa90e9702af31b3f5353 Mon Sep 17 00:00:00 2001 From: Frank Li Date: Mon, 1 Apr 2024 18:25:06 -0400 Subject: arm64: dts: imx8-ss-dma: fix pwm lpcg indices adma_pwm_lpcg: clock-controller@5a590000 { ... col1 col2 clocks = <&clk IMX_SC_R_LCD_0_PWM_0 IMX_SC_PM_CLK_PER>,// 0 0 <&dma_ipg_clk>; // 1 4 clock-indices = , ; ... }; Col1: index, which existing dts try to get. Col2: actual index in lpcg driver. adma_pwm: pwm@5a190000 { ... clocks = <&adma_pwm_lpcg 1>, <&adma_pwm_lpcg 0>; ^^ ^^ Should be clocks = <&adma_pwm_lpcg IMX_LPCG_CLK_4>, <&adma_pwm_lpcg IMX_LPCG_CLK_0>; }; Arg0 will be divided by 4 in lcpg driver, so pwm will get IMX_SC_PM_CLK_PER by <&adma_pwm_lpcg 1>, <&adma_pwm_lpcg 0>. Although function can work, code logic is wrong. Fix it by use correct indices. Cc: stable@vger.kernel.org Fixes: f1d6a6b991ef ("arm64: dts: imx8qxp: add adma_pwm in adma") Signed-off-by: Frank Li Signed-off-by: Shawn Guo --- arch/arm64/boot/dts/freescale/imx8-ss-dma.dtsi | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/arm64/boot/dts/freescale/imx8-ss-dma.dtsi b/arch/arm64/boot/dts/freescale/imx8-ss-dma.dtsi index 169cf885c744..e3e911e57790 100644 --- a/arch/arm64/boot/dts/freescale/imx8-ss-dma.dtsi +++ b/arch/arm64/boot/dts/freescale/imx8-ss-dma.dtsi @@ -145,8 +145,8 @@ dma_subsys: bus@5a000000 { compatible = "fsl,imx8qxp-pwm", "fsl,imx27-pwm"; reg = <0x5a190000 0x1000>; interrupts = ; - clocks = <&adma_pwm_lpcg 1>, - <&adma_pwm_lpcg 0>; + clocks = <&adma_pwm_lpcg IMX_LPCG_CLK_4>, + <&adma_pwm_lpcg IMX_LPCG_CLK_0>; clock-names = "ipg", "per"; assigned-clocks = <&clk IMX_SC_R_LCD_0_PWM_0 IMX_SC_PM_CLK_PER>; assigned-clock-rates = <24000000>; -- cgit v1.2.3 From 81975080f14167610976e968e8016e92d836266f Mon Sep 17 00:00:00 2001 From: Frank Li Date: Mon, 1 Apr 2024 18:25:07 -0400 Subject: arm64: dts: imx8-ss-dma: fix adc lpcg indices adc0_lpcg: clock-controller@5ac80000 { ... Col1 Col2 clocks = <&clk IMX_SC_R_ADC_0 IMX_SC_PM_CLK_PER>, // 0 0 <&dma_ipg_clk>; // 1 4 clock-indices = , ; }; Col1: index, which existing dts try to get. Col2: actual index in lpcg driver. adc0: adc@5a880000 { clocks = <&adc0_lpcg 0>, <&adc0_lpcg 1>; ^^ ^^ clocks = <&adc0_lpcg IMX_LPCG_CLK_0>, <&adc0_lpcg IMX_LPCG_CLK_4>; Arg0 is divided by 4 in lpcg driver. So adc get IMX_SC_PM_CLK_PER by <&adc0_lpcg 0>, <&adc0_lpcg 1>. Although function can work, code logic is wrong. Fix it by using correct indices. Cc: stable@vger.kernel.org Fixes: 1db044b25d2e ("arm64: dts: imx8dxl: add adc0 support") Signed-off-by: Frank Li Signed-off-by: Shawn Guo --- arch/arm64/boot/dts/freescale/imx8-ss-dma.dtsi | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/arch/arm64/boot/dts/freescale/imx8-ss-dma.dtsi b/arch/arm64/boot/dts/freescale/imx8-ss-dma.dtsi index e3e911e57790..23d59b34bc4c 100644 --- a/arch/arm64/boot/dts/freescale/imx8-ss-dma.dtsi +++ b/arch/arm64/boot/dts/freescale/imx8-ss-dma.dtsi @@ -355,8 +355,8 @@ dma_subsys: bus@5a000000 { reg = <0x5a880000 0x10000>; interrupts = ; interrupt-parent = <&gic>; - clocks = <&adc0_lpcg 0>, - <&adc0_lpcg 1>; + clocks = <&adc0_lpcg IMX_LPCG_CLK_0>, + <&adc0_lpcg IMX_LPCG_CLK_4>; clock-names = "per", "ipg"; assigned-clocks = <&clk IMX_SC_R_ADC_0 IMX_SC_PM_CLK_PER>; assigned-clock-rates = <24000000>; @@ -370,8 +370,8 @@ dma_subsys: bus@5a000000 { reg = <0x5a890000 0x10000>; interrupts = ; interrupt-parent = <&gic>; - clocks = <&adc1_lpcg 0>, - <&adc1_lpcg 1>; + clocks = <&adc1_lpcg IMX_LPCG_CLK_0>, + <&adc1_lpcg IMX_LPCG_CLK_4>; clock-names = "per", "ipg"; assigned-clocks = <&clk IMX_SC_R_ADC_1 IMX_SC_PM_CLK_PER>; assigned-clock-rates = <24000000>; -- cgit v1.2.3 From 0893392334b5dffdf616a53679c6a2942c46391b Mon Sep 17 00:00:00 2001 From: Frank Li Date: Mon, 1 Apr 2024 18:25:08 -0400 Subject: arm64: dts: imx8-ss-dma: fix can lpcg indices can0_lpcg: clock-controller@5acd0000 { ... Col1 Col2 clocks = <&clk IMX_SC_R_CAN_0 IMX_SC_PM_CLK_PER>, // 0 0 <&dma_ipg_clk>, // 1 4 <&dma_ipg_clk>; // 2 5 clock-indices = , , ; } Col1: index, which existing dts try to get. Col2: actual index in lpcg driver. flexcan1: can@5a8d0000 { clocks = <&can0_lpcg 1>, <&can0_lpcg 0>; ^^ ^^ Should be: clocks = <&can0_lpcg IMX_LPCG_CLK_4>, <&can0_lpcg IMX_LPCG_CLK_0>; }; Arg0 is divided by 4 in lpcg driver. flexcan driver get IMX_SC_PM_CLK_PER by <&can0_lpcg 1> and <&can0_lpcg 0>. Although function can work, code logic is wrong. Fix it by using correct clock indices. Cc: stable@vger.kernel.org Fixes: 5e7d5b023e03 ("arm64: dts: imx8qxp: add flexcan in adma") Signed-off-by: Frank Li Signed-off-by: Shawn Guo --- arch/arm64/boot/dts/freescale/imx8-ss-dma.dtsi | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/arch/arm64/boot/dts/freescale/imx8-ss-dma.dtsi b/arch/arm64/boot/dts/freescale/imx8-ss-dma.dtsi index 23d59b34bc4c..f7a91d43a0ff 100644 --- a/arch/arm64/boot/dts/freescale/imx8-ss-dma.dtsi +++ b/arch/arm64/boot/dts/freescale/imx8-ss-dma.dtsi @@ -384,8 +384,8 @@ dma_subsys: bus@5a000000 { reg = <0x5a8d0000 0x10000>; interrupts = ; interrupt-parent = <&gic>; - clocks = <&can0_lpcg 1>, - <&can0_lpcg 0>; + clocks = <&can0_lpcg IMX_LPCG_CLK_4>, + <&can0_lpcg IMX_LPCG_CLK_0>; clock-names = "ipg", "per"; assigned-clocks = <&clk IMX_SC_R_CAN_0 IMX_SC_PM_CLK_PER>; assigned-clock-rates = <40000000>; @@ -405,8 +405,8 @@ dma_subsys: bus@5a000000 { * CAN1 shares CAN0's clock and to enable CAN0's clock it * has to be powered on. */ - clocks = <&can0_lpcg 1>, - <&can0_lpcg 0>; + clocks = <&can0_lpcg IMX_LPCG_CLK_4>, + <&can0_lpcg IMX_LPCG_CLK_0>; clock-names = "ipg", "per"; assigned-clocks = <&clk IMX_SC_R_CAN_0 IMX_SC_PM_CLK_PER>; assigned-clock-rates = <40000000>; @@ -426,8 +426,8 @@ dma_subsys: bus@5a000000 { * CAN2 shares CAN0's clock and to enable CAN0's clock it * has to be powered on. */ - clocks = <&can0_lpcg 1>, - <&can0_lpcg 0>; + clocks = <&can0_lpcg IMX_LPCG_CLK_4>, + <&can0_lpcg IMX_LPCG_CLK_0>; clock-names = "ipg", "per"; assigned-clocks = <&clk IMX_SC_R_CAN_0 IMX_SC_PM_CLK_PER>; assigned-clock-rates = <40000000>; -- cgit v1.2.3 From 00b436182138310bb8d362b912b12a9df8f72ca3 Mon Sep 17 00:00:00 2001 From: Frank Li Date: Mon, 1 Apr 2024 18:25:09 -0400 Subject: arm64: dts: imx8qm-ss-dma: fix can lpcg indices can1_lpcg: clock-controller@5ace0000 { ... Col1 Col2 clocks = <&clk IMX_SC_R_CAN_1 IMX_SC_PM_CLK_PER>,// 0 0 <&dma_ipg_clk>, // 1 4 <&dma_ipg_clk>; // 2 5 clock-indices = , , ; }; Col1: index, which existing dts try to get. Col2: actual index in lpcg driver &flexcan2 { clocks = <&can1_lpcg 1>, <&can1_lpcg 0>; ^^ ^^ Should be: clocks = <&can1_lpcg IMX_LPCG_CLK_4>, <&can1_lpcg IMX_LPCG_CLK_0>; }; Arg0 is divided by 4 in lpcg driver. So flexcan get IMX_SC_PM_CLK_PER by <&can1_lpcg 1> and <&can1_lpcg 0>. Although function work, code logic is wrong. Fix it by using correct clock indices. Cc: stable@vger.kernel.org Fixes: be85831de020 ("arm64: dts: imx8qm: add can node in devicetree") Signed-off-by: Frank Li Signed-off-by: Shawn Guo --- arch/arm64/boot/dts/freescale/imx8qm-ss-dma.dtsi | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/arch/arm64/boot/dts/freescale/imx8qm-ss-dma.dtsi b/arch/arm64/boot/dts/freescale/imx8qm-ss-dma.dtsi index 11626fae5f97..aa9f28c4431d 100644 --- a/arch/arm64/boot/dts/freescale/imx8qm-ss-dma.dtsi +++ b/arch/arm64/boot/dts/freescale/imx8qm-ss-dma.dtsi @@ -153,15 +153,15 @@ }; &flexcan2 { - clocks = <&can1_lpcg 1>, - <&can1_lpcg 0>; + clocks = <&can1_lpcg IMX_LPCG_CLK_4>, + <&can1_lpcg IMX_LPCG_CLK_0>; assigned-clocks = <&clk IMX_SC_R_CAN_1 IMX_SC_PM_CLK_PER>; fsl,clk-source = /bits/ 8 <1>; }; &flexcan3 { - clocks = <&can2_lpcg 1>, - <&can2_lpcg 0>; + clocks = <&can2_lpcg IMX_LPCG_CLK_4>, + <&can2_lpcg IMX_LPCG_CLK_0>; assigned-clocks = <&clk IMX_SC_R_CAN_2 IMX_SC_PM_CLK_PER>; fsl,clk-source = /bits/ 8 <1>; }; -- cgit v1.2.3 From 4d0333798ebbfa1683cc3bc056d1b25b8c24344c Mon Sep 17 00:00:00 2001 From: Simon Trimmer Date: Mon, 25 Mar 2024 11:31:23 +0000 Subject: firmware: cs_dsp: Add locked wrappers for coeff read and write It is a common pattern for functions to take and release the DSP pwr_lock over the cs_dsp calls to read and write firmware controls. Add wrapper functions to do this sequence so that the calling code can be simplified to a single function call.. Signed-off-by: Simon Trimmer Signed-off-by: Richard Fitzgerald Reviewed-by: Takashi Iwai Link: https://msgid.link/r/20240325113127.112783-2-rf@opensource.cirrus.com Signed-off-by: Mark Brown --- drivers/firmware/cirrus/cs_dsp.c | 54 ++++++++++++++++++++++++++++++++++ include/linux/firmware/cirrus/cs_dsp.h | 4 +++ 2 files changed, 58 insertions(+) diff --git a/drivers/firmware/cirrus/cs_dsp.c b/drivers/firmware/cirrus/cs_dsp.c index 79d4254d1f9b..1263382e0d10 100644 --- a/drivers/firmware/cirrus/cs_dsp.c +++ b/drivers/firmware/cirrus/cs_dsp.c @@ -819,6 +819,33 @@ int cs_dsp_coeff_write_ctrl(struct cs_dsp_coeff_ctl *ctl, } EXPORT_SYMBOL_NS_GPL(cs_dsp_coeff_write_ctrl, FW_CS_DSP); +/** + * cs_dsp_coeff_lock_and_write_ctrl() - Writes the given buffer to the given coefficient control + * @ctl: pointer to coefficient control + * @off: word offset at which data should be written + * @buf: the buffer to write to the given control + * @len: the length of the buffer in bytes + * + * Same as cs_dsp_coeff_write_ctrl() but takes pwr_lock. + * + * Return: A negative number on error, 1 when the control value changed and 0 when it has not. + */ +int cs_dsp_coeff_lock_and_write_ctrl(struct cs_dsp_coeff_ctl *ctl, + unsigned int off, const void *buf, size_t len) +{ + struct cs_dsp *dsp = ctl->dsp; + int ret; + + lockdep_assert_not_held(&dsp->pwr_lock); + + mutex_lock(&dsp->pwr_lock); + ret = cs_dsp_coeff_write_ctrl(ctl, off, buf, len); + mutex_unlock(&dsp->pwr_lock); + + return ret; +} +EXPORT_SYMBOL_GPL(cs_dsp_coeff_lock_and_write_ctrl); + static int cs_dsp_coeff_read_ctrl_raw(struct cs_dsp_coeff_ctl *ctl, unsigned int off, void *buf, size_t len) { @@ -891,6 +918,33 @@ int cs_dsp_coeff_read_ctrl(struct cs_dsp_coeff_ctl *ctl, } EXPORT_SYMBOL_NS_GPL(cs_dsp_coeff_read_ctrl, FW_CS_DSP); +/** + * cs_dsp_coeff_lock_and_read_ctrl() - Reads the given coefficient control into the given buffer + * @ctl: pointer to coefficient control + * @off: word offset at which data should be read + * @buf: the buffer to store to the given control + * @len: the length of the buffer in bytes + * + * Same as cs_dsp_coeff_read_ctrl() but takes pwr_lock. + * + * Return: Zero for success, a negative number on error. + */ +int cs_dsp_coeff_lock_and_read_ctrl(struct cs_dsp_coeff_ctl *ctl, + unsigned int off, void *buf, size_t len) +{ + struct cs_dsp *dsp = ctl->dsp; + int ret; + + lockdep_assert_not_held(&dsp->pwr_lock); + + mutex_lock(&dsp->pwr_lock); + ret = cs_dsp_coeff_read_ctrl(ctl, off, buf, len); + mutex_unlock(&dsp->pwr_lock); + + return ret; +} +EXPORT_SYMBOL_GPL(cs_dsp_coeff_lock_and_read_ctrl); + static int cs_dsp_coeff_init_control_caches(struct cs_dsp *dsp) { struct cs_dsp_coeff_ctl *ctl; diff --git a/include/linux/firmware/cirrus/cs_dsp.h b/include/linux/firmware/cirrus/cs_dsp.h index 29cd11d5a3cf..6097b1f701f1 100644 --- a/include/linux/firmware/cirrus/cs_dsp.h +++ b/include/linux/firmware/cirrus/cs_dsp.h @@ -239,8 +239,12 @@ void cs_dsp_cleanup_debugfs(struct cs_dsp *dsp); int cs_dsp_coeff_write_acked_control(struct cs_dsp_coeff_ctl *ctl, unsigned int event_id); int cs_dsp_coeff_write_ctrl(struct cs_dsp_coeff_ctl *ctl, unsigned int off, const void *buf, size_t len); +int cs_dsp_coeff_lock_and_write_ctrl(struct cs_dsp_coeff_ctl *ctl, unsigned int off, + const void *buf, size_t len); int cs_dsp_coeff_read_ctrl(struct cs_dsp_coeff_ctl *ctl, unsigned int off, void *buf, size_t len); +int cs_dsp_coeff_lock_and_read_ctrl(struct cs_dsp_coeff_ctl *ctl, unsigned int off, + void *buf, size_t len); struct cs_dsp_coeff_ctl *cs_dsp_get_ctl(struct cs_dsp *dsp, const char *name, int type, unsigned int alg); -- cgit v1.2.3 From 3802a9969bd365749f5e34928082cff96ed7769b Mon Sep 17 00:00:00 2001 From: Simon Trimmer Date: Mon, 25 Mar 2024 11:31:24 +0000 Subject: ASoC: wm_adsp: Use cs_dsp_coeff_lock_and_[read|write]_ctrl() Using the cs_dsp_coeff_lock_and_[read|write]_ctrl() wrappers tidies the calling functions as it does not need to manage the DSP pwr_lock. Signed-off-by: Simon Trimmer Signed-off-by: Richard Fitzgerald Reviewed-by: Takashi Iwai Link: https://msgid.link/r/20240325113127.112783-3-rf@opensource.cirrus.com Signed-off-by: Mark Brown --- sound/soc/codecs/wm_adsp.c | 24 ++++++------------------ 1 file changed, 6 insertions(+), 18 deletions(-) diff --git a/sound/soc/codecs/wm_adsp.c b/sound/soc/codecs/wm_adsp.c index 9cb9068c0462..f41d668e4c01 100644 --- a/sound/soc/codecs/wm_adsp.c +++ b/sound/soc/codecs/wm_adsp.c @@ -403,13 +403,8 @@ static int wm_coeff_put(struct snd_kcontrol *kctl, struct wm_coeff_ctl *ctl = bytes_ext_to_ctl(bytes_ext); struct cs_dsp_coeff_ctl *cs_ctl = ctl->cs_ctl; char *p = ucontrol->value.bytes.data; - int ret = 0; - - mutex_lock(&cs_ctl->dsp->pwr_lock); - ret = cs_dsp_coeff_write_ctrl(cs_ctl, 0, p, cs_ctl->len); - mutex_unlock(&cs_ctl->dsp->pwr_lock); - return ret; + return cs_dsp_coeff_lock_and_write_ctrl(cs_ctl, 0, p, cs_ctl->len); } static int wm_coeff_tlv_put(struct snd_kcontrol *kctl, @@ -426,13 +421,11 @@ static int wm_coeff_tlv_put(struct snd_kcontrol *kctl, if (!scratch) return -ENOMEM; - if (copy_from_user(scratch, bytes, size)) { + if (copy_from_user(scratch, bytes, size)) ret = -EFAULT; - } else { - mutex_lock(&cs_ctl->dsp->pwr_lock); - ret = cs_dsp_coeff_write_ctrl(cs_ctl, 0, scratch, size); - mutex_unlock(&cs_ctl->dsp->pwr_lock); - } + else + ret = cs_dsp_coeff_lock_and_write_ctrl(cs_ctl, 0, scratch, size); + vfree(scratch); return ret; @@ -474,13 +467,8 @@ static int wm_coeff_get(struct snd_kcontrol *kctl, struct wm_coeff_ctl *ctl = bytes_ext_to_ctl(bytes_ext); struct cs_dsp_coeff_ctl *cs_ctl = ctl->cs_ctl; char *p = ucontrol->value.bytes.data; - int ret; - mutex_lock(&cs_ctl->dsp->pwr_lock); - ret = cs_dsp_coeff_read_ctrl(cs_ctl, 0, p, cs_ctl->len); - mutex_unlock(&cs_ctl->dsp->pwr_lock); - - return ret; + return cs_dsp_coeff_lock_and_read_ctrl(cs_ctl, 0, p, cs_ctl->len); } static int wm_coeff_tlv_get(struct snd_kcontrol *kctl, -- cgit v1.2.3 From 62daf3df8a6b1920f7613e478935443a8f449708 Mon Sep 17 00:00:00 2001 From: Simon Trimmer Date: Mon, 25 Mar 2024 11:31:25 +0000 Subject: ALSA: hda: hda_cs_dsp_ctl: Use cs_dsp_coeff_lock_and_[read|write]_ctrl() Using the cs_dsp_coeff_lock_and_[read|write]_ctrl() wrappers tidies the calling functions as it does not need to manage the DSP pwr_lock. Signed-off-by: Simon Trimmer Signed-off-by: Richard Fitzgerald Reviewed-by: Takashi Iwai Link: https://msgid.link/r/20240325113127.112783-4-rf@opensource.cirrus.com Signed-off-by: Mark Brown --- sound/pci/hda/hda_cs_dsp_ctl.c | 14 ++------------ 1 file changed, 2 insertions(+), 12 deletions(-) diff --git a/sound/pci/hda/hda_cs_dsp_ctl.c b/sound/pci/hda/hda_cs_dsp_ctl.c index 463ca06036bf..725544d81941 100644 --- a/sound/pci/hda/hda_cs_dsp_ctl.c +++ b/sound/pci/hda/hda_cs_dsp_ctl.c @@ -51,13 +51,8 @@ static int hda_cs_dsp_coeff_put(struct snd_kcontrol *kctl, struct snd_ctl_elem_v struct hda_cs_dsp_coeff_ctl *ctl = (struct hda_cs_dsp_coeff_ctl *)snd_kcontrol_chip(kctl); struct cs_dsp_coeff_ctl *cs_ctl = ctl->cs_ctl; char *p = ucontrol->value.bytes.data; - int ret = 0; - - mutex_lock(&cs_ctl->dsp->pwr_lock); - ret = cs_dsp_coeff_write_ctrl(cs_ctl, 0, p, cs_ctl->len); - mutex_unlock(&cs_ctl->dsp->pwr_lock); - return ret; + return cs_dsp_coeff_lock_and_write_ctrl(cs_ctl, 0, p, cs_ctl->len); } static int hda_cs_dsp_coeff_get(struct snd_kcontrol *kctl, struct snd_ctl_elem_value *ucontrol) @@ -65,13 +60,8 @@ static int hda_cs_dsp_coeff_get(struct snd_kcontrol *kctl, struct snd_ctl_elem_v struct hda_cs_dsp_coeff_ctl *ctl = (struct hda_cs_dsp_coeff_ctl *)snd_kcontrol_chip(kctl); struct cs_dsp_coeff_ctl *cs_ctl = ctl->cs_ctl; char *p = ucontrol->value.bytes.data; - int ret; - - mutex_lock(&cs_ctl->dsp->pwr_lock); - ret = cs_dsp_coeff_read_ctrl(cs_ctl, 0, p, cs_ctl->len); - mutex_unlock(&cs_ctl->dsp->pwr_lock); - return ret; + return cs_dsp_coeff_lock_and_read_ctrl(cs_ctl, 0, p, cs_ctl->len); } static unsigned int wmfw_convert_flags(unsigned int in) -- cgit v1.2.3 From e81f5c9f7d06a69dc505fa6ad351df6cc86a6c2d Mon Sep 17 00:00:00 2001 From: Simon Trimmer Date: Mon, 25 Mar 2024 11:31:26 +0000 Subject: ASoC: wm_adsp: Remove notification of driver write Any control that the driver is updating should be marked as SYSTEM and therefore will not have an ALSA control to notify. Signed-off-by: Simon Trimmer Signed-off-by: Richard Fitzgerald Reviewed-by: Takashi Iwai Link: https://msgid.link/r/20240325113127.112783-5-rf@opensource.cirrus.com Signed-off-by: Mark Brown --- sound/soc/codecs/wm_adsp.c | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/sound/soc/codecs/wm_adsp.c b/sound/soc/codecs/wm_adsp.c index f41d668e4c01..517f46fb9130 100644 --- a/sound/soc/codecs/wm_adsp.c +++ b/sound/soc/codecs/wm_adsp.c @@ -672,7 +672,6 @@ int wm_adsp_write_ctl(struct wm_adsp *dsp, const char *name, int type, unsigned int alg, void *buf, size_t len) { struct cs_dsp_coeff_ctl *cs_ctl; - struct wm_coeff_ctl *ctl; int ret; mutex_lock(&dsp->cs_dsp.pwr_lock); @@ -683,12 +682,7 @@ int wm_adsp_write_ctl(struct wm_adsp *dsp, const char *name, int type, if (ret < 0) return ret; - if (ret == 0 || (cs_ctl->flags & WMFW_CTL_FLAG_SYS)) - return 0; - - ctl = cs_ctl->priv; - - return snd_soc_component_notify_control(dsp->component, ctl->name); + return 0; } EXPORT_SYMBOL_GPL(wm_adsp_write_ctl); -- cgit v1.2.3 From d641def12ec929af6c4f9b1b28efcd3e5dff21b4 Mon Sep 17 00:00:00 2001 From: Simon Trimmer Date: Mon, 25 Mar 2024 11:31:27 +0000 Subject: ALSA: hda: hda_cs_dsp_ctl: Remove notification of driver write Any control that the driver is updating should be marked as SYSTEM and therefore will not have an ALSA control to notify. Signed-off-by: Simon Trimmer Signed-off-by: Richard Fitzgerald Reviewed-by: Takashi Iwai Link: https://msgid.link/r/20240325113127.112783-6-rf@opensource.cirrus.com Signed-off-by: Mark Brown --- sound/pci/hda/hda_cs_dsp_ctl.c | 8 -------- 1 file changed, 8 deletions(-) diff --git a/sound/pci/hda/hda_cs_dsp_ctl.c b/sound/pci/hda/hda_cs_dsp_ctl.c index 725544d81941..7f2d35cf245b 100644 --- a/sound/pci/hda/hda_cs_dsp_ctl.c +++ b/sound/pci/hda/hda_cs_dsp_ctl.c @@ -201,7 +201,6 @@ int hda_cs_dsp_write_ctl(struct cs_dsp *dsp, const char *name, int type, unsigned int alg, const void *buf, size_t len) { struct cs_dsp_coeff_ctl *cs_ctl; - struct hda_cs_dsp_coeff_ctl *ctl; int ret; mutex_lock(&dsp->pwr_lock); @@ -211,13 +210,6 @@ int hda_cs_dsp_write_ctl(struct cs_dsp *dsp, const char *name, int type, if (ret < 0) return ret; - if (ret == 0 || (cs_ctl->flags & WMFW_CTL_FLAG_SYS)) - return 0; - - ctl = cs_ctl->priv; - - snd_ctl_notify(ctl->card, SNDRV_CTL_EVENT_MASK_VALUE, &ctl->kctl->id); - return 0; } EXPORT_SYMBOL_NS_GPL(hda_cs_dsp_write_ctl, SND_HDA_CS_DSP_CONTROLS); -- cgit v1.2.3 From 21f28a7eb78dea6c59be6b0a5e0b47bf3d25fcbb Mon Sep 17 00:00:00 2001 From: Yaraslau Furman Date: Wed, 3 Apr 2024 19:54:24 +0300 Subject: HID: logitech-dj: allow mice to use all types of reports You can bind whatever action you want to the mouse's reprogrammable buttons using Windows application. Allow Linux to receive multimedia keycodes. Fixes: 3ed224e273ac ("HID: logitech-dj: Fix 064d:c52f receiver support") Signed-off-by: Yaraslau Furman Reviewed-by: Hans de Goede Signed-off-by: Jiri Kosina --- drivers/hid/hid-logitech-dj.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/hid/hid-logitech-dj.c b/drivers/hid/hid-logitech-dj.c index e6a8b6d8eab7..3c3c497b6b91 100644 --- a/drivers/hid/hid-logitech-dj.c +++ b/drivers/hid/hid-logitech-dj.c @@ -965,9 +965,7 @@ static void logi_hidpp_dev_conn_notif_equad(struct hid_device *hdev, } break; case REPORT_TYPE_MOUSE: - workitem->reports_supported |= STD_MOUSE | HIDPP; - if (djrcv_dev->type == recvr_type_mouse_only) - workitem->reports_supported |= MULTIMEDIA; + workitem->reports_supported |= STD_MOUSE | HIDPP | MULTIMEDIA; break; } } -- cgit v1.2.3 From f7c52345ccc96343c0a05bdea3121c8ac7b67d5f Mon Sep 17 00:00:00 2001 From: Kwangjin Ko Date: Tue, 2 Apr 2024 17:14:03 +0900 Subject: cxl/core: Fix initialization of mbox_cmd.size_out in get event Since mbox_cmd.size_out is overwritten with the actual output size in the function below, it needs to be initialized every time. cxl_internal_send_cmd -> __cxl_pci_mbox_send_cmd Problem scenario: 1) The size_out variable is initially set to the size of the mailbox. 2) Read an event. - size_out is set to 160 bytes(header 32B + one event 128B). - Two event are created while reading. 3) Read the new *two* events. - size_out is still set to 160 bytes. - Although the value of out_len is 288 bytes, only 160 bytes are copied from the mailbox register to the local variable. - record_count is set to 2. - Accessing records[1] will result in reading incorrect data. Fixes: 6ebe28f9ec72 ("cxl/mem: Read, trace, and clear events on driver load") Tested-by: Ira Weiny Reviewed-by: Ira Weiny Reviewed-by: Jonathan Cameron Signed-off-by: Kwangjin Ko Signed-off-by: Dave Jiang --- drivers/cxl/core/mbox.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/cxl/core/mbox.c b/drivers/cxl/core/mbox.c index 50146161887d..f0f54aeccc87 100644 --- a/drivers/cxl/core/mbox.c +++ b/drivers/cxl/core/mbox.c @@ -958,13 +958,14 @@ static void cxl_mem_get_records_log(struct cxl_memdev_state *mds, .payload_in = &log_type, .size_in = sizeof(log_type), .payload_out = payload, - .size_out = mds->payload_size, .min_out = struct_size(payload, records, 0), }; do { int rc, i; + mbox_cmd.size_out = mds->payload_size; + rc = cxl_internal_send_cmd(mds, &mbox_cmd); if (rc) { dev_err_ratelimited(dev, -- cgit v1.2.3 From e7d24c0aa8e678f41457d1304e2091cac6fd1a2e Mon Sep 17 00:00:00 2001 From: Ard Biesheuvel Date: Thu, 28 Mar 2024 07:42:57 +0100 Subject: gcc-plugins/stackleak: Avoid .head.text section The .head.text section carries the startup code that runs with the MMU off or with a translation of memory that deviates from the ordinary one. So avoid instrumentation with the stackleak plugin, which already avoids .init.text and .noinstr.text entirely. Fixes: 48204aba801f1b51 ("x86/sme: Move early SME kernel encryption handling into .head.text") Reported-by: kernel test robot Closes: https://lore.kernel.org/oe-lkp/202403221630.2692c998-oliver.sang@intel.com Signed-off-by: Ard Biesheuvel Link: https://lore.kernel.org/r/20240328064256.2358634-2-ardb+git@google.com Signed-off-by: Kees Cook --- scripts/gcc-plugins/stackleak_plugin.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/scripts/gcc-plugins/stackleak_plugin.c b/scripts/gcc-plugins/stackleak_plugin.c index c5c2ce113c92..d20c47d21ad8 100644 --- a/scripts/gcc-plugins/stackleak_plugin.c +++ b/scripts/gcc-plugins/stackleak_plugin.c @@ -467,6 +467,8 @@ static bool stackleak_gate(void) return false; if (STRING_EQUAL(section, ".entry.text")) return false; + if (STRING_EQUAL(section, ".head.text")) + return false; } return track_frame_size >= 0; -- cgit v1.2.3 From bbda3ba626b9f57ff6063058877eca856f5b734d Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Wed, 3 Apr 2024 10:06:20 +0200 Subject: ubsan: fix unused variable warning in test module This is one of the drivers with an unused variable that is marked 'const'. Adding a __used annotation here avoids the warning and lets us enable the option by default: lib/test_ubsan.c:137:28: error: unused variable 'skip_ubsan_array' [-Werror,-Wunused-const-variable] Fixes: 4a26f49b7b3d ("ubsan: expand tests and reporting") Signed-off-by: Arnd Bergmann Link: https://lore.kernel.org/r/20240403080702.3509288-3-arnd@kernel.org Signed-off-by: Kees Cook --- lib/test_ubsan.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/test_ubsan.c b/lib/test_ubsan.c index 276c12140ee2..c288df9372ed 100644 --- a/lib/test_ubsan.c +++ b/lib/test_ubsan.c @@ -134,7 +134,7 @@ static const test_ubsan_fp test_ubsan_array[] = { }; /* Excluded because they Oops the module. */ -static const test_ubsan_fp skip_ubsan_array[] = { +static __used const test_ubsan_fp skip_ubsan_array[] = { test_ubsan_divrem_overflow, }; -- cgit v1.2.3 From 9c573cd313433f6c1f7236fe64b9b743500c1628 Mon Sep 17 00:00:00 2001 From: Kees Cook Date: Sat, 9 Mar 2024 12:24:48 -0800 Subject: randomize_kstack: Improve entropy diffusion The kstack_offset variable was really only ever using the low bits for kernel stack offset entropy. Add a ror32() to increase bit diffusion. Suggested-by: Arnd Bergmann Fixes: 39218ff4c625 ("stack: Optionally randomize kernel stack offset each syscall") Link: https://lore.kernel.org/r/20240309202445.work.165-kees@kernel.org Signed-off-by: Kees Cook --- include/linux/randomize_kstack.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/linux/randomize_kstack.h b/include/linux/randomize_kstack.h index 5d868505a94e..6d92b68efbf6 100644 --- a/include/linux/randomize_kstack.h +++ b/include/linux/randomize_kstack.h @@ -80,7 +80,7 @@ DECLARE_PER_CPU(u32, kstack_offset); if (static_branch_maybe(CONFIG_RANDOMIZE_KSTACK_OFFSET_DEFAULT, \ &randomize_kstack_offset)) { \ u32 offset = raw_cpu_read(kstack_offset); \ - offset ^= (rand); \ + offset = ror32(offset, 5) ^ (rand); \ raw_cpu_write(kstack_offset, offset); \ } \ } while (0) -- cgit v1.2.3 From e60aa472400b1ff8d0e6c563a2eb05916927f10a Mon Sep 17 00:00:00 2001 From: Thomas Bertschinger Date: Thu, 14 Mar 2024 10:02:18 -0600 Subject: bcachefs: create debugfs dir for each btree MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This creates a subdirectory for each individual btree under the btrees/ debugfs directory. Directory structure, before: /sys/kernel/debug/bcachefs/$FS_ID/btrees/ ├── alloc ├── alloc-bfloat-failed ├── alloc-formats ├── backpointers ├── backpointers-bfloat-failed ├── backpointers-formats ... Directory structure, after: /sys/kernel/debug/bcachefs/$FS_ID/btrees/ ├── alloc │   ├── bfloat-failed │   ├── formats │   └── keys ├── backpointers │   ├── bfloat-failed │   ├── formats │   └── keys ... Signed-off-by: Thomas Bertschinger Signed-off-by: Kent Overstreet --- fs/bcachefs/debug.c | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/fs/bcachefs/debug.c b/fs/bcachefs/debug.c index 208ce6f0fc43..7b681ae91510 100644 --- a/fs/bcachefs/debug.c +++ b/fs/bcachefs/debug.c @@ -866,6 +866,20 @@ void bch2_fs_debug_exit(struct bch_fs *c) debugfs_remove_recursive(c->fs_debug_dir); } +static void bch2_fs_debug_btree_init(struct bch_fs *c, struct btree_debug *bd) +{ + struct dentry *d; + + d = debugfs_create_dir(bch2_btree_id_str(bd->id), c->btree_debug_dir); + + debugfs_create_file("keys", 0400, d, bd, &btree_debug_ops); + + debugfs_create_file("formats", 0400, d, bd, &btree_format_debug_ops); + + debugfs_create_file("bfloat-failed", 0400, d, bd, + &bfloat_failed_debug_ops); +} + void bch2_fs_debug_init(struct bch_fs *c) { struct btree_debug *bd; @@ -902,21 +916,7 @@ void bch2_fs_debug_init(struct bch_fs *c) bd < c->btree_debug + ARRAY_SIZE(c->btree_debug); bd++) { bd->id = bd - c->btree_debug; - debugfs_create_file(bch2_btree_id_str(bd->id), - 0400, c->btree_debug_dir, bd, - &btree_debug_ops); - - snprintf(name, sizeof(name), "%s-formats", - bch2_btree_id_str(bd->id)); - - debugfs_create_file(name, 0400, c->btree_debug_dir, bd, - &btree_format_debug_ops); - - snprintf(name, sizeof(name), "%s-bfloat-failed", - bch2_btree_id_str(bd->id)); - - debugfs_create_file(name, 0400, c->btree_debug_dir, bd, - &bfloat_failed_debug_ops); + bch2_fs_debug_btree_init(c, bd); } } -- cgit v1.2.3 From 7d8ed162e6a92268d4b2b84d364a931216102c8e Mon Sep 17 00:00:00 2001 From: Wei Yang Date: Tue, 2 Apr 2024 13:26:59 +0000 Subject: memblock tests: fix undefined reference to `early_pfn_to_nid' commit 6a9531c3a880 ("memblock: fix crash when reserved memory is not added to memory") introduce the usage of early_pfn_to_nid, which is not defined in memblock tests. The original definition of early_pfn_to_nid is defined in mm.h, so let add this in the corresponding mm.h. Signed-off-by: Wei Yang CC: Yajun Deng CC: Mike Rapoport Link: https://lore.kernel.org/r/20240402132701.29744-2-richard.weiyang@gmail.com Signed-off-by: Mike Rapoport (IBM) --- tools/include/linux/mm.h | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/tools/include/linux/mm.h b/tools/include/linux/mm.h index f3c82ab5b14c..7d73da098047 100644 --- a/tools/include/linux/mm.h +++ b/tools/include/linux/mm.h @@ -37,4 +37,9 @@ static inline void totalram_pages_add(long count) { } +static inline int early_pfn_to_nid(unsigned long pfn) +{ + return 0; +} + #endif -- cgit v1.2.3 From e0f5a8e74be88f2476e58b25d3b49a9521bdc4ec Mon Sep 17 00:00:00 2001 From: Wei Yang Date: Tue, 2 Apr 2024 13:27:00 +0000 Subject: memblock tests: fix undefined reference to `panic' commit e96c6b8f212a ("memblock: report failures when memblock_can_resize is not set") introduced the usage of panic, which is not defined in memblock test. Let's define it directly in panic.h to fix it. Signed-off-by: Wei Yang CC: Song Shuai CC: Mike Rapoport Link: https://lore.kernel.org/r/20240402132701.29744-3-richard.weiyang@gmail.com Signed-off-by: Mike Rapoport (IBM) --- tools/include/linux/kernel.h | 1 + tools/include/linux/panic.h | 19 +++++++++++++++++++ 2 files changed, 20 insertions(+) create mode 100644 tools/include/linux/panic.h diff --git a/tools/include/linux/kernel.h b/tools/include/linux/kernel.h index 4b0673bf52c2..07cfad817d53 100644 --- a/tools/include/linux/kernel.h +++ b/tools/include/linux/kernel.h @@ -8,6 +8,7 @@ #include #include #include +#include #include #include diff --git a/tools/include/linux/panic.h b/tools/include/linux/panic.h new file mode 100644 index 000000000000..9c8f17a41ce8 --- /dev/null +++ b/tools/include/linux/panic.h @@ -0,0 +1,19 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#ifndef _TOOLS_LINUX_PANIC_H +#define _TOOLS_LINUX_PANIC_H + +#include +#include +#include + +static inline void panic(const char *fmt, ...) +{ + va_list argp; + + va_start(argp, fmt); + vfprintf(stderr, fmt, argp); + va_end(argp); + exit(-1); +} + +#endif -- cgit v1.2.3 From 592447f6cb3c20d606d6c5d8e6af68e99707b786 Mon Sep 17 00:00:00 2001 From: Wei Yang Date: Tue, 2 Apr 2024 13:27:01 +0000 Subject: memblock tests: fix undefined reference to `BIT' commit 772dd0342727 ("mm: enumerate all gfp flags") define gfp flags with the help of BIT, while gfp_types.h doesn't include header file for the definition. This through an error on building memblock tests. Let's include linux/bits.h to fix it. Signed-off-by: Wei Yang CC: Suren Baghdasaryan CC: Michal Hocko Link: https://lore.kernel.org/r/20240402132701.29744-4-richard.weiyang@gmail.com Signed-off-by: Mike Rapoport (IBM) --- include/linux/gfp_types.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/include/linux/gfp_types.h b/include/linux/gfp_types.h index 868c8fb1bbc1..13becafe41df 100644 --- a/include/linux/gfp_types.h +++ b/include/linux/gfp_types.h @@ -2,6 +2,8 @@ #ifndef __LINUX_GFP_TYPES_H #define __LINUX_GFP_TYPES_H +#include + /* The typedef is in types.h but we want the documentation here */ #if 0 /** -- cgit v1.2.3 From 2ba2d17170f9e415fc31d7978214f0f26e8afc64 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Thu, 4 Apr 2024 11:57:34 +0200 Subject: ASoC: codecs: rk3308: fix building without CONFIG_OF The newly added codec has an extraneous of_match_ptr() annotation for the ID table: sound/soc/codecs/rk3308_codec.c:956:34: error: 'rk3308_codec_of_match' defined but not used [-Werror=unused-const-variable=] 956 | static const struct of_device_id rk3308_codec_of_match[] = { Remove it to avoid introducing a warning when -Wunused-const-variable gets enabled by default: Fixes: 4ed0915f5bc4 ("ASoC: codecs: Add RK3308 internal audio codec driver") Signed-off-by: Arnd Bergmann Link: https://msgid.link/r/20240404095755.650364-1-arnd@kernel.org Signed-off-by: Mark Brown --- sound/soc/codecs/rk3308_codec.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/codecs/rk3308_codec.c b/sound/soc/codecs/rk3308_codec.c index 74c3836995b1..8b51e87a1711 100644 --- a/sound/soc/codecs/rk3308_codec.c +++ b/sound/soc/codecs/rk3308_codec.c @@ -962,7 +962,7 @@ MODULE_DEVICE_TABLE(of, rk3308_codec_of_match); static struct platform_driver rk3308_codec_driver = { .driver = { .name = "rk3308-acodec", - .of_match_table = of_match_ptr(rk3308_codec_of_match), + .of_match_table = rk3308_codec_of_match, }, .probe = rk3308_codec_platform_probe, }; -- cgit v1.2.3 From 9f1aeef4cbcb0e8c616e29cdce3232f9f102c2c1 Mon Sep 17 00:00:00 2001 From: Francesco Dolcini Date: Thu, 4 Apr 2024 13:19:53 +0200 Subject: ASoC: nau8822: Remove unused member from struct Remove unused mclk_idx struct member. Signed-off-by: Francesco Dolcini Link: https://msgid.link/r/20240404111953.99287-1-francesco@dolcini.it Signed-off-by: Mark Brown --- sound/soc/codecs/nau8822.h | 1 - 1 file changed, 1 deletion(-) diff --git a/sound/soc/codecs/nau8822.h b/sound/soc/codecs/nau8822.h index 646f6bb64bc5..6ecd46e45923 100644 --- a/sound/soc/codecs/nau8822.h +++ b/sound/soc/codecs/nau8822.h @@ -215,7 +215,6 @@ struct nau8822_pll { struct nau8822 { struct device *dev; struct regmap *regmap; - int mclk_idx; struct nau8822_pll pll; int sysclk; int div_id; -- cgit v1.2.3 From 5bfc311dd6c376d350b39028b9000ad766ddc934 Mon Sep 17 00:00:00 2001 From: Oliver Neukum Date: Thu, 4 Apr 2024 15:11:05 +0300 Subject: usb: xhci: correct return value in case of STS_HCE If we get STS_HCE we give up on the interrupt, but for the purpose of IRQ handling that still counts as ours. We may return IRQ_NONE only if we are positive that it wasn't ours. Hence correct the default. Fixes: 2a25e66d676d ("xhci: print warning when HCE was set") Cc: stable@vger.kernel.org # v6.2+ Signed-off-by: Oliver Neukum Signed-off-by: Mathias Nyman Link: https://lore.kernel.org/r/20240404121106.2842417-2-mathias.nyman@linux.intel.com Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/xhci-ring.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c index 52278afea94b..575f0fd9c9f1 100644 --- a/drivers/usb/host/xhci-ring.c +++ b/drivers/usb/host/xhci-ring.c @@ -3133,7 +3133,7 @@ static int xhci_handle_events(struct xhci_hcd *xhci, struct xhci_interrupter *ir irqreturn_t xhci_irq(struct usb_hcd *hcd) { struct xhci_hcd *xhci = hcd_to_xhci(hcd); - irqreturn_t ret = IRQ_NONE; + irqreturn_t ret = IRQ_HANDLED; u32 status; spin_lock(&xhci->lock); @@ -3141,12 +3141,13 @@ irqreturn_t xhci_irq(struct usb_hcd *hcd) status = readl(&xhci->op_regs->status); if (status == ~(u32)0) { xhci_hc_died(xhci); - ret = IRQ_HANDLED; goto out; } - if (!(status & STS_EINT)) + if (!(status & STS_EINT)) { + ret = IRQ_NONE; goto out; + } if (status & STS_HCE) { xhci_warn(xhci, "WARNING: Host Controller Error\n"); @@ -3156,7 +3157,6 @@ irqreturn_t xhci_irq(struct usb_hcd *hcd) if (status & STS_FATAL) { xhci_warn(xhci, "WARNING: Host System Error\n"); xhci_halt(xhci); - ret = IRQ_HANDLED; goto out; } @@ -3167,7 +3167,6 @@ irqreturn_t xhci_irq(struct usb_hcd *hcd) */ status |= STS_EINT; writel(status, &xhci->op_regs->status); - ret = IRQ_HANDLED; /* This is the handler of the primary interrupter */ xhci_handle_events(xhci, xhci->interrupters[0]); -- cgit v1.2.3 From dda7e89e53d6ebf27c49df7d87a54e3e1614d332 Mon Sep 17 00:00:00 2001 From: Mathias Nyman Date: Thu, 4 Apr 2024 15:11:06 +0300 Subject: xhci: Fix root hub port null pointer dereference in xhci tracepoints The pointer from a xhci usb virt device to its root hub port (vdev->rhub_port) is set later when device is addressed, not while vdev is allocated. Tracepoints dereferenced this rhub_port pointer when freeing the virt device, which causes null pointer dereference if tracing is enabled and device is freed before addressed. This can happen if tracing is enabled and xhci driver is unloaded before a device is fully enumerated, or initial enumeration fails and device is reset and freed before retry. Don't dereference the rhub_port or show port numbers when tracing xhci_free_virt_device(). This info is not very useful anyway. Print the more useful slot id instead Fixes: 06790c19086f ("xhci: replace real & fake port with pointer to root hub port") Reported-by: Thinh Nguyen Closes: https://lore.kernel.org/linux-usb/20240402005007.klv2ij727fkz7rpd@synopsys.com/ Signed-off-by: Mathias Nyman Link: https://lore.kernel.org/r/20240404121106.2842417-3-mathias.nyman@linux.intel.com Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/xhci-trace.h | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/drivers/usb/host/xhci-trace.h b/drivers/usb/host/xhci-trace.h index 1740000d54c2..5762564b9d73 100644 --- a/drivers/usb/host/xhci-trace.h +++ b/drivers/usb/host/xhci-trace.h @@ -172,8 +172,7 @@ DECLARE_EVENT_CLASS(xhci_log_free_virt_dev, __field(void *, vdev) __field(unsigned long long, out_ctx) __field(unsigned long long, in_ctx) - __field(int, hcd_portnum) - __field(int, hw_portnum) + __field(int, slot_id) __field(u16, current_mel) ), @@ -181,13 +180,12 @@ DECLARE_EVENT_CLASS(xhci_log_free_virt_dev, __entry->vdev = vdev; __entry->in_ctx = (unsigned long long) vdev->in_ctx->dma; __entry->out_ctx = (unsigned long long) vdev->out_ctx->dma; - __entry->hcd_portnum = (int) vdev->rhub_port->hcd_portnum; - __entry->hw_portnum = (int) vdev->rhub_port->hw_portnum; + __entry->slot_id = (int) vdev->slot_id; __entry->current_mel = (u16) vdev->current_mel; ), - TP_printk("vdev %p ctx %llx | %llx hcd_portnum %d hw_portnum %d current_mel %d", - __entry->vdev, __entry->in_ctx, __entry->out_ctx, - __entry->hcd_portnum, __entry->hw_portnum, __entry->current_mel + TP_printk("vdev %p slot %d ctx %llx | %llx current_mel %d", + __entry->vdev, __entry->slot_id, __entry->in_ctx, + __entry->out_ctx, __entry->current_mel ) ); -- cgit v1.2.3 From 69630926011c1f7170a465b7b5c228deb66e9372 Mon Sep 17 00:00:00 2001 From: Michael Ellerman Date: Fri, 29 Mar 2024 00:02:00 +1100 Subject: powerpc/crypto/chacha-p10: Fix failure on non Power10 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The chacha-p10-crypto module provides optimised chacha routines for Power10. It also selects CRYPTO_ARCH_HAVE_LIB_CHACHA which says it provides chacha_crypt_arch() to generic code. Notably the module needs to provide chacha_crypt_arch() regardless of whether it is loaded on Power10 or an older CPU. The implementation of chacha_crypt_arch() already has a fallback to chacha_crypt_generic(), however the module as a whole fails to load on pre-Power10, because of the use of module_cpu_feature_match(). This breaks for example loading wireguard: jostaberry-1:~ # modprobe -v wireguard insmod /lib/modules/6.8.0-lp155.8.g7e0e887-default/kernel/arch/powerpc/crypto/chacha-p10-crypto.ko.zst modprobe: ERROR: could not insert 'wireguard': No such device Fix it by removing module_cpu_feature_match(), and instead check the CPU feature manually. If the CPU feature is not found, the module still loads successfully, but doesn't register the Power10 specific algorithms. That allows chacha_crypt_generic() to remain available for use, fixing the problem. [root@fedora ~]# modprobe -v wireguard insmod /lib/modules/6.8.0-00001-g786a790c4d79/kernel/net/ipv4/udp_tunnel.ko insmod /lib/modules/6.8.0-00001-g786a790c4d79/kernel/net/ipv6/ip6_udp_tunnel.ko insmod /lib/modules/6.8.0-00001-g786a790c4d79/kernel/lib/crypto/libchacha.ko insmod /lib/modules/6.8.0-00001-g786a790c4d79/kernel/arch/powerpc/crypto/chacha-p10-crypto.ko insmod /lib/modules/6.8.0-00001-g786a790c4d79/kernel/lib/crypto/libchacha20poly1305.ko insmod /lib/modules/6.8.0-00001-g786a790c4d79/kernel/drivers/net/wireguard/wireguard.ko [ 18.910452][ T721] wireguard: allowedips self-tests: pass [ 18.914999][ T721] wireguard: nonce counter self-tests: pass [ 19.029066][ T721] wireguard: ratelimiter self-tests: pass [ 19.029257][ T721] wireguard: WireGuard 1.0.0 loaded. See www.wireguard.com for information. [ 19.029361][ T721] wireguard: Copyright (C) 2015-2019 Jason A. Donenfeld . All Rights Reserved. Reported-by: Michal Suchánek Closes: https://lore.kernel.org/all/20240315122005.GG20665@kitsune.suse.cz/ Acked-by: Herbert Xu Signed-off-by: Michael Ellerman Link: https://msgid.link/20240328130200.3041687-1-mpe@ellerman.id.au --- arch/powerpc/crypto/chacha-p10-glue.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/arch/powerpc/crypto/chacha-p10-glue.c b/arch/powerpc/crypto/chacha-p10-glue.c index 74fb86b0d209..7c728755852e 100644 --- a/arch/powerpc/crypto/chacha-p10-glue.c +++ b/arch/powerpc/crypto/chacha-p10-glue.c @@ -197,6 +197,9 @@ static struct skcipher_alg algs[] = { static int __init chacha_p10_init(void) { + if (!cpu_has_feature(CPU_FTR_ARCH_31)) + return 0; + static_branch_enable(&have_p10); return crypto_register_skciphers(algs, ARRAY_SIZE(algs)); @@ -204,10 +207,13 @@ static int __init chacha_p10_init(void) static void __exit chacha_p10_exit(void) { + if (!static_branch_likely(&have_p10)) + return; + crypto_unregister_skciphers(algs, ARRAY_SIZE(algs)); } -module_cpu_feature_match(PPC_MODULE_FEATURE_P10, chacha_p10_init); +module_init(chacha_p10_init); module_exit(chacha_p10_exit); MODULE_DESCRIPTION("ChaCha and XChaCha stream ciphers (P10 accelerated)"); -- cgit v1.2.3 From 3f03e7717c2999473a3ed38475ed0a962ba9f393 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Wed, 27 Mar 2024 18:53:08 +0100 Subject: usb: phy: MAINTAINERS: mark Freescale USB PHY as orphaned Emails to the only maintainer bounce: : host nxp-com.mail.protection.outlook.com[52.101.68.39] said: 550 5.4.1 Recipient address rejected: Access denied. Signed-off-by: Krzysztof Kozlowski Link: https://lore.kernel.org/r/20240327175308.520317-1-krzysztof.kozlowski@linaro.org Signed-off-by: Greg Kroah-Hartman --- MAINTAINERS | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/MAINTAINERS b/MAINTAINERS index 7c121493f43d..3c78979fb819 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -8752,10 +8752,9 @@ S: Maintained F: drivers/usb/gadget/udc/fsl* FREESCALE USB PHY DRIVER -M: Ran Wang L: linux-usb@vger.kernel.org L: linuxppc-dev@lists.ozlabs.org -S: Maintained +S: Orphan F: drivers/usb/phy/phy-fsl-usb* FREEVXFS FILESYSTEM -- cgit v1.2.3 From ce4c8d21054ae9396cd759fe6e8157b525616dc4 Mon Sep 17 00:00:00 2001 From: "Christian A. Ehrhardt" Date: Mon, 1 Apr 2024 23:05:15 +0200 Subject: usb: typec: ucsi: Fix connector check on init Fix issues when initially checking for a connector change: - Use the correct connector number not the entire CCI. - Call ->read under the PPM lock. - Remove a bogus READ_ONCE. Fixes: 808a8b9e0b87 ("usb: typec: ucsi: Check for notifications after init") Cc: stable@kernel.org Signed-off-by: Christian A. Ehrhardt Reviewed-by: Heikki Krogerus Link: https://lore.kernel.org/r/20240401210515.1902048-1-lk@c--e.de Signed-off-by: Greg Kroah-Hartman --- drivers/usb/typec/ucsi/ucsi.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/usb/typec/ucsi/ucsi.c b/drivers/usb/typec/ucsi/ucsi.c index 31d8a46ae5e7..bd6ae92aa39e 100644 --- a/drivers/usb/typec/ucsi/ucsi.c +++ b/drivers/usb/typec/ucsi/ucsi.c @@ -1736,11 +1736,13 @@ static int ucsi_init(struct ucsi *ucsi) ucsi->connector = connector; ucsi->ntfy = ntfy; + mutex_lock(&ucsi->ppm_lock); ret = ucsi->ops->read(ucsi, UCSI_CCI, &cci, sizeof(cci)); + mutex_unlock(&ucsi->ppm_lock); if (ret) return ret; - if (UCSI_CCI_CONNECTOR(READ_ONCE(cci))) - ucsi_connector_change(ucsi, cci); + if (UCSI_CCI_CONNECTOR(cci)) + ucsi_connector_change(ucsi, UCSI_CCI_CONNECTOR(cci)); return 0; -- cgit v1.2.3 From 1500a7b2794d46beadd408132ddb5ef669c5c057 Mon Sep 17 00:00:00 2001 From: Paul Cercueil Date: Tue, 2 Apr 2024 13:09:50 +0200 Subject: usb: gadget: functionfs: Fix inverted DMA fence direction A "read" fence was installed when the DMABUF was to be written to, and a "write" fence was installed when the DMABUF was to be read from. Besides, dma_resv_usage_rw() should only be used when waiting for fences. Fixes: 7b07a2a7ca02 ("usb: gadget: functionfs: Add DMABUF import interface") Signed-off-by: Paul Cercueil Link: https://lore.kernel.org/r/20240402110951.16376-2-paul@crapouillou.net Signed-off-by: Greg Kroah-Hartman --- drivers/usb/gadget/function/f_fs.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/usb/gadget/function/f_fs.c b/drivers/usb/gadget/function/f_fs.c index bffbc1dc651f..70e8532127ad 100644 --- a/drivers/usb/gadget/function/f_fs.c +++ b/drivers/usb/gadget/function/f_fs.c @@ -1578,6 +1578,7 @@ static int ffs_dmabuf_transfer(struct file *file, struct ffs_dmabuf_priv *priv; struct ffs_dma_fence *fence; struct usb_request *usb_req; + enum dma_resv_usage resv_dir; struct dma_buf *dmabuf; struct ffs_ep *ep; bool cookie; @@ -1665,8 +1666,9 @@ static int ffs_dmabuf_transfer(struct file *file, dma_fence_init(&fence->base, &ffs_dmabuf_fence_ops, &priv->lock, priv->context, seqno); - dma_resv_add_fence(dmabuf->resv, &fence->base, - dma_resv_usage_rw(epfile->in)); + resv_dir = epfile->in ? DMA_RESV_USAGE_WRITE : DMA_RESV_USAGE_READ; + + dma_resv_add_fence(dmabuf->resv, &fence->base, resv_dir); dma_resv_unlock(dmabuf->resv); /* Now that the dma_fence is in place, queue the transfer. */ -- cgit v1.2.3 From 862b416560c348f66d2091c56e71fd5462510cab Mon Sep 17 00:00:00 2001 From: Paul Cercueil Date: Tue, 2 Apr 2024 13:09:51 +0200 Subject: usb: gadget: functionfs: Wait for fences before enqueueing DMABUF Instead of bailing when fences have already been installed on the DMABUF, wait for them (with a timeout) when doing a blocking operation. This fixes the issue where userspace would submit a DMABUF with fences already installed, with the (correct) expectation that it would just work. Fixes: 7b07a2a7ca02 ("usb: gadget: functionfs: Add DMABUF import interface") Signed-off-by: Paul Cercueil Link: https://lore.kernel.org/r/20240402110951.16376-3-paul@crapouillou.net Signed-off-by: Greg Kroah-Hartman --- drivers/usb/gadget/function/f_fs.c | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/drivers/usb/gadget/function/f_fs.c b/drivers/usb/gadget/function/f_fs.c index 70e8532127ad..f855f1fc8e5e 100644 --- a/drivers/usb/gadget/function/f_fs.c +++ b/drivers/usb/gadget/function/f_fs.c @@ -46,6 +46,8 @@ #define FUNCTIONFS_MAGIC 0xa647361 /* Chosen by a honest dice roll ;) */ +#define DMABUF_ENQUEUE_TIMEOUT_MS 5000 + MODULE_IMPORT_NS(DMA_BUF); /* Reference counter handling */ @@ -1580,9 +1582,11 @@ static int ffs_dmabuf_transfer(struct file *file, struct usb_request *usb_req; enum dma_resv_usage resv_dir; struct dma_buf *dmabuf; + unsigned long timeout; struct ffs_ep *ep; bool cookie; u32 seqno; + long retl; int ret; if (req->flags & ~USB_FFS_DMABUF_TRANSFER_MASK) @@ -1616,17 +1620,14 @@ static int ffs_dmabuf_transfer(struct file *file, goto err_attachment_put; /* Make sure we don't have writers */ - if (!dma_resv_test_signaled(dmabuf->resv, DMA_RESV_USAGE_WRITE)) { - pr_vdebug("FFS WRITE fence is not signaled\n"); - ret = -EBUSY; - goto err_resv_unlock; - } - - /* If we're writing to the DMABUF, make sure we don't have readers */ - if (epfile->in && - !dma_resv_test_signaled(dmabuf->resv, DMA_RESV_USAGE_READ)) { - pr_vdebug("FFS READ fence is not signaled\n"); - ret = -EBUSY; + timeout = nonblock ? 0 : msecs_to_jiffies(DMABUF_ENQUEUE_TIMEOUT_MS); + retl = dma_resv_wait_timeout(dmabuf->resv, + dma_resv_usage_rw(epfile->in), + true, timeout); + if (retl == 0) + retl = -EBUSY; + if (retl < 0) { + ret = (int)retl; goto err_resv_unlock; } -- cgit v1.2.3 From c4128304c2169b4664ed6fb6200f228cead2ab70 Mon Sep 17 00:00:00 2001 From: Kyle Tso Date: Thu, 4 Apr 2024 21:35:17 +0800 Subject: usb: typec: tcpm: Correct the PDO counting in pd_set Off-by-one errors happen because nr_snk_pdo and nr_src_pdo are incorrectly added one. The index of the loop is equal to the number of PDOs to be updated when leaving the loop and it doesn't need to be added one. When doing the power negotiation, TCPM relies on the "nr_snk_pdo" as the size of the local sink PDO array to match the Source capabilities of the partner port. If the off-by-one overflow occurs, a wrong RDO might be sent and unexpected power transfer might happen such as over voltage or over current (than expected). "nr_src_pdo" is used to set the Rp level when the port is in Source role. It is also the array size of the local Source capabilities when filling up the buffer which will be sent as the Source PDOs (such as in Power Negotiation). If the off-by-one overflow occurs, a wrong Rp level might be set and wrong Source PDOs will be sent to the partner port. This could potentially cause over current or port resets. Fixes: cd099cde4ed2 ("usb: typec: tcpm: Support multiple capabilities") Cc: stable@vger.kernel.org Signed-off-by: Kyle Tso Reviewed-by: Heikki Krogerus Link: https://lore.kernel.org/r/20240404133517.2707955-1-kyletso@google.com Signed-off-by: Greg Kroah-Hartman --- drivers/usb/typec/tcpm/tcpm.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/usb/typec/tcpm/tcpm.c b/drivers/usb/typec/tcpm/tcpm.c index c26fb70c3ec6..ab6ed6111ed0 100644 --- a/drivers/usb/typec/tcpm/tcpm.c +++ b/drivers/usb/typec/tcpm/tcpm.c @@ -6855,14 +6855,14 @@ static int tcpm_pd_set(struct typec_port *p, struct usb_power_delivery *pd) if (data->sink_desc.pdo[0]) { for (i = 0; i < PDO_MAX_OBJECTS && data->sink_desc.pdo[i]; i++) port->snk_pdo[i] = data->sink_desc.pdo[i]; - port->nr_snk_pdo = i + 1; + port->nr_snk_pdo = i; port->operating_snk_mw = data->operating_snk_mw; } if (data->source_desc.pdo[0]) { for (i = 0; i < PDO_MAX_OBJECTS && data->source_desc.pdo[i]; i++) port->src_pdo[i] = data->source_desc.pdo[i]; - port->nr_src_pdo = i + 1; + port->nr_src_pdo = i; } switch (port->state) { -- cgit v1.2.3 From 251ea652050e715886b272f831cf5016150a60c8 Mon Sep 17 00:00:00 2001 From: Cezary Rojewski Date: Wed, 3 Apr 2024 11:16:26 +0200 Subject: ASoC: Intel: Skylake: Remove soc-topology ABI v4 support MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The only known users are Chromebook configurations. Starting from kernel v5.4, all of them are making use of soc-topology ABI v5. Cc: Curtis Malainey Cc: Łukasz Majczak Signed-off-by: Cezary Rojewski Link: https://msgid.link/r/20240403091629.647267-2-cezary.rojewski@intel.com Signed-off-by: Mark Brown --- include/uapi/sound/skl-tplg-interface.h | 74 -------------- sound/soc/intel/skylake/skl-topology.c | 169 -------------------------------- 2 files changed, 243 deletions(-) diff --git a/include/uapi/sound/skl-tplg-interface.h b/include/uapi/sound/skl-tplg-interface.h index 4bf9c4f9add8..940c4269322b 100644 --- a/include/uapi/sound/skl-tplg-interface.h +++ b/include/uapi/sound/skl-tplg-interface.h @@ -165,78 +165,4 @@ enum skl_tuple_type { SKL_TYPE_DATA }; -/* v4 configuration data */ - -struct skl_dfw_v4_module_pin { - __u16 module_id; - __u16 instance_id; -} __packed; - -struct skl_dfw_v4_module_fmt { - __u32 channels; - __u32 freq; - __u32 bit_depth; - __u32 valid_bit_depth; - __u32 ch_cfg; - __u32 interleaving_style; - __u32 sample_type; - __u32 ch_map; -} __packed; - -struct skl_dfw_v4_module_caps { - __u32 set_params:2; - __u32 rsvd:30; - __u32 param_id; - __u32 caps_size; - __u32 caps[HDA_SST_CFG_MAX]; -} __packed; - -struct skl_dfw_v4_pipe { - __u8 pipe_id; - __u8 pipe_priority; - __u16 conn_type:4; - __u16 rsvd:4; - __u16 memory_pages:8; -} __packed; - -struct skl_dfw_v4_module { - char uuid[SKL_UUID_STR_SZ]; - - __u16 module_id; - __u16 instance_id; - __u32 max_mcps; - __u32 mem_pages; - __u32 obs; - __u32 ibs; - __u32 vbus_id; - - __u32 max_in_queue:8; - __u32 max_out_queue:8; - __u32 time_slot:8; - __u32 core_id:4; - __u32 rsvd1:4; - - __u32 module_type:8; - __u32 conn_type:4; - __u32 dev_type:4; - __u32 hw_conn_type:4; - __u32 rsvd2:12; - - __u32 params_fixup:8; - __u32 converter:8; - __u32 input_pin_type:1; - __u32 output_pin_type:1; - __u32 is_dynamic_in_pin:1; - __u32 is_dynamic_out_pin:1; - __u32 is_loadable:1; - __u32 rsvd3:11; - - struct skl_dfw_v4_pipe pipe; - struct skl_dfw_v4_module_fmt in_fmt[MAX_IN_QUEUE]; - struct skl_dfw_v4_module_fmt out_fmt[MAX_OUT_QUEUE]; - struct skl_dfw_v4_module_pin in_pin[MAX_IN_QUEUE]; - struct skl_dfw_v4_module_pin out_pin[MAX_OUT_QUEUE]; - struct skl_dfw_v4_module_caps caps; -} __packed; - #endif diff --git a/sound/soc/intel/skylake/skl-topology.c b/sound/soc/intel/skylake/skl-topology.c index 96cfebded072..e27f0fc3d897 100644 --- a/sound/soc/intel/skylake/skl-topology.c +++ b/sound/soc/intel/skylake/skl-topology.c @@ -2682,168 +2682,6 @@ static int skl_tplg_get_desc_blocks(struct device *dev, return -EINVAL; } -/* Functions to parse private data from configuration file format v4 */ - -/* - * Add pipeline from topology binary into driver pipeline list - * - * If already added we return that instance - * Otherwise we create a new instance and add into driver list - */ -static int skl_tplg_add_pipe_v4(struct device *dev, - struct skl_module_cfg *mconfig, struct skl_dev *skl, - struct skl_dfw_v4_pipe *dfw_pipe) -{ - struct skl_pipeline *ppl; - struct skl_pipe *pipe; - struct skl_pipe_params *params; - - list_for_each_entry(ppl, &skl->ppl_list, node) { - if (ppl->pipe->ppl_id == dfw_pipe->pipe_id) { - mconfig->pipe = ppl->pipe; - return 0; - } - } - - ppl = devm_kzalloc(dev, sizeof(*ppl), GFP_KERNEL); - if (!ppl) - return -ENOMEM; - - pipe = devm_kzalloc(dev, sizeof(*pipe), GFP_KERNEL); - if (!pipe) - return -ENOMEM; - - params = devm_kzalloc(dev, sizeof(*params), GFP_KERNEL); - if (!params) - return -ENOMEM; - - pipe->ppl_id = dfw_pipe->pipe_id; - pipe->memory_pages = dfw_pipe->memory_pages; - pipe->pipe_priority = dfw_pipe->pipe_priority; - pipe->conn_type = dfw_pipe->conn_type; - pipe->state = SKL_PIPE_INVALID; - pipe->p_params = params; - INIT_LIST_HEAD(&pipe->w_list); - - ppl->pipe = pipe; - list_add(&ppl->node, &skl->ppl_list); - - mconfig->pipe = pipe; - - return 0; -} - -static void skl_fill_module_pin_info_v4(struct skl_dfw_v4_module_pin *dfw_pin, - struct skl_module_pin *m_pin, - bool is_dynamic, int max_pin) -{ - int i; - - for (i = 0; i < max_pin; i++) { - m_pin[i].id.module_id = dfw_pin[i].module_id; - m_pin[i].id.instance_id = dfw_pin[i].instance_id; - m_pin[i].in_use = false; - m_pin[i].is_dynamic = is_dynamic; - m_pin[i].pin_state = SKL_PIN_UNBIND; - } -} - -static void skl_tplg_fill_fmt_v4(struct skl_module_pin_fmt *dst_fmt, - struct skl_dfw_v4_module_fmt *src_fmt, - int pins) -{ - int i; - - for (i = 0; i < pins; i++) { - dst_fmt[i].fmt.channels = src_fmt[i].channels; - dst_fmt[i].fmt.s_freq = src_fmt[i].freq; - dst_fmt[i].fmt.bit_depth = src_fmt[i].bit_depth; - dst_fmt[i].fmt.valid_bit_depth = src_fmt[i].valid_bit_depth; - dst_fmt[i].fmt.ch_cfg = src_fmt[i].ch_cfg; - dst_fmt[i].fmt.ch_map = src_fmt[i].ch_map; - dst_fmt[i].fmt.interleaving_style = - src_fmt[i].interleaving_style; - dst_fmt[i].fmt.sample_type = src_fmt[i].sample_type; - } -} - -static int skl_tplg_get_pvt_data_v4(struct snd_soc_tplg_dapm_widget *tplg_w, - struct skl_dev *skl, struct device *dev, - struct skl_module_cfg *mconfig) -{ - struct skl_dfw_v4_module *dfw = - (struct skl_dfw_v4_module *)tplg_w->priv.data; - int ret; - int idx = mconfig->fmt_cfg_idx; - - dev_dbg(dev, "Parsing Skylake v4 widget topology data\n"); - - ret = guid_parse(dfw->uuid, (guid_t *)mconfig->guid); - if (ret) - return ret; - mconfig->id.module_id = -1; - mconfig->id.instance_id = dfw->instance_id; - mconfig->module->resources[0].cpc = dfw->max_mcps / 1000; - mconfig->module->resources[0].ibs = dfw->ibs; - mconfig->module->resources[0].obs = dfw->obs; - mconfig->core_id = dfw->core_id; - mconfig->module->max_input_pins = dfw->max_in_queue; - mconfig->module->max_output_pins = dfw->max_out_queue; - mconfig->module->loadable = dfw->is_loadable; - skl_tplg_fill_fmt_v4(mconfig->module->formats[0].inputs, dfw->in_fmt, - MAX_IN_QUEUE); - skl_tplg_fill_fmt_v4(mconfig->module->formats[0].outputs, dfw->out_fmt, - MAX_OUT_QUEUE); - - mconfig->params_fixup = dfw->params_fixup; - mconfig->converter = dfw->converter; - mconfig->m_type = dfw->module_type; - mconfig->vbus_id = dfw->vbus_id; - mconfig->module->resources[0].is_pages = dfw->mem_pages; - - ret = skl_tplg_add_pipe_v4(dev, mconfig, skl, &dfw->pipe); - if (ret) - return ret; - - mconfig->dev_type = dfw->dev_type; - mconfig->hw_conn_type = dfw->hw_conn_type; - mconfig->time_slot = dfw->time_slot; - mconfig->formats_config[idx].caps_size = dfw->caps.caps_size; - - mconfig->m_in_pin = devm_kcalloc(dev, - MAX_IN_QUEUE, sizeof(*mconfig->m_in_pin), - GFP_KERNEL); - if (!mconfig->m_in_pin) - return -ENOMEM; - - mconfig->m_out_pin = devm_kcalloc(dev, - MAX_OUT_QUEUE, sizeof(*mconfig->m_out_pin), - GFP_KERNEL); - if (!mconfig->m_out_pin) - return -ENOMEM; - - skl_fill_module_pin_info_v4(dfw->in_pin, mconfig->m_in_pin, - dfw->is_dynamic_in_pin, - mconfig->module->max_input_pins); - skl_fill_module_pin_info_v4(dfw->out_pin, mconfig->m_out_pin, - dfw->is_dynamic_out_pin, - mconfig->module->max_output_pins); - - if (mconfig->formats_config[idx].caps_size) { - mconfig->formats_config[idx].set_params = dfw->caps.set_params; - mconfig->formats_config[idx].param_id = dfw->caps.param_id; - mconfig->formats_config[idx].caps = - devm_kzalloc(dev, mconfig->formats_config[idx].caps_size, - GFP_KERNEL); - if (!mconfig->formats_config[idx].caps) - return -ENOMEM; - memcpy(mconfig->formats_config[idx].caps, dfw->caps.caps, - dfw->caps.caps_size); - } - - return 0; -} - static int skl_tplg_get_caps_data(struct device *dev, char *data, struct skl_module_cfg *mconfig) { @@ -2877,13 +2715,6 @@ static int skl_tplg_get_pvt_data(struct snd_soc_tplg_dapm_widget *tplg_w, char *data; int ret; - /* - * v4 configuration files have a valid UUID at the start of - * the widget's private data. - */ - if (uuid_is_valid((char *)tplg_w->priv.data)) - return skl_tplg_get_pvt_data_v4(tplg_w, skl, dev, mconfig); - /* Read the NUM_DATA_BLOCKS descriptor */ array = (struct snd_soc_tplg_vendor_array *)tplg_w->priv.data; ret = skl_tplg_get_desc_blocks(dev, array); -- cgit v1.2.3 From c57468dc1f80a4a3bf6dd271688837d3c1f26e75 Mon Sep 17 00:00:00 2001 From: Cezary Rojewski Date: Wed, 3 Apr 2024 11:16:27 +0200 Subject: ASoC: topology: Remove ABI v4 support MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit There are no users of soc-topology ABI v4 since kernel v5.4 so remove all v4 -> v5 converters. Cc: Curtis Malainey Cc: Łukasz Majczak Signed-off-by: Cezary Rojewski Link: https://msgid.link/r/20240403091629.647267-3-cezary.rojewski@intel.com Signed-off-by: Mark Brown --- sound/soc/soc-topology.c | 210 ++++------------------------------------------- 1 file changed, 16 insertions(+), 194 deletions(-) diff --git a/sound/soc/soc-topology.c b/sound/soc/soc-topology.c index ba4890991f0d..75a7481a4f18 100644 --- a/sound/soc/soc-topology.c +++ b/sound/soc/soc-topology.c @@ -1761,75 +1761,6 @@ static int soc_tplg_pcm_create(struct soc_tplg *tplg, return soc_tplg_fe_link_create(tplg, pcm); } -/* copy stream caps from the old version 4 of source */ -static void stream_caps_new_ver(struct snd_soc_tplg_stream_caps *dest, - struct snd_soc_tplg_stream_caps_v4 *src) -{ - dest->size = cpu_to_le32(sizeof(*dest)); - memcpy(dest->name, src->name, SNDRV_CTL_ELEM_ID_NAME_MAXLEN); - dest->formats = src->formats; - dest->rates = src->rates; - dest->rate_min = src->rate_min; - dest->rate_max = src->rate_max; - dest->channels_min = src->channels_min; - dest->channels_max = src->channels_max; - dest->periods_min = src->periods_min; - dest->periods_max = src->periods_max; - dest->period_size_min = src->period_size_min; - dest->period_size_max = src->period_size_max; - dest->buffer_size_min = src->buffer_size_min; - dest->buffer_size_max = src->buffer_size_max; -} - -/** - * pcm_new_ver - Create the new version of PCM from the old version. - * @tplg: topology context - * @src: older version of pcm as a source - * @pcm: latest version of pcm created from the source - * - * Support from version 4. User should free the returned pcm manually. - */ -static int pcm_new_ver(struct soc_tplg *tplg, - struct snd_soc_tplg_pcm *src, - struct snd_soc_tplg_pcm **pcm) -{ - struct snd_soc_tplg_pcm *dest; - struct snd_soc_tplg_pcm_v4 *src_v4; - int i; - - *pcm = NULL; - - if (le32_to_cpu(src->size) != sizeof(*src_v4)) { - dev_err(tplg->dev, "ASoC: invalid PCM size\n"); - return -EINVAL; - } - - dev_warn(tplg->dev, "ASoC: old version of PCM\n"); - src_v4 = (struct snd_soc_tplg_pcm_v4 *)src; - dest = kzalloc(sizeof(*dest), GFP_KERNEL); - if (!dest) - return -ENOMEM; - - dest->size = cpu_to_le32(sizeof(*dest)); /* size of latest abi version */ - memcpy(dest->pcm_name, src_v4->pcm_name, SNDRV_CTL_ELEM_ID_NAME_MAXLEN); - memcpy(dest->dai_name, src_v4->dai_name, SNDRV_CTL_ELEM_ID_NAME_MAXLEN); - dest->pcm_id = src_v4->pcm_id; - dest->dai_id = src_v4->dai_id; - dest->playback = src_v4->playback; - dest->capture = src_v4->capture; - dest->compress = src_v4->compress; - dest->num_streams = src_v4->num_streams; - for (i = 0; i < le32_to_cpu(dest->num_streams); i++) - memcpy(&dest->stream[i], &src_v4->stream[i], - sizeof(struct snd_soc_tplg_stream)); - - for (i = 0; i < 2; i++) - stream_caps_new_ver(&dest->caps[i], &src_v4->caps[i]); - - *pcm = dest; - return 0; -} - static int soc_tplg_pcm_elems_load(struct soc_tplg *tplg, struct snd_soc_tplg_hdr *hdr) { @@ -1845,8 +1776,7 @@ static int soc_tplg_pcm_elems_load(struct soc_tplg *tplg, /* check the element size and count */ pcm = (struct snd_soc_tplg_pcm *)tplg->pos; size = le32_to_cpu(pcm->size); - if (size > sizeof(struct snd_soc_tplg_pcm) - || size < sizeof(struct snd_soc_tplg_pcm_v4)) { + if (size > sizeof(struct snd_soc_tplg_pcm)) { dev_err(tplg->dev, "ASoC: invalid size %d for PCM elems\n", size); return -EINVAL; @@ -1865,15 +1795,11 @@ static int soc_tplg_pcm_elems_load(struct soc_tplg *tplg, /* check ABI version by size, create a new version of pcm * if abi not match. */ - if (size == sizeof(*pcm)) { - abi_match = true; - _pcm = pcm; - } else { - abi_match = false; - ret = pcm_new_ver(tplg, pcm, &_pcm); - if (ret < 0) - return ret; - } + if (size != sizeof(*pcm)) + return -EINVAL; + + abi_match = true; + _pcm = pcm; /* create the FE DAIs and DAI links */ ret = soc_tplg_pcm_create(tplg, _pcm); @@ -1965,49 +1891,6 @@ static void set_link_hw_format(struct snd_soc_dai_link *link, } } -/** - * link_new_ver - Create a new physical link config from the old - * version of source. - * @tplg: topology context - * @src: old version of phyical link config as a source - * @link: latest version of physical link config created from the source - * - * Support from version 4. User need free the returned link config manually. - */ -static int link_new_ver(struct soc_tplg *tplg, - struct snd_soc_tplg_link_config *src, - struct snd_soc_tplg_link_config **link) -{ - struct snd_soc_tplg_link_config *dest; - struct snd_soc_tplg_link_config_v4 *src_v4; - int i; - - *link = NULL; - - if (le32_to_cpu(src->size) != - sizeof(struct snd_soc_tplg_link_config_v4)) { - dev_err(tplg->dev, "ASoC: invalid physical link config size\n"); - return -EINVAL; - } - - dev_warn(tplg->dev, "ASoC: old version of physical link config\n"); - - src_v4 = (struct snd_soc_tplg_link_config_v4 *)src; - dest = kzalloc(sizeof(*dest), GFP_KERNEL); - if (!dest) - return -ENOMEM; - - dest->size = cpu_to_le32(sizeof(*dest)); - dest->id = src_v4->id; - dest->num_streams = src_v4->num_streams; - for (i = 0; i < le32_to_cpu(dest->num_streams); i++) - memcpy(&dest->stream[i], &src_v4->stream[i], - sizeof(struct snd_soc_tplg_stream)); - - *link = dest; - return 0; -} - /** * snd_soc_find_dai_link - Find a DAI link * @@ -2124,8 +2007,7 @@ static int soc_tplg_link_elems_load(struct soc_tplg *tplg, /* check the element size and count */ link = (struct snd_soc_tplg_link_config *)tplg->pos; size = le32_to_cpu(link->size); - if (size > sizeof(struct snd_soc_tplg_link_config) - || size < sizeof(struct snd_soc_tplg_link_config_v4)) { + if (size > sizeof(struct snd_soc_tplg_link_config)) { dev_err(tplg->dev, "ASoC: invalid size %d for physical link elems\n", size); return -EINVAL; @@ -2140,15 +2022,11 @@ static int soc_tplg_link_elems_load(struct soc_tplg *tplg, for (i = 0; i < count; i++) { link = (struct snd_soc_tplg_link_config *)tplg->pos; size = le32_to_cpu(link->size); - if (size == sizeof(*link)) { - abi_match = true; - _link = link; - } else { - abi_match = false; - ret = link_new_ver(tplg, link, &_link); - if (ret < 0) - return ret; - } + if (size != sizeof(*link)) + return -EINVAL; + + abi_match = true; + _link = link; ret = soc_tplg_link_config(tplg, _link); if (ret < 0) { @@ -2273,57 +2151,6 @@ static int soc_tplg_dai_elems_load(struct soc_tplg *tplg, return 0; } -/** - * manifest_new_ver - Create a new version of manifest from the old version - * of source. - * @tplg: topology context - * @src: old version of manifest as a source - * @manifest: latest version of manifest created from the source - * - * Support from version 4. Users need free the returned manifest manually. - */ -static int manifest_new_ver(struct soc_tplg *tplg, - struct snd_soc_tplg_manifest *src, - struct snd_soc_tplg_manifest **manifest) -{ - struct snd_soc_tplg_manifest *dest; - struct snd_soc_tplg_manifest_v4 *src_v4; - int size; - - *manifest = NULL; - - size = le32_to_cpu(src->size); - if (size != sizeof(*src_v4)) { - dev_warn(tplg->dev, "ASoC: invalid manifest size %d\n", - size); - if (size) - return -EINVAL; - src->size = cpu_to_le32(sizeof(*src_v4)); - } - - dev_warn(tplg->dev, "ASoC: old version of manifest\n"); - - src_v4 = (struct snd_soc_tplg_manifest_v4 *)src; - dest = kzalloc(sizeof(*dest) + le32_to_cpu(src_v4->priv.size), - GFP_KERNEL); - if (!dest) - return -ENOMEM; - - dest->size = cpu_to_le32(sizeof(*dest)); /* size of latest abi version */ - dest->control_elems = src_v4->control_elems; - dest->widget_elems = src_v4->widget_elems; - dest->graph_elems = src_v4->graph_elems; - dest->pcm_elems = src_v4->pcm_elems; - dest->dai_link_elems = src_v4->dai_link_elems; - dest->priv.size = src_v4->priv.size; - if (dest->priv.size) - memcpy(dest->priv.data, src_v4->priv.data, - le32_to_cpu(src_v4->priv.size)); - - *manifest = dest; - return 0; -} - static int soc_tplg_manifest_load(struct soc_tplg *tplg, struct snd_soc_tplg_hdr *hdr) { @@ -2334,16 +2161,11 @@ static int soc_tplg_manifest_load(struct soc_tplg *tplg, manifest = (struct snd_soc_tplg_manifest *)tplg->pos; /* check ABI version by size, create a new manifest if abi not match */ - if (le32_to_cpu(manifest->size) == sizeof(*manifest)) { - abi_match = true; - _manifest = manifest; - } else { - abi_match = false; + if (le32_to_cpu(manifest->size) != sizeof(*manifest)) + return -EINVAL; - ret = manifest_new_ver(tplg, manifest, &_manifest); - if (ret < 0) - return ret; - } + abi_match = true; + _manifest = manifest; /* pass control to component driver for optional further init */ if (tplg->ops && tplg->ops->manifest) -- cgit v1.2.3 From 82c192540b242a8bf3c3d4140905650df9f327d4 Mon Sep 17 00:00:00 2001 From: Cezary Rojewski Date: Wed, 3 Apr 2024 11:16:28 +0200 Subject: ASoC: topology: Cleanup after ABI v4 support removal MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Flag 'abi_match' along with several other local variables has no purpose with v4 related members removed. Cc: Curtis Malainey Cc: Łukasz Majczak Signed-off-by: Cezary Rojewski Link: https://msgid.link/r/20240403091629.647267-4-cezary.rojewski@intel.com Signed-off-by: Mark Brown --- sound/soc/soc-topology.c | 47 ++++++++++------------------------------------- 1 file changed, 10 insertions(+), 37 deletions(-) diff --git a/sound/soc/soc-topology.c b/sound/soc/soc-topology.c index 75a7481a4f18..d6d368837235 100644 --- a/sound/soc/soc-topology.c +++ b/sound/soc/soc-topology.c @@ -1764,11 +1764,10 @@ static int soc_tplg_pcm_create(struct soc_tplg *tplg, static int soc_tplg_pcm_elems_load(struct soc_tplg *tplg, struct snd_soc_tplg_hdr *hdr) { - struct snd_soc_tplg_pcm *pcm, *_pcm; + struct snd_soc_tplg_pcm *pcm; int count; int size; int i; - bool abi_match; int ret; count = le32_to_cpu(hdr->count); @@ -1798,24 +1797,15 @@ static int soc_tplg_pcm_elems_load(struct soc_tplg *tplg, if (size != sizeof(*pcm)) return -EINVAL; - abi_match = true; - _pcm = pcm; - /* create the FE DAIs and DAI links */ - ret = soc_tplg_pcm_create(tplg, _pcm); - if (ret < 0) { - if (!abi_match) - kfree(_pcm); + ret = soc_tplg_pcm_create(tplg, pcm); + if (ret < 0) return ret; - } /* offset by version-specific struct size and * real priv data size */ - tplg->pos += size + le32_to_cpu(_pcm->priv.size); - - if (!abi_match) - kfree(_pcm); /* free the duplicated one */ + tplg->pos += size + le32_to_cpu(pcm->priv.size); } dev_dbg(tplg->dev, "ASoC: adding %d PCM DAIs\n", count); @@ -1996,11 +1986,10 @@ static int soc_tplg_link_config(struct soc_tplg *tplg, static int soc_tplg_link_elems_load(struct soc_tplg *tplg, struct snd_soc_tplg_hdr *hdr) { - struct snd_soc_tplg_link_config *link, *_link; + struct snd_soc_tplg_link_config *link; int count; int size; int i, ret; - bool abi_match; count = le32_to_cpu(hdr->count); @@ -2025,23 +2014,14 @@ static int soc_tplg_link_elems_load(struct soc_tplg *tplg, if (size != sizeof(*link)) return -EINVAL; - abi_match = true; - _link = link; - - ret = soc_tplg_link_config(tplg, _link); - if (ret < 0) { - if (!abi_match) - kfree(_link); + ret = soc_tplg_link_config(tplg, link); + if (ret < 0) return ret; - } /* offset by version-specific struct size and * real priv data size */ - tplg->pos += size + le32_to_cpu(_link->priv.size); - - if (!abi_match) - kfree(_link); /* free the duplicated one */ + tplg->pos += size + le32_to_cpu(link->priv.size); } return 0; @@ -2154,8 +2134,7 @@ static int soc_tplg_dai_elems_load(struct soc_tplg *tplg, static int soc_tplg_manifest_load(struct soc_tplg *tplg, struct snd_soc_tplg_hdr *hdr) { - struct snd_soc_tplg_manifest *manifest, *_manifest; - bool abi_match; + struct snd_soc_tplg_manifest *manifest; int ret = 0; manifest = (struct snd_soc_tplg_manifest *)tplg->pos; @@ -2164,15 +2143,9 @@ static int soc_tplg_manifest_load(struct soc_tplg *tplg, if (le32_to_cpu(manifest->size) != sizeof(*manifest)) return -EINVAL; - abi_match = true; - _manifest = manifest; - /* pass control to component driver for optional further init */ if (tplg->ops && tplg->ops->manifest) - ret = tplg->ops->manifest(tplg->comp, tplg->index, _manifest); - - if (!abi_match) /* free the duplicated one */ - kfree(_manifest); + ret = tplg->ops->manifest(tplg->comp, tplg->index, manifest); return ret; } -- cgit v1.2.3 From 4ba509bf3988f36b536b49b9e7022a6358f87f56 Mon Sep 17 00:00:00 2001 From: Cezary Rojewski Date: Wed, 3 Apr 2024 11:16:29 +0200 Subject: ASoC: topology: Remove obsolete ABI v4 structs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit There are no users of soc-topology ABI v4 since kernel v5.4 and no kernel code makes use of them. Cc: Curtis Malainey Cc: Łukasz Majczak Signed-off-by: Cezary Rojewski Link: https://msgid.link/r/20240403091629.647267-5-cezary.rojewski@intel.com Signed-off-by: Mark Brown --- include/uapi/sound/asoc.h | 56 ----------------------------------------------- 1 file changed, 56 deletions(-) diff --git a/include/uapi/sound/asoc.h b/include/uapi/sound/asoc.h index 10851bca7174..99333cbd3114 100644 --- a/include/uapi/sound/asoc.h +++ b/include/uapi/sound/asoc.h @@ -576,60 +576,4 @@ struct snd_soc_tplg_dai { struct snd_soc_tplg_private priv; } __attribute__((packed)); -/* - * Old version of ABI structs, supported for backward compatibility. - */ - -/* Manifest v4 */ -struct snd_soc_tplg_manifest_v4 { - __le32 size; /* in bytes of this structure */ - __le32 control_elems; /* number of control elements */ - __le32 widget_elems; /* number of widget elements */ - __le32 graph_elems; /* number of graph elements */ - __le32 pcm_elems; /* number of PCM elements */ - __le32 dai_link_elems; /* number of DAI link elements */ - struct snd_soc_tplg_private priv; -} __packed; - -/* Stream Capabilities v4 */ -struct snd_soc_tplg_stream_caps_v4 { - __le32 size; /* in bytes of this structure */ - char name[SNDRV_CTL_ELEM_ID_NAME_MAXLEN]; - __le64 formats; /* supported formats SNDRV_PCM_FMTBIT_* */ - __le32 rates; /* supported rates SNDRV_PCM_RATE_* */ - __le32 rate_min; /* min rate */ - __le32 rate_max; /* max rate */ - __le32 channels_min; /* min channels */ - __le32 channels_max; /* max channels */ - __le32 periods_min; /* min number of periods */ - __le32 periods_max; /* max number of periods */ - __le32 period_size_min; /* min period size bytes */ - __le32 period_size_max; /* max period size bytes */ - __le32 buffer_size_min; /* min buffer size bytes */ - __le32 buffer_size_max; /* max buffer size bytes */ -} __packed; - -/* PCM v4 */ -struct snd_soc_tplg_pcm_v4 { - __le32 size; /* in bytes of this structure */ - char pcm_name[SNDRV_CTL_ELEM_ID_NAME_MAXLEN]; - char dai_name[SNDRV_CTL_ELEM_ID_NAME_MAXLEN]; - __le32 pcm_id; /* unique ID - used to match with DAI link */ - __le32 dai_id; /* unique ID - used to match */ - __le32 playback; /* supports playback mode */ - __le32 capture; /* supports capture mode */ - __le32 compress; /* 1 = compressed; 0 = PCM */ - struct snd_soc_tplg_stream stream[SND_SOC_TPLG_STREAM_CONFIG_MAX]; /* for DAI link */ - __le32 num_streams; /* number of streams */ - struct snd_soc_tplg_stream_caps_v4 caps[2]; /* playback and capture for DAI */ -} __packed; - -/* Physical link config v4 */ -struct snd_soc_tplg_link_config_v4 { - __le32 size; /* in bytes of this structure */ - __le32 id; /* unique ID - used to match */ - struct snd_soc_tplg_stream stream[SND_SOC_TPLG_STREAM_CONFIG_MAX]; /* supported configs playback and captrure */ - __le32 num_streams; /* number of streams */ -} __packed; - #endif -- cgit v1.2.3 From 6334b8e4553cc69f51e383c9de545082213d785e Mon Sep 17 00:00:00 2001 From: Norihiko Hama Date: Wed, 27 Mar 2024 11:35:50 +0900 Subject: usb: gadget: f_ncm: Fix UAF ncm object at re-bind after usb ep transport error When ncm function is working and then stop usb0 interface for link down, eth_stop() is called. At this piont, accidentally if usb transport error should happen in usb_ep_enable(), 'in_ep' and/or 'out_ep' may not be enabled. After that, ncm_disable() is called to disable for ncm unbind but gether_disconnect() is never called since 'in_ep' is not enabled. As the result, ncm object is released in ncm unbind but 'dev->port_usb' associated to 'ncm->port' is not NULL. And when ncm bind again to recover netdev, ncm object is reallocated but usb0 interface is already associated to previous released ncm object. Therefore, once usb0 interface is up and eth_start_xmit() is called, released ncm object is dereferrenced and it might cause use-after-free memory. [function unlink via configfs] usb0: eth_stop dev->port_usb=ffffff9b179c3200 --> error happens in usb_ep_enable(). NCM: ncm_disable: ncm=ffffff9b179c3200 --> no gether_disconnect() since ncm->port.in_ep->enabled is false. NCM: ncm_unbind: ncm unbind ncm=ffffff9b179c3200 NCM: ncm_free: ncm free ncm=ffffff9b179c3200 <-- released ncm [function link via configfs] NCM: ncm_alloc: ncm alloc ncm=ffffff9ac4f8a000 NCM: ncm_bind: ncm bind ncm=ffffff9ac4f8a000 NCM: ncm_set_alt: ncm=ffffff9ac4f8a000 alt=0 usb0: eth_open dev->port_usb=ffffff9b179c3200 <-- previous released ncm usb0: eth_start dev->port_usb=ffffff9b179c3200 <-- eth_start_xmit() --> dev->wrap() Unable to handle kernel paging request at virtual address dead00000000014f This patch addresses the issue by checking if 'ncm->netdev' is not NULL at ncm_disable() to call gether_disconnect() to deassociate 'dev->port_usb'. It's more reasonable to check 'ncm->netdev' to call gether_connect/disconnect rather than check 'ncm->port.in_ep->enabled' since it might not be enabled but the gether connection might be established. Signed-off-by: Norihiko Hama Cc: stable Link: https://lore.kernel.org/r/20240327023550.51214-1-Norihiko.Hama@alpsalpine.com Signed-off-by: Greg Kroah-Hartman --- drivers/usb/gadget/function/f_ncm.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/usb/gadget/function/f_ncm.c b/drivers/usb/gadget/function/f_ncm.c index 28f4e6552e84..0acc32ed9960 100644 --- a/drivers/usb/gadget/function/f_ncm.c +++ b/drivers/usb/gadget/function/f_ncm.c @@ -878,7 +878,7 @@ static int ncm_set_alt(struct usb_function *f, unsigned intf, unsigned alt) if (alt > 1) goto fail; - if (ncm->port.in_ep->enabled) { + if (ncm->netdev) { DBG(cdev, "reset ncm\n"); ncm->netdev = NULL; gether_disconnect(&ncm->port); @@ -1367,7 +1367,7 @@ static void ncm_disable(struct usb_function *f) DBG(cdev, "ncm deactivated\n"); - if (ncm->port.in_ep->enabled) { + if (ncm->netdev) { ncm->netdev = NULL; gether_disconnect(&ncm->port); } -- cgit v1.2.3 From d920a2ed8620be04a3301e1a9c2b7cc1de65f19d Mon Sep 17 00:00:00 2001 From: Kai-Heng Feng Date: Tue, 5 Mar 2024 14:51:38 +0800 Subject: usb: Disable USB3 LPM at shutdown SanDisks USB3 storage may disapper after system reboot: usb usb2-port3: link state change xhci_hcd 0000:00:14.0: clear port3 link state change, portsc: 0x2c0 usb usb2-port3: do warm reset, port only xhci_hcd 0000:00:14.0: xhci_hub_status_data: stopping usb2 port polling xhci_hcd 0000:00:14.0: Get port status 2-3 read: 0x2b0, return 0x2b0 usb usb2-port3: not warm reset yet, waiting 50ms xhci_hcd 0000:00:14.0: Get port status 2-3 read: 0x2f0, return 0x2f0 usb usb2-port3: not warm reset yet, waiting 200ms ... xhci_hcd 0000:00:14.0: Get port status 2-3 read: 0x6802c0, return 0x7002c0 usb usb2-port3: not warm reset yet, waiting 200ms xhci_hcd 0000:00:14.0: clear port3 reset change, portsc: 0x4802c0 xhci_hcd 0000:00:14.0: clear port3 warm(BH) reset change, portsc: 0x4002c0 xhci_hcd 0000:00:14.0: clear port3 link state change, portsc: 0x2c0 xhci_hcd 0000:00:14.0: Get port status 2-3 read: 0x2c0, return 0x2c0 usb usb2-port3: not enabled, trying warm reset again... This is due to the USB device still cause port change event after xHCI is shuted down: xhci_hcd 0000:38:00.0: // Setting command ring address to 0xffffe001 xhci_hcd 0000:38:00.0: xhci_resume: starting usb3 port polling. xhci_hcd 0000:38:00.0: xhci_hub_status_data: stopping usb4 port polling xhci_hcd 0000:38:00.0: xhci_hub_status_data: stopping usb3 port polling xhci_hcd 0000:38:00.0: hcd_pci_runtime_resume: 0 xhci_hcd 0000:38:00.0: xhci_shutdown: stopping usb3 port polling. xhci_hcd 0000:38:00.0: // Halt the HC xhci_hcd 0000:38:00.0: xhci_shutdown completed - status = 1 xhci_hcd 0000:00:14.0: xhci_shutdown: stopping usb1 port polling. xhci_hcd 0000:00:14.0: // Halt the HC xhci_hcd 0000:00:14.0: xhci_shutdown completed - status = 1 xhci_hcd 0000:00:14.0: Get port status 2-3 read: 0x1203, return 0x203 xhci_hcd 0000:00:14.0: set port reset, actual port 2-3 status = 0x1311 xhci_hcd 0000:00:14.0: Get port status 2-3 read: 0x201203, return 0x100203 xhci_hcd 0000:00:14.0: clear port3 reset change, portsc: 0x1203 xhci_hcd 0000:00:14.0: clear port3 warm(BH) reset change, portsc: 0x1203 xhci_hcd 0000:00:14.0: clear port3 link state change, portsc: 0x1203 xhci_hcd 0000:00:14.0: clear port3 connect change, portsc: 0x1203 xhci_hcd 0000:00:14.0: Get port status 2-3 read: 0x1203, return 0x203 usb 2-3: device not accepting address 2, error -108 xhci_hcd 0000:00:14.0: xHCI dying or halted, can't queue_command xhci_hcd 0000:00:14.0: Set port 2-3 link state, portsc: 0x1203, write 0x11261 xhci_hcd 0000:00:14.0: Get port status 2-3 read: 0x1263, return 0x263 xhci_hcd 0000:00:14.0: set port reset, actual port 2-3 status = 0x1271 xhci_hcd 0000:00:14.0: Get port status 2-3 read: 0x12b1, return 0x2b1 usb usb2-port3: not reset yet, waiting 60ms ACPI: PM: Preparing to enter system sleep state S5 xhci_hcd 0000:00:14.0: Get port status 2-3 read: 0x12f1, return 0x2f1 usb usb2-port3: not reset yet, waiting 200ms reboot: Restarting system The port change event is caused by LPM transition, so disabling LPM at shutdown to make sure the device is in U0 for warmboot. Signed-off-by: Kai-Heng Feng Cc: stable Link: https://lore.kernel.org/r/20240305065140.66801-1-kai.heng.feng@canonical.com Signed-off-by: Greg Kroah-Hartman --- drivers/usb/core/port.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/usb/core/port.c b/drivers/usb/core/port.c index 686c01af03e6..0e1262a077ae 100644 --- a/drivers/usb/core/port.c +++ b/drivers/usb/core/port.c @@ -449,8 +449,10 @@ static void usb_port_shutdown(struct device *dev) { struct usb_port *port_dev = to_usb_port(dev); - if (port_dev->child) + if (port_dev->child) { usb_disable_usb2_hardware_lpm(port_dev->child); + usb_unlocked_disable_lpm(port_dev->child); + } } static const struct dev_pm_ops usb_port_pm_ops = { -- cgit v1.2.3 From 1fc9af813b25e146d3607669247d0f970f5a87c3 Mon Sep 17 00:00:00 2001 From: Boris Brezillon Date: Fri, 5 Jan 2024 21:46:11 +0300 Subject: drm/panfrost: Fix the error path in panfrost_mmu_map_fault_addr() Subject: [PATCH] drm/panfrost: Fix the error path in panfrost_mmu_map_fault_addr() If some the pages or sgt allocation failed, we shouldn't release the pages ref we got earlier, otherwise we will end up with unbalanced get/put_pages() calls. We should instead leave everything in place and let the BO release function deal with extra cleanup when the object is destroyed, or let the fault handler try again next time it's called. Fixes: 187d2929206e ("drm/panfrost: Add support for GPU heap allocations") Cc: Reviewed-by: Steven Price Reviewed-by: AngeloGioacchino Del Regno Signed-off-by: Boris Brezillon Co-developed-by: Dmitry Osipenko Signed-off-by: Dmitry Osipenko Link: https://patchwork.freedesktop.org/patch/msgid/20240105184624.508603-18-dmitry.osipenko@collabora.com --- drivers/gpu/drm/panfrost/panfrost_mmu.c | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/panfrost/panfrost_mmu.c b/drivers/gpu/drm/panfrost/panfrost_mmu.c index f38385fe76bb..b91019cd5acb 100644 --- a/drivers/gpu/drm/panfrost/panfrost_mmu.c +++ b/drivers/gpu/drm/panfrost/panfrost_mmu.c @@ -502,11 +502,18 @@ static int panfrost_mmu_map_fault_addr(struct panfrost_device *pfdev, int as, mapping_set_unevictable(mapping); for (i = page_offset; i < page_offset + NUM_FAULT_PAGES; i++) { + /* Can happen if the last fault only partially filled this + * section of the pages array before failing. In that case + * we skip already filled pages. + */ + if (pages[i]) + continue; + pages[i] = shmem_read_mapping_page(mapping, i); if (IS_ERR(pages[i])) { ret = PTR_ERR(pages[i]); pages[i] = NULL; - goto err_pages; + goto err_unlock; } } @@ -514,7 +521,7 @@ static int panfrost_mmu_map_fault_addr(struct panfrost_device *pfdev, int as, ret = sg_alloc_table_from_pages(sgt, pages + page_offset, NUM_FAULT_PAGES, 0, SZ_2M, GFP_KERNEL); if (ret) - goto err_pages; + goto err_unlock; ret = dma_map_sgtable(pfdev->dev, sgt, DMA_BIDIRECTIONAL, 0); if (ret) @@ -537,8 +544,6 @@ out: err_map: sg_free_table(sgt); -err_pages: - drm_gem_shmem_put_pages(&bo->base); err_unlock: dma_resv_unlock(obj->resv); err_bo: -- cgit v1.2.3 From 84ae7d9cfa5f6ec284efccedcb7baf7c075774d4 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Thu, 4 Apr 2024 10:38:45 +0300 Subject: ASoC: SOF: Disable pointless writes to debugfs file The permissions on this debugfs file are 0444 so it can't be written to. And writing to the file hasn't done anything since commit 6e9548cdb30e ("ASoC: SOF: Convert the generic IPC flood test into SOF client"). Delete the write function. Signed-off-by: Dan Carpenter Acked-by: Peter Ujfalusi Link: https://msgid.link/r/9d2477cf-25aa-4d12-818f-fdafc9aaa28a@moroto.mountain Signed-off-by: Mark Brown --- sound/soc/sof/debug.c | 19 ------------------- 1 file changed, 19 deletions(-) diff --git a/sound/soc/sof/debug.c b/sound/soc/sof/debug.c index 7c8aafca8fde..937e51b02a24 100644 --- a/sound/soc/sof/debug.c +++ b/sound/soc/sof/debug.c @@ -19,24 +19,6 @@ #include "sof-priv.h" #include "ops.h" -static ssize_t sof_dfsentry_write(struct file *file, const char __user *buffer, - size_t count, loff_t *ppos) -{ - size_t size; - char *string; - int ret; - - string = kzalloc(count+1, GFP_KERNEL); - if (!string) - return -ENOMEM; - - size = simple_write_to_buffer(string, count, ppos, buffer, count); - ret = size; - - kfree(string); - return ret; -} - static ssize_t sof_dfsentry_read(struct file *file, char __user *buffer, size_t count, loff_t *ppos) { @@ -126,7 +108,6 @@ static const struct file_operations sof_dfs_fops = { .open = simple_open, .read = sof_dfsentry_read, .llseek = default_llseek, - .write = sof_dfsentry_write, }; /* create FS entry for debug files that can expose DSP memories, registers */ -- cgit v1.2.3 From 2cfa0eea2675ce569dc80d2c0d2d644a452b77b3 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Thu, 4 Apr 2024 10:34:53 +0300 Subject: ASoC: SOF: Clean up sof_ipc_flood_dfs_write() This function doesn't support partial writes so using simple_write_to_buffer() doesn't really make sense. It's better to just use copy_from_user(). Signed-off-by: Dan Carpenter Acked-by: Peter Ujfalusi Link: https://msgid.link/r/a35dded2-392b-4ccb-9dbb-d782ac9b6547@moroto.mountain Signed-off-by: Mark Brown --- sound/soc/sof/sof-client-ipc-flood-test.c | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/sound/soc/sof/sof-client-ipc-flood-test.c b/sound/soc/sof/sof-client-ipc-flood-test.c index c0d6723aed59..1b2e9e25a836 100644 --- a/sound/soc/sof/sof-client-ipc-flood-test.c +++ b/sound/soc/sof/sof-client-ipc-flood-test.c @@ -160,15 +160,20 @@ static ssize_t sof_ipc_flood_dfs_write(struct file *file, const char __user *buf unsigned long ipc_count = 0; struct dentry *dentry; int err; - size_t size; char *string; int ret; + if (*ppos != 0) + return -EINVAL; + string = kzalloc(count + 1, GFP_KERNEL); if (!string) return -ENOMEM; - size = simple_write_to_buffer(string, count, ppos, buffer, count); + if (copy_from_user(string, buffer, count)) { + ret = -EFAULT; + goto out; + } /* * write op is only supported for ipc_flood_count or @@ -198,7 +203,7 @@ static ssize_t sof_ipc_flood_dfs_write(struct file *file, const char __user *buf /* limit max duration/ipc count for flood test */ if (flood_duration_test) { if (!ipc_duration_ms) { - ret = size; + ret = count; goto out; } @@ -207,7 +212,7 @@ static ssize_t sof_ipc_flood_dfs_write(struct file *file, const char __user *buf ipc_duration_ms = MAX_IPC_FLOOD_DURATION_MS; } else { if (!ipc_count) { - ret = size; + ret = count; goto out; } @@ -231,9 +236,9 @@ static ssize_t sof_ipc_flood_dfs_write(struct file *file, const char __user *buf if (err < 0) dev_err_ratelimited(dev, "debugfs write failed to idle %d\n", err); - /* return size if test is successful */ + /* return count if test is successful */ if (ret >= 0) - ret = size; + ret = count; out: kfree(string); return ret; -- cgit v1.2.3 From 1a4ea83a6e67f1415a1f17c1af5e9c814c882bb5 Mon Sep 17 00:00:00 2001 From: Yuanhe Shu Date: Mon, 26 Feb 2024 11:18:16 +0800 Subject: selftests/ftrace: Limit length in subsystem-enable tests While sched* events being traced and sched* events continuously happen, "[xx] event tracing - enable/disable with subsystem level files" would not stop as on some slower systems it seems to take forever. Select the first 100 lines of output would be enough to judge whether there are more than 3 types of sched events. Fixes: 815b18ea66d6 ("ftracetest: Add basic event tracing test cases") Cc: stable@vger.kernel.org Signed-off-by: Yuanhe Shu Acked-by: Masami Hiramatsu (Google) Acked-by: Steven Rostedt (Google) Signed-off-by: Shuah Khan --- tools/testing/selftests/ftrace/test.d/event/subsystem-enable.tc | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tools/testing/selftests/ftrace/test.d/event/subsystem-enable.tc b/tools/testing/selftests/ftrace/test.d/event/subsystem-enable.tc index b1ede6249866..b7c8f29c09a9 100644 --- a/tools/testing/selftests/ftrace/test.d/event/subsystem-enable.tc +++ b/tools/testing/selftests/ftrace/test.d/event/subsystem-enable.tc @@ -18,7 +18,7 @@ echo 'sched:*' > set_event yield -count=`cat trace | grep -v ^# | awk '{ print $5 }' | sort -u | wc -l` +count=`head -n 100 trace | grep -v ^# | awk '{ print $5 }' | sort -u | wc -l` if [ $count -lt 3 ]; then fail "at least fork, exec and exit events should be recorded" fi @@ -29,7 +29,7 @@ echo 1 > events/sched/enable yield -count=`cat trace | grep -v ^# | awk '{ print $5 }' | sort -u | wc -l` +count=`head -n 100 trace | grep -v ^# | awk '{ print $5 }' | sort -u | wc -l` if [ $count -lt 3 ]; then fail "at least fork, exec and exit events should be recorded" fi @@ -40,7 +40,7 @@ echo 0 > events/sched/enable yield -count=`cat trace | grep -v ^# | awk '{ print $5 }' | sort -u | wc -l` +count=`head -n 100 trace | grep -v ^# | awk '{ print $5 }' | sort -u | wc -l` if [ $count -ne 0 ]; then fail "any of scheduler events should not be recorded" fi -- cgit v1.2.3 From 72d7cb5c190befbb095bae7737e71560ec0fcaa6 Mon Sep 17 00:00:00 2001 From: Shengyu Li Date: Wed, 27 Mar 2024 05:13:15 +0800 Subject: selftests/harness: Prevent infinite loop due to Assert in FIXTURE_TEARDOWN This patch addresses an issue in the selftests/harness where an assertion within FIXTURE_TEARDOWN could trigger an infinite loop. The problem arises because the teardown procedure is meant to execute once, but the presence of failing assertions (ASSERT_EQ(0, 1)) leads to repeated attempts to execute teardown due to the long jump mechanism used by the harness for handling assertions. To resolve this, the patch ensures that the teardown process runs only once, regardless of assertion outcomes, preventing the infinite loop and allowing tests to fail. A simple test demo(test.c): #include "kselftest_harness.h" FIXTURE(f) { int fd; }; FIXTURE_SETUP(f) { self->fd = 0; } FIXTURE_TEARDOWN(f) { TH_LOG("TEARDOWN"); ASSERT_EQ(0, 1); self->fd = -1; } TEST_F(f, open_close) { ASSERT_NE(self->fd, 1); } TEST_HARNESS_MAIN will always output the following output due to a dead loop until timeout: # test.c:15:open_close:TEARDOWN # test.c:16:open_close:Expected 0 (0) == 1 (1) # test.c:15:open_close:TEARDOWN # test.c:16:open_close:Expected 0 (0) == 1 (1) ... But here's what we should and expect to get: TAP version 13 1..1 # Starting 1 tests from 2 test cases. # RUN f.open_close ... # test.c:15:open_close:TEARDOWN # test.c:16:open_close:Expected 0 (0) == 1 (1) # open_close: Test terminated by assertion # FAIL f.open_close not ok 1 f.open_close # FAILED: 0 / 1 tests passed. # Totals: pass:0 fail:1 xfail:0 xpass:0 skip:0 error:0 also this is related to the issue mentioned in this patch https://patchwork.kernel.org/project/linux-kselftest/patch/e2ba3f8c-80e6-477d-9cea-1c9af820e0ed@alu.unizg.hr/ Signed-off-by: Shengyu Li Signed-off-by: Shuah Khan --- tools/testing/selftests/kselftest_harness.h | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/tools/testing/selftests/kselftest_harness.h b/tools/testing/selftests/kselftest_harness.h index 4fd735e48ee7..230d62884885 100644 --- a/tools/testing/selftests/kselftest_harness.h +++ b/tools/testing/selftests/kselftest_harness.h @@ -383,6 +383,7 @@ FIXTURE_DATA(fixture_name) self; \ pid_t child = 1; \ int status = 0; \ + bool jmp = false; \ memset(&self, 0, sizeof(FIXTURE_DATA(fixture_name))); \ if (setjmp(_metadata->env) == 0) { \ /* Use the same _metadata. */ \ @@ -399,8 +400,10 @@ _metadata->exit_code = KSFT_FAIL; \ } \ } \ + else \ + jmp = true; \ if (child == 0) { \ - if (_metadata->setup_completed && !_metadata->teardown_parent) \ + if (_metadata->setup_completed && !_metadata->teardown_parent && !jmp) \ fixture_name##_teardown(_metadata, &self, variant->data); \ _exit(0); \ } \ -- cgit v1.2.3 From e9ae5adce99e27ef29ea9ccb01afe260bf1c1408 Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Thu, 4 Apr 2024 13:54:45 -0500 Subject: ASoC: SOF: Intel: hda-loader: add flag to tag ICCMAX stream MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The existing code conflates capture stream and ICCMAX stream. This isn't going to be true any longer when we add support for SDW BPT RX streams. Add a boolean tag to flag ICCMAX streams. No functionality change, only future-proofing change. Signed-off-by: Pierre-Louis Bossart Reviewed-by: Péter Ujfalusi Reviewed-by: Rander Wang Reviewed-by: Ranjani Sridharan Link: https://msgid.link/r/20240404185448.136157-2-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/intel/hda-loader.c | 10 +++++----- sound/soc/sof/intel/hda.h | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/sound/soc/sof/intel/hda-loader.c b/sound/soc/sof/intel/hda-loader.c index d5b9209beb5a..dafb6b3ebb20 100644 --- a/sound/soc/sof/intel/hda-loader.c +++ b/sound/soc/sof/intel/hda-loader.c @@ -46,7 +46,7 @@ static void hda_ssp_set_cbp_cfp(struct snd_sof_dev *sdev) struct hdac_ext_stream *hda_cl_stream_prepare(struct snd_sof_dev *sdev, unsigned int format, unsigned int size, struct snd_dma_buffer *dmab, - int direction) + int direction, bool is_iccmax) { struct hdac_ext_stream *hext_stream; struct hdac_stream *hstream; @@ -73,7 +73,7 @@ struct hdac_ext_stream *hda_cl_stream_prepare(struct snd_sof_dev *sdev, unsigned hstream->format_val = format; hstream->bufsize = size; - if (direction == SNDRV_PCM_STREAM_CAPTURE) { + if (is_iccmax) { ret = hda_dsp_iccmax_stream_hw_params(sdev, hext_stream, dmab, NULL); if (ret < 0) { dev_err(sdev->dev, "error: iccmax stream prepare failed: %d\n", ret); @@ -335,7 +335,7 @@ int hda_dsp_cl_boot_firmware_iccmax(struct snd_sof_dev *sdev) * the data, so use a buffer of PAGE_SIZE for receiving. */ iccmax_stream = hda_cl_stream_prepare(sdev, HDA_CL_STREAM_FORMAT, PAGE_SIZE, - &dmab_bdl, SNDRV_PCM_STREAM_CAPTURE); + &dmab_bdl, SNDRV_PCM_STREAM_CAPTURE, true); if (IS_ERR(iccmax_stream)) { dev_err(sdev->dev, "error: dma prepare for ICCMAX stream failed\n"); return PTR_ERR(iccmax_stream); @@ -421,7 +421,7 @@ int hda_dsp_cl_boot_firmware(struct snd_sof_dev *sdev) /* prepare DMA for code loader stream */ hext_stream = hda_cl_stream_prepare(sdev, HDA_CL_STREAM_FORMAT, stripped_firmware.size, - &dmab, SNDRV_PCM_STREAM_PLAYBACK); + &dmab, SNDRV_PCM_STREAM_PLAYBACK, false); if (IS_ERR(hext_stream)) { dev_err(sdev->dev, "error: dma prepare for fw loading failed\n"); return PTR_ERR(hext_stream); @@ -538,7 +538,7 @@ int hda_dsp_ipc4_load_library(struct snd_sof_dev *sdev, /* prepare DMA for code loader stream */ hext_stream = hda_cl_stream_prepare(sdev, HDA_CL_STREAM_FORMAT, stripped_firmware.size, - &dmab, SNDRV_PCM_STREAM_PLAYBACK); + &dmab, SNDRV_PCM_STREAM_PLAYBACK, false); if (IS_ERR(hext_stream)) { dev_err(sdev->dev, "%s: DMA prepare failed\n", __func__); return PTR_ERR(hext_stream); diff --git a/sound/soc/sof/intel/hda.h b/sound/soc/sof/intel/hda.h index 16140ae22c90..30a185d4c7ab 100644 --- a/sound/soc/sof/intel/hda.h +++ b/sound/soc/sof/intel/hda.h @@ -705,7 +705,7 @@ int hda_dsp_cl_boot_firmware_iccmax(struct snd_sof_dev *sdev); int hda_cl_copy_fw(struct snd_sof_dev *sdev, struct hdac_ext_stream *hext_stream); struct hdac_ext_stream *hda_cl_stream_prepare(struct snd_sof_dev *sdev, unsigned int format, unsigned int size, struct snd_dma_buffer *dmab, - int direction); + int direction, bool is_iccmax); int hda_cl_cleanup(struct snd_sof_dev *sdev, struct snd_dma_buffer *dmab, struct hdac_ext_stream *hext_stream); int cl_dsp_init(struct snd_sof_dev *sdev, int stream_tag, bool imr_boot); -- cgit v1.2.3 From 6cbf086143cf9674c7f029e1cf435c65a537066a Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Thu, 4 Apr 2024 13:54:46 -0500 Subject: ASoC: SOF: Intel: hda-loader: change signature of code loader helpers MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We need to reuse cl_prepare, cl_trigger and cl_cleanup helpers from a SoundWire context where only the device information is available. Rather than pass the 'sdev' argument, use get_drvdata() to retrieve the required structure. For consistency, rename hda_cl_stream_prepare() as hda_cl_prepare(). These three helpers are also exported so that they can be referenced from another module. Signed-off-by: Pierre-Louis Bossart Reviewed-by: Péter Ujfalusi Reviewed-by: Rander Wang Reviewed-by: Ranjani Sridharan Link: https://msgid.link/r/20240404185448.136157-3-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/intel/hda-loader.c | 50 ++++++++++++++++++++++------------------ sound/soc/sof/intel/hda.h | 11 +++++---- 2 files changed, 34 insertions(+), 27 deletions(-) diff --git a/sound/soc/sof/intel/hda-loader.c b/sound/soc/sof/intel/hda-loader.c index dafb6b3ebb20..5716772a7a91 100644 --- a/sound/soc/sof/intel/hda-loader.c +++ b/sound/soc/sof/intel/hda-loader.c @@ -44,13 +44,13 @@ static void hda_ssp_set_cbp_cfp(struct snd_sof_dev *sdev) } } -struct hdac_ext_stream *hda_cl_stream_prepare(struct snd_sof_dev *sdev, unsigned int format, - unsigned int size, struct snd_dma_buffer *dmab, - int direction, bool is_iccmax) +struct hdac_ext_stream *hda_cl_prepare(struct device *dev, unsigned int format, + unsigned int size, struct snd_dma_buffer *dmab, + int direction, bool is_iccmax) { + struct snd_sof_dev *sdev = dev_get_drvdata(dev); struct hdac_ext_stream *hext_stream; struct hdac_stream *hstream; - struct pci_dev *pci = to_pci_dev(sdev->dev); int ret; hext_stream = hda_dsp_stream_get(sdev, direction, 0); @@ -63,7 +63,7 @@ struct hdac_ext_stream *hda_cl_stream_prepare(struct snd_sof_dev *sdev, unsigned hstream->substream = NULL; /* allocate DMA buffer */ - ret = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV_SG, &pci->dev, size, dmab); + ret = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV_SG, dev, size, dmab); if (ret < 0) { dev_err(sdev->dev, "error: memory alloc failed: %d\n", ret); goto out_put; @@ -96,6 +96,7 @@ out_put: hda_dsp_stream_put(sdev, direction, hstream->stream_tag); return ERR_PTR(ret); } +EXPORT_SYMBOL_NS(hda_cl_prepare, SND_SOC_SOF_INTEL_HDA_COMMON); /* * first boot sequence has some extra steps. @@ -220,9 +221,9 @@ err: return ret; } -static int cl_trigger(struct snd_sof_dev *sdev, - struct hdac_ext_stream *hext_stream, int cmd) +int hda_cl_trigger(struct device *dev, struct hdac_ext_stream *hext_stream, int cmd) { + struct snd_sof_dev *sdev = dev_get_drvdata(dev); struct hdac_stream *hstream = &hext_stream->hstream; int sd_offset = SOF_STREAM_SD_OFFSET(hstream); @@ -246,10 +247,12 @@ static int cl_trigger(struct snd_sof_dev *sdev, return hda_dsp_stream_trigger(sdev, hext_stream, cmd); } } +EXPORT_SYMBOL_NS(hda_cl_trigger, SND_SOC_SOF_INTEL_HDA_COMMON); -int hda_cl_cleanup(struct snd_sof_dev *sdev, struct snd_dma_buffer *dmab, +int hda_cl_cleanup(struct device *dev, struct snd_dma_buffer *dmab, struct hdac_ext_stream *hext_stream) { + struct snd_sof_dev *sdev = dev_get_drvdata(dev); struct hdac_stream *hstream = &hext_stream->hstream; int sd_offset = SOF_STREAM_SD_OFFSET(hstream); int ret = 0; @@ -278,6 +281,7 @@ int hda_cl_cleanup(struct snd_sof_dev *sdev, struct snd_dma_buffer *dmab, return ret; } +EXPORT_SYMBOL_NS(hda_cl_cleanup, SND_SOC_SOF_INTEL_HDA_COMMON); int hda_cl_copy_fw(struct snd_sof_dev *sdev, struct hdac_ext_stream *hext_stream) { @@ -286,7 +290,7 @@ int hda_cl_copy_fw(struct snd_sof_dev *sdev, struct hdac_ext_stream *hext_stream unsigned int reg; int ret, status; - ret = cl_trigger(sdev, hext_stream, SNDRV_PCM_TRIGGER_START); + ret = hda_cl_trigger(sdev->dev, hext_stream, SNDRV_PCM_TRIGGER_START); if (ret < 0) { dev_err(sdev->dev, "error: DMA trigger start failed\n"); return ret; @@ -309,7 +313,7 @@ int hda_cl_copy_fw(struct snd_sof_dev *sdev, struct hdac_ext_stream *hext_stream __func__, chip->rom_status_reg); } - ret = cl_trigger(sdev, hext_stream, SNDRV_PCM_TRIGGER_STOP); + ret = hda_cl_trigger(sdev->dev, hext_stream, SNDRV_PCM_TRIGGER_STOP); if (ret < 0) { dev_err(sdev->dev, "error: DMA trigger stop failed\n"); if (!status) @@ -334,8 +338,8 @@ int hda_dsp_cl_boot_firmware_iccmax(struct snd_sof_dev *sdev) * Prepare capture stream for ICCMAX. We do not need to store * the data, so use a buffer of PAGE_SIZE for receiving. */ - iccmax_stream = hda_cl_stream_prepare(sdev, HDA_CL_STREAM_FORMAT, PAGE_SIZE, - &dmab_bdl, SNDRV_PCM_STREAM_CAPTURE, true); + iccmax_stream = hda_cl_prepare(sdev->dev, HDA_CL_STREAM_FORMAT, PAGE_SIZE, + &dmab_bdl, SNDRV_PCM_STREAM_CAPTURE, true); if (IS_ERR(iccmax_stream)) { dev_err(sdev->dev, "error: dma prepare for ICCMAX stream failed\n"); return PTR_ERR(iccmax_stream); @@ -347,7 +351,7 @@ int hda_dsp_cl_boot_firmware_iccmax(struct snd_sof_dev *sdev) * Perform iccmax stream cleanup. This should be done even if firmware loading fails. * If the cleanup also fails, we return the initial error */ - ret1 = hda_cl_cleanup(sdev, &dmab_bdl, iccmax_stream); + ret1 = hda_cl_cleanup(sdev->dev, &dmab_bdl, iccmax_stream); if (ret1 < 0) { dev_err(sdev->dev, "error: ICCMAX stream cleanup failed\n"); @@ -419,9 +423,9 @@ int hda_dsp_cl_boot_firmware(struct snd_sof_dev *sdev) init_waitqueue_head(&sdev->boot_wait); /* prepare DMA for code loader stream */ - hext_stream = hda_cl_stream_prepare(sdev, HDA_CL_STREAM_FORMAT, - stripped_firmware.size, - &dmab, SNDRV_PCM_STREAM_PLAYBACK, false); + hext_stream = hda_cl_prepare(sdev->dev, HDA_CL_STREAM_FORMAT, + stripped_firmware.size, + &dmab, SNDRV_PCM_STREAM_PLAYBACK, false); if (IS_ERR(hext_stream)) { dev_err(sdev->dev, "error: dma prepare for fw loading failed\n"); return PTR_ERR(hext_stream); @@ -494,7 +498,7 @@ cleanup: * This should be done even if firmware loading fails. * If the cleanup also fails, we return the initial error */ - ret1 = hda_cl_cleanup(sdev, &dmab, hext_stream); + ret1 = hda_cl_cleanup(sdev->dev, &dmab, hext_stream); if (ret1 < 0) { dev_err(sdev->dev, "error: Code loader DSP cleanup failed\n"); @@ -536,9 +540,9 @@ int hda_dsp_ipc4_load_library(struct snd_sof_dev *sdev, stripped_firmware.size = fw_lib->sof_fw.fw->size - fw_lib->sof_fw.payload_offset; /* prepare DMA for code loader stream */ - hext_stream = hda_cl_stream_prepare(sdev, HDA_CL_STREAM_FORMAT, - stripped_firmware.size, - &dmab, SNDRV_PCM_STREAM_PLAYBACK, false); + hext_stream = hda_cl_prepare(sdev->dev, HDA_CL_STREAM_FORMAT, + stripped_firmware.size, + &dmab, SNDRV_PCM_STREAM_PLAYBACK, false); if (IS_ERR(hext_stream)) { dev_err(sdev->dev, "%s: DMA prepare failed\n", __func__); return PTR_ERR(hext_stream); @@ -581,7 +585,7 @@ int hda_dsp_ipc4_load_library(struct snd_sof_dev *sdev, goto cleanup; } - ret = cl_trigger(sdev, hext_stream, SNDRV_PCM_TRIGGER_START); + ret = hda_cl_trigger(sdev->dev, hext_stream, SNDRV_PCM_TRIGGER_START); if (ret < 0) { dev_err(sdev->dev, "%s: DMA trigger start failed\n", __func__); goto cleanup; @@ -598,7 +602,7 @@ int hda_dsp_ipc4_load_library(struct snd_sof_dev *sdev, ret = sof_ipc_tx_message_no_reply(sdev->ipc, &msg, 0); /* Stop the DMA channel */ - ret1 = cl_trigger(sdev, hext_stream, SNDRV_PCM_TRIGGER_STOP); + ret1 = hda_cl_trigger(sdev->dev, hext_stream, SNDRV_PCM_TRIGGER_STOP); if (ret1 < 0) { dev_err(sdev->dev, "%s: DMA trigger stop failed\n", __func__); if (!ret) @@ -607,7 +611,7 @@ int hda_dsp_ipc4_load_library(struct snd_sof_dev *sdev, cleanup: /* clean up even in case of error and return the first error */ - ret1 = hda_cl_cleanup(sdev, &dmab, hext_stream); + ret1 = hda_cl_cleanup(sdev->dev, &dmab, hext_stream); if (ret1 < 0) { dev_err(sdev->dev, "%s: Code loader DSP cleanup failed\n", __func__); diff --git a/sound/soc/sof/intel/hda.h b/sound/soc/sof/intel/hda.h index 30a185d4c7ab..b4b037758fcb 100644 --- a/sound/soc/sof/intel/hda.h +++ b/sound/soc/sof/intel/hda.h @@ -703,10 +703,13 @@ void hda_dsp_get_state(struct snd_sof_dev *sdev, const char *level); int hda_dsp_cl_boot_firmware(struct snd_sof_dev *sdev); int hda_dsp_cl_boot_firmware_iccmax(struct snd_sof_dev *sdev); int hda_cl_copy_fw(struct snd_sof_dev *sdev, struct hdac_ext_stream *hext_stream); -struct hdac_ext_stream *hda_cl_stream_prepare(struct snd_sof_dev *sdev, unsigned int format, - unsigned int size, struct snd_dma_buffer *dmab, - int direction, bool is_iccmax); -int hda_cl_cleanup(struct snd_sof_dev *sdev, struct snd_dma_buffer *dmab, + +struct hdac_ext_stream *hda_cl_prepare(struct device *dev, unsigned int format, + unsigned int size, struct snd_dma_buffer *dmab, + int direction, bool is_iccmax); +int hda_cl_trigger(struct device *dev, struct hdac_ext_stream *hext_stream, int cmd); + +int hda_cl_cleanup(struct device *dev, struct snd_dma_buffer *dmab, struct hdac_ext_stream *hext_stream); int cl_dsp_init(struct snd_sof_dev *sdev, int stream_tag, bool imr_boot); #define HDA_CL_STREAM_FORMAT 0x40 -- cgit v1.2.3 From d5263dbbd8af026159b16a08a94bedfe51b5f67b Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Thu, 4 Apr 2024 13:54:47 -0500 Subject: ASoC: SOF: Intel: don't ignore IOC interrupts for non-audio transfers MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The HDaudio stream interrupts are ignored unless the stream is PCM or compressed audio. For alternate non-audio usages, such as code loader or SoundWire BPT case, the IOC interrupt on the last buffer transferred is silently ignored. This patch adds a 'struct completion' for each HDaudio stream. This capability helps detect if the non-audio data transfers completed. There is no performance impact for audio streams. In the code loader case, the code currently starts the DMA and directly checks if the firmware status changes, without checking if the DMA succeeded. With a first pass waiting for the DMA to complete, system validation engineers can gather more precise timing information on firmware boot time or root-cause boot failures more accurately. A timeout of 500ms was selected for the code loader DMA. This is an experimental value which should be more than enough - higher values would certainly be problematic from a usage/latency perspective. Signed-off-by: Pierre-Louis Bossart Reviewed-by: Péter Ujfalusi Reviewed-by: Rander Wang Reviewed-by: Ranjani Sridharan Link: https://msgid.link/r/20240404185448.136157-4-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/intel/hda-loader.c | 28 ++++++++++++++++++++++++++++ sound/soc/sof/intel/hda-stream.c | 22 +++++++++++++++++++--- sound/soc/sof/intel/hda.h | 2 ++ 3 files changed, 49 insertions(+), 3 deletions(-) diff --git a/sound/soc/sof/intel/hda-loader.c b/sound/soc/sof/intel/hda-loader.c index 5716772a7a91..dc88b7ea599e 100644 --- a/sound/soc/sof/intel/hda-loader.c +++ b/sound/soc/sof/intel/hda-loader.c @@ -226,10 +226,15 @@ int hda_cl_trigger(struct device *dev, struct hdac_ext_stream *hext_stream, int struct snd_sof_dev *sdev = dev_get_drvdata(dev); struct hdac_stream *hstream = &hext_stream->hstream; int sd_offset = SOF_STREAM_SD_OFFSET(hstream); + struct sof_intel_hda_stream *hda_stream; /* code loader is special case that reuses stream ops */ switch (cmd) { case SNDRV_PCM_TRIGGER_START: + hda_stream = container_of(hext_stream, struct sof_intel_hda_stream, + hext_stream); + reinit_completion(&hda_stream->ioc); + snd_sof_dsp_update_bits(sdev, HDA_DSP_HDA_BAR, SOF_HDA_INTCTL, 1 << hstream->index, 1 << hstream->index); @@ -283,19 +288,38 @@ int hda_cl_cleanup(struct device *dev, struct snd_dma_buffer *dmab, } EXPORT_SYMBOL_NS(hda_cl_cleanup, SND_SOC_SOF_INTEL_HDA_COMMON); +#define HDA_CL_DMA_IOC_TIMEOUT_MS 500 + int hda_cl_copy_fw(struct snd_sof_dev *sdev, struct hdac_ext_stream *hext_stream) { struct sof_intel_hda_dev *hda = sdev->pdata->hw_pdata; const struct sof_intel_dsp_desc *chip = hda->desc; + struct sof_intel_hda_stream *hda_stream; + unsigned long time_left; unsigned int reg; int ret, status; + hda_stream = container_of(hext_stream, struct sof_intel_hda_stream, + hext_stream); + + dev_dbg(sdev->dev, "Code loader DMA starting\n"); + ret = hda_cl_trigger(sdev->dev, hext_stream, SNDRV_PCM_TRIGGER_START); if (ret < 0) { dev_err(sdev->dev, "error: DMA trigger start failed\n"); return ret; } + /* Wait for completion of transfer */ + time_left = wait_for_completion_timeout(&hda_stream->ioc, + msecs_to_jiffies(HDA_CL_DMA_IOC_TIMEOUT_MS)); + + if (!time_left) { + dev_err(sdev->dev, "Code loader DMA did not complete\n"); + return -ETIMEDOUT; + } + dev_dbg(sdev->dev, "Code loader DMA done, waiting for FW_ENTERED status\n"); + status = snd_sof_dsp_read_poll_timeout(sdev, HDA_DSP_BAR, chip->rom_status_reg, reg, (FSR_TO_STATE_CODE(reg) == FSR_STATE_FW_ENTERED), @@ -311,6 +335,8 @@ int hda_cl_copy_fw(struct snd_sof_dev *sdev, struct hdac_ext_stream *hext_stream dev_err(sdev->dev, "%s: timeout with rom_status_reg (%#x) read\n", __func__, chip->rom_status_reg); + } else { + dev_dbg(sdev->dev, "Code loader FW_ENTERED status\n"); } ret = hda_cl_trigger(sdev->dev, hext_stream, SNDRV_PCM_TRIGGER_STOP); @@ -318,6 +344,8 @@ int hda_cl_copy_fw(struct snd_sof_dev *sdev, struct hdac_ext_stream *hext_stream dev_err(sdev->dev, "error: DMA trigger stop failed\n"); if (!status) status = ret; + } else { + dev_dbg(sdev->dev, "Code loader DMA stopped\n"); } return status; diff --git a/sound/soc/sof/intel/hda-stream.c b/sound/soc/sof/intel/hda-stream.c index 0c189d3b19c1..76c33795ade4 100644 --- a/sound/soc/sof/intel/hda-stream.c +++ b/sound/soc/sof/intel/hda-stream.c @@ -765,10 +765,25 @@ static bool hda_dsp_stream_check(struct hdac_bus *bus, u32 status) writeb(sd_status, s->sd_addr + SOF_HDA_ADSP_REG_SD_STS); active = true; - if ((!s->substream && !s->cstream) || - !s->running || - (sd_status & SOF_HDA_CL_DMA_SD_INT_COMPLETE) == 0) + if (!s->running) continue; + if ((sd_status & SOF_HDA_CL_DMA_SD_INT_COMPLETE) == 0) + continue; + if (!s->substream && !s->cstream) { + /* + * when no substream is found, the DMA may used for code loading + * or data transfers which can rely on wait_for_completion() + */ + struct sof_intel_hda_stream *hda_stream; + struct hdac_ext_stream *hext_stream; + + hext_stream = stream_to_hdac_ext_stream(s); + hda_stream = container_of(hext_stream, struct sof_intel_hda_stream, + hext_stream); + + complete(&hda_stream->ioc); + continue; + } /* Inform ALSA only in case not do that with IPC */ if (s->substream && sof_hda->no_ipc_position) { @@ -880,6 +895,7 @@ int hda_dsp_stream_init(struct snd_sof_dev *sdev) return -ENOMEM; hda_stream->sdev = sdev; + init_completion(&hda_stream->ioc); hext_stream = &hda_stream->hext_stream; diff --git a/sound/soc/sof/intel/hda.h b/sound/soc/sof/intel/hda.h index b4b037758fcb..b59d1a572bce 100644 --- a/sound/soc/sof/intel/hda.h +++ b/sound/soc/sof/intel/hda.h @@ -11,6 +11,7 @@ #ifndef __SOF_INTEL_HDA_H #define __SOF_INTEL_HDA_H +#include #include #include #include @@ -559,6 +560,7 @@ struct sof_intel_hda_stream { struct sof_intel_stream sof_intel_stream; int host_reserved; /* reserve host DMA channel */ u32 flags; + struct completion ioc; }; #define hstream_to_sof_hda_stream(hstream) \ -- cgit v1.2.3 From 716778b3d71fe1c799a4f5cf84faf4979f80b267 Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Thu, 4 Apr 2024 13:54:48 -0500 Subject: ASoC: SOF: Intel: hda-stream: clarify comment MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The Yoda grammar and multiple negatives are unclear. Signed-off-by: Pierre-Louis Bossart Reviewed-by: Péter Ujfalusi Reviewed-by: Rander Wang Reviewed-by: Ranjani Sridharan Link: https://msgid.link/r/20240404185448.136157-5-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/intel/hda-stream.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/sof/intel/hda-stream.c b/sound/soc/sof/intel/hda-stream.c index 76c33795ade4..91b1371745e6 100644 --- a/sound/soc/sof/intel/hda-stream.c +++ b/sound/soc/sof/intel/hda-stream.c @@ -785,7 +785,7 @@ static bool hda_dsp_stream_check(struct hdac_bus *bus, u32 status) continue; } - /* Inform ALSA only in case not do that with IPC */ + /* Inform ALSA only if the IPC position is not used */ if (s->substream && sof_hda->no_ipc_position) { snd_sof_pcm_period_elapsed(s->substream); } else if (s->cstream) { -- cgit v1.2.3 From bd5863f9ef12e26c2cfdce9c0adbf0222c731a3c Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Thu, 4 Apr 2024 14:03:54 -0500 Subject: ASoC: SOF: Intel: hda-ctrl: add missing WAKE_STS clear MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit For some reason, the programming sequences in the SOF driver do not include a clear of the WAKE_STS bits before resetting the controller. This clear is not formally required by the HDaudio specification, but was added to harden the snd-hda-reset back in 2007. Adding this sequence back avoids an issue reported by the Intel CI. Closes: https://github.com/thesofproject/linux/issues/4889 Reviewed-by: Péter Ujfalusi Reviewed-by: Bard Liao Signed-off-by: Pierre-Louis Bossart Link: https://msgid.link/r/20240404190357.138073-2-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/intel/hda-ctrl.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/sound/soc/sof/intel/hda-ctrl.c b/sound/soc/sof/intel/hda-ctrl.c index 84bf01bd360a..b4f0756e21f6 100644 --- a/sound/soc/sof/intel/hda-ctrl.c +++ b/sound/soc/sof/intel/hda-ctrl.c @@ -184,6 +184,7 @@ int hda_dsp_ctrl_init_chip(struct snd_sof_dev *sdev) struct hdac_bus *bus = sof_to_bus(sdev); struct hdac_stream *stream; int sd_offset, ret = 0; + u32 gctl; if (bus->chip_init) return 0; @@ -192,6 +193,12 @@ int hda_dsp_ctrl_init_chip(struct snd_sof_dev *sdev) hda_dsp_ctrl_misc_clock_gating(sdev, false); + /* clear WAKE_STS if not in reset */ + gctl = snd_sof_dsp_read(sdev, HDA_DSP_HDA_BAR, SOF_HDA_GCTL); + if (gctl & SOF_HDA_GCTL_RESET) + snd_sof_dsp_write(sdev, HDA_DSP_HDA_BAR, + SOF_HDA_WAKESTS, SOF_HDA_WAKESTS_INT_MASK); + /* reset HDA controller */ ret = hda_dsp_ctrl_link_reset(sdev, true); if (ret < 0) { -- cgit v1.2.3 From ab9182441ee5a94dd6f47743ed1b7b6b07b63cb2 Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Thu, 4 Apr 2024 14:03:55 -0500 Subject: ASoC: SOF: Intel: lnl: add helper to detect SoundWire wakes The global STATESTS register will provide information on all links. Rather than iterate on all possible links, the helpers only filters the range of possible bits for a quick lookup. The process_wakeen() helper will walk through all the links and deal with wakes. Signed-off-by: Pierre-Louis Bossart Reviewed-by: Bard Liao Reviewed-by: Rander Wang Link: https://msgid.link/r/20240404190357.138073-3-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/intel/lnl.c | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/sound/soc/sof/intel/lnl.c b/sound/soc/sof/intel/lnl.c index 8e7193344341..8aa5430e9576 100644 --- a/sound/soc/sof/intel/lnl.c +++ b/sound/soc/sof/intel/lnl.c @@ -189,6 +189,23 @@ static int lnl_dsp_disable_interrupts(struct snd_sof_dev *sdev) return mtl_enable_interrupts(sdev, false); } +static bool lnl_sdw_check_wakeen_irq(struct snd_sof_dev *sdev) +{ + struct hdac_bus *bus = sof_to_bus(sdev); + u16 wake_sts; + + /* + * we need to use the global HDaudio WAKEEN/STS to be able to + * detect wakes in low-power modes. The link-specific information + * is handled in the process_wakeen() helper, this helper only + * detects a SoundWire wake without identifying the link. + */ + wake_sts = snd_hdac_chip_readw(bus, STATESTS); + + /* filter out the range of SDIs that can be set for SoundWire */ + return wake_sts & GENMASK(SDW_MAX_DEVICES, SDW_INTEL_DEV_NUM_IDA_MIN); +} + const struct sof_intel_dsp_desc lnl_chip_info = { .cores_num = 5, .init_core_mask = BIT(0), @@ -205,6 +222,7 @@ const struct sof_intel_dsp_desc lnl_chip_info = { .read_sdw_lcount = hda_sdw_check_lcount_ext, .enable_sdw_irq = lnl_enable_sdw_irq, .check_sdw_irq = lnl_dsp_check_sdw_irq, + .check_sdw_wakeen_irq = lnl_sdw_check_wakeen_irq, .check_ipc_irq = mtl_dsp_check_ipc_irq, .cl_init = mtl_dsp_cl_init, .power_down_dsp = mtl_power_down_dsp, -- cgit v1.2.3 From b69480edf4eb71c6f754e3c4020e8dd72a330558 Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Thu, 4 Apr 2024 14:03:56 -0500 Subject: ASoC: SOF: Intel: hda-codec: preserve WAKEEN values Since LunarLake, we use the HDadio WAKEEN/WAKESTS to detect wakes for SoundWire codecs. Unfortunately, the existing code in hda_codec_jack_wake_enable() unconditionally resets the WAKEEN bits. This patch changes the initialization to preserve SoundWire WAKEEN bits. For HDAudio codecs the same strategy is used, WAKEEN is only set when the jacktbl.used property is set. Closes: https://github.com/thesofproject/linux/issues/4687 Co-developed-by: Bard Liao Signed-off-by: Bard Liao Signed-off-by: Pierre-Louis Bossart Reviewed-by: Keqiao Zhang Reviewed-by: Bard Liao Link: https://msgid.link/r/20240404190357.138073-4-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/intel/hda-codec.c | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/sound/soc/sof/intel/hda-codec.c b/sound/soc/sof/intel/hda-codec.c index 9f84b0d287a5..6a13f38a8d21 100644 --- a/sound/soc/sof/intel/hda-codec.c +++ b/sound/soc/sof/intel/hda-codec.c @@ -79,18 +79,27 @@ void hda_codec_jack_wake_enable(struct snd_sof_dev *sdev, bool enable) struct hdac_bus *bus = sof_to_bus(sdev); struct hda_codec *codec; unsigned int mask = 0; + unsigned int val = 0; if (IS_ENABLED(CONFIG_SND_SOC_SOF_NOCODEC_DEBUG_SUPPORT) && sof_debug_check_flag(SOF_DBG_FORCE_NOCODEC)) return; if (enable) { - list_for_each_codec(codec, hbus) + list_for_each_codec(codec, hbus) { + /* only set WAKEEN when needed for HDaudio codecs */ + mask |= BIT(codec->core.addr); if (codec->jacktbl.used) - mask |= BIT(codec->core.addr); + val |= BIT(codec->core.addr); + } + } else { + list_for_each_codec(codec, hbus) { + /* reset WAKEEN only HDaudio codecs */ + mask |= BIT(codec->core.addr); + } } - snd_hdac_chip_updatew(bus, WAKEEN, STATESTS_INT_MASK, mask); + snd_hdac_chip_updatew(bus, WAKEEN, mask & STATESTS_INT_MASK, val); } EXPORT_SYMBOL_NS_GPL(hda_codec_jack_wake_enable, SND_SOC_SOF_HDA_AUDIO_CODEC); -- cgit v1.2.3 From 35b5806e2edee1741f6bd2de2a5c149a876c4a60 Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Thu, 4 Apr 2024 14:03:57 -0500 Subject: ASoC: SOF: Intel: hda-ctrl: only clear WAKESTS for HDaudio codecs When a PME wake happens due to a SoundWire wake, we currently clear all WAKESTS bits during the resume operation initiated by the PCI subsystem. As a result, we are unable to identify which SoundWire links need to be resumed and don't properly handle jack detection. This patch only clears the WAKESTS bits for the HDaudio codecs detected earlier. Note that we still clear all WAKESTS bits unconditionally in hda_dsp_ctrl_stop_chip(). The existing behavior is potentially racy if e.g. a jack event happens during a suspend routine, but there's a risk of breaking shutdown or reboot sequences so the code is left as is for now. Closes: https://github.com/thesofproject/linux/issues/4687 Co-developed-by: Bard Liao Signed-off-by: Bard Liao Signed-off-by: Pierre-Louis Bossart Reviewed-by: Keqiao Zhang Reviewed-by: Bard Liao Link: https://msgid.link/r/20240404190357.138073-5-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/intel/hda-ctrl.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/sof/intel/hda-ctrl.c b/sound/soc/sof/intel/hda-ctrl.c index b4f0756e21f6..6d941209847f 100644 --- a/sound/soc/sof/intel/hda-ctrl.c +++ b/sound/soc/sof/intel/hda-ctrl.c @@ -228,7 +228,7 @@ int hda_dsp_ctrl_init_chip(struct snd_sof_dev *sdev) /* clear WAKESTS */ snd_sof_dsp_write(sdev, HDA_DSP_HDA_BAR, SOF_HDA_WAKESTS, - SOF_HDA_WAKESTS_INT_MASK); + bus->codec_mask); hda_codec_rirb_status_clear(sdev); -- cgit v1.2.3 From 01e5f4fc0fead3ef19000e1d2fc748e87aac3f02 Mon Sep 17 00:00:00 2001 From: Kent Overstreet Date: Thu, 4 Apr 2024 15:50:26 -0400 Subject: bcachefs: Make snapshot_is_ancestor() safe Snapshot table accesses generally need to be checking for invalid snapshot ID now, fix one that was missed. Signed-off-by: Kent Overstreet --- fs/bcachefs/snapshot.c | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/fs/bcachefs/snapshot.c b/fs/bcachefs/snapshot.c index 0e806f04f3d7..544322d5c251 100644 --- a/fs/bcachefs/snapshot.c +++ b/fs/bcachefs/snapshot.c @@ -125,6 +125,15 @@ static inline u32 get_ancestor_below(struct snapshot_table *t, u32 id, u32 ances return s->parent; } +static bool test_ancestor_bitmap(struct snapshot_table *t, u32 id, u32 ancestor) +{ + const struct snapshot_t *s = __snapshot_t(t, id); + if (!s) + return false; + + return test_bit(ancestor - id - 1, s->is_ancestor); +} + bool __bch2_snapshot_is_ancestor(struct bch_fs *c, u32 id, u32 ancestor) { bool ret; @@ -140,13 +149,11 @@ bool __bch2_snapshot_is_ancestor(struct bch_fs *c, u32 id, u32 ancestor) while (id && id < ancestor - IS_ANCESTOR_BITMAP) id = get_ancestor_below(t, id, ancestor); - if (id && id < ancestor) { - ret = test_bit(ancestor - id - 1, __snapshot_t(t, id)->is_ancestor); + ret = id && id < ancestor + ? test_ancestor_bitmap(t, id, ancestor) + : id == ancestor; - EBUG_ON(ret != __bch2_snapshot_is_ancestor_early(t, id, ancestor)); - } else { - ret = id == ancestor; - } + EBUG_ON(ret != __bch2_snapshot_is_ancestor_early(t, id, ancestor)); out: rcu_read_unlock(); -- cgit v1.2.3 From be42e4a621fee05e3299169fbb1068b473e779c2 Mon Sep 17 00:00:00 2001 From: Kent Overstreet Date: Thu, 4 Apr 2024 16:51:40 -0400 Subject: bcachefs: Bump limit in btree_trans_too_many_iters() Signed-off-by: Kent Overstreet --- fs/bcachefs/btree_iter.h | 2 +- fs/bcachefs/btree_types.h | 14 ++++++++++++++ 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/fs/bcachefs/btree_iter.h b/fs/bcachefs/btree_iter.h index 24772538e4cc..1d58d447b386 100644 --- a/fs/bcachefs/btree_iter.h +++ b/fs/bcachefs/btree_iter.h @@ -642,7 +642,7 @@ int __bch2_btree_trans_too_many_iters(struct btree_trans *); static inline int btree_trans_too_many_iters(struct btree_trans *trans) { - if (bitmap_weight(trans->paths_allocated, trans->nr_paths) > BTREE_ITER_INITIAL - 8) + if (bitmap_weight(trans->paths_allocated, trans->nr_paths) > BTREE_ITER_NORMAL_LIMIT - 8) return __bch2_btree_trans_too_many_iters(trans); return 0; diff --git a/fs/bcachefs/btree_types.h b/fs/bcachefs/btree_types.h index 9404d96c38f3..e0c982a4195c 100644 --- a/fs/bcachefs/btree_types.h +++ b/fs/bcachefs/btree_types.h @@ -364,7 +364,21 @@ struct btree_insert_entry { unsigned long ip_allocated; }; +/* Number of btree paths we preallocate, usually enough */ #define BTREE_ITER_INITIAL 64 +/* + * Lmiit for btree_trans_too_many_iters(); this is enough that almost all code + * paths should run inside this limit, and if they don't it usually indicates a + * bug (leaking/duplicated btree paths). + * + * exception: some fsck paths + * + * bugs with excessive path usage seem to have possibly been eliminated now, so + * we might consider eliminating this (and btree_trans_too_many_iter()) at some + * point. + */ +#define BTREE_ITER_NORMAL_LIMIT 256 +/* never exceed limit */ #define BTREE_ITER_MAX (1U << 10) struct btree_trans_commit_hook; -- cgit v1.2.3 From 9fb3036fe3d9414ae32a97d01d7ccf7550e168a7 Mon Sep 17 00:00:00 2001 From: Kent Overstreet Date: Wed, 3 Apr 2024 19:15:53 -0400 Subject: bcachefs: Move btree_updates to debugfs sysfs is limited to PAGE_SIZE, and when we're debugging strange deadlocks/priority inversions we need to see the full list. Signed-off-by: Kent Overstreet --- fs/bcachefs/debug.c | 45 ++++++++++++++++++++++++++++++++++++++++++--- fs/bcachefs/sysfs.c | 6 ------ 2 files changed, 42 insertions(+), 9 deletions(-) diff --git a/fs/bcachefs/debug.c b/fs/bcachefs/debug.c index 7b681ae91510..cd99b7399414 100644 --- a/fs/bcachefs/debug.c +++ b/fs/bcachefs/debug.c @@ -13,6 +13,7 @@ #include "btree_iter.h" #include "btree_locking.h" #include "btree_update.h" +#include "btree_update_interior.h" #include "buckets.h" #include "debug.h" #include "error.h" @@ -668,7 +669,7 @@ static ssize_t bch2_journal_pins_read(struct file *file, char __user *buf, i->size = size; i->ret = 0; - do { + while (1) { err = flush_buf(i); if (err) return err; @@ -676,9 +677,12 @@ static ssize_t bch2_journal_pins_read(struct file *file, char __user *buf, if (!i->size) break; + if (done) + break; + done = bch2_journal_seq_pins_to_text(&i->buf, &c->journal, &i->iter); i->iter++; - } while (!done); + } if (i->buf.allocation_failure) return -ENOMEM; @@ -693,13 +697,45 @@ static const struct file_operations journal_pins_ops = { .read = bch2_journal_pins_read, }; +static ssize_t bch2_btree_updates_read(struct file *file, char __user *buf, + size_t size, loff_t *ppos) +{ + struct dump_iter *i = file->private_data; + struct bch_fs *c = i->c; + int err; + + i->ubuf = buf; + i->size = size; + i->ret = 0; + + if (!i->iter) { + bch2_btree_updates_to_text(&i->buf, c); + i->iter++; + } + + err = flush_buf(i); + if (err) + return err; + + if (i->buf.allocation_failure) + return -ENOMEM; + + return i->ret; +} + +static const struct file_operations btree_updates_ops = { + .owner = THIS_MODULE, + .open = bch2_dump_open, + .release = bch2_dump_release, + .read = bch2_btree_updates_read, +}; + static int btree_transaction_stats_open(struct inode *inode, struct file *file) { struct bch_fs *c = inode->i_private; struct dump_iter *i; i = kzalloc(sizeof(struct dump_iter), GFP_KERNEL); - if (!i) return -ENOMEM; @@ -902,6 +938,9 @@ void bch2_fs_debug_init(struct bch_fs *c) debugfs_create_file("journal_pins", 0400, c->fs_debug_dir, c->btree_debug, &journal_pins_ops); + debugfs_create_file("btree_updates", 0400, c->fs_debug_dir, + c->btree_debug, &btree_updates_ops); + debugfs_create_file("btree_transaction_stats", 0400, c->fs_debug_dir, c, &btree_transaction_stats_op); diff --git a/fs/bcachefs/sysfs.c b/fs/bcachefs/sysfs.c index c86a93a8d8fc..b18b0cc81b59 100644 --- a/fs/bcachefs/sysfs.c +++ b/fs/bcachefs/sysfs.c @@ -17,7 +17,6 @@ #include "btree_iter.h" #include "btree_key_cache.h" #include "btree_update.h" -#include "btree_update_interior.h" #include "btree_gc.h" #include "buckets.h" #include "clock.h" @@ -166,7 +165,6 @@ read_attribute(btree_write_stats); read_attribute(btree_cache_size); read_attribute(compression_stats); read_attribute(journal_debug); -read_attribute(btree_updates); read_attribute(btree_cache); read_attribute(btree_key_cache); read_attribute(stripes_heap); @@ -415,9 +413,6 @@ SHOW(bch2_fs) if (attr == &sysfs_journal_debug) bch2_journal_debug_to_text(out, &c->journal); - if (attr == &sysfs_btree_updates) - bch2_btree_updates_to_text(out, c); - if (attr == &sysfs_btree_cache) bch2_btree_cache_to_text(out, c); @@ -639,7 +634,6 @@ SYSFS_OPS(bch2_fs_internal); struct attribute *bch2_fs_internal_files[] = { &sysfs_flags, &sysfs_journal_debug, - &sysfs_btree_updates, &sysfs_btree_cache, &sysfs_btree_key_cache, &sysfs_new_stripes, -- cgit v1.2.3 From d880a43836d5e2ba951b10471104cdacc2eefbed Mon Sep 17 00:00:00 2001 From: Kent Overstreet Date: Wed, 3 Apr 2024 19:52:10 -0400 Subject: bcachefs: Further improve btree_update_to_text() Print start and end level of the btree update; also a bit of cleanup. Signed-off-by: Kent Overstreet --- fs/bcachefs/btree_update_interior.c | 100 +++++++++++++++++------------------- fs/bcachefs/btree_update_interior.h | 3 +- 2 files changed, 48 insertions(+), 55 deletions(-) diff --git a/fs/bcachefs/btree_update_interior.c b/fs/bcachefs/btree_update_interior.c index 32397b99752f..24fbd5be70a2 100644 --- a/fs/bcachefs/btree_update_interior.c +++ b/fs/bcachefs/btree_update_interior.c @@ -26,9 +26,9 @@ #include -const char * const bch2_btree_update_modes[] = { +static const char * const bch2_btree_update_modes[] = { #define x(t) #t, - BCH_WATERMARKS() + BTREE_UPDATE_MODES() #undef x NULL }; @@ -850,15 +850,17 @@ static void btree_update_updated_node(struct btree_update *as, struct btree *b) { struct bch_fs *c = as->c; - mutex_lock(&c->btree_interior_update_lock); - list_add_tail(&as->unwritten_list, &c->btree_interior_updates_unwritten); - BUG_ON(as->mode != BTREE_UPDATE_none); + BUG_ON(as->update_level_end < b->c.level); BUG_ON(!btree_node_dirty(b)); BUG_ON(!b->c.level); + mutex_lock(&c->btree_interior_update_lock); + list_add_tail(&as->unwritten_list, &c->btree_interior_updates_unwritten); + as->mode = BTREE_UPDATE_node; as->b = b; + as->update_level_end = b->c.level; set_btree_node_write_blocked(b); list_add(&as->write_blocked_list, &b->write_blocked); @@ -1100,7 +1102,7 @@ static void bch2_btree_update_done(struct btree_update *as, struct btree_trans * static struct btree_update * bch2_btree_update_start(struct btree_trans *trans, struct btree_path *path, - unsigned level, bool split, unsigned flags) + unsigned level_start, bool split, unsigned flags) { struct bch_fs *c = trans->c; struct btree_update *as; @@ -1108,7 +1110,7 @@ bch2_btree_update_start(struct btree_trans *trans, struct btree_path *path, int disk_res_flags = (flags & BCH_TRANS_COMMIT_no_enospc) ? BCH_DISK_RESERVATION_NOFAIL : 0; unsigned nr_nodes[2] = { 0, 0 }; - unsigned update_level = level; + unsigned level_end = level_start; enum bch_watermark watermark = flags & BCH_WATERMARK_MASK; int ret = 0; u32 restart_count = trans->restart_count; @@ -1140,17 +1142,17 @@ bch2_btree_update_start(struct btree_trans *trans, struct btree_path *path, } while (1) { - nr_nodes[!!update_level] += 1 + split; - update_level++; + nr_nodes[!!level_end] += 1 + split; + level_end++; - ret = bch2_btree_path_upgrade(trans, path, update_level + 1); + ret = bch2_btree_path_upgrade(trans, path, level_end + 1); if (ret) return ERR_PTR(ret); - if (!btree_path_node(path, update_level)) { + if (!btree_path_node(path, level_end)) { /* Allocating new root? */ nr_nodes[1] += split; - update_level = BTREE_MAX_DEPTH; + level_end = BTREE_MAX_DEPTH; break; } @@ -1158,11 +1160,11 @@ bch2_btree_update_start(struct btree_trans *trans, struct btree_path *path, * Always check for space for two keys, even if we won't have to * split at prior level - it might have been a merge instead: */ - if (bch2_btree_node_insert_fits(path->l[update_level].b, + if (bch2_btree_node_insert_fits(path->l[level_end].b, BKEY_BTREE_PTR_U64s_MAX * 2)) break; - split = path->l[update_level].b->nr.live_u64s > BTREE_SPLIT_THRESHOLD(c); + split = path->l[level_end].b->nr.live_u64s > BTREE_SPLIT_THRESHOLD(c); } if (!down_read_trylock(&c->gc_lock)) { @@ -1176,14 +1178,15 @@ bch2_btree_update_start(struct btree_trans *trans, struct btree_path *path, as = mempool_alloc(&c->btree_interior_update_pool, GFP_NOFS); memset(as, 0, sizeof(*as)); closure_init(&as->cl, NULL); - as->c = c; - as->start_time = start_time; - as->ip_started = _RET_IP_; - as->mode = BTREE_UPDATE_none; - as->watermark = watermark; - as->took_gc_lock = true; - as->btree_id = path->btree_id; - as->update_level = update_level; + as->c = c; + as->start_time = start_time; + as->ip_started = _RET_IP_; + as->mode = BTREE_UPDATE_none; + as->watermark = watermark; + as->took_gc_lock = true; + as->btree_id = path->btree_id; + as->update_level_start = level_start; + as->update_level_end = level_end; INIT_LIST_HEAD(&as->list); INIT_LIST_HEAD(&as->unwritten_list); INIT_LIST_HEAD(&as->write_blocked_list); @@ -1373,12 +1376,12 @@ static void bch2_insert_fixup_btree_ptr(struct btree_update *as, } static void -__bch2_btree_insert_keys_interior(struct btree_update *as, - struct btree_trans *trans, - struct btree_path *path, - struct btree *b, - struct btree_node_iter node_iter, - struct keylist *keys) +bch2_btree_insert_keys_interior(struct btree_update *as, + struct btree_trans *trans, + struct btree_path *path, + struct btree *b, + struct btree_node_iter node_iter, + struct keylist *keys) { struct bkey_i *insert = bch2_keylist_front(keys); struct bkey_packed *k; @@ -1534,7 +1537,7 @@ static void btree_split_insert_keys(struct btree_update *as, bch2_btree_node_iter_init(&node_iter, b, &bch2_keylist_front(keys)->k.p); - __bch2_btree_insert_keys_interior(as, trans, path, b, node_iter, keys); + bch2_btree_insert_keys_interior(as, trans, path, b, node_iter, keys); BUG_ON(bch2_btree_node_check_topology(trans, b)); } @@ -1714,27 +1717,6 @@ err: goto out; } -static void -bch2_btree_insert_keys_interior(struct btree_update *as, - struct btree_trans *trans, - struct btree_path *path, - struct btree *b, - struct keylist *keys) -{ - struct btree_path *linked; - unsigned i; - - __bch2_btree_insert_keys_interior(as, trans, path, b, - path->l[b->c.level].iter, keys); - - btree_update_updated_node(as, b); - - trans_for_each_path_with_node(trans, b, linked, i) - bch2_btree_node_iter_peek(&linked->l[b->c.level].iter, b); - - bch2_trans_verify_paths(trans); -} - /** * bch2_btree_insert_node - insert bkeys into a given btree node * @@ -1755,7 +1737,8 @@ static int bch2_btree_insert_node(struct btree_update *as, struct btree_trans *t struct keylist *keys) { struct bch_fs *c = as->c; - struct btree_path *path = trans->paths + path_idx; + struct btree_path *path = trans->paths + path_idx, *linked; + unsigned i; int old_u64s = le16_to_cpu(btree_bset_last(b)->u64s); int old_live_u64s = b->nr.live_u64s; int live_u64s_added, u64s_added; @@ -1784,7 +1767,13 @@ static int bch2_btree_insert_node(struct btree_update *as, struct btree_trans *t return ret; } - bch2_btree_insert_keys_interior(as, trans, path, b, keys); + bch2_btree_insert_keys_interior(as, trans, path, b, + path->l[b->c.level].iter, keys); + + trans_for_each_path_with_node(trans, b, linked, i) + bch2_btree_node_iter_peek(&linked->l[b->c.level].iter, b); + + bch2_trans_verify_paths(trans); live_u64s_added = (int) b->nr.live_u64s - old_live_u64s; u64s_added = (int) le16_to_cpu(btree_bset_last(b)->u64s) - old_u64s; @@ -1798,6 +1787,7 @@ static int bch2_btree_insert_node(struct btree_update *as, struct btree_trans *t bch2_maybe_compact_whiteouts(c, b)) bch2_trans_node_reinit_iter(trans, b); + btree_update_updated_node(as, b); bch2_btree_node_unlock_write(trans, path, b); BUG_ON(bch2_btree_node_check_topology(trans, b)); @@ -1807,7 +1797,7 @@ split: * We could attempt to avoid the transaction restart, by calling * bch2_btree_path_upgrade() and allocating more nodes: */ - if (b->c.level >= as->update_level) { + if (b->c.level >= as->update_level_end) { trace_and_count(c, trans_restart_split_race, trans, _THIS_IP_, b); return btree_trans_restart(trans, BCH_ERR_transaction_restart_split_race); } @@ -2519,9 +2509,11 @@ void bch2_btree_root_alloc_fake(struct bch_fs *c, enum btree_id id, unsigned lev static void bch2_btree_update_to_text(struct printbuf *out, struct btree_update *as) { - prt_printf(out, "%ps: btree=%s watermark=%s mode=%s nodes_written=%u cl.remaining=%u journal_seq=%llu\n", + prt_printf(out, "%ps: btree=%s l=%u-%u watermark=%s mode=%s nodes_written=%u cl.remaining=%u journal_seq=%llu\n", (void *) as->ip_started, bch2_btree_id_str(as->btree_id), + as->update_level_start, + as->update_level_end, bch2_watermarks[as->watermark], bch2_btree_update_modes[as->mode], as->nodes_written, diff --git a/fs/bcachefs/btree_update_interior.h b/fs/bcachefs/btree_update_interior.h index 88dcf5a22a3b..c1a479ebaad1 100644 --- a/fs/bcachefs/btree_update_interior.h +++ b/fs/bcachefs/btree_update_interior.h @@ -57,7 +57,8 @@ struct btree_update { unsigned took_gc_lock:1; enum btree_id btree_id; - unsigned update_level; + unsigned update_level_start; + unsigned update_level_end; struct disk_reservation disk_res; -- cgit v1.2.3 From 9802ff48f3fd8ae5d6699c5a32afc76769920c98 Mon Sep 17 00:00:00 2001 From: Kent Overstreet Date: Tue, 20 Feb 2024 21:08:24 -0500 Subject: bcachefs: Print shutdown journal sequence number Signed-off-by: Kent Overstreet --- fs/bcachefs/super.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/fs/bcachefs/super.c b/fs/bcachefs/super.c index ed63018f21be..8daf80a38d60 100644 --- a/fs/bcachefs/super.c +++ b/fs/bcachefs/super.c @@ -288,8 +288,13 @@ static void __bch2_fs_read_only(struct bch_fs *c) if (test_bit(JOURNAL_REPLAY_DONE, &c->journal.flags) && !test_bit(BCH_FS_emergency_ro, &c->flags)) set_bit(BCH_FS_clean_shutdown, &c->flags); + bch2_fs_journal_stop(&c->journal); + bch_info(c, "%sshutdown complete, journal seq %llu", + test_bit(BCH_FS_clean_shutdown, &c->flags) ? "" : "un", + c->journal.seq_ondisk); + /* * After stopping journal: */ -- cgit v1.2.3 From d4e655c49f474deffaf5ed7e65034b8167ee39c8 Mon Sep 17 00:00:00 2001 From: Alexander Wetzel Date: Mon, 1 Apr 2024 21:10:38 +0200 Subject: scsi: sg: Avoid race in error handling & drop bogus warn Commit 27f58c04a8f4 ("scsi: sg: Avoid sg device teardown race") introduced an incorrect WARN_ON_ONCE() and missed a sequence where sg_device_destroy() was used after scsi_device_put(). sg_device_destroy() is accessing the parent scsi_device request_queue which will already be set to NULL when the preceding call to scsi_device_put() removed the last reference to the parent scsi_device. Drop the incorrect WARN_ON_ONCE() - allowing more than one concurrent access to the sg device - and make sure sg_device_destroy() is not used after scsi_device_put() in the error handling. Link: https://lore.kernel.org/all/5375B275-D137-4D5F-BE25-6AF8ACAE41EF@linux.ibm.com Fixes: 27f58c04a8f4 ("scsi: sg: Avoid sg device teardown race") Cc: stable@vger.kernel.org Signed-off-by: Alexander Wetzel Link: https://lore.kernel.org/r/20240401191038.18359-1-Alexander@wetzel-home.de Tested-by: Sachin Sant Reviewed-by: Bart Van Assche Signed-off-by: Martin K. Petersen --- drivers/scsi/sg.c | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c index 386981c6976a..baf870a03ecf 100644 --- a/drivers/scsi/sg.c +++ b/drivers/scsi/sg.c @@ -285,6 +285,7 @@ sg_open(struct inode *inode, struct file *filp) int dev = iminor(inode); int flags = filp->f_flags; struct request_queue *q; + struct scsi_device *device; Sg_device *sdp; Sg_fd *sfp; int retval; @@ -301,11 +302,12 @@ sg_open(struct inode *inode, struct file *filp) /* This driver's module count bumped by fops_get in */ /* Prevent the device driver from vanishing while we sleep */ - retval = scsi_device_get(sdp->device); + device = sdp->device; + retval = scsi_device_get(device); if (retval) goto sg_put; - retval = scsi_autopm_get_device(sdp->device); + retval = scsi_autopm_get_device(device); if (retval) goto sdp_put; @@ -313,7 +315,7 @@ sg_open(struct inode *inode, struct file *filp) * check if O_NONBLOCK. Permits SCSI commands to be issued * during error recovery. Tread carefully. */ if (!((flags & O_NONBLOCK) || - scsi_block_when_processing_errors(sdp->device))) { + scsi_block_when_processing_errors(device))) { retval = -ENXIO; /* we are in error recovery for this device */ goto error_out; @@ -344,7 +346,7 @@ sg_open(struct inode *inode, struct file *filp) if (sdp->open_cnt < 1) { /* no existing opens */ sdp->sgdebug = 0; - q = sdp->device->request_queue; + q = device->request_queue; sdp->sg_tablesize = queue_max_segments(q); } sfp = sg_add_sfp(sdp); @@ -370,10 +372,11 @@ out_undo: error_mutex_locked: mutex_unlock(&sdp->open_rel_lock); error_out: - scsi_autopm_put_device(sdp->device); + scsi_autopm_put_device(device); sdp_put: - scsi_device_put(sdp->device); - goto sg_put; + kref_put(&sdp->d_ref, sg_device_destroy); + scsi_device_put(device); + return retval; } /* Release resources associated with a successful sg_open() @@ -2233,7 +2236,6 @@ sg_remove_sfp_usercontext(struct work_struct *work) "sg_remove_sfp: sfp=0x%p\n", sfp)); kfree(sfp); - WARN_ON_ONCE(kref_read(&sdp->d_ref) != 1); kref_put(&sdp->d_ref, sg_device_destroy); scsi_device_put(device); module_put(THIS_MODULE); -- cgit v1.2.3 From d464dac47260a33add5a206fd3289ec1216e8435 Mon Sep 17 00:00:00 2001 From: Uwe Kleine-König Date: Fri, 5 Apr 2024 07:58:10 +0200 Subject: usb: gadget: fsl: Initialize udc before using it MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit fsl_ep_queue() is only called by usb_ep_queue() (as ep->ops->queue()). So _ep isn't NULL. As ep->ops->queue = fsl_ep_queue, the ep was initialized by struct_ep_setup() and so ep->udc isn't NULL either. Drop the check for _ep being NULL and assign udc earlier to prevent following an uninitialized pointer in the two dev_vdbg()s in lines 878 and 882. This fixes a compiler warning when using clang and CONFIG_USB_GADGET_VERBOSE=y. Reported-by: kernel test robot Closes: https://lore.kernel.org/oe-kbuild-all/202404050227.TTvcCPBu-lkp@intel.com/ Fixes: 6025f20f16c2 ("usb: gadget: fsl-udc: Replace custom log wrappers by dev_{err,warn,dbg,vdbg}") Signed-off-by: Uwe Kleine-König Link: https://lore.kernel.org/r/20240405055812.694123-2-u.kleine-koenig@pengutronix.de Signed-off-by: Greg Kroah-Hartman --- drivers/usb/gadget/udc/fsl_udc_core.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/drivers/usb/gadget/udc/fsl_udc_core.c b/drivers/usb/gadget/udc/fsl_udc_core.c index e82d03224f94..3432ebfae978 100644 --- a/drivers/usb/gadget/udc/fsl_udc_core.c +++ b/drivers/usb/gadget/udc/fsl_udc_core.c @@ -868,7 +868,7 @@ fsl_ep_queue(struct usb_ep *_ep, struct usb_request *_req, gfp_t gfp_flags) { struct fsl_ep *ep = container_of(_ep, struct fsl_ep, ep); struct fsl_req *req = container_of(_req, struct fsl_req, req); - struct fsl_udc *udc; + struct fsl_udc *udc = ep->udc; unsigned long flags; int ret; @@ -878,7 +878,7 @@ fsl_ep_queue(struct usb_ep *_ep, struct usb_request *_req, gfp_t gfp_flags) dev_vdbg(&udc->gadget.dev, "%s, bad params\n", __func__); return -EINVAL; } - if (unlikely(!_ep || !ep->ep.desc)) { + if (unlikely(!ep->ep.desc)) { dev_vdbg(&udc->gadget.dev, "%s, bad ep\n", __func__); return -EINVAL; } @@ -887,7 +887,6 @@ fsl_ep_queue(struct usb_ep *_ep, struct usb_request *_req, gfp_t gfp_flags) return -EMSGSIZE; } - udc = ep->udc; if (!udc->driver || udc->gadget.speed == USB_SPEED_UNKNOWN) return -ESHUTDOWN; -- cgit v1.2.3 From 5957e0a28b5177849f7666d041b32f5dc7d27427 Mon Sep 17 00:00:00 2001 From: Kent Overstreet Date: Fri, 5 Apr 2024 02:43:08 -0400 Subject: bcachefs: Fix rebalance from durability=0 device Signed-off-by: Kent Overstreet --- fs/bcachefs/data_update.c | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/fs/bcachefs/data_update.c b/fs/bcachefs/data_update.c index 34731ee0217f..0022b51ce3c0 100644 --- a/fs/bcachefs/data_update.c +++ b/fs/bcachefs/data_update.c @@ -598,6 +598,8 @@ int bch2_data_update_init(struct btree_trans *trans, i++; } + unsigned durability_required = max(0, (int) (io_opts.data_replicas - durability_have)); + /* * If current extent durability is less than io_opts.data_replicas, * we're not trying to rereplicate the extent up to data_replicas here - @@ -607,7 +609,7 @@ int bch2_data_update_init(struct btree_trans *trans, * rereplicate, currently, so that users don't get an unexpected -ENOSPC */ if (!(m->data_opts.write_flags & BCH_WRITE_CACHED) && - durability_have >= io_opts.data_replicas) { + !durability_required) { m->data_opts.kill_ptrs |= m->data_opts.rewrite_ptrs; m->data_opts.rewrite_ptrs = 0; /* if iter == NULL, it's just a promote */ @@ -616,11 +618,18 @@ int bch2_data_update_init(struct btree_trans *trans, goto done; } - m->op.nr_replicas = min(durability_removing, io_opts.data_replicas - durability_have) + + m->op.nr_replicas = min(durability_removing, durability_required) + m->data_opts.extra_replicas; - m->op.nr_replicas_required = m->op.nr_replicas; - BUG_ON(!m->op.nr_replicas); + /* + * If device(s) were set to durability=0 after data was written to them + * we can end up with a duribilty=0 extent, and the normal algorithm + * that tries not to increase durability doesn't work: + */ + if (!(durability_have + durability_removing)) + m->op.nr_replicas = max((unsigned) m->op.nr_replicas, 1); + + m->op.nr_replicas_required = m->op.nr_replicas; if (reserve_sectors) { ret = bch2_disk_reservation_add(c, &m->op.res, reserve_sectors, -- cgit v1.2.3 From bc004f5038220b1891ef4107134ccae44be55109 Mon Sep 17 00:00:00 2001 From: Jammy Huang Date: Wed, 3 Apr 2024 17:02:46 +0800 Subject: drm/ast: Fix soft lockup There is a while-loop in ast_dp_set_on_off() that could lead to infinite-loop. This is because the register, VGACRI-Dx, checked in this API is a scratch register actually controlled by a MCU, named DPMCU, in BMC. These scratch registers are protected by scu-lock. If suc-lock is not off, DPMCU can not update these registers and then host will have soft lockup due to never updated status. DPMCU is used to control DP and relative registers to handshake with host's VGA driver. Even the most time-consuming task, DP's link training, is less than 100ms. 200ms should be enough. Signed-off-by: Jammy Huang Fixes: 594e9c04b586 ("drm/ast: Create the driver for ASPEED proprietory Display-Port") Reviewed-by: Jocelyn Falempe Reviewed-by: Thomas Zimmermann Signed-off-by: Thomas Zimmermann Cc: KuoHsiang Chou Cc: Thomas Zimmermann Cc: Dave Airlie Cc: Jocelyn Falempe Cc: dri-devel@lists.freedesktop.org Cc: # v5.19+ Link: https://patchwork.freedesktop.org/patch/msgid/20240403090246.1495487-1-jammy_huang@aspeedtech.com --- drivers/gpu/drm/ast/ast_dp.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/gpu/drm/ast/ast_dp.c b/drivers/gpu/drm/ast/ast_dp.c index ebb6d8ebd44e..1e9259416980 100644 --- a/drivers/gpu/drm/ast/ast_dp.c +++ b/drivers/gpu/drm/ast/ast_dp.c @@ -180,6 +180,7 @@ void ast_dp_set_on_off(struct drm_device *dev, bool on) { struct ast_device *ast = to_ast_device(dev); u8 video_on_off = on; + u32 i = 0; // Video On/Off ast_set_index_reg_mask(ast, AST_IO_VGACRI, 0xE3, (u8) ~AST_DP_VIDEO_ENABLE, on); @@ -192,6 +193,8 @@ void ast_dp_set_on_off(struct drm_device *dev, bool on) ASTDP_MIRROR_VIDEO_ENABLE) != video_on_off) { // wait 1 ms mdelay(1); + if (++i > 200) + break; } } } -- cgit v1.2.3 From 680507581e025d16a0b6d3782603ca8c598fbe2b Mon Sep 17 00:00:00 2001 From: Amadeusz Sławiński Date: Fri, 5 Apr 2024 11:09:17 +0200 Subject: ASoC: Intel: avs: Restore stream decoupling on prepare MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Revert changes from commit b87b8f43afd5 ("ASoC: Intel: avs: Drop superfluous stream decoupling") to restore working streaming during S3. Fixes: b87b8f43afd5 ("ASoC: Intel: avs: Drop superfluous stream decoupling") Signed-off-by: Amadeusz Sławiński Signed-off-by: Cezary Rojewski Link: https://msgid.link/r/20240405090929.1184068-2-cezary.rojewski@intel.com Signed-off-by: Mark Brown --- sound/soc/intel/avs/pcm.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/sound/soc/intel/avs/pcm.c b/sound/soc/intel/avs/pcm.c index 2cafbc392cdb..72f1bc3b7b1f 100644 --- a/sound/soc/intel/avs/pcm.c +++ b/sound/soc/intel/avs/pcm.c @@ -356,6 +356,7 @@ static int avs_dai_hda_be_prepare(struct snd_pcm_substream *substream, struct sn stream_info->sig_bits); format_val = snd_hdac_stream_format(runtime->channels, bits, runtime->rate); + snd_hdac_ext_stream_decouple(bus, link_stream, true); snd_hdac_ext_stream_reset(link_stream); snd_hdac_ext_stream_setup(link_stream, format_val); @@ -611,6 +612,7 @@ static int avs_dai_fe_prepare(struct snd_pcm_substream *substream, struct snd_so struct avs_dev *adev = to_avs_dev(dai->dev); struct hdac_ext_stream *host_stream; unsigned int format_val; + struct hdac_bus *bus; unsigned int bits; int ret; @@ -620,6 +622,8 @@ static int avs_dai_fe_prepare(struct snd_pcm_substream *substream, struct snd_so if (hdac_stream(host_stream)->prepared) return 0; + bus = hdac_stream(host_stream)->bus; + snd_hdac_ext_stream_decouple(bus, data->host_stream, true); snd_hdac_stream_reset(hdac_stream(host_stream)); stream_info = snd_soc_dai_get_pcm_stream(dai, substream->stream); -- cgit v1.2.3 From c91b692781c1839fcc389b2a9120e46593c6424b Mon Sep 17 00:00:00 2001 From: Cezary Rojewski Date: Fri, 5 Apr 2024 11:09:18 +0200 Subject: ASoC: Intel: avs: Fix debug-slot offset calculation For resources with ID other than 0 the current calculus is incorrect. Fixes: 275b583d047a ("ASoC: Intel: avs: ICL-based platforms support") Signed-off-by: Cezary Rojewski Link: https://msgid.link/r/20240405090929.1184068-3-cezary.rojewski@intel.com Signed-off-by: Mark Brown --- sound/soc/intel/avs/icl.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/sound/soc/intel/avs/icl.c b/sound/soc/intel/avs/icl.c index 9d9921e1cd4d..3e0716160f5a 100644 --- a/sound/soc/intel/avs/icl.c +++ b/sound/soc/intel/avs/icl.c @@ -66,7 +66,7 @@ struct avs_icl_memwnd2 { struct avs_icl_memwnd2_desc slot_desc[AVS_ICL_MEMWND2_SLOTS_COUNT]; u8 rsvd[PAGE_SIZE]; }; - u8 slot_array[AVS_ICL_MEMWND2_SLOTS_COUNT][PAGE_SIZE]; + u8 slot_array[AVS_ICL_MEMWND2_SLOTS_COUNT][SZ_4K]; } __packed; #define AVS_ICL_SLOT_UNUSED \ @@ -89,8 +89,7 @@ static int avs_icl_slot_offset(struct avs_dev *adev, union avs_icl_memwnd2_slot_ for (i = 0; i < AVS_ICL_MEMWND2_SLOTS_COUNT; i++) if (desc[i].slot_id.val == slot_type.val) - return offsetof(struct avs_icl_memwnd2, slot_array) + - avs_skl_log_buffer_offset(adev, i); + return offsetof(struct avs_icl_memwnd2, slot_array) + i * SZ_4K; return -ENXIO; } -- cgit v1.2.3 From 6dd68c2da44d92c25b323bcc2603421463437a64 Mon Sep 17 00:00:00 2001 From: Cezary Rojewski Date: Fri, 5 Apr 2024 11:09:19 +0200 Subject: ASoC: Intel: avs: Silence false-positive memcpy() warnings Commit df8fc4e934c1 ("kbuild: Enable -fstrict-flex-arrays=3") enforced strict flex array declarations. This generates false-positive in form of: "memcpy: detected field-spanning write". Avoid it by utilizing the DECLARE_FLEX_ARRAY() macro. Signed-off-by: Cezary Rojewski Link: https://msgid.link/r/20240405090929.1184068-4-cezary.rojewski@intel.com Signed-off-by: Mark Brown --- sound/soc/intel/avs/messages.h | 4 ++-- sound/soc/intel/avs/path.c | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/sound/soc/intel/avs/messages.h b/sound/soc/intel/avs/messages.h index 4e609a08863c..007bc4fb6d99 100644 --- a/sound/soc/intel/avs/messages.h +++ b/sound/soc/intel/avs/messages.h @@ -752,9 +752,9 @@ struct avs_copier_gtw_cfg { union avs_connector_node_id node_id; u32 dma_buffer_size; u32 config_length; - struct { + union { union avs_gtw_attributes attrs; - u32 blob[]; + DECLARE_FLEX_ARRAY(u32, blob); } config; } __packed; diff --git a/sound/soc/intel/avs/path.c b/sound/soc/intel/avs/path.c index e785fc2a7008..5944865a1193 100644 --- a/sound/soc/intel/avs/path.c +++ b/sound/soc/intel/avs/path.c @@ -254,7 +254,7 @@ static int avs_copier_create(struct avs_dev *adev, struct avs_path_module *mod) /* config_length in DWORDs */ cfg->gtw_cfg.config_length = DIV_ROUND_UP(data_size, 4); if (data) - memcpy(&cfg->gtw_cfg.config, data, data_size); + memcpy(&cfg->gtw_cfg.config.blob, data, data_size); mod->gtw_attrs = cfg->gtw_cfg.config.attrs; -- cgit v1.2.3 From beeeee9686affef32ee04d8ae30db8c53cbc7aee Mon Sep 17 00:00:00 2001 From: Cezary Rojewski Date: Fri, 5 Apr 2024 11:09:20 +0200 Subject: ASoC: Intel: avs: Fix config_length for config-less copiers Copier's config_length shall always be at least one even if there is no configuration payload to carry. While the firmware treats config_length=0 or 1 in the same manner, the driver shall initialize the module properly. Signed-off-by: Cezary Rojewski Link: https://msgid.link/r/20240405090929.1184068-5-cezary.rojewski@intel.com Signed-off-by: Mark Brown --- sound/soc/intel/avs/path.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/sound/soc/intel/avs/path.c b/sound/soc/intel/avs/path.c index 5944865a1193..9bd03a44fcb9 100644 --- a/sound/soc/intel/avs/path.c +++ b/sound/soc/intel/avs/path.c @@ -148,11 +148,12 @@ static int avs_copier_create(struct avs_dev *adev, struct avs_path_module *mod) struct avs_copier_cfg *cfg; struct nhlt_specific_cfg *ep_blob; union avs_connector_node_id node_id = {0}; - size_t cfg_size, data_size = 0; + size_t cfg_size, data_size; void *data = NULL; u32 dma_type; int ret; + data_size = sizeof(cfg->gtw_cfg.config); dma_type = t->cfg_ext->copier.dma_type; node_id.dma_type = dma_type; @@ -233,10 +234,7 @@ static int avs_copier_create(struct avs_dev *adev, struct avs_path_module *mod) break; } - cfg_size = sizeof(*cfg) + data_size; - /* Every config-BLOB contains gateway attributes. */ - if (data_size) - cfg_size -= sizeof(cfg->gtw_cfg.config.attrs); + cfg_size = offsetof(struct avs_copier_cfg, gtw_cfg.config) + data_size; if (cfg_size > AVS_MAILBOX_SIZE) return -EINVAL; -- cgit v1.2.3 From 9d2e26f31c7cc3fa495c423af9b4902ec0dc7be3 Mon Sep 17 00:00:00 2001 From: Cezary Rojewski Date: Fri, 5 Apr 2024 11:09:21 +0200 Subject: ASoC: Intel: avs: Fix ASRC module initialization The ASRC module configuration consists of several reserved fields. Zero them out when initializing the module to avoid sending invalid data. Fixes: 274d79e51875 ("ASoC: Intel: avs: Configure modules according to their type") Signed-off-by: Cezary Rojewski Link: https://msgid.link/r/20240405090929.1184068-6-cezary.rojewski@intel.com Signed-off-by: Mark Brown --- sound/soc/intel/avs/path.c | 1 + 1 file changed, 1 insertion(+) diff --git a/sound/soc/intel/avs/path.c b/sound/soc/intel/avs/path.c index 9bd03a44fcb9..8dfd90587427 100644 --- a/sound/soc/intel/avs/path.c +++ b/sound/soc/intel/avs/path.c @@ -365,6 +365,7 @@ static int avs_asrc_create(struct avs_dev *adev, struct avs_path_module *mod) struct avs_tplg_module *t = mod->template; struct avs_asrc_cfg cfg; + memset(&cfg, 0, sizeof(cfg)); cfg.base.cpc = t->cfg_base->cpc; cfg.base.ibs = t->cfg_base->ibs; cfg.base.obs = t->cfg_base->obs; -- cgit v1.2.3 From 47714847592b574ff594ceca7ebe0ada70dbac3c Mon Sep 17 00:00:00 2001 From: Cezary Rojewski Date: Fri, 5 Apr 2024 11:09:22 +0200 Subject: ASoC: Intel: avs: Replace risky functions with safer variants strscpy() and snprintf() are the recommended equivalents of their riskier friends. Signed-off-by: Cezary Rojewski Link: https://msgid.link/r/20240405090929.1184068-7-cezary.rojewski@intel.com Signed-off-by: Mark Brown --- sound/soc/intel/avs/loader.c | 4 ++-- sound/soc/intel/avs/pcm.c | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/sound/soc/intel/avs/loader.c b/sound/soc/intel/avs/loader.c index 8e34d3536082..57370f0905dc 100644 --- a/sound/soc/intel/avs/loader.c +++ b/sound/soc/intel/avs/loader.c @@ -535,7 +535,7 @@ int avs_dsp_load_libraries(struct avs_dev *adev, struct avs_tplg_library *libs, if (ret) return ret; - strncpy(adev->lib_names[id], man->name, AVS_LIB_NAME_SIZE); + strscpy(adev->lib_names[id], man->name, AVS_LIB_NAME_SIZE); id++; next_lib: i++; @@ -698,7 +698,7 @@ int avs_dsp_first_boot_firmware(struct avs_dev *adev) } /* basefw always occupies slot 0 */ - strcpy(&adev->lib_names[0][0], "BASEFW"); + strscpy(adev->lib_names[0], "BASEFW", AVS_LIB_NAME_SIZE); ida_init(&adev->ppl_ida); diff --git a/sound/soc/intel/avs/pcm.c b/sound/soc/intel/avs/pcm.c index 72f1bc3b7b1f..405de1d58178 100644 --- a/sound/soc/intel/avs/pcm.c +++ b/sound/soc/intel/avs/pcm.c @@ -1420,7 +1420,7 @@ static void avs_component_hda_unregister_dais(struct snd_soc_component *componen mach = dev_get_platdata(component->card->dev); codec = mach->pdata; - sprintf(name, "%s-cpu", dev_name(&codec->core.dev)); + snprintf(name, sizeof(name), "%s-cpu", dev_name(&codec->core.dev)); for_each_component_dais_safe(component, dai, save) { int stream; -- cgit v1.2.3 From c7e832cabe635df47c2bf6df7801e97bf3045b1e Mon Sep 17 00:00:00 2001 From: Cezary Rojewski Date: Fri, 5 Apr 2024 11:09:23 +0200 Subject: ASoC: Intel: avs: Fix potential integer overflow While stream_tag for CLDMA on SKL-based platforms is always 1, function hda_cldma_setup() uses AZX_SD_CTL_STRM() macro which does: stream_tag << 20 what combined with stream_tag type of 'unsigned int' generates a potential overflow issue. Update the field type to fix that. Fixes: 45864e49a05a ("ASoC: Intel: avs: Implement CLDMA transfer") Signed-off-by: Cezary Rojewski Link: https://msgid.link/r/20240405090929.1184068-8-cezary.rojewski@intel.com Signed-off-by: Mark Brown --- sound/soc/intel/avs/cldma.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/intel/avs/cldma.c b/sound/soc/intel/avs/cldma.c index d7a9390b5e48..585579840b64 100644 --- a/sound/soc/intel/avs/cldma.c +++ b/sound/soc/intel/avs/cldma.c @@ -35,7 +35,7 @@ struct hda_cldma { unsigned int buffer_size; unsigned int num_periods; - unsigned int stream_tag; + unsigned char stream_tag; void __iomem *sd_addr; struct snd_dma_buffer dmab_data; -- cgit v1.2.3 From 41bf4525fadb3d8df3860420d6ac9025c51a3bac Mon Sep 17 00:00:00 2001 From: Cezary Rojewski Date: Fri, 5 Apr 2024 11:09:24 +0200 Subject: ASoC: Intel: avs: Test result of avs_get_module_entry() While PROBE_MOD_UUID is always part of the base AudioDSP firmware manifest, from maintenance point of view it is better to check the result. Fixes: dab8d000e25c ("ASoC: Intel: avs: Add data probing requests") Signed-off-by: Cezary Rojewski Link: https://msgid.link/r/20240405090929.1184068-9-cezary.rojewski@intel.com Signed-off-by: Mark Brown --- sound/soc/intel/avs/probes.c | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/sound/soc/intel/avs/probes.c b/sound/soc/intel/avs/probes.c index 817e543036f2..7e781a315690 100644 --- a/sound/soc/intel/avs/probes.c +++ b/sound/soc/intel/avs/probes.c @@ -19,8 +19,11 @@ static int avs_dsp_init_probe(struct avs_dev *adev, union avs_connector_node_id struct avs_probe_cfg cfg = {{0}}; struct avs_module_entry mentry; u8 dummy; + int ret; - avs_get_module_entry(adev, &AVS_PROBE_MOD_UUID, &mentry); + ret = avs_get_module_entry(adev, &AVS_PROBE_MOD_UUID, &mentry); + if (ret) + return ret; /* * Probe module uses no cycles, audio data format and input and output @@ -39,11 +42,12 @@ static int avs_dsp_init_probe(struct avs_dev *adev, union avs_connector_node_id static void avs_dsp_delete_probe(struct avs_dev *adev) { struct avs_module_entry mentry; + int ret; - avs_get_module_entry(adev, &AVS_PROBE_MOD_UUID, &mentry); - - /* There is only ever one probe module instance. */ - avs_dsp_delete_module(adev, mentry.module_id, 0, INVALID_PIPELINE_ID, 0); + ret = avs_get_module_entry(adev, &AVS_PROBE_MOD_UUID, &mentry); + if (!ret) + /* There is only ever one probe module instance. */ + avs_dsp_delete_module(adev, mentry.module_id, 0, INVALID_PIPELINE_ID, 0); } static inline struct hdac_ext_stream *avs_compr_get_host_stream(struct snd_compr_stream *cstream) -- cgit v1.2.3 From d58275f474b4a27b4e97839ffe8d9fe55c0cc40a Mon Sep 17 00:00:00 2001 From: Cezary Rojewski Date: Fri, 5 Apr 2024 11:09:25 +0200 Subject: ASoC: Intel: avs: Remove dead code The result of list_next_entry()/list_last_entry() is never null. Signed-off-by: Cezary Rojewski Link: https://msgid.link/r/20240405090929.1184068-10-cezary.rojewski@intel.com Signed-off-by: Mark Brown --- sound/soc/intel/avs/path.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/sound/soc/intel/avs/path.c b/sound/soc/intel/avs/path.c index 8dfd90587427..fa3fec339548 100644 --- a/sound/soc/intel/avs/path.c +++ b/sound/soc/intel/avs/path.c @@ -709,8 +709,6 @@ static int avs_path_pipeline_arm(struct avs_dev *adev, /* bind current module to next module on list */ source = mod; sink = list_next_entry(mod, node); - if (!source || !sink) - return -EINVAL; ret = avs_ipc_bind(adev, source->module_id, source->instance_id, sink->module_id, sink->instance_id, 0, 0); -- cgit v1.2.3 From 30df76bbcb59254ce646477e3e05f00021a10117 Mon Sep 17 00:00:00 2001 From: Cezary Rojewski Date: Fri, 5 Apr 2024 11:09:26 +0200 Subject: ASoC: Intel: avs: Wake from D0ix when starting streaming It is recommended to keep the DSP domain in full-power when starting DMA engines. Signed-off-by: Cezary Rojewski Link: https://msgid.link/r/20240405090929.1184068-11-cezary.rojewski@intel.com Signed-off-by: Mark Brown --- sound/soc/intel/avs/icl.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/sound/soc/intel/avs/icl.c b/sound/soc/intel/avs/icl.c index 3e0716160f5a..d279ec1e0ad0 100644 --- a/sound/soc/intel/avs/icl.c +++ b/sound/soc/intel/avs/icl.c @@ -109,6 +109,10 @@ int avs_icl_log_buffer_offset(struct avs_dev *adev, u32 core) bool avs_icl_d0ix_toggle(struct avs_dev *adev, struct avs_ipc_msg *tx, bool wake) { + /* Full-power when starting DMA engines. */ + if (tx->glb.set_ppl_state.state == AVS_PPL_STATE_RUNNING) + return true; + /* Payload-less IPCs do not take part in d0ix toggling. */ return tx->size; } -- cgit v1.2.3 From ff0aefe2d217ce6fec6487b225737b2019eb88c0 Mon Sep 17 00:00:00 2001 From: Cezary Rojewski Date: Fri, 5 Apr 2024 11:09:27 +0200 Subject: ASoC: Intel: avs: Init debugfs before booting firmware When bringing up setups it's vital to have access to debug functionality even if firmware boot fails. As order of probe()ing operations is changed, update remove() procedure accordingly. Signed-off-by: Cezary Rojewski Link: https://msgid.link/r/20240405090929.1184068-12-cezary.rojewski@intel.com Signed-off-by: Mark Brown --- sound/soc/intel/avs/core.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/soc/intel/avs/core.c b/sound/soc/intel/avs/core.c index d7f8940099ce..76782a0f32bc 100644 --- a/sound/soc/intel/avs/core.c +++ b/sound/soc/intel/avs/core.c @@ -209,6 +209,7 @@ static void avs_hda_probe_work(struct work_struct *work) snd_hdac_ext_bus_ppcap_enable(bus, true); snd_hdac_ext_bus_ppcap_int_enable(bus, true); + avs_debugfs_init(adev); ret = avs_dsp_first_boot_firmware(adev); if (ret < 0) @@ -217,7 +218,6 @@ static void avs_hda_probe_work(struct work_struct *work) adev->nhlt = intel_nhlt_init(adev->dev); if (!adev->nhlt) dev_info(bus->dev, "platform has no NHLT\n"); - avs_debugfs_init(adev); avs_register_all_boards(adev); @@ -548,9 +548,9 @@ static void avs_pci_remove(struct pci_dev *pci) avs_unregister_all_boards(adev); - avs_debugfs_exit(adev); if (adev->nhlt) intel_nhlt_free(adev->nhlt); + avs_debugfs_exit(adev); if (avs_platattr_test(adev, CLDMA)) hda_cldma_free(&code_loader); -- cgit v1.2.3 From c2b10acb62c195db2c976d614d9d8092ad6339ae Mon Sep 17 00:00:00 2001 From: Amadeusz Sławiński Date: Fri, 5 Apr 2024 11:09:28 +0200 Subject: ASoC: Intel: avs: Add assert_static to guarantee ABI sizes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In order to make sure that IPC interface is stable use assert_static to check union and struct sizes that describe communication interface. Signed-off-by: Amadeusz Sławiński Signed-off-by: Cezary Rojewski Link: https://msgid.link/r/20240405090929.1184068-13-cezary.rojewski@intel.com Signed-off-by: Mark Brown --- sound/soc/intel/avs/avs.h | 1 + sound/soc/intel/avs/icl.c | 3 +++ sound/soc/intel/avs/loader.c | 2 ++ sound/soc/intel/avs/messages.h | 43 ++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 49 insertions(+) diff --git a/sound/soc/intel/avs/avs.h b/sound/soc/intel/avs/avs.h index f80f79415344..39bdec591d58 100644 --- a/sound/soc/intel/avs/avs.h +++ b/sound/soc/intel/avs/avs.h @@ -381,6 +381,7 @@ struct avs_apl_log_buffer_layout { u32 write_ptr; u8 buffer[]; } __packed; +static_assert(sizeof(struct avs_apl_log_buffer_layout) == 8); #define avs_apl_log_payload_size(adev) \ (avs_log_buffer_size(adev) - sizeof(struct avs_apl_log_buffer_layout)) diff --git a/sound/soc/intel/avs/icl.c b/sound/soc/intel/avs/icl.c index d279ec1e0ad0..e8b4983e03e9 100644 --- a/sound/soc/intel/avs/icl.c +++ b/sound/soc/intel/avs/icl.c @@ -52,12 +52,14 @@ union avs_icl_memwnd2_slot_type { u32 type:24; }; } __packed; +static_assert(sizeof(union avs_icl_memwnd2_slot_type) == 4); struct avs_icl_memwnd2_desc { u32 resource_id; union avs_icl_memwnd2_slot_type slot_id; u32 vma; } __packed; +static_assert(sizeof(struct avs_icl_memwnd2_desc) == 12); #define AVS_ICL_MEMWND2_SLOTS_COUNT 15 @@ -68,6 +70,7 @@ struct avs_icl_memwnd2 { }; u8 slot_array[AVS_ICL_MEMWND2_SLOTS_COUNT][SZ_4K]; } __packed; +static_assert(sizeof(struct avs_icl_memwnd2) == 65536); #define AVS_ICL_SLOT_UNUSED \ ((union avs_icl_memwnd2_slot_type) { 0x00000000U }) diff --git a/sound/soc/intel/avs/loader.c b/sound/soc/intel/avs/loader.c index 57370f0905dc..c255c898b7a8 100644 --- a/sound/soc/intel/avs/loader.c +++ b/sound/soc/intel/avs/loader.c @@ -56,6 +56,7 @@ struct avs_fw_manifest { u32 feature_mask; struct avs_fw_version version; } __packed; +static_assert(sizeof(struct avs_fw_manifest) == 36); struct avs_fw_ext_manifest { u32 id; @@ -64,6 +65,7 @@ struct avs_fw_ext_manifest { u16 version_minor; u32 entries; } __packed; +static_assert(sizeof(struct avs_fw_ext_manifest) == 16); static int avs_fw_ext_manifest_strip(struct firmware *fw) { diff --git a/sound/soc/intel/avs/messages.h b/sound/soc/intel/avs/messages.h index 007bc4fb6d99..285d89607b6a 100644 --- a/sound/soc/intel/avs/messages.h +++ b/sound/soc/intel/avs/messages.h @@ -93,12 +93,14 @@ union avs_global_msg { } ext; }; } __packed; +static_assert(sizeof(union avs_global_msg) == 8); struct avs_tlv { u32 type; u32 length; u32 value[]; } __packed; +static_assert(sizeof(struct avs_tlv) == 8); enum avs_module_msg_type { AVS_MOD_INIT_INSTANCE = 0, @@ -155,6 +157,7 @@ union avs_module_msg { } ext; }; } __packed; +static_assert(sizeof(union avs_module_msg) == 8); #define AVS_IPC_NOT_SUPPORTED 15 @@ -190,6 +193,7 @@ union avs_reply_msg { } ext; }; } __packed; +static_assert(sizeof(union avs_reply_msg) == 8); enum avs_notify_msg_type { AVS_NOTIFY_PHRASE_DETECTED = 4, @@ -226,6 +230,7 @@ union avs_notify_msg { } ext; }; } __packed; +static_assert(sizeof(union avs_notify_msg) == 8); #define AVS_MSG(hdr) { .val = hdr } @@ -264,6 +269,7 @@ struct avs_notify_voice_data { u16 kpd_score; u16 reserved; } __packed; +static_assert(sizeof(struct avs_notify_voice_data) == 4); struct avs_notify_res_data { u32 resource_type; @@ -272,6 +278,7 @@ struct avs_notify_res_data { u32 reserved; u32 data[6]; } __packed; +static_assert(sizeof(struct avs_notify_res_data) == 40); struct avs_notify_mod_data { u32 module_instance_id; @@ -279,6 +286,7 @@ struct avs_notify_mod_data { u32 data_size; u32 data[]; } __packed; +static_assert(sizeof(struct avs_notify_mod_data) == 12); /* ROM messages */ enum avs_rom_control_msg_type { @@ -332,6 +340,7 @@ struct avs_dxstate_info { u32 core_mask; /* which cores are subject for power transition */ u32 dx_mask; /* bit[n]=1 core n goes to D0, bit[n]=0 it goes to D3 */ } __packed; +static_assert(sizeof(struct avs_dxstate_info) == 8); int avs_ipc_set_dx(struct avs_dev *adev, u32 core_mask, bool powerup); int avs_ipc_set_d0ix(struct avs_dev *adev, bool enable_pg, bool streaming); @@ -367,11 +376,13 @@ struct avs_skl_log_state { u32 enable; u32 min_priority; } __packed; +static_assert(sizeof(struct avs_skl_log_state) == 8); struct avs_skl_log_state_info { u32 core_mask; struct avs_skl_log_state logs_core[]; } __packed; +static_assert(sizeof(struct avs_skl_log_state_info) == 4); struct avs_apl_log_state_info { u32 aging_timer_period; @@ -379,6 +390,7 @@ struct avs_apl_log_state_info { u32 core_mask; struct avs_skl_log_state logs_core[]; } __packed; +static_assert(sizeof(struct avs_apl_log_state_info) == 12); enum avs_icl_log_priority { AVS_ICL_LOG_CRITICAL = 0, @@ -403,6 +415,7 @@ struct avs_icl_log_state_info { u32 enable; u32 logs_priorities_mask[]; } __packed; +static_assert(sizeof(struct avs_icl_log_state_info) == 12); int avs_ipc_set_enable_logs(struct avs_dev *adev, u8 *log_info, size_t size); @@ -521,6 +534,7 @@ struct avs_module_type { u32 lib_code:1; u32 rsvd:24; } __packed; +static_assert(sizeof(struct avs_module_type) == 4); union avs_segment_flags { u32 ul; @@ -537,12 +551,14 @@ union avs_segment_flags { u32 length:16; }; } __packed; +static_assert(sizeof(union avs_segment_flags) == 4); struct avs_segment_desc { union avs_segment_flags flags; u32 v_base_addr; u32 file_offset; } __packed; +static_assert(sizeof(struct avs_segment_desc) == 12); struct avs_module_entry { u16 module_id; @@ -559,11 +575,13 @@ struct avs_module_entry { u16 instance_bss_size; struct avs_segment_desc segments[3]; } __packed; +static_assert(sizeof(struct avs_module_entry) == 116); struct avs_mods_info { u32 count; struct avs_module_entry entries[]; } __packed; +static_assert(sizeof(struct avs_mods_info) == 4); static inline bool avs_module_entry_is_loaded(struct avs_module_entry *mentry) { @@ -577,6 +595,7 @@ struct avs_sys_time { u32 val_l; u32 val_u; } __packed; +static_assert(sizeof(struct avs_sys_time) == 8); int avs_ipc_set_system_time(struct avs_dev *adev); @@ -680,6 +699,7 @@ struct avs_audio_format { u32 sample_type:8; u32 reserved:8; } __packed; +static_assert(sizeof(struct avs_audio_format) == 24); struct avs_modcfg_base { u32 cpc; @@ -688,12 +708,14 @@ struct avs_modcfg_base { u32 is_pages; struct avs_audio_format audio_fmt; } __packed; +static_assert(sizeof(struct avs_modcfg_base) == 40); struct avs_pin_format { u32 pin_index; u32 iobs; struct avs_audio_format audio_fmt; } __packed; +static_assert(sizeof(struct avs_pin_format) == 32); struct avs_modcfg_ext { struct avs_modcfg_base base; @@ -703,6 +725,7 @@ struct avs_modcfg_ext { /* input pin formats followed by output ones */ struct avs_pin_format pin_fmts[]; } __packed; +static_assert(sizeof(struct avs_modcfg_ext) == 56); enum avs_dma_type { AVS_DMA_HDA_HOST_OUTPUT = 0, @@ -726,6 +749,7 @@ union avs_virtual_index { u8 instance:3; } dmic; } __packed; +static_assert(sizeof(union avs_virtual_index) == 1); union avs_connector_node_id { u32 val; @@ -735,6 +759,7 @@ union avs_connector_node_id { u32 rsvd:19; }; } __packed; +static_assert(sizeof(union avs_connector_node_id) == 4); #define INVALID_PIPELINE_ID 0xFF #define INVALID_NODE_ID \ @@ -747,6 +772,7 @@ union avs_gtw_attributes { u32 rsvd:31; }; } __packed; +static_assert(sizeof(union avs_gtw_attributes) == 4); struct avs_copier_gtw_cfg { union avs_connector_node_id node_id; @@ -757,6 +783,7 @@ struct avs_copier_gtw_cfg { DECLARE_FLEX_ARRAY(u32, blob); } config; } __packed; +static_assert(sizeof(struct avs_copier_gtw_cfg) == 16); struct avs_copier_cfg { struct avs_modcfg_base base; @@ -764,6 +791,7 @@ struct avs_copier_cfg { u32 feature_mask; struct avs_copier_gtw_cfg gtw_cfg; } __packed; +static_assert(sizeof(struct avs_copier_cfg) == 84); struct avs_volume_cfg { u32 channel_id; @@ -772,22 +800,26 @@ struct avs_volume_cfg { u32 reserved; /* alignment */ u64 curve_duration; } __packed; +static_assert(sizeof(struct avs_volume_cfg) == 24); struct avs_peakvol_cfg { struct avs_modcfg_base base; struct avs_volume_cfg vols[]; } __packed; +static_assert(sizeof(struct avs_peakvol_cfg) == 40); struct avs_micsel_cfg { struct avs_modcfg_base base; struct avs_audio_format out_fmt; } __packed; +static_assert(sizeof(struct avs_micsel_cfg) == 64); struct avs_mux_cfg { struct avs_modcfg_base base; struct avs_audio_format ref_fmt; struct avs_audio_format out_fmt; } __packed; +static_assert(sizeof(struct avs_mux_cfg) == 88); struct avs_updown_mixer_cfg { struct avs_modcfg_base base; @@ -796,21 +828,25 @@ struct avs_updown_mixer_cfg { s32 coefficients[AVS_CHANNELS_MAX]; u32 channel_map; } __packed; +static_assert(sizeof(struct avs_updown_mixer_cfg) == 84); struct avs_src_cfg { struct avs_modcfg_base base; u32 out_freq; } __packed; +static_assert(sizeof(struct avs_src_cfg) == 44); struct avs_probe_gtw_cfg { union avs_connector_node_id node_id; u32 dma_buffer_size; } __packed; +static_assert(sizeof(struct avs_probe_gtw_cfg) == 8); struct avs_probe_cfg { struct avs_modcfg_base base; struct avs_probe_gtw_cfg gtw_cfg; } __packed; +static_assert(sizeof(struct avs_probe_cfg) == 48); struct avs_aec_cfg { struct avs_modcfg_base base; @@ -818,6 +854,7 @@ struct avs_aec_cfg { struct avs_audio_format out_fmt; u32 cpc_lp_mode; } __packed; +static_assert(sizeof(struct avs_aec_cfg) == 92); struct avs_asrc_cfg { struct avs_modcfg_base base; @@ -828,11 +865,13 @@ struct avs_asrc_cfg { u32 disable_jitter_buffer:1; u32 rsvd3:27; } __packed; +static_assert(sizeof(struct avs_asrc_cfg) == 48); struct avs_wov_cfg { struct avs_modcfg_base base; u32 cpc_lp_mode; } __packed; +static_assert(sizeof(struct avs_wov_cfg) == 44); /* Module runtime parameters */ @@ -845,6 +884,7 @@ struct avs_copier_sink_format { struct avs_audio_format src_fmt; struct avs_audio_format sink_fmt; } __packed; +static_assert(sizeof(struct avs_copier_sink_format) == 52); int avs_ipc_copier_set_sink_format(struct avs_dev *adev, u16 module_id, u8 instance_id, u32 sink_id, @@ -878,6 +918,7 @@ struct avs_probe_dma { union avs_connector_node_id node_id; u32 dma_buffer_size; } __packed; +static_assert(sizeof(struct avs_probe_dma) == 8); enum avs_probe_type { AVS_PROBE_TYPE_INPUT = 0, @@ -894,6 +935,7 @@ union avs_probe_point_id { u32 index:6; } id; } __packed; +static_assert(sizeof(union avs_probe_point_id) == 4); enum avs_connection_purpose { AVS_CONNECTION_PURPOSE_EXTRACT = 0, @@ -906,6 +948,7 @@ struct avs_probe_point_desc { u32 purpose; union avs_connector_node_id node_id; } __packed; +static_assert(sizeof(struct avs_probe_point_desc) == 12); int avs_ipc_probe_get_dma(struct avs_dev *adev, struct avs_probe_dma **dmas, size_t *num_dmas); int avs_ipc_probe_attach_dma(struct avs_dev *adev, struct avs_probe_dma *dmas, size_t num_dmas); -- cgit v1.2.3 From 9a385993504e47a0fd6fd34b5384827b4abdee60 Mon Sep 17 00:00:00 2001 From: Cezary Rojewski Date: Fri, 5 Apr 2024 11:09:29 +0200 Subject: ASoC: Intel: avs: Rule invalid buffer and period sizes out While HDAudio controller supports buffer packets up to 128 bytes low, audio format shall be taken into consideration when calculating buffer and period sizes to avoid undesired xruns. As *_size in ALSA terms means frames (channels times bit-depth-bytes), hw_rules can calculate minimal buffer and period sizes solely from sample rate and the number of milliseconds commonly used on the AudioDSP firmware side. Signed-off-by: Cezary Rojewski Link: https://msgid.link/r/20240405090929.1184068-14-cezary.rojewski@intel.com Signed-off-by: Mark Brown --- sound/soc/intel/avs/pcm.c | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/sound/soc/intel/avs/pcm.c b/sound/soc/intel/avs/pcm.c index 405de1d58178..77a7e8f93951 100644 --- a/sound/soc/intel/avs/pcm.c +++ b/sound/soc/intel/avs/pcm.c @@ -457,6 +457,26 @@ static const struct snd_pcm_hw_constraint_list hw_rates = { const struct snd_soc_dai_ops avs_dai_fe_ops; +static int hw_rule_param_size(struct snd_pcm_hw_params *params, struct snd_pcm_hw_rule *rule) +{ + struct snd_interval *interval = hw_param_interval(params, rule->var); + struct snd_interval to; + + snd_interval_any(&to); + to.integer = interval->integer; + to.max = interval->max; + /* + * Commonly 2ms buffer size is used in HDA scenarios whereas 4ms is used + * when streaming through GPDMA. Align to the latter to account for both. + */ + to.min = params_rate(params) / 1000 * 4; + + if (rule->var == SNDRV_PCM_HW_PARAM_PERIOD_SIZE) + to.min /= params_periods(params); + + return snd_interval_refine(interval, &to); +} + static int avs_dai_fe_startup(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) { struct snd_pcm_runtime *runtime = substream->runtime; @@ -492,6 +512,14 @@ static int avs_dai_fe_startup(struct snd_pcm_substream *substream, struct snd_so if (ret < 0) goto err; + /* Adjust buffer and period size based on the audio format. */ + snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_BUFFER_SIZE, hw_rule_param_size, NULL, + SNDRV_PCM_HW_PARAM_FORMAT, SNDRV_PCM_HW_PARAM_CHANNELS, + SNDRV_PCM_HW_PARAM_RATE, -1); + snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_SIZE, hw_rule_param_size, NULL, + SNDRV_PCM_HW_PARAM_FORMAT, SNDRV_PCM_HW_PARAM_CHANNELS, + SNDRV_PCM_HW_PARAM_RATE, -1); + snd_pcm_set_sync(substream); dev_dbg(dai->dev, "%s fe STARTUP tag %d str %p", -- cgit v1.2.3 From 07ed11afb68d94eadd4ffc082b97c2331307c5ea Mon Sep 17 00:00:00 2001 From: Alex Constantino Date: Thu, 4 Apr 2024 19:14:48 +0100 Subject: Revert "drm/qxl: simplify qxl_fence_wait" This reverts commit 5a838e5d5825c85556011478abde708251cc0776. Changes from commit 5a838e5d5825 ("drm/qxl: simplify qxl_fence_wait") would result in a '[TTM] Buffer eviction failed' exception whenever it reached a timeout. Due to a dependency to DMA_FENCE_WARN this also restores some code deleted by commit d72277b6c37d ("dma-buf: nuke DMA_FENCE_TRACE macros v2"). Fixes: 5a838e5d5825 ("drm/qxl: simplify qxl_fence_wait") Link: https://lore.kernel.org/regressions/ZTgydqRlK6WX_b29@eldamar.lan/ Reported-by: Timo Lindfors Closes: https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=1054514 Signed-off-by: Alex Constantino Signed-off-by: Maxime Ripard Link: https://patchwork.freedesktop.org/patch/msgid/20240404181448.1643-2-dreaming.about.electric.sheep@gmail.com --- drivers/gpu/drm/qxl/qxl_release.c | 50 +++++++++++++++++++++++++++++++++++---- include/linux/dma-fence.h | 7 ++++++ 2 files changed, 52 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/qxl/qxl_release.c b/drivers/gpu/drm/qxl/qxl_release.c index 368d26da0d6a..9febc8b73f09 100644 --- a/drivers/gpu/drm/qxl/qxl_release.c +++ b/drivers/gpu/drm/qxl/qxl_release.c @@ -58,16 +58,56 @@ static long qxl_fence_wait(struct dma_fence *fence, bool intr, signed long timeout) { struct qxl_device *qdev; + struct qxl_release *release; + int count = 0, sc = 0; + bool have_drawable_releases; unsigned long cur, end = jiffies + timeout; qdev = container_of(fence->lock, struct qxl_device, release_lock); + release = container_of(fence, struct qxl_release, base); + have_drawable_releases = release->type == QXL_RELEASE_DRAWABLE; - if (!wait_event_timeout(qdev->release_event, - (dma_fence_is_signaled(fence) || - (qxl_io_notify_oom(qdev), 0)), - timeout)) - return 0; +retry: + sc++; + + if (dma_fence_is_signaled(fence)) + goto signaled; + + qxl_io_notify_oom(qdev); + + for (count = 0; count < 11; count++) { + if (!qxl_queue_garbage_collect(qdev, true)) + break; + + if (dma_fence_is_signaled(fence)) + goto signaled; + } + + if (dma_fence_is_signaled(fence)) + goto signaled; + + if (have_drawable_releases || sc < 4) { + if (sc > 2) + /* back off */ + usleep_range(500, 1000); + + if (time_after(jiffies, end)) + return 0; + + if (have_drawable_releases && sc > 300) { + DMA_FENCE_WARN(fence, + "failed to wait on release %llu after spincount %d\n", + fence->context & ~0xf0000000, sc); + goto signaled; + } + goto retry; + } + /* + * yeah, original sync_obj_wait gave up after 3 spins when + * have_drawable_releases is not set. + */ +signaled: cur = jiffies; if (time_after(cur, end)) return 0; diff --git a/include/linux/dma-fence.h b/include/linux/dma-fence.h index e06bad467f55..c3f9bb6602ba 100644 --- a/include/linux/dma-fence.h +++ b/include/linux/dma-fence.h @@ -682,4 +682,11 @@ static inline bool dma_fence_is_container(struct dma_fence *fence) return dma_fence_is_array(fence) || dma_fence_is_chain(fence); } +#define DMA_FENCE_WARN(f, fmt, args...) \ + do { \ + struct dma_fence *__ff = (f); \ + pr_warn("f %llu#%llu: " fmt, __ff->context, __ff->seqno,\ + ##args); \ + } while (0) + #endif /* __LINUX_DMA_FENCE_H */ -- cgit v1.2.3 From 24cfd86433c920188ac3f02df8aba6bc4c792f4b Mon Sep 17 00:00:00 2001 From: Damien Le Moal Date: Thu, 4 Apr 2024 18:30:14 +0900 Subject: ata: ahci: Add mask_port_map module parameter Commits 0077a504e1a4 ("ahci: asm1166: correct count of reported ports") and 9815e3961754 ("ahci: asm1064: correct count of reported ports") attempted to limit the ports of the ASM1166 and ASM1064 AHCI controllers to avoid long boot times caused by the fact that these adapters report a port map larger than the number of physical ports. The excess ports are "virtual" to hide port multiplier devices and probing these ports takes time. However, these commits caused a regression for users that do use PMP devices, as the ATA devices connected to the PMP cannot be scanned. These commits have thus been reverted by commit 6cd8adc3e18 ("ahci: asm1064: asm1166: don't limit reported ports") to allow the discovery of devices connected through a port multiplier. But this revert re-introduced the long boot times for users that do not use a port multiplier setup. This patch adds the mask_port_map ahci module parameter to allow users to manually specify port map masks for controllers. In the case of the ASMedia 1166 and 1064 controllers, users that do not have port multiplier devices can mask the excess virtual ports exposed by the controller to speedup port scanning, thus reducing boot time. The mask_port_map parameter accepts 2 different formats: - mask_port_map= This applies the same mask to all AHCI controllers present in the system. This format is convenient for small systems that have only a single AHCI controller. - mask_port_map==,=mask,... This applies the specified masks only to the PCI device listed. The field is a regular PCI device ID (domain:bus:dev.func). This ID can be seen following "ahci" in the kernel messages. E.g. for "ahci 0000:01:00.0: 2/2 ports implemented (port mask 0x3)", the field is "0000:01:00.0". When used, the function ahci_save_initial_config() indicates that a port map mask was applied with the message "masking port_map ...". E.g.: without a mask: modprobe ahci dmesg | grep ahci ... ahci 0000:00:17.0: AHCI vers 0001.0301, 32 command slots, 6 Gbps, SATA mode ahci 0000:00:17.0: (0000:00:17.0) 8/8 ports implemented (port mask 0xff) With a mask: modprobe ahci mask_port_map=0000:00:17.0=0x1 dmesg | grep ahci ... ahci 0000:00:17.0: masking port_map 0xff -> 0x1 ahci 0000:00:17.0: AHCI vers 0001.0301, 32 command slots, 6 Gbps, SATA mode ahci 0000:00:17.0: (0000:00:17.0) 1/8 ports implemented (port mask 0x1) Signed-off-by: Damien Le Moal Reviewed-by: Niklas Cassel --- drivers/ata/ahci.c | 85 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 85 insertions(+) diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c index 562302e2e57c..6548f10e61d9 100644 --- a/drivers/ata/ahci.c +++ b/drivers/ata/ahci.c @@ -666,6 +666,87 @@ static int mobile_lpm_policy = -1; module_param(mobile_lpm_policy, int, 0644); MODULE_PARM_DESC(mobile_lpm_policy, "Default LPM policy for mobile chipsets"); +static char *ahci_mask_port_map; +module_param_named(mask_port_map, ahci_mask_port_map, charp, 0444); +MODULE_PARM_DESC(mask_port_map, + "32-bits port map masks to ignore controllers ports. " + "Valid values are: " + "\"\" to apply the same mask to all AHCI controller " + "devices, and \"=,=,...\" to " + "specify different masks for the controllers specified, " + "where is the PCI ID of an AHCI controller in the " + "form \"domain:bus:dev.func\""); + +static void ahci_apply_port_map_mask(struct device *dev, + struct ahci_host_priv *hpriv, char *mask_s) +{ + unsigned int mask; + + if (kstrtouint(mask_s, 0, &mask)) { + dev_err(dev, "Invalid port map mask\n"); + return; + } + + hpriv->mask_port_map = mask; +} + +static void ahci_get_port_map_mask(struct device *dev, + struct ahci_host_priv *hpriv) +{ + char *param, *end, *str, *mask_s; + char *name; + + if (!strlen(ahci_mask_port_map)) + return; + + str = kstrdup(ahci_mask_port_map, GFP_KERNEL); + if (!str) + return; + + /* Handle single mask case */ + if (!strchr(str, '=')) { + ahci_apply_port_map_mask(dev, hpriv, str); + goto free; + } + + /* + * Mask list case: parse the parameter to apply the mask only if + * the device name matches. + */ + param = str; + end = param + strlen(param); + while (param && param < end && *param) { + name = param; + param = strchr(name, '='); + if (!param) + break; + + *param = '\0'; + param++; + if (param >= end) + break; + + if (strcmp(dev_name(dev), name) != 0) { + param = strchr(param, ','); + if (param) + param++; + continue; + } + + mask_s = param; + param = strchr(mask_s, ','); + if (param) { + *param = '\0'; + param++; + } + + ahci_apply_port_map_mask(dev, hpriv, mask_s); + } + +free: + kfree(str); +} + static void ahci_pci_save_initial_config(struct pci_dev *pdev, struct ahci_host_priv *hpriv) { @@ -688,6 +769,10 @@ static void ahci_pci_save_initial_config(struct pci_dev *pdev, "Disabling your PATA port. Use the boot option 'ahci.marvell_enable=0' to avoid this.\n"); } + /* Handle port map masks passed as module parameter. */ + if (ahci_mask_port_map) + ahci_get_port_map_mask(&pdev->dev, hpriv); + ahci_save_initial_config(&pdev->dev, hpriv); } -- cgit v1.2.3 From 648dae58a830ecceea3b1bebf68432435980f137 Mon Sep 17 00:00:00 2001 From: Dave Jiang Date: Wed, 3 Apr 2024 08:47:12 -0700 Subject: cxl: Remove checking of iter in cxl_endpoint_get_perf_coordinates() The while() loop in cxl_endpoint_get_perf_coordinates() checks to see if 'iter' is valid as part of the condition breaking out of the loop. is_cxl_root() will stop the loop before the next iteration could go NULL. Remove the iter check. The presence of the iter or removing the iter does not impact the behavior of the code. This is a code clean up and not a bug fix. Reviewed-by: Jonathan Cameron Reviewed-by: Davidlohr Bueso Reviewed-by: Dan Williams Link: https://lore.kernel.org/r/20240403154844.3403859-2-dave.jiang@intel.com Signed-off-by: Dave Jiang --- drivers/cxl/core/port.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/cxl/core/port.c b/drivers/cxl/core/port.c index 2b0cab556072..6cbde50a742b 100644 --- a/drivers/cxl/core/port.c +++ b/drivers/cxl/core/port.c @@ -2197,7 +2197,7 @@ int cxl_endpoint_get_perf_coordinates(struct cxl_port *port, * port each iteration. If the parent is cxl root then there is * nothing to gather. */ - while (iter && !is_cxl_root(to_cxl_port(iter->dev.parent))) { + while (!is_cxl_root(to_cxl_port(iter->dev.parent))) { cxl_coordinates_combine(&c, &c, &dport->sw_coord); c.write_latency += dport->link_latency; c.read_latency += dport->link_latency; -- cgit v1.2.3 From 838ae9f45c4e43b4633d8b0ad1fbedff9ecf177d Mon Sep 17 00:00:00 2001 From: Kees Cook Date: Sat, 30 Mar 2024 07:12:03 -0700 Subject: nouveau/gsp: Avoid addressing beyond end of rpc->entries Using the end of rpc->entries[] for addressing runs into both compile-time and run-time detection of accessing beyond the end of the array. Use the base pointer instead, since was allocated with the additional bytes for storing the strings. Avoids the following warning in future GCC releases with support for __counted_by: In function 'fortify_memcpy_chk', inlined from 'r535_gsp_rpc_set_registry' at ../drivers/gpu/drm/nouveau/nvkm/subdev/gsp/r535.c:1123:3: ../include/linux/fortify-string.h:553:25: error: call to '__write_overflow_field' declared with attribute warning: detected write beyond size of field (1st parameter); maybe use struct_group()? [-Werror=attribute-warning] 553 | __write_overflow_field(p_size_field, size); | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ for this code: strings = (char *)&rpc->entries[NV_GSP_REG_NUM_ENTRIES]; ... memcpy(strings, r535_registry_entries[i].name, name_len); Signed-off-by: Kees Cook Signed-off-by: Danilo Krummrich Link: https://patchwork.freedesktop.org/patch/msgid/20240330141159.work.063-kees@kernel.org --- drivers/gpu/drm/nouveau/nvkm/subdev/gsp/r535.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/r535.c b/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/r535.c index 9994cbd6f1c4..9858c1438aa7 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/r535.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/r535.c @@ -1112,7 +1112,7 @@ r535_gsp_rpc_set_registry(struct nvkm_gsp *gsp) rpc->numEntries = NV_GSP_REG_NUM_ENTRIES; str_offset = offsetof(typeof(*rpc), entries[NV_GSP_REG_NUM_ENTRIES]); - strings = (char *)&rpc->entries[NV_GSP_REG_NUM_ENTRIES]; + strings = (char *)rpc + str_offset; for (i = 0; i < NV_GSP_REG_NUM_ENTRIES; i++) { int name_len = strlen(r535_registry_entries[i].name) + 1; -- cgit v1.2.3 From 185fdb4697cc9684a02f2fab0530ecdd0c2f15d4 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Thu, 4 Apr 2024 18:02:25 +0200 Subject: nouveau: fix function cast warning Calling a function through an incompatible pointer type causes breaks kcfi, so clang warns about the assignment: drivers/gpu/drm/nouveau/nvkm/subdev/bios/shadowof.c:73:10: error: cast from 'void (*)(const void *)' to 'void (*)(void *)' converts to incompatible function type [-Werror,-Wcast-function-type-strict] 73 | .fini = (void(*)(void *))kfree, Avoid this with a trivial wrapper. Fixes: c39f472e9f14 ("drm/nouveau: remove symlinks, move core/ to nvkm/ (no code changes)") Signed-off-by: Arnd Bergmann Signed-off-by: Danilo Krummrich Link: https://patchwork.freedesktop.org/patch/msgid/20240404160234.2923554-1-arnd@kernel.org --- drivers/gpu/drm/nouveau/nvkm/subdev/bios/shadowof.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/bios/shadowof.c b/drivers/gpu/drm/nouveau/nvkm/subdev/bios/shadowof.c index 4bf486b57101..cb05f7f48a98 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/bios/shadowof.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/bios/shadowof.c @@ -66,11 +66,16 @@ of_init(struct nvkm_bios *bios, const char *name) return ERR_PTR(-EINVAL); } +static void of_fini(void *p) +{ + kfree(p); +} + const struct nvbios_source nvbios_of = { .name = "OpenFirmware", .init = of_init, - .fini = (void(*)(void *))kfree, + .fini = of_fini, .read = of_read, .size = of_size, .rw = false, -- cgit v1.2.3 From 0c3b532ad3fbf82884a2e7e83e37c7dcdd4d1d99 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Fri, 5 Apr 2024 19:25:21 +0300 Subject: gpio: wcove: Use -ENOTSUPP consistently The GPIO library expects the drivers to return -ENOTSUPP in some cases and not using analogue POSIX code. Make the driver to follow this. Reviewed-by: Kuppuswamy Sathyanarayanan Signed-off-by: Andy Shevchenko --- drivers/gpio/gpio-wcove.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpio/gpio-wcove.c b/drivers/gpio/gpio-wcove.c index c18b6b47384f..94ca9d03c094 100644 --- a/drivers/gpio/gpio-wcove.c +++ b/drivers/gpio/gpio-wcove.c @@ -104,7 +104,7 @@ static inline int to_reg(int gpio, enum ctrl_register type) unsigned int reg = type == CTRL_IN ? GPIO_IN_CTRL_BASE : GPIO_OUT_CTRL_BASE; if (gpio >= WCOVE_GPIO_NUM) - return -EOPNOTSUPP; + return -ENOTSUPP; return reg + gpio; } -- cgit v1.2.3 From ace0ebe5c98d66889f19e0f30e2518d0c58d0e04 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Fri, 5 Apr 2024 19:26:22 +0300 Subject: gpio: crystalcove: Use -ENOTSUPP consistently The GPIO library expects the drivers to return -ENOTSUPP in some cases and not using analogue POSIX code. Make the driver to follow this. Signed-off-by: Andy Shevchenko --- drivers/gpio/gpio-crystalcove.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpio/gpio-crystalcove.c b/drivers/gpio/gpio-crystalcove.c index 1ee62cd58582..25db014494a4 100644 --- a/drivers/gpio/gpio-crystalcove.c +++ b/drivers/gpio/gpio-crystalcove.c @@ -92,7 +92,7 @@ static inline int to_reg(int gpio, enum ctrl_register reg_type) case 0x5e: return GPIOPANELCTL; default: - return -EOPNOTSUPP; + return -ENOTSUPP; } } -- cgit v1.2.3 From d3bbc4dfcc8d436b1e27a0bb6a5893b090fc1cab Mon Sep 17 00:00:00 2001 From: Miguel Ojeda Date: Tue, 26 Mar 2024 22:23:24 +0100 Subject: drm/msm: fix the `CRASHDUMP_READ` target of `a6xx_get_shader_block()` Clang 14 in an (essentially) defconfig arm64 build for next-20240326 reports [1]: drivers/gpu/drm/msm/adreno/a6xx_gpu_state.c:843:6: error: variable 'out' set but not used [-Werror,-Wunused-but-set-variable] The variable `out` in these functions is meant to compute the `target` of `CRASHDUMP_READ()`, but in this case only the initial value (`dumper->iova + A6XX_CD_DATA_OFFSET`) was being passed. Thus use `out` as it was intended by Connor [2]. There was an alternative patch at [3] that removed the variable altogether, but that would only use the initial value. Fixes: 64d6255650d4 ("drm/msm: More fully implement devcoredump for a7xx") Closes: https://lore.kernel.org/lkml/CANiq72mjc5t4n25SQvYSrOEhxxpXYPZ4pPzneSJHEnc3qApu2Q@mail.gmail.com/ [1] Link: https://lore.kernel.org/lkml/CACu1E7HhCKMJd6fixZSPiNAz6ekoZnkMTHTcLFVmbZ-9VoLxKg@mail.gmail.com/ [2] Link: https://lore.kernel.org/lkml/20240307093727.1978126-1-colin.i.king@gmail.com/ [3] Signed-off-by: Miguel Ojeda Reviewed-by: Abhinav Kumar Patchwork: https://patchwork.freedesktop.org/patch/584955/ Signed-off-by: Rob Clark --- drivers/gpu/drm/msm/adreno/a6xx_gpu_state.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gpu_state.c b/drivers/gpu/drm/msm/adreno/a6xx_gpu_state.c index 1f5245fc2cdc..a847a0f7a73c 100644 --- a/drivers/gpu/drm/msm/adreno/a6xx_gpu_state.c +++ b/drivers/gpu/drm/msm/adreno/a6xx_gpu_state.c @@ -852,7 +852,7 @@ static void a6xx_get_shader_block(struct msm_gpu *gpu, (block->type << 8) | i); in += CRASHDUMP_READ(in, REG_A6XX_HLSQ_DBG_AHB_READ_APERTURE, - block->size, dumper->iova + A6XX_CD_DATA_OFFSET); + block->size, out); out += block->size * sizeof(u32); } -- cgit v1.2.3 From 9dc23cba0927d09cb481da064c8413eb9df42e2b Mon Sep 17 00:00:00 2001 From: Luca Weiss Date: Thu, 28 Mar 2024 09:02:45 +0100 Subject: drm/msm/adreno: Set highest_bank_bit for A619 The default highest_bank_bit of 15 didn't seem to cause issues so far but downstream defines it to be 14. But similar to [0] leaving it on 14 (or 15 for that matter) causes some corruption issues with some resolutions with DisplayPort, like 1920x1200. So set it to 13 for now so that there's no screen corruption. [0] commit 6a0dbcd20ef2 ("drm/msm/a6xx: set highest_bank_bit to 13 for a610") Fixes: b7616b5c69e6 ("drm/msm/adreno: Add A619 support") Signed-off-by: Luca Weiss Patchwork: https://patchwork.freedesktop.org/patch/585215/ Signed-off-by: Rob Clark --- drivers/gpu/drm/msm/adreno/a6xx_gpu.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c index 0674aca0f8a3..cf0b1de1c071 100644 --- a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c +++ b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c @@ -1377,6 +1377,10 @@ static void a6xx_calc_ubwc_config(struct adreno_gpu *gpu) if (adreno_is_a618(gpu)) gpu->ubwc_config.highest_bank_bit = 14; + if (adreno_is_a619(gpu)) + /* TODO: Should be 14 but causes corruption at e.g. 1920x1200 on DP */ + gpu->ubwc_config.highest_bank_bit = 13; + if (adreno_is_a619_holi(gpu)) gpu->ubwc_config.highest_bank_bit = 13; -- cgit v1.2.3 From a6c4162d844dae4dbfea1bf9ecffcb852d3ed615 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Fri, 5 Apr 2024 18:01:02 +0300 Subject: bcachefs: fix ! vs ~ typo in __clear_bit_le64() The ! was obviously intended to be ~. As it is, this function does the equivalent to: "addr[bit / 64] = 0;". Fixes: 27fcec6c27ca ("bcachefs: Clear recovery_passes_required as they complete without errors") Signed-off-by: Dan Carpenter Signed-off-by: Kent Overstreet --- fs/bcachefs/util.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/bcachefs/util.h b/fs/bcachefs/util.h index b7e7c29278fc..de639e8a3ab5 100644 --- a/fs/bcachefs/util.h +++ b/fs/bcachefs/util.h @@ -795,7 +795,7 @@ static inline void __set_bit_le64(size_t bit, __le64 *addr) static inline void __clear_bit_le64(size_t bit, __le64 *addr) { - addr[bit / 64] &= !cpu_to_le64(BIT_ULL(bit % 64)); + addr[bit / 64] &= ~cpu_to_le64(BIT_ULL(bit % 64)); } static inline bool test_bit_le64(size_t bit, __le64 *addr) -- cgit v1.2.3 From cf979fca9a05d7d0b116257e5c4dc12b6bb7eb3a Mon Sep 17 00:00:00 2001 From: Kent Overstreet Date: Fri, 5 Apr 2024 16:21:18 -0400 Subject: bcachefs: fix rand_delete unit test Signed-off-by: Kent Overstreet --- fs/bcachefs/tests.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/bcachefs/tests.c b/fs/bcachefs/tests.c index b3fe9fc57747..bfec656f94c0 100644 --- a/fs/bcachefs/tests.c +++ b/fs/bcachefs/tests.c @@ -672,7 +672,7 @@ static int __do_delete(struct btree_trans *trans, struct bpos pos) bch2_trans_iter_init(trans, &iter, BTREE_ID_xattrs, pos, BTREE_ITER_INTENT); - k = bch2_btree_iter_peek(&iter); + k = bch2_btree_iter_peek_upto(&iter, POS(0, U64_MAX)); ret = bkey_err(k); if (ret) goto err; -- cgit v1.2.3 From 97a54ef596c3fd24ec2b227ba8aaf2cf5415e779 Mon Sep 17 00:00:00 2001 From: Maurizio Lombardi Date: Thu, 15 Feb 2024 15:39:43 +0100 Subject: scsi: target: Fix SELinux error when systemd-modules loads the target module If the systemd-modules service loads the target module, the credentials of that userspace process will be used to validate the access to the target db directory. SELinux will prevent it, reporting an error like the following: kernel: audit: type=1400 audit(1676301082.205:4): avc: denied { read } for pid=1020 comm="systemd-modules" name="target" dev="dm-3" ino=4657583 scontext=system_u:system_r:systemd_modules_load_t:s0 tcontext=system_u:object_r:targetd_etc_rw_t:s0 tclass=dir permissive=0 Fix the error by using the kernel credentials to access the db directory Signed-off-by: Maurizio Lombardi Link: https://lore.kernel.org/r/20240215143944.847184-2-mlombard@redhat.com Reviewed-by: Mike Christie Signed-off-by: Martin K. Petersen --- drivers/target/target_core_configfs.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/drivers/target/target_core_configfs.c b/drivers/target/target_core_configfs.c index c1fbcdd16182..c40217f44b1b 100644 --- a/drivers/target/target_core_configfs.c +++ b/drivers/target/target_core_configfs.c @@ -3672,6 +3672,8 @@ static int __init target_core_init_configfs(void) { struct configfs_subsystem *subsys = &target_core_fabrics; struct t10_alua_lu_gp *lu_gp; + struct cred *kern_cred; + const struct cred *old_cred; int ret; pr_debug("TARGET_CORE[0]: Loading Generic Kernel Storage" @@ -3748,11 +3750,21 @@ static int __init target_core_init_configfs(void) if (ret < 0) goto out; + /* We use the kernel credentials to access the target directory */ + kern_cred = prepare_kernel_cred(&init_task); + if (!kern_cred) { + ret = -ENOMEM; + goto out; + } + old_cred = override_creds(kern_cred); target_init_dbroot(); + revert_creds(old_cred); + put_cred(kern_cred); return 0; out: + target_xcopy_release_pt(); configfs_unregister_subsystem(subsys); core_dev_release_virtual_lun0(); rd_module_exit(); -- cgit v1.2.3 From 358e919a351f2ea4b412e7dac6b1c23ec10bd4f5 Mon Sep 17 00:00:00 2001 From: Xiang Chen Date: Tue, 2 Apr 2024 11:55:12 +0800 Subject: scsi: hisi_sas: Handle the NCQ error returned by D2H frame We find that some disks use D2H frame instead of SDB frame to return NCQ error. Currently, only the I/O corresponding to the D2H frame is processed in this scenario, which does not meet the processing requirements of the NCQ error scenario. So we set dev_status to HISI_SAS_DEV_NCQ_ERR and abort all I/Os of the disk in this scenario. Co-developed-by: Xingui Yang Signed-off-by: Xingui Yang Signed-off-by: Xiang Chen Link: https://lore.kernel.org/r/20240402035513.2024241-2-chenxiang66@hisilicon.com Signed-off-by: Martin K. Petersen --- drivers/scsi/hisi_sas/hisi_sas_v3_hw.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c index 7d2a33514538..34f96cc35342 100644 --- a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c +++ b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c @@ -2244,7 +2244,15 @@ slot_err_v3_hw(struct hisi_hba *hisi_hba, struct sas_task *task, case SAS_PROTOCOL_SATA | SAS_PROTOCOL_STP: if ((dw0 & CMPLT_HDR_RSPNS_XFRD_MSK) && (sipc_rx_err_type & RX_FIS_STATUS_ERR_MSK)) { - ts->stat = SAS_PROTO_RESPONSE; + if (task->ata_task.use_ncq) { + struct domain_device *device = task->dev; + struct hisi_sas_device *sas_dev = device->lldd_dev; + + sas_dev->dev_status = HISI_SAS_DEV_NCQ_ERR; + slot->abort = 1; + } else { + ts->stat = SAS_PROTO_RESPONSE; + } } else if (dma_rx_err_type & RX_DATA_LEN_UNDERFLOW_MSK) { ts->residual = trans_tx_fail_type; ts->stat = SAS_DATA_UNDERRUN; -- cgit v1.2.3 From 0098c55e0881f0b32591f2110410d5c8b7f9bd5a Mon Sep 17 00:00:00 2001 From: Xiang Chen Date: Tue, 2 Apr 2024 11:55:13 +0800 Subject: scsi: hisi_sas: Modify the deadline for ata_wait_after_reset() We found that the second parameter of function ata_wait_after_reset() is incorrectly used. We call smp_ata_check_ready_type() to poll the device type until the 30s timeout, so the correct deadline should be (jiffies + 30000). Fixes: 3c2673a09cf1 ("scsi: hisi_sas: Fix SATA devices missing issue during I_T nexus reset") Co-developed-by: xiabing Signed-off-by: xiabing Co-developed-by: Yihang Li Signed-off-by: Yihang Li Signed-off-by: Xiang Chen Link: https://lore.kernel.org/r/20240402035513.2024241-3-chenxiang66@hisilicon.com Signed-off-by: Martin K. Petersen --- drivers/scsi/hisi_sas/hisi_sas_main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/scsi/hisi_sas/hisi_sas_main.c b/drivers/scsi/hisi_sas/hisi_sas_main.c index 097dfe4b620d..35f8e00850d6 100644 --- a/drivers/scsi/hisi_sas/hisi_sas_main.c +++ b/drivers/scsi/hisi_sas/hisi_sas_main.c @@ -1797,7 +1797,7 @@ static int hisi_sas_debug_I_T_nexus_reset(struct domain_device *device) if (dev_is_sata(device)) { struct ata_link *link = &device->sata_dev.ap->link; - rc = ata_wait_after_reset(link, HISI_SAS_WAIT_PHYUP_TIMEOUT, + rc = ata_wait_after_reset(link, jiffies + HISI_SAS_WAIT_PHYUP_TIMEOUT, smp_ata_check_ready_type); } else { msleep(2000); -- cgit v1.2.3 From 4406e4176f47177f5e51b4cc7e6a7a2ff3dbfbbd Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Tue, 2 Apr 2024 12:56:54 +0300 Subject: scsi: qla2xxx: Fix off by one in qla_edif_app_getstats() The app_reply->elem[] array is allocated earlier in this function and it has app_req.num_ports elements. Thus this > comparison needs to be >= to prevent memory corruption. Fixes: 7878f22a2e03 ("scsi: qla2xxx: edif: Add getfcinfo and statistic bsgs") Signed-off-by: Dan Carpenter Link: https://lore.kernel.org/r/5c125b2f-92dd-412b-9b6f-fc3a3207bd60@moroto.mountain Reviewed-by: Himanshu Madhani Signed-off-by: Martin K. Petersen --- drivers/scsi/qla2xxx/qla_edif.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/scsi/qla2xxx/qla_edif.c b/drivers/scsi/qla2xxx/qla_edif.c index 26e6b3e3af43..dcde55c8ee5d 100644 --- a/drivers/scsi/qla2xxx/qla_edif.c +++ b/drivers/scsi/qla2xxx/qla_edif.c @@ -1100,7 +1100,7 @@ qla_edif_app_getstats(scsi_qla_host_t *vha, struct bsg_job *bsg_job) list_for_each_entry_safe(fcport, tf, &vha->vp_fcports, list) { if (fcport->edif.enable) { - if (pcnt > app_req.num_ports) + if (pcnt >= app_req.num_ports) break; app_reply->elem[pcnt].rekey_count = -- cgit v1.2.3 From 978e5c19dfefc271e5550efba92fcef0d3f62864 Mon Sep 17 00:00:00 2001 From: Alexey Izbyshev Date: Fri, 5 Apr 2024 15:55:51 +0300 Subject: io_uring: Fix io_cqring_wait() not restoring sigmask on get_timespec64() failure This bug was introduced in commit 950e79dd7313 ("io_uring: minor io_cqring_wait() optimization"), which was made in preparation for adc8682ec690 ("io_uring: Add support for napi_busy_poll"). The latter got reverted in cb3182167325 ("Revert "io_uring: Add support for napi_busy_poll""), so simply undo the former as well. Cc: stable@vger.kernel.org Fixes: 950e79dd7313 ("io_uring: minor io_cqring_wait() optimization") Signed-off-by: Alexey Izbyshev Link: https://lore.kernel.org/r/20240405125551.237142-1-izbyshev@ispras.ru Signed-off-by: Jens Axboe --- io_uring/io_uring.c | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/io_uring/io_uring.c b/io_uring/io_uring.c index 4521c2b66b98..c170a2b8d2cf 100644 --- a/io_uring/io_uring.c +++ b/io_uring/io_uring.c @@ -2602,19 +2602,6 @@ static int io_cqring_wait(struct io_ring_ctx *ctx, int min_events, if (__io_cqring_events_user(ctx) >= min_events) return 0; - if (sig) { -#ifdef CONFIG_COMPAT - if (in_compat_syscall()) - ret = set_compat_user_sigmask((const compat_sigset_t __user *)sig, - sigsz); - else -#endif - ret = set_user_sigmask(sig, sigsz); - - if (ret) - return ret; - } - init_waitqueue_func_entry(&iowq.wq, io_wake_function); iowq.wq.private = current; INIT_LIST_HEAD(&iowq.wq.entry); @@ -2633,6 +2620,19 @@ static int io_cqring_wait(struct io_ring_ctx *ctx, int min_events, io_napi_adjust_timeout(ctx, &iowq, &ts); } + if (sig) { +#ifdef CONFIG_COMPAT + if (in_compat_syscall()) + ret = set_compat_user_sigmask((const compat_sigset_t __user *)sig, + sigsz); + else +#endif + ret = set_user_sigmask(sig, sigsz); + + if (ret) + return ret; + } + io_napi_busy_loop(ctx, &iowq); trace_io_uring_cqring_wait(ctx, min_events); -- cgit v1.2.3 From beaa51b36012fad5a4d3c18b88a617aea7a9b96d Mon Sep 17 00:00:00 2001 From: Rik van Riel Date: Thu, 4 Apr 2024 12:32:53 -0400 Subject: blk-iocost: avoid out of bounds shift UBSAN catches undefined behavior in blk-iocost, where sometimes iocg->delay is shifted right by a number that is too large, resulting in undefined behavior on some architectures. [ 186.556576] ------------[ cut here ]------------ UBSAN: shift-out-of-bounds in block/blk-iocost.c:1366:23 shift exponent 64 is too large for 64-bit type 'u64' (aka 'unsigned long long') CPU: 16 PID: 0 Comm: swapper/16 Tainted: G S E N 6.9.0-0_fbk700_debug_rc2_kbuilder_0_gc85af715cac0 #1 Hardware name: Quanta Twin Lakes MP/Twin Lakes Passive MP, BIOS F09_3A23 12/08/2020 Call Trace: dump_stack_lvl+0x8f/0xe0 __ubsan_handle_shift_out_of_bounds+0x22c/0x280 iocg_kick_delay+0x30b/0x310 ioc_timer_fn+0x2fb/0x1f80 __run_timer_base+0x1b6/0x250 ... Avoid that undefined behavior by simply taking the "delay = 0" branch if the shift is too large. I am not sure what the symptoms of an undefined value delay will be, but I suspect it could be more than a little annoying to debug. Signed-off-by: Rik van Riel Cc: Tejun Heo Cc: Josef Bacik Cc: Jens Axboe Acked-by: Tejun Heo Link: https://lore.kernel.org/r/20240404123253.0f58010f@imladris.surriel.com Signed-off-by: Jens Axboe --- block/blk-iocost.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/block/blk-iocost.c b/block/blk-iocost.c index 9a85bfbbc45a..baa20c85799d 100644 --- a/block/blk-iocost.c +++ b/block/blk-iocost.c @@ -1347,7 +1347,7 @@ static bool iocg_kick_delay(struct ioc_gq *iocg, struct ioc_now *now) { struct ioc *ioc = iocg->ioc; struct blkcg_gq *blkg = iocg_to_blkg(iocg); - u64 tdelta, delay, new_delay; + u64 tdelta, delay, new_delay, shift; s64 vover, vover_pct; u32 hwa; @@ -1362,8 +1362,9 @@ static bool iocg_kick_delay(struct ioc_gq *iocg, struct ioc_now *now) /* calculate the current delay in effect - 1/2 every second */ tdelta = now->now - iocg->delay_at; - if (iocg->delay) - delay = iocg->delay >> div64_u64(tdelta, USEC_PER_SEC); + shift = div64_u64(tdelta, USEC_PER_SEC); + if (iocg->delay && shift < BITS_PER_LONG) + delay = iocg->delay >> shift; else delay = 0; -- cgit v1.2.3 From 4539f91f2a801c0c028c252bffae56030cfb2cae Mon Sep 17 00:00:00 2001 From: Ilya Maximets Date: Wed, 3 Apr 2024 22:38:01 +0200 Subject: net: openvswitch: fix unwanted error log on timeout policy probing On startup, ovs-vswitchd probes different datapath features including support for timeout policies. While probing, it tries to execute certain operations with OVS_PACKET_ATTR_PROBE or OVS_FLOW_ATTR_PROBE attributes set. These attributes tell the openvswitch module to not log any errors when they occur as it is expected that some of the probes will fail. For some reason, setting the timeout policy ignores the PROBE attribute and logs a failure anyway. This is causing the following kernel log on each re-start of ovs-vswitchd: kernel: Failed to associated timeout policy `ovs_test_tp' Fix that by using the same logging macro that all other messages are using. The message will still be printed at info level when needed and will be rate limited, but with a net rate limiter instead of generic printk one. The nf_ct_set_timeout() itself will still print some info messages, but at least this change makes logging in openvswitch module more consistent. Fixes: 06bd2bdf19d2 ("openvswitch: Add timeout support to ct action") Signed-off-by: Ilya Maximets Acked-by: Eelco Chaudron Link: https://lore.kernel.org/r/20240403203803.2137962-1-i.maximets@ovn.org Signed-off-by: Jakub Kicinski --- net/openvswitch/conntrack.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/net/openvswitch/conntrack.c b/net/openvswitch/conntrack.c index 3019a4406ca4..74b63cdb5992 100644 --- a/net/openvswitch/conntrack.c +++ b/net/openvswitch/conntrack.c @@ -1380,8 +1380,9 @@ int ovs_ct_copy_action(struct net *net, const struct nlattr *attr, if (ct_info.timeout[0]) { if (nf_ct_set_timeout(net, ct_info.ct, family, key->ip.proto, ct_info.timeout)) - pr_info_ratelimited("Failed to associated timeout " - "policy `%s'\n", ct_info.timeout); + OVS_NLERR(log, + "Failed to associated timeout policy '%s'", + ct_info.timeout); else ct_info.nf_ct_timeout = rcu_dereference( nf_ct_timeout_find(ct_info.ct)->timeout); -- cgit v1.2.3 From 38a15d0a50e0a43778561a5861403851f0b0194c Mon Sep 17 00:00:00 2001 From: Petr Tesarik Date: Thu, 4 Apr 2024 09:57:40 +0200 Subject: u64_stats: fix u64_stats_init() for lockdep when used repeatedly in one file Fix bogus lockdep warnings if multiple u64_stats_sync variables are initialized in the same file. With CONFIG_LOCKDEP, seqcount_init() is a macro which declares: static struct lock_class_key __key; Since u64_stats_init() is a function (albeit an inline one), all calls within the same file end up using the same instance, effectively treating them all as a single lock-class. Fixes: 9464ca650008 ("net: make u64_stats_init() a function") Closes: https://lore.kernel.org/netdev/ea1567d9-ce66-45e6-8168-ac40a47d1821@roeck-us.net/ Signed-off-by: Petr Tesarik Reviewed-by: Simon Horman Reviewed-by: Eric Dumazet Link: https://lore.kernel.org/r/20240404075740.30682-1-petr@tesarici.cz Signed-off-by: Jakub Kicinski --- include/linux/u64_stats_sync.h | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/include/linux/u64_stats_sync.h b/include/linux/u64_stats_sync.h index ffe48e69b3f3..457879938fc1 100644 --- a/include/linux/u64_stats_sync.h +++ b/include/linux/u64_stats_sync.h @@ -135,10 +135,11 @@ static inline void u64_stats_inc(u64_stats_t *p) p->v++; } -static inline void u64_stats_init(struct u64_stats_sync *syncp) -{ - seqcount_init(&syncp->seq); -} +#define u64_stats_init(syncp) \ + do { \ + struct u64_stats_sync *__s = (syncp); \ + seqcount_init(&__s->seq); \ + } while (0) static inline void __u64_stats_update_begin(struct u64_stats_sync *syncp) { -- cgit v1.2.3 From 237f3cf13b20db183d3706d997eedc3c49eacd44 Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Thu, 4 Apr 2024 20:27:38 +0000 Subject: xsk: validate user input for XDP_{UMEM|COMPLETION}_FILL_RING MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit syzbot reported an illegal copy in xsk_setsockopt() [1] Make sure to validate setsockopt() @optlen parameter. [1] BUG: KASAN: slab-out-of-bounds in copy_from_sockptr_offset include/linux/sockptr.h:49 [inline] BUG: KASAN: slab-out-of-bounds in copy_from_sockptr include/linux/sockptr.h:55 [inline] BUG: KASAN: slab-out-of-bounds in xsk_setsockopt+0x909/0xa40 net/xdp/xsk.c:1420 Read of size 4 at addr ffff888028c6cde3 by task syz-executor.0/7549 CPU: 0 PID: 7549 Comm: syz-executor.0 Not tainted 6.8.0-syzkaller-08951-gfe46a7dd189e #0 Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 03/27/2024 Call Trace: __dump_stack lib/dump_stack.c:88 [inline] dump_stack_lvl+0x241/0x360 lib/dump_stack.c:114 print_address_description mm/kasan/report.c:377 [inline] print_report+0x169/0x550 mm/kasan/report.c:488 kasan_report+0x143/0x180 mm/kasan/report.c:601 copy_from_sockptr_offset include/linux/sockptr.h:49 [inline] copy_from_sockptr include/linux/sockptr.h:55 [inline] xsk_setsockopt+0x909/0xa40 net/xdp/xsk.c:1420 do_sock_setsockopt+0x3af/0x720 net/socket.c:2311 __sys_setsockopt+0x1ae/0x250 net/socket.c:2334 __do_sys_setsockopt net/socket.c:2343 [inline] __se_sys_setsockopt net/socket.c:2340 [inline] __x64_sys_setsockopt+0xb5/0xd0 net/socket.c:2340 do_syscall_64+0xfb/0x240 entry_SYSCALL_64_after_hwframe+0x6d/0x75 RIP: 0033:0x7fb40587de69 Code: 28 00 00 00 75 05 48 83 c4 28 c3 e8 e1 20 00 00 90 48 89 f8 48 89 f7 48 89 d6 48 89 ca 4d 89 c2 4d 89 c8 4c 8b 4c 24 08 0f 05 <48> 3d 01 f0 ff ff 73 01 c3 48 c7 c1 b0 ff ff ff f7 d8 64 89 01 48 RSP: 002b:00007fb40665a0c8 EFLAGS: 00000246 ORIG_RAX: 0000000000000036 RAX: ffffffffffffffda RBX: 00007fb4059abf80 RCX: 00007fb40587de69 RDX: 0000000000000005 RSI: 000000000000011b RDI: 0000000000000006 RBP: 00007fb4058ca47a R08: 0000000000000002 R09: 0000000000000000 R10: 0000000020001980 R11: 0000000000000246 R12: 0000000000000000 R13: 000000000000000b R14: 00007fb4059abf80 R15: 00007fff57ee4d08 Allocated by task 7549: kasan_save_stack mm/kasan/common.c:47 [inline] kasan_save_track+0x3f/0x80 mm/kasan/common.c:68 poison_kmalloc_redzone mm/kasan/common.c:370 [inline] __kasan_kmalloc+0x98/0xb0 mm/kasan/common.c:387 kasan_kmalloc include/linux/kasan.h:211 [inline] __do_kmalloc_node mm/slub.c:3966 [inline] __kmalloc+0x233/0x4a0 mm/slub.c:3979 kmalloc include/linux/slab.h:632 [inline] __cgroup_bpf_run_filter_setsockopt+0xd2f/0x1040 kernel/bpf/cgroup.c:1869 do_sock_setsockopt+0x6b4/0x720 net/socket.c:2293 __sys_setsockopt+0x1ae/0x250 net/socket.c:2334 __do_sys_setsockopt net/socket.c:2343 [inline] __se_sys_setsockopt net/socket.c:2340 [inline] __x64_sys_setsockopt+0xb5/0xd0 net/socket.c:2340 do_syscall_64+0xfb/0x240 entry_SYSCALL_64_after_hwframe+0x6d/0x75 The buggy address belongs to the object at ffff888028c6cde0 which belongs to the cache kmalloc-8 of size 8 The buggy address is located 1 bytes to the right of allocated 2-byte region [ffff888028c6cde0, ffff888028c6cde2) The buggy address belongs to the physical page: page:ffffea0000a31b00 refcount:1 mapcount:0 mapping:0000000000000000 index:0xffff888028c6c9c0 pfn:0x28c6c anon flags: 0xfff00000000800(slab|node=0|zone=1|lastcpupid=0x7ff) page_type: 0xffffffff() raw: 00fff00000000800 ffff888014c41280 0000000000000000 dead000000000001 raw: ffff888028c6c9c0 0000000080800057 00000001ffffffff 0000000000000000 page dumped because: kasan: bad access detected page_owner tracks the page as allocated page last allocated via order 0, migratetype Unmovable, gfp_mask 0x112cc0(GFP_USER|__GFP_NOWARN|__GFP_NORETRY), pid 6648, tgid 6644 (syz-executor.0), ts 133906047828, free_ts 133859922223 set_page_owner include/linux/page_owner.h:31 [inline] post_alloc_hook+0x1ea/0x210 mm/page_alloc.c:1533 prep_new_page mm/page_alloc.c:1540 [inline] get_page_from_freelist+0x33ea/0x3580 mm/page_alloc.c:3311 __alloc_pages+0x256/0x680 mm/page_alloc.c:4569 __alloc_pages_node include/linux/gfp.h:238 [inline] alloc_pages_node include/linux/gfp.h:261 [inline] alloc_slab_page+0x5f/0x160 mm/slub.c:2175 allocate_slab mm/slub.c:2338 [inline] new_slab+0x84/0x2f0 mm/slub.c:2391 ___slab_alloc+0xc73/0x1260 mm/slub.c:3525 __slab_alloc mm/slub.c:3610 [inline] __slab_alloc_node mm/slub.c:3663 [inline] slab_alloc_node mm/slub.c:3835 [inline] __do_kmalloc_node mm/slub.c:3965 [inline] __kmalloc_node+0x2db/0x4e0 mm/slub.c:3973 kmalloc_node include/linux/slab.h:648 [inline] __vmalloc_area_node mm/vmalloc.c:3197 [inline] __vmalloc_node_range+0x5f9/0x14a0 mm/vmalloc.c:3392 __vmalloc_node mm/vmalloc.c:3457 [inline] vzalloc+0x79/0x90 mm/vmalloc.c:3530 bpf_check+0x260/0x19010 kernel/bpf/verifier.c:21162 bpf_prog_load+0x1667/0x20f0 kernel/bpf/syscall.c:2895 __sys_bpf+0x4ee/0x810 kernel/bpf/syscall.c:5631 __do_sys_bpf kernel/bpf/syscall.c:5738 [inline] __se_sys_bpf kernel/bpf/syscall.c:5736 [inline] __x64_sys_bpf+0x7c/0x90 kernel/bpf/syscall.c:5736 do_syscall_64+0xfb/0x240 entry_SYSCALL_64_after_hwframe+0x6d/0x75 page last free pid 6650 tgid 6647 stack trace: reset_page_owner include/linux/page_owner.h:24 [inline] free_pages_prepare mm/page_alloc.c:1140 [inline] free_unref_page_prepare+0x95d/0xa80 mm/page_alloc.c:2346 free_unref_page_list+0x5a3/0x850 mm/page_alloc.c:2532 release_pages+0x2117/0x2400 mm/swap.c:1042 tlb_batch_pages_flush mm/mmu_gather.c:98 [inline] tlb_flush_mmu_free mm/mmu_gather.c:293 [inline] tlb_flush_mmu+0x34d/0x4e0 mm/mmu_gather.c:300 tlb_finish_mmu+0xd4/0x200 mm/mmu_gather.c:392 exit_mmap+0x4b6/0xd40 mm/mmap.c:3300 __mmput+0x115/0x3c0 kernel/fork.c:1345 exit_mm+0x220/0x310 kernel/exit.c:569 do_exit+0x99e/0x27e0 kernel/exit.c:865 do_group_exit+0x207/0x2c0 kernel/exit.c:1027 get_signal+0x176e/0x1850 kernel/signal.c:2907 arch_do_signal_or_restart+0x96/0x860 arch/x86/kernel/signal.c:310 exit_to_user_mode_loop kernel/entry/common.c:105 [inline] exit_to_user_mode_prepare include/linux/entry-common.h:328 [inline] __syscall_exit_to_user_mode_work kernel/entry/common.c:201 [inline] syscall_exit_to_user_mode+0xc9/0x360 kernel/entry/common.c:212 do_syscall_64+0x10a/0x240 arch/x86/entry/common.c:89 entry_SYSCALL_64_after_hwframe+0x6d/0x75 Memory state around the buggy address: ffff888028c6cc80: fa fc fc fc fa fc fc fc fa fc fc fc fa fc fc fc ffff888028c6cd00: fa fc fc fc fa fc fc fc 00 fc fc fc 06 fc fc fc >ffff888028c6cd80: fa fc fc fc fa fc fc fc fa fc fc fc 02 fc fc fc ^ ffff888028c6ce00: fa fc fc fc fa fc fc fc fa fc fc fc fa fc fc fc ffff888028c6ce80: fa fc fc fc fa fc fc fc fa fc fc fc fa fc fc fc Fixes: 423f38329d26 ("xsk: add umem fill queue support and mmap") Reported-by: syzbot Signed-off-by: Eric Dumazet Cc: "Björn Töpel" Cc: Magnus Karlsson Cc: Maciej Fijalkowski Cc: Jonathan Lemon Acked-by: Daniel Borkmann Link: https://lore.kernel.org/r/20240404202738.3634547-1-edumazet@google.com Signed-off-by: Jakub Kicinski --- net/xdp/xsk.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/net/xdp/xsk.c b/net/xdp/xsk.c index 3404d076a8a3..727aa20be4bd 100644 --- a/net/xdp/xsk.c +++ b/net/xdp/xsk.c @@ -1417,6 +1417,8 @@ static int xsk_setsockopt(struct socket *sock, int level, int optname, struct xsk_queue **q; int entries; + if (optlen < sizeof(entries)) + return -EINVAL; if (copy_from_sockptr(&entries, optval, sizeof(entries))) return -EFAULT; -- cgit v1.2.3 From 374b3d38feff4a1cb4ecadace9bd915ffd91fe4b Mon Sep 17 00:00:00 2001 From: Kent Overstreet Date: Fri, 5 Apr 2024 22:23:29 -0400 Subject: bcachefs: Fix BCH_IOCTL_FSCK_OFFLINE for encrypted filesystems To open an encrypted filesystem, we use request_key() to get the encryption key from the user's keyring - but request_key() needs to happen in the context of the process that invoked the ioctl. This easily fixed by using bch2_fs_open() in nostart mode. Signed-off-by: Kent Overstreet --- fs/bcachefs/chardev.c | 94 +++++++++++++++++++++++++++------------------------ 1 file changed, 50 insertions(+), 44 deletions(-) diff --git a/fs/bcachefs/chardev.c b/fs/bcachefs/chardev.c index cbfa6459bdbc..1e033df330b0 100644 --- a/fs/bcachefs/chardev.c +++ b/fs/bcachefs/chardev.c @@ -134,42 +134,38 @@ static long bch2_ioctl_incremental(struct bch_ioctl_incremental __user *user_arg struct fsck_thread { struct thread_with_stdio thr; struct bch_fs *c; - char **devs; - size_t nr_devs; struct bch_opts opts; }; static void bch2_fsck_thread_exit(struct thread_with_stdio *_thr) { struct fsck_thread *thr = container_of(_thr, struct fsck_thread, thr); - if (thr->devs) - for (size_t i = 0; i < thr->nr_devs; i++) - kfree(thr->devs[i]); - kfree(thr->devs); kfree(thr); } static int bch2_fsck_offline_thread_fn(struct thread_with_stdio *stdio) { struct fsck_thread *thr = container_of(stdio, struct fsck_thread, thr); - struct bch_fs *c = bch2_fs_open(thr->devs, thr->nr_devs, thr->opts); - - if (IS_ERR(c)) - return PTR_ERR(c); + struct bch_fs *c = thr->c; - int ret = 0; - if (test_bit(BCH_FS_errors_fixed, &c->flags)) - ret |= 1; - if (test_bit(BCH_FS_error, &c->flags)) - ret |= 4; + int ret = PTR_ERR_OR_ZERO(c); + if (ret) + return ret; - bch2_fs_stop(c); + ret = bch2_fs_start(thr->c); + if (ret) + goto err; - if (ret & 1) + if (test_bit(BCH_FS_errors_fixed, &c->flags)) { bch2_stdio_redirect_printf(&stdio->stdio, false, "%s: errors fixed\n", c->name); - if (ret & 4) + ret |= 1; + } + if (test_bit(BCH_FS_error, &c->flags)) { bch2_stdio_redirect_printf(&stdio->stdio, false, "%s: still has errors\n", c->name); - + ret |= 4; + } +err: + bch2_fs_stop(c); return ret; } @@ -182,7 +178,7 @@ static long bch2_ioctl_fsck_offline(struct bch_ioctl_fsck_offline __user *user_a { struct bch_ioctl_fsck_offline arg; struct fsck_thread *thr = NULL; - u64 *devs = NULL; + darray_str(devs) = {}; long ret = 0; if (copy_from_user(&arg, user_arg, sizeof(arg))) @@ -194,29 +190,32 @@ static long bch2_ioctl_fsck_offline(struct bch_ioctl_fsck_offline __user *user_a if (!capable(CAP_SYS_ADMIN)) return -EPERM; - if (!(devs = kcalloc(arg.nr_devs, sizeof(*devs), GFP_KERNEL)) || - !(thr = kzalloc(sizeof(*thr), GFP_KERNEL)) || - !(thr->devs = kcalloc(arg.nr_devs, sizeof(*thr->devs), GFP_KERNEL))) { - ret = -ENOMEM; - goto err; - } + for (size_t i = 0; i < arg.nr_devs; i++) { + u64 dev_u64; + ret = copy_from_user_errcode(&dev_u64, &user_arg->devs[i], sizeof(u64)); + if (ret) + goto err; - thr->opts = bch2_opts_empty(); - thr->nr_devs = arg.nr_devs; + char *dev_str = strndup_user((char __user *)(unsigned long) dev_u64, PATH_MAX); + ret = PTR_ERR_OR_ZERO(dev_str); + if (ret) + goto err; - if (copy_from_user(devs, &user_arg->devs[0], - array_size(sizeof(user_arg->devs[0]), arg.nr_devs))) { - ret = -EINVAL; - goto err; + ret = darray_push(&devs, dev_str); + if (ret) { + kfree(dev_str); + goto err; + } } - for (size_t i = 0; i < arg.nr_devs; i++) { - thr->devs[i] = strndup_user((char __user *)(unsigned long) devs[i], PATH_MAX); - ret = PTR_ERR_OR_ZERO(thr->devs[i]); - if (ret) - goto err; + thr = kzalloc(sizeof(*thr), GFP_KERNEL); + if (!thr) { + ret = -ENOMEM; + goto err; } + thr->opts = bch2_opts_empty(); + if (arg.opts) { char *optstr = strndup_user((char __user *)(unsigned long) arg.opts, 1 << 16); @@ -230,15 +229,22 @@ static long bch2_ioctl_fsck_offline(struct bch_ioctl_fsck_offline __user *user_a opt_set(thr->opts, stdio, (u64)(unsigned long)&thr->thr.stdio); + /* We need request_key() to be called before we punt to kthread: */ + opt_set(thr->opts, nostart, true); + + thr->c = bch2_fs_open(devs.data, arg.nr_devs, thr->opts); + ret = bch2_run_thread_with_stdio(&thr->thr, &bch2_offline_fsck_ops); -err: - if (ret < 0) { - if (thr) - bch2_fsck_thread_exit(&thr->thr); - pr_err("ret %s", bch2_err_str(ret)); - } - kfree(devs); +out: + darray_for_each(devs, i) + kfree(*i); + darray_exit(&devs); return ret; +err: + if (thr) + bch2_fsck_thread_exit(&thr->thr); + pr_err("ret %s", bch2_err_str(ret)); + goto out; } static long bch2_global_ioctl(unsigned cmd, void __user *arg) -- cgit v1.2.3 From 05801b6526156aefe55c0440fab877109c9a89c5 Mon Sep 17 00:00:00 2001 From: Kent Overstreet Date: Fri, 5 Apr 2024 22:30:30 -0400 Subject: bcachefs: Disable errors=panic for BCH_IOCTL_FSCK_OFFLINE BCH_IOCTL_FSCK_OFFLINE allows the userspace fsck tool to use the kernel implementation of fsck - primarily when the kernel version is a better version match. It should look and act exactly like the normal userspace fsck that the user expected to be invoking, so errors should never result in a kernel panic. We may want to consider further restricting errors=panic - it's only intended for debugging in controlled test environments, it should have no purpose it normal usage. Signed-off-by: Kent Overstreet --- fs/bcachefs/chardev.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/fs/bcachefs/chardev.c b/fs/bcachefs/chardev.c index 1e033df330b0..72781aad6ba7 100644 --- a/fs/bcachefs/chardev.c +++ b/fs/bcachefs/chardev.c @@ -234,6 +234,10 @@ static long bch2_ioctl_fsck_offline(struct bch_ioctl_fsck_offline __user *user_a thr->c = bch2_fs_open(devs.data, arg.nr_devs, thr->opts); + if (!IS_ERR(thr->c) && + thr->c->opts.errors == BCH_ON_ERROR_panic) + thr->c->opts.errors = BCH_ON_ERROR_ro; + ret = bch2_run_thread_with_stdio(&thr->thr, &bch2_offline_fsck_ops); out: darray_for_each(devs, i) -- cgit v1.2.3 From 6088234ce83acec4aaf56ecc0e9525bac18b4295 Mon Sep 17 00:00:00 2001 From: Kent Overstreet Date: Fri, 5 Apr 2024 23:27:27 -0400 Subject: bcachefs: JOURNAL_SPACE_LOW "bcachefs; Fix deadlock in bch2_btree_update_start()" was a significant performance regression (nearly 50%) on multithreaded random writes with fio. The reason is that the journal watermark checks multiple things, including the state of the btree write buffer, and on multithreaded update heavy workloads we're bottleneked on write buffer flushing - we don't want kicknig off btree updates to depend on the state of the write buffer. This isn't strictly correct; the interior btree update path does do write buffer updates, but it's a tiny fraction of total accounting updates and we're more concerned with space in the journal itself. Signed-off-by: Kent Overstreet --- fs/bcachefs/btree_key_cache.c | 2 +- fs/bcachefs/btree_update_interior.c | 18 +++++++----------- fs/bcachefs/journal_reclaim.c | 2 ++ fs/bcachefs/journal_types.h | 1 + fs/bcachefs/util.h | 8 ++++++++ 5 files changed, 19 insertions(+), 12 deletions(-) diff --git a/fs/bcachefs/btree_key_cache.c b/fs/bcachefs/btree_key_cache.c index 581edcb0911b..4ae7890f07c6 100644 --- a/fs/bcachefs/btree_key_cache.c +++ b/fs/bcachefs/btree_key_cache.c @@ -659,7 +659,7 @@ static int btree_key_cache_flush_pos(struct btree_trans *trans, commit_flags |= BCH_WATERMARK_reclaim; if (ck->journal.seq != journal_last_seq(j) || - j->watermark == BCH_WATERMARK_stripe) + !test_bit(JOURNAL_SPACE_LOW, &c->journal.flags)) commit_flags |= BCH_TRANS_COMMIT_no_journal_res; ret = bch2_btree_iter_traverse(&b_iter) ?: diff --git a/fs/bcachefs/btree_update_interior.c b/fs/bcachefs/btree_update_interior.c index 24fbd5be70a2..a4a63e363047 100644 --- a/fs/bcachefs/btree_update_interior.c +++ b/fs/bcachefs/btree_update_interior.c @@ -1125,18 +1125,14 @@ bch2_btree_update_start(struct btree_trans *trans, struct btree_path *path, flags &= ~BCH_WATERMARK_MASK; flags |= watermark; - if (watermark < c->journal.watermark) { - struct journal_res res = { 0 }; - unsigned journal_flags = watermark|JOURNAL_RES_GET_CHECK; + if (watermark < BCH_WATERMARK_reclaim && + test_bit(JOURNAL_SPACE_LOW, &c->journal.flags)) { + if (flags & BCH_TRANS_COMMIT_journal_reclaim) + return ERR_PTR(-BCH_ERR_journal_reclaim_would_deadlock); - if ((flags & BCH_TRANS_COMMIT_journal_reclaim) && - watermark < BCH_WATERMARK_reclaim) - journal_flags |= JOURNAL_RES_GET_NONBLOCK; - - ret = drop_locks_do(trans, - bch2_journal_res_get(&c->journal, &res, 1, journal_flags)); - if (bch2_err_matches(ret, BCH_ERR_operation_blocked)) - ret = -BCH_ERR_journal_reclaim_would_deadlock; + bch2_trans_unlock(trans); + wait_event(c->journal.wait, !test_bit(JOURNAL_SPACE_LOW, &c->journal.flags)); + ret = bch2_trans_relock(trans); if (ret) return ERR_PTR(ret); } diff --git a/fs/bcachefs/journal_reclaim.c b/fs/bcachefs/journal_reclaim.c index ab811c0dad26..04a577848b01 100644 --- a/fs/bcachefs/journal_reclaim.c +++ b/fs/bcachefs/journal_reclaim.c @@ -67,6 +67,8 @@ void bch2_journal_set_watermark(struct journal *j) track_event_change(&c->times[BCH_TIME_blocked_write_buffer_full], low_on_wb)) trace_and_count(c, journal_full, c); + mod_bit(JOURNAL_SPACE_LOW, &j->flags, low_on_space || low_on_pin); + swap(watermark, j->watermark); if (watermark > j->watermark) journal_wake(j); diff --git a/fs/bcachefs/journal_types.h b/fs/bcachefs/journal_types.h index 8c053cb64ca5..b5161b5d76a0 100644 --- a/fs/bcachefs/journal_types.h +++ b/fs/bcachefs/journal_types.h @@ -134,6 +134,7 @@ enum journal_flags { JOURNAL_STARTED, JOURNAL_MAY_SKIP_FLUSH, JOURNAL_NEED_FLUSH_WRITE, + JOURNAL_SPACE_LOW, }; /* Reasons we may fail to get a journal reservation: */ diff --git a/fs/bcachefs/util.h b/fs/bcachefs/util.h index de639e8a3ab5..5cf885b09986 100644 --- a/fs/bcachefs/util.h +++ b/fs/bcachefs/util.h @@ -788,6 +788,14 @@ static inline int copy_from_user_errcode(void *to, const void __user *from, unsi #endif +static inline void mod_bit(long nr, volatile unsigned long *addr, bool v) +{ + if (v) + set_bit(nr, addr); + else + clear_bit(nr, addr); +} + static inline void __set_bit_le64(size_t bit, __le64 *addr) { addr[bit / 64] |= cpu_to_le64(BIT_ULL(bit % 64)); -- cgit v1.2.3 From aa98e70fc6c97f39a7bd68cb1e641ca50d4f9423 Mon Sep 17 00:00:00 2001 From: Bagas Sanjaya Date: Fri, 5 Apr 2024 14:23:18 +0700 Subject: Documentation: filesystems: Add bcachefs toctree Commit eb386617be4bdf ("bcachefs: Errcode tracepoint, documentation") adds initial bcachefs documentation (private error codes) but without any table of contents tree for the filesystem docs, hence Sphinx warns: Documentation/filesystems/bcachefs/errorcodes.rst: WARNING: document isn't included in any toctree Add bcachefs toctree to fix above warning. Fixes: eb386617be4b ("bcachefs: Errcode tracepoint, documentation") Signed-off-by: Bagas Sanjaya Signed-off-by: Kent Overstreet --- Documentation/filesystems/bcachefs/index.rst | 11 +++++++++++ Documentation/filesystems/index.rst | 1 + 2 files changed, 12 insertions(+) create mode 100644 Documentation/filesystems/bcachefs/index.rst diff --git a/Documentation/filesystems/bcachefs/index.rst b/Documentation/filesystems/bcachefs/index.rst new file mode 100644 index 000000000000..e2bd61ccd96f --- /dev/null +++ b/Documentation/filesystems/bcachefs/index.rst @@ -0,0 +1,11 @@ +.. SPDX-License-Identifier: GPL-2.0 + +====================== +bcachefs Documentation +====================== + +.. toctree:: + :maxdepth: 2 + :numbered: + + errorcodes diff --git a/Documentation/filesystems/index.rst b/Documentation/filesystems/index.rst index 0ea1e44fa028..1f9b4c905a6a 100644 --- a/Documentation/filesystems/index.rst +++ b/Documentation/filesystems/index.rst @@ -69,6 +69,7 @@ Documentation for filesystem implementations. afs autofs autofs-mount-control + bcachefs/index befs bfs btrfs -- cgit v1.2.3 From 7d83cf53c77c8fdc0a8033e1472ac62745fac2ac Mon Sep 17 00:00:00 2001 From: Bagas Sanjaya Date: Fri, 5 Apr 2024 14:23:19 +0700 Subject: MAINTAINERS: Add entry for bcachefs documentation Now that bcachefs docs exist in Documentation/filesystems/bcachefs/, cover it in MAINTAINERS entry for the filesystem. Signed-off-by: Bagas Sanjaya Signed-off-by: Kent Overstreet --- MAINTAINERS | 1 + 1 file changed, 1 insertion(+) diff --git a/MAINTAINERS b/MAINTAINERS index 7c121493f43d..c0091a206fd2 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -3573,6 +3573,7 @@ S: Supported C: irc://irc.oftc.net/bcache T: git https://evilpiepirate.org/git/bcachefs.git F: fs/bcachefs/ +F: Documentation/filesystems/bcachefs/ BDISP ST MEDIA DRIVER M: Fabien Dessenne -- cgit v1.2.3 From 2d793e9315e335ef299024fe8bf7742c9c974b33 Mon Sep 17 00:00:00 2001 From: Thorsten Blum Date: Sat, 6 Apr 2024 16:19:20 +0200 Subject: bcachefs: Rename struct field swap to prevent macro naming collision The struct field swap can collide with the swap() macro defined in linux/minmax.h. Rename the struct field to prevent such collisions. Signed-off-by: Thorsten Blum Signed-off-by: Kent Overstreet --- fs/bcachefs/eytzinger.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/fs/bcachefs/eytzinger.c b/fs/bcachefs/eytzinger.c index 4ce5e957a6e9..0f955c3c76a7 100644 --- a/fs/bcachefs/eytzinger.c +++ b/fs/bcachefs/eytzinger.c @@ -115,7 +115,7 @@ static void swap_bytes(void *a, void *b, size_t n) struct wrapper { cmp_func_t cmp; - swap_func_t swap; + swap_func_t swap_func; }; /* @@ -125,7 +125,7 @@ struct wrapper { static void do_swap(void *a, void *b, size_t size, swap_r_func_t swap_func, const void *priv) { if (swap_func == SWAP_WRAPPER) { - ((const struct wrapper *)priv)->swap(a, b, (int)size); + ((const struct wrapper *)priv)->swap_func(a, b, (int)size); return; } @@ -174,7 +174,7 @@ void eytzinger0_sort_r(void *base, size_t n, size_t size, int i, c, r; /* called from 'sort' without swap function, let's pick the default */ - if (swap_func == SWAP_WRAPPER && !((struct wrapper *)priv)->swap) + if (swap_func == SWAP_WRAPPER && !((struct wrapper *)priv)->swap_func) swap_func = NULL; if (!swap_func) { @@ -227,7 +227,7 @@ void eytzinger0_sort(void *base, size_t n, size_t size, { struct wrapper w = { .cmp = cmp_func, - .swap = swap_func, + .swap_func = swap_func, }; return eytzinger0_sort_r(base, n, size, _CMP_WRAPPER, SWAP_WRAPPER, &w); -- cgit v1.2.3 From 30e615a2ce6601d85729caefd8ac15634f848e59 Mon Sep 17 00:00:00 2001 From: Kent Overstreet Date: Sat, 6 Apr 2024 21:45:46 -0400 Subject: bcachefs: Fix gap buffer bug in bch2_journal_key_insert_take() Multiple bug fixes for journal iters: - When the journal keys gap buffer is resized, we have to adjust the iterators for moving the gap to the end - We don't want to rewind iterators to point to the key we just inserted if it's not for the correct btree/level Also, add some new assertions. Signed-off-by: Kent Overstreet --- fs/bcachefs/btree_journal_iter.c | 55 ++++++++++++++++++++++++++++++++-------- 1 file changed, 45 insertions(+), 10 deletions(-) diff --git a/fs/bcachefs/btree_journal_iter.c b/fs/bcachefs/btree_journal_iter.c index 5cbcbfe85235..a6413a8747d3 100644 --- a/fs/bcachefs/btree_journal_iter.c +++ b/fs/bcachefs/btree_journal_iter.c @@ -130,12 +130,30 @@ struct bkey_i *bch2_journal_keys_peek_slot(struct bch_fs *c, enum btree_id btree return bch2_journal_keys_peek_upto(c, btree_id, level, pos, pos, &idx); } +static void journal_iter_verify(struct journal_iter *iter) +{ + struct journal_keys *keys = iter->keys; + size_t gap_size = keys->size - keys->nr; + + BUG_ON(iter->idx >= keys->gap && + iter->idx < keys->gap + gap_size); + + if (iter->idx < keys->size) { + struct journal_key *k = keys->data + iter->idx; + + int cmp = cmp_int(k->btree_id, iter->btree_id) ?: + cmp_int(k->level, iter->level); + BUG_ON(cmp < 0); + } +} + static void journal_iters_fix(struct bch_fs *c) { struct journal_keys *keys = &c->journal_keys; /* The key we just inserted is immediately before the gap: */ size_t gap_end = keys->gap + (keys->size - keys->nr); - struct btree_and_journal_iter *iter; + struct journal_key *new_key = &keys->data[keys->gap - 1]; + struct journal_iter *iter; /* * If an iterator points one after the key we just inserted, decrement @@ -143,9 +161,14 @@ static void journal_iters_fix(struct bch_fs *c) * decrement was unnecessary, bch2_btree_and_journal_iter_peek() will * handle that: */ - list_for_each_entry(iter, &c->journal_iters, journal.list) - if (iter->journal.idx == gap_end) - iter->journal.idx = keys->gap - 1; + list_for_each_entry(iter, &c->journal_iters, list) { + journal_iter_verify(iter); + if (iter->idx == gap_end && + new_key->btree_id == iter->btree_id && + new_key->level == iter->level) + iter->idx = keys->gap - 1; + journal_iter_verify(iter); + } } static void journal_iters_move_gap(struct bch_fs *c, size_t old_gap, size_t new_gap) @@ -192,7 +215,12 @@ int bch2_journal_key_insert_take(struct bch_fs *c, enum btree_id id, if (idx > keys->gap) idx -= keys->size - keys->nr; + size_t old_gap = keys->gap; + if (keys->nr == keys->size) { + journal_iters_move_gap(c, old_gap, keys->size); + old_gap = keys->size; + struct journal_keys new_keys = { .nr = keys->nr, .size = max_t(size_t, keys->size, 8) * 2, @@ -216,7 +244,7 @@ int bch2_journal_key_insert_take(struct bch_fs *c, enum btree_id id, keys->gap = keys->nr; } - journal_iters_move_gap(c, keys->gap, idx); + journal_iters_move_gap(c, old_gap, idx); move_gap(keys, idx); @@ -301,16 +329,21 @@ static void bch2_journal_iter_advance(struct journal_iter *iter) static struct bkey_s_c bch2_journal_iter_peek(struct journal_iter *iter) { - struct journal_key *k = iter->keys->data + iter->idx; + journal_iter_verify(iter); + + while (iter->idx < iter->keys->size) { + struct journal_key *k = iter->keys->data + iter->idx; + + int cmp = cmp_int(k->btree_id, iter->btree_id) ?: + cmp_int(k->level, iter->level); + if (cmp > 0) + break; + BUG_ON(cmp); - while (k < iter->keys->data + iter->keys->size && - k->btree_id == iter->btree_id && - k->level == iter->level) { if (!k->overwritten) return bkey_i_to_s_c(k->k); bch2_journal_iter_advance(iter); - k = iter->keys->data + iter->idx; } return bkey_s_c_null; @@ -330,6 +363,8 @@ static void bch2_journal_iter_init(struct bch_fs *c, iter->level = level; iter->keys = &c->journal_keys; iter->idx = bch2_journal_key_search(&c->journal_keys, id, level, pos); + + journal_iter_verify(iter); } static struct bkey_s_c bch2_journal_iter_peek_btree(struct btree_and_journal_iter *iter) -- cgit v1.2.3 From 059a49aa2e25c58f90b50151f109dd3c4cdb3a47 Mon Sep 17 00:00:00 2001 From: Breno Leitao Date: Wed, 3 Apr 2024 08:43:12 -0700 Subject: virtio_net: Do not send RSS key if it is not supported There is a bug when setting the RSS options in virtio_net that can break the whole machine, getting the kernel into an infinite loop. Running the following command in any QEMU virtual machine with virtionet will reproduce this problem: # ethtool -X eth0 hfunc toeplitz This is how the problem happens: 1) ethtool_set_rxfh() calls virtnet_set_rxfh() 2) virtnet_set_rxfh() calls virtnet_commit_rss_command() 3) virtnet_commit_rss_command() populates 4 entries for the rss scatter-gather 4) Since the command above does not have a key, then the last scatter-gatter entry will be zeroed, since rss_key_size == 0. sg_buf_size = vi->rss_key_size; 5) This buffer is passed to qemu, but qemu is not happy with a buffer with zero length, and do the following in virtqueue_map_desc() (QEMU function): if (!sz) { virtio_error(vdev, "virtio: zero sized buffers are not allowed"); 6) virtio_error() (also QEMU function) set the device as broken vdev->broken = true; 7) Qemu bails out, and do not repond this crazy kernel. 8) The kernel is waiting for the response to come back (function virtnet_send_command()) 9) The kernel is waiting doing the following : while (!virtqueue_get_buf(vi->cvq, &tmp) && !virtqueue_is_broken(vi->cvq)) cpu_relax(); 10) None of the following functions above is true, thus, the kernel loops here forever. Keeping in mind that virtqueue_is_broken() does not look at the qemu `vdev->broken`, so, it never realizes that the vitio is broken at QEMU side. Fix it by not sending RSS commands if the feature is not available in the device. Fixes: c7114b1249fa ("drivers/net/virtio_net: Added basic RSS support.") Cc: stable@vger.kernel.org Cc: qemu-devel@nongnu.org Signed-off-by: Breno Leitao Reviewed-by: Heng Qi Reviewed-by: Xuan Zhuo Signed-off-by: David S. Miller --- drivers/net/virtio_net.c | 26 ++++++++++++++++++++++---- 1 file changed, 22 insertions(+), 4 deletions(-) diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c index c22d1118a133..115c3c5414f2 100644 --- a/drivers/net/virtio_net.c +++ b/drivers/net/virtio_net.c @@ -3807,6 +3807,7 @@ static int virtnet_set_rxfh(struct net_device *dev, struct netlink_ext_ack *extack) { struct virtnet_info *vi = netdev_priv(dev); + bool update = false; int i; if (rxfh->hfunc != ETH_RSS_HASH_NO_CHANGE && @@ -3814,13 +3815,28 @@ static int virtnet_set_rxfh(struct net_device *dev, return -EOPNOTSUPP; if (rxfh->indir) { + if (!vi->has_rss) + return -EOPNOTSUPP; + for (i = 0; i < vi->rss_indir_table_size; ++i) vi->ctrl->rss.indirection_table[i] = rxfh->indir[i]; + update = true; } - if (rxfh->key) + + if (rxfh->key) { + /* If either _F_HASH_REPORT or _F_RSS are negotiated, the + * device provides hash calculation capabilities, that is, + * hash_key is configured. + */ + if (!vi->has_rss && !vi->has_rss_hash_report) + return -EOPNOTSUPP; + memcpy(vi->ctrl->rss.key, rxfh->key, vi->rss_key_size); + update = true; + } - virtnet_commit_rss_command(vi); + if (update) + virtnet_commit_rss_command(vi); return 0; } @@ -4729,13 +4745,15 @@ static int virtnet_probe(struct virtio_device *vdev) if (virtio_has_feature(vdev, VIRTIO_NET_F_HASH_REPORT)) vi->has_rss_hash_report = true; - if (virtio_has_feature(vdev, VIRTIO_NET_F_RSS)) + if (virtio_has_feature(vdev, VIRTIO_NET_F_RSS)) { vi->has_rss = true; - if (vi->has_rss || vi->has_rss_hash_report) { vi->rss_indir_table_size = virtio_cread16(vdev, offsetof(struct virtio_net_config, rss_max_indirection_table_length)); + } + + if (vi->has_rss || vi->has_rss_hash_report) { vi->rss_key_size = virtio_cread8(vdev, offsetof(struct virtio_net_config, rss_max_key_size)); -- cgit v1.2.3 From bccb798e07f8bb8b91212fe8ed1e421685449076 Mon Sep 17 00:00:00 2001 From: Hariprasad Kelam Date: Thu, 4 Apr 2024 16:54:27 +0530 Subject: octeontx2-pf: Fix transmit scheduler resource leak Inorder to support shaping and scheduling, Upon class creation Netdev driver allocates trasmit schedulers. The previous patch which added support for Round robin scheduling has a bug due to which driver is not freeing transmit schedulers post class deletion. This patch fixes the same. Fixes: 47a9656f168a ("octeontx2-pf: htb offload support for Round Robin scheduling") Signed-off-by: Hariprasad Kelam Signed-off-by: David S. Miller --- drivers/net/ethernet/marvell/octeontx2/nic/qos.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/qos.c b/drivers/net/ethernet/marvell/octeontx2/nic/qos.c index 1e77bbf5d22a..1723e9912ae0 100644 --- a/drivers/net/ethernet/marvell/octeontx2/nic/qos.c +++ b/drivers/net/ethernet/marvell/octeontx2/nic/qos.c @@ -382,6 +382,7 @@ static void otx2_qos_read_txschq_cfg_tl(struct otx2_qos_node *parent, otx2_qos_read_txschq_cfg_tl(node, cfg); cnt = cfg->static_node_pos[node->level]; cfg->schq_contig_list[node->level][cnt] = node->schq; + cfg->schq_index_used[node->level][cnt] = true; cfg->schq_contig[node->level]++; cfg->static_node_pos[node->level]++; otx2_qos_read_txschq_cfg_schq(node, cfg); -- cgit v1.2.3 From 09e913f5826936c0f6632d6d0d35a36295fac7cc Mon Sep 17 00:00:00 2001 From: Hongbo Li Date: Tue, 26 Mar 2024 12:04:56 +0800 Subject: bcachefs: fix the count of nr_freed_pcpu after changing bc->freed_nonpcpu list When allocating bkey_cached from bc->freed_pcpu list, it missed decreasing the count of nr_freed_pcpu which would cause the mismatch between the value of nr_freed_pcpu and the list items. This problem also exists in moving new bkey_cached to bc->freed_pcpu list. If these happened, the bug info may appear in bch2_fs_btree_key_cache_exit by the follow code: BUG_ON(list_count_nodes(&bc->freed_pcpu) != bc->nr_freed_pcpu); BUG_ON(list_count_nodes(&bc->freed_nonpcpu) != bc->nr_freed_nonpcpu); Fixes: c65c13f0eac6 ("bcachefs: Run btree key cache shrinker less aggressively") Signed-off-by: Hongbo Li Signed-off-by: Kent Overstreet --- fs/bcachefs/btree_key_cache.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/fs/bcachefs/btree_key_cache.c b/fs/bcachefs/btree_key_cache.c index 4ae7890f07c6..88a3582a3275 100644 --- a/fs/bcachefs/btree_key_cache.c +++ b/fs/bcachefs/btree_key_cache.c @@ -169,6 +169,7 @@ static void bkey_cached_move_to_freelist(struct btree_key_cache *bc, } else { mutex_lock(&bc->lock); list_move_tail(&ck->list, &bc->freed_pcpu); + bc->nr_freed_pcpu++; mutex_unlock(&bc->lock); } } @@ -245,6 +246,7 @@ bkey_cached_alloc(struct btree_trans *trans, struct btree_path *path, if (!list_empty(&bc->freed_pcpu)) { ck = list_last_entry(&bc->freed_pcpu, struct bkey_cached, list); list_del_init(&ck->list); + bc->nr_freed_pcpu--; } mutex_unlock(&bc->lock); } -- cgit v1.2.3 From b897b148ee30c7fca995e6d15cf791f52993920b Mon Sep 17 00:00:00 2001 From: Kent Overstreet Date: Sun, 7 Apr 2024 16:20:17 -0400 Subject: bcachefs: fix bch2_get_acl() transaction restart handling bch2_acl_from_disk() uses allocate_dropping_locks, and can thus return a transaction restart - this wasn't handled. Signed-off-by: Kent Overstreet --- fs/bcachefs/acl.c | 30 ++++++++++++++---------------- 1 file changed, 14 insertions(+), 16 deletions(-) diff --git a/fs/bcachefs/acl.c b/fs/bcachefs/acl.c index 3640f417cce1..5c180fdc3efb 100644 --- a/fs/bcachefs/acl.c +++ b/fs/bcachefs/acl.c @@ -281,7 +281,6 @@ struct posix_acl *bch2_get_acl(struct mnt_idmap *idmap, struct xattr_search_key search = X_SEARCH(acl_to_xattr_type(type), "", 0); struct btree_trans *trans = bch2_trans_get(c); struct btree_iter iter = { NULL }; - struct bkey_s_c_xattr xattr; struct posix_acl *acl = NULL; struct bkey_s_c k; int ret; @@ -290,28 +289,27 @@ retry: ret = bch2_hash_lookup(trans, &iter, bch2_xattr_hash_desc, &hash, inode_inum(inode), &search, 0); - if (ret) { - if (!bch2_err_matches(ret, ENOENT)) - acl = ERR_PTR(ret); - goto out; - } + if (ret) + goto err; k = bch2_btree_iter_peek_slot(&iter); ret = bkey_err(k); - if (ret) { - acl = ERR_PTR(ret); - goto out; - } + if (ret) + goto err; - xattr = bkey_s_c_to_xattr(k); + struct bkey_s_c_xattr xattr = bkey_s_c_to_xattr(k); acl = bch2_acl_from_disk(trans, xattr_val(xattr.v), - le16_to_cpu(xattr.v->x_val_len)); + le16_to_cpu(xattr.v->x_val_len)); + ret = PTR_ERR_OR_ZERO(acl); +err: + if (bch2_err_matches(ret, BCH_ERR_transaction_restart)) + goto retry; - if (!IS_ERR(acl)) + if (ret) + acl = !bch2_err_matches(ret, ENOENT) ? ERR_PTR(ret) : NULL; + + if (!IS_ERR_OR_NULL(acl)) set_cached_acl(&inode->v, type, acl); -out: - if (bch2_err_matches(PTR_ERR_OR_ZERO(acl), BCH_ERR_transaction_restart)) - goto retry; bch2_trans_iter_exit(trans, &iter); bch2_trans_put(trans); -- cgit v1.2.3 From 8b8ace080319a866f5dfe9da8e665ae51d971c54 Mon Sep 17 00:00:00 2001 From: Ming Lei Date: Sun, 7 Apr 2024 20:59:10 +0800 Subject: block: fix q->blkg_list corruption during disk rebind Multiple gendisk instances can allocated/added for single request queue in case of disk rebind. blkg may still stay in q->blkg_list when calling blkcg_init_disk() for rebind, then q->blkg_list becomes corrupted. Fix the list corruption issue by: - add blkg_init_queue() to initialize q->blkg_list & q->blkcg_mutex only - move calling blkg_init_queue() into blk_alloc_queue() The list corruption should be started since commit f1c006f1c685 ("blk-cgroup: synchronize pd_free_fn() from blkg_free_workfn() and blkcg_deactivate_policy()") which delays removing blkg from q->blkg_list into blkg_free_workfn(). Fixes: f1c006f1c685 ("blk-cgroup: synchronize pd_free_fn() from blkg_free_workfn() and blkcg_deactivate_policy()") Fixes: 1059699f87eb ("block: move blkcg initialization/destroy into disk allocation/release handler") Cc: Yu Kuai Cc: Tejun Heo Signed-off-by: Ming Lei Reviewed-by: Yu Kuai Link: https://lore.kernel.org/r/20240407125910.4053377-1-ming.lei@redhat.com Signed-off-by: Jens Axboe --- block/blk-cgroup.c | 9 ++++++--- block/blk-cgroup.h | 2 ++ block/blk-core.c | 2 ++ 3 files changed, 10 insertions(+), 3 deletions(-) diff --git a/block/blk-cgroup.c b/block/blk-cgroup.c index bdbb557feb5a..059467086b13 100644 --- a/block/blk-cgroup.c +++ b/block/blk-cgroup.c @@ -1409,6 +1409,12 @@ static int blkcg_css_online(struct cgroup_subsys_state *css) return 0; } +void blkg_init_queue(struct request_queue *q) +{ + INIT_LIST_HEAD(&q->blkg_list); + mutex_init(&q->blkcg_mutex); +} + int blkcg_init_disk(struct gendisk *disk) { struct request_queue *q = disk->queue; @@ -1416,9 +1422,6 @@ int blkcg_init_disk(struct gendisk *disk) bool preloaded; int ret; - INIT_LIST_HEAD(&q->blkg_list); - mutex_init(&q->blkcg_mutex); - new_blkg = blkg_alloc(&blkcg_root, disk, GFP_KERNEL); if (!new_blkg) return -ENOMEM; diff --git a/block/blk-cgroup.h b/block/blk-cgroup.h index 78b74106bf10..90b3959d88cf 100644 --- a/block/blk-cgroup.h +++ b/block/blk-cgroup.h @@ -189,6 +189,7 @@ struct blkcg_policy { extern struct blkcg blkcg_root; extern bool blkcg_debug_stats; +void blkg_init_queue(struct request_queue *q); int blkcg_init_disk(struct gendisk *disk); void blkcg_exit_disk(struct gendisk *disk); @@ -482,6 +483,7 @@ struct blkcg { }; static inline struct blkcg_gq *blkg_lookup(struct blkcg *blkcg, void *key) { return NULL; } +static inline void blkg_init_queue(struct request_queue *q) { } static inline int blkcg_init_disk(struct gendisk *disk) { return 0; } static inline void blkcg_exit_disk(struct gendisk *disk) { } static inline int blkcg_policy_register(struct blkcg_policy *pol) { return 0; } diff --git a/block/blk-core.c b/block/blk-core.c index a16b5abdbbf5..3a6f5603fb44 100644 --- a/block/blk-core.c +++ b/block/blk-core.c @@ -442,6 +442,8 @@ struct request_queue *blk_alloc_queue(struct queue_limits *lim, int node_id) init_waitqueue_head(&q->mq_freeze_wq); mutex_init(&q->mq_freeze_lock); + blkg_init_queue(q); + /* * Init percpu_ref in atomic mode so that it's faster to shutdown. * See blk_register_queue() for details. -- cgit v1.2.3 From b561ea56a26415bf44ce8ca6a8e625c7c390f1ea Mon Sep 17 00:00:00 2001 From: Ming Lei Date: Sun, 7 Apr 2024 21:19:31 +0800 Subject: block: allow device to have both virt_boundary_mask and max segment size When one stacking device is over one device with virt_boundary_mask and another one with max segment size, the stacking device have both limits set. This way is allowed before d690cb8ae14b ("block: add an API to atomically update queue limits"). Relax the limit so that we won't break such kind of stacking setting. Closes: https://bugzilla.kernel.org/show_bug.cgi?id=218687 Reported-by: janpieter.sollie@edpnet.be Fixes: d690cb8ae14b ("block: add an API to atomically update queue limits") Link: https://lore.kernel.org/linux-block/ZfGl8HzUpiOxCLm3@fedora/ Cc: Christoph Hellwig Cc: Mike Snitzer Cc: dm-devel@lists.linux.dev Cc: Song Liu Cc: linux-raid@vger.kernel.org Signed-off-by: Ming Lei Reviewed-by: Mike Snitzer Link: https://lore.kernel.org/r/20240407131931.4055231-1-ming.lei@redhat.com Signed-off-by: Jens Axboe --- block/blk-settings.c | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) diff --git a/block/blk-settings.c b/block/blk-settings.c index cdbaef159c4b..d2731843f2fc 100644 --- a/block/blk-settings.c +++ b/block/blk-settings.c @@ -182,17 +182,13 @@ static int blk_validate_limits(struct queue_limits *lim) return -EINVAL; /* - * Devices that require a virtual boundary do not support scatter/gather - * I/O natively, but instead require a descriptor list entry for each - * page (which might not be identical to the Linux PAGE_SIZE). Because - * of that they are not limited by our notion of "segment size". + * Stacking device may have both virtual boundary and max segment + * size limit, so allow this setting now, and long-term the two + * might need to move out of stacking limits since we have immutable + * bvec and lower layer bio splitting is supposed to handle the two + * correctly. */ - if (lim->virt_boundary_mask) { - if (WARN_ON_ONCE(lim->max_segment_size && - lim->max_segment_size != UINT_MAX)) - return -EINVAL; - lim->max_segment_size = UINT_MAX; - } else { + if (!lim->virt_boundary_mask) { /* * The maximum segment size has an odd historic 64k default that * drivers probably should override. Just like the I/O size we -- cgit v1.2.3 From 8358a76cfb47c9a5af627a0c4e7168aa14fa25f6 Mon Sep 17 00:00:00 2001 From: Stephen Boyd Date: Mon, 25 Mar 2024 11:41:55 -0700 Subject: clk: Remove prepare_lock hold assertion in __clk_release() Removing this assertion lets us move the kref_put() call outside the prepare_lock section. We don't need to hold the prepare_lock here to free memory and destroy the clk_core structure. We've already unlinked the clk from the clk tree and by the time the release function runs nothing holds a reference to the clk_core anymore so anything with the pointer can't access the memory that's being freed anyway. Way back in commit 496eadf821c2 ("clk: Use lockdep asserts to find missing hold of prepare_lock") we didn't need to have this assertion either. Fixes: 496eadf821c2 ("clk: Use lockdep asserts to find missing hold of prepare_lock") Cc: Krzysztof Kozlowski Reviewed-by: Douglas Anderson Signed-off-by: Stephen Boyd Link: https://lore.kernel.org/r/20240325184204.745706-2-sboyd@kernel.org --- drivers/clk/clk.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c index 25371c91a58f..fed20641822c 100644 --- a/drivers/clk/clk.c +++ b/drivers/clk/clk.c @@ -4375,8 +4375,6 @@ static void __clk_release(struct kref *ref) { struct clk_core *core = container_of(ref, struct clk_core, ref); - lockdep_assert_held(&prepare_lock); - clk_core_free_parent_map(core); kfree_const(core->name); kfree(core); -- cgit v1.2.3 From 6f63af7511e7058f3fa4ad5b8102210741c9f947 Mon Sep 17 00:00:00 2001 From: Stephen Boyd Date: Mon, 25 Mar 2024 11:41:56 -0700 Subject: clk: Don't hold prepare_lock when calling kref_put() We don't need to hold the prepare_lock when dropping a ref on a struct clk_core. The release function is only freeing memory and any code with a pointer reference has already unlinked anything pointing to the clk_core. This reduces the holding area of the prepare_lock a bit. Note that we also don't call free_clk() with the prepare_lock held. There isn't any reason to do that. Reviewed-by: Douglas Anderson Signed-off-by: Stephen Boyd Link: https://lore.kernel.org/r/20240325184204.745706-3-sboyd@kernel.org --- drivers/clk/clk.c | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c index fed20641822c..e950d0cf6b2f 100644 --- a/drivers/clk/clk.c +++ b/drivers/clk/clk.c @@ -4470,7 +4470,8 @@ void clk_unregister(struct clk *clk) if (ops == &clk_nodrv_ops) { pr_err("%s: unregistered clock: %s\n", __func__, clk->core->name); - goto unlock; + clk_prepare_unlock(); + return; } /* * Assign empty clock ops for consumers that might still hold @@ -4504,11 +4505,10 @@ void clk_unregister(struct clk *clk) if (clk->core->protect_count) pr_warn("%s: unregistering protected clock: %s\n", __func__, clk->core->name); + clk_prepare_unlock(); kref_put(&clk->core->ref, __clk_release); free_clk(clk); -unlock: - clk_prepare_unlock(); } EXPORT_SYMBOL_GPL(clk_unregister); @@ -4667,13 +4667,11 @@ void __clk_put(struct clk *clk) if (clk->min_rate > 0 || clk->max_rate < ULONG_MAX) clk_set_rate_range_nolock(clk, 0, ULONG_MAX); - owner = clk->core->owner; - kref_put(&clk->core->ref, __clk_release); - clk_prepare_unlock(); + owner = clk->core->owner; + kref_put(&clk->core->ref, __clk_release); module_put(owner); - free_clk(clk); } -- cgit v1.2.3 From 9d05ae531c2cff20d5d527f04e28d28e04379929 Mon Sep 17 00:00:00 2001 From: Stephen Boyd Date: Mon, 25 Mar 2024 11:41:57 -0700 Subject: clk: Initialize struct clk_core kref earlier Initialize this kref once we allocate memory for the struct clk_core so that we can reuse the release function to free any memory associated with the structure. This mostly consolidates code, but also clarifies that the kref lifetime exists once the container structure (struct clk_core) is allocated instead of leaving it in a half-baked state for most of __clk_core_init(). Reviewed-by: Douglas Anderson Signed-off-by: Stephen Boyd Link: https://lore.kernel.org/r/20240325184204.745706-4-sboyd@kernel.org --- drivers/clk/clk.c | 28 +++++++++++++--------------- 1 file changed, 13 insertions(+), 15 deletions(-) diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c index e950d0cf6b2f..8b35ca32f45e 100644 --- a/drivers/clk/clk.c +++ b/drivers/clk/clk.c @@ -3981,8 +3981,6 @@ static int __clk_core_init(struct clk_core *core) } clk_core_reparent_orphans_nolock(); - - kref_init(&core->ref); out: clk_pm_runtime_put(core); unlock: @@ -4211,6 +4209,16 @@ static void clk_core_free_parent_map(struct clk_core *core) kfree(core->parents); } +/* Free memory allocated for a struct clk_core */ +static void __clk_release(struct kref *ref) +{ + struct clk_core *core = container_of(ref, struct clk_core, ref); + + clk_core_free_parent_map(core); + kfree_const(core->name); + kfree(core); +} + static struct clk * __clk_register(struct device *dev, struct device_node *np, struct clk_hw *hw) { @@ -4231,6 +4239,8 @@ __clk_register(struct device *dev, struct device_node *np, struct clk_hw *hw) goto fail_out; } + kref_init(&core->ref); + core->name = kstrdup_const(init->name, GFP_KERNEL); if (!core->name) { ret = -ENOMEM; @@ -4285,12 +4295,10 @@ __clk_register(struct device *dev, struct device_node *np, struct clk_hw *hw) hw->clk = NULL; fail_create_clk: - clk_core_free_parent_map(core); fail_parents: fail_ops: - kfree_const(core->name); fail_name: - kfree(core); + kref_put(&core->ref, __clk_release); fail_out: return ERR_PTR(ret); } @@ -4370,16 +4378,6 @@ int of_clk_hw_register(struct device_node *node, struct clk_hw *hw) } EXPORT_SYMBOL_GPL(of_clk_hw_register); -/* Free memory allocated for a clock. */ -static void __clk_release(struct kref *ref) -{ - struct clk_core *core = container_of(ref, struct clk_core, ref); - - clk_core_free_parent_map(core); - kfree_const(core->name); - kfree(core); -} - /* * Empty clk_ops for unregistered clocks. These are used temporarily * after clk_unregister() was called on a clock and until last clock -- cgit v1.2.3 From e581cf5d216289ef292d1a4036d53ce90e122469 Mon Sep 17 00:00:00 2001 From: Stephen Boyd Date: Mon, 25 Mar 2024 11:41:58 -0700 Subject: clk: Get runtime PM before walking tree during disable_unused Doug reported [1] the following hung task: INFO: task swapper/0:1 blocked for more than 122 seconds. Not tainted 5.15.149-21875-gf795ebc40eb8 #1 "echo 0 > /proc/sys/kernel/hung_task_timeout_secs" disables this message. task:swapper/0 state:D stack: 0 pid: 1 ppid: 0 flags:0x00000008 Call trace: __switch_to+0xf4/0x1f4 __schedule+0x418/0xb80 schedule+0x5c/0x10c rpm_resume+0xe0/0x52c rpm_resume+0x178/0x52c __pm_runtime_resume+0x58/0x98 clk_pm_runtime_get+0x30/0xb0 clk_disable_unused_subtree+0x58/0x208 clk_disable_unused_subtree+0x38/0x208 clk_disable_unused_subtree+0x38/0x208 clk_disable_unused_subtree+0x38/0x208 clk_disable_unused_subtree+0x38/0x208 clk_disable_unused+0x4c/0xe4 do_one_initcall+0xcc/0x2d8 do_initcall_level+0xa4/0x148 do_initcalls+0x5c/0x9c do_basic_setup+0x24/0x30 kernel_init_freeable+0xec/0x164 kernel_init+0x28/0x120 ret_from_fork+0x10/0x20 INFO: task kworker/u16:0:9 blocked for more than 122 seconds. Not tainted 5.15.149-21875-gf795ebc40eb8 #1 "echo 0 > /proc/sys/kernel/hung_task_timeout_secs" disables this message. task:kworker/u16:0 state:D stack: 0 pid: 9 ppid: 2 flags:0x00000008 Workqueue: events_unbound deferred_probe_work_func Call trace: __switch_to+0xf4/0x1f4 __schedule+0x418/0xb80 schedule+0x5c/0x10c schedule_preempt_disabled+0x2c/0x48 __mutex_lock+0x238/0x488 __mutex_lock_slowpath+0x1c/0x28 mutex_lock+0x50/0x74 clk_prepare_lock+0x7c/0x9c clk_core_prepare_lock+0x20/0x44 clk_prepare+0x24/0x30 clk_bulk_prepare+0x40/0xb0 mdss_runtime_resume+0x54/0x1c8 pm_generic_runtime_resume+0x30/0x44 __genpd_runtime_resume+0x68/0x7c genpd_runtime_resume+0x108/0x1f4 __rpm_callback+0x84/0x144 rpm_callback+0x30/0x88 rpm_resume+0x1f4/0x52c rpm_resume+0x178/0x52c __pm_runtime_resume+0x58/0x98 __device_attach+0xe0/0x170 device_initial_probe+0x1c/0x28 bus_probe_device+0x3c/0x9c device_add+0x644/0x814 mipi_dsi_device_register_full+0xe4/0x170 devm_mipi_dsi_device_register_full+0x28/0x70 ti_sn_bridge_probe+0x1dc/0x2c0 auxiliary_bus_probe+0x4c/0x94 really_probe+0xcc/0x2c8 __driver_probe_device+0xa8/0x130 driver_probe_device+0x48/0x110 __device_attach_driver+0xa4/0xcc bus_for_each_drv+0x8c/0xd8 __device_attach+0xf8/0x170 device_initial_probe+0x1c/0x28 bus_probe_device+0x3c/0x9c deferred_probe_work_func+0x9c/0xd8 process_one_work+0x148/0x518 worker_thread+0x138/0x350 kthread+0x138/0x1e0 ret_from_fork+0x10/0x20 The first thread is walking the clk tree and calling clk_pm_runtime_get() to power on devices required to read the clk hardware via struct clk_ops::is_enabled(). This thread holds the clk prepare_lock, and is trying to runtime PM resume a device, when it finds that the device is in the process of resuming so the thread schedule()s away waiting for the device to finish resuming before continuing. The second thread is runtime PM resuming the same device, but the runtime resume callback is calling clk_prepare(), trying to grab the prepare_lock waiting on the first thread. This is a classic ABBA deadlock. To properly fix the deadlock, we must never runtime PM resume or suspend a device with the clk prepare_lock held. Actually doing that is near impossible today because the global prepare_lock would have to be dropped in the middle of the tree, the device runtime PM resumed/suspended, and then the prepare_lock grabbed again to ensure consistency of the clk tree topology. If anything changes with the clk tree in the meantime, we've lost and will need to start the operation all over again. Luckily, most of the time we're simply incrementing or decrementing the runtime PM count on an active device, so we don't have the chance to schedule away with the prepare_lock held. Let's fix this immediate problem that can be triggered more easily by simply booting on Qualcomm sc7180. Introduce a list of clk_core structures that have been registered, or are in the process of being registered, that require runtime PM to operate. Iterate this list and call clk_pm_runtime_get() on each of them without holding the prepare_lock during clk_disable_unused(). This way we can be certain that the runtime PM state of the devices will be active and resumed so we can't schedule away while walking the clk tree with the prepare_lock held. Similarly, call clk_pm_runtime_put() without the prepare_lock held to properly drop the runtime PM reference. We remove the calls to clk_pm_runtime_{get,put}() in this path because they're superfluous now that we know the devices are runtime resumed. Reported-by: Douglas Anderson Closes: https://lore.kernel.org/all/20220922084322.RFC.2.I375b6b9e0a0a5348962f004beb3dafee6a12dfbb@changeid/ [1] Closes: https://issuetracker.google.com/328070191 Cc: Marek Szyprowski Cc: Ulf Hansson Cc: Krzysztof Kozlowski Fixes: 9a34b45397e5 ("clk: Add support for runtime PM") Signed-off-by: Stephen Boyd Link: https://lore.kernel.org/r/20240325184204.745706-5-sboyd@kernel.org Reviewed-by: Douglas Anderson --- drivers/clk/clk.c | 117 ++++++++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 105 insertions(+), 12 deletions(-) diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c index 8b35ca32f45e..9b907cb3ef61 100644 --- a/drivers/clk/clk.c +++ b/drivers/clk/clk.c @@ -37,6 +37,10 @@ static HLIST_HEAD(clk_root_list); static HLIST_HEAD(clk_orphan_list); static LIST_HEAD(clk_notifier_list); +/* List of registered clks that use runtime PM */ +static HLIST_HEAD(clk_rpm_list); +static DEFINE_MUTEX(clk_rpm_list_lock); + static const struct hlist_head *all_lists[] = { &clk_root_list, &clk_orphan_list, @@ -59,6 +63,7 @@ struct clk_core { struct clk_hw *hw; struct module *owner; struct device *dev; + struct hlist_node rpm_node; struct device_node *of_node; struct clk_core *parent; struct clk_parent_map *parents; @@ -122,6 +127,89 @@ static void clk_pm_runtime_put(struct clk_core *core) pm_runtime_put_sync(core->dev); } +/** + * clk_pm_runtime_get_all() - Runtime "get" all clk provider devices + * + * Call clk_pm_runtime_get() on all runtime PM enabled clks in the clk tree so + * that disabling unused clks avoids a deadlock where a device is runtime PM + * resuming/suspending and the runtime PM callback is trying to grab the + * prepare_lock for something like clk_prepare_enable() while + * clk_disable_unused_subtree() holds the prepare_lock and is trying to runtime + * PM resume/suspend the device as well. + * + * Context: Acquires the 'clk_rpm_list_lock' and returns with the lock held on + * success. Otherwise the lock is released on failure. + * + * Return: 0 on success, negative errno otherwise. + */ +static int clk_pm_runtime_get_all(void) +{ + int ret; + struct clk_core *core, *failed; + + /* + * Grab the list lock to prevent any new clks from being registered + * or unregistered until clk_pm_runtime_put_all(). + */ + mutex_lock(&clk_rpm_list_lock); + + /* + * Runtime PM "get" all the devices that are needed for the clks + * currently registered. Do this without holding the prepare_lock, to + * avoid the deadlock. + */ + hlist_for_each_entry(core, &clk_rpm_list, rpm_node) { + ret = clk_pm_runtime_get(core); + if (ret) { + failed = core; + pr_err("clk: Failed to runtime PM get '%s' for clk '%s'\n", + dev_name(failed->dev), failed->name); + goto err; + } + } + + return 0; + +err: + hlist_for_each_entry(core, &clk_rpm_list, rpm_node) { + if (core == failed) + break; + + clk_pm_runtime_put(core); + } + mutex_unlock(&clk_rpm_list_lock); + + return ret; +} + +/** + * clk_pm_runtime_put_all() - Runtime "put" all clk provider devices + * + * Put the runtime PM references taken in clk_pm_runtime_get_all() and release + * the 'clk_rpm_list_lock'. + */ +static void clk_pm_runtime_put_all(void) +{ + struct clk_core *core; + + hlist_for_each_entry(core, &clk_rpm_list, rpm_node) + clk_pm_runtime_put(core); + mutex_unlock(&clk_rpm_list_lock); +} + +static void clk_pm_runtime_init(struct clk_core *core) +{ + struct device *dev = core->dev; + + if (dev && pm_runtime_enabled(dev)) { + core->rpm_enabled = true; + + mutex_lock(&clk_rpm_list_lock); + hlist_add_head(&core->rpm_node, &clk_rpm_list); + mutex_unlock(&clk_rpm_list_lock); + } +} + /*** locking ***/ static void clk_prepare_lock(void) { @@ -1381,9 +1469,6 @@ static void __init clk_unprepare_unused_subtree(struct clk_core *core) if (core->flags & CLK_IGNORE_UNUSED) return; - if (clk_pm_runtime_get(core)) - return; - if (clk_core_is_prepared(core)) { trace_clk_unprepare(core); if (core->ops->unprepare_unused) @@ -1392,8 +1477,6 @@ static void __init clk_unprepare_unused_subtree(struct clk_core *core) core->ops->unprepare(core->hw); trace_clk_unprepare_complete(core); } - - clk_pm_runtime_put(core); } static void __init clk_disable_unused_subtree(struct clk_core *core) @@ -1409,9 +1492,6 @@ static void __init clk_disable_unused_subtree(struct clk_core *core) if (core->flags & CLK_OPS_PARENT_ENABLE) clk_core_prepare_enable(core->parent); - if (clk_pm_runtime_get(core)) - goto unprepare_out; - flags = clk_enable_lock(); if (core->enable_count) @@ -1436,8 +1516,6 @@ static void __init clk_disable_unused_subtree(struct clk_core *core) unlock_out: clk_enable_unlock(flags); - clk_pm_runtime_put(core); -unprepare_out: if (core->flags & CLK_OPS_PARENT_ENABLE) clk_core_disable_unprepare(core->parent); } @@ -1453,6 +1531,7 @@ __setup("clk_ignore_unused", clk_ignore_unused_setup); static int __init clk_disable_unused(void) { struct clk_core *core; + int ret; if (clk_ignore_unused) { pr_warn("clk: Not disabling unused clocks\n"); @@ -1461,6 +1540,13 @@ static int __init clk_disable_unused(void) pr_info("clk: Disabling unused clocks\n"); + ret = clk_pm_runtime_get_all(); + if (ret) + return ret; + /* + * Grab the prepare lock to keep the clk topology stable while iterating + * over clks. + */ clk_prepare_lock(); hlist_for_each_entry(core, &clk_root_list, child_node) @@ -1477,6 +1563,8 @@ static int __init clk_disable_unused(void) clk_prepare_unlock(); + clk_pm_runtime_put_all(); + return 0; } late_initcall_sync(clk_disable_unused); @@ -4214,6 +4302,12 @@ static void __clk_release(struct kref *ref) { struct clk_core *core = container_of(ref, struct clk_core, ref); + if (core->rpm_enabled) { + mutex_lock(&clk_rpm_list_lock); + hlist_del(&core->rpm_node); + mutex_unlock(&clk_rpm_list_lock); + } + clk_core_free_parent_map(core); kfree_const(core->name); kfree(core); @@ -4253,9 +4347,8 @@ __clk_register(struct device *dev, struct device_node *np, struct clk_hw *hw) } core->ops = init->ops; - if (dev && pm_runtime_enabled(dev)) - core->rpm_enabled = true; core->dev = dev; + clk_pm_runtime_init(core); core->of_node = np; if (dev && dev->driver) core->owner = dev->driver->owner; -- cgit v1.2.3 From 9d1e795f754db1ac3344528b7af0b17b8146f321 Mon Sep 17 00:00:00 2001 From: Stephen Boyd Date: Mon, 25 Mar 2024 11:41:59 -0700 Subject: clk: Get runtime PM before walking tree for clk_summary Similar to the previous commit, we should make sure that all devices are runtime resumed before printing the clk_summary through debugfs. Failure to do so would result in a deadlock if the thread is resuming a device to print clk state and that device is also runtime resuming in another thread, e.g the screen is turning on and the display driver is starting up. We remove the calls to clk_pm_runtime_{get,put}() in this path because they're superfluous now that we know the devices are runtime resumed. This also squashes a bug where the return value of clk_pm_runtime_get() wasn't checked, leading to an RPM count underflow on error paths. Fixes: 1bb294a7981c ("clk: Enable/Disable runtime PM for clk_summary") Cc: Taniya Das Cc: Douglas Anderson Signed-off-by: Stephen Boyd Link: https://lore.kernel.org/r/20240325184204.745706-6-sboyd@kernel.org Reviewed-by: Douglas Anderson --- drivers/clk/clk.c | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c index 9b907cb3ef61..8cca52be993f 100644 --- a/drivers/clk/clk.c +++ b/drivers/clk/clk.c @@ -3340,9 +3340,7 @@ static void clk_summary_show_subtree(struct seq_file *s, struct clk_core *c, { struct clk_core *child; - clk_pm_runtime_get(c); clk_summary_show_one(s, c, level); - clk_pm_runtime_put(c); hlist_for_each_entry(child, &c->children, child_node) clk_summary_show_subtree(s, child, level + 1); @@ -3352,11 +3350,15 @@ static int clk_summary_show(struct seq_file *s, void *data) { struct clk_core *c; struct hlist_head **lists = s->private; + int ret; seq_puts(s, " enable prepare protect duty hardware connection\n"); seq_puts(s, " clock count count count rate accuracy phase cycle enable consumer id\n"); seq_puts(s, "---------------------------------------------------------------------------------------------------------------------------------------------\n"); + ret = clk_pm_runtime_get_all(); + if (ret) + return ret; clk_prepare_lock(); @@ -3365,6 +3367,7 @@ static int clk_summary_show(struct seq_file *s, void *data) clk_summary_show_subtree(s, c, 0); clk_prepare_unlock(); + clk_pm_runtime_put_all(); return 0; } @@ -3412,8 +3415,14 @@ static int clk_dump_show(struct seq_file *s, void *data) struct clk_core *c; bool first_node = true; struct hlist_head **lists = s->private; + int ret; + + ret = clk_pm_runtime_get_all(); + if (ret) + return ret; seq_putc(s, '{'); + clk_prepare_lock(); for (; *lists; lists++) { @@ -3426,6 +3435,7 @@ static int clk_dump_show(struct seq_file *s, void *data) } clk_prepare_unlock(); + clk_pm_runtime_put_all(); seq_puts(s, "}\n"); return 0; -- cgit v1.2.3 From 22e1992cf7b034db5325660e98c41ca5afa5f519 Mon Sep 17 00:00:00 2001 From: Gavin Shan Date: Thu, 28 Mar 2024 10:21:47 +1000 Subject: vhost: Add smp_rmb() in vhost_vq_avail_empty() A smp_rmb() has been missed in vhost_vq_avail_empty(), spotted by Will. Otherwise, it's not ensured the available ring entries pushed by guest can be observed by vhost in time, leading to stale available ring entries fetched by vhost in vhost_get_vq_desc(), as reported by Yihuang Yu on NVidia's grace-hopper (ARM64) platform. /home/gavin/sandbox/qemu.main/build/qemu-system-aarch64 \ -accel kvm -machine virt,gic-version=host -cpu host \ -smp maxcpus=1,cpus=1,sockets=1,clusters=1,cores=1,threads=1 \ -m 4096M,slots=16,maxmem=64G \ -object memory-backend-ram,id=mem0,size=4096M \ : \ -netdev tap,id=vnet0,vhost=true \ -device virtio-net-pci,bus=pcie.8,netdev=vnet0,mac=52:54:00:f1:26:b0 : guest# netperf -H 10.26.1.81 -l 60 -C -c -t UDP_STREAM virtio_net virtio0: output.0:id 100 is not a head! Add the missed smp_rmb() in vhost_vq_avail_empty(). When tx_can_batch() returns true, it means there's still pending tx buffers. Since it might read indices, so it still can bypass the smp_rmb() in vhost_get_vq_desc(). Note that it should be safe until vq->avail_idx is changed by commit 275bf960ac697 ("vhost: better detection of available buffers"). Fixes: 275bf960ac69 ("vhost: better detection of available buffers") Cc: # v4.11+ Reported-by: Yihuang Yu Suggested-by: Will Deacon Signed-off-by: Gavin Shan Acked-by: Jason Wang Message-Id: <20240328002149.1141302-2-gshan@redhat.com> Signed-off-by: Michael S. Tsirkin Reviewed-by: Stefano Garzarella --- drivers/vhost/vhost.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/drivers/vhost/vhost.c b/drivers/vhost/vhost.c index 045f666b4f12..29df65b2ebf2 100644 --- a/drivers/vhost/vhost.c +++ b/drivers/vhost/vhost.c @@ -2799,9 +2799,19 @@ bool vhost_vq_avail_empty(struct vhost_dev *dev, struct vhost_virtqueue *vq) r = vhost_get_avail_idx(vq, &avail_idx); if (unlikely(r)) return false; + vq->avail_idx = vhost16_to_cpu(vq, avail_idx); + if (vq->avail_idx != vq->last_avail_idx) { + /* Since we have updated avail_idx, the following + * call to vhost_get_vq_desc() will read available + * ring entries. Make sure that read happens after + * the avail_idx read. + */ + smp_rmb(); + return false; + } - return vq->avail_idx == vq->last_avail_idx; + return true; } EXPORT_SYMBOL_GPL(vhost_vq_avail_empty); -- cgit v1.2.3 From df9ace7647d4123209395bb9967e998d5758c645 Mon Sep 17 00:00:00 2001 From: Gavin Shan Date: Thu, 28 Mar 2024 10:21:48 +1000 Subject: vhost: Add smp_rmb() in vhost_enable_notify() A smp_rmb() has been missed in vhost_enable_notify(), inspired by Will. Otherwise, it's not ensured the available ring entries pushed by guest can be observed by vhost in time, leading to stale available ring entries fetched by vhost in vhost_get_vq_desc(), as reported by Yihuang Yu on NVidia's grace-hopper (ARM64) platform. /home/gavin/sandbox/qemu.main/build/qemu-system-aarch64 \ -accel kvm -machine virt,gic-version=host -cpu host \ -smp maxcpus=1,cpus=1,sockets=1,clusters=1,cores=1,threads=1 \ -m 4096M,slots=16,maxmem=64G \ -object memory-backend-ram,id=mem0,size=4096M \ : \ -netdev tap,id=vnet0,vhost=true \ -device virtio-net-pci,bus=pcie.8,netdev=vnet0,mac=52:54:00:f1:26:b0 : guest# netperf -H 10.26.1.81 -l 60 -C -c -t UDP_STREAM virtio_net virtio0: output.0:id 100 is not a head! Add the missed smp_rmb() in vhost_enable_notify(). When it returns true, it means there's still pending tx buffers. Since it might read indices, so it still can bypass the smp_rmb() in vhost_get_vq_desc(). Note that it should be safe until vq->avail_idx is changed by commit d3bb267bbdcb ("vhost: cache avail index in vhost_enable_notify()"). Fixes: d3bb267bbdcb ("vhost: cache avail index in vhost_enable_notify()") Cc: # v5.18+ Reported-by: Yihuang Yu Suggested-by: Will Deacon Signed-off-by: Gavin Shan Acked-by: Jason Wang Message-Id: <20240328002149.1141302-3-gshan@redhat.com> Signed-off-by: Michael S. Tsirkin Reviewed-by: Stefano Garzarella --- drivers/vhost/vhost.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/drivers/vhost/vhost.c b/drivers/vhost/vhost.c index 29df65b2ebf2..32686c79c41d 100644 --- a/drivers/vhost/vhost.c +++ b/drivers/vhost/vhost.c @@ -2848,9 +2848,19 @@ bool vhost_enable_notify(struct vhost_dev *dev, struct vhost_virtqueue *vq) &vq->avail->idx, r); return false; } + vq->avail_idx = vhost16_to_cpu(vq, avail_idx); + if (vq->avail_idx != vq->last_avail_idx) { + /* Since we have updated avail_idx, the following + * call to vhost_get_vq_desc() will read available + * ring entries. Make sure that read happens after + * the avail_idx read. + */ + smp_rmb(); + return true; + } - return vq->avail_idx != vq->last_avail_idx; + return false; } EXPORT_SYMBOL_GPL(vhost_enable_notify); -- cgit v1.2.3 From ffe6176b7f53ca0c99355f13e14a33a40cf49406 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Sun, 31 Mar 2024 10:43:48 +0200 Subject: virtio: store owner from modules with register_virtio_driver() Modules registering driver with register_virtio_driver() might forget to set .owner field. i2c-virtio.c for example has it missing. The field is used by some other kernel parts for reference counting (try_module_get()), so it is expected that drivers will set it. Solve the problem by moving this task away from the drivers to the core virtio code, just like we did for platform_driver in commit 9447057eaff8 ("platform_device: use a macro instead of platform_driver_register"). Fixes: 3cfc88380413 ("i2c: virtio: add a virtio i2c frontend driver") Cc: "Jie Deng" Signed-off-by: Krzysztof Kozlowski Message-Id: <20240331-module-owner-virtio-v2-1-98f04bfaf46a@linaro.org> Signed-off-by: Michael S. Tsirkin --- Documentation/driver-api/virtio/writing_virtio_drivers.rst | 1 - drivers/virtio/virtio.c | 6 ++++-- include/linux/virtio.h | 7 +++++-- 3 files changed, 9 insertions(+), 5 deletions(-) diff --git a/Documentation/driver-api/virtio/writing_virtio_drivers.rst b/Documentation/driver-api/virtio/writing_virtio_drivers.rst index e14c58796d25..e5de6f5d061a 100644 --- a/Documentation/driver-api/virtio/writing_virtio_drivers.rst +++ b/Documentation/driver-api/virtio/writing_virtio_drivers.rst @@ -97,7 +97,6 @@ like this:: static struct virtio_driver virtio_dummy_driver = { .driver.name = KBUILD_MODNAME, - .driver.owner = THIS_MODULE, .id_table = id_table, .probe = virtio_dummy_probe, .remove = virtio_dummy_remove, diff --git a/drivers/virtio/virtio.c b/drivers/virtio/virtio.c index f173587893cb..9510c551dce8 100644 --- a/drivers/virtio/virtio.c +++ b/drivers/virtio/virtio.c @@ -362,14 +362,16 @@ static const struct bus_type virtio_bus = { .remove = virtio_dev_remove, }; -int register_virtio_driver(struct virtio_driver *driver) +int __register_virtio_driver(struct virtio_driver *driver, struct module *owner) { /* Catch this early. */ BUG_ON(driver->feature_table_size && !driver->feature_table); driver->driver.bus = &virtio_bus; + driver->driver.owner = owner; + return driver_register(&driver->driver); } -EXPORT_SYMBOL_GPL(register_virtio_driver); +EXPORT_SYMBOL_GPL(__register_virtio_driver); void unregister_virtio_driver(struct virtio_driver *driver) { diff --git a/include/linux/virtio.h b/include/linux/virtio.h index b0201747a263..26c4325aa373 100644 --- a/include/linux/virtio.h +++ b/include/linux/virtio.h @@ -170,7 +170,7 @@ size_t virtio_max_dma_size(const struct virtio_device *vdev); /** * struct virtio_driver - operations for a virtio I/O driver - * @driver: underlying device driver (populate name and owner). + * @driver: underlying device driver (populate name). * @id_table: the ids serviced by this driver. * @feature_table: an array of feature numbers supported by this driver. * @feature_table_size: number of entries in the feature table array. @@ -208,7 +208,10 @@ static inline struct virtio_driver *drv_to_virtio(struct device_driver *drv) return container_of(drv, struct virtio_driver, driver); } -int register_virtio_driver(struct virtio_driver *drv); +/* use a macro to avoid include chaining to get THIS_MODULE */ +#define register_virtio_driver(drv) \ + __register_virtio_driver(drv, THIS_MODULE) +int __register_virtio_driver(struct virtio_driver *drv, struct module *owner); void unregister_virtio_driver(struct virtio_driver *drv); /* module_virtio_driver() - Helper macro for drivers that don't do -- cgit v1.2.3 From 2855c2a7820bc8198ae937a9a67dbdc3990e9d2c Mon Sep 17 00:00:00 2001 From: "Michael S. Tsirkin" Date: Tue, 2 Apr 2024 17:21:43 -0400 Subject: vhost-vdpa: change ioctl # for VDPA_GET_VRING_SIZE MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit VDPA_GET_VRING_SIZE by mistake uses the already occupied ioctl # 0x80 and we never noticed - it happens to work because the direction and size are different, but confuses tools such as perf which like to look at just the number, and breaks the extra robustness of the ioctl numbering macros. To fix, sort the entries and renumber the ioctl - not too late since it wasn't in any released kernels yet. Cc: Arnaldo Carvalho de Melo Reported-by: Namhyung Kim Fixes: 1496c47065f9 ("vhost-vdpa: uapi to support reporting per vq size") Cc: "Zhu Lingshan" Signed-off-by: Michael S. Tsirkin Message-Id: <41c1c5489688abe5bfef9f7cf15584e3fb872ac5.1712092759.git.mst@redhat.com> Reviewed-by: Eugenio Pérez Reviewed-by: Zhu Lingshan Reviewed-by: Stefano Garzarella Acked-by: Jason Wang --- include/uapi/linux/vhost.h | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/include/uapi/linux/vhost.h b/include/uapi/linux/vhost.h index bea697390613..b95dd84eef2d 100644 --- a/include/uapi/linux/vhost.h +++ b/include/uapi/linux/vhost.h @@ -179,12 +179,6 @@ /* Get the config size */ #define VHOST_VDPA_GET_CONFIG_SIZE _IOR(VHOST_VIRTIO, 0x79, __u32) -/* Get the count of all virtqueues */ -#define VHOST_VDPA_GET_VQS_COUNT _IOR(VHOST_VIRTIO, 0x80, __u32) - -/* Get the number of virtqueue groups. */ -#define VHOST_VDPA_GET_GROUP_NUM _IOR(VHOST_VIRTIO, 0x81, __u32) - /* Get the number of address spaces. */ #define VHOST_VDPA_GET_AS_NUM _IOR(VHOST_VIRTIO, 0x7A, unsigned int) @@ -228,10 +222,17 @@ #define VHOST_VDPA_GET_VRING_DESC_GROUP _IOWR(VHOST_VIRTIO, 0x7F, \ struct vhost_vring_state) + +/* Get the count of all virtqueues */ +#define VHOST_VDPA_GET_VQS_COUNT _IOR(VHOST_VIRTIO, 0x80, __u32) + +/* Get the number of virtqueue groups. */ +#define VHOST_VDPA_GET_GROUP_NUM _IOR(VHOST_VIRTIO, 0x81, __u32) + /* Get the queue size of a specific virtqueue. * userspace set the vring index in vhost_vring_state.index * kernel set the queue size in vhost_vring_state.num */ -#define VHOST_VDPA_GET_VRING_SIZE _IOWR(VHOST_VIRTIO, 0x80, \ +#define VHOST_VDPA_GET_VRING_SIZE _IOWR(VHOST_VIRTIO, 0x82, \ struct vhost_vring_state) #endif -- cgit v1.2.3 From 76f408535aab39c33e0a1dcada9fba5631c65595 Mon Sep 17 00:00:00 2001 From: Xianting Tian Date: Mon, 11 Mar 2024 16:21:09 +0800 Subject: vhost: correct misleading printing information Guest moved avail idx not used idx when we need to print log if '(vq->avail_idx - last_avail_idx) > vq->num', so fix it. Signed-off-by: Xianting Tian Message-Id: <20240311082109.46773-1-xianting.tian@linux.alibaba.com> Signed-off-by: Michael S. Tsirkin --- drivers/vhost/vhost.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/vhost/vhost.c b/drivers/vhost/vhost.c index 32686c79c41d..8995730ce0bf 100644 --- a/drivers/vhost/vhost.c +++ b/drivers/vhost/vhost.c @@ -2515,7 +2515,7 @@ int vhost_get_vq_desc(struct vhost_virtqueue *vq, vq->avail_idx = vhost16_to_cpu(vq, avail_idx); if (unlikely((u16)(vq->avail_idx - last_avail_idx) > vq->num)) { - vq_err(vq, "Guest moved used index from %u to %u", + vq_err(vq, "Guest moved avail index from %u to %u", last_avail_idx, vq->avail_idx); return -EFAULT; } -- cgit v1.2.3 From f0cf7ffcd02953c72fed5995378805883d16203e Mon Sep 17 00:00:00 2001 From: "Wachowski, Karol" Date: Tue, 2 Apr 2024 12:49:22 +0200 Subject: accel/ivpu: Check return code of ipc->lock init Return value of drmm_mutex_init(ipc->lock) was unchecked. Fixes: 5d7422cfb498 ("accel/ivpu: Add IPC driver and JSM messages") Cc: # v6.3+ Signed-off-by: Wachowski, Karol Signed-off-by: Jacek Lawrynowicz Reviewed-by: Jeffrey Hugo Link: https://patchwork.freedesktop.org/patch/msgid/20240402104929.941186-2-jacek.lawrynowicz@linux.intel.com --- drivers/accel/ivpu/ivpu_ipc.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/drivers/accel/ivpu/ivpu_ipc.c b/drivers/accel/ivpu/ivpu_ipc.c index 04ac4b9840fb..56ff067f63e2 100644 --- a/drivers/accel/ivpu/ivpu_ipc.c +++ b/drivers/accel/ivpu/ivpu_ipc.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (C) 2020-2023 Intel Corporation + * Copyright (C) 2020-2024 Intel Corporation */ #include @@ -501,7 +501,11 @@ int ivpu_ipc_init(struct ivpu_device *vdev) spin_lock_init(&ipc->cons_lock); INIT_LIST_HEAD(&ipc->cons_list); INIT_LIST_HEAD(&ipc->cb_msg_list); - drmm_mutex_init(&vdev->drm, &ipc->lock); + ret = drmm_mutex_init(&vdev->drm, &ipc->lock); + if (ret) { + ivpu_err(vdev, "Failed to initialize ipc->lock, ret %d\n", ret); + goto err_free_rx; + } ivpu_ipc_reset(vdev); return 0; -- cgit v1.2.3 From e3caadf1f9dfc9d62b5ffc3bd73ebac0c8f26b3f Mon Sep 17 00:00:00 2001 From: Jacek Lawrynowicz Date: Tue, 2 Apr 2024 12:49:23 +0200 Subject: accel/ivpu: Remove d3hot_after_power_off WA Always enter D3hot after entering D0i3 an all platforms. This minimizes power usage. Signed-off-by: Jacek Lawrynowicz Reviewed-by: Jeffrey Hugo Link: https://patchwork.freedesktop.org/patch/msgid/20240402104929.941186-3-jacek.lawrynowicz@linux.intel.com --- drivers/accel/ivpu/ivpu_drv.c | 20 ++++++++++---------- drivers/accel/ivpu/ivpu_drv.h | 3 +-- drivers/accel/ivpu/ivpu_hw_37xx.c | 4 +--- drivers/accel/ivpu/ivpu_pm.c | 7 ++----- 4 files changed, 14 insertions(+), 20 deletions(-) diff --git a/drivers/accel/ivpu/ivpu_drv.c b/drivers/accel/ivpu/ivpu_drv.c index 39f6d1b98fd6..303d92753387 100644 --- a/drivers/accel/ivpu/ivpu_drv.c +++ b/drivers/accel/ivpu/ivpu_drv.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (C) 2020-2023 Intel Corporation + * Copyright (C) 2020-2024 Intel Corporation */ #include @@ -387,12 +387,15 @@ int ivpu_shutdown(struct ivpu_device *vdev) { int ret; - ivpu_prepare_for_reset(vdev); + /* Save PCI state before powering down as it sometimes gets corrupted if NPU hangs */ + pci_save_state(to_pci_dev(vdev->drm.dev)); ret = ivpu_hw_power_down(vdev); if (ret) ivpu_warn(vdev, "Failed to power down HW: %d\n", ret); + pci_set_power_state(to_pci_dev(vdev->drm.dev), PCI_D3hot); + return ret; } @@ -560,11 +563,11 @@ static int ivpu_dev_init(struct ivpu_device *vdev) /* Power up early so the rest of init code can access VPU registers */ ret = ivpu_hw_power_up(vdev); if (ret) - goto err_power_down; + goto err_shutdown; ret = ivpu_mmu_global_context_init(vdev); if (ret) - goto err_power_down; + goto err_shutdown; ret = ivpu_mmu_init(vdev); if (ret) @@ -601,10 +604,8 @@ err_mmu_rctx_fini: ivpu_mmu_reserved_context_fini(vdev); err_mmu_gctx_fini: ivpu_mmu_global_context_fini(vdev); -err_power_down: - ivpu_hw_power_down(vdev); - if (IVPU_WA(d3hot_after_power_off)) - pci_set_power_state(to_pci_dev(vdev->drm.dev), PCI_D3hot); +err_shutdown: + ivpu_shutdown(vdev); err_xa_destroy: xa_destroy(&vdev->db_xa); xa_destroy(&vdev->submitted_jobs_xa); @@ -628,9 +629,8 @@ static void ivpu_bo_unbind_all_user_contexts(struct ivpu_device *vdev) static void ivpu_dev_fini(struct ivpu_device *vdev) { ivpu_pm_disable(vdev); + ivpu_prepare_for_reset(vdev); ivpu_shutdown(vdev); - if (IVPU_WA(d3hot_after_power_off)) - pci_set_power_state(to_pci_dev(vdev->drm.dev), PCI_D3hot); ivpu_jobs_abort_all(vdev); ivpu_job_done_consumer_fini(vdev); diff --git a/drivers/accel/ivpu/ivpu_drv.h b/drivers/accel/ivpu/ivpu_drv.h index 7be0500d9bb8..bb4374d0eaec 100644 --- a/drivers/accel/ivpu/ivpu_drv.h +++ b/drivers/accel/ivpu/ivpu_drv.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (C) 2020-2023 Intel Corporation + * Copyright (C) 2020-2024 Intel Corporation */ #ifndef __IVPU_DRV_H__ @@ -90,7 +90,6 @@ struct ivpu_wa_table { bool punit_disabled; bool clear_runtime_mem; - bool d3hot_after_power_off; bool interrupt_clear_with_0; bool disable_clock_relinquish; bool disable_d0i3_msg; diff --git a/drivers/accel/ivpu/ivpu_hw_37xx.c b/drivers/accel/ivpu/ivpu_hw_37xx.c index 9a0c9498baba..5e2865f9f7d6 100644 --- a/drivers/accel/ivpu/ivpu_hw_37xx.c +++ b/drivers/accel/ivpu/ivpu_hw_37xx.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (C) 2020-2023 Intel Corporation + * Copyright (C) 2020-2024 Intel Corporation */ #include "ivpu_drv.h" @@ -75,7 +75,6 @@ static void ivpu_hw_wa_init(struct ivpu_device *vdev) { vdev->wa.punit_disabled = false; vdev->wa.clear_runtime_mem = false; - vdev->wa.d3hot_after_power_off = true; REGB_WR32(VPU_37XX_BUTTRESS_INTERRUPT_STAT, BUTTRESS_ALL_IRQ_MASK); if (REGB_RD32(VPU_37XX_BUTTRESS_INTERRUPT_STAT) == BUTTRESS_ALL_IRQ_MASK) { @@ -86,7 +85,6 @@ static void ivpu_hw_wa_init(struct ivpu_device *vdev) IVPU_PRINT_WA(punit_disabled); IVPU_PRINT_WA(clear_runtime_mem); - IVPU_PRINT_WA(d3hot_after_power_off); IVPU_PRINT_WA(interrupt_clear_with_0); } diff --git a/drivers/accel/ivpu/ivpu_pm.c b/drivers/accel/ivpu/ivpu_pm.c index 7cce1c928a7f..9cbd7af6576b 100644 --- a/drivers/accel/ivpu/ivpu_pm.c +++ b/drivers/accel/ivpu/ivpu_pm.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (C) 2020-2023 Intel Corporation + * Copyright (C) 2020-2024 Intel Corporation */ #include @@ -58,15 +58,12 @@ static int ivpu_suspend(struct ivpu_device *vdev) { int ret; - /* Save PCI state before powering down as it sometimes gets corrupted if NPU hangs */ - pci_save_state(to_pci_dev(vdev->drm.dev)); + ivpu_prepare_for_reset(vdev); ret = ivpu_shutdown(vdev); if (ret) ivpu_err(vdev, "Failed to shutdown VPU: %d\n", ret); - pci_set_power_state(to_pci_dev(vdev->drm.dev), PCI_D3hot); - return ret; } -- cgit v1.2.3 From 3534eacbf101f6e66105f03d869a03893407c384 Mon Sep 17 00:00:00 2001 From: "Wachowski, Karol" Date: Tue, 2 Apr 2024 12:49:24 +0200 Subject: accel/ivpu: Fix PCI D0 state entry in resume In case of failed power up we end up left in PCI D3hot state making it impossible to access NPU registers on retry. Enter D0 state on retry before proceeding with power up sequence. Fixes: 28083ff18d3f ("accel/ivpu: Fix DevTLB errors on suspend/resume and recovery") Cc: # v6.8+ Signed-off-by: Wachowski, Karol Signed-off-by: Jacek Lawrynowicz Reviewed-by: Jeffrey Hugo Link: https://patchwork.freedesktop.org/patch/msgid/20240402104929.941186-4-jacek.lawrynowicz@linux.intel.com --- drivers/accel/ivpu/ivpu_pm.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/accel/ivpu/ivpu_pm.c b/drivers/accel/ivpu/ivpu_pm.c index 9cbd7af6576b..325b82f8d971 100644 --- a/drivers/accel/ivpu/ivpu_pm.c +++ b/drivers/accel/ivpu/ivpu_pm.c @@ -71,10 +71,10 @@ static int ivpu_resume(struct ivpu_device *vdev) { int ret; - pci_set_power_state(to_pci_dev(vdev->drm.dev), PCI_D0); +retry: pci_restore_state(to_pci_dev(vdev->drm.dev)); + pci_set_power_state(to_pci_dev(vdev->drm.dev), PCI_D0); -retry: ret = ivpu_hw_power_up(vdev); if (ret) { ivpu_err(vdev, "Failed to power up HW: %d\n", ret); -- cgit v1.2.3 From 875bc9cd1b33eb027a5663f5e6878a43d98e9a16 Mon Sep 17 00:00:00 2001 From: Jacek Lawrynowicz Date: Tue, 2 Apr 2024 12:49:25 +0200 Subject: accel/ivpu: Put NPU back to D3hot after failed resume Put NPU in D3hot after ivpu_resume() fails to power up the device. This will assure that D3->D0 power cycle will be performed before the next resume and also will minimize power usage in this corner case. Fixes: 28083ff18d3f ("accel/ivpu: Fix DevTLB errors on suspend/resume and recovery") Cc: # v6.8+ Signed-off-by: Jacek Lawrynowicz Reviewed-by: Jeffrey Hugo Link: https://patchwork.freedesktop.org/patch/msgid/20240402104929.941186-5-jacek.lawrynowicz@linux.intel.com --- drivers/accel/ivpu/ivpu_pm.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/accel/ivpu/ivpu_pm.c b/drivers/accel/ivpu/ivpu_pm.c index 325b82f8d971..ba51781b5896 100644 --- a/drivers/accel/ivpu/ivpu_pm.c +++ b/drivers/accel/ivpu/ivpu_pm.c @@ -97,6 +97,7 @@ err_mmu_disable: ivpu_mmu_disable(vdev); err_power_down: ivpu_hw_power_down(vdev); + pci_set_power_state(to_pci_dev(vdev->drm.dev), PCI_D3hot); if (!ivpu_fw_is_cold_boot(vdev)) { ivpu_pm_prepare_cold_boot(vdev); -- cgit v1.2.3 From 3556f922612caf4c9b97cf7337626f8342b3dea3 Mon Sep 17 00:00:00 2001 From: "Wachowski, Karol" Date: Tue, 2 Apr 2024 12:49:26 +0200 Subject: accel/ivpu: Improve clarity of MMU error messages This patch improves readability and clarity of MMU error messages. Previously, the error strings were somewhat confusing and could lead to ambiguous interpretations, making it difficult to diagnose issues. Signed-off-by: Wachowski, Karol Signed-off-by: Jacek Lawrynowicz Reviewed-by: Jeffrey Hugo Link: https://patchwork.freedesktop.org/patch/msgid/20240402104929.941186-6-jacek.lawrynowicz@linux.intel.com --- drivers/accel/ivpu/ivpu_mmu.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/accel/ivpu/ivpu_mmu.c b/drivers/accel/ivpu/ivpu_mmu.c index 91bd640655ab..2e46b322c450 100644 --- a/drivers/accel/ivpu/ivpu_mmu.c +++ b/drivers/accel/ivpu/ivpu_mmu.c @@ -278,7 +278,7 @@ static const char *ivpu_mmu_event_to_str(u32 cmd) case IVPU_MMU_EVT_F_VMS_FETCH: return "Fetch of VMS caused external abort"; default: - return "Unknown CMDQ command"; + return "Unknown event"; } } @@ -286,15 +286,15 @@ static const char *ivpu_mmu_cmdq_err_to_str(u32 err) { switch (err) { case IVPU_MMU_CERROR_NONE: - return "No CMDQ Error"; + return "No error"; case IVPU_MMU_CERROR_ILL: return "Illegal command"; case IVPU_MMU_CERROR_ABT: - return "External abort on CMDQ read"; + return "External abort on command queue read"; case IVPU_MMU_CERROR_ATC_INV_SYNC: return "Sync failed to complete ATS invalidation"; default: - return "Unknown CMDQ Error"; + return "Unknown error"; } } -- cgit v1.2.3 From c52c35e5b404b95a5bcff39af9be1b9293be3434 Mon Sep 17 00:00:00 2001 From: Jacek Lawrynowicz Date: Tue, 2 Apr 2024 12:49:27 +0200 Subject: accel/ivpu: Return max freq for DRM_IVPU_PARAM_CORE_CLOCK_RATE DRM_IVPU_PARAM_CORE_CLOCK_RATE returns current NPU frequency which could be 0 if device was sleeping. This value isn't really useful to the user space, so return max freq instead which can be used to estimate NPU performance. Fixes: c39dc15191c4 ("accel/ivpu: Read clock rate only if device is up") Cc: # v6.7 Signed-off-by: Jacek Lawrynowicz Reviewed-by: Jeffrey Hugo Link: https://patchwork.freedesktop.org/patch/msgid/20240402104929.941186-7-jacek.lawrynowicz@linux.intel.com --- drivers/accel/ivpu/ivpu_drv.c | 18 +----------------- drivers/accel/ivpu/ivpu_hw.h | 6 ++++++ drivers/accel/ivpu/ivpu_hw_37xx.c | 7 ++++--- drivers/accel/ivpu/ivpu_hw_40xx.c | 6 ++++++ 4 files changed, 17 insertions(+), 20 deletions(-) diff --git a/drivers/accel/ivpu/ivpu_drv.c b/drivers/accel/ivpu/ivpu_drv.c index 303d92753387..77283daaedd1 100644 --- a/drivers/accel/ivpu/ivpu_drv.c +++ b/drivers/accel/ivpu/ivpu_drv.c @@ -131,22 +131,6 @@ static int ivpu_get_capabilities(struct ivpu_device *vdev, struct drm_ivpu_param return 0; } -static int ivpu_get_core_clock_rate(struct ivpu_device *vdev, u64 *clk_rate) -{ - int ret; - - ret = ivpu_rpm_get_if_active(vdev); - if (ret < 0) - return ret; - - *clk_rate = ret ? ivpu_hw_reg_pll_freq_get(vdev) : 0; - - if (ret) - ivpu_rpm_put(vdev); - - return 0; -} - static int ivpu_get_param_ioctl(struct drm_device *dev, void *data, struct drm_file *file) { struct ivpu_file_priv *file_priv = file->driver_priv; @@ -170,7 +154,7 @@ static int ivpu_get_param_ioctl(struct drm_device *dev, void *data, struct drm_f args->value = vdev->platform; break; case DRM_IVPU_PARAM_CORE_CLOCK_RATE: - ret = ivpu_get_core_clock_rate(vdev, &args->value); + args->value = ivpu_hw_ratio_to_freq(vdev, vdev->hw->pll.max_ratio); break; case DRM_IVPU_PARAM_NUM_CONTEXTS: args->value = ivpu_get_context_count(vdev); diff --git a/drivers/accel/ivpu/ivpu_hw.h b/drivers/accel/ivpu/ivpu_hw.h index b2909168a0a6..094c659d2800 100644 --- a/drivers/accel/ivpu/ivpu_hw.h +++ b/drivers/accel/ivpu/ivpu_hw.h @@ -21,6 +21,7 @@ struct ivpu_hw_ops { u32 (*profiling_freq_get)(struct ivpu_device *vdev); void (*profiling_freq_drive)(struct ivpu_device *vdev, bool enable); u32 (*reg_pll_freq_get)(struct ivpu_device *vdev); + u32 (*ratio_to_freq)(struct ivpu_device *vdev, u32 ratio); u32 (*reg_telemetry_offset_get)(struct ivpu_device *vdev); u32 (*reg_telemetry_size_get)(struct ivpu_device *vdev); u32 (*reg_telemetry_enable_get)(struct ivpu_device *vdev); @@ -130,6 +131,11 @@ static inline u32 ivpu_hw_reg_pll_freq_get(struct ivpu_device *vdev) return vdev->hw->ops->reg_pll_freq_get(vdev); }; +static inline u32 ivpu_hw_ratio_to_freq(struct ivpu_device *vdev, u32 ratio) +{ + return vdev->hw->ops->ratio_to_freq(vdev, ratio); +} + static inline u32 ivpu_hw_reg_telemetry_offset_get(struct ivpu_device *vdev) { return vdev->hw->ops->reg_telemetry_offset_get(vdev); diff --git a/drivers/accel/ivpu/ivpu_hw_37xx.c b/drivers/accel/ivpu/ivpu_hw_37xx.c index 5e2865f9f7d6..bd25e2d9fb0f 100644 --- a/drivers/accel/ivpu/ivpu_hw_37xx.c +++ b/drivers/accel/ivpu/ivpu_hw_37xx.c @@ -803,12 +803,12 @@ static void ivpu_hw_37xx_profiling_freq_drive(struct ivpu_device *vdev, bool ena /* Profiling freq - is a debug feature. Unavailable on VPU 37XX. */ } -static u32 ivpu_hw_37xx_pll_to_freq(u32 ratio, u32 config) +static u32 ivpu_hw_37xx_ratio_to_freq(struct ivpu_device *vdev, u32 ratio) { u32 pll_clock = PLL_REF_CLK_FREQ * ratio; u32 cpu_clock; - if ((config & 0xff) == PLL_RATIO_4_3) + if ((vdev->hw->config & 0xff) == PLL_RATIO_4_3) cpu_clock = pll_clock * 2 / 4; else cpu_clock = pll_clock * 2 / 5; @@ -827,7 +827,7 @@ static u32 ivpu_hw_37xx_reg_pll_freq_get(struct ivpu_device *vdev) if (!ivpu_is_silicon(vdev)) return PLL_SIMULATION_FREQ; - return ivpu_hw_37xx_pll_to_freq(pll_curr_ratio, vdev->hw->config); + return ivpu_hw_37xx_ratio_to_freq(vdev, pll_curr_ratio); } static u32 ivpu_hw_37xx_reg_telemetry_offset_get(struct ivpu_device *vdev) @@ -1050,6 +1050,7 @@ const struct ivpu_hw_ops ivpu_hw_37xx_ops = { .profiling_freq_get = ivpu_hw_37xx_profiling_freq_get, .profiling_freq_drive = ivpu_hw_37xx_profiling_freq_drive, .reg_pll_freq_get = ivpu_hw_37xx_reg_pll_freq_get, + .ratio_to_freq = ivpu_hw_37xx_ratio_to_freq, .reg_telemetry_offset_get = ivpu_hw_37xx_reg_telemetry_offset_get, .reg_telemetry_size_get = ivpu_hw_37xx_reg_telemetry_size_get, .reg_telemetry_enable_get = ivpu_hw_37xx_reg_telemetry_enable_get, diff --git a/drivers/accel/ivpu/ivpu_hw_40xx.c b/drivers/accel/ivpu/ivpu_hw_40xx.c index e4eddbf5d11c..b0b88d4c8926 100644 --- a/drivers/accel/ivpu/ivpu_hw_40xx.c +++ b/drivers/accel/ivpu/ivpu_hw_40xx.c @@ -980,6 +980,11 @@ static u32 ivpu_hw_40xx_reg_pll_freq_get(struct ivpu_device *vdev) return PLL_RATIO_TO_FREQ(pll_curr_ratio); } +static u32 ivpu_hw_40xx_ratio_to_freq(struct ivpu_device *vdev, u32 ratio) +{ + return PLL_RATIO_TO_FREQ(ratio); +} + static u32 ivpu_hw_40xx_reg_telemetry_offset_get(struct ivpu_device *vdev) { return REGB_RD32(VPU_40XX_BUTTRESS_VPU_TELEMETRY_OFFSET); @@ -1230,6 +1235,7 @@ const struct ivpu_hw_ops ivpu_hw_40xx_ops = { .profiling_freq_get = ivpu_hw_40xx_profiling_freq_get, .profiling_freq_drive = ivpu_hw_40xx_profiling_freq_drive, .reg_pll_freq_get = ivpu_hw_40xx_reg_pll_freq_get, + .ratio_to_freq = ivpu_hw_40xx_ratio_to_freq, .reg_telemetry_offset_get = ivpu_hw_40xx_reg_telemetry_offset_get, .reg_telemetry_size_get = ivpu_hw_40xx_reg_telemetry_size_get, .reg_telemetry_enable_get = ivpu_hw_40xx_reg_telemetry_enable_get, -- cgit v1.2.3 From 0d298e23292b7a5b58c5589fe33b96e95363214f Mon Sep 17 00:00:00 2001 From: Jacek Lawrynowicz Date: Tue, 2 Apr 2024 12:49:28 +0200 Subject: accel/ivpu: Fix missed error message after VPU rename Change "VPU" to "NPU" in ivpu_suspend() so it matches all other error messages. Signed-off-by: Jacek Lawrynowicz Reviewed-by: Jeffrey Hugo Link: https://patchwork.freedesktop.org/patch/msgid/20240402104929.941186-8-jacek.lawrynowicz@linux.intel.com --- drivers/accel/ivpu/ivpu_pm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/accel/ivpu/ivpu_pm.c b/drivers/accel/ivpu/ivpu_pm.c index ba51781b5896..4f5ea466731f 100644 --- a/drivers/accel/ivpu/ivpu_pm.c +++ b/drivers/accel/ivpu/ivpu_pm.c @@ -62,7 +62,7 @@ static int ivpu_suspend(struct ivpu_device *vdev) ret = ivpu_shutdown(vdev); if (ret) - ivpu_err(vdev, "Failed to shutdown VPU: %d\n", ret); + ivpu_err(vdev, "Failed to shutdown NPU: %d\n", ret); return ret; } -- cgit v1.2.3 From fd7726e75968b27fe98534ccbf47ccd6fef686f3 Mon Sep 17 00:00:00 2001 From: Jacek Lawrynowicz Date: Tue, 2 Apr 2024 12:49:29 +0200 Subject: accel/ivpu: Fix deadlock in context_xa ivpu_device->context_xa is locked both in kernel thread and IRQ context. It requires XA_FLAGS_LOCK_IRQ flag to be passed during initialization otherwise the lock could be acquired from a thread and interrupted by an IRQ that locks it for the second time causing the deadlock. This deadlock was reported by lockdep and observed in internal tests. Fixes: 35b137630f08 ("accel/ivpu: Introduce a new DRM driver for Intel VPU") Cc: # v6.3+ Signed-off-by: Jacek Lawrynowicz Reviewed-by: Jeffrey Hugo Link: https://patchwork.freedesktop.org/patch/msgid/20240402104929.941186-9-jacek.lawrynowicz@linux.intel.com --- drivers/accel/ivpu/ivpu_drv.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/accel/ivpu/ivpu_drv.c b/drivers/accel/ivpu/ivpu_drv.c index 77283daaedd1..51d3f1a55d02 100644 --- a/drivers/accel/ivpu/ivpu_drv.c +++ b/drivers/accel/ivpu/ivpu_drv.c @@ -517,7 +517,7 @@ static int ivpu_dev_init(struct ivpu_device *vdev) vdev->context_xa_limit.min = IVPU_USER_CONTEXT_MIN_SSID; vdev->context_xa_limit.max = IVPU_USER_CONTEXT_MAX_SSID; atomic64_set(&vdev->unique_id_counter, 0); - xa_init_flags(&vdev->context_xa, XA_FLAGS_ALLOC); + xa_init_flags(&vdev->context_xa, XA_FLAGS_ALLOC | XA_FLAGS_LOCK_IRQ); xa_init_flags(&vdev->submitted_jobs_xa, XA_FLAGS_ALLOC1); xa_init_flags(&vdev->db_xa, XA_FLAGS_ALLOC1); lockdep_set_class(&vdev->submitted_jobs_xa.xa_lock, &submitted_jobs_xa_lock_class_key); -- cgit v1.2.3 From e9d47b7b31563a6524b9f64ea70ed0289cc4d9c4 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Thu, 4 Apr 2024 18:36:45 +0200 Subject: lib: checksum: hide unused expected_csum_ipv6_magic[] When CONFIG_NET is disabled, an extra warning shows up for this unused variable: lib/checksum_kunit.c:218:18: error: 'expected_csum_ipv6_magic' defined but not used [-Werror=unused-const-variable=] Replace the #ifdef with an IS_ENABLED() check that makes the compiler's dead-code-elimination take care of the link failure. Fixes: f24a70106dc1 ("lib: checksum: Fix build with CONFIG_NET=n") Suggested-by: Christophe Leroy Acked-by: Palmer Dabbelt Acked-by: Jakub Kicinski Signed-off-by: Arnd Bergmann Reviewed-by: Simon Horman Tested-by: Simon Horman # build-tested Signed-off-by: David S. Miller --- lib/checksum_kunit.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/lib/checksum_kunit.c b/lib/checksum_kunit.c index bf70850035c7..404dba36bae3 100644 --- a/lib/checksum_kunit.c +++ b/lib/checksum_kunit.c @@ -594,13 +594,15 @@ static void test_ip_fast_csum(struct kunit *test) static void test_csum_ipv6_magic(struct kunit *test) { -#if defined(CONFIG_NET) const struct in6_addr *saddr; const struct in6_addr *daddr; unsigned int len; unsigned char proto; __wsum csum; + if (!IS_ENABLED(CONFIG_NET)) + return; + const int daddr_offset = sizeof(struct in6_addr); const int len_offset = sizeof(struct in6_addr) + sizeof(struct in6_addr); const int proto_offset = sizeof(struct in6_addr) + sizeof(struct in6_addr) + @@ -618,7 +620,6 @@ static void test_csum_ipv6_magic(struct kunit *test) CHECK_EQ(to_sum16(expected_csum_ipv6_magic[i]), csum_ipv6_magic(saddr, daddr, len, proto, csum)); } -#endif /* !CONFIG_NET */ } static struct kunit_case __refdata checksum_test_cases[] = { -- cgit v1.2.3 From be121ffb384f53e966ee7299ffccc6eeb61bc73d Mon Sep 17 00:00:00 2001 From: Michael Guralnik Date: Wed, 3 Apr 2024 12:03:46 +0300 Subject: RDMA/mlx5: Fix port number for counter query in multi-port configuration Set the correct port when querying PPCNT in multi-port configuration. Distinguish between cases where switchdev mode was enabled to multi-port configuration and don't overwrite the queried port to 1 in multi-port case. Fixes: 74b30b3ad5ce ("RDMA/mlx5: Set local port to one when accessing counters") Signed-off-by: Michael Guralnik Link: https://lore.kernel.org/r/9bfcc8ade958b760a51408c3ad654a01b11f7d76.1712134988.git.leon@kernel.org Signed-off-by: Leon Romanovsky --- drivers/infiniband/hw/mlx5/mad.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/infiniband/hw/mlx5/mad.c b/drivers/infiniband/hw/mlx5/mad.c index 0c3c4e64812c..3e43687a7f6f 100644 --- a/drivers/infiniband/hw/mlx5/mad.c +++ b/drivers/infiniband/hw/mlx5/mad.c @@ -188,7 +188,8 @@ static int process_pma_cmd(struct mlx5_ib_dev *dev, u32 port_num, mdev = dev->mdev; mdev_port_num = 1; } - if (MLX5_CAP_GEN(dev->mdev, num_ports) == 1) { + if (MLX5_CAP_GEN(dev->mdev, num_ports) == 1 && + !mlx5_core_mp_enabled(mdev)) { /* set local port to one for Function-Per-Port HCA. */ mdev = dev->mdev; mdev_port_num = 1; -- cgit v1.2.3 From eaac25d026a14be4fe97683103f2a3ae76bff7bd Mon Sep 17 00:00:00 2001 From: Uwe Kleine-König Date: Fri, 5 Apr 2024 09:20:41 +0200 Subject: MAINTAINERS: Drop Li Yang as their email address stopped working MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When sending a patch to (among others) Li Yang the nxp MTA replied that the address doesn't exist and so the mail couldn't be delivered. The error code was 550, so at least technically that's not a temporal issue. Signed-off-by: Uwe Kleine-König Signed-off-by: David S. Miller --- MAINTAINERS | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/MAINTAINERS b/MAINTAINERS index 75381386fe4c..f389bf6d78a3 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -2191,7 +2191,6 @@ N: mxs ARM/FREESCALE LAYERSCAPE ARM ARCHITECTURE M: Shawn Guo -M: Li Yang L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) S: Maintained T: git git://git.kernel.org/pub/scm/linux/kernel/git/shawnguo/linux.git @@ -8523,7 +8522,6 @@ S: Maintained F: drivers/video/fbdev/fsl-diu-fb.* FREESCALE DMA DRIVER -M: Li Yang M: Zhang Wei L: linuxppc-dev@lists.ozlabs.org S: Maintained @@ -8688,10 +8686,9 @@ F: drivers/soc/fsl/qe/tsa.h F: include/dt-bindings/soc/cpm1-fsl,tsa.h FREESCALE QUICC ENGINE UCC ETHERNET DRIVER -M: Li Yang L: netdev@vger.kernel.org L: linuxppc-dev@lists.ozlabs.org -S: Maintained +S: Orphan F: drivers/net/ethernet/freescale/ucc_geth* FREESCALE QUICC ENGINE UCC HDLC DRIVER @@ -8708,10 +8705,9 @@ S: Maintained F: drivers/tty/serial/ucc_uart.c FREESCALE SOC DRIVERS -M: Li Yang L: linuxppc-dev@lists.ozlabs.org L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) -S: Maintained +S: Orphan F: Documentation/devicetree/bindings/misc/fsl,dpaa2-console.yaml F: Documentation/devicetree/bindings/soc/fsl/ F: drivers/soc/fsl/ @@ -8745,10 +8741,9 @@ F: Documentation/devicetree/bindings/sound/fsl,qmc-audio.yaml F: sound/soc/fsl/fsl_qmc_audio.c FREESCALE USB PERIPHERAL DRIVERS -M: Li Yang L: linux-usb@vger.kernel.org L: linuxppc-dev@lists.ozlabs.org -S: Maintained +S: Orphan F: drivers/usb/gadget/udc/fsl* FREESCALE USB PHY DRIVER -- cgit v1.2.3 From d8a6213d70accb403b82924a1c229e733433a5ef Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Fri, 5 Apr 2024 10:30:34 +0000 Subject: geneve: fix header validation in geneve[6]_xmit_skb syzbot is able to trigger an uninit-value in geneve_xmit() [1] Problem : While most ip tunnel helpers (like ip_tunnel_get_dsfield()) uses skb_protocol(skb, true), pskb_inet_may_pull() is only using skb->protocol. If anything else than ETH_P_IPV6 or ETH_P_IP is found in skb->protocol, pskb_inet_may_pull() does nothing at all. If a vlan tag was provided by the caller (af_packet in the syzbot case), the network header might not point to the correct location, and skb linear part could be smaller than expected. Add skb_vlan_inet_prepare() to perform a complete mac validation. Use this in geneve for the moment, I suspect we need to adopt this more broadly. v4 - Jakub reported v3 broke l2_tos_ttl_inherit.sh selftest - Only call __vlan_get_protocol() for vlan types. Link: https://lore.kernel.org/netdev/20240404100035.3270a7d5@kernel.org/ v2,v3 - Addressed Sabrina comments on v1 and v2 Link: https://lore.kernel.org/netdev/Zg1l9L2BNoZWZDZG@hog/ [1] BUG: KMSAN: uninit-value in geneve_xmit_skb drivers/net/geneve.c:910 [inline] BUG: KMSAN: uninit-value in geneve_xmit+0x302d/0x5420 drivers/net/geneve.c:1030 geneve_xmit_skb drivers/net/geneve.c:910 [inline] geneve_xmit+0x302d/0x5420 drivers/net/geneve.c:1030 __netdev_start_xmit include/linux/netdevice.h:4903 [inline] netdev_start_xmit include/linux/netdevice.h:4917 [inline] xmit_one net/core/dev.c:3531 [inline] dev_hard_start_xmit+0x247/0xa20 net/core/dev.c:3547 __dev_queue_xmit+0x348d/0x52c0 net/core/dev.c:4335 dev_queue_xmit include/linux/netdevice.h:3091 [inline] packet_xmit+0x9c/0x6c0 net/packet/af_packet.c:276 packet_snd net/packet/af_packet.c:3081 [inline] packet_sendmsg+0x8bb0/0x9ef0 net/packet/af_packet.c:3113 sock_sendmsg_nosec net/socket.c:730 [inline] __sock_sendmsg+0x30f/0x380 net/socket.c:745 __sys_sendto+0x685/0x830 net/socket.c:2191 __do_sys_sendto net/socket.c:2203 [inline] __se_sys_sendto net/socket.c:2199 [inline] __x64_sys_sendto+0x125/0x1d0 net/socket.c:2199 do_syscall_64+0xd5/0x1f0 entry_SYSCALL_64_after_hwframe+0x6d/0x75 Uninit was created at: slab_post_alloc_hook mm/slub.c:3804 [inline] slab_alloc_node mm/slub.c:3845 [inline] kmem_cache_alloc_node+0x613/0xc50 mm/slub.c:3888 kmalloc_reserve+0x13d/0x4a0 net/core/skbuff.c:577 __alloc_skb+0x35b/0x7a0 net/core/skbuff.c:668 alloc_skb include/linux/skbuff.h:1318 [inline] alloc_skb_with_frags+0xc8/0xbf0 net/core/skbuff.c:6504 sock_alloc_send_pskb+0xa81/0xbf0 net/core/sock.c:2795 packet_alloc_skb net/packet/af_packet.c:2930 [inline] packet_snd net/packet/af_packet.c:3024 [inline] packet_sendmsg+0x722d/0x9ef0 net/packet/af_packet.c:3113 sock_sendmsg_nosec net/socket.c:730 [inline] __sock_sendmsg+0x30f/0x380 net/socket.c:745 __sys_sendto+0x685/0x830 net/socket.c:2191 __do_sys_sendto net/socket.c:2203 [inline] __se_sys_sendto net/socket.c:2199 [inline] __x64_sys_sendto+0x125/0x1d0 net/socket.c:2199 do_syscall_64+0xd5/0x1f0 entry_SYSCALL_64_after_hwframe+0x6d/0x75 CPU: 0 PID: 5033 Comm: syz-executor346 Not tainted 6.9.0-rc1-syzkaller-00005-g928a87efa423 #0 Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 02/29/2024 Fixes: d13f048dd40e ("net: geneve: modify IP header check in geneve6_xmit_skb and geneve_xmit_skb") Reported-by: syzbot+9ee20ec1de7b3168db09@syzkaller.appspotmail.com Closes: https://lore.kernel.org/netdev/000000000000d19c3a06152f9ee4@google.com/ Signed-off-by: Eric Dumazet Cc: Phillip Potter Cc: Sabrina Dubroca Reviewed-by: Sabrina Dubroca Reviewed-by: Phillip Potter Signed-off-by: David S. Miller --- drivers/net/geneve.c | 4 ++-- include/net/ip_tunnels.h | 33 +++++++++++++++++++++++++++++++++ 2 files changed, 35 insertions(+), 2 deletions(-) diff --git a/drivers/net/geneve.c b/drivers/net/geneve.c index 2f6739fe78af..6c2835086b57 100644 --- a/drivers/net/geneve.c +++ b/drivers/net/geneve.c @@ -822,7 +822,7 @@ static int geneve_xmit_skb(struct sk_buff *skb, struct net_device *dev, __be16 sport; int err; - if (!pskb_inet_may_pull(skb)) + if (!skb_vlan_inet_prepare(skb)) return -EINVAL; if (!gs4) @@ -929,7 +929,7 @@ static int geneve6_xmit_skb(struct sk_buff *skb, struct net_device *dev, __be16 sport; int err; - if (!pskb_inet_may_pull(skb)) + if (!skb_vlan_inet_prepare(skb)) return -EINVAL; if (!gs6) diff --git a/include/net/ip_tunnels.h b/include/net/ip_tunnels.h index 5cd64bb2104d..c286cc2e766e 100644 --- a/include/net/ip_tunnels.h +++ b/include/net/ip_tunnels.h @@ -361,6 +361,39 @@ static inline bool pskb_inet_may_pull(struct sk_buff *skb) return pskb_network_may_pull(skb, nhlen); } +/* Variant of pskb_inet_may_pull(). + */ +static inline bool skb_vlan_inet_prepare(struct sk_buff *skb) +{ + int nhlen = 0, maclen = ETH_HLEN; + __be16 type = skb->protocol; + + /* Essentially this is skb_protocol(skb, true) + * And we get MAC len. + */ + if (eth_type_vlan(type)) + type = __vlan_get_protocol(skb, type, &maclen); + + switch (type) { +#if IS_ENABLED(CONFIG_IPV6) + case htons(ETH_P_IPV6): + nhlen = sizeof(struct ipv6hdr); + break; +#endif + case htons(ETH_P_IP): + nhlen = sizeof(struct iphdr); + break; + } + /* For ETH_P_IPV6/ETH_P_IP we make sure to pull + * a base network header in skb->head. + */ + if (!pskb_may_pull(skb, maclen + nhlen)) + return false; + + skb_set_network_header(skb, maclen); + return true; +} + static inline int ip_encap_hlen(struct ip_tunnel_encap *e) { const struct ip_tunnel_encap_ops *ops; -- cgit v1.2.3 From 58effa3476536215530c9ec4910ffc981613b413 Mon Sep 17 00:00:00 2001 From: Gerd Bayer Date: Fri, 5 Apr 2024 13:16:06 +0200 Subject: s390/ism: fix receive message buffer allocation Since [1], dma_alloc_coherent() does not accept requests for GFP_COMP anymore, even on archs that may be able to fulfill this. Functionality that relied on the receive buffer being a compound page broke at that point: The SMC-D protocol, that utilizes the ism device driver, passes receive buffers to the splice processor in a struct splice_pipe_desc with a single entry list of struct pages. As the buffer is no longer a compound page, the splice processor now rejects requests to handle more than a page worth of data. Replace dma_alloc_coherent() and allocate a buffer with folio_alloc and create a DMA map for it with dma_map_page(). Since only receive buffers on ISM devices use DMA, qualify the mapping as FROM_DEVICE. Since ISM devices are available on arch s390, only and on that arch all DMA is coherent, there is no need to introduce and export some kind of dma_sync_to_cpu() method to be called by the SMC-D protocol layer. Analogously, replace dma_free_coherent by a two step dma_unmap_page, then folio_put to free the receive buffer. [1] https://lore.kernel.org/all/20221113163535.884299-1-hch@lst.de/ Fixes: c08004eede4b ("s390/ism: don't pass bogus GFP_ flags to dma_alloc_coherent") Signed-off-by: Gerd Bayer Signed-off-by: David S. Miller --- drivers/s390/net/ism_drv.c | 38 +++++++++++++++++++++++++++++--------- 1 file changed, 29 insertions(+), 9 deletions(-) diff --git a/drivers/s390/net/ism_drv.c b/drivers/s390/net/ism_drv.c index 2c8e964425dc..affb05521e14 100644 --- a/drivers/s390/net/ism_drv.c +++ b/drivers/s390/net/ism_drv.c @@ -14,6 +14,8 @@ #include #include #include +#include +#include #include "ism.h" @@ -292,13 +294,15 @@ out: static void ism_free_dmb(struct ism_dev *ism, struct ism_dmb *dmb) { clear_bit(dmb->sba_idx, ism->sba_bitmap); - dma_free_coherent(&ism->pdev->dev, dmb->dmb_len, - dmb->cpu_addr, dmb->dma_addr); + dma_unmap_page(&ism->pdev->dev, dmb->dma_addr, dmb->dmb_len, + DMA_FROM_DEVICE); + folio_put(virt_to_folio(dmb->cpu_addr)); } static int ism_alloc_dmb(struct ism_dev *ism, struct ism_dmb *dmb) { unsigned long bit; + int rc; if (PAGE_ALIGN(dmb->dmb_len) > dma_get_max_seg_size(&ism->pdev->dev)) return -EINVAL; @@ -315,14 +319,30 @@ static int ism_alloc_dmb(struct ism_dev *ism, struct ism_dmb *dmb) test_and_set_bit(dmb->sba_idx, ism->sba_bitmap)) return -EINVAL; - dmb->cpu_addr = dma_alloc_coherent(&ism->pdev->dev, dmb->dmb_len, - &dmb->dma_addr, - GFP_KERNEL | __GFP_NOWARN | - __GFP_NOMEMALLOC | __GFP_NORETRY); - if (!dmb->cpu_addr) - clear_bit(dmb->sba_idx, ism->sba_bitmap); + dmb->cpu_addr = + folio_address(folio_alloc(GFP_KERNEL | __GFP_NOWARN | + __GFP_NOMEMALLOC | __GFP_NORETRY, + get_order(dmb->dmb_len))); - return dmb->cpu_addr ? 0 : -ENOMEM; + if (!dmb->cpu_addr) { + rc = -ENOMEM; + goto out_bit; + } + dmb->dma_addr = dma_map_page(&ism->pdev->dev, + virt_to_page(dmb->cpu_addr), 0, + dmb->dmb_len, DMA_FROM_DEVICE); + if (dma_mapping_error(&ism->pdev->dev, dmb->dma_addr)) { + rc = -ENOMEM; + goto out_free; + } + + return 0; + +out_free: + kfree(dmb->cpu_addr); +out_bit: + clear_bit(dmb->sba_idx, ism->sba_bitmap); + return rc; } int ism_register_dmb(struct ism_dev *ism, struct ism_dmb *dmb, -- cgit v1.2.3 From b45d0d01da542be280d935d87b71465028cdcb1f Mon Sep 17 00:00:00 2001 From: Bernhard Rosenkränzer Date: Fri, 29 Mar 2024 16:28:00 +0100 Subject: platform/x86: acer-wmi: Add support for Acer PH18-71 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add Acer Predator PH18-71 to acer_quirks with predator_v4 to support mode button and fan speed sensor. Signed-off-by: Bernhard Rosenkränzer Reviewed-by: Ilpo Järvinen Link: https://lore.kernel.org/r/20240329152800.29393-1-bero@baylibre.com Signed-off-by: Ilpo Järvinen --- drivers/platform/x86/acer-wmi.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/drivers/platform/x86/acer-wmi.c b/drivers/platform/x86/acer-wmi.c index ee2e164f86b9..38c932df6446 100644 --- a/drivers/platform/x86/acer-wmi.c +++ b/drivers/platform/x86/acer-wmi.c @@ -597,6 +597,15 @@ static const struct dmi_system_id acer_quirks[] __initconst = { }, .driver_data = &quirk_acer_predator_v4, }, + { + .callback = dmi_matched, + .ident = "Acer Predator PH18-71", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Acer"), + DMI_MATCH(DMI_PRODUCT_NAME, "Predator PH18-71"), + }, + .driver_data = &quirk_acer_predator_v4, + }, { .callback = set_force_caps, .ident = "Acer Aspire Switch 10E SW3-016", -- cgit v1.2.3 From c64c4e3f789123e82ffae3404d108cf826c9599a Mon Sep 17 00:00:00 2001 From: Mohammad Rafi Shaik Date: Mon, 8 Apr 2024 09:53:30 +0530 Subject: ASoC: dt-bindings: qcom,sm8250: Add QCM6490 snd QCS6490 sound card Document the bindings for the Qualcomm QCM6490 IDP and QCS6490 RB3Gen2 board specific sound card. The bindings are the same as for other newer Qualcomm ADSP sound cards, thus keep them in existing qcom,sm8250.yaml file, even though Linux driver is separate. Signed-off-by: Mohammad Rafi Shaik Acked-by: Krzysztof Kozlowski Reviewed-by: Srinivas Kandagatla Link: https://msgid.link/r/20240408042331.403103-2-quic_mohs@quicinc.com Signed-off-by: Mark Brown --- Documentation/devicetree/bindings/sound/qcom,sm8250.yaml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Documentation/devicetree/bindings/sound/qcom,sm8250.yaml b/Documentation/devicetree/bindings/sound/qcom,sm8250.yaml index 2ab6871e89e5..b2e15ebbd1bc 100644 --- a/Documentation/devicetree/bindings/sound/qcom,sm8250.yaml +++ b/Documentation/devicetree/bindings/sound/qcom,sm8250.yaml @@ -29,6 +29,8 @@ properties: - enum: - qcom,apq8016-sbc-sndcard - qcom,msm8916-qdsp6-sndcard + - qcom,qcm6490-idp-sndcard + - qcom,qcs6490-rb3gen2-sndcard - qcom,qrb5165-rb5-sndcard - qcom,sc7180-qdsp6-sndcard - qcom,sc8280xp-sndcard -- cgit v1.2.3 From 5485c3fa96f78314207a30e81dbe270424d70ede Mon Sep 17 00:00:00 2001 From: Mohammad Rafi Shaik Date: Mon, 8 Apr 2024 09:53:31 +0530 Subject: ASoC: qcom: sc8280xp: Add support for QCM6490 and QCS6490 Add compatibles for sound card on Qualcomm QCM6490 IDP and QCS6490 RB3Gen2 boards. Signed-off-by: Mohammad Rafi Shaik Reviewed-by: Srinivas Kandagatla Link: https://msgid.link/r/20240408042331.403103-3-quic_mohs@quicinc.com Signed-off-by: Mark Brown --- sound/soc/qcom/sc8280xp.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sound/soc/qcom/sc8280xp.c b/sound/soc/qcom/sc8280xp.c index b7fd503a1666..878bd50ad4a7 100644 --- a/sound/soc/qcom/sc8280xp.c +++ b/sound/soc/qcom/sc8280xp.c @@ -169,6 +169,8 @@ static int sc8280xp_platform_probe(struct platform_device *pdev) } static const struct of_device_id snd_sc8280xp_dt_match[] = { + {.compatible = "qcom,qcm6490-idp-sndcard", "qcm6490"}, + {.compatible = "qcom,qcs6490-rb3gen2-sndcard", "qcs6490"}, {.compatible = "qcom,sc8280xp-sndcard", "sc8280xp"}, {.compatible = "qcom,sm8450-sndcard", "sm8450"}, {.compatible = "qcom,sm8550-sndcard", "sm8550"}, -- cgit v1.2.3 From 8167bd1c8a45c289316417cf938bcd8ceec24fd5 Mon Sep 17 00:00:00 2001 From: Animesh Agarwal Date: Sat, 6 Apr 2024 19:44:49 +0530 Subject: ASoC: dt-bindings: ti,pcm1681: Convert to dtschema Convert the Texas Instruments PCM1681 bindings to DT schema. Make bindings complete by adding #sound-dai-cells. Signed-off-by: Animesh Agarwal Reviewed-by: Krzysztof Kozlowski Link: https://msgid.link/r/20240406141454.45529-1-animeshagarwal28@gmail.com Signed-off-by: Mark Brown --- .../devicetree/bindings/sound/ti,pcm1681.txt | 15 -------- .../devicetree/bindings/sound/ti,pcm1681.yaml | 43 ++++++++++++++++++++++ 2 files changed, 43 insertions(+), 15 deletions(-) delete mode 100644 Documentation/devicetree/bindings/sound/ti,pcm1681.txt create mode 100644 Documentation/devicetree/bindings/sound/ti,pcm1681.yaml diff --git a/Documentation/devicetree/bindings/sound/ti,pcm1681.txt b/Documentation/devicetree/bindings/sound/ti,pcm1681.txt deleted file mode 100644 index 4df17185ab80..000000000000 --- a/Documentation/devicetree/bindings/sound/ti,pcm1681.txt +++ /dev/null @@ -1,15 +0,0 @@ -Texas Instruments PCM1681 8-channel PWM Processor - -Required properties: - - - compatible: Should contain "ti,pcm1681". - - reg: The i2c address. Should contain <0x4c>. - -Examples: - - i2c_bus { - pcm1681@4c { - compatible = "ti,pcm1681"; - reg = <0x4c>; - }; - }; diff --git a/Documentation/devicetree/bindings/sound/ti,pcm1681.yaml b/Documentation/devicetree/bindings/sound/ti,pcm1681.yaml new file mode 100644 index 000000000000..5aa00617291c --- /dev/null +++ b/Documentation/devicetree/bindings/sound/ti,pcm1681.yaml @@ -0,0 +1,43 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/sound/ti,pcm1681.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Texas Instruments PCM1681 8-channel PWM Processor + +maintainers: + - Shenghao Ding + - Kevin Lu + - Baojun Xu + +allOf: + - $ref: dai-common.yaml# + +properties: + compatible: + const: ti,pcm1681 + + reg: + maxItems: 1 + + "#sound-dai-cells": + const: 0 + +required: + - compatible + - reg + +unevaluatedProperties: false + +examples: + - | + i2c { + #address-cells = <1>; + #size-cells = <0>; + + pcm1681: audio-codec@4c { + compatible = "ti,pcm1681"; + reg = <0x4c>; + }; + }; -- cgit v1.2.3 From 7ac10c7d728d75bc9daaa8fade3c7a3273b9a9ff Mon Sep 17 00:00:00 2001 From: Vikas Gupta Date: Fri, 5 Apr 2024 16:55:11 -0700 Subject: bnxt_en: Fix possible memory leak in bnxt_rdma_aux_device_init() If ulp = kzalloc() fails, the allocated edev will leak because it is not properly assigned and the cleanup path will not be able to free it. Fix it by assigning it properly immediately after allocation. Fixes: 303432211324 ("bnxt_en: Remove runtime interrupt vector allocation") Reviewed-by: Andy Gospodarek Signed-off-by: Vikas Gupta Signed-off-by: Michael Chan Signed-off-by: David S. Miller --- drivers/net/ethernet/broadcom/bnxt/bnxt_ulp.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt_ulp.c b/drivers/net/ethernet/broadcom/bnxt/bnxt_ulp.c index 93f9bd55020f..a5f9c9090a6b 100644 --- a/drivers/net/ethernet/broadcom/bnxt/bnxt_ulp.c +++ b/drivers/net/ethernet/broadcom/bnxt/bnxt_ulp.c @@ -392,12 +392,13 @@ void bnxt_rdma_aux_device_init(struct bnxt *bp) if (!edev) goto aux_dev_uninit; + aux_priv->edev = edev; + ulp = kzalloc(sizeof(*ulp), GFP_KERNEL); if (!ulp) goto aux_dev_uninit; edev->ulp_tbl = ulp; - aux_priv->edev = edev; bp->edev = edev; bnxt_set_edev_info(edev, bp); -- cgit v1.2.3 From b5ea7d33ba2a42b95b4298d08d2af9cdeeaf0090 Mon Sep 17 00:00:00 2001 From: Vikas Gupta Date: Fri, 5 Apr 2024 16:55:12 -0700 Subject: bnxt_en: Fix error recovery for RoCE ulp client Since runtime MSIXs vector allocation/free has been removed, the L2 driver needs to repopulate the MSIX entries for the ulp client as the irq table may change during the recovery process. Fixes: 303432211324 ("bnxt_en: Remove runtime interrupt vector allocation") Reviewed-by: Andy Gospodarek Signed-off-by: Vikas Gupta Signed-off-by: Michael Chan Signed-off-by: David S. Miller --- drivers/net/ethernet/broadcom/bnxt/bnxt_ulp.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt_ulp.c b/drivers/net/ethernet/broadcom/bnxt/bnxt_ulp.c index a5f9c9090a6b..195c02dc0683 100644 --- a/drivers/net/ethernet/broadcom/bnxt/bnxt_ulp.c +++ b/drivers/net/ethernet/broadcom/bnxt/bnxt_ulp.c @@ -210,6 +210,9 @@ void bnxt_ulp_start(struct bnxt *bp, int err) if (err) return; + if (edev->ulp_tbl->msix_requested) + bnxt_fill_msix_vecs(bp, edev->msix_entries); + if (aux_priv) { struct auxiliary_device *adev; -- cgit v1.2.3 From faa12ca245585379d612736a4b5e98e88481ea59 Mon Sep 17 00:00:00 2001 From: Pavan Chebbi Date: Fri, 5 Apr 2024 16:55:13 -0700 Subject: bnxt_en: Reset PTP tx_avail after possible firmware reset It is possible that during error recovery and firmware reset, there is a pending TX PTP packet waiting for the timestamp. We need to reset this condition so that after recovery, the tx_avail count for PTP is reset back to the initial value. Otherwise, we may not accept any PTP TX timestamps after recovery. Fixes: 118612d519d8 ("bnxt_en: Add PTP clock APIs, ioctls, and ethtool methods") Reviewed-by: Kalesh AP Signed-off-by: Pavan Chebbi Signed-off-by: Michael Chan Signed-off-by: David S. Miller --- drivers/net/ethernet/broadcom/bnxt/bnxt.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.c b/drivers/net/ethernet/broadcom/bnxt/bnxt.c index 493b724848c8..57e61f963167 100644 --- a/drivers/net/ethernet/broadcom/bnxt/bnxt.c +++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.c @@ -11758,6 +11758,8 @@ static int __bnxt_open_nic(struct bnxt *bp, bool irq_re_init, bool link_re_init) /* VF-reps may need to be re-opened after the PF is re-opened */ if (BNXT_PF(bp)) bnxt_vf_reps_open(bp); + if (bp->ptp_cfg) + atomic_set(&bp->ptp_cfg->tx_avail, BNXT_MAX_TX_TS); bnxt_ptp_init_rtc(bp, true); bnxt_ptp_cfg_tstamp_filters(bp); bnxt_cfg_usr_fltrs(bp); -- cgit v1.2.3 From 3c89a068bfd0698a5478f4cf39493595ef757d5e Mon Sep 17 00:00:00 2001 From: Anna-Maria Behnsen Date: Mon, 8 Apr 2024 09:02:23 +0200 Subject: PM: s2idle: Make sure CPUs will wakeup directly on resume s2idle works like a regular suspend with freezing processes and freezing devices. All CPUs except the control CPU go into idle. Once this is completed the control CPU kicks all other CPUs out of idle, so that they reenter the idle loop and then enter s2idle state. The control CPU then issues an swait() on the suspend state and therefore enters the idle loop as well. Due to being kicked out of idle, the other CPUs leave their NOHZ states, which means the tick is active and the corresponding hrtimer is programmed to the next jiffie. On entering s2idle the CPUs shut down their local clockevent device to prevent wakeups. The last CPU which enters s2idle shuts down its local clockevent and freezes timekeeping. On resume, one of the CPUs receives the wakeup interrupt, unfreezes timekeeping and its local clockevent and starts the resume process. At that point all other CPUs are still in s2idle with their clockevents switched off. They only resume when they are kicked by another CPU or after resuming devices and then receiving a device interrupt. That means there is no guarantee that all CPUs will wakeup directly on resume. As a consequence there is no guarantee that timers which are queued on those CPUs and should expire directly after resume, are handled. Also timer list timers which are remotely queued to one of those CPUs after resume will not result in a reprogramming IPI as the tick is active. Queueing a hrtimer will also not result in a reprogramming IPI because the first hrtimer event is already in the past. The recent introduction of the timer pull model (7ee988770326 ("timers: Implement the hierarchical pull model")) amplifies this problem, if the current migrator is one of the non woken up CPUs. When a non pinned timer list timer is queued and the queuing CPU goes idle, it relies on the still suspended migrator CPU to expire the timer which will happen by chance. The problem exists since commit 8d89835b0467 ("PM: suspend: Do not pause cpuidle in the suspend-to-idle path"). There the cpuidle_pause() call which in turn invoked a wakeup for all idle CPUs was moved to a later point in the resume process. This might not be reached or reached very late because it waits on a timer of a still suspended CPU. Address this by kicking all CPUs out of idle after the control CPU returns from swait() so that they resume their timers and restore consistent system state. Closes: https://bugzilla.kernel.org/show_bug.cgi?id=218641 Fixes: 8d89835b0467 ("PM: suspend: Do not pause cpuidle in the suspend-to-idle path") Signed-off-by: Anna-Maria Behnsen Reviewed-by: Thomas Gleixner Tested-by: Mario Limonciello Cc: 5.16+ # 5.16+ Acked-by: Peter Zijlstra (Intel) Reviewed-by: Ulf Hansson Signed-off-by: Rafael J. Wysocki --- kernel/power/suspend.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/kernel/power/suspend.c b/kernel/power/suspend.c index e3ae93bbcb9b..09f8397bae15 100644 --- a/kernel/power/suspend.c +++ b/kernel/power/suspend.c @@ -106,6 +106,12 @@ static void s2idle_enter(void) swait_event_exclusive(s2idle_wait_head, s2idle_state == S2IDLE_STATE_WAKE); + /* + * Kick all CPUs to ensure that they resume their timers and restore + * consistent system state. + */ + wake_up_all_idle_cpus(); + cpus_read_unlock(); raw_spin_lock_irq(&s2idle_lock); -- cgit v1.2.3 From 5ce344beaca688f4cdea07045e0b8f03dc537e74 Mon Sep 17 00:00:00 2001 From: Adam Dunlap Date: Mon, 18 Mar 2024 16:09:27 -0700 Subject: x86/apic: Force native_apic_mem_read() to use the MOV instruction When done from a virtual machine, instructions that touch APIC memory must be emulated. By convention, MMIO accesses are typically performed via io.h helpers such as readl() or writeq() to simplify instruction emulation/decoding (ex: in KVM hosts and SEV guests) [0]. Currently, native_apic_mem_read() does not follow this convention, allowing the compiler to emit instructions other than the MOV instruction generated by readl(). In particular, when the kernel is compiled with clang and run as a SEV-ES or SEV-SNP guest, the compiler would emit a TESTL instruction which is not supported by the SEV-ES emulator, causing a boot failure in that environment. It is likely the same problem would happen in a TDX guest as that uses the same instruction emulator as SEV-ES. To make sure all emulators can emulate APIC memory reads via MOV, use the readl() function in native_apic_mem_read(). It is expected that any emulator would support MOV in any addressing mode as it is the most generic and is what is usually emitted currently. The TESTL instruction is emitted when native_apic_mem_read() is inlined into apic_mem_wait_icr_idle(). The emulator comes from insn_decode_mmio() in arch/x86/lib/insn-eval.c. It's not worth it to extend insn_decode_mmio() to support more instructions since, in theory, the compiler could choose to output nearly any instruction for such reads which would bloat the emulator beyond reason. [0] https://lore.kernel.org/all/20220405232939.73860-12-kirill.shutemov@linux.intel.com/ [ bp: Massage commit message, fix typos. ] Signed-off-by: Adam Dunlap Signed-off-by: Borislav Petkov (AMD) Reviewed-by: Thomas Gleixner Reviewed-by: Ard Biesheuvel Tested-by: Kevin Loughlin Cc: Link: https://lore.kernel.org/r/20240318230927.2191933-1-acdunlap@google.com --- arch/x86/include/asm/apic.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/arch/x86/include/asm/apic.h b/arch/x86/include/asm/apic.h index 94ce0f7c9d3a..e6ab0cf15ed5 100644 --- a/arch/x86/include/asm/apic.h +++ b/arch/x86/include/asm/apic.h @@ -13,6 +13,7 @@ #include #include #include +#include #define ARCH_APICTIMER_STOPS_ON_C3 1 @@ -98,7 +99,7 @@ static inline void native_apic_mem_write(u32 reg, u32 v) static inline u32 native_apic_mem_read(u32 reg) { - return *((volatile u32 *)(APIC_BASE + reg)); + return readl((void __iomem *)(APIC_BASE + reg)); } static inline void native_apic_mem_eoi(void) -- cgit v1.2.3 From dfe073f8714dc8022b5578510e2288e5292adeb5 Mon Sep 17 00:00:00 2001 From: Minda Chen Date: Mon, 8 Apr 2024 09:29:42 +0800 Subject: net: stmmac: mmc_core: Add GMAC LPI statistics XGMAC MMC has already added LPI statistics. GMAC MMC lack of these statistics. Add register definition and reading the LPI statistics from registers. Signed-off-by: Minda Chen Reviewed-by: Simon Horman Signed-off-by: David S. Miller --- drivers/net/ethernet/stmicro/stmmac/mmc_core.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/drivers/net/ethernet/stmicro/stmmac/mmc_core.c b/drivers/net/ethernet/stmicro/stmmac/mmc_core.c index 7eb477faa75a..b0db5f4e8fe8 100644 --- a/drivers/net/ethernet/stmicro/stmmac/mmc_core.c +++ b/drivers/net/ethernet/stmicro/stmmac/mmc_core.c @@ -79,6 +79,12 @@ #define MMC_RX_FIFO_OVERFLOW 0xd4 #define MMC_RX_VLAN_FRAMES_GB 0xd8 #define MMC_RX_WATCHDOG_ERROR 0xdc + +#define MMC_TX_LPI_USEC 0xec +#define MMC_TX_LPI_TRAN 0xf0 +#define MMC_RX_LPI_USEC 0xf4 +#define MMC_RX_LPI_TRAN 0xf8 + /* IPC*/ #define MMC_RX_IPC_INTR_MASK 0x100 #define MMC_RX_IPC_INTR 0x108 @@ -283,6 +289,8 @@ static void dwmac_mmc_read(void __iomem *mmcaddr, struct stmmac_counters *mmc) mmc->mmc_tx_excessdef += readl(mmcaddr + MMC_TX_EXCESSDEF); mmc->mmc_tx_pause_frame += readl(mmcaddr + MMC_TX_PAUSE_FRAME); mmc->mmc_tx_vlan_frame_g += readl(mmcaddr + MMC_TX_VLAN_FRAME_G); + mmc->mmc_tx_lpi_usec += readl(mmcaddr + MMC_TX_LPI_USEC); + mmc->mmc_tx_lpi_tran += readl(mmcaddr + MMC_TX_LPI_TRAN); /* MMC RX counter registers */ mmc->mmc_rx_framecount_gb += readl(mmcaddr + MMC_RX_FRAMECOUNT_GB); @@ -316,6 +324,9 @@ static void dwmac_mmc_read(void __iomem *mmcaddr, struct stmmac_counters *mmc) mmc->mmc_rx_fifo_overflow += readl(mmcaddr + MMC_RX_FIFO_OVERFLOW); mmc->mmc_rx_vlan_frames_gb += readl(mmcaddr + MMC_RX_VLAN_FRAMES_GB); mmc->mmc_rx_watchdog_error += readl(mmcaddr + MMC_RX_WATCHDOG_ERROR); + mmc->mmc_rx_lpi_usec += readl(mmcaddr + MMC_RX_LPI_USEC); + mmc->mmc_rx_lpi_tran += readl(mmcaddr + MMC_RX_LPI_TRAN); + /* IPv4 */ mmc->mmc_rx_ipv4_gd += readl(mmcaddr + MMC_RX_IPV4_GD); mmc->mmc_rx_ipv4_hderr += readl(mmcaddr + MMC_RX_IPV4_HDERR); -- cgit v1.2.3 From ff20393bdc4537c5e044e3002d7f25a45f0d0f98 Mon Sep 17 00:00:00 2001 From: Minda Chen Date: Mon, 8 Apr 2024 09:29:43 +0800 Subject: net: stmmac: mmc_core: Add GMAC mmc tx/rx missing statistics The missing statistics including Rx_Receive_Error_Packets and Tx_OSize_Packets_Good. Signed-off-by: Minda Chen Reviewed-by: Simon Horman Signed-off-by: David S. Miller --- drivers/net/ethernet/stmicro/stmmac/mmc.h | 2 ++ drivers/net/ethernet/stmicro/stmmac/mmc_core.c | 4 ++++ drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c | 2 ++ 3 files changed, 8 insertions(+) diff --git a/drivers/net/ethernet/stmicro/stmmac/mmc.h b/drivers/net/ethernet/stmicro/stmmac/mmc.h index dff02d75d519..5d1ea3e07459 100644 --- a/drivers/net/ethernet/stmicro/stmmac/mmc.h +++ b/drivers/net/ethernet/stmicro/stmmac/mmc.h @@ -52,6 +52,7 @@ struct stmmac_counters { unsigned int mmc_tx_excessdef; unsigned int mmc_tx_pause_frame; unsigned int mmc_tx_vlan_frame_g; + unsigned int mmc_tx_oversize_g; unsigned int mmc_tx_lpi_usec; unsigned int mmc_tx_lpi_tran; @@ -80,6 +81,7 @@ struct stmmac_counters { unsigned int mmc_rx_fifo_overflow; unsigned int mmc_rx_vlan_frames_gb; unsigned int mmc_rx_watchdog_error; + unsigned int mmc_rx_error; unsigned int mmc_rx_lpi_usec; unsigned int mmc_rx_lpi_tran; unsigned int mmc_rx_discard_frames_gb; diff --git a/drivers/net/ethernet/stmicro/stmmac/mmc_core.c b/drivers/net/ethernet/stmicro/stmmac/mmc_core.c index b0db5f4e8fe8..0fab842902a8 100644 --- a/drivers/net/ethernet/stmicro/stmmac/mmc_core.c +++ b/drivers/net/ethernet/stmicro/stmmac/mmc_core.c @@ -53,6 +53,7 @@ #define MMC_TX_EXCESSDEF 0x6c #define MMC_TX_PAUSE_FRAME 0x70 #define MMC_TX_VLAN_FRAME_G 0x74 +#define MMC_TX_OVERSIZE_G 0x78 /* MMC RX counter registers */ #define MMC_RX_FRAMECOUNT_GB 0x80 @@ -79,6 +80,7 @@ #define MMC_RX_FIFO_OVERFLOW 0xd4 #define MMC_RX_VLAN_FRAMES_GB 0xd8 #define MMC_RX_WATCHDOG_ERROR 0xdc +#define MMC_RX_ERROR 0xe0 #define MMC_TX_LPI_USEC 0xec #define MMC_TX_LPI_TRAN 0xf0 @@ -289,6 +291,7 @@ static void dwmac_mmc_read(void __iomem *mmcaddr, struct stmmac_counters *mmc) mmc->mmc_tx_excessdef += readl(mmcaddr + MMC_TX_EXCESSDEF); mmc->mmc_tx_pause_frame += readl(mmcaddr + MMC_TX_PAUSE_FRAME); mmc->mmc_tx_vlan_frame_g += readl(mmcaddr + MMC_TX_VLAN_FRAME_G); + mmc->mmc_tx_oversize_g += readl(mmcaddr + MMC_TX_OVERSIZE_G); mmc->mmc_tx_lpi_usec += readl(mmcaddr + MMC_TX_LPI_USEC); mmc->mmc_tx_lpi_tran += readl(mmcaddr + MMC_TX_LPI_TRAN); @@ -324,6 +327,7 @@ static void dwmac_mmc_read(void __iomem *mmcaddr, struct stmmac_counters *mmc) mmc->mmc_rx_fifo_overflow += readl(mmcaddr + MMC_RX_FIFO_OVERFLOW); mmc->mmc_rx_vlan_frames_gb += readl(mmcaddr + MMC_RX_VLAN_FRAMES_GB); mmc->mmc_rx_watchdog_error += readl(mmcaddr + MMC_RX_WATCHDOG_ERROR); + mmc->mmc_rx_error += readl(mmcaddr + MMC_RX_ERROR); mmc->mmc_rx_lpi_usec += readl(mmcaddr + MMC_RX_LPI_USEC); mmc->mmc_rx_lpi_tran += readl(mmcaddr + MMC_RX_LPI_TRAN); diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c index e1537a57815f..542e2633a6f5 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c @@ -212,6 +212,7 @@ static const struct stmmac_stats stmmac_mmc[] = { STMMAC_MMC_STAT(mmc_tx_excessdef), STMMAC_MMC_STAT(mmc_tx_pause_frame), STMMAC_MMC_STAT(mmc_tx_vlan_frame_g), + STMMAC_MMC_STAT(mmc_tx_oversize_g), STMMAC_MMC_STAT(mmc_tx_lpi_usec), STMMAC_MMC_STAT(mmc_tx_lpi_tran), STMMAC_MMC_STAT(mmc_rx_framecount_gb), @@ -238,6 +239,7 @@ static const struct stmmac_stats stmmac_mmc[] = { STMMAC_MMC_STAT(mmc_rx_fifo_overflow), STMMAC_MMC_STAT(mmc_rx_vlan_frames_gb), STMMAC_MMC_STAT(mmc_rx_watchdog_error), + STMMAC_MMC_STAT(mmc_rx_error), STMMAC_MMC_STAT(mmc_rx_lpi_usec), STMMAC_MMC_STAT(mmc_rx_lpi_tran), STMMAC_MMC_STAT(mmc_rx_discard_frames_gb), -- cgit v1.2.3 From c1d11fc2c8320871b40730991071dd0a0b405bc8 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Mon, 8 Apr 2024 09:46:01 +0200 Subject: irqflags: Explicitly ignore lockdep_hrtimer_exit() argument When building with 'make W=1' but CONFIG_TRACE_IRQFLAGS=n, the unused argument to lockdep_hrtimer_exit() causes a warning: kernel/time/hrtimer.c:1655:14: error: variable 'expires_in_hardirq' set but not used [-Werror=unused-but-set-variable] This is intentional behavior, so add a cast to void to shut up the warning. Fixes: 73d20564e0dc ("hrtimer: Don't dereference the hrtimer pointer after the callback") Reported-by: kernel test robot Signed-off-by: Arnd Bergmann Signed-off-by: Thomas Gleixner Reviewed-by: Sebastian Andrzej Siewior Cc: stable@vger.kernel.org Link: https://lore.kernel.org/r/20240408074609.3170807-1-arnd@kernel.org Closes: https://lore.kernel.org/oe-kbuild-all/202311191229.55QXHVc6-lkp@intel.com/ --- include/linux/irqflags.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/linux/irqflags.h b/include/linux/irqflags.h index 147feebd508c..3f003d5fde53 100644 --- a/include/linux/irqflags.h +++ b/include/linux/irqflags.h @@ -114,7 +114,7 @@ do { \ # define lockdep_softirq_enter() do { } while (0) # define lockdep_softirq_exit() do { } while (0) # define lockdep_hrtimer_enter(__hrtimer) false -# define lockdep_hrtimer_exit(__context) do { } while (0) +# define lockdep_hrtimer_exit(__context) do { (void)(__context); } while (0) # define lockdep_posixtimer_enter() do { } while (0) # define lockdep_posixtimer_exit() do { } while (0) # define lockdep_irq_work_enter(__work) do { } while (0) -- cgit v1.2.3 From fa1f51162338b3e2f520d4bfedc42b3b2e00da6d Mon Sep 17 00:00:00 2001 From: Sebastian Andrzej Siewior Date: Tue, 19 Mar 2024 19:20:50 +0100 Subject: locking: Make rwsem_assert_held_write_nolockdep() build with PREEMPT_RT=y The commit cited below broke the build for PREEMPT_RT because rwsem_assert_held_write_nolockdep() passes a struct rw_semaphore but rw_base_assert_held_write() expects struct rwbase_rt. Fixing the type alone leads to the problem that WARN_ON() is not found because bug.h is missing. In order to resolve this: - Keep the assert (WARN_ON()) in rwsem.h (not rwbase_rt.h) - Make rwsem_assert_held_write_nolockdep() do the implementation specific (rw_base) writer check. - Replace the "inline" with __always_inline which was used before. Fixes: f70405afc99b1 ("locking: Add rwsem_assert_held() and rwsem_assert_held_write()") Reported-by: Clark Williams Signed-off-by: Sebastian Andrzej Siewior Signed-off-by: Thomas Gleixner Reviewed-by: Waiman Long Link: https://lore.kernel.org/r/20240319182050.U4AzUF3I@linutronix.de --- include/linux/rwbase_rt.h | 4 ++-- include/linux/rwsem.h | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/include/linux/rwbase_rt.h b/include/linux/rwbase_rt.h index 29c4e4f243e4..f2394a409c9d 100644 --- a/include/linux/rwbase_rt.h +++ b/include/linux/rwbase_rt.h @@ -31,9 +31,9 @@ static __always_inline bool rw_base_is_locked(const struct rwbase_rt *rwb) return atomic_read(&rwb->readers) != READER_BIAS; } -static inline void rw_base_assert_held_write(const struct rwbase_rt *rwb) +static __always_inline bool rw_base_is_write_locked(const struct rwbase_rt *rwb) { - WARN_ON(atomic_read(&rwb->readers) != WRITER_BIAS); + return atomic_read(&rwb->readers) == WRITER_BIAS; } static __always_inline bool rw_base_is_contended(const struct rwbase_rt *rwb) diff --git a/include/linux/rwsem.h b/include/linux/rwsem.h index 4f1c18992f76..c8b543d428b0 100644 --- a/include/linux/rwsem.h +++ b/include/linux/rwsem.h @@ -167,14 +167,14 @@ static __always_inline int rwsem_is_locked(const struct rw_semaphore *sem) return rw_base_is_locked(&sem->rwbase); } -static inline void rwsem_assert_held_nolockdep(const struct rw_semaphore *sem) +static __always_inline void rwsem_assert_held_nolockdep(const struct rw_semaphore *sem) { WARN_ON(!rwsem_is_locked(sem)); } -static inline void rwsem_assert_held_write_nolockdep(const struct rw_semaphore *sem) +static __always_inline void rwsem_assert_held_write_nolockdep(const struct rw_semaphore *sem) { - rw_base_assert_held_write(sem); + WARN_ON(!rw_base_is_write_locked(&sem->rwbase)); } static __always_inline int rwsem_is_contended(struct rw_semaphore *sem) -- cgit v1.2.3 From d730192ff0246356a2d7e63ff5bd501060670eec Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Sat, 6 Apr 2024 13:40:52 +0200 Subject: ACPI: scan: Do not increase dep_unmet for already met dependencies On the Toshiba Encore WT10-A tablet the BATC battery ACPI device depends on 3 other devices: Name (_DEP, Package (0x03) // _DEP: Dependencies { I2C1, GPO2, GPO0 }) acpi_scan_check_dep() adds all 3 of these to the acpi_dep_list and then before an acpi_device is created for the BATC handle (and thus before acpi_scan_dep_init() runs) acpi_scan_clear_dep() gets called for both GPIO depenencies, with free_when_met not set for the dependencies. Since there is no adev for BATC yet, there also is no dep_unmet to decrement. The only result of acpi_scan_clear_dep() in this case is dep->met getting set. Soon after acpi_scan_clear_dep() has been called for the GPIO dependencies the acpi_device gets created for the BATC handle and acpi_scan_dep_init() runs, this sees 3 dependencies on the acpi_dep_list and initializes unmet_dep to 3. Later when the dependency for I2C1 is met unmet_dep becomes 2, but since the 2 GPIO deps where already met it never becomes 0 causing battery monitoring to not work. Fix this by modifying acpi_scan_dep_init() to not increase dep_met for dependencies which have already been marked as being met. Fixes: 3ba12d8de3fa ("ACPI: scan: Reduce overhead related to devices with dependencies") Signed-off-by: Hans de Goede Cc: 6.5+ # 6.5+ Signed-off-by: Rafael J. Wysocki --- drivers/acpi/scan.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c index 7c157bf92695..d1464324de95 100644 --- a/drivers/acpi/scan.c +++ b/drivers/acpi/scan.c @@ -1843,7 +1843,8 @@ static void acpi_scan_dep_init(struct acpi_device *adev) if (dep->honor_dep) adev->flags.honor_deps = 1; - adev->dep_unmet++; + if (!dep->met) + adev->dep_unmet++; } } } -- cgit v1.2.3 From 8ab58f6841b19423231c5db3378691ec80c778f8 Mon Sep 17 00:00:00 2001 From: Thierry Reding Date: Thu, 14 Mar 2024 16:49:43 +0100 Subject: gpu: host1x: Do not setup DMA for virtual devices The host1x devices are virtual compound devices and do not perform DMA accesses themselves, so they do not need to be set up for DMA. Ideally we would also not need to set up DMA masks for the virtual devices, but we currently still need those for legacy support on old hardware. Tested-by: Jon Hunter Acked-by: Jon Hunter Signed-off-by: Thierry Reding Link: https://patchwork.freedesktop.org/patch/msgid/20240314154943.2487549-1-thierry.reding@gmail.com --- drivers/gpu/host1x/bus.c | 8 -------- 1 file changed, 8 deletions(-) diff --git a/drivers/gpu/host1x/bus.c b/drivers/gpu/host1x/bus.c index 783975d1384f..7c52757a89db 100644 --- a/drivers/gpu/host1x/bus.c +++ b/drivers/gpu/host1x/bus.c @@ -351,11 +351,6 @@ static int host1x_device_uevent(const struct device *dev, return 0; } -static int host1x_dma_configure(struct device *dev) -{ - return of_dma_configure(dev, dev->of_node, true); -} - static const struct dev_pm_ops host1x_device_pm_ops = { .suspend = pm_generic_suspend, .resume = pm_generic_resume, @@ -369,7 +364,6 @@ const struct bus_type host1x_bus_type = { .name = "host1x", .match = host1x_device_match, .uevent = host1x_device_uevent, - .dma_configure = host1x_dma_configure, .pm = &host1x_device_pm_ops, }; @@ -458,8 +452,6 @@ static int host1x_device_add(struct host1x *host1x, device->dev.bus = &host1x_bus_type; device->dev.parent = host1x->dev; - of_dma_configure(&device->dev, host1x->dev->of_node, true); - device->dev.dma_parms = &device->dma_parms; dma_set_max_seg_size(&device->dev, UINT_MAX); -- cgit v1.2.3 From aca1a5287ea328fd1f7e2bfa6806646486d86a70 Mon Sep 17 00:00:00 2001 From: Raag Jadav Date: Thu, 28 Mar 2024 09:25:40 +0530 Subject: ACPI: bus: allow _UID matching for integer zero Commit b2b32a173881 ("ACPI: bus: update acpi_dev_hid_uid_match() to support multiple types") added _UID matching support for both integer and string types, which satisfies NULL @uid2 argument for string types using inversion, but this logic prevents _UID comparision in case the argument is integer 0, which may result in false positives. Fix this using _Generic(), which will allow NULL @uid2 argument for string types as well as _UID matching for all possible integer values. Fixes: b2b32a173881 ("ACPI: bus: update acpi_dev_hid_uid_match() to support multiple types") Signed-off-by: Raag Jadav [ rjw: Comment adjustment ] Signed-off-by: Rafael J. Wysocki --- include/acpi/acpi_bus.h | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/include/acpi/acpi_bus.h b/include/acpi/acpi_bus.h index 5de954e2b18a..e7796f373d0d 100644 --- a/include/acpi/acpi_bus.h +++ b/include/acpi/acpi_bus.h @@ -911,17 +911,19 @@ static inline bool acpi_int_uid_match(struct acpi_device *adev, u64 uid2) * acpi_dev_hid_uid_match - Match device by supplied HID and UID * @adev: ACPI device to match. * @hid2: Hardware ID of the device. - * @uid2: Unique ID of the device, pass 0 or NULL to not check _UID. + * @uid2: Unique ID of the device, pass NULL to not check _UID. * * Matches HID and UID in @adev with given @hid2 and @uid2. Absence of @uid2 * will be treated as a match. If user wants to validate @uid2, it should be * done before calling this function. * - * Returns: %true if matches or @uid2 is 0 or NULL, %false otherwise. + * Returns: %true if matches or @uid2 is NULL, %false otherwise. */ #define acpi_dev_hid_uid_match(adev, hid2, uid2) \ (acpi_dev_hid_match(adev, hid2) && \ - (!(uid2) || acpi_dev_uid_match(adev, uid2))) + /* Distinguish integer 0 from NULL @uid2 */ \ + (_Generic(uid2, ACPI_STR_TYPES(!(uid2)), default: 0) || \ + acpi_dev_uid_match(adev, uid2))) void acpi_dev_clear_dependencies(struct acpi_device *supplier); bool acpi_dev_ready_for_enumeration(const struct acpi_device *device); -- cgit v1.2.3 From 3eadd887dbac1df8f25f701e5d404d1b90fd0fea Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Thu, 4 Apr 2024 23:33:25 +0300 Subject: drm/client: Fully protect modes[] with dev->mode_config.mutex MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The modes[] array contains pointers to modes on the connectors' mode lists, which are protected by dev->mode_config.mutex. Thus we need to extend modes[] the same protection or by the time we use it the elements may already be pointing to freed/reused memory. Cc: stable@vger.kernel.org Closes: https://gitlab.freedesktop.org/drm/intel/-/issues/10583 Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20240404203336.10454-2-ville.syrjala@linux.intel.com Reviewed-by: Dmitry Baryshkov Reviewed-by: Jani Nikula Reviewed-by: Thomas Zimmermann --- drivers/gpu/drm/drm_client_modeset.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/drm_client_modeset.c b/drivers/gpu/drm/drm_client_modeset.c index 871e4e2129d6..0683a129b362 100644 --- a/drivers/gpu/drm/drm_client_modeset.c +++ b/drivers/gpu/drm/drm_client_modeset.c @@ -777,6 +777,7 @@ int drm_client_modeset_probe(struct drm_client_dev *client, unsigned int width, unsigned int total_modes_count = 0; struct drm_client_offset *offsets; unsigned int connector_count = 0; + /* points to modes protected by mode_config.mutex */ struct drm_display_mode **modes; struct drm_crtc **crtcs; int i, ret = 0; @@ -845,7 +846,6 @@ int drm_client_modeset_probe(struct drm_client_dev *client, unsigned int width, drm_client_pick_crtcs(client, connectors, connector_count, crtcs, modes, 0, width, height); } - mutex_unlock(&dev->mode_config.mutex); drm_client_modeset_release(client); @@ -875,6 +875,7 @@ int drm_client_modeset_probe(struct drm_client_dev *client, unsigned int width, modeset->y = offset->y; } } + mutex_unlock(&dev->mode_config.mutex); mutex_unlock(&client->modeset_mutex); out: -- cgit v1.2.3 From 5864e479ca4344f3a5df8074524da24c960f440b Mon Sep 17 00:00:00 2001 From: David McFarland Date: Thu, 4 Apr 2024 08:41:45 -0300 Subject: platform/x86/intel/hid: Don't wake on 5-button releases MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit If, for example, the power button is configured to suspend, holding it and releasing it after the machine has suspended, will wake the machine. Also on some machines, power button release events are sent during hibernation, even if the button wasn't used to hibernate the machine. This causes hibernation to be aborted. Fixes: 0c4cae1bc00d ("PM: hibernate: Avoid missing wakeup events during hibernation") Signed-off-by: David McFarland Tested-by: Enrik Berkhan Reviewed-by: Hans de Goede Link: https://lore.kernel.org/r/878r1tpd6u.fsf_-_@gmail.com Reviewed-by: Ilpo Järvinen Signed-off-by: Ilpo Järvinen --- drivers/platform/x86/intel/hid.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/drivers/platform/x86/intel/hid.c b/drivers/platform/x86/intel/hid.c index 7457ca2b27a6..9ffbdc988fe5 100644 --- a/drivers/platform/x86/intel/hid.c +++ b/drivers/platform/x86/intel/hid.c @@ -504,6 +504,7 @@ static void notify_handler(acpi_handle handle, u32 event, void *context) struct platform_device *device = context; struct intel_hid_priv *priv = dev_get_drvdata(&device->dev); unsigned long long ev_index; + struct key_entry *ke; int err; /* @@ -545,11 +546,15 @@ static void notify_handler(acpi_handle handle, u32 event, void *context) if (event == 0xc0 || !priv->array) return; - if (!sparse_keymap_entry_from_scancode(priv->array, event)) { + ke = sparse_keymap_entry_from_scancode(priv->array, event); + if (!ke) { dev_info(&device->dev, "unknown event 0x%x\n", event); return; } + if (ke->type == KE_IGNORE) + return; + wakeup: pm_wakeup_hard_event(&device->dev); -- cgit v1.2.3 From 79ce88064bb04ec62c4e9e4da4614d36906f8a04 Mon Sep 17 00:00:00 2001 From: Sumeet Pawnikar Date: Fri, 5 Apr 2024 17:56:30 +0530 Subject: platform/x86/intel/hid: Add Lunar Lake and Arrow Lake support MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add INTC107B for Lunar Lake and INTC10CB for Arrow Lake ACPI devices IDs. Signed-off-by: Sumeet Pawnikar Link: https://lore.kernel.org/r/20240405122630.32154-1-sumeet.r.pawnikar@intel.com Reviewed-by: Ilpo Järvinen Signed-off-by: Ilpo Järvinen --- drivers/platform/x86/intel/hid.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/platform/x86/intel/hid.c b/drivers/platform/x86/intel/hid.c index 9ffbdc988fe5..c7a827645864 100644 --- a/drivers/platform/x86/intel/hid.c +++ b/drivers/platform/x86/intel/hid.c @@ -49,6 +49,8 @@ static const struct acpi_device_id intel_hid_ids[] = { {"INTC1076", 0}, {"INTC1077", 0}, {"INTC1078", 0}, + {"INTC107B", 0}, + {"INTC10CB", 0}, {"", 0}, }; MODULE_DEVICE_TABLE(acpi, intel_hid_ids); -- cgit v1.2.3 From 592780b8391fe31f129ef4823c1513528f4dcb76 Mon Sep 17 00:00:00 2001 From: Dave Jiang Date: Wed, 3 Apr 2024 08:47:13 -0700 Subject: cxl: Fix retrieving of access_coordinates in PCIe path Current loop in cxl_endpoint_get_perf_coordinates() incorrectly assumes the Root Port (RP) dport is the one with generic port access_coordinate. However those coordinates are one level up in the Host Bridge (HB). Current code causes the computation code to pick up 0s as the coordinates and cause minimal bandwidth to result in 0. Add check to skip RP when combining coordinates. Fixes: 14a6960b3e92 ("cxl: Add helper function that calculate performance data for downstream ports") Reported-by: Jonathan Cameron Reviewed-by: Jonathan Cameron Reviewed-by: Dan Williams Link: https://lore.kernel.org/r/20240403154844.3403859-3-dave.jiang@intel.com Signed-off-by: Dave Jiang --- drivers/cxl/core/port.c | 35 ++++++++++++++++++++++------------- 1 file changed, 22 insertions(+), 13 deletions(-) diff --git a/drivers/cxl/core/port.c b/drivers/cxl/core/port.c index 6cbde50a742b..7aadcec4fc64 100644 --- a/drivers/cxl/core/port.c +++ b/drivers/cxl/core/port.c @@ -2165,6 +2165,11 @@ int cxl_hb_get_perf_coordinates(struct cxl_port *port, return 0; } +static bool parent_port_is_cxl_root(struct cxl_port *port) +{ + return is_cxl_root(to_cxl_port(port->dev.parent)); +} + /** * cxl_endpoint_get_perf_coordinates - Retrieve performance numbers stored in dports * of CXL path @@ -2184,27 +2189,31 @@ int cxl_endpoint_get_perf_coordinates(struct cxl_port *port, struct cxl_dport *dport; struct pci_dev *pdev; unsigned int bw; + bool is_cxl_root; if (!is_cxl_endpoint(port)) return -EINVAL; - dport = iter->parent_dport; - /* - * Exit the loop when the parent port of the current port is cxl root. - * The iterative loop starts at the endpoint and gathers the - * latency of the CXL link from the current iter to the next downstream - * port each iteration. If the parent is cxl root then there is - * nothing to gather. + * Exit the loop when the parent port of the current iter port is cxl + * root. The iterative loop starts at the endpoint and gathers the + * latency of the CXL link from the current device/port to the connected + * downstream port each iteration. */ - while (!is_cxl_root(to_cxl_port(iter->dev.parent))) { - cxl_coordinates_combine(&c, &c, &dport->sw_coord); + do { + dport = iter->parent_dport; + iter = to_cxl_port(iter->dev.parent); + is_cxl_root = parent_port_is_cxl_root(iter); + + /* + * There's no valid access_coordinate for a root port since RPs do not + * have CDAT and therefore needs to be skipped. + */ + if (!is_cxl_root) + cxl_coordinates_combine(&c, &c, &dport->sw_coord); c.write_latency += dport->link_latency; c.read_latency += dport->link_latency; - - iter = to_cxl_port(iter->dev.parent); - dport = iter->parent_dport; - } + } while (!is_cxl_root); /* Get the calculated PCI paths bandwidth */ pdev = to_pci_dev(port->uport_dev->parent); -- cgit v1.2.3 From 51293c565cf4b8d57c154efadb57b17866c74bcb Mon Sep 17 00:00:00 2001 From: Dave Jiang Date: Wed, 3 Apr 2024 08:47:14 -0700 Subject: cxl: Fix incorrect region perf data calculation Current math in cxl_region_perf_data_calculate divides the latency by 1000 every time the function gets called. This causes the region latency to be divided by 1000 per memory device and the math is incorrect. This is user visible as the latency access_coordinate exposed via sysfs will show incorrect latency data. Normalize values from CDAT to nanoseconds. Adjust sub-nanoseconds latency to at least 1. Remove adjustment of perf numbers from the generic target since hmat handling code has already normalized those numbers. Now all computation and stored numbers should be in nanoseconds. cxl_hb_get_perf_coordinates() is removed and HB coords are calculated in the port access_coordinate calculation path since it no longer need to be treated special. Fixes: 3d9f4a197230 ("cxl/region: Calculate performance data for a region") Reviewed-by: Jonathan Cameron Reviewed-by: Dan Williams Link: https://lore.kernel.org/r/20240403154844.3403859-4-dave.jiang@intel.com Signed-off-by: Dave Jiang --- drivers/cxl/acpi.c | 13 +------ drivers/cxl/core/cdat.c | 94 +++++++++++++++++++++---------------------------- drivers/cxl/core/port.c | 36 +++---------------- drivers/cxl/cxl.h | 2 -- 4 files changed, 45 insertions(+), 100 deletions(-) diff --git a/drivers/cxl/acpi.c b/drivers/cxl/acpi.c index af5cb818f84d..566c387d4385 100644 --- a/drivers/cxl/acpi.c +++ b/drivers/cxl/acpi.c @@ -525,22 +525,11 @@ static int get_genport_coordinates(struct device *dev, struct cxl_dport *dport) { struct acpi_device *hb = to_cxl_host_bridge(NULL, dev); u32 uid; - int rc; if (kstrtou32(acpi_device_uid(hb), 0, &uid)) return -EINVAL; - rc = acpi_get_genport_coordinates(uid, dport->hb_coord); - if (rc < 0) - return rc; - - /* Adjust back to picoseconds from nanoseconds */ - for (int i = 0; i < ACCESS_COORDINATE_MAX; i++) { - dport->hb_coord[i].read_latency *= 1000; - dport->hb_coord[i].write_latency *= 1000; - } - - return 0; + return acpi_get_genport_coordinates(uid, dport->hb_coord); } static int add_host_bridge_dport(struct device *match, void *arg) diff --git a/drivers/cxl/core/cdat.c b/drivers/cxl/core/cdat.c index eddbbe21450c..f66b493b5d3c 100644 --- a/drivers/cxl/core/cdat.c +++ b/drivers/cxl/core/cdat.c @@ -20,6 +20,36 @@ struct dsmas_entry { int qos_class; }; +static u32 cdat_normalize(u16 entry, u64 base, u8 type) +{ + u32 value; + + /* + * Check for invalid and overflow values + */ + if (entry == 0xffff || !entry) + return 0; + else if (base > (UINT_MAX / (entry))) + return 0; + + /* + * CDAT fields follow the format of HMAT fields. See table 5 Device + * Scoped Latency and Bandwidth Information Structure in Coherent Device + * Attribute Table (CDAT) Specification v1.01. + */ + value = entry * base; + switch (type) { + case ACPI_HMAT_ACCESS_LATENCY: + case ACPI_HMAT_READ_LATENCY: + case ACPI_HMAT_WRITE_LATENCY: + value = DIV_ROUND_UP(value, 1000); + break; + default: + break; + } + return value; +} + static int cdat_dsmas_handler(union acpi_subtable_headers *header, void *arg, const unsigned long end) { @@ -97,7 +127,6 @@ static int cdat_dslbis_handler(union acpi_subtable_headers *header, void *arg, __le16 le_val; u64 val; u16 len; - int rc; len = le16_to_cpu((__force __le16)hdr->length); if (len != size || (unsigned long)hdr + len > end) { @@ -124,10 +153,8 @@ static int cdat_dslbis_handler(union acpi_subtable_headers *header, void *arg, le_base = (__force __le64)dslbis->entry_base_unit; le_val = (__force __le16)dslbis->entry[0]; - rc = check_mul_overflow(le64_to_cpu(le_base), - le16_to_cpu(le_val), &val); - if (rc) - pr_warn("DSLBIS value overflowed.\n"); + val = cdat_normalize(le16_to_cpu(le_val), le64_to_cpu(le_base), + dslbis->data_type); cxl_access_coordinate_set(&dent->coord, dslbis->data_type, val); @@ -164,7 +191,6 @@ static int cxl_port_perf_data_calculate(struct cxl_port *port, struct xarray *dsmas_xa) { struct access_coordinate ep_c; - struct access_coordinate coord[ACCESS_COORDINATE_MAX]; struct dsmas_entry *dent; int valid_entries = 0; unsigned long index; @@ -176,12 +202,6 @@ static int cxl_port_perf_data_calculate(struct cxl_port *port, return rc; } - rc = cxl_hb_get_perf_coordinates(port, coord); - if (rc) { - dev_dbg(&port->dev, "Failed to retrieve hb perf coordinates.\n"); - return rc; - } - struct cxl_root *cxl_root __free(put_cxl_root) = find_cxl_root(port); if (!cxl_root) @@ -194,18 +214,9 @@ static int cxl_port_perf_data_calculate(struct cxl_port *port, int qos_class; cxl_coordinates_combine(&dent->coord, &dent->coord, &ep_c); - /* - * Keeping the host bridge coordinates separate from the dsmas - * coordinates in order to allow calculation of access class - * 0 and 1 for region later. - */ - cxl_coordinates_combine(&coord[ACCESS_COORDINATE_CPU], - &coord[ACCESS_COORDINATE_CPU], - &dent->coord); dent->entries = 1; - rc = cxl_root->ops->qos_class(cxl_root, - &coord[ACCESS_COORDINATE_CPU], - 1, &qos_class); + rc = cxl_root->ops->qos_class(cxl_root, &dent->coord, 1, + &qos_class); if (rc != 1) continue; @@ -461,10 +472,8 @@ static int cdat_sslbis_handler(union acpi_subtable_headers *header, void *arg, le_base = (__force __le64)tbl->sslbis_header.entry_base_unit; le_val = (__force __le16)tbl->entries[i].latency_or_bandwidth; - - if (check_mul_overflow(le64_to_cpu(le_base), - le16_to_cpu(le_val), &val)) - dev_warn(dev, "SSLBIS value overflowed!\n"); + val = cdat_normalize(le16_to_cpu(le_val), le64_to_cpu(le_base), + sslbis->data_type); xa_for_each(&port->dports, index, dport) { if (dsp_id == ACPI_CDAT_SSLBIS_ANY_PORT || @@ -521,17 +530,13 @@ void cxl_region_perf_data_calculate(struct cxl_region *cxlr, struct cxl_endpoint_decoder *cxled) { struct cxl_memdev *cxlmd = cxled_to_memdev(cxled); - struct cxl_port *port = cxlmd->endpoint; struct cxl_dev_state *cxlds = cxlmd->cxlds; struct cxl_memdev_state *mds = to_cxl_memdev_state(cxlds); - struct access_coordinate hb_coord[ACCESS_COORDINATE_MAX]; - struct access_coordinate coord; struct range dpa = { .start = cxled->dpa_res->start, .end = cxled->dpa_res->end, }; struct cxl_dpa_perf *perf; - int rc; switch (cxlr->mode) { case CXL_DECODER_RAM: @@ -549,35 +554,16 @@ void cxl_region_perf_data_calculate(struct cxl_region *cxlr, if (!range_contains(&perf->dpa_range, &dpa)) return; - rc = cxl_hb_get_perf_coordinates(port, hb_coord); - if (rc) { - dev_dbg(&port->dev, "Failed to retrieve hb perf coordinates.\n"); - return; - } - for (int i = 0; i < ACCESS_COORDINATE_MAX; i++) { - /* Pickup the host bridge coords */ - cxl_coordinates_combine(&coord, &hb_coord[i], &perf->coord); - /* Get total bandwidth and the worst latency for the cxl region */ cxlr->coord[i].read_latency = max_t(unsigned int, cxlr->coord[i].read_latency, - coord.read_latency); + perf->coord.read_latency); cxlr->coord[i].write_latency = max_t(unsigned int, cxlr->coord[i].write_latency, - coord.write_latency); - cxlr->coord[i].read_bandwidth += coord.read_bandwidth; - cxlr->coord[i].write_bandwidth += coord.write_bandwidth; - - /* - * Convert latency to nanosec from picosec to be consistent - * with the resulting latency coordinates computed by the - * HMAT_REPORTING code. - */ - cxlr->coord[i].read_latency = - DIV_ROUND_UP(cxlr->coord[i].read_latency, 1000); - cxlr->coord[i].write_latency = - DIV_ROUND_UP(cxlr->coord[i].write_latency, 1000); + perf->coord.write_latency); + cxlr->coord[i].read_bandwidth += perf->coord.read_bandwidth; + cxlr->coord[i].write_bandwidth += perf->coord.write_bandwidth; } } diff --git a/drivers/cxl/core/port.c b/drivers/cxl/core/port.c index 7aadcec4fc64..c7c00eb373af 100644 --- a/drivers/cxl/core/port.c +++ b/drivers/cxl/core/port.c @@ -2133,38 +2133,6 @@ bool schedule_cxl_memdev_detach(struct cxl_memdev *cxlmd) } EXPORT_SYMBOL_NS_GPL(schedule_cxl_memdev_detach, CXL); -/** - * cxl_hb_get_perf_coordinates - Retrieve performance numbers between initiator - * and host bridge - * - * @port: endpoint cxl_port - * @coord: output access coordinates - * - * Return: errno on failure, 0 on success. - */ -int cxl_hb_get_perf_coordinates(struct cxl_port *port, - struct access_coordinate *coord) -{ - struct cxl_port *iter = port; - struct cxl_dport *dport; - - if (!is_cxl_endpoint(port)) - return -EINVAL; - - dport = iter->parent_dport; - while (iter && !is_cxl_root(to_cxl_port(iter->dev.parent))) { - iter = to_cxl_port(iter->dev.parent); - dport = iter->parent_dport; - } - - coord[ACCESS_COORDINATE_LOCAL] = - dport->hb_coord[ACCESS_COORDINATE_LOCAL]; - coord[ACCESS_COORDINATE_CPU] = - dport->hb_coord[ACCESS_COORDINATE_CPU]; - - return 0; -} - static bool parent_port_is_cxl_root(struct cxl_port *port) { return is_cxl_root(to_cxl_port(port->dev.parent)); @@ -2215,6 +2183,10 @@ int cxl_endpoint_get_perf_coordinates(struct cxl_port *port, c.read_latency += dport->link_latency; } while (!is_cxl_root); + dport = iter->parent_dport; + /* Retrieve HB coords */ + cxl_coordinates_combine(&c, &c, dport->hb_coord); + /* Get the calculated PCI paths bandwidth */ pdev = to_pci_dev(port->uport_dev->parent); bw = pcie_bandwidth_available(pdev, NULL, NULL, NULL); diff --git a/drivers/cxl/cxl.h b/drivers/cxl/cxl.h index 534e25e2f0a4..ed02373ce3d9 100644 --- a/drivers/cxl/cxl.h +++ b/drivers/cxl/cxl.h @@ -884,8 +884,6 @@ void cxl_switch_parse_cdat(struct cxl_port *port); int cxl_endpoint_get_perf_coordinates(struct cxl_port *port, struct access_coordinate *coord); -int cxl_hb_get_perf_coordinates(struct cxl_port *port, - struct access_coordinate *coord); void cxl_region_perf_data_calculate(struct cxl_region *cxlr, struct cxl_endpoint_decoder *cxled); -- cgit v1.2.3 From 001c5d19341a39cb683ab0a18ce4b662a09d96a0 Mon Sep 17 00:00:00 2001 From: Dave Jiang Date: Wed, 3 Apr 2024 08:47:15 -0700 Subject: cxl: Consolidate dport access_coordinate ->hb_coord and ->sw_coord into ->coord The driver stores access_coordinate for host bridge in ->hb_coord and switch CDAT access_coordinate in ->sw_coord. Since neither of these access_coordinate clobber each other, the variable name can be consolidated into ->coord to simplify the code. Reviewed-by: Jonathan Cameron Reviewed-by: Davidlohr Bueso Reviewed-by: Dan Williams Link: https://lore.kernel.org/r/20240403154844.3403859-5-dave.jiang@intel.com Signed-off-by: Dave Jiang --- drivers/cxl/acpi.c | 2 +- drivers/cxl/core/cdat.c | 74 ++++++++++++++++++++++++++++---------------- drivers/cxl/core/port.c | 48 +++++++++++++++++++++------- drivers/cxl/cxl.h | 6 ++-- drivers/cxl/cxlmem.h | 2 +- tools/testing/cxl/test/cxl.c | 10 +++--- 6 files changed, 94 insertions(+), 48 deletions(-) diff --git a/drivers/cxl/acpi.c b/drivers/cxl/acpi.c index 566c387d4385..cb8c155a2c9b 100644 --- a/drivers/cxl/acpi.c +++ b/drivers/cxl/acpi.c @@ -529,7 +529,7 @@ static int get_genport_coordinates(struct device *dev, struct cxl_dport *dport) if (kstrtou32(acpi_device_uid(hb), 0, &uid)) return -EINVAL; - return acpi_get_genport_coordinates(uid, dport->hb_coord); + return acpi_get_genport_coordinates(uid, dport->coord); } static int add_host_bridge_dport(struct device *match, void *arg) diff --git a/drivers/cxl/core/cdat.c b/drivers/cxl/core/cdat.c index f66b493b5d3c..bb83867d9fec 100644 --- a/drivers/cxl/core/cdat.c +++ b/drivers/cxl/core/cdat.c @@ -14,7 +14,7 @@ struct dsmas_entry { struct range dpa_range; u8 handle; - struct access_coordinate coord; + struct access_coordinate coord[ACCESS_COORDINATE_MAX]; int entries; int qos_class; @@ -88,8 +88,8 @@ static int cdat_dsmas_handler(union acpi_subtable_headers *header, void *arg, return 0; } -static void cxl_access_coordinate_set(struct access_coordinate *coord, - int access, unsigned int val) +static void __cxl_access_coordinate_set(struct access_coordinate *coord, + int access, unsigned int val) { switch (access) { case ACPI_HMAT_ACCESS_LATENCY: @@ -115,6 +115,13 @@ static void cxl_access_coordinate_set(struct access_coordinate *coord, } } +static void cxl_access_coordinate_set(struct access_coordinate *coord, + int access, unsigned int val) +{ + for (int i = 0; i < ACCESS_COORDINATE_MAX; i++) + __cxl_access_coordinate_set(&coord[i], access, val); +} + static int cdat_dslbis_handler(union acpi_subtable_headers *header, void *arg, const unsigned long end) { @@ -156,7 +163,7 @@ static int cdat_dslbis_handler(union acpi_subtable_headers *header, void *arg, val = cdat_normalize(le16_to_cpu(le_val), le64_to_cpu(le_base), dslbis->data_type); - cxl_access_coordinate_set(&dent->coord, dslbis->data_type, val); + cxl_access_coordinate_set(dent->coord, dslbis->data_type, val); return 0; } @@ -190,13 +197,13 @@ static int cxl_cdat_endpoint_process(struct cxl_port *port, static int cxl_port_perf_data_calculate(struct cxl_port *port, struct xarray *dsmas_xa) { - struct access_coordinate ep_c; + struct access_coordinate ep_c[ACCESS_COORDINATE_MAX]; struct dsmas_entry *dent; int valid_entries = 0; unsigned long index; int rc; - rc = cxl_endpoint_get_perf_coordinates(port, &ep_c); + rc = cxl_endpoint_get_perf_coordinates(port, ep_c); if (rc) { dev_dbg(&port->dev, "Failed to retrieve ep perf coordinates.\n"); return rc; @@ -213,10 +220,11 @@ static int cxl_port_perf_data_calculate(struct cxl_port *port, xa_for_each(dsmas_xa, index, dent) { int qos_class; - cxl_coordinates_combine(&dent->coord, &dent->coord, &ep_c); + cxl_coordinates_combine(dent->coord, dent->coord, ep_c); dent->entries = 1; - rc = cxl_root->ops->qos_class(cxl_root, &dent->coord, 1, - &qos_class); + rc = cxl_root->ops->qos_class(cxl_root, + &dent->coord[ACCESS_COORDINATE_CPU], + 1, &qos_class); if (rc != 1) continue; @@ -233,14 +241,17 @@ static int cxl_port_perf_data_calculate(struct cxl_port *port, static void update_perf_entry(struct device *dev, struct dsmas_entry *dent, struct cxl_dpa_perf *dpa_perf) { + for (int i = 0; i < ACCESS_COORDINATE_MAX; i++) + dpa_perf->coord[i] = dent->coord[i]; dpa_perf->dpa_range = dent->dpa_range; - dpa_perf->coord = dent->coord; dpa_perf->qos_class = dent->qos_class; dev_dbg(dev, "DSMAS: dpa: %#llx qos: %d read_bw: %d write_bw %d read_lat: %d write_lat: %d\n", dent->dpa_range.start, dpa_perf->qos_class, - dent->coord.read_bandwidth, dent->coord.write_bandwidth, - dent->coord.read_latency, dent->coord.write_latency); + dent->coord[ACCESS_COORDINATE_CPU].read_bandwidth, + dent->coord[ACCESS_COORDINATE_CPU].write_bandwidth, + dent->coord[ACCESS_COORDINATE_CPU].read_latency, + dent->coord[ACCESS_COORDINATE_CPU].write_latency); } static void cxl_memdev_set_qos_class(struct cxl_dev_state *cxlds, @@ -477,10 +488,11 @@ static int cdat_sslbis_handler(union acpi_subtable_headers *header, void *arg, xa_for_each(&port->dports, index, dport) { if (dsp_id == ACPI_CDAT_SSLBIS_ANY_PORT || - dsp_id == dport->port_id) - cxl_access_coordinate_set(&dport->sw_coord, + dsp_id == dport->port_id) { + cxl_access_coordinate_set(dport->coord, sslbis->data_type, val); + } } } @@ -502,6 +514,21 @@ void cxl_switch_parse_cdat(struct cxl_port *port) } EXPORT_SYMBOL_NS_GPL(cxl_switch_parse_cdat, CXL); +static void __cxl_coordinates_combine(struct access_coordinate *out, + struct access_coordinate *c1, + struct access_coordinate *c2) +{ + if (c1->write_bandwidth && c2->write_bandwidth) + out->write_bandwidth = min(c1->write_bandwidth, + c2->write_bandwidth); + out->write_latency = c1->write_latency + c2->write_latency; + + if (c1->read_bandwidth && c2->read_bandwidth) + out->read_bandwidth = min(c1->read_bandwidth, + c2->read_bandwidth); + out->read_latency = c1->read_latency + c2->read_latency; +} + /** * cxl_coordinates_combine - Combine the two input coordinates * @@ -513,15 +540,8 @@ void cxl_coordinates_combine(struct access_coordinate *out, struct access_coordinate *c1, struct access_coordinate *c2) { - if (c1->write_bandwidth && c2->write_bandwidth) - out->write_bandwidth = min(c1->write_bandwidth, - c2->write_bandwidth); - out->write_latency = c1->write_latency + c2->write_latency; - - if (c1->read_bandwidth && c2->read_bandwidth) - out->read_bandwidth = min(c1->read_bandwidth, - c2->read_bandwidth); - out->read_latency = c1->read_latency + c2->read_latency; + for (int i = 0; i < ACCESS_COORDINATE_MAX; i++) + __cxl_coordinates_combine(&out[i], &c1[i], &c2[i]); } MODULE_IMPORT_NS(CXL); @@ -558,12 +578,12 @@ void cxl_region_perf_data_calculate(struct cxl_region *cxlr, /* Get total bandwidth and the worst latency for the cxl region */ cxlr->coord[i].read_latency = max_t(unsigned int, cxlr->coord[i].read_latency, - perf->coord.read_latency); + perf->coord[i].read_latency); cxlr->coord[i].write_latency = max_t(unsigned int, cxlr->coord[i].write_latency, - perf->coord.write_latency); - cxlr->coord[i].read_bandwidth += perf->coord.read_bandwidth; - cxlr->coord[i].write_bandwidth += perf->coord.write_bandwidth; + perf->coord[i].write_latency); + cxlr->coord[i].read_bandwidth += perf->coord[i].read_bandwidth; + cxlr->coord[i].write_bandwidth += perf->coord[i].write_bandwidth; } } diff --git a/drivers/cxl/core/port.c b/drivers/cxl/core/port.c index c7c00eb373af..801c4018a1dd 100644 --- a/drivers/cxl/core/port.c +++ b/drivers/cxl/core/port.c @@ -2133,6 +2133,29 @@ bool schedule_cxl_memdev_detach(struct cxl_memdev *cxlmd) } EXPORT_SYMBOL_NS_GPL(schedule_cxl_memdev_detach, CXL); +static void add_latency(struct access_coordinate *c, long latency) +{ + for (int i = 0; i < ACCESS_COORDINATE_MAX; i++) { + c[i].write_latency += latency; + c[i].read_latency += latency; + } +} + +static void set_min_bandwidth(struct access_coordinate *c, unsigned int bw) +{ + for (int i = 0; i < ACCESS_COORDINATE_MAX; i++) { + c[i].write_bandwidth = min(c[i].write_bandwidth, bw); + c[i].read_bandwidth = min(c[i].read_bandwidth, bw); + } +} + +static void set_access_coordinates(struct access_coordinate *out, + struct access_coordinate *in) +{ + for (int i = 0; i < ACCESS_COORDINATE_MAX; i++) + out[i] = in[i]; +} + static bool parent_port_is_cxl_root(struct cxl_port *port) { return is_cxl_root(to_cxl_port(port->dev.parent)); @@ -2149,9 +2172,15 @@ static bool parent_port_is_cxl_root(struct cxl_port *port) int cxl_endpoint_get_perf_coordinates(struct cxl_port *port, struct access_coordinate *coord) { - struct access_coordinate c = { - .read_bandwidth = UINT_MAX, - .write_bandwidth = UINT_MAX, + struct access_coordinate c[] = { + { + .read_bandwidth = UINT_MAX, + .write_bandwidth = UINT_MAX, + }, + { + .read_bandwidth = UINT_MAX, + .write_bandwidth = UINT_MAX, + }, }; struct cxl_port *iter = port; struct cxl_dport *dport; @@ -2178,14 +2207,13 @@ int cxl_endpoint_get_perf_coordinates(struct cxl_port *port, * have CDAT and therefore needs to be skipped. */ if (!is_cxl_root) - cxl_coordinates_combine(&c, &c, &dport->sw_coord); - c.write_latency += dport->link_latency; - c.read_latency += dport->link_latency; + cxl_coordinates_combine(c, c, dport->coord); + add_latency(c, dport->link_latency); } while (!is_cxl_root); dport = iter->parent_dport; /* Retrieve HB coords */ - cxl_coordinates_combine(&c, &c, dport->hb_coord); + cxl_coordinates_combine(c, c, dport->coord); /* Get the calculated PCI paths bandwidth */ pdev = to_pci_dev(port->uport_dev->parent); @@ -2194,10 +2222,8 @@ int cxl_endpoint_get_perf_coordinates(struct cxl_port *port, return -ENXIO; bw /= BITS_PER_BYTE; - c.write_bandwidth = min(c.write_bandwidth, bw); - c.read_bandwidth = min(c.read_bandwidth, bw); - - *coord = c; + set_min_bandwidth(c, bw); + set_access_coordinates(coord, c); return 0; } diff --git a/drivers/cxl/cxl.h b/drivers/cxl/cxl.h index ed02373ce3d9..036d17db68e0 100644 --- a/drivers/cxl/cxl.h +++ b/drivers/cxl/cxl.h @@ -663,8 +663,7 @@ struct cxl_rcrb_info { * @rch: Indicate whether this dport was enumerated in RCH or VH mode * @port: reference to cxl_port that contains this downstream port * @regs: Dport parsed register blocks - * @sw_coord: access coordinates (performance) for switch from CDAT - * @hb_coord: access coordinates (performance) from ACPI generic port (host bridge) + * @coord: access coordinates (bandwidth and latency performance attributes) * @link_latency: calculated PCIe downstream latency */ struct cxl_dport { @@ -675,8 +674,7 @@ struct cxl_dport { bool rch; struct cxl_port *port; struct cxl_regs regs; - struct access_coordinate sw_coord; - struct access_coordinate hb_coord[ACCESS_COORDINATE_MAX]; + struct access_coordinate coord[ACCESS_COORDINATE_MAX]; long link_latency; }; diff --git a/drivers/cxl/cxlmem.h b/drivers/cxl/cxlmem.h index 20fb3b35e89e..36cee9c30ceb 100644 --- a/drivers/cxl/cxlmem.h +++ b/drivers/cxl/cxlmem.h @@ -401,7 +401,7 @@ enum cxl_devtype { */ struct cxl_dpa_perf { struct range dpa_range; - struct access_coordinate coord; + struct access_coordinate coord[ACCESS_COORDINATE_MAX]; int qos_class; }; diff --git a/tools/testing/cxl/test/cxl.c b/tools/testing/cxl/test/cxl.c index 908e0d083936..61c69297e797 100644 --- a/tools/testing/cxl/test/cxl.c +++ b/tools/testing/cxl/test/cxl.c @@ -986,10 +986,12 @@ static void dpa_perf_setup(struct cxl_port *endpoint, struct range *range, { dpa_perf->qos_class = FAKE_QTG_ID; dpa_perf->dpa_range = *range; - dpa_perf->coord.read_latency = 500; - dpa_perf->coord.write_latency = 500; - dpa_perf->coord.read_bandwidth = 1000; - dpa_perf->coord.write_bandwidth = 1000; + for (int i = 0; i < ACCESS_COORDINATE_MAX; i++) { + dpa_perf->coord[i].read_latency = 500; + dpa_perf->coord[i].write_latency = 500; + dpa_perf->coord[i].read_bandwidth = 1000; + dpa_perf->coord[i].write_bandwidth = 1000; + } } static void mock_cxl_endpoint_parse_cdat(struct cxl_port *port) -- cgit v1.2.3 From 7bcf809b1e7889ab7e75fe1fcf8f1a98332f36d2 Mon Sep 17 00:00:00 2001 From: Dave Jiang Date: Wed, 3 Apr 2024 08:47:16 -0700 Subject: cxl: Add checks to access_coordinate calculation to fail missing data Jonathan noted that when the coordinates for host bridge and switches can be 0s if no actual data are retrieved and the calculation continues. The resulting number would be inaccurate. Add checks to ensure that the calculation would complete only if the numbers are valid. While not seen in the wild, issue may show up with a BIOS that reported CXL root ports via Generic Ports (via a PCI handle in the SRAT entry). Fixes: 14a6960b3e92 ("cxl: Add helper function that calculate performance data for downstream ports") Reported-by: Jonathan Cameron Reviewed-by: Jonathan Cameron Reviewed-by: Davidlohr Bueso Reviewed-by: Dan Williams Link: https://lore.kernel.org/r/20240403154844.3403859-6-dave.jiang@intel.com Signed-off-by: Dave Jiang --- drivers/cxl/core/port.c | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/drivers/cxl/core/port.c b/drivers/cxl/core/port.c index 801c4018a1dd..762783bb091a 100644 --- a/drivers/cxl/core/port.c +++ b/drivers/cxl/core/port.c @@ -2141,6 +2141,18 @@ static void add_latency(struct access_coordinate *c, long latency) } } +static bool coordinates_valid(struct access_coordinate *c) +{ + for (int i = 0; i < ACCESS_COORDINATE_MAX; i++) { + if (c[i].read_bandwidth && c[i].write_bandwidth && + c[i].read_latency && c[i].write_latency) + continue; + return false; + } + + return true; +} + static void set_min_bandwidth(struct access_coordinate *c, unsigned int bw) { for (int i = 0; i < ACCESS_COORDINATE_MAX; i++) { @@ -2206,13 +2218,18 @@ int cxl_endpoint_get_perf_coordinates(struct cxl_port *port, * There's no valid access_coordinate for a root port since RPs do not * have CDAT and therefore needs to be skipped. */ - if (!is_cxl_root) + if (!is_cxl_root) { + if (!coordinates_valid(dport->coord)) + return -EINVAL; cxl_coordinates_combine(c, c, dport->coord); + } add_latency(c, dport->link_latency); } while (!is_cxl_root); dport = iter->parent_dport; /* Retrieve HB coords */ + if (!coordinates_valid(dport->coord)) + return -EINVAL; cxl_coordinates_combine(c, c, dport->coord); /* Get the calculated PCI paths bandwidth */ -- cgit v1.2.3 From 0dd50b3e2c3d651ea972c97cff1af67870f3deaf Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Tue, 2 Apr 2024 14:43:51 +0200 Subject: platform/x86: toshiba_acpi: Silence logging for some events MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Stop logging unknown event / unknown keycode messages on suspend / resume on a Toshiba Portege Z830: 1. The Toshiba Portege Z830 sends a 0x8e event when the power button is pressed, ignore this. 2. The Toshiba Portege Z830 sends a 0xe00 hotkey event on resume from suspend, ignore this. Signed-off-by: Hans de Goede Link: https://lore.kernel.org/r/20240402124351.167152-1-hdegoede@redhat.com Reviewed-by: Ilpo Järvinen Signed-off-by: Ilpo Järvinen --- drivers/platform/x86/toshiba_acpi.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/platform/x86/toshiba_acpi.c b/drivers/platform/x86/toshiba_acpi.c index 291f14ef6702..77244c9aa60d 100644 --- a/drivers/platform/x86/toshiba_acpi.c +++ b/drivers/platform/x86/toshiba_acpi.c @@ -264,6 +264,7 @@ static const struct key_entry toshiba_acpi_keymap[] = { { KE_KEY, 0xb32, { KEY_NEXTSONG } }, { KE_KEY, 0xb33, { KEY_PLAYPAUSE } }, { KE_KEY, 0xb5a, { KEY_MEDIA } }, + { KE_IGNORE, 0x0e00, { KEY_RESERVED } }, /* Wake from sleep */ { KE_IGNORE, 0x1430, { KEY_RESERVED } }, /* Wake from sleep */ { KE_IGNORE, 0x1501, { KEY_RESERVED } }, /* Output changed */ { KE_IGNORE, 0x1502, { KEY_RESERVED } }, /* HDMI plugged/unplugged */ @@ -3523,9 +3524,10 @@ static void toshiba_acpi_notify(struct acpi_device *acpi_dev, u32 event) (dev->kbd_mode == SCI_KBD_MODE_ON) ? LED_FULL : LED_OFF); break; + case 0x8e: /* Power button pressed */ + break; case 0x85: /* Unknown */ case 0x8d: /* Unknown */ - case 0x8e: /* Unknown */ case 0x94: /* Unknown */ case 0x95: /* Unknown */ default: -- cgit v1.2.3 From 868adf8a29179c00309ddd8ffe0afa2043f42cb5 Mon Sep 17 00:00:00 2001 From: Gwendal Grignou Date: Fri, 29 Mar 2024 07:32:05 -0700 Subject: platform/x86: intel-vbtn: Use acpi_has_method to check for switch MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The check for a device having virtual buttons is done using acpi_has_method(..."VBDL"). Mimic that for checking virtual switch presence. Signed-off-by: Gwendal Grignou Reviewed-by: Kuppuswamy Sathyanarayanan Reviewed-by: Hans de Goede Link: https://lore.kernel.org/r/20240329143206.2977734-2-gwendal@chromium.org Reviewed-by: Ilpo Järvinen Signed-off-by: Ilpo Järvinen --- drivers/platform/x86/intel/vbtn.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/drivers/platform/x86/intel/vbtn.c b/drivers/platform/x86/intel/vbtn.c index 084c355c86f5..48f0ac19d6dd 100644 --- a/drivers/platform/x86/intel/vbtn.c +++ b/drivers/platform/x86/intel/vbtn.c @@ -258,9 +258,6 @@ static const struct dmi_system_id dmi_switches_allow_list[] = { static bool intel_vbtn_has_switches(acpi_handle handle, bool dual_accel) { - unsigned long long vgbs; - acpi_status status; - /* See dual_accel_detect.h for more info */ if (dual_accel) return false; @@ -268,8 +265,7 @@ static bool intel_vbtn_has_switches(acpi_handle handle, bool dual_accel) if (!dmi_check_system(dmi_switches_allow_list)) return false; - status = acpi_evaluate_integer(handle, "VGBS", NULL, &vgbs); - return ACPI_SUCCESS(status); + return acpi_has_method(handle, "VGBS"); } static int intel_vbtn_probe(struct platform_device *device) -- cgit v1.2.3 From 434e5781d8cd2d0ed512d920c6cdeba4b33a2e81 Mon Sep 17 00:00:00 2001 From: Gwendal Grignou Date: Fri, 29 Mar 2024 07:32:06 -0700 Subject: platform/x86: intel-vbtn: Update tablet mode switch at end of probe MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ACER Vivobook Flip (TP401NAS) virtual intel switch is implemented as follow: Device (VGBI) { Name (_HID, EisaId ("INT33D6") ... Name (VBDS, Zero) Method (_STA, 0, Serialized) // _STA: Status ... Method (VBDL, 0, Serialized) { PB1E |= 0x20 VBDS |= 0x40 } Method (VGBS, 0, Serialized) { Return (VBDS) /* \_SB_.PCI0.SBRG.EC0_.VGBI.VBDS */ } ... } By default VBDS is set to 0. At boot it is set to clamshell (bit 6 set) only after method VBDL is executed. Since VBDL is now evaluated in the probe routine later, after the device is registered, the retrieved value of VBDS was still 0 ("tablet mode") when setting up the virtual switch. Make sure to evaluate VGBS after VBDL, to ensure the convertible boots in clamshell mode, the expected default. Fixes: 26173179fae1 ("platform/x86: intel-vbtn: Eval VBDL after registering our notifier") Signed-off-by: Gwendal Grignou Reviewed-by: Kuppuswamy Sathyanarayanan Reviewed-by: Hans de Goede Link: https://lore.kernel.org/r/20240329143206.2977734-3-gwendal@chromium.org Reviewed-by: Ilpo Järvinen Signed-off-by: Ilpo Järvinen --- drivers/platform/x86/intel/vbtn.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/platform/x86/intel/vbtn.c b/drivers/platform/x86/intel/vbtn.c index 48f0ac19d6dd..79bb2c801daa 100644 --- a/drivers/platform/x86/intel/vbtn.c +++ b/drivers/platform/x86/intel/vbtn.c @@ -136,8 +136,6 @@ static int intel_vbtn_input_setup(struct platform_device *device) priv->switches_dev->id.bustype = BUS_HOST; if (priv->has_switches) { - detect_tablet_mode(&device->dev); - ret = input_register_device(priv->switches_dev); if (ret) return ret; @@ -312,6 +310,9 @@ static int intel_vbtn_probe(struct platform_device *device) if (ACPI_FAILURE(status)) dev_err(&device->dev, "Error VBDL failed with ACPI status %d\n", status); } + // Check switches after buttons since VBDL may have side effects. + if (has_switches) + detect_tablet_mode(&device->dev); device_init_wakeup(&device->dev, true); /* -- cgit v1.2.3 From e71c8481692582c70cdfd0996c20cdcc71e425d3 Mon Sep 17 00:00:00 2001 From: Gergo Koteles Date: Wed, 3 Apr 2024 16:34:27 +0200 Subject: platform/x86: lg-laptop: fix %s null argument warning MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit W=1 warns about null argument to kprintf: warning: ‘%s’ directive argument is null [-Wformat-overflow=] pr_info("product: %s year: %d\n", product, year); Use "unknown" instead of NULL. Signed-off-by: Gergo Koteles Reviewed-by: Kuppuswamy Sathyanarayanan Link: https://lore.kernel.org/r/33d40e976f08f82b9227d0ecae38c787fcc0c0b2.1712154684.git.soyer@irl.hu Reviewed-by: Ilpo Järvinen Signed-off-by: Ilpo Järvinen --- drivers/platform/x86/lg-laptop.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/platform/x86/lg-laptop.c b/drivers/platform/x86/lg-laptop.c index ad3c39e9e9f5..e714ee6298dd 100644 --- a/drivers/platform/x86/lg-laptop.c +++ b/drivers/platform/x86/lg-laptop.c @@ -736,7 +736,7 @@ static int acpi_add(struct acpi_device *device) default: year = 2019; } - pr_info("product: %s year: %d\n", product, year); + pr_info("product: %s year: %d\n", product ?: "unknown", year); if (year >= 2019) battery_limit_use_wmbb = 1; -- cgit v1.2.3 From 7b1f6b5aaec0f849e19c3e99d4eea75876853cdd Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Tue, 2 Apr 2024 18:50:03 +0300 Subject: drm/i915/cdclk: Fix CDCLK programming order when pipes are active MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Currently we always reprogram CDCLK from the intel_set_cdclk_pre_plane_update() when using squash/crawl. The code only works correctly for the cd2x update or full modeset cases, and it was simply never updated to deal with squash/crawl. If the CDCLK frequency is increasing we must reprogram it before we do anything else that might depend on the new higher frequency, and conversely we must not decrease the frequency until everything that might still depend on the old higher frequency has been dealt with. Since cdclk_state->pipe is only relevant when doing a cd2x update we can't use it to determine the correct sequence during squash/crawl. To that end introduce cdclk_state->disable_pipes which simply indicates that we must perform the update while the pipes are disable (ie. during intel_set_cdclk_pre_plane_update()). Otherwise we use the same old vs. new CDCLK frequency comparsiong as for cd2x updates. The only remaining problem case is when the voltage_level needs to increase due to a DDI port, but the CDCLK frequency is decreasing (and not all pipes are being disabled). The current approach will not bump the voltage level up until after the port has already been enabled, which is too late. But we'll take care of that case separately. v2: Don't break the "must disable pipes case" v3: Keep the on stack 'pipe' for future use Cc: stable@vger.kernel.org Fixes: d62686ba3b54 ("drm/i915/adl_p: CDCLK crawl support for ADL") Reviewed-by: Uma Shankar Reviewed-by: Gustavo Sousa Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20240402155016.13733-2-ville.syrjala@linux.intel.com (cherry picked from commit 3aecee90ac12a351905f12dda7643d5b0676d6ca) Signed-off-by: Rodrigo Vivi --- drivers/gpu/drm/i915/display/intel_cdclk.c | 7 +++++-- drivers/gpu/drm/i915/display/intel_cdclk.h | 3 +++ 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_cdclk.c b/drivers/gpu/drm/i915/display/intel_cdclk.c index ed89b86ea625..4833479e2e17 100644 --- a/drivers/gpu/drm/i915/display/intel_cdclk.c +++ b/drivers/gpu/drm/i915/display/intel_cdclk.c @@ -2543,7 +2543,7 @@ intel_set_cdclk_pre_plane_update(struct intel_atomic_state *state) if (IS_DG2(i915)) intel_cdclk_pcode_pre_notify(state); - if (pipe == INVALID_PIPE || + if (new_cdclk_state->disable_pipes || old_cdclk_state->actual.cdclk <= new_cdclk_state->actual.cdclk) { drm_WARN_ON(&i915->drm, !new_cdclk_state->base.changed); @@ -2575,7 +2575,7 @@ intel_set_cdclk_post_plane_update(struct intel_atomic_state *state) if (IS_DG2(i915)) intel_cdclk_pcode_post_notify(state); - if (pipe != INVALID_PIPE && + if (!new_cdclk_state->disable_pipes && old_cdclk_state->actual.cdclk > new_cdclk_state->actual.cdclk) { drm_WARN_ON(&i915->drm, !new_cdclk_state->base.changed); @@ -3058,6 +3058,7 @@ static struct intel_global_state *intel_cdclk_duplicate_state(struct intel_globa return NULL; cdclk_state->pipe = INVALID_PIPE; + cdclk_state->disable_pipes = false; return &cdclk_state->base; } @@ -3236,6 +3237,8 @@ int intel_modeset_calc_cdclk(struct intel_atomic_state *state) if (ret) return ret; + new_cdclk_state->disable_pipes = true; + drm_dbg_kms(&dev_priv->drm, "Modeset required for cdclk change\n"); } diff --git a/drivers/gpu/drm/i915/display/intel_cdclk.h b/drivers/gpu/drm/i915/display/intel_cdclk.h index 48fd7d39e0cd..71bc032bfef1 100644 --- a/drivers/gpu/drm/i915/display/intel_cdclk.h +++ b/drivers/gpu/drm/i915/display/intel_cdclk.h @@ -51,6 +51,9 @@ struct intel_cdclk_state { /* bitmask of active pipes */ u8 active_pipes; + + /* update cdclk with pipes disabled */ + bool disable_pipes; }; int intel_crtc_compute_min_cdclk(const struct intel_crtc_state *crtc_state); -- cgit v1.2.3 From 6154cc9177ccea00c89ce0bf93352e474b819ff2 Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Tue, 2 Apr 2024 18:50:04 +0300 Subject: drm/i915/cdclk: Fix voltage_level programming edge case MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Currently we only consider the relationship of the old and new CDCLK frequencies when determining whether to do the repgramming from intel_set_cdclk_pre_plane_update() or intel_set_cdclk_post_plane_update(). It is technically possible to have a situation where the CDCLK frequency is decreasing, but the voltage_level is increasing due a DDI port. In this case we should bump the voltage level already in intel_set_cdclk_pre_plane_update() (so that the voltage_level will have been increased by the time the port gets enabled), while leaving the CDCLK frequency unchanged (as active planes/etc. may still depend on it). We can then reduce the CDCLK frequency to its final value from intel_set_cdclk_post_plane_update(). In order to handle that correctly we shall construct a suitable amalgam of the old and new cdclk states in intel_set_cdclk_pre_plane_update(). And we can simply call intel_set_cdclk() unconditionally in both places as it will not do anything if nothing actually changes vs. the current hw state. v2: Handle cdclk_state->disable_pipes v3: Only synchronize the cd2x update against the pipe's vblank when the cdclk frequency is changing during the current commit phase (Gustavo) Cc: stable@vger.kernel.org Cc: Gustavo Sousa Reviewed-by: Uma Shankar Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20240402155016.13733-3-ville.syrjala@linux.intel.com (cherry picked from commit 34d127e2bdef73a923aa0dcd95cbc3257ad5af52) Signed-off-by: Rodrigo Vivi --- drivers/gpu/drm/i915/display/intel_cdclk.c | 37 ++++++++++++++++++++++-------- 1 file changed, 27 insertions(+), 10 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_cdclk.c b/drivers/gpu/drm/i915/display/intel_cdclk.c index 4833479e2e17..f672bfd70d45 100644 --- a/drivers/gpu/drm/i915/display/intel_cdclk.c +++ b/drivers/gpu/drm/i915/display/intel_cdclk.c @@ -2534,7 +2534,8 @@ intel_set_cdclk_pre_plane_update(struct intel_atomic_state *state) intel_atomic_get_old_cdclk_state(state); const struct intel_cdclk_state *new_cdclk_state = intel_atomic_get_new_cdclk_state(state); - enum pipe pipe = new_cdclk_state->pipe; + struct intel_cdclk_config cdclk_config; + enum pipe pipe; if (!intel_cdclk_changed(&old_cdclk_state->actual, &new_cdclk_state->actual)) @@ -2543,12 +2544,25 @@ intel_set_cdclk_pre_plane_update(struct intel_atomic_state *state) if (IS_DG2(i915)) intel_cdclk_pcode_pre_notify(state); - if (new_cdclk_state->disable_pipes || - old_cdclk_state->actual.cdclk <= new_cdclk_state->actual.cdclk) { - drm_WARN_ON(&i915->drm, !new_cdclk_state->base.changed); + if (new_cdclk_state->disable_pipes) { + cdclk_config = new_cdclk_state->actual; + pipe = INVALID_PIPE; + } else { + if (new_cdclk_state->actual.cdclk >= old_cdclk_state->actual.cdclk) { + cdclk_config = new_cdclk_state->actual; + pipe = new_cdclk_state->pipe; + } else { + cdclk_config = old_cdclk_state->actual; + pipe = INVALID_PIPE; + } - intel_set_cdclk(i915, &new_cdclk_state->actual, pipe); + cdclk_config.voltage_level = max(new_cdclk_state->actual.voltage_level, + old_cdclk_state->actual.voltage_level); } + + drm_WARN_ON(&i915->drm, !new_cdclk_state->base.changed); + + intel_set_cdclk(i915, &cdclk_config, pipe); } /** @@ -2566,7 +2580,7 @@ intel_set_cdclk_post_plane_update(struct intel_atomic_state *state) intel_atomic_get_old_cdclk_state(state); const struct intel_cdclk_state *new_cdclk_state = intel_atomic_get_new_cdclk_state(state); - enum pipe pipe = new_cdclk_state->pipe; + enum pipe pipe; if (!intel_cdclk_changed(&old_cdclk_state->actual, &new_cdclk_state->actual)) @@ -2576,11 +2590,14 @@ intel_set_cdclk_post_plane_update(struct intel_atomic_state *state) intel_cdclk_pcode_post_notify(state); if (!new_cdclk_state->disable_pipes && - old_cdclk_state->actual.cdclk > new_cdclk_state->actual.cdclk) { - drm_WARN_ON(&i915->drm, !new_cdclk_state->base.changed); + new_cdclk_state->actual.cdclk < old_cdclk_state->actual.cdclk) + pipe = new_cdclk_state->pipe; + else + pipe = INVALID_PIPE; - intel_set_cdclk(i915, &new_cdclk_state->actual, pipe); - } + drm_WARN_ON(&i915->drm, !new_cdclk_state->base.changed); + + intel_set_cdclk(i915, &new_cdclk_state->actual, pipe); } static int intel_pixel_rate_to_cdclk(const struct intel_crtc_state *crtc_state) -- cgit v1.2.3 From 12bcd9108f9d3b8d4b5f4418bd16df4628b6fa8f Mon Sep 17 00:00:00 2001 From: Suraj Kandpal Date: Mon, 1 Apr 2024 11:26:53 +0530 Subject: drm/i915/hdcp: Fix get remote hdcp capability function HDCP 1.x capability needs to be checked even if setup is not HDCP 2.x capable. --v2 -Assign hdcp_capable and hdcp2_capable to false [Chaitanya] --v3 -Fix variable assignment [Chaitanya] Fixes: 813cca96e4ac ("drm/i915/hdcp: Add new remote capability check shim function") Signed-off-by: Suraj Kandpal Reviewed-by: Chaitanya Kumar Borah Signed-off-by: Animesh Manna Link: https://patchwork.freedesktop.org/patch/msgid/20240401055652.276785-2-suraj.kandpal@intel.com (cherry picked from commit 6809f9246d43f7cb07310ca6a3deb7aa1c0ea938) Signed-off-by: Rodrigo Vivi --- drivers/gpu/drm/i915/display/intel_dp_hdcp.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/display/intel_dp_hdcp.c b/drivers/gpu/drm/i915/display/intel_dp_hdcp.c index b98a87883fef..9db43bd81ce2 100644 --- a/drivers/gpu/drm/i915/display/intel_dp_hdcp.c +++ b/drivers/gpu/drm/i915/display/intel_dp_hdcp.c @@ -691,12 +691,15 @@ int intel_dp_hdcp_get_remote_capability(struct intel_connector *connector, u8 bcaps; int ret; + *hdcp_capable = false; + *hdcp2_capable = false; if (!intel_encoder_is_mst(connector->encoder)) return -EINVAL; ret = _intel_dp_hdcp2_get_capability(aux, hdcp2_capable); if (ret) - return ret; + drm_dbg_kms(&i915->drm, + "HDCP2 DPCD capability read failed err: %d\n", ret); ret = intel_dp_hdcp_read_bcaps(aux, i915, &bcaps); if (ret) -- cgit v1.2.3 From 152191e5e94bba55c938c18688e66c7276b765a7 Mon Sep 17 00:00:00 2001 From: John Harrison Date: Fri, 29 Mar 2024 16:53:05 -0700 Subject: drm/i915/guc: Fix the fix for reset lock confusion The previous fix for the circlular lock splat about the busyness worker wasn't quite complete. Even though the reset-in-progress flag is cleared at the start of intel_uc_reset_finish, the entire function is still inside the reset mutex lock. Not sure why the patch appeared to fix the issue both locally and in CI. However, it is now back again. There is a further complication that the wedge code path within intel_gt_reset() jumps around so much that it results in nested reset_prepare/_finish calls. That is, the call sequence is: intel_gt_reset | reset_prepare | __intel_gt_set_wedged | | reset_prepare | | reset_finish | reset_finish The nested finish means that even if the clear of the in-progress flag was moved to the end of _finish, it would still be clear for the entire second call. Surprisingly, this does not seem to be causing any other problems at present. As an aside, a wedge on fini does not call the finish functions at all. The reset_in_progress flag is left set (twice). So instead of trying to cancel the worker anywhere at all in the reset path, just add a cancel to intel_guc_submission_fini instead. Note that it is not a problem if the worker is still active during a reset. Either it will run before the reset path starts locking things and will simply block the reset code for a tiny amount of time. Or it will run after the locks have been acquired and will early exit due to the try-lock. Also, do not use the reset-in-progress flag to decide whether a synchronous cancel is safe (from a lockdep perspective) or not. Instead, use the actual reset mutex state (both the genuine one and the custom rolled BACKOFF one). Fixes: 0e00a8814eec ("drm/i915/guc: Avoid circular locking issue on busyness flush") Signed-off-by: John Harrison Cc: Zhanjun Dong Cc: John Harrison Cc: Andi Shyti Cc: Daniel Vetter Cc: Daniel Vetter Cc: Rodrigo Vivi Cc: Nirmoy Das Cc: Tvrtko Ursulin Cc: Umesh Nerlige Ramappa Cc: Andrzej Hajda Cc: Matt Roper Cc: Jonathan Cavitt Cc: Prathap Kumar Valsan Cc: Alan Previn Cc: Madhumitha Tolakanahalli Pradeep Cc: Daniele Ceraolo Spurio Cc: Ashutosh Dixit Cc: Dnyaneshwar Bhadane Reviewed-by: Nirmoy Das Reviewed-by: Andi Shyti Link: https://patchwork.freedesktop.org/patch/msgid/20240329235306.1559639-1-John.C.Harrison@Intel.com (cherry picked from commit 3563d855312acedcd445a3767f0cb07906f1c26f) Signed-off-by: Rodrigo Vivi --- drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c | 23 +++++++++-------------- drivers/gpu/drm/i915/gt/uc/intel_uc.c | 4 ++++ 2 files changed, 13 insertions(+), 14 deletions(-) diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c b/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c index f3dcae4b9d45..0f83c6d4376f 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c @@ -1403,14 +1403,17 @@ static void guc_cancel_busyness_worker(struct intel_guc *guc) * Trying to pass a 'need_sync' or 'in_reset' flag all the way down through * every possible call stack is unfeasible. It would be too intrusive to many * areas that really don't care about the GuC backend. However, there is the - * 'reset_in_progress' flag available, so just use that. + * I915_RESET_BACKOFF flag and the gt->reset.mutex can be tested for is_locked. + * So just use those. Note that testing both is required due to the hideously + * complex nature of the i915 driver's reset code paths. * * And note that in the case of a reset occurring during driver unload - * (wedge_on_fini), skipping the cancel in _prepare (when the reset flag is set - * is fine because there is another cancel in _finish (when the reset flag is - * not). + * (wedged_on_fini), skipping the cancel in reset_prepare/reset_fini (when the + * reset flag/mutex are set) is fine because there is another explicit cancel in + * intel_guc_submission_fini (when the reset flag/mutex are not). */ - if (guc_to_gt(guc)->uc.reset_in_progress) + if (mutex_is_locked(&guc_to_gt(guc)->reset.mutex) || + test_bit(I915_RESET_BACKOFF, &guc_to_gt(guc)->reset.flags)) cancel_delayed_work(&guc->timestamp.work); else cancel_delayed_work_sync(&guc->timestamp.work); @@ -1424,8 +1427,6 @@ static void __reset_guc_busyness_stats(struct intel_guc *guc) unsigned long flags; ktime_t unused; - guc_cancel_busyness_worker(guc); - spin_lock_irqsave(&guc->timestamp.lock, flags); guc_update_pm_timestamp(guc, &unused); @@ -2004,13 +2005,6 @@ void intel_guc_submission_cancel_requests(struct intel_guc *guc) void intel_guc_submission_reset_finish(struct intel_guc *guc) { - /* - * Ensure the busyness worker gets cancelled even on a fatal wedge. - * Note that reset_prepare is not allowed to because it confuses lockdep. - */ - if (guc_submission_initialized(guc)) - guc_cancel_busyness_worker(guc); - /* Reset called during driver load or during wedge? */ if (unlikely(!guc_submission_initialized(guc) || !intel_guc_is_fw_running(guc) || @@ -2136,6 +2130,7 @@ void intel_guc_submission_fini(struct intel_guc *guc) if (!guc->submission_initialized) return; + guc_fini_engine_stats(guc); guc_flush_destroyed_contexts(guc); guc_lrc_desc_pool_destroy_v69(guc); i915_sched_engine_put(guc->sched_engine); diff --git a/drivers/gpu/drm/i915/gt/uc/intel_uc.c b/drivers/gpu/drm/i915/gt/uc/intel_uc.c index 6dfe5d9456c6..399bc319180b 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_uc.c +++ b/drivers/gpu/drm/i915/gt/uc/intel_uc.c @@ -637,6 +637,10 @@ void intel_uc_reset_finish(struct intel_uc *uc) { struct intel_guc *guc = &uc->guc; + /* + * NB: The wedge code path results in prepare -> prepare -> finish -> finish. + * So this function is sometimes called with the in-progress flag not set. + */ uc->reset_in_progress = false; /* Firmware expected to be running when this function is called */ -- cgit v1.2.3 From e3d4ead4d48c05355bd3b99c8162428f68c3c1a5 Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Fri, 5 Apr 2024 00:34:26 +0300 Subject: drm/i915/psr: Disable PSR when bigjoiner is used MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bigjoiner seem to be causing all kinds of grief to the PSR code currently. I don't believe there is any hardware issue but the code simply not handling this correctly. For now just disable PSR when bigjoiner is needed. Cc: stable@vger.kernel.org Link: https://patchwork.freedesktop.org/patch/msgid/20240404213441.17637-3-ville.syrjala@linux.intel.com Reviewed-by: Arun R Murthy Acked-by: Jouni Högander Signed-off-by: Ville Syrjälä (cherry picked from commit 372fa0c79d3f289f813d8001e0a8a96d1011826c) Signed-off-by: Rodrigo Vivi --- drivers/gpu/drm/i915/display/intel_psr.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/drivers/gpu/drm/i915/display/intel_psr.c b/drivers/gpu/drm/i915/display/intel_psr.c index b6e539f1342c..aabd018bd737 100644 --- a/drivers/gpu/drm/i915/display/intel_psr.c +++ b/drivers/gpu/drm/i915/display/intel_psr.c @@ -1422,6 +1422,17 @@ void intel_psr_compute_config(struct intel_dp *intel_dp, return; } + /* + * FIXME figure out what is wrong with PSR+bigjoiner and + * fix it. Presumably something related to the fact that + * PSR is a transcoder level feature. + */ + if (crtc_state->bigjoiner_pipes) { + drm_dbg_kms(&dev_priv->drm, + "PSR disabled due to bigjoiner\n"); + return; + } + if (CAN_PANEL_REPLAY(intel_dp)) crtc_state->has_panel_replay = true; else -- cgit v1.2.3 From 0653d501409eeb9f1deb7e4c12e4d0d2c9f1cba1 Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Fri, 5 Apr 2024 00:34:27 +0300 Subject: drm/i915: Disable port sync when bigjoiner is used MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The current modeset sequence can't handle port sync and bigjoiner at the same time. Refuse port sync when bigjoiner is needed, at least until we fix the modeset sequence. v2: Add a FIXME (Vandite) Cc: stable@vger.kernel.org Tested-by: Vidya Srinivas Reviewed-by: Vandita Kulkarni Link: https://patchwork.freedesktop.org/patch/msgid/20240404213441.17637-4-ville.syrjala@linux.intel.com Signed-off-by: Ville Syrjälä (cherry picked from commit b37e1347b991459c38c56ec2476087854a4f720b) Signed-off-by: Rodrigo Vivi --- drivers/gpu/drm/i915/display/intel_ddi.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/gpu/drm/i915/display/intel_ddi.c b/drivers/gpu/drm/i915/display/intel_ddi.c index c587a8efeafc..c17462b4c2ac 100644 --- a/drivers/gpu/drm/i915/display/intel_ddi.c +++ b/drivers/gpu/drm/i915/display/intel_ddi.c @@ -4256,7 +4256,12 @@ static bool m_n_equal(const struct intel_link_m_n *m_n_1, static bool crtcs_port_sync_compatible(const struct intel_crtc_state *crtc_state1, const struct intel_crtc_state *crtc_state2) { + /* + * FIXME the modeset sequence is currently wrong and + * can't deal with bigjoiner + port sync at the same time. + */ return crtc_state1->hw.active && crtc_state2->hw.active && + !crtc_state1->bigjoiner_pipes && !crtc_state2->bigjoiner_pipes && crtc_state1->output_types == crtc_state2->output_types && crtc_state1->output_format == crtc_state2->output_format && crtc_state1->lane_count == crtc_state2->lane_count && -- cgit v1.2.3 From 4a36e46df7aa781c756f09727d37dc2783f1ee75 Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Fri, 5 Apr 2024 00:34:28 +0300 Subject: drm/i915: Disable live M/N updates when using bigjoiner MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit All joined pipes share the same transcoder/timing generator. Currently we just do the commits per-pipe, which doesn't really work if we need to change the timings at the same time. For now just disable live M/N updates when bigjoiner is needed. Cc: stable@vger.kernel.org Tested-by: Vidya Srinivas Reviewed-by: Arun R Murthy Link: https://patchwork.freedesktop.org/patch/msgid/20240404213441.17637-5-ville.syrjala@linux.intel.com Signed-off-by: Ville Syrjälä (cherry picked from commit ef79820db723a2a7c229a7251c12859e7e25a247) Signed-off-by: Rodrigo Vivi --- drivers/gpu/drm/i915/display/intel_dp.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c index abd62bebc46d..e583515f9b25 100644 --- a/drivers/gpu/drm/i915/display/intel_dp.c +++ b/drivers/gpu/drm/i915/display/intel_dp.c @@ -2725,7 +2725,11 @@ intel_dp_drrs_compute_config(struct intel_connector *connector, intel_panel_downclock_mode(connector, &pipe_config->hw.adjusted_mode); int pixel_clock; - if (has_seamless_m_n(connector)) + /* + * FIXME all joined pipes share the same transcoder. + * Need to account for that when updating M/N live. + */ + if (has_seamless_m_n(connector) && !pipe_config->bigjoiner_pipes) pipe_config->update_m_n = true; if (!can_enable_drrs(connector, pipe_config, downclock_mode)) { -- cgit v1.2.3 From dcd8992e47f13afb5c11a61e8d9c141c35e23751 Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Fri, 5 Apr 2024 00:34:29 +0300 Subject: drm/i915/vrr: Disable VRR when using bigjoiner MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit All joined pipes share the same transcoder/timing generator. Currently we just do the commits per-pipe, which doesn't really work if we need to change switch between non-VRR and VRR timings generators on the fly, or even when sending the push to the transcoder. For now just disable VRR when bigjoiner is needed. Cc: stable@vger.kernel.org Tested-by: Vidya Srinivas Reviewed-by: Vandita Kulkarni Link: https://patchwork.freedesktop.org/patch/msgid/20240404213441.17637-6-ville.syrjala@linux.intel.com Signed-off-by: Ville Syrjälä (cherry picked from commit f9d5e51db65652dbd8a2102fd7619440e3599fd2) Signed-off-by: Rodrigo Vivi --- drivers/gpu/drm/i915/display/intel_vrr.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/drivers/gpu/drm/i915/display/intel_vrr.c b/drivers/gpu/drm/i915/display/intel_vrr.c index eb5bd0743902..f542ee1db1d9 100644 --- a/drivers/gpu/drm/i915/display/intel_vrr.c +++ b/drivers/gpu/drm/i915/display/intel_vrr.c @@ -117,6 +117,13 @@ intel_vrr_compute_config(struct intel_crtc_state *crtc_state, const struct drm_display_info *info = &connector->base.display_info; int vmin, vmax; + /* + * FIXME all joined pipes share the same transcoder. + * Need to account for that during VRR toggle/push/etc. + */ + if (crtc_state->bigjoiner_pipes) + return; + if (adjusted_mode->flags & DRM_MODE_FLAG_INTERLACE) return; -- cgit v1.2.3 From 0cd01ac5dcb1e18eb18df0f0d05b5de76522a437 Mon Sep 17 00:00:00 2001 From: Josh Poimboeuf Date: Fri, 5 Apr 2024 11:14:13 -0700 Subject: x86/bugs: Change commas to semicolons in 'spectre_v2' sysfs file Change the format of the 'spectre_v2' vulnerabilities sysfs file slightly by converting the commas to semicolons, so that mitigations for future variants can be grouped together and separated by commas. Signed-off-by: Josh Poimboeuf Signed-off-by: Daniel Sneddon Signed-off-by: Thomas Gleixner --- arch/x86/kernel/cpu/bugs.c | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/arch/x86/kernel/cpu/bugs.c b/arch/x86/kernel/cpu/bugs.c index e7ba936d798b..e8c7146f9ed7 100644 --- a/arch/x86/kernel/cpu/bugs.c +++ b/arch/x86/kernel/cpu/bugs.c @@ -2695,15 +2695,15 @@ static char *stibp_state(void) switch (spectre_v2_user_stibp) { case SPECTRE_V2_USER_NONE: - return ", STIBP: disabled"; + return "; STIBP: disabled"; case SPECTRE_V2_USER_STRICT: - return ", STIBP: forced"; + return "; STIBP: forced"; case SPECTRE_V2_USER_STRICT_PREFERRED: - return ", STIBP: always-on"; + return "; STIBP: always-on"; case SPECTRE_V2_USER_PRCTL: case SPECTRE_V2_USER_SECCOMP: if (static_key_enabled(&switch_to_cond_stibp)) - return ", STIBP: conditional"; + return "; STIBP: conditional"; } return ""; } @@ -2712,10 +2712,10 @@ static char *ibpb_state(void) { if (boot_cpu_has(X86_FEATURE_IBPB)) { if (static_key_enabled(&switch_mm_always_ibpb)) - return ", IBPB: always-on"; + return "; IBPB: always-on"; if (static_key_enabled(&switch_mm_cond_ibpb)) - return ", IBPB: conditional"; - return ", IBPB: disabled"; + return "; IBPB: conditional"; + return "; IBPB: disabled"; } return ""; } @@ -2725,11 +2725,11 @@ static char *pbrsb_eibrs_state(void) if (boot_cpu_has_bug(X86_BUG_EIBRS_PBRSB)) { if (boot_cpu_has(X86_FEATURE_RSB_VMEXIT_LITE) || boot_cpu_has(X86_FEATURE_RSB_VMEXIT)) - return ", PBRSB-eIBRS: SW sequence"; + return "; PBRSB-eIBRS: SW sequence"; else - return ", PBRSB-eIBRS: Vulnerable"; + return "; PBRSB-eIBRS: Vulnerable"; } else { - return ", PBRSB-eIBRS: Not affected"; + return "; PBRSB-eIBRS: Not affected"; } } @@ -2748,9 +2748,9 @@ static ssize_t spectre_v2_show_state(char *buf) return sysfs_emit(buf, "%s%s%s%s%s%s%s\n", spectre_v2_strings[spectre_v2_enabled], ibpb_state(), - boot_cpu_has(X86_FEATURE_USE_IBRS_FW) ? ", IBRS_FW" : "", + boot_cpu_has(X86_FEATURE_USE_IBRS_FW) ? "; IBRS_FW" : "", stibp_state(), - boot_cpu_has(X86_FEATURE_RSB_CTXSW) ? ", RSB filling" : "", + boot_cpu_has(X86_FEATURE_RSB_CTXSW) ? "; RSB filling" : "", pbrsb_eibrs_state(), spectre_v2_module_string()); } -- cgit v1.2.3 From 1e3ad78334a69b36e107232e337f9d693dcc9df2 Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Wed, 3 Apr 2024 16:36:44 -0700 Subject: x86/syscall: Don't force use of indirect calls for system calls Make build a switch statement instead, and the compiler can either decide to generate an indirect jump, or - more likely these days due to mitigations - just a series of conditional branches. Yes, the conditional branches also have branch prediction, but the branch prediction is much more controlled, in that it just causes speculatively running the wrong system call (harmless), rather than speculatively running possibly wrong random less controlled code gadgets. This doesn't mitigate other indirect calls, but the system call indirection is the first and most easily triggered case. Signed-off-by: Linus Torvalds Signed-off-by: Daniel Sneddon Signed-off-by: Thomas Gleixner Reviewed-by: Josh Poimboeuf --- arch/x86/entry/common.c | 6 +++--- arch/x86/entry/syscall_32.c | 21 +++++++++++++++++++-- arch/x86/entry/syscall_64.c | 19 +++++++++++++++++-- arch/x86/entry/syscall_x32.c | 10 +++++++--- arch/x86/include/asm/syscall.h | 10 ++++------ 5 files changed, 50 insertions(+), 16 deletions(-) diff --git a/arch/x86/entry/common.c b/arch/x86/entry/common.c index 6356060caaf3..cea0e2a23b42 100644 --- a/arch/x86/entry/common.c +++ b/arch/x86/entry/common.c @@ -49,7 +49,7 @@ static __always_inline bool do_syscall_x64(struct pt_regs *regs, int nr) if (likely(unr < NR_syscalls)) { unr = array_index_nospec(unr, NR_syscalls); - regs->ax = sys_call_table[unr](regs); + regs->ax = x64_sys_call(regs, unr); return true; } return false; @@ -66,7 +66,7 @@ static __always_inline bool do_syscall_x32(struct pt_regs *regs, int nr) if (IS_ENABLED(CONFIG_X86_X32_ABI) && likely(xnr < X32_NR_syscalls)) { xnr = array_index_nospec(xnr, X32_NR_syscalls); - regs->ax = x32_sys_call_table[xnr](regs); + regs->ax = x32_sys_call(regs, xnr); return true; } return false; @@ -162,7 +162,7 @@ static __always_inline void do_syscall_32_irqs_on(struct pt_regs *regs, int nr) if (likely(unr < IA32_NR_syscalls)) { unr = array_index_nospec(unr, IA32_NR_syscalls); - regs->ax = ia32_sys_call_table[unr](regs); + regs->ax = ia32_sys_call(regs, unr); } else if (nr != -1) { regs->ax = __ia32_sys_ni_syscall(regs); } diff --git a/arch/x86/entry/syscall_32.c b/arch/x86/entry/syscall_32.c index 8cfc9bc73e7f..c2235bae17ef 100644 --- a/arch/x86/entry/syscall_32.c +++ b/arch/x86/entry/syscall_32.c @@ -18,8 +18,25 @@ #include #undef __SYSCALL +/* + * The sys_call_table[] is no longer used for system calls, but + * kernel/trace/trace_syscalls.c still wants to know the system + * call address. + */ +#ifdef CONFIG_X86_32 #define __SYSCALL(nr, sym) __ia32_##sym, - -__visible const sys_call_ptr_t ia32_sys_call_table[] = { +const sys_call_ptr_t sys_call_table[] = { #include }; +#undef __SYSCALL +#endif + +#define __SYSCALL(nr, sym) case nr: return __ia32_##sym(regs); + +long ia32_sys_call(const struct pt_regs *regs, unsigned int nr) +{ + switch (nr) { + #include + default: return __ia32_sys_ni_syscall(regs); + } +}; diff --git a/arch/x86/entry/syscall_64.c b/arch/x86/entry/syscall_64.c index be120eec1fc9..33b3f09e6f15 100644 --- a/arch/x86/entry/syscall_64.c +++ b/arch/x86/entry/syscall_64.c @@ -11,8 +11,23 @@ #include #undef __SYSCALL +/* + * The sys_call_table[] is no longer used for system calls, but + * kernel/trace/trace_syscalls.c still wants to know the system + * call address. + */ #define __SYSCALL(nr, sym) __x64_##sym, - -asmlinkage const sys_call_ptr_t sys_call_table[] = { +const sys_call_ptr_t sys_call_table[] = { #include }; +#undef __SYSCALL + +#define __SYSCALL(nr, sym) case nr: return __x64_##sym(regs); + +long x64_sys_call(const struct pt_regs *regs, unsigned int nr) +{ + switch (nr) { + #include + default: return __x64_sys_ni_syscall(regs); + } +}; diff --git a/arch/x86/entry/syscall_x32.c b/arch/x86/entry/syscall_x32.c index bdd0e03a1265..03de4a932131 100644 --- a/arch/x86/entry/syscall_x32.c +++ b/arch/x86/entry/syscall_x32.c @@ -11,8 +11,12 @@ #include #undef __SYSCALL -#define __SYSCALL(nr, sym) __x64_##sym, +#define __SYSCALL(nr, sym) case nr: return __x64_##sym(regs); -asmlinkage const sys_call_ptr_t x32_sys_call_table[] = { -#include +long x32_sys_call(const struct pt_regs *regs, unsigned int nr) +{ + switch (nr) { + #include + default: return __x64_sys_ni_syscall(regs); + } }; diff --git a/arch/x86/include/asm/syscall.h b/arch/x86/include/asm/syscall.h index f44e2f9ab65d..3c28f26bfe22 100644 --- a/arch/x86/include/asm/syscall.h +++ b/arch/x86/include/asm/syscall.h @@ -16,19 +16,17 @@ #include /* for TS_COMPAT */ #include +/* This is used purely for kernel/trace/trace_syscalls.c */ typedef long (*sys_call_ptr_t)(const struct pt_regs *); extern const sys_call_ptr_t sys_call_table[]; -#if defined(CONFIG_X86_32) -#define ia32_sys_call_table sys_call_table -#else /* * These may not exist, but still put the prototypes in so we * can use IS_ENABLED(). */ -extern const sys_call_ptr_t ia32_sys_call_table[]; -extern const sys_call_ptr_t x32_sys_call_table[]; -#endif +extern long ia32_sys_call(const struct pt_regs *, unsigned int nr); +extern long x32_sys_call(const struct pt_regs *, unsigned int nr); +extern long x64_sys_call(const struct pt_regs *, unsigned int nr); /* * Only the low 32 bits of orig_ax are meaningful, so we return int. -- cgit v1.2.3 From 7390db8aea0d64e9deb28b8e1ce716f5020c7ee5 Mon Sep 17 00:00:00 2001 From: Pawan Gupta Date: Mon, 11 Mar 2024 08:56:58 -0700 Subject: x86/bhi: Add support for clearing branch history at syscall entry Branch History Injection (BHI) attacks may allow a malicious application to influence indirect branch prediction in kernel by poisoning the branch history. eIBRS isolates indirect branch targets in ring0. The BHB can still influence the choice of indirect branch predictor entry, and although branch predictor entries are isolated between modes when eIBRS is enabled, the BHB itself is not isolated between modes. Alder Lake and new processors supports a hardware control BHI_DIS_S to mitigate BHI. For older processors Intel has released a software sequence to clear the branch history on parts that don't support BHI_DIS_S. Add support to execute the software sequence at syscall entry and VMexit to overwrite the branch history. For now, branch history is not cleared at interrupt entry, as malicious applications are not believed to have sufficient control over the registers, since previous register state is cleared at interrupt entry. Researchers continue to poke at this area and it may become necessary to clear at interrupt entry as well in the future. This mitigation is only defined here. It is enabled later. Signed-off-by: Pawan Gupta Co-developed-by: Daniel Sneddon Signed-off-by: Daniel Sneddon Signed-off-by: Thomas Gleixner Reviewed-by: Alexandre Chartre Reviewed-by: Josh Poimboeuf --- arch/x86/entry/common.c | 4 +-- arch/x86/entry/entry_64.S | 61 ++++++++++++++++++++++++++++++++++++ arch/x86/entry/entry_64_compat.S | 16 ++++++++++ arch/x86/include/asm/cpufeatures.h | 3 +- arch/x86/include/asm/nospec-branch.h | 12 +++++++ arch/x86/include/asm/syscall.h | 1 + arch/x86/kvm/vmx/vmenter.S | 2 ++ 7 files changed, 96 insertions(+), 3 deletions(-) diff --git a/arch/x86/entry/common.c b/arch/x86/entry/common.c index cea0e2a23b42..6de50b80702e 100644 --- a/arch/x86/entry/common.c +++ b/arch/x86/entry/common.c @@ -189,7 +189,7 @@ static __always_inline bool int80_is_external(void) } /** - * int80_emulation - 32-bit legacy syscall entry + * do_int80_emulation - 32-bit legacy syscall C entry from asm * * This entry point can be used by 32-bit and 64-bit programs to perform * 32-bit system calls. Instances of INT $0x80 can be found inline in @@ -207,7 +207,7 @@ static __always_inline bool int80_is_external(void) * eax: system call number * ebx, ecx, edx, esi, edi, ebp: arg1 - arg 6 */ -DEFINE_IDTENTRY_RAW(int80_emulation) +__visible noinstr void do_int80_emulation(struct pt_regs *regs) { int nr; diff --git a/arch/x86/entry/entry_64.S b/arch/x86/entry/entry_64.S index 8af2a26b24f6..1b5be07f8669 100644 --- a/arch/x86/entry/entry_64.S +++ b/arch/x86/entry/entry_64.S @@ -116,6 +116,7 @@ SYM_INNER_LABEL(entry_SYSCALL_64_after_hwframe, SYM_L_GLOBAL) /* clobbers %rax, make sure it is after saving the syscall nr */ IBRS_ENTER UNTRAIN_RET + CLEAR_BRANCH_HISTORY call do_syscall_64 /* returns with IRQs disabled */ @@ -1491,3 +1492,63 @@ SYM_CODE_START_NOALIGN(rewind_stack_and_make_dead) call make_task_dead SYM_CODE_END(rewind_stack_and_make_dead) .popsection + +/* + * This sequence executes branches in order to remove user branch information + * from the branch history tracker in the Branch Predictor, therefore removing + * user influence on subsequent BTB lookups. + * + * It should be used on parts prior to Alder Lake. Newer parts should use the + * BHI_DIS_S hardware control instead. If a pre-Alder Lake part is being + * virtualized on newer hardware the VMM should protect against BHI attacks by + * setting BHI_DIS_S for the guests. + * + * CALLs/RETs are necessary to prevent Loop Stream Detector(LSD) from engaging + * and not clearing the branch history. The call tree looks like: + * + * call 1 + * call 2 + * call 2 + * call 2 + * call 2 + * call 2 + * ret + * ret + * ret + * ret + * ret + * ret + * + * This means that the stack is non-constant and ORC can't unwind it with %rsp + * alone. Therefore we unconditionally set up the frame pointer, which allows + * ORC to unwind properly. + * + * The alignment is for performance and not for safety, and may be safely + * refactored in the future if needed. + */ +SYM_FUNC_START(clear_bhb_loop) + push %rbp + mov %rsp, %rbp + movl $5, %ecx + ANNOTATE_INTRA_FUNCTION_CALL + call 1f + jmp 5f + .align 64, 0xcc + ANNOTATE_INTRA_FUNCTION_CALL +1: call 2f + RET + .align 64, 0xcc +2: movl $5, %eax +3: jmp 4f + nop +4: sub $1, %eax + jnz 3b + sub $1, %ecx + jnz 1b + RET +5: lfence + pop %rbp + RET +SYM_FUNC_END(clear_bhb_loop) +EXPORT_SYMBOL_GPL(clear_bhb_loop) +STACK_FRAME_NON_STANDARD(clear_bhb_loop) diff --git a/arch/x86/entry/entry_64_compat.S b/arch/x86/entry/entry_64_compat.S index eabf48c4d4b4..c779046cc3fe 100644 --- a/arch/x86/entry/entry_64_compat.S +++ b/arch/x86/entry/entry_64_compat.S @@ -92,6 +92,7 @@ SYM_INNER_LABEL(entry_SYSENTER_compat_after_hwframe, SYM_L_GLOBAL) IBRS_ENTER UNTRAIN_RET + CLEAR_BRANCH_HISTORY /* * SYSENTER doesn't filter flags, so we need to clear NT and AC @@ -206,6 +207,7 @@ SYM_INNER_LABEL(entry_SYSCALL_compat_after_hwframe, SYM_L_GLOBAL) IBRS_ENTER UNTRAIN_RET + CLEAR_BRANCH_HISTORY movq %rsp, %rdi call do_fast_syscall_32 @@ -276,3 +278,17 @@ SYM_INNER_LABEL(entry_SYSRETL_compat_end, SYM_L_GLOBAL) ANNOTATE_NOENDBR int3 SYM_CODE_END(entry_SYSCALL_compat) + +/* + * int 0x80 is used by 32 bit mode as a system call entry. Normally idt entries + * point to C routines, however since this is a system call interface the branch + * history needs to be scrubbed to protect against BHI attacks, and that + * scrubbing needs to take place in assembly code prior to entering any C + * routines. + */ +SYM_CODE_START(int80_emulation) + ANNOTATE_NOENDBR + UNWIND_HINT_FUNC + CLEAR_BRANCH_HISTORY + jmp do_int80_emulation +SYM_CODE_END(int80_emulation) diff --git a/arch/x86/include/asm/cpufeatures.h b/arch/x86/include/asm/cpufeatures.h index a38f8f9ba657..9b94a86f4600 100644 --- a/arch/x86/include/asm/cpufeatures.h +++ b/arch/x86/include/asm/cpufeatures.h @@ -461,11 +461,12 @@ /* * Extended auxiliary flags: Linux defined - for features scattered in various - * CPUID levels like 0x80000022, etc. + * CPUID levels like 0x80000022, etc and Linux defined features. * * Reuse free bits when adding new feature flags! */ #define X86_FEATURE_AMD_LBR_PMC_FREEZE (21*32+ 0) /* AMD LBR and PMC Freeze */ +#define X86_FEATURE_CLEAR_BHB_LOOP (21*32+ 1) /* "" Clear branch history at syscall entry using SW loop */ /* * BUG word(s) diff --git a/arch/x86/include/asm/nospec-branch.h b/arch/x86/include/asm/nospec-branch.h index 170c89ed22fc..aea40204278b 100644 --- a/arch/x86/include/asm/nospec-branch.h +++ b/arch/x86/include/asm/nospec-branch.h @@ -326,6 +326,14 @@ ALTERNATIVE "", __stringify(verw _ASM_RIP(mds_verw_sel)), X86_FEATURE_CLEAR_CPU_BUF .endm +#ifdef CONFIG_X86_64 +.macro CLEAR_BRANCH_HISTORY + ALTERNATIVE "", "call clear_bhb_loop", X86_FEATURE_CLEAR_BHB_LOOP +.endm +#else +#define CLEAR_BRANCH_HISTORY +#endif + #else /* __ASSEMBLY__ */ #define ANNOTATE_RETPOLINE_SAFE \ @@ -368,6 +376,10 @@ extern void srso_alias_return_thunk(void); extern void entry_untrain_ret(void); extern void entry_ibpb(void); +#ifdef CONFIG_X86_64 +extern void clear_bhb_loop(void); +#endif + extern void (*x86_return_thunk)(void); extern void __warn_thunk(void); diff --git a/arch/x86/include/asm/syscall.h b/arch/x86/include/asm/syscall.h index 3c28f26bfe22..2fc7bc3863ff 100644 --- a/arch/x86/include/asm/syscall.h +++ b/arch/x86/include/asm/syscall.h @@ -125,6 +125,7 @@ static inline int syscall_get_arch(struct task_struct *task) } bool do_syscall_64(struct pt_regs *regs, int nr); +void do_int80_emulation(struct pt_regs *regs); #endif /* CONFIG_X86_32 */ diff --git a/arch/x86/kvm/vmx/vmenter.S b/arch/x86/kvm/vmx/vmenter.S index 2bfbf758d061..0f3593e10c57 100644 --- a/arch/x86/kvm/vmx/vmenter.S +++ b/arch/x86/kvm/vmx/vmenter.S @@ -275,6 +275,8 @@ SYM_INNER_LABEL_ALIGN(vmx_vmexit, SYM_L_GLOBAL) call vmx_spec_ctrl_restore_host + CLEAR_BRANCH_HISTORY + /* Put return value in AX */ mov %_ASM_BX, %_ASM_AX -- cgit v1.2.3 From 0f4a837615ff925ba62648d280a861adf1582df7 Mon Sep 17 00:00:00 2001 From: Daniel Sneddon Date: Wed, 13 Mar 2024 09:47:57 -0700 Subject: x86/bhi: Define SPEC_CTRL_BHI_DIS_S Newer processors supports a hardware control BHI_DIS_S to mitigate Branch History Injection (BHI). Setting BHI_DIS_S protects the kernel from userspace BHI attacks without having to manually overwrite the branch history. Define MSR_SPEC_CTRL bit BHI_DIS_S and its enumeration CPUID.BHI_CTRL. Mitigation is enabled later. Signed-off-by: Daniel Sneddon Signed-off-by: Pawan Gupta Signed-off-by: Daniel Sneddon Signed-off-by: Thomas Gleixner Reviewed-by: Alexandre Chartre Reviewed-by: Josh Poimboeuf --- arch/x86/include/asm/cpufeatures.h | 1 + arch/x86/include/asm/msr-index.h | 5 ++++- arch/x86/kernel/cpu/scattered.c | 1 + arch/x86/kvm/reverse_cpuid.h | 3 ++- 4 files changed, 8 insertions(+), 2 deletions(-) diff --git a/arch/x86/include/asm/cpufeatures.h b/arch/x86/include/asm/cpufeatures.h index 9b94a86f4600..408509070429 100644 --- a/arch/x86/include/asm/cpufeatures.h +++ b/arch/x86/include/asm/cpufeatures.h @@ -467,6 +467,7 @@ */ #define X86_FEATURE_AMD_LBR_PMC_FREEZE (21*32+ 0) /* AMD LBR and PMC Freeze */ #define X86_FEATURE_CLEAR_BHB_LOOP (21*32+ 1) /* "" Clear branch history at syscall entry using SW loop */ +#define X86_FEATURE_BHI_CTRL (21*32+ 2) /* "" BHI_DIS_S HW control available */ /* * BUG word(s) diff --git a/arch/x86/include/asm/msr-index.h b/arch/x86/include/asm/msr-index.h index 05956bd8bacf..24615e826998 100644 --- a/arch/x86/include/asm/msr-index.h +++ b/arch/x86/include/asm/msr-index.h @@ -61,10 +61,13 @@ #define SPEC_CTRL_SSBD BIT(SPEC_CTRL_SSBD_SHIFT) /* Speculative Store Bypass Disable */ #define SPEC_CTRL_RRSBA_DIS_S_SHIFT 6 /* Disable RRSBA behavior */ #define SPEC_CTRL_RRSBA_DIS_S BIT(SPEC_CTRL_RRSBA_DIS_S_SHIFT) +#define SPEC_CTRL_BHI_DIS_S_SHIFT 10 /* Disable Branch History Injection behavior */ +#define SPEC_CTRL_BHI_DIS_S BIT(SPEC_CTRL_BHI_DIS_S_SHIFT) /* A mask for bits which the kernel toggles when controlling mitigations */ #define SPEC_CTRL_MITIGATIONS_MASK (SPEC_CTRL_IBRS | SPEC_CTRL_STIBP | SPEC_CTRL_SSBD \ - | SPEC_CTRL_RRSBA_DIS_S) + | SPEC_CTRL_RRSBA_DIS_S \ + | SPEC_CTRL_BHI_DIS_S) #define MSR_IA32_PRED_CMD 0x00000049 /* Prediction Command */ #define PRED_CMD_IBPB BIT(0) /* Indirect Branch Prediction Barrier */ diff --git a/arch/x86/kernel/cpu/scattered.c b/arch/x86/kernel/cpu/scattered.c index a515328d9d7d..af5aa2c754c2 100644 --- a/arch/x86/kernel/cpu/scattered.c +++ b/arch/x86/kernel/cpu/scattered.c @@ -28,6 +28,7 @@ static const struct cpuid_bit cpuid_bits[] = { { X86_FEATURE_EPB, CPUID_ECX, 3, 0x00000006, 0 }, { X86_FEATURE_INTEL_PPIN, CPUID_EBX, 0, 0x00000007, 1 }, { X86_FEATURE_RRSBA_CTRL, CPUID_EDX, 2, 0x00000007, 2 }, + { X86_FEATURE_BHI_CTRL, CPUID_EDX, 4, 0x00000007, 2 }, { X86_FEATURE_CQM_LLC, CPUID_EDX, 1, 0x0000000f, 0 }, { X86_FEATURE_CQM_OCCUP_LLC, CPUID_EDX, 0, 0x0000000f, 1 }, { X86_FEATURE_CQM_MBM_TOTAL, CPUID_EDX, 1, 0x0000000f, 1 }, diff --git a/arch/x86/kvm/reverse_cpuid.h b/arch/x86/kvm/reverse_cpuid.h index aadefcaa9561..da9880d74a0b 100644 --- a/arch/x86/kvm/reverse_cpuid.h +++ b/arch/x86/kvm/reverse_cpuid.h @@ -52,7 +52,7 @@ enum kvm_only_cpuid_leafs { #define X86_FEATURE_IPRED_CTRL KVM_X86_FEATURE(CPUID_7_2_EDX, 1) #define KVM_X86_FEATURE_RRSBA_CTRL KVM_X86_FEATURE(CPUID_7_2_EDX, 2) #define X86_FEATURE_DDPD_U KVM_X86_FEATURE(CPUID_7_2_EDX, 3) -#define X86_FEATURE_BHI_CTRL KVM_X86_FEATURE(CPUID_7_2_EDX, 4) +#define KVM_X86_FEATURE_BHI_CTRL KVM_X86_FEATURE(CPUID_7_2_EDX, 4) #define X86_FEATURE_MCDT_NO KVM_X86_FEATURE(CPUID_7_2_EDX, 5) /* CPUID level 0x80000007 (EDX). */ @@ -126,6 +126,7 @@ static __always_inline u32 __feature_translate(int x86_feature) KVM_X86_TRANSLATE_FEATURE(CONSTANT_TSC); KVM_X86_TRANSLATE_FEATURE(PERFMON_V2); KVM_X86_TRANSLATE_FEATURE(RRSBA_CTRL); + KVM_X86_TRANSLATE_FEATURE(BHI_CTRL); default: return x86_feature; } -- cgit v1.2.3 From be482ff9500999f56093738f9219bbabc729d163 Mon Sep 17 00:00:00 2001 From: Pawan Gupta Date: Mon, 11 Mar 2024 08:57:03 -0700 Subject: x86/bhi: Enumerate Branch History Injection (BHI) bug Mitigation for BHI is selected based on the bug enumeration. Add bits needed to enumerate BHI bug. Signed-off-by: Pawan Gupta Signed-off-by: Daniel Sneddon Signed-off-by: Thomas Gleixner Reviewed-by: Alexandre Chartre Reviewed-by: Josh Poimboeuf --- arch/x86/include/asm/cpufeatures.h | 1 + arch/x86/include/asm/msr-index.h | 4 ++++ arch/x86/kernel/cpu/common.c | 24 ++++++++++++++++-------- 3 files changed, 21 insertions(+), 8 deletions(-) diff --git a/arch/x86/include/asm/cpufeatures.h b/arch/x86/include/asm/cpufeatures.h index 408509070429..8edd7a28869a 100644 --- a/arch/x86/include/asm/cpufeatures.h +++ b/arch/x86/include/asm/cpufeatures.h @@ -517,4 +517,5 @@ #define X86_BUG_SRSO X86_BUG(1*32 + 0) /* AMD SRSO bug */ #define X86_BUG_DIV0 X86_BUG(1*32 + 1) /* AMD DIV0 speculation bug */ #define X86_BUG_RFDS X86_BUG(1*32 + 2) /* CPU is vulnerable to Register File Data Sampling */ +#define X86_BUG_BHI X86_BUG(1*32 + 3) /* CPU is affected by Branch History Injection */ #endif /* _ASM_X86_CPUFEATURES_H */ diff --git a/arch/x86/include/asm/msr-index.h b/arch/x86/include/asm/msr-index.h index 24615e826998..e72c2b872957 100644 --- a/arch/x86/include/asm/msr-index.h +++ b/arch/x86/include/asm/msr-index.h @@ -166,6 +166,10 @@ * are restricted to targets in * kernel. */ +#define ARCH_CAP_BHI_NO BIT(20) /* + * CPU is not affected by Branch + * History Injection. + */ #define ARCH_CAP_PBRSB_NO BIT(24) /* * Not susceptible to Post-Barrier * Return Stack Buffer Predictions. diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c index 5c1e6d6be267..754d91857d63 100644 --- a/arch/x86/kernel/cpu/common.c +++ b/arch/x86/kernel/cpu/common.c @@ -1120,6 +1120,7 @@ static void identify_cpu_without_cpuid(struct cpuinfo_x86 *c) #define NO_SPECTRE_V2 BIT(8) #define NO_MMIO BIT(9) #define NO_EIBRS_PBRSB BIT(10) +#define NO_BHI BIT(11) #define VULNWL(vendor, family, model, whitelist) \ X86_MATCH_VENDOR_FAM_MODEL(vendor, family, model, whitelist) @@ -1182,18 +1183,18 @@ static const __initconst struct x86_cpu_id cpu_vuln_whitelist[] = { VULNWL_INTEL(ATOM_TREMONT_D, NO_ITLB_MULTIHIT | NO_EIBRS_PBRSB), /* AMD Family 0xf - 0x12 */ - VULNWL_AMD(0x0f, NO_MELTDOWN | NO_SSB | NO_L1TF | NO_MDS | NO_SWAPGS | NO_ITLB_MULTIHIT | NO_MMIO), - VULNWL_AMD(0x10, NO_MELTDOWN | NO_SSB | NO_L1TF | NO_MDS | NO_SWAPGS | NO_ITLB_MULTIHIT | NO_MMIO), - VULNWL_AMD(0x11, NO_MELTDOWN | NO_SSB | NO_L1TF | NO_MDS | NO_SWAPGS | NO_ITLB_MULTIHIT | NO_MMIO), - VULNWL_AMD(0x12, NO_MELTDOWN | NO_SSB | NO_L1TF | NO_MDS | NO_SWAPGS | NO_ITLB_MULTIHIT | NO_MMIO), + VULNWL_AMD(0x0f, NO_MELTDOWN | NO_SSB | NO_L1TF | NO_MDS | NO_SWAPGS | NO_ITLB_MULTIHIT | NO_MMIO | NO_BHI), + VULNWL_AMD(0x10, NO_MELTDOWN | NO_SSB | NO_L1TF | NO_MDS | NO_SWAPGS | NO_ITLB_MULTIHIT | NO_MMIO | NO_BHI), + VULNWL_AMD(0x11, NO_MELTDOWN | NO_SSB | NO_L1TF | NO_MDS | NO_SWAPGS | NO_ITLB_MULTIHIT | NO_MMIO | NO_BHI), + VULNWL_AMD(0x12, NO_MELTDOWN | NO_SSB | NO_L1TF | NO_MDS | NO_SWAPGS | NO_ITLB_MULTIHIT | NO_MMIO | NO_BHI), /* FAMILY_ANY must be last, otherwise 0x0f - 0x12 matches won't work */ - VULNWL_AMD(X86_FAMILY_ANY, NO_MELTDOWN | NO_L1TF | NO_MDS | NO_SWAPGS | NO_ITLB_MULTIHIT | NO_MMIO | NO_EIBRS_PBRSB), - VULNWL_HYGON(X86_FAMILY_ANY, NO_MELTDOWN | NO_L1TF | NO_MDS | NO_SWAPGS | NO_ITLB_MULTIHIT | NO_MMIO | NO_EIBRS_PBRSB), + VULNWL_AMD(X86_FAMILY_ANY, NO_MELTDOWN | NO_L1TF | NO_MDS | NO_SWAPGS | NO_ITLB_MULTIHIT | NO_MMIO | NO_EIBRS_PBRSB | NO_BHI), + VULNWL_HYGON(X86_FAMILY_ANY, NO_MELTDOWN | NO_L1TF | NO_MDS | NO_SWAPGS | NO_ITLB_MULTIHIT | NO_MMIO | NO_EIBRS_PBRSB | NO_BHI), /* Zhaoxin Family 7 */ - VULNWL(CENTAUR, 7, X86_MODEL_ANY, NO_SPECTRE_V2 | NO_SWAPGS | NO_MMIO), - VULNWL(ZHAOXIN, 7, X86_MODEL_ANY, NO_SPECTRE_V2 | NO_SWAPGS | NO_MMIO), + VULNWL(CENTAUR, 7, X86_MODEL_ANY, NO_SPECTRE_V2 | NO_SWAPGS | NO_MMIO | NO_BHI), + VULNWL(ZHAOXIN, 7, X86_MODEL_ANY, NO_SPECTRE_V2 | NO_SWAPGS | NO_MMIO | NO_BHI), {} }; @@ -1435,6 +1436,13 @@ static void __init cpu_set_bug_bits(struct cpuinfo_x86 *c) if (vulnerable_to_rfds(ia32_cap)) setup_force_cpu_bug(X86_BUG_RFDS); + /* When virtualized, eIBRS could be hidden, assume vulnerable */ + if (!(ia32_cap & ARCH_CAP_BHI_NO) && + !cpu_matches(cpu_vuln_whitelist, NO_BHI) && + (boot_cpu_has(X86_FEATURE_IBRS_ENHANCED) || + boot_cpu_has(X86_FEATURE_HYPERVISOR))) + setup_force_cpu_bug(X86_BUG_BHI); + if (cpu_matches(cpu_vuln_whitelist, NO_MELTDOWN)) return; -- cgit v1.2.3 From ec9404e40e8f36421a2b66ecb76dc2209fe7f3ef Mon Sep 17 00:00:00 2001 From: Pawan Gupta Date: Mon, 11 Mar 2024 08:57:05 -0700 Subject: x86/bhi: Add BHI mitigation knob Branch history clearing software sequences and hardware control BHI_DIS_S were defined to mitigate Branch History Injection (BHI). Add cmdline spectre_bhi={on|off|auto} to control BHI mitigation: auto - Deploy the hardware mitigation BHI_DIS_S, if available. on - Deploy the hardware mitigation BHI_DIS_S, if available, otherwise deploy the software sequence at syscall entry and VMexit. off - Turn off BHI mitigation. The default is auto mode which does not deploy the software sequence mitigation. This is because of the hardening done in the syscall dispatch path, which is the likely target of BHI. Signed-off-by: Pawan Gupta Signed-off-by: Daniel Sneddon Signed-off-by: Thomas Gleixner Reviewed-by: Alexandre Chartre Reviewed-by: Josh Poimboeuf --- Documentation/admin-guide/hw-vuln/spectre.rst | 45 +++++++++++-- Documentation/admin-guide/kernel-parameters.txt | 11 +++ arch/x86/Kconfig | 25 +++++++ arch/x86/include/asm/cpufeatures.h | 1 + arch/x86/kernel/cpu/bugs.c | 90 ++++++++++++++++++++++++- 5 files changed, 165 insertions(+), 7 deletions(-) diff --git a/Documentation/admin-guide/hw-vuln/spectre.rst b/Documentation/admin-guide/hw-vuln/spectre.rst index cce768afec6b..7cb99b09827c 100644 --- a/Documentation/admin-guide/hw-vuln/spectre.rst +++ b/Documentation/admin-guide/hw-vuln/spectre.rst @@ -138,11 +138,10 @@ associated with the source address of the indirect branch. Specifically, the BHB might be shared across privilege levels even in the presence of Enhanced IBRS. -Currently the only known real-world BHB attack vector is via -unprivileged eBPF. Therefore, it's highly recommended to not enable -unprivileged eBPF, especially when eIBRS is used (without retpolines). -For a full mitigation against BHB attacks, it's recommended to use -retpolines (or eIBRS combined with retpolines). +Previously the only known real-world BHB attack vector was via unprivileged +eBPF. Further research has found attacks that don't require unprivileged eBPF. +For a full mitigation against BHB attacks it is recommended to set BHI_DIS_S or +use the BHB clearing sequence. Attack scenarios ---------------- @@ -430,6 +429,21 @@ The possible values in this file are: 'PBRSB-eIBRS: Not affected' CPU is not affected by PBRSB =========================== ======================================================= + - Branch History Injection (BHI) protection status: + +.. list-table:: + + * - BHI: Not affected + - System is not affected + * - BHI: Retpoline + - System is protected by retpoline + * - BHI: BHI_DIS_S + - System is protected by BHI_DIS_S + * - BHI: SW loop + - System is protected by software clearing sequence + * - BHI: Syscall hardening + - Syscalls are hardened against BHI + Full mitigation might require a microcode update from the CPU vendor. When the necessary microcode is not available, the kernel will report vulnerability. @@ -484,7 +498,11 @@ Spectre variant 2 Systems which support enhanced IBRS (eIBRS) enable IBRS protection once at boot, by setting the IBRS bit, and they're automatically protected against - Spectre v2 variant attacks. + some Spectre v2 variant attacks. The BHB can still influence the choice of + indirect branch predictor entry, and although branch predictor entries are + isolated between modes when eIBRS is enabled, the BHB itself is not isolated + between modes. Systems which support BHI_DIS_S will set it to protect against + BHI attacks. On Intel's enhanced IBRS systems, this includes cross-thread branch target injections on SMT systems (STIBP). In other words, Intel eIBRS enables @@ -638,6 +656,21 @@ kernel command line. spectre_v2=off. Spectre variant 1 mitigations cannot be disabled. + spectre_bhi= + + [X86] Control mitigation of Branch History Injection + (BHI) vulnerability. Syscalls are hardened against BHI + regardless of this setting. This setting affects the deployment + of the HW BHI control and the SW BHB clearing sequence. + + on + unconditionally enable. + off + unconditionally disable. + auto + enable if hardware mitigation + control(BHI_DIS_S) is available. + For spectre_v2_user see Documentation/admin-guide/kernel-parameters.txt Mitigation selection guide diff --git a/Documentation/admin-guide/kernel-parameters.txt b/Documentation/admin-guide/kernel-parameters.txt index bb884c14b2f6..2dbe60c1db22 100644 --- a/Documentation/admin-guide/kernel-parameters.txt +++ b/Documentation/admin-guide/kernel-parameters.txt @@ -6063,6 +6063,17 @@ sonypi.*= [HW] Sony Programmable I/O Control Device driver See Documentation/admin-guide/laptops/sonypi.rst + spectre_bhi= [X86] Control mitigation of Branch History Injection + (BHI) vulnerability. Syscalls are hardened against BHI + reglardless of this setting. This setting affects the + deployment of the HW BHI control and the SW BHB + clearing sequence. + + on - unconditionally enable. + off - unconditionally disable. + auto - (default) enable only if hardware mitigation + control(BHI_DIS_S) is available. + spectre_v2= [X86,EARLY] Control mitigation of Spectre variant 2 (indirect branch speculation) vulnerability. The default operation protects the kernel from diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index 4fff6ed46e90..29a7b69a1316 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig @@ -2633,6 +2633,31 @@ config MITIGATION_RFDS stored in floating point, vector and integer registers. See also +choice + prompt "Clear branch history" + depends on CPU_SUP_INTEL + default SPECTRE_BHI_AUTO + help + Enable BHI mitigations. BHI attacks are a form of Spectre V2 attacks + where the branch history buffer is poisoned to speculatively steer + indirect branches. + See + +config SPECTRE_BHI_ON + bool "on" + help + Equivalent to setting spectre_bhi=on command line parameter. +config SPECTRE_BHI_OFF + bool "off" + help + Equivalent to setting spectre_bhi=off command line parameter. +config SPECTRE_BHI_AUTO + bool "auto" + help + Equivalent to setting spectre_bhi=auto command line parameter. + +endchoice + endif config ARCH_HAS_ADD_PAGES diff --git a/arch/x86/include/asm/cpufeatures.h b/arch/x86/include/asm/cpufeatures.h index 8edd7a28869a..a2ee9a00e4a7 100644 --- a/arch/x86/include/asm/cpufeatures.h +++ b/arch/x86/include/asm/cpufeatures.h @@ -468,6 +468,7 @@ #define X86_FEATURE_AMD_LBR_PMC_FREEZE (21*32+ 0) /* AMD LBR and PMC Freeze */ #define X86_FEATURE_CLEAR_BHB_LOOP (21*32+ 1) /* "" Clear branch history at syscall entry using SW loop */ #define X86_FEATURE_BHI_CTRL (21*32+ 2) /* "" BHI_DIS_S HW control available */ +#define X86_FEATURE_CLEAR_BHB_HW (21*32+ 3) /* "" BHI_DIS_S HW control enabled */ /* * BUG word(s) diff --git a/arch/x86/kernel/cpu/bugs.c b/arch/x86/kernel/cpu/bugs.c index e8c7146f9ed7..1ab275029888 100644 --- a/arch/x86/kernel/cpu/bugs.c +++ b/arch/x86/kernel/cpu/bugs.c @@ -1607,6 +1607,74 @@ static void __init spectre_v2_determine_rsb_fill_type_at_vmexit(enum spectre_v2_ dump_stack(); } +/* + * Set BHI_DIS_S to prevent indirect branches in kernel to be influenced by + * branch history in userspace. Not needed if BHI_NO is set. + */ +static bool __init spec_ctrl_bhi_dis(void) +{ + if (!boot_cpu_has(X86_FEATURE_BHI_CTRL)) + return false; + + x86_spec_ctrl_base |= SPEC_CTRL_BHI_DIS_S; + update_spec_ctrl(x86_spec_ctrl_base); + setup_force_cpu_cap(X86_FEATURE_CLEAR_BHB_HW); + + return true; +} + +enum bhi_mitigations { + BHI_MITIGATION_OFF, + BHI_MITIGATION_ON, + BHI_MITIGATION_AUTO, +}; + +static enum bhi_mitigations bhi_mitigation __ro_after_init = + IS_ENABLED(CONFIG_SPECTRE_BHI_ON) ? BHI_MITIGATION_ON : + IS_ENABLED(CONFIG_SPECTRE_BHI_OFF) ? BHI_MITIGATION_OFF : + BHI_MITIGATION_AUTO; + +static int __init spectre_bhi_parse_cmdline(char *str) +{ + if (!str) + return -EINVAL; + + if (!strcmp(str, "off")) + bhi_mitigation = BHI_MITIGATION_OFF; + else if (!strcmp(str, "on")) + bhi_mitigation = BHI_MITIGATION_ON; + else if (!strcmp(str, "auto")) + bhi_mitigation = BHI_MITIGATION_AUTO; + else + pr_err("Ignoring unknown spectre_bhi option (%s)", str); + + return 0; +} +early_param("spectre_bhi", spectre_bhi_parse_cmdline); + +static void __init bhi_select_mitigation(void) +{ + if (bhi_mitigation == BHI_MITIGATION_OFF) + return; + + /* Retpoline mitigates against BHI unless the CPU has RRSBA behavior */ + if (cpu_feature_enabled(X86_FEATURE_RETPOLINE) && + !(x86_read_arch_cap_msr() & ARCH_CAP_RRSBA)) + return; + + if (spec_ctrl_bhi_dis()) + return; + + if (!IS_ENABLED(CONFIG_X86_64)) + return; + + if (bhi_mitigation == BHI_MITIGATION_AUTO) + return; + + setup_force_cpu_cap(X86_FEATURE_CLEAR_BHB_LOOP); + pr_info("Spectre BHI mitigation: SW BHB clearing on syscall\n"); +} + static void __init spectre_v2_select_mitigation(void) { enum spectre_v2_mitigation_cmd cmd = spectre_v2_parse_cmdline(); @@ -1718,6 +1786,9 @@ static void __init spectre_v2_select_mitigation(void) mode == SPECTRE_V2_RETPOLINE) spec_ctrl_disable_kernel_rrsba(); + if (boot_cpu_has(X86_BUG_BHI)) + bhi_select_mitigation(); + spectre_v2_enabled = mode; pr_info("%s\n", spectre_v2_strings[mode]); @@ -2733,6 +2804,21 @@ static char *pbrsb_eibrs_state(void) } } +static const char * const spectre_bhi_state(void) +{ + if (!boot_cpu_has_bug(X86_BUG_BHI)) + return "; BHI: Not affected"; + else if (boot_cpu_has(X86_FEATURE_CLEAR_BHB_HW)) + return "; BHI: BHI_DIS_S"; + else if (boot_cpu_has(X86_FEATURE_CLEAR_BHB_LOOP)) + return "; BHI: SW loop"; + else if (boot_cpu_has(X86_FEATURE_RETPOLINE) && + !(x86_read_arch_cap_msr() & ARCH_CAP_RRSBA)) + return "; BHI: Retpoline"; + + return "; BHI: Vulnerable (Syscall hardening enabled)"; +} + static ssize_t spectre_v2_show_state(char *buf) { if (spectre_v2_enabled == SPECTRE_V2_LFENCE) @@ -2745,13 +2831,15 @@ static ssize_t spectre_v2_show_state(char *buf) spectre_v2_enabled == SPECTRE_V2_EIBRS_LFENCE) return sysfs_emit(buf, "Vulnerable: eIBRS+LFENCE with unprivileged eBPF and SMT\n"); - return sysfs_emit(buf, "%s%s%s%s%s%s%s\n", + return sysfs_emit(buf, "%s%s%s%s%s%s%s%s\n", spectre_v2_strings[spectre_v2_enabled], ibpb_state(), boot_cpu_has(X86_FEATURE_USE_IBRS_FW) ? "; IBRS_FW" : "", stibp_state(), boot_cpu_has(X86_FEATURE_RSB_CTXSW) ? "; RSB filling" : "", pbrsb_eibrs_state(), + spectre_bhi_state(), + /* this should always be at the end */ spectre_v2_module_string()); } -- cgit v1.2.3 From 95a6ccbdc7199a14b71ad8901cb788ba7fb5167b Mon Sep 17 00:00:00 2001 From: Pawan Gupta Date: Mon, 11 Mar 2024 08:57:09 -0700 Subject: x86/bhi: Mitigate KVM by default BHI mitigation mode spectre_bhi=auto does not deploy the software mitigation by default. In a cloud environment, it is a likely scenario where userspace is trusted but the guests are not trusted. Deploying system wide mitigation in such cases is not desirable. Update the auto mode to unconditionally mitigate against malicious guests. Deploy the software sequence at VMexit in auto mode also, when hardware mitigation is not available. Unlike the force =on mode, software sequence is not deployed at syscalls in auto mode. Suggested-by: Alexandre Chartre Signed-off-by: Pawan Gupta Signed-off-by: Daniel Sneddon Signed-off-by: Thomas Gleixner Reviewed-by: Alexandre Chartre Reviewed-by: Josh Poimboeuf --- Documentation/admin-guide/hw-vuln/spectre.rst | 7 +++++-- Documentation/admin-guide/kernel-parameters.txt | 5 +++-- arch/x86/include/asm/cpufeatures.h | 1 + arch/x86/include/asm/nospec-branch.h | 5 +++++ arch/x86/kernel/cpu/bugs.c | 9 ++++++++- arch/x86/kvm/vmx/vmenter.S | 2 +- 6 files changed, 23 insertions(+), 6 deletions(-) diff --git a/Documentation/admin-guide/hw-vuln/spectre.rst b/Documentation/admin-guide/hw-vuln/spectre.rst index 7cb99b09827c..b70b1d8bd8e6 100644 --- a/Documentation/admin-guide/hw-vuln/spectre.rst +++ b/Documentation/admin-guide/hw-vuln/spectre.rst @@ -439,10 +439,12 @@ The possible values in this file are: - System is protected by retpoline * - BHI: BHI_DIS_S - System is protected by BHI_DIS_S - * - BHI: SW loop + * - BHI: SW loop; KVM SW loop - System is protected by software clearing sequence * - BHI: Syscall hardening - Syscalls are hardened against BHI + * - BHI: Syscall hardening; KVM: SW loop + - System is protected from userspace attacks by syscall hardening; KVM is protected by software clearing sequence Full mitigation might require a microcode update from the CPU vendor. When the necessary microcode is not available, the kernel will @@ -669,7 +671,8 @@ kernel command line. unconditionally disable. auto enable if hardware mitigation - control(BHI_DIS_S) is available. + control(BHI_DIS_S) is available, otherwise + enable alternate mitigation in KVM. For spectre_v2_user see Documentation/admin-guide/kernel-parameters.txt diff --git a/Documentation/admin-guide/kernel-parameters.txt b/Documentation/admin-guide/kernel-parameters.txt index 2dbe60c1db22..4fa46302f436 100644 --- a/Documentation/admin-guide/kernel-parameters.txt +++ b/Documentation/admin-guide/kernel-parameters.txt @@ -6071,8 +6071,9 @@ on - unconditionally enable. off - unconditionally disable. - auto - (default) enable only if hardware mitigation - control(BHI_DIS_S) is available. + auto - (default) enable hardware mitigation + (BHI_DIS_S) if available, otherwise enable + alternate mitigation in KVM. spectre_v2= [X86,EARLY] Control mitigation of Spectre variant 2 (indirect branch speculation) vulnerability. diff --git a/arch/x86/include/asm/cpufeatures.h b/arch/x86/include/asm/cpufeatures.h index a2ee9a00e4a7..3c7434329661 100644 --- a/arch/x86/include/asm/cpufeatures.h +++ b/arch/x86/include/asm/cpufeatures.h @@ -469,6 +469,7 @@ #define X86_FEATURE_CLEAR_BHB_LOOP (21*32+ 1) /* "" Clear branch history at syscall entry using SW loop */ #define X86_FEATURE_BHI_CTRL (21*32+ 2) /* "" BHI_DIS_S HW control available */ #define X86_FEATURE_CLEAR_BHB_HW (21*32+ 3) /* "" BHI_DIS_S HW control enabled */ +#define X86_FEATURE_CLEAR_BHB_LOOP_ON_VMEXIT (21*32+ 4) /* "" Clear branch history at vmexit using SW loop */ /* * BUG word(s) diff --git a/arch/x86/include/asm/nospec-branch.h b/arch/x86/include/asm/nospec-branch.h index aea40204278b..ff5f1ecc7d1e 100644 --- a/arch/x86/include/asm/nospec-branch.h +++ b/arch/x86/include/asm/nospec-branch.h @@ -330,8 +330,13 @@ .macro CLEAR_BRANCH_HISTORY ALTERNATIVE "", "call clear_bhb_loop", X86_FEATURE_CLEAR_BHB_LOOP .endm + +.macro CLEAR_BRANCH_HISTORY_VMEXIT + ALTERNATIVE "", "call clear_bhb_loop", X86_FEATURE_CLEAR_BHB_LOOP_ON_VMEXIT +.endm #else #define CLEAR_BRANCH_HISTORY +#define CLEAR_BRANCH_HISTORY_VMEXIT #endif #else /* __ASSEMBLY__ */ diff --git a/arch/x86/kernel/cpu/bugs.c b/arch/x86/kernel/cpu/bugs.c index 1ab275029888..295463707e68 100644 --- a/arch/x86/kernel/cpu/bugs.c +++ b/arch/x86/kernel/cpu/bugs.c @@ -1668,9 +1668,14 @@ static void __init bhi_select_mitigation(void) if (!IS_ENABLED(CONFIG_X86_64)) return; + /* Mitigate KVM by default */ + setup_force_cpu_cap(X86_FEATURE_CLEAR_BHB_LOOP_ON_VMEXIT); + pr_info("Spectre BHI mitigation: SW BHB clearing on vm exit\n"); + if (bhi_mitigation == BHI_MITIGATION_AUTO) return; + /* Mitigate syscalls when the mitigation is forced =on */ setup_force_cpu_cap(X86_FEATURE_CLEAR_BHB_LOOP); pr_info("Spectre BHI mitigation: SW BHB clearing on syscall\n"); } @@ -2811,10 +2816,12 @@ static const char * const spectre_bhi_state(void) else if (boot_cpu_has(X86_FEATURE_CLEAR_BHB_HW)) return "; BHI: BHI_DIS_S"; else if (boot_cpu_has(X86_FEATURE_CLEAR_BHB_LOOP)) - return "; BHI: SW loop"; + return "; BHI: SW loop, KVM: SW loop"; else if (boot_cpu_has(X86_FEATURE_RETPOLINE) && !(x86_read_arch_cap_msr() & ARCH_CAP_RRSBA)) return "; BHI: Retpoline"; + else if (boot_cpu_has(X86_FEATURE_CLEAR_BHB_LOOP_ON_VMEXIT)) + return "; BHI: Syscall hardening, KVM: SW loop"; return "; BHI: Vulnerable (Syscall hardening enabled)"; } diff --git a/arch/x86/kvm/vmx/vmenter.S b/arch/x86/kvm/vmx/vmenter.S index 0f3593e10c57..f6986dee6f8c 100644 --- a/arch/x86/kvm/vmx/vmenter.S +++ b/arch/x86/kvm/vmx/vmenter.S @@ -275,7 +275,7 @@ SYM_INNER_LABEL_ALIGN(vmx_vmexit, SYM_L_GLOBAL) call vmx_spec_ctrl_restore_host - CLEAR_BRANCH_HISTORY + CLEAR_BRANCH_HISTORY_VMEXIT /* Put return value in AX */ mov %_ASM_BX, %_ASM_AX -- cgit v1.2.3 From ed2e8d49b54d677f3123668a21a57822d679651f Mon Sep 17 00:00:00 2001 From: Daniel Sneddon Date: Wed, 13 Mar 2024 09:49:17 -0700 Subject: KVM: x86: Add BHI_NO Intel processors that aren't vulnerable to BHI will set MSR_IA32_ARCH_CAPABILITIES[BHI_NO] = 1;. Guests may use this BHI_NO bit to determine if they need to implement BHI mitigations or not. Allow this bit to be passed to the guests. Signed-off-by: Daniel Sneddon Signed-off-by: Pawan Gupta Signed-off-by: Daniel Sneddon Signed-off-by: Thomas Gleixner Reviewed-by: Alexandre Chartre Reviewed-by: Josh Poimboeuf --- arch/x86/kvm/x86.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c index 47d9f03b7778..984ea2089efc 100644 --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c @@ -1621,7 +1621,7 @@ static bool kvm_is_immutable_feature_msr(u32 msr) ARCH_CAP_PSCHANGE_MC_NO | ARCH_CAP_TSX_CTRL_MSR | ARCH_CAP_TAA_NO | \ ARCH_CAP_SBDR_SSDP_NO | ARCH_CAP_FBSDP_NO | ARCH_CAP_PSDP_NO | \ ARCH_CAP_FB_CLEAR | ARCH_CAP_RRSBA | ARCH_CAP_PBRSB_NO | ARCH_CAP_GDS_NO | \ - ARCH_CAP_RFDS_NO | ARCH_CAP_RFDS_CLEAR) + ARCH_CAP_RFDS_NO | ARCH_CAP_RFDS_CLEAR | ARCH_CAP_BHI_NO) static u64 kvm_get_arch_capabilities(void) { -- cgit v1.2.3 From 9cb83ed19b35e6c596b4e6644708ac4e011f32ab Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Mon, 8 Apr 2024 10:35:59 +0300 Subject: ASoC: Intel: sof_rt5682: Fix uninitialized variable in probe Initialize "is_legacy_cpu" to false to prevent an uninitialized variable bug. Fixes: 8efcd4864652 ("ASoC: Intel: sof_rt5682: use common module for sof_card_private initialization") Signed-off-by: Dan Carpenter Acked-by: Pierre-Louis Bossart Link: https://msgid.link/r/6e16433f-1897-46a2-b3ee-e177e7d846b8@moroto.mountain Signed-off-by: Mark Brown --- sound/soc/intel/boards/sof_rt5682.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/intel/boards/sof_rt5682.c b/sound/soc/intel/boards/sof_rt5682.c index aadd341a202c..966bcd3e8bdc 100644 --- a/sound/soc/intel/boards/sof_rt5682.c +++ b/sound/soc/intel/boards/sof_rt5682.c @@ -606,7 +606,7 @@ static int sof_audio_probe(struct platform_device *pdev) { struct snd_soc_acpi_mach *mach = pdev->dev.platform_data; struct sof_card_private *ctx; - bool is_legacy_cpu; + bool is_legacy_cpu = false; int ret; if (pdev->id_entry && pdev->id_entry->driver_data) -- cgit v1.2.3 From 7c1c73bf84c50b641449f9811e2196cdc3ca4a1b Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Tue, 26 Mar 2024 21:38:58 +0100 Subject: wifi: mac80211: check EHT/TTLM action frame length Check the EHT action frame length before accessing the action code, if it's not present then the frame cannot be valid. Reported-by: syzbot+75af45a00cf13243ba39@syzkaller.appspotmail.com Closes: https://lore.kernel.org/r/0000000000006c06870614886611@google.com/ Fixes: 8f500fbc6c65 ("wifi: mac80211: process and save negotiated TID to Link mapping request") Link: https://msgid.link/20240326213858.19c84f34349f.I71b439f016b28f65284bb7646fe36343b74cbc9a@changeid Signed-off-by: Johannes Berg --- net/mac80211/rx.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index c1f850138405..685185dc04f9 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c @@ -3780,6 +3780,10 @@ ieee80211_rx_h_action(struct ieee80211_rx_data *rx) } break; case WLAN_CATEGORY_PROTECTED_EHT: + if (len < offsetofend(typeof(*mgmt), + u.action.u.ttlm_req.action_code)) + break; + switch (mgmt->u.action.u.ttlm_req.action_code) { case WLAN_PROTECTED_EHT_ACTION_TTLM_REQ: if (sdata->vif.type != NL80211_IFTYPE_STATION) -- cgit v1.2.3 From ab9177d83c040eba58387914077ebca56f14fae6 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Tue, 26 Mar 2024 22:08:54 +0100 Subject: wifi: mac80211: don't use rate mask for scanning The rate mask is intended for use during operation, and can be set to only have masks for the currently active band. As such, it cannot be used for scanning which can be on other bands as well. Simply ignore the rate masks during scanning to avoid warnings from incorrect settings. Reported-by: syzbot+fdc5123366fb9c3fdc6d@syzkaller.appspotmail.com Closes: https://syzkaller.appspot.com/bug?extid=fdc5123366fb9c3fdc6d Co-developed-by: Dmitry Antipov Signed-off-by: Dmitry Antipov Tested-by: Dmitry Antipov Link: https://msgid.link/20240326220854.9594cbb418ca.I7f86c0ba1f98cf7e27c2bacf6c2d417200ecea5c@changeid Signed-off-by: Johannes Berg --- include/net/mac80211.h | 3 +++ net/mac80211/rate.c | 6 +++++- net/mac80211/scan.c | 1 + net/mac80211/tx.c | 13 +++++++++---- 4 files changed, 18 insertions(+), 5 deletions(-) diff --git a/include/net/mac80211.h b/include/net/mac80211.h index 353488ab94a2..2d7f87bc5324 100644 --- a/include/net/mac80211.h +++ b/include/net/mac80211.h @@ -953,6 +953,8 @@ enum mac80211_tx_info_flags { * of their QoS TID or other priority field values. * @IEEE80211_TX_CTRL_MCAST_MLO_FIRST_TX: first MLO TX, used mostly internally * for sequence number assignment + * @IEEE80211_TX_CTRL_SCAN_TX: Indicates that this frame is transmitted + * due to scanning, not in normal operation on the interface. * @IEEE80211_TX_CTRL_MLO_LINK: If not @IEEE80211_LINK_UNSPECIFIED, this * frame should be transmitted on the specific link. This really is * only relevant for frames that do not have data present, and is @@ -973,6 +975,7 @@ enum mac80211_tx_control_flags { IEEE80211_TX_CTRL_NO_SEQNO = BIT(7), IEEE80211_TX_CTRL_DONT_REORDER = BIT(8), IEEE80211_TX_CTRL_MCAST_MLO_FIRST_TX = BIT(9), + IEEE80211_TX_CTRL_SCAN_TX = BIT(10), IEEE80211_TX_CTRL_MLO_LINK = 0xf0000000, }; diff --git a/net/mac80211/rate.c b/net/mac80211/rate.c index 23404b275457..4dc1def69548 100644 --- a/net/mac80211/rate.c +++ b/net/mac80211/rate.c @@ -877,6 +877,7 @@ void ieee80211_get_tx_rates(struct ieee80211_vif *vif, struct ieee80211_sub_if_data *sdata; struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); struct ieee80211_supported_band *sband; + u32 mask = ~0; rate_control_fill_sta_table(sta, info, dest, max_rates); @@ -889,9 +890,12 @@ void ieee80211_get_tx_rates(struct ieee80211_vif *vif, if (ieee80211_is_tx_data(skb)) rate_control_apply_mask(sdata, sta, sband, dest, max_rates); + if (!(info->control.flags & IEEE80211_TX_CTRL_SCAN_TX)) + mask = sdata->rc_rateidx_mask[info->band]; + if (dest[0].idx < 0) __rate_control_send_low(&sdata->local->hw, sband, sta, info, - sdata->rc_rateidx_mask[info->band]); + mask); if (sta) rate_fixup_ratelist(vif, sband, info, dest, max_rates); diff --git a/net/mac80211/scan.c b/net/mac80211/scan.c index 0429e59ba387..73850312580f 100644 --- a/net/mac80211/scan.c +++ b/net/mac80211/scan.c @@ -648,6 +648,7 @@ static void ieee80211_send_scan_probe_req(struct ieee80211_sub_if_data *sdata, cpu_to_le16(IEEE80211_SN_TO_SEQ(sn)); } IEEE80211_SKB_CB(skb)->flags |= tx_flags; + IEEE80211_SKB_CB(skb)->control.flags |= IEEE80211_TX_CTRL_SCAN_TX; ieee80211_tx_skb_tid_band(sdata, skb, 7, channel->band); } } diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c index 6bf223e6cd1a..cfd0a62d0152 100644 --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c @@ -698,11 +698,16 @@ ieee80211_tx_h_rate_ctrl(struct ieee80211_tx_data *tx) txrc.bss_conf = &tx->sdata->vif.bss_conf; txrc.skb = tx->skb; txrc.reported_rate.idx = -1; - txrc.rate_idx_mask = tx->sdata->rc_rateidx_mask[info->band]; - if (tx->sdata->rc_has_mcs_mask[info->band]) - txrc.rate_idx_mcs_mask = - tx->sdata->rc_rateidx_mcs_mask[info->band]; + if (unlikely(info->control.flags & IEEE80211_TX_CTRL_SCAN_TX)) { + txrc.rate_idx_mask = ~0; + } else { + txrc.rate_idx_mask = tx->sdata->rc_rateidx_mask[info->band]; + + if (tx->sdata->rc_has_mcs_mask[info->band]) + txrc.rate_idx_mcs_mask = + tx->sdata->rc_rateidx_mcs_mask[info->band]; + } txrc.bss = (tx->sdata->vif.type == NL80211_IFTYPE_AP || tx->sdata->vif.type == NL80211_IFTYPE_MESH_POINT || -- cgit v1.2.3 From d12b9779cc9ba29d65fbfc728eb8a037871dd331 Mon Sep 17 00:00:00 2001 From: Richard Kinder Date: Thu, 28 Mar 2024 11:57:25 +1100 Subject: wifi: mac80211: ensure beacon is non-S1G prior to extracting the beacon timestamp field Logic inside ieee80211_rx_mgmt_beacon accesses the mgmt->u.beacon.timestamp field without first checking whether the beacon received is non-S1G format. Fix the problem by checking the beacon is non-S1G format to avoid access of the mgmt->u.beacon.timestamp field. Signed-off-by: Richard Kinder Link: https://msgid.link/20240328005725.85355-1-richard.kinder@gmail.com Signed-off-by: Johannes Berg --- net/mac80211/mlme.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index 96b70006b7fc..db7128f6c901 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c @@ -6193,7 +6193,8 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_link_data *link, link->u.mgd.dtim_period = elems->dtim_period; link->u.mgd.have_beacon = true; ifmgd->assoc_data->need_beacon = false; - if (ieee80211_hw_check(&local->hw, TIMING_BEACON_ONLY)) { + if (ieee80211_hw_check(&local->hw, TIMING_BEACON_ONLY) && + !ieee80211_is_s1g_beacon(hdr->frame_control)) { link->conf->sync_tsf = le64_to_cpu(mgmt->u.beacon.timestamp); link->conf->sync_device_ts = -- cgit v1.2.3 From 9ef369973cd2c97cce3388d2c0c7e3c056656e8a Mon Sep 17 00:00:00 2001 From: Igor Artemiev Date: Fri, 5 Apr 2024 18:24:30 +0300 Subject: wifi: cfg80211: fix the order of arguments for trace events of the tx_rx_evt class The declarations of the tx_rx_evt class and the rdev_set_antenna event use the wrong order of arguments in the TP_ARGS macro. Fix the order of arguments in the TP_ARGS macro. Found by Linux Verification Center (linuxtesting.org) with SVACE. Signed-off-by: Igor Artemiev Link: https://msgid.link/20240405152431.270267-1-Igor.A.Artemiev@mcst.ru Signed-off-by: Johannes Berg --- net/wireless/trace.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/net/wireless/trace.h b/net/wireless/trace.h index cbbf347c6b2e..df013c98b80d 100644 --- a/net/wireless/trace.h +++ b/net/wireless/trace.h @@ -1758,7 +1758,7 @@ TRACE_EVENT(rdev_return_void_tx_rx, DECLARE_EVENT_CLASS(tx_rx_evt, TP_PROTO(struct wiphy *wiphy, u32 tx, u32 rx), - TP_ARGS(wiphy, rx, tx), + TP_ARGS(wiphy, tx, rx), TP_STRUCT__entry( WIPHY_ENTRY __field(u32, tx) @@ -1775,7 +1775,7 @@ DECLARE_EVENT_CLASS(tx_rx_evt, DEFINE_EVENT(tx_rx_evt, rdev_set_antenna, TP_PROTO(struct wiphy *wiphy, u32 tx, u32 rx), - TP_ARGS(wiphy, rx, tx) + TP_ARGS(wiphy, tx, rx) ); DECLARE_EVENT_CLASS(wiphy_netdev_id_evt, -- cgit v1.2.3 From 8db8f6ce556af60ca9a9fd5e826d369ded70fcc7 Mon Sep 17 00:00:00 2001 From: Manivannan Sadhasivam Date: Wed, 3 Apr 2024 18:50:03 +0530 Subject: scsi: ufs: qcom: Add missing interconnect bandwidth values for Gear 5 These entries are necessary to scale the interconnect bandwidth while operating in Gear 5. Cc: Amit Pundir Fixes: 03ce80a1bb86 ("scsi: ufs: qcom: Add support for scaling interconnects") Tested-by: Amit Pundir Signed-off-by: Manivannan Sadhasivam Link: https://lore.kernel.org/r/20240403-ufs-icc-fix-v2-1-958412a5eb45@linaro.org Signed-off-by: Martin K. Petersen --- drivers/ufs/host/ufs-qcom.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/drivers/ufs/host/ufs-qcom.c b/drivers/ufs/host/ufs-qcom.c index 06859e17b67b..7a00004bfd03 100644 --- a/drivers/ufs/host/ufs-qcom.c +++ b/drivers/ufs/host/ufs-qcom.c @@ -47,7 +47,7 @@ enum { TSTBUS_MAX, }; -#define QCOM_UFS_MAX_GEAR 4 +#define QCOM_UFS_MAX_GEAR 5 #define QCOM_UFS_MAX_LANE 2 enum { @@ -67,26 +67,32 @@ static const struct __ufs_qcom_bw_table { [MODE_PWM][UFS_PWM_G2][UFS_LANE_1] = { 1844, 1000 }, [MODE_PWM][UFS_PWM_G3][UFS_LANE_1] = { 3688, 1000 }, [MODE_PWM][UFS_PWM_G4][UFS_LANE_1] = { 7376, 1000 }, + [MODE_PWM][UFS_PWM_G5][UFS_LANE_1] = { 14752, 1000 }, [MODE_PWM][UFS_PWM_G1][UFS_LANE_2] = { 1844, 1000 }, [MODE_PWM][UFS_PWM_G2][UFS_LANE_2] = { 3688, 1000 }, [MODE_PWM][UFS_PWM_G3][UFS_LANE_2] = { 7376, 1000 }, [MODE_PWM][UFS_PWM_G4][UFS_LANE_2] = { 14752, 1000 }, + [MODE_PWM][UFS_PWM_G5][UFS_LANE_2] = { 29504, 1000 }, [MODE_HS_RA][UFS_HS_G1][UFS_LANE_1] = { 127796, 1000 }, [MODE_HS_RA][UFS_HS_G2][UFS_LANE_1] = { 255591, 1000 }, [MODE_HS_RA][UFS_HS_G3][UFS_LANE_1] = { 1492582, 102400 }, [MODE_HS_RA][UFS_HS_G4][UFS_LANE_1] = { 2915200, 204800 }, + [MODE_HS_RA][UFS_HS_G5][UFS_LANE_1] = { 5836800, 409600 }, [MODE_HS_RA][UFS_HS_G1][UFS_LANE_2] = { 255591, 1000 }, [MODE_HS_RA][UFS_HS_G2][UFS_LANE_2] = { 511181, 1000 }, [MODE_HS_RA][UFS_HS_G3][UFS_LANE_2] = { 1492582, 204800 }, [MODE_HS_RA][UFS_HS_G4][UFS_LANE_2] = { 2915200, 409600 }, + [MODE_HS_RA][UFS_HS_G5][UFS_LANE_2] = { 5836800, 819200 }, [MODE_HS_RB][UFS_HS_G1][UFS_LANE_1] = { 149422, 1000 }, [MODE_HS_RB][UFS_HS_G2][UFS_LANE_1] = { 298189, 1000 }, [MODE_HS_RB][UFS_HS_G3][UFS_LANE_1] = { 1492582, 102400 }, [MODE_HS_RB][UFS_HS_G4][UFS_LANE_1] = { 2915200, 204800 }, + [MODE_HS_RB][UFS_HS_G5][UFS_LANE_1] = { 5836800, 409600 }, [MODE_HS_RB][UFS_HS_G1][UFS_LANE_2] = { 298189, 1000 }, [MODE_HS_RB][UFS_HS_G2][UFS_LANE_2] = { 596378, 1000 }, [MODE_HS_RB][UFS_HS_G3][UFS_LANE_2] = { 1492582, 204800 }, [MODE_HS_RB][UFS_HS_G4][UFS_LANE_2] = { 2915200, 409600 }, + [MODE_HS_RB][UFS_HS_G5][UFS_LANE_2] = { 5836800, 819200 }, [MODE_MAX][0][0] = { 7643136, 307200 }, }; -- cgit v1.2.3 From 18f06e97692516d28c3cdc577fb5c501d690b303 Mon Sep 17 00:00:00 2001 From: Sean Christopherson Date: Tue, 19 Mar 2024 17:15:40 -0700 Subject: KVM: Add helpers to consolidate gfn_to_pfn_cache's page split check Add a helper to check that the incoming length for a gfn_to_pfn_cache is valid with respect to the cache's GPA and/or HVA. To avoid activating a cache with a bogus GPA, a future fix will fork the page split check in the inner refresh path into activate() and the public rerfresh() APIs, at which point KVM will check the length in three separate places. Deliberately keep the "page offset" logic open coded, as the only other path that consumes the offset, __kvm_gpc_refresh(), already needs to differentiate between GPA-based and HVA-based caches, and it's not obvious that using a helper is a net positive in overall code readability. Note, for GPA-based caches, this has a subtle side effect of using the GPA instead of the resolved HVA in the check() path, but that should be a nop as the HVA offset is derived from the GPA, i.e. the two offsets are identical, barring a KVM bug. Reviewed-by: Paul Durrant Reviewed-by: David Woodhouse Link: https://lore.kernel.org/r/20240320001542.3203871-2-seanjc@google.com Signed-off-by: Sean Christopherson --- virt/kvm/pfncache.c | 27 +++++++++++++++++++-------- 1 file changed, 19 insertions(+), 8 deletions(-) diff --git a/virt/kvm/pfncache.c b/virt/kvm/pfncache.c index 4e07112a24c2..8f2121b5f2a0 100644 --- a/virt/kvm/pfncache.c +++ b/virt/kvm/pfncache.c @@ -57,6 +57,19 @@ void gfn_to_pfn_cache_invalidate_start(struct kvm *kvm, unsigned long start, spin_unlock(&kvm->gpc_lock); } +static bool kvm_gpc_is_valid_len(gpa_t gpa, unsigned long uhva, + unsigned long len) +{ + unsigned long offset = kvm_is_error_gpa(gpa) ? offset_in_page(uhva) : + offset_in_page(gpa); + + /* + * The cached access must fit within a single page. The 'len' argument + * to activate() and refresh() exists only to enforce that. + */ + return offset + len <= PAGE_SIZE; +} + bool kvm_gpc_check(struct gfn_to_pfn_cache *gpc, unsigned long len) { struct kvm_memslots *slots = kvm_memslots(gpc->kvm); @@ -74,7 +87,7 @@ bool kvm_gpc_check(struct gfn_to_pfn_cache *gpc, unsigned long len) if (kvm_is_error_hva(gpc->uhva)) return false; - if (offset_in_page(gpc->uhva) + len > PAGE_SIZE) + if (!kvm_gpc_is_valid_len(gpc->gpa, gpc->uhva, len)) return false; if (!gpc->valid) @@ -247,13 +260,7 @@ static int __kvm_gpc_refresh(struct gfn_to_pfn_cache *gpc, gpa_t gpa, unsigned l if (WARN_ON_ONCE(kvm_is_error_gpa(gpa) == kvm_is_error_hva(uhva))) return -EINVAL; - /* - * The cached acces must fit within a single page. The 'len' argument - * exists only to enforce that. - */ - page_offset = kvm_is_error_gpa(gpa) ? offset_in_page(uhva) : - offset_in_page(gpa); - if (page_offset + len > PAGE_SIZE) + if (!kvm_gpc_is_valid_len(gpa, uhva, len)) return -EINVAL; lockdep_assert_held(&gpc->refresh_lock); @@ -270,6 +277,8 @@ static int __kvm_gpc_refresh(struct gfn_to_pfn_cache *gpc, gpa_t gpa, unsigned l old_uhva = PAGE_ALIGN_DOWN(gpc->uhva); if (kvm_is_error_gpa(gpa)) { + page_offset = offset_in_page(uhva); + gpc->gpa = INVALID_GPA; gpc->memslot = NULL; gpc->uhva = PAGE_ALIGN_DOWN(uhva); @@ -279,6 +288,8 @@ static int __kvm_gpc_refresh(struct gfn_to_pfn_cache *gpc, gpa_t gpa, unsigned l } else { struct kvm_memslots *slots = kvm_memslots(gpc->kvm); + page_offset = offset_in_page(gpa); + if (gpc->gpa != gpa || gpc->generation != slots->generation || kvm_is_error_hva(gpc->uhva)) { gfn_t gfn = gpa_to_gfn(gpa); -- cgit v1.2.3 From 5c9ca4ed890889a2b7c300c4f63f3baf3f63383f Mon Sep 17 00:00:00 2001 From: Sean Christopherson Date: Tue, 19 Mar 2024 17:15:41 -0700 Subject: KVM: Check validity of offset+length of gfn_to_pfn_cache prior to activation When activating a gfn_to_pfn_cache, verify that the offset+length is sane and usable before marking the cache active. Letting __kvm_gpc_refresh() detect the problem results in a cache being marked active without setting the GPA (or any other fields), which in turn results in KVM trying to refresh a cache with INVALID_GPA. Attempting to refresh a cache with INVALID_GPA isn't functionally problematic, but it runs afoul of the sanity check that exactly one of GPA or userspace HVA is valid, i.e. that a cache is either GPA-based or HVA-based. Reported-by: syzbot+106a4f72b0474e1d1b33@syzkaller.appspotmail.com Closes: https://lore.kernel.org/all/0000000000005fa5cc0613f1cebd@google.com Fixes: 721f5b0dda78 ("KVM: pfncache: allow a cache to be activated with a fixed (userspace) HVA") Cc: David Woodhouse Cc: Paul Durrant Reviewed-by: Paul Durrant Reviewed-by: David Woodhouse Link: https://lore.kernel.org/r/20240320001542.3203871-3-seanjc@google.com Signed-off-by: Sean Christopherson --- virt/kvm/pfncache.c | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/virt/kvm/pfncache.c b/virt/kvm/pfncache.c index 8f2121b5f2a0..91b0e329006b 100644 --- a/virt/kvm/pfncache.c +++ b/virt/kvm/pfncache.c @@ -245,8 +245,7 @@ out_error: return -EFAULT; } -static int __kvm_gpc_refresh(struct gfn_to_pfn_cache *gpc, gpa_t gpa, unsigned long uhva, - unsigned long len) +static int __kvm_gpc_refresh(struct gfn_to_pfn_cache *gpc, gpa_t gpa, unsigned long uhva) { unsigned long page_offset; bool unmap_old = false; @@ -260,9 +259,6 @@ static int __kvm_gpc_refresh(struct gfn_to_pfn_cache *gpc, gpa_t gpa, unsigned l if (WARN_ON_ONCE(kvm_is_error_gpa(gpa) == kvm_is_error_hva(uhva))) return -EINVAL; - if (!kvm_gpc_is_valid_len(gpa, uhva, len)) - return -EINVAL; - lockdep_assert_held(&gpc->refresh_lock); write_lock_irq(&gpc->lock); @@ -365,6 +361,9 @@ int kvm_gpc_refresh(struct gfn_to_pfn_cache *gpc, unsigned long len) guard(mutex)(&gpc->refresh_lock); + if (!kvm_gpc_is_valid_len(gpc->gpa, gpc->uhva, len)) + return -EINVAL; + /* * If the GPA is valid then ignore the HVA, as a cache can be GPA-based * or HVA-based, not both. For GPA-based caches, the HVA will be @@ -372,7 +371,7 @@ int kvm_gpc_refresh(struct gfn_to_pfn_cache *gpc, unsigned long len) */ uhva = kvm_is_error_gpa(gpc->gpa) ? gpc->uhva : KVM_HVA_ERR_BAD; - return __kvm_gpc_refresh(gpc, gpc->gpa, uhva, len); + return __kvm_gpc_refresh(gpc, gpc->gpa, uhva); } void kvm_gpc_init(struct gfn_to_pfn_cache *gpc, struct kvm *kvm) @@ -392,6 +391,9 @@ static int __kvm_gpc_activate(struct gfn_to_pfn_cache *gpc, gpa_t gpa, unsigned { struct kvm *kvm = gpc->kvm; + if (!kvm_gpc_is_valid_len(gpa, uhva, len)) + return -EINVAL; + guard(mutex)(&gpc->refresh_lock); if (!gpc->active) { @@ -411,7 +413,7 @@ static int __kvm_gpc_activate(struct gfn_to_pfn_cache *gpc, gpa_t gpa, unsigned gpc->active = true; write_unlock_irq(&gpc->lock); } - return __kvm_gpc_refresh(gpc, gpa, uhva, len); + return __kvm_gpc_refresh(gpc, gpa, uhva); } int kvm_gpc_activate(struct gfn_to_pfn_cache *gpc, gpa_t gpa, unsigned long len) -- cgit v1.2.3 From fc62a4e8dee2d1a9037e8cdeaa52ba67457f7300 Mon Sep 17 00:00:00 2001 From: Sean Christopherson Date: Tue, 19 Mar 2024 17:15:42 -0700 Subject: KVM: Explicitly disallow activatating a gfn_to_pfn_cache with INVALID_GPA Explicit disallow activating a gfn_to_pfn_cache with an error gpa, i.e. INVALID_GPA, to ensure that KVM doesn't mistake a GPA-based cache for an HVA-based cache (KVM uses INVALID_GPA as a magic value to differentiate between GPA-based and HVA-based caches). WARN if KVM attempts to activate a cache with INVALID_GPA, purely so that new caches need to at least consider what to do with a "bad" GPA, as all existing usage of kvm_gpc_activate() guarantees gpa != INVALID_GPA. I.e. removing the WARN in the future is completely reasonable if doing so would yield cleaner/better code overall. Reviewed-by: David Woodhouse Reviewed-by: Paul Durrant Link: https://lore.kernel.org/r/20240320001542.3203871-4-seanjc@google.com Signed-off-by: Sean Christopherson --- virt/kvm/pfncache.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/virt/kvm/pfncache.c b/virt/kvm/pfncache.c index 91b0e329006b..f618719644e0 100644 --- a/virt/kvm/pfncache.c +++ b/virt/kvm/pfncache.c @@ -418,6 +418,13 @@ static int __kvm_gpc_activate(struct gfn_to_pfn_cache *gpc, gpa_t gpa, unsigned int kvm_gpc_activate(struct gfn_to_pfn_cache *gpc, gpa_t gpa, unsigned long len) { + /* + * Explicitly disallow INVALID_GPA so that the magic value can be used + * by KVM to differentiate between GPA-based and HVA-based caches. + */ + if (WARN_ON_ONCE(kvm_is_error_gpa(gpa))) + return -EINVAL; + return __kvm_gpc_activate(gpc, gpa, KVM_HVA_ERR_BAD, len); } -- cgit v1.2.3 From 9e985cbf2942a1bb8fcef9adc2a17d90fd7ca8ee Mon Sep 17 00:00:00 2001 From: Sean Christopherson Date: Wed, 6 Mar 2024 16:58:33 -0800 Subject: KVM: x86/pmu: Disable support for adaptive PEBS Drop support for virtualizing adaptive PEBS, as KVM's implementation is architecturally broken without an obvious/easy path forward, and because exposing adaptive PEBS can leak host LBRs to the guest, i.e. can leak host kernel addresses to the guest. Bug #1 is that KVM doesn't account for the upper 32 bits of IA32_FIXED_CTR_CTRL when (re)programming fixed counters, e.g fixed_ctrl_field() drops the upper bits, reprogram_fixed_counters() stores local variables as u8s and truncates the upper bits too, etc. Bug #2 is that, because KVM _always_ sets precise_ip to a non-zero value for PEBS events, perf will _always_ generate an adaptive record, even if the guest requested a basic record. Note, KVM will also enable adaptive PEBS in individual *counter*, even if adaptive PEBS isn't exposed to the guest, but this is benign as MSR_PEBS_DATA_CFG is guaranteed to be zero, i.e. the guest will only ever see Basic records. Bug #3 is in perf. intel_pmu_disable_fixed() doesn't clear the upper bits either, i.e. leaves ICL_FIXED_0_ADAPTIVE set, and intel_pmu_enable_fixed() effectively doesn't clear ICL_FIXED_0_ADAPTIVE either. I.e. perf _always_ enables ADAPTIVE counters, regardless of what KVM requests. Bug #4 is that adaptive PEBS *might* effectively bypass event filters set by the host, as "Updated Memory Access Info Group" records information that might be disallowed by userspace via KVM_SET_PMU_EVENT_FILTER. Bug #5 is that KVM doesn't ensure LBR MSRs hold guest values (or at least zeros) when entering a vCPU with adaptive PEBS, which allows the guest to read host LBRs, i.e. host RIPs/addresses, by enabling "LBR Entries" records. Disable adaptive PEBS support as an immediate fix due to the severity of the LBR leak in particular, and because fixing all of the bugs will be non-trivial, e.g. not suitable for backporting to stable kernels. Note! This will break live migration, but trying to make KVM play nice with live migration would be quite complicated, wouldn't be guaranteed to work (i.e. KVM might still kill/confuse the guest), and it's not clear that there are any publicly available VMMs that support adaptive PEBS, let alone live migrate VMs that support adaptive PEBS, e.g. QEMU doesn't support PEBS in any capacity. Link: https://lore.kernel.org/all/20240306230153.786365-1-seanjc@google.com Link: https://lore.kernel.org/all/ZeepGjHCeSfadANM@google.com Fixes: c59a1f106f5c ("KVM: x86/pmu: Add IA32_PEBS_ENABLE MSR emulation for extended PEBS") Cc: stable@vger.kernel.org Cc: Like Xu Cc: Mingwei Zhang Cc: Zhenyu Wang Cc: Zhang Xiong Cc: Lv Zhiyuan Cc: Dapeng Mi Cc: Jim Mattson Acked-by: Like Xu Link: https://lore.kernel.org/r/20240307005833.827147-1-seanjc@google.com Signed-off-by: Sean Christopherson --- arch/x86/kvm/vmx/vmx.c | 24 ++++++++++++++++++++++-- 1 file changed, 22 insertions(+), 2 deletions(-) diff --git a/arch/x86/kvm/vmx/vmx.c b/arch/x86/kvm/vmx/vmx.c index c37a89eda90f..e3315bda6237 100644 --- a/arch/x86/kvm/vmx/vmx.c +++ b/arch/x86/kvm/vmx/vmx.c @@ -7882,8 +7882,28 @@ static u64 vmx_get_perf_capabilities(void) if (vmx_pebs_supported()) { perf_cap |= host_perf_cap & PERF_CAP_PEBS_MASK; - if ((perf_cap & PERF_CAP_PEBS_FORMAT) < 4) - perf_cap &= ~PERF_CAP_PEBS_BASELINE; + + /* + * Disallow adaptive PEBS as it is functionally broken, can be + * used by the guest to read *host* LBRs, and can be used to + * bypass userspace event filters. To correctly and safely + * support adaptive PEBS, KVM needs to: + * + * 1. Account for the ADAPTIVE flag when (re)programming fixed + * counters. + * + * 2. Gain support from perf (or take direct control of counter + * programming) to support events without adaptive PEBS + * enabled for the hardware counter. + * + * 3. Ensure LBR MSRs cannot hold host data on VM-Entry with + * adaptive PEBS enabled and MSR_PEBS_DATA_CFG.LBRS=1. + * + * 4. Document which PMU events are effectively exposed to the + * guest via adaptive PEBS, and make adaptive PEBS mutually + * exclusive with KVM_SET_PMU_EVENT_FILTER if necessary. + */ + perf_cap &= ~PERF_CAP_PEBS_BASELINE; } return perf_cap; -- cgit v1.2.3 From 992b54bd083c5bee24ff7cc35991388ab08598c4 Mon Sep 17 00:00:00 2001 From: Rick Edgecombe Date: Thu, 14 Mar 2024 14:29:02 -0700 Subject: KVM: x86/mmu: x86: Don't overflow lpage_info when checking attributes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fix KVM_SET_MEMORY_ATTRIBUTES to not overflow lpage_info array and trigger KASAN splat, as seen in the private_mem_conversions_test selftest. When memory attributes are set on a GFN range, that range will have specific properties applied to the TDP. A huge page cannot be used when the attributes are inconsistent, so they are disabled for those the specific huge pages. For internal KVM reasons, huge pages are also not allowed to span adjacent memslots regardless of whether the backing memory could be mapped as huge. What GFNs support which huge page sizes is tracked by an array of arrays 'lpage_info' on the memslot, of ‘kvm_lpage_info’ structs. Each index of lpage_info contains a vmalloc allocated array of these for a specific supported page size. The kvm_lpage_info denotes whether a specific huge page (GFN and page size) on the memslot is supported. These arrays include indices for unaligned head and tail huge pages. Preventing huge pages from spanning adjacent memslot is covered by incrementing the count in head and tail kvm_lpage_info when the memslot is allocated, but disallowing huge pages for memory that has mixed attributes has to be done in a more complicated way. During the KVM_SET_MEMORY_ATTRIBUTES ioctl KVM updates lpage_info for each memslot in the range that has mismatched attributes. KVM does this a memslot at a time, and marks a special bit, KVM_LPAGE_MIXED_FLAG, in the kvm_lpage_info for any huge page. This bit is essentially a permanently elevated count. So huge pages will not be mapped for the GFN at that page size if the count is elevated in either case: a huge head or tail page unaligned to the memslot or if KVM_LPAGE_MIXED_FLAG is set because it has mixed attributes. To determine whether a huge page has consistent attributes, the KVM_SET_MEMORY_ATTRIBUTES operation checks an xarray to make sure it consistently has the incoming attribute. Since level - 1 huge pages are aligned to level huge pages, it employs an optimization. As long as the level - 1 huge pages are checked first, it can just check these and assume that if each level - 1 huge page contained within the level sized huge page is not mixed, then the level size huge page is not mixed. This optimization happens in the helper hugepage_has_attrs(). Unfortunately, although the kvm_lpage_info array representing page size 'level' will contain an entry for an unaligned tail page of size level, the array for level - 1 will not contain an entry for each GFN at page size level. The level - 1 array will only contain an index for any unaligned region covered by level - 1 huge page size, which can be a smaller region. So this causes the optimization to overflow the level - 1 kvm_lpage_info and perform a vmalloc out of bounds read. In some cases of head and tail pages where an overflow could happen, callers skip the operation completely as KVM_LPAGE_MIXED_FLAG is not required to prevent huge pages as discussed earlier. But for memslots that are smaller than the 1GB page size, it does call hugepage_has_attrs(). In this case the huge page is both the head and tail page. The issue can be observed simply by compiling the kernel with CONFIG_KASAN_VMALLOC and running the selftest “private_mem_conversions_test”, which produces the output like the following: BUG: KASAN: vmalloc-out-of-bounds in hugepage_has_attrs+0x7e/0x110 Read of size 4 at addr ffffc900000a3008 by task private_mem_con/169 Call Trace: dump_stack_lvl print_report ? __virt_addr_valid ? hugepage_has_attrs ? hugepage_has_attrs kasan_report ? hugepage_has_attrs hugepage_has_attrs kvm_arch_post_set_memory_attributes kvm_vm_ioctl It is a little ambiguous whether the unaligned head page (in the bug case also the tail page) should be expected to have KVM_LPAGE_MIXED_FLAG set. It is not functionally required, as the unaligned head/tail pages will already have their kvm_lpage_info count incremented. The comments imply not setting it on unaligned head pages is intentional, so fix the callers to skip trying to set KVM_LPAGE_MIXED_FLAG in this case, and in doing so not call hugepage_has_attrs(). Cc: stable@vger.kernel.org Fixes: 90b4fe17981e ("KVM: x86: Disallow hugepages when memory attributes are mixed") Signed-off-by: Rick Edgecombe Reviewed-by: Kai Huang Reviewed-by: Chao Peng Link: https://lore.kernel.org/r/20240314212902.2762507-1-rick.p.edgecombe@intel.com Signed-off-by: Sean Christopherson --- arch/x86/kvm/mmu/mmu.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/arch/x86/kvm/mmu/mmu.c b/arch/x86/kvm/mmu/mmu.c index 992e651540e8..18a404b5923f 100644 --- a/arch/x86/kvm/mmu/mmu.c +++ b/arch/x86/kvm/mmu/mmu.c @@ -7399,7 +7399,8 @@ bool kvm_arch_post_set_memory_attributes(struct kvm *kvm, * by the memslot, KVM can't use a hugepage due to the * misaligned address regardless of memory attributes. */ - if (gfn >= slot->base_gfn) { + if (gfn >= slot->base_gfn && + gfn + nr_pages <= slot->base_gfn + slot->npages) { if (hugepage_has_attrs(kvm, slot, gfn, level, attrs)) hugepage_clear_mixed(slot, gfn, level); else -- cgit v1.2.3 From de120e1d692d73c7eefa3278837b1eb68f90728a Mon Sep 17 00:00:00 2001 From: Sean Christopherson Date: Fri, 8 Mar 2024 17:36:40 -0800 Subject: KVM: x86/pmu: Set enable bits for GP counters in PERF_GLOBAL_CTRL at "RESET" Set the enable bits for general purpose counters in IA32_PERF_GLOBAL_CTRL when refreshing the PMU to emulate the MSR's architecturally defined post-RESET behavior. Per Intel's SDM: IA32_PERF_GLOBAL_CTRL: Sets bits n-1:0 and clears the upper bits. and Where "n" is the number of general-purpose counters available in the processor. AMD also documents this behavior for PerfMonV2 CPUs in one of AMD's many PPRs. Do not set any PERF_GLOBAL_CTRL bits if there are no general purpose counters, although a literal reading of the SDM would require the CPU to set either bits 63:0 or 31:0. The intent of the behavior is to globally enable all GP counters; honor the intent, if not the letter of the law. Leaving PERF_GLOBAL_CTRL '0' effectively breaks PMU usage in guests that haven't been updated to work with PMUs that support PERF_GLOBAL_CTRL. This bug was recently exposed when KVM added supported for AMD's PerfMonV2, i.e. when KVM started exposing a vPMU with PERF_GLOBAL_CTRL to guest software that only knew how to program v1 PMUs (that don't support PERF_GLOBAL_CTRL). Failure to emulate the post-RESET behavior results in such guests unknowingly leaving all general purpose counters globally disabled (the entire reason the post-RESET value sets the GP counter enable bits is to maintain backwards compatibility). The bug has likely gone unnoticed because PERF_GLOBAL_CTRL has been supported on Intel CPUs for as long as KVM has existed, i.e. hardly anyone is running guest software that isn't aware of PERF_GLOBAL_CTRL on Intel PMUs. And because up until v6.0, KVM _did_ emulate the behavior for Intel CPUs, although the old behavior was likely dumb luck. Because (a) that old code was also broken in its own way (the history of this code is a comedy of errors), and (b) PERF_GLOBAL_CTRL was documented as having a value of '0' post-RESET in all SDMs before March 2023. Initial vPMU support in commit f5132b01386b ("KVM: Expose a version 2 architectural PMU to a guests") *almost* got it right (again likely by dumb luck), but for some reason only set the bits if the guest PMU was advertised as v1: if (pmu->version == 1) { pmu->global_ctrl = (1 << pmu->nr_arch_gp_counters) - 1; return; } Commit f19a0c2c2e6a ("KVM: PMU emulation: GLOBAL_CTRL MSR should be enabled on reset") then tried to remedy that goof, presumably because guest PMUs were leaving PERF_GLOBAL_CTRL '0', i.e. weren't enabling counters. pmu->global_ctrl = ((1 << pmu->nr_arch_gp_counters) - 1) | (((1ull << pmu->nr_arch_fixed_counters) - 1) << X86_PMC_IDX_FIXED); pmu->global_ctrl_mask = ~pmu->global_ctrl; That was KVM's behavior up until commit c49467a45fe0 ("KVM: x86/pmu: Don't overwrite the pmu->global_ctrl when refreshing") removed *everything*. However, it did so based on the behavior defined by the SDM , which at the time stated that "Global Perf Counter Controls" is '0' at Power-Up and RESET. But then the March 2023 SDM (325462-079US), stealthily changed its "IA-32 and Intel 64 Processor States Following Power-up, Reset, or INIT" table to say: IA32_PERF_GLOBAL_CTRL: Sets bits n-1:0 and clears the upper bits. Note, kvm_pmu_refresh() can be invoked multiple times, i.e. it's not a "pure" RESET flow. But it can only be called prior to the first KVM_RUN, i.e. the guest will only ever observe the final value. Note #2, KVM has always cleared global_ctrl during refresh (see commit f5132b01386b ("KVM: Expose a version 2 architectural PMU to a guests")), i.e. there is no danger of breaking existing setups by clobbering a value set by userspace. Reported-by: Babu Moger Cc: Sandipan Das Cc: Like Xu Cc: Mingwei Zhang Cc: Dapeng Mi Cc: stable@vger.kernel.org Reviewed-by: Dapeng Mi Tested-by: Dapeng Mi Link: https://lore.kernel.org/r/20240309013641.1413400-2-seanjc@google.com Signed-off-by: Sean Christopherson --- arch/x86/kvm/pmu.c | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/arch/x86/kvm/pmu.c b/arch/x86/kvm/pmu.c index c397b28e3d1b..a593b03c9aed 100644 --- a/arch/x86/kvm/pmu.c +++ b/arch/x86/kvm/pmu.c @@ -775,8 +775,20 @@ void kvm_pmu_refresh(struct kvm_vcpu *vcpu) pmu->pebs_data_cfg_mask = ~0ull; bitmap_zero(pmu->all_valid_pmc_idx, X86_PMC_IDX_MAX); - if (vcpu->kvm->arch.enable_pmu) - static_call(kvm_x86_pmu_refresh)(vcpu); + if (!vcpu->kvm->arch.enable_pmu) + return; + + static_call(kvm_x86_pmu_refresh)(vcpu); + + /* + * At RESET, both Intel and AMD CPUs set all enable bits for general + * purpose counters in IA32_PERF_GLOBAL_CTRL (so that software that + * was written for v1 PMUs don't unknowingly leave GP counters disabled + * in the global controls). Emulate that behavior when refreshing the + * PMU so that userspace doesn't need to manually set PERF_GLOBAL_CTRL. + */ + if (kvm_pmu_has_perf_global_ctrl(pmu) && pmu->nr_arch_gp_counters) + pmu->global_ctrl = GENMASK_ULL(pmu->nr_arch_gp_counters - 1, 0); } void kvm_pmu_init(struct kvm_vcpu *vcpu) -- cgit v1.2.3 From 08a828249b16f69248652937be7f1b8dab340a22 Mon Sep 17 00:00:00 2001 From: Sean Christopherson Date: Fri, 8 Mar 2024 17:36:41 -0800 Subject: KVM: selftests: Verify post-RESET value of PERF_GLOBAL_CTRL in PMCs test Add a guest assert in the PMU counters test to verify that KVM stuffs the vCPU's post-RESET value to globally enable all general purpose counters. Per Intel's SDM, IA32_PERF_GLOBAL_CTRL: Sets bits n-1:0 and clears the upper bits. and Where "n" is the number of general-purpose counters available in the processor. For the edge case where there are zero GP counters, follow the spirit of the architecture, not the SDM's literal wording, which doesn't account for this possibility and would require the CPU to set _all_ bits in PERF_GLOBAL_CTRL. Reviewed-by: Dapeng Mi Tested-by: Dapeng Mi Link: https://lore.kernel.org/r/20240309013641.1413400-3-seanjc@google.com Signed-off-by: Sean Christopherson --- .../testing/selftests/kvm/x86_64/pmu_counters_test.c | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/tools/testing/selftests/kvm/x86_64/pmu_counters_test.c b/tools/testing/selftests/kvm/x86_64/pmu_counters_test.c index 29609b52f8fa..26c85815f7e9 100644 --- a/tools/testing/selftests/kvm/x86_64/pmu_counters_test.c +++ b/tools/testing/selftests/kvm/x86_64/pmu_counters_test.c @@ -416,12 +416,30 @@ static void guest_rd_wr_counters(uint32_t base_msr, uint8_t nr_possible_counters static void guest_test_gp_counters(void) { + uint8_t pmu_version = guest_get_pmu_version(); uint8_t nr_gp_counters = 0; uint32_t base_msr; - if (guest_get_pmu_version()) + if (pmu_version) nr_gp_counters = this_cpu_property(X86_PROPERTY_PMU_NR_GP_COUNTERS); + /* + * For v2+ PMUs, PERF_GLOBAL_CTRL's architectural post-RESET value is + * "Sets bits n-1:0 and clears the upper bits", where 'n' is the number + * of GP counters. If there are no GP counters, require KVM to leave + * PERF_GLOBAL_CTRL '0'. This edge case isn't covered by the SDM, but + * follow the spirit of the architecture and only globally enable GP + * counters, of which there are none. + */ + if (pmu_version > 1) { + uint64_t global_ctrl = rdmsr(MSR_CORE_PERF_GLOBAL_CTRL); + + if (nr_gp_counters) + GUEST_ASSERT_EQ(global_ctrl, GENMASK_ULL(nr_gp_counters - 1, 0)); + else + GUEST_ASSERT_EQ(global_ctrl, 0); + } + if (this_cpu_has(X86_FEATURE_PDCM) && rdmsr(MSR_IA32_PERF_CAPABILITIES) & PMU_CAP_FW_WRITES) base_msr = MSR_IA32_PMC0; -- cgit v1.2.3 From 0ef2dd1f4144bc024d3c98954fa061a102f6481b Mon Sep 17 00:00:00 2001 From: Maxim Levitsky Date: Fri, 15 Mar 2024 10:35:07 -0400 Subject: KVM: selftests: fix max_guest_memory_test with more that 256 vCPUs max_guest_memory_test uses ucalls to sync with the host, but it also resets the guest RIP back to its initial value in between tests stages. This makes the guest never reach the code which frees the ucall struct and since a fixed pool of 512 ucall structs is used, the test starts to fail when more that 256 vCPUs are used. Fix that by replacing the manual register reset with a loop in the guest code. Signed-off-by: Maxim Levitsky Link: https://lore.kernel.org/r/20240315143507.102629-1-mlevitsk@redhat.com Signed-off-by: Sean Christopherson --- tools/testing/selftests/kvm/max_guest_memory_test.c | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/tools/testing/selftests/kvm/max_guest_memory_test.c b/tools/testing/selftests/kvm/max_guest_memory_test.c index 6628dc4dda89..1a6da7389bf1 100644 --- a/tools/testing/selftests/kvm/max_guest_memory_test.c +++ b/tools/testing/selftests/kvm/max_guest_memory_test.c @@ -22,10 +22,11 @@ static void guest_code(uint64_t start_gpa, uint64_t end_gpa, uint64_t stride) { uint64_t gpa; - for (gpa = start_gpa; gpa < end_gpa; gpa += stride) - *((volatile uint64_t *)gpa) = gpa; - - GUEST_DONE(); + for (;;) { + for (gpa = start_gpa; gpa < end_gpa; gpa += stride) + *((volatile uint64_t *)gpa) = gpa; + GUEST_SYNC(0); + } } struct vcpu_info { @@ -55,7 +56,7 @@ static void rendezvous_with_boss(void) static void run_vcpu(struct kvm_vcpu *vcpu) { vcpu_run(vcpu); - TEST_ASSERT_EQ(get_ucall(vcpu, NULL), UCALL_DONE); + TEST_ASSERT_EQ(get_ucall(vcpu, NULL), UCALL_SYNC); } static void *vcpu_worker(void *data) @@ -64,17 +65,13 @@ static void *vcpu_worker(void *data) struct kvm_vcpu *vcpu = info->vcpu; struct kvm_vm *vm = vcpu->vm; struct kvm_sregs sregs; - struct kvm_regs regs; vcpu_args_set(vcpu, 3, info->start_gpa, info->end_gpa, vm->page_size); - /* Snapshot regs before the first run. */ - vcpu_regs_get(vcpu, ®s); rendezvous_with_boss(); run_vcpu(vcpu); rendezvous_with_boss(); - vcpu_regs_set(vcpu, ®s); vcpu_sregs_get(vcpu, &sregs); #ifdef __x86_64__ /* Toggle CR0.WP to trigger a MMU context reset. */ -- cgit v1.2.3 From 449c0811d8729068646e1a270be72bf2da2e66f3 Mon Sep 17 00:00:00 2001 From: Andrew Jones Date: Wed, 3 Apr 2024 14:33:01 +0200 Subject: KVM: selftests: fix supported_flags for riscv commit 849c1816436f ("KVM: selftests: fix supported_flags for aarch64") fixed the set-memory-region test for aarch64 by declaring the read-only flag is supported. riscv also supports the read-only flag. Fix it too. Signed-off-by: Andrew Jones Link: https://lore.kernel.org/r/20240403123300.63923-2-ajones@ventanamicro.com Signed-off-by: Sean Christopherson --- tools/testing/selftests/kvm/set_memory_region_test.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/testing/selftests/kvm/set_memory_region_test.c b/tools/testing/selftests/kvm/set_memory_region_test.c index 06b43ed23580..bd57d991e27d 100644 --- a/tools/testing/selftests/kvm/set_memory_region_test.c +++ b/tools/testing/selftests/kvm/set_memory_region_test.c @@ -333,7 +333,7 @@ static void test_invalid_memory_region_flags(void) struct kvm_vm *vm; int r, i; -#if defined __aarch64__ || defined __x86_64__ +#if defined __aarch64__ || defined __riscv || defined __x86_64__ supported_flags |= KVM_MEM_READONLY; #endif -- cgit v1.2.3 From 7f2817ef52a1cc3ee0ace35eb8df7a39bd4fc9b7 Mon Sep 17 00:00:00 2001 From: Tao Su Date: Tue, 19 Mar 2024 11:11:11 +0800 Subject: KVM: VMX: Ignore MKTME KeyID bits when intercepting #PF for allow_smaller_maxphyaddr Use the raw/true host.MAXPHYADDR when deciding whether or not KVM must intercept #PFs when allow_smaller_maxphyaddr is enabled, as any adjustments the kernel makes to boot_cpu_data.x86_phys_bits to account for MKTME KeyID bits do not apply to the guest physical address space. I.e. the KeyID are off-limits for host physical addresses, but are not reserved for GPAs as far as hardware is concerned. Signed-off-by: Tao Su Link: https://lore.kernel.org/r/20240319031111.495006-1-tao1.su@linux.intel.com [sean: massage changelog] Signed-off-by: Sean Christopherson --- arch/x86/kvm/vmx/vmx.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/arch/x86/kvm/vmx/vmx.h b/arch/x86/kvm/vmx/vmx.h index 65786dbe7d60..1742c88ba9c8 100644 --- a/arch/x86/kvm/vmx/vmx.h +++ b/arch/x86/kvm/vmx/vmx.h @@ -15,6 +15,7 @@ #include "vmx_ops.h" #include "../cpuid.h" #include "run_flags.h" +#include "../mmu.h" #define MSR_TYPE_R 1 #define MSR_TYPE_W 2 @@ -719,7 +720,8 @@ static inline bool vmx_need_pf_intercept(struct kvm_vcpu *vcpu) if (!enable_ept) return true; - return allow_smaller_maxphyaddr && cpuid_maxphyaddr(vcpu) < boot_cpu_data.x86_phys_bits; + return allow_smaller_maxphyaddr && + cpuid_maxphyaddr(vcpu) < kvm_get_shadow_phys_bits(); } static inline bool is_unrestricted_guest(struct kvm_vcpu *vcpu) -- cgit v1.2.3 From ca91259b775f6fd98ae5d23bb4eec101d468ba8d Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Mon, 25 Mar 2024 15:44:17 -0700 Subject: scsi: core: Fix handling of SCMD_FAIL_IF_RECOVERING There is code in the SCSI core that sets the SCMD_FAIL_IF_RECOVERING flag but there is no code that clears this flag. Instead of only clearing SCMD_INITIALIZED in scsi_end_request(), clear all flags. It is never necessary to preserve any command flags inside scsi_end_request(). Cc: stable@vger.kernel.org Fixes: 310bcaef6d7e ("scsi: core: Support failing requests while recovering") Signed-off-by: Bart Van Assche Link: https://lore.kernel.org/r/20240325224417.1477135-1-bvanassche@acm.org Signed-off-by: Martin K. Petersen --- drivers/scsi/scsi_lib.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c index 2e28e2360c85..5b3230ef51fe 100644 --- a/drivers/scsi/scsi_lib.c +++ b/drivers/scsi/scsi_lib.c @@ -635,10 +635,9 @@ static bool scsi_end_request(struct request *req, blk_status_t error, if (blk_queue_add_random(q)) add_disk_randomness(req->q->disk); - if (!blk_rq_is_passthrough(req)) { - WARN_ON_ONCE(!(cmd->flags & SCMD_INITIALIZED)); - cmd->flags &= ~SCMD_INITIALIZED; - } + WARN_ON_ONCE(!blk_rq_is_passthrough(req) && + !(cmd->flags & SCMD_INITIALIZED)); + cmd->flags = 0; /* * Calling rcu_barrier() is not necessary here because the -- cgit v1.2.3 From f96f700449b6d190e06272f1cf732ae8e45b73df Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Fri, 5 Apr 2024 22:30:39 +0200 Subject: net: ks8851: Inline ks8851_rx_skb() Both ks8851_rx_skb_par() and ks8851_rx_skb_spi() call netif_rx(skb), inline the netif_rx(skb) call directly into ks8851_common.c and drop the .rx_skb callback and ks8851_rx_skb() wrapper. This removes one indirect call from the driver, no functional change otherwise. Signed-off-by: Marek Vasut Link: https://lore.kernel.org/r/20240405203204.82062-1-marex@denx.de Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/micrel/ks8851.h | 3 --- drivers/net/ethernet/micrel/ks8851_common.c | 12 +----------- drivers/net/ethernet/micrel/ks8851_par.c | 11 ----------- drivers/net/ethernet/micrel/ks8851_spi.c | 11 ----------- 4 files changed, 1 insertion(+), 36 deletions(-) diff --git a/drivers/net/ethernet/micrel/ks8851.h b/drivers/net/ethernet/micrel/ks8851.h index e5ec0a363aff..31f75b4a67fd 100644 --- a/drivers/net/ethernet/micrel/ks8851.h +++ b/drivers/net/ethernet/micrel/ks8851.h @@ -368,7 +368,6 @@ union ks8851_tx_hdr { * @rdfifo: FIFO read callback * @wrfifo: FIFO write callback * @start_xmit: start_xmit() implementation callback - * @rx_skb: rx_skb() implementation callback * @flush_tx_work: flush_tx_work() implementation callback * * The @statelock is used to protect information in the structure which may @@ -423,8 +422,6 @@ struct ks8851_net { struct sk_buff *txp, bool irq); netdev_tx_t (*start_xmit)(struct sk_buff *skb, struct net_device *dev); - void (*rx_skb)(struct ks8851_net *ks, - struct sk_buff *skb); void (*flush_tx_work)(struct ks8851_net *ks); }; diff --git a/drivers/net/ethernet/micrel/ks8851_common.c b/drivers/net/ethernet/micrel/ks8851_common.c index 0bf13b38b8f5..896d43bb8883 100644 --- a/drivers/net/ethernet/micrel/ks8851_common.c +++ b/drivers/net/ethernet/micrel/ks8851_common.c @@ -231,16 +231,6 @@ static void ks8851_dbg_dumpkkt(struct ks8851_net *ks, u8 *rxpkt) rxpkt[12], rxpkt[13], rxpkt[14], rxpkt[15]); } -/** - * ks8851_rx_skb - receive skbuff - * @ks: The device state. - * @skb: The skbuff - */ -static void ks8851_rx_skb(struct ks8851_net *ks, struct sk_buff *skb) -{ - ks->rx_skb(ks, skb); -} - /** * ks8851_rx_pkts - receive packets from the host * @ks: The device information. @@ -309,7 +299,7 @@ static void ks8851_rx_pkts(struct ks8851_net *ks) ks8851_dbg_dumpkkt(ks, rxpkt); skb->protocol = eth_type_trans(skb, ks->netdev); - ks8851_rx_skb(ks, skb); + netif_rx(skb); ks->netdev->stats.rx_packets++; ks->netdev->stats.rx_bytes += rxlen; diff --git a/drivers/net/ethernet/micrel/ks8851_par.c b/drivers/net/ethernet/micrel/ks8851_par.c index 2a7f29854267..381b9cd285eb 100644 --- a/drivers/net/ethernet/micrel/ks8851_par.c +++ b/drivers/net/ethernet/micrel/ks8851_par.c @@ -210,16 +210,6 @@ static void ks8851_wrfifo_par(struct ks8851_net *ks, struct sk_buff *txp, iowrite16_rep(ksp->hw_addr, txp->data, len / 2); } -/** - * ks8851_rx_skb_par - receive skbuff - * @ks: The device state. - * @skb: The skbuff - */ -static void ks8851_rx_skb_par(struct ks8851_net *ks, struct sk_buff *skb) -{ - netif_rx(skb); -} - static unsigned int ks8851_rdreg16_par_txqcr(struct ks8851_net *ks) { return ks8851_rdreg16_par(ks, KS_TXQCR); @@ -298,7 +288,6 @@ static int ks8851_probe_par(struct platform_device *pdev) ks->rdfifo = ks8851_rdfifo_par; ks->wrfifo = ks8851_wrfifo_par; ks->start_xmit = ks8851_start_xmit_par; - ks->rx_skb = ks8851_rx_skb_par; #define STD_IRQ (IRQ_LCI | /* Link Change */ \ IRQ_RXI | /* RX done */ \ diff --git a/drivers/net/ethernet/micrel/ks8851_spi.c b/drivers/net/ethernet/micrel/ks8851_spi.c index 2f803377c9f9..670c1de966db 100644 --- a/drivers/net/ethernet/micrel/ks8851_spi.c +++ b/drivers/net/ethernet/micrel/ks8851_spi.c @@ -298,16 +298,6 @@ static unsigned int calc_txlen(unsigned int len) return ALIGN(len + 4, 4); } -/** - * ks8851_rx_skb_spi - receive skbuff - * @ks: The device state - * @skb: The skbuff - */ -static void ks8851_rx_skb_spi(struct ks8851_net *ks, struct sk_buff *skb) -{ - netif_rx(skb); -} - /** * ks8851_tx_work - process tx packet(s) * @work: The work strucutre what was scheduled. @@ -435,7 +425,6 @@ static int ks8851_probe_spi(struct spi_device *spi) ks->rdfifo = ks8851_rdfifo_spi; ks->wrfifo = ks8851_wrfifo_spi; ks->start_xmit = ks8851_start_xmit_spi; - ks->rx_skb = ks8851_rx_skb_spi; ks->flush_tx_work = ks8851_flush_tx_work_spi; #define STD_IRQ (IRQ_LCI | /* Link Change */ \ -- cgit v1.2.3 From be0384bf599cf1eb8d337517feeb732d71f75a6f Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Fri, 5 Apr 2024 22:30:40 +0200 Subject: net: ks8851: Handle softirqs at the end of IRQ thread to fix hang The ks8851_irq() thread may call ks8851_rx_pkts() in case there are any packets in the MAC FIFO, which calls netif_rx(). This netif_rx() implementation is guarded by local_bh_disable() and local_bh_enable(). The local_bh_enable() may call do_softirq() to run softirqs in case any are pending. One of the softirqs is net_rx_action, which ultimately reaches the driver .start_xmit callback. If that happens, the system hangs. The entire call chain is below: ks8851_start_xmit_par from netdev_start_xmit netdev_start_xmit from dev_hard_start_xmit dev_hard_start_xmit from sch_direct_xmit sch_direct_xmit from __dev_queue_xmit __dev_queue_xmit from __neigh_update __neigh_update from neigh_update neigh_update from arp_process.constprop.0 arp_process.constprop.0 from __netif_receive_skb_one_core __netif_receive_skb_one_core from process_backlog process_backlog from __napi_poll.constprop.0 __napi_poll.constprop.0 from net_rx_action net_rx_action from __do_softirq __do_softirq from call_with_stack call_with_stack from do_softirq do_softirq from __local_bh_enable_ip __local_bh_enable_ip from netif_rx netif_rx from ks8851_irq ks8851_irq from irq_thread_fn irq_thread_fn from irq_thread irq_thread from kthread kthread from ret_from_fork The hang happens because ks8851_irq() first locks a spinlock in ks8851_par.c ks8851_lock_par() spin_lock_irqsave(&ksp->lock, ...) and with that spinlock locked, calls netif_rx(). Once the execution reaches ks8851_start_xmit_par(), it calls ks8851_lock_par() again which attempts to claim the already locked spinlock again, and the hang happens. Move the do_softirq() call outside of the spinlock protected section of ks8851_irq() by disabling BHs around the entire spinlock protected section of ks8851_irq() handler. Place local_bh_enable() outside of the spinlock protected section, so that it can trigger do_softirq() without the ks8851_par.c ks8851_lock_par() spinlock being held, and safely call ks8851_start_xmit_par() without attempting to lock the already locked spinlock. Since ks8851_irq() is protected by local_bh_disable()/local_bh_enable() now, replace netif_rx() with __netif_rx() which is not duplicating the local_bh_disable()/local_bh_enable() calls. Fixes: 797047f875b5 ("net: ks8851: Implement Parallel bus operations") Signed-off-by: Marek Vasut Link: https://lore.kernel.org/r/20240405203204.82062-2-marex@denx.de Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/micrel/ks8851_common.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/drivers/net/ethernet/micrel/ks8851_common.c b/drivers/net/ethernet/micrel/ks8851_common.c index 896d43bb8883..d4cdf3d4f552 100644 --- a/drivers/net/ethernet/micrel/ks8851_common.c +++ b/drivers/net/ethernet/micrel/ks8851_common.c @@ -299,7 +299,7 @@ static void ks8851_rx_pkts(struct ks8851_net *ks) ks8851_dbg_dumpkkt(ks, rxpkt); skb->protocol = eth_type_trans(skb, ks->netdev); - netif_rx(skb); + __netif_rx(skb); ks->netdev->stats.rx_packets++; ks->netdev->stats.rx_bytes += rxlen; @@ -330,6 +330,8 @@ static irqreturn_t ks8851_irq(int irq, void *_ks) unsigned long flags; unsigned int status; + local_bh_disable(); + ks8851_lock(ks, &flags); status = ks8851_rdreg16(ks, KS_ISR); @@ -406,6 +408,8 @@ static irqreturn_t ks8851_irq(int irq, void *_ks) if (status & IRQ_LCI) mii_check_link(&ks->mii); + local_bh_enable(); + return IRQ_HANDLED; } -- cgit v1.2.3 From 9c432404b9555c9444cbf6c8feaf52c0d8cad486 Mon Sep 17 00:00:00 2001 From: Kent Overstreet Date: Mon, 8 Apr 2024 22:32:08 -0400 Subject: bcachefs: fix eytzinger0_find_gt() - fix return types: promoting from unsigned to ssize_t does not do what we want here, and was pointless since the rest of the eytzinger code is u32 - nr, not size Signed-off-by: Kent Overstreet --- fs/bcachefs/eytzinger.h | 26 ++++++++++++++++++++------ 1 file changed, 20 insertions(+), 6 deletions(-) diff --git a/fs/bcachefs/eytzinger.h b/fs/bcachefs/eytzinger.h index ee0e2df33322..24840aee335c 100644 --- a/fs/bcachefs/eytzinger.h +++ b/fs/bcachefs/eytzinger.h @@ -242,8 +242,8 @@ static inline unsigned inorder_to_eytzinger0(unsigned i, unsigned size) (_i) = eytzinger0_next((_i), (_size))) /* return greatest node <= @search, or -1 if not found */ -static inline ssize_t eytzinger0_find_le(void *base, size_t nr, size_t size, - cmp_func_t cmp, const void *search) +static inline int eytzinger0_find_le(void *base, size_t nr, size_t size, + cmp_func_t cmp, const void *search) { unsigned i, n = 0; @@ -256,18 +256,32 @@ static inline ssize_t eytzinger0_find_le(void *base, size_t nr, size_t size, } while (n < nr); if (n & 1) { - /* @i was greater than @search, return previous node: */ + /* + * @i was greater than @search, return previous node: + * + * if @i was leftmost/smallest element, + * eytzinger0_prev(eytzinger0_first())) returns -1, as expected + */ return eytzinger0_prev(i, nr); } else { return i; } } -static inline ssize_t eytzinger0_find_gt(void *base, size_t nr, size_t size, - cmp_func_t cmp, const void *search) +static inline int eytzinger0_find_gt(void *base, size_t nr, size_t size, + cmp_func_t cmp, const void *search) { ssize_t idx = eytzinger0_find_le(base, nr, size, cmp, search); - return eytzinger0_next(idx, size); + + /* + * if eytitzinger0_find_le() returned -1 - no element was <= search - we + * want to return the first element; next/prev identities mean this work + * as expected + * + * similarly if find_le() returns last element, we should return -1; + * identities mean this all works out: + */ + return eytzinger0_next(idx, nr); } #define eytzinger0_find(base, nr, size, _cmp, search) \ -- cgit v1.2.3 From b46f4eaa4f0ec38909fb0072eea3aeddb32f954e Mon Sep 17 00:00:00 2001 From: Kuniyuki Iwashima Date: Fri, 5 Apr 2024 15:10:57 -0700 Subject: af_unix: Clear stale u->oob_skb. syzkaller started to report deadlock of unix_gc_lock after commit 4090fa373f0e ("af_unix: Replace garbage collection algorithm."), but it just uncovers the bug that has been there since commit 314001f0bf92 ("af_unix: Add OOB support"). The repro basically does the following. from socket import * from array import array c1, c2 = socketpair(AF_UNIX, SOCK_STREAM) c1.sendmsg([b'a'], [(SOL_SOCKET, SCM_RIGHTS, array("i", [c2.fileno()]))], MSG_OOB) c2.recv(1) # blocked as no normal data in recv queue c2.close() # done async and unblock recv() c1.close() # done async and trigger GC A socket sends its file descriptor to itself as OOB data and tries to receive normal data, but finally recv() fails due to async close(). The problem here is wrong handling of OOB skb in manage_oob(). When recvmsg() is called without MSG_OOB, manage_oob() is called to check if the peeked skb is OOB skb. In such a case, manage_oob() pops it out of the receive queue but does not clear unix_sock(sk)->oob_skb. This is wrong in terms of uAPI. Let's say we send "hello" with MSG_OOB, and "world" without MSG_OOB. The 'o' is handled as OOB data. When recv() is called twice without MSG_OOB, the OOB data should be lost. >>> from socket import * >>> c1, c2 = socketpair(AF_UNIX, SOCK_STREAM, 0) >>> c1.send(b'hello', MSG_OOB) # 'o' is OOB data 5 >>> c1.send(b'world') 5 >>> c2.recv(5) # OOB data is not received b'hell' >>> c2.recv(5) # OOB date is skipped b'world' >>> c2.recv(5, MSG_OOB) # This should return an error b'o' In the same situation, TCP actually returns -EINVAL for the last recv(). Also, if we do not clear unix_sk(sk)->oob_skb, unix_poll() always set EPOLLPRI even though the data has passed through by previous recv(). To avoid these issues, we must clear unix_sk(sk)->oob_skb when dequeuing it from recv queue. The reason why the old GC did not trigger the deadlock is because the old GC relied on the receive queue to detect the loop. When it is triggered, the socket with OOB data is marked as GC candidate because file refcount == inflight count (1). However, after traversing all inflight sockets, the socket still has a positive inflight count (1), thus the socket is excluded from candidates. Then, the old GC lose the chance to garbage-collect the socket. With the old GC, the repro continues to create true garbage that will never be freed nor detected by kmemleak as it's linked to the global inflight list. That's why we couldn't even notice the issue. Fixes: 314001f0bf92 ("af_unix: Add OOB support") Reported-by: syzbot+7f7f201cc2668a8fd169@syzkaller.appspotmail.com Closes: https://syzkaller.appspot.com/bug?extid=7f7f201cc2668a8fd169 Signed-off-by: Kuniyuki Iwashima Reviewed-by: Eric Dumazet Link: https://lore.kernel.org/r/20240405221057.2406-1-kuniyu@amazon.com Signed-off-by: Jakub Kicinski --- net/unix/af_unix.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c index 5b41e2321209..d032eb5fa6df 100644 --- a/net/unix/af_unix.c +++ b/net/unix/af_unix.c @@ -2665,7 +2665,9 @@ static struct sk_buff *manage_oob(struct sk_buff *skb, struct sock *sk, } } else if (!(flags & MSG_PEEK)) { skb_unlink(skb, &sk->sk_receive_queue); - consume_skb(skb); + WRITE_ONCE(u->oob_skb, NULL); + if (!WARN_ON_ONCE(skb_unref(skb))) + kfree_skb(skb); skb = skb_peek(&sk->sk_receive_queue); } } -- cgit v1.2.3 From 718c4fb221dbeff9072810841b949413c5ffc345 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Mon, 8 Apr 2024 16:42:43 +1000 Subject: nouveau: fix devinit paths to only handle display on GSP. This reverts: nouveau/gsp: don't check devinit disable on GSP. and applies a further fix. It turns out the open gpu driver, checks this register, but only for display. Match that behaviour and in the turing path only disable the display block. (ampere already only does displays). Fixes: 5d4e8ae6e57b ("nouveau/gsp: don't check devinit disable on GSP.") Reviewed-by: Danilo Krummrich Signed-off-by: Dave Airlie Link: https://patchwork.freedesktop.org/patch/msgid/20240408064243.2219527-1-airlied@gmail.com --- drivers/gpu/drm/nouveau/nvkm/subdev/devinit/gm107.c | 12 ++++++++---- drivers/gpu/drm/nouveau/nvkm/subdev/devinit/r535.c | 1 + 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/devinit/gm107.c b/drivers/gpu/drm/nouveau/nvkm/subdev/devinit/gm107.c index 7bcbc4895ec2..271bfa038f5b 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/devinit/gm107.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/devinit/gm107.c @@ -25,6 +25,7 @@ #include #include +#include void gm107_devinit_disable(struct nvkm_devinit *init) @@ -33,10 +34,13 @@ gm107_devinit_disable(struct nvkm_devinit *init) u32 r021c00 = nvkm_rd32(device, 0x021c00); u32 r021c04 = nvkm_rd32(device, 0x021c04); - if (r021c00 & 0x00000001) - nvkm_subdev_disable(device, NVKM_ENGINE_CE, 0); - if (r021c00 & 0x00000004) - nvkm_subdev_disable(device, NVKM_ENGINE_CE, 2); + /* gsp only wants to enable/disable display */ + if (!nvkm_gsp_rm(device->gsp)) { + if (r021c00 & 0x00000001) + nvkm_subdev_disable(device, NVKM_ENGINE_CE, 0); + if (r021c00 & 0x00000004) + nvkm_subdev_disable(device, NVKM_ENGINE_CE, 2); + } if (r021c04 & 0x00000001) nvkm_subdev_disable(device, NVKM_ENGINE_DISP, 0); } diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/devinit/r535.c b/drivers/gpu/drm/nouveau/nvkm/subdev/devinit/r535.c index 11b4c9c274a1..666eb93b1742 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/devinit/r535.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/devinit/r535.c @@ -41,6 +41,7 @@ r535_devinit_new(const struct nvkm_devinit_func *hw, rm->dtor = r535_devinit_dtor; rm->post = hw->post; + rm->disable = hw->disable; ret = nv50_devinit_new_(rm, device, type, inst, pdevinit); if (ret) -- cgit v1.2.3 From 4fe82aedeb8a8cb09bfa60f55ab57b5c10a74ac4 Mon Sep 17 00:00:00 2001 From: Pavel Begunkov Date: Mon, 8 Apr 2024 18:11:09 +0100 Subject: io_uring/net: restore msg_control on sendzc retry cac9e4418f4cb ("io_uring/net: save msghdr->msg_control for retries") reinstatiates msg_control before every __sys_sendmsg_sock(), since the function can overwrite the value in msghdr. We need to do same for zerocopy sendmsg. Cc: stable@vger.kernel.org Fixes: 493108d95f146 ("io_uring/net: zerocopy sendmsg") Link: https://github.com/axboe/liburing/issues/1067 Signed-off-by: Pavel Begunkov Link: https://lore.kernel.org/r/cc1d5d9df0576fa66ddad4420d240a98a020b267.1712596179.git.asml.silence@gmail.com Signed-off-by: Jens Axboe --- io_uring/net.c | 1 + 1 file changed, 1 insertion(+) diff --git a/io_uring/net.c b/io_uring/net.c index 1e7665ff6ef7..4afb475d4197 100644 --- a/io_uring/net.c +++ b/io_uring/net.c @@ -1276,6 +1276,7 @@ int io_sendmsg_zc(struct io_kiocb *req, unsigned int issue_flags) if (req_has_async_data(req)) { kmsg = req->async_data; + kmsg->msg.msg_control_user = sr->msg_control; } else { ret = io_sendmsg_copy_hdr(req, &iomsg); if (ret) -- cgit v1.2.3 From 359571c327a726d622786aef3833637dacfd5d38 Mon Sep 17 00:00:00 2001 From: Kent Overstreet Date: Tue, 9 Apr 2024 00:02:47 -0400 Subject: bcachefs: Fix check_topology() when using node scan shoot down journal keys _before_ populating journal keys with pointers to scanned nodes Signed-off-by: Kent Overstreet --- fs/bcachefs/btree_gc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/bcachefs/btree_gc.c b/fs/bcachefs/btree_gc.c index 6280da1244b5..a1c2c0ffb0cc 100644 --- a/fs/bcachefs/btree_gc.c +++ b/fs/bcachefs/btree_gc.c @@ -544,12 +544,12 @@ reconstruct_root: bch2_btree_root_alloc_fake(c, i, 0); } else { bch2_btree_root_alloc_fake(c, i, 1); + bch2_shoot_down_journal_keys(c, i, 1, BTREE_MAX_DEPTH, POS_MIN, SPOS_MAX); ret = bch2_get_scanned_nodes(c, i, 0, POS_MIN, SPOS_MAX); if (ret) break; } - bch2_shoot_down_journal_keys(c, i, 1, BTREE_MAX_DEPTH, POS_MIN, SPOS_MAX); reconstructed_root = true; } -- cgit v1.2.3 From 5ab4beb759c05c74fb385ac5ca0ade5d3db67975 Mon Sep 17 00:00:00 2001 From: Kent Overstreet Date: Tue, 9 Apr 2024 00:49:39 -0400 Subject: bcachefs: Don't scan for btree nodes when we can reconstruct Signed-off-by: Kent Overstreet --- fs/bcachefs/bcachefs_format.h | 14 ++++++++++++++ fs/bcachefs/btree_gc.c | 11 ++++++++--- fs/bcachefs/btree_node_scan.c | 8 +++++++- fs/bcachefs/recovery.c | 14 -------------- 4 files changed, 29 insertions(+), 18 deletions(-) diff --git a/fs/bcachefs/bcachefs_format.h b/fs/bcachefs/bcachefs_format.h index 63102992d955..364ae42022af 100644 --- a/fs/bcachefs/bcachefs_format.h +++ b/fs/bcachefs/bcachefs_format.h @@ -1535,6 +1535,20 @@ enum btree_id { BTREE_ID_NR }; +static inline bool btree_id_is_alloc(enum btree_id id) +{ + switch (id) { + case BTREE_ID_alloc: + case BTREE_ID_backpointers: + case BTREE_ID_need_discard: + case BTREE_ID_freespace: + case BTREE_ID_bucket_gens: + return true; + default: + return false; + } +} + #define BTREE_MAX_DEPTH 4U /* Btree nodes */ diff --git a/fs/bcachefs/btree_gc.c b/fs/bcachefs/btree_gc.c index a1c2c0ffb0cc..d2555da55c6d 100644 --- a/fs/bcachefs/btree_gc.c +++ b/fs/bcachefs/btree_gc.c @@ -368,11 +368,16 @@ again: buf.buf)) { bch2_btree_node_evict(trans, cur_k.k); cur = NULL; - ret = bch2_run_explicit_recovery_pass(c, BCH_RECOVERY_PASS_scan_for_btree_nodes) ?: - bch2_journal_key_delete(c, b->c.btree_id, - b->c.level, cur_k.k->k.p); + ret = bch2_journal_key_delete(c, b->c.btree_id, + b->c.level, cur_k.k->k.p); if (ret) break; + + if (!btree_id_is_alloc(b->c.btree_id)) { + ret = bch2_run_explicit_recovery_pass(c, BCH_RECOVERY_PASS_scan_for_btree_nodes); + if (ret) + break; + } continue; } diff --git a/fs/bcachefs/btree_node_scan.c b/fs/bcachefs/btree_node_scan.c index 3f33be7e5e5c..a7d0593b3871 100644 --- a/fs/bcachefs/btree_node_scan.c +++ b/fs/bcachefs/btree_node_scan.c @@ -133,6 +133,9 @@ static void try_read_btree_node(struct find_btree_nodes *f, struct bch_dev *ca, if (le64_to_cpu(bn->magic) != bset_magic(c)) return; + if (btree_id_is_alloc(BTREE_NODE_ID(bn))) + return; + rcu_read_lock(); struct found_btree_node n = { .btree_id = BTREE_NODE_ID(bn), @@ -290,7 +293,7 @@ again: found_btree_node_to_text(&buf, c, n); bch_err(c, "%s", buf.buf); printbuf_exit(&buf); - return -1; + return -BCH_ERR_fsck_repair_unimplemented; } } @@ -436,6 +439,9 @@ bool bch2_btree_has_scanned_nodes(struct bch_fs *c, enum btree_id btree) int bch2_get_scanned_nodes(struct bch_fs *c, enum btree_id btree, unsigned level, struct bpos node_min, struct bpos node_max) { + if (btree_id_is_alloc(btree)) + return 0; + struct find_btree_nodes *f = &c->found_btree_nodes; int ret = bch2_run_explicit_recovery_pass(c, BCH_RECOVERY_PASS_scan_for_btree_nodes); diff --git a/fs/bcachefs/recovery.c b/fs/bcachefs/recovery.c index b76c16152579..0f328aba9760 100644 --- a/fs/bcachefs/recovery.c +++ b/fs/bcachefs/recovery.c @@ -47,20 +47,6 @@ void bch2_btree_lost_data(struct bch_fs *c, enum btree_id btree) } } -static bool btree_id_is_alloc(enum btree_id id) -{ - switch (id) { - case BTREE_ID_alloc: - case BTREE_ID_backpointers: - case BTREE_ID_need_discard: - case BTREE_ID_freespace: - case BTREE_ID_bucket_gens: - return true; - default: - return false; - } -} - /* for -o reconstruct_alloc: */ static void bch2_reconstruct_alloc(struct bch_fs *c) { -- cgit v1.2.3 From 80e9963fb3b5509dfcabe9652d56bf4b35542055 Mon Sep 17 00:00:00 2001 From: Nianyao Tang Date: Sat, 6 Apr 2024 02:27:37 +0000 Subject: irqchip/gic-v3-its: Fix VSYNC referencing an unmapped VPE on GIC v4.1 As per the GICv4.1 spec (Arm IHI 0069H, 5.3.19): "A VMAPP with {V, Alloc}=={0, x} is self-synchronizing, This means the ITS command queue does not show the command as consumed until all of its effects are completed." Furthermore, VSYNC is allowed to deliver an SError when referencing a non existent VPE. By these definitions, a VMAPP followed by a VSYNC is a bug, as the later references a VPE that has been unmapped by the former. Fix it by eliding the VSYNC in this scenario. Fixes: 64edfaa9a234 ("irqchip/gic-v4.1: Implement the v4.1 flavour of VMAPP") Signed-off-by: Nianyao Tang Signed-off-by: Thomas Gleixner Reviewed-by: Marc Zyngier Reviewed-by: Zenghui Yu Link: https://lore.kernel.org/r/20240406022737.3898763-1-tangnianyao@huawei.com --- drivers/irqchip/irq-gic-v3-its.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/drivers/irqchip/irq-gic-v3-its.c b/drivers/irqchip/irq-gic-v3-its.c index fca888b36680..2a537cbfcb07 100644 --- a/drivers/irqchip/irq-gic-v3-its.c +++ b/drivers/irqchip/irq-gic-v3-its.c @@ -786,6 +786,7 @@ static struct its_vpe *its_build_vmapp_cmd(struct its_node *its, struct its_cmd_block *cmd, struct its_cmd_desc *desc) { + struct its_vpe *vpe = valid_vpe(its, desc->its_vmapp_cmd.vpe); unsigned long vpt_addr, vconf_addr; u64 target; bool alloc; @@ -798,6 +799,11 @@ static struct its_vpe *its_build_vmapp_cmd(struct its_node *its, if (is_v4_1(its)) { alloc = !atomic_dec_return(&desc->its_vmapp_cmd.vpe->vmapp_count); its_encode_alloc(cmd, alloc); + /* + * Unmapping a VPE is self-synchronizing on GICv4.1, + * no need to issue a VSYNC. + */ + vpe = NULL; } goto out; @@ -832,7 +838,7 @@ static struct its_vpe *its_build_vmapp_cmd(struct its_node *its, out: its_fixup_cmd(cmd); - return valid_vpe(its, desc->its_vmapp_cmd.vpe); + return vpe; } static struct its_vpe *its_build_vmapti_cmd(struct its_node *its, -- cgit v1.2.3 From faf23006185e777db18912685922c5ddb2df383f Mon Sep 17 00:00:00 2001 From: Geetha sowjanya Date: Mon, 8 Apr 2024 12:06:43 +0530 Subject: octeontx2-af: Fix NIX SQ mode and BP config NIX SQ mode and link backpressure configuration is required for all platforms. But in current driver this code is wrongly placed under specific platform check. This patch fixes the issue by moving the code out of platform check. Fixes: 5d9b976d4480 ("octeontx2-af: Support fixed transmit scheduler topology") Signed-off-by: Geetha sowjanya Link: https://lore.kernel.org/r/20240408063643.26288-1-gakula@marvell.com Signed-off-by: Paolo Abeni --- drivers/net/ethernet/marvell/octeontx2/af/rvu_nix.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/drivers/net/ethernet/marvell/octeontx2/af/rvu_nix.c b/drivers/net/ethernet/marvell/octeontx2/af/rvu_nix.c index d39001cdc707..00af8888e329 100644 --- a/drivers/net/ethernet/marvell/octeontx2/af/rvu_nix.c +++ b/drivers/net/ethernet/marvell/octeontx2/af/rvu_nix.c @@ -4819,18 +4819,18 @@ static int rvu_nix_block_init(struct rvu *rvu, struct nix_hw *nix_hw) */ rvu_write64(rvu, blkaddr, NIX_AF_CFG, rvu_read64(rvu, blkaddr, NIX_AF_CFG) | 0x40ULL); + } - /* Set chan/link to backpressure TL3 instead of TL2 */ - rvu_write64(rvu, blkaddr, NIX_AF_PSE_CHANNEL_LEVEL, 0x01); + /* Set chan/link to backpressure TL3 instead of TL2 */ + rvu_write64(rvu, blkaddr, NIX_AF_PSE_CHANNEL_LEVEL, 0x01); - /* Disable SQ manager's sticky mode operation (set TM6 = 0) - * This sticky mode is known to cause SQ stalls when multiple - * SQs are mapped to same SMQ and transmitting pkts at a time. - */ - cfg = rvu_read64(rvu, blkaddr, NIX_AF_SQM_DBG_CTL_STATUS); - cfg &= ~BIT_ULL(15); - rvu_write64(rvu, blkaddr, NIX_AF_SQM_DBG_CTL_STATUS, cfg); - } + /* Disable SQ manager's sticky mode operation (set TM6 = 0) + * This sticky mode is known to cause SQ stalls when multiple + * SQs are mapped to same SMQ and transmitting pkts at a time. + */ + cfg = rvu_read64(rvu, blkaddr, NIX_AF_SQM_DBG_CTL_STATUS); + cfg &= ~BIT_ULL(15); + rvu_write64(rvu, blkaddr, NIX_AF_SQM_DBG_CTL_STATUS, cfg); ltdefs = rvu->kpu.lt_def; /* Calibrate X2P bus to check if CGX/LBK links are fine */ -- cgit v1.2.3 From 25ab9c40e77ed4d73995fb6eef514e2e9c421dab Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Tue, 9 Apr 2024 14:33:47 +0300 Subject: ASoC: SOF: Intel: tgl: Add fw_regs area to debugfs map for IPC4 Expose the firmware registers via debugfs. it can be of great help while debugging complex issues. The area is only available with IPC4. Signed-off-by: Peter Ujfalusi Reviewed-by: Bard Liao Reviewed-by: Pierre-Louis Bossart Link: https://msgid.link/r/20240409113349.21623-2-peter.ujfalusi@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/intel/tgl.c | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/sound/soc/sof/intel/tgl.c b/sound/soc/sof/intel/tgl.c index c2bb04c89b9d..6cda47a78118 100644 --- a/sound/soc/sof/intel/tgl.c +++ b/sound/soc/sof/intel/tgl.c @@ -22,6 +22,13 @@ static const struct snd_sof_debugfs_map tgl_dsp_debugfs[] = { {"dsp", HDA_DSP_BAR, 0, 0x10000, SOF_DEBUGFS_ACCESS_ALWAYS}, }; +static const struct snd_sof_debugfs_map tgl_ipc4_dsp_debugfs[] = { + {"hda", HDA_DSP_HDA_BAR, 0, 0x4000, SOF_DEBUGFS_ACCESS_ALWAYS}, + {"pp", HDA_DSP_PP_BAR, 0, 0x1000, SOF_DEBUGFS_ACCESS_ALWAYS}, + {"dsp", HDA_DSP_BAR, 0, 0x10000, SOF_DEBUGFS_ACCESS_ALWAYS}, + {"fw_regs", HDA_DSP_BAR, SRAM_WINDOW_OFFSET(0), 0x1000, SOF_DEBUGFS_ACCESS_D0_ONLY}, +}; + static int tgl_dsp_core_get(struct snd_sof_dev *sdev, int core) { const struct sof_ipc_pm_ops *pm_ops = sdev->ipc->ops->pm; @@ -75,6 +82,8 @@ int sof_tgl_ops_init(struct snd_sof_dev *sdev) /* debug */ sof_tgl_ops.ipc_dump = cnl_ipc_dump; + sof_tgl_ops.debug_map = tgl_dsp_debugfs; + sof_tgl_ops.debug_map_count = ARRAY_SIZE(tgl_dsp_debugfs); sof_tgl_ops.set_power_state = hda_dsp_set_power_state_ipc3; } @@ -105,6 +114,8 @@ int sof_tgl_ops_init(struct snd_sof_dev *sdev) /* debug */ sof_tgl_ops.ipc_dump = cnl_ipc4_dump; sof_tgl_ops.dbg_dump = hda_ipc4_dsp_dump; + sof_tgl_ops.debug_map = tgl_ipc4_dsp_debugfs; + sof_tgl_ops.debug_map_count = ARRAY_SIZE(tgl_ipc4_dsp_debugfs); sof_tgl_ops.set_power_state = hda_dsp_set_power_state_ipc4; } @@ -112,10 +123,6 @@ int sof_tgl_ops_init(struct snd_sof_dev *sdev) /* set DAI driver ops */ hda_set_dai_drv_ops(sdev, &sof_tgl_ops); - /* debug */ - sof_tgl_ops.debug_map = tgl_dsp_debugfs; - sof_tgl_ops.debug_map_count = ARRAY_SIZE(tgl_dsp_debugfs); - /* pre/post fw run */ sof_tgl_ops.post_fw_run = hda_dsp_post_fw_run; -- cgit v1.2.3 From d33a369ddad522eff40c6b9687db1488e19729d6 Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Tue, 9 Apr 2024 14:33:48 +0300 Subject: ASoC: SOF: Intel: mtl: Add fw_regs area to debugfs map Expose the firmware registers via debugfs. it can be of great help while debugging complex issues. Signed-off-by: Peter Ujfalusi Reviewed-by: Bard Liao Reviewed-by: Pierre-Louis Bossart Link: https://msgid.link/r/20240409113349.21623-3-peter.ujfalusi@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/intel/mtl.c | 1 + 1 file changed, 1 insertion(+) diff --git a/sound/soc/sof/intel/mtl.c b/sound/soc/sof/intel/mtl.c index dc203505536c..5d3b2d4be78a 100644 --- a/sound/soc/sof/intel/mtl.c +++ b/sound/soc/sof/intel/mtl.c @@ -25,6 +25,7 @@ static const struct snd_sof_debugfs_map mtl_dsp_debugfs[] = { {"hda", HDA_DSP_HDA_BAR, 0, 0x4000, SOF_DEBUGFS_ACCESS_ALWAYS}, {"pp", HDA_DSP_PP_BAR, 0, 0x1000, SOF_DEBUGFS_ACCESS_ALWAYS}, {"dsp", HDA_DSP_BAR, 0, 0x10000, SOF_DEBUGFS_ACCESS_ALWAYS}, + {"fw_regs", HDA_DSP_BAR, MTL_SRAM_WINDOW_OFFSET(0), 0x1000, SOF_DEBUGFS_ACCESS_D0_ONLY}, }; static void mtl_ipc_host_done(struct snd_sof_dev *sdev) -- cgit v1.2.3 From 61faefa220262de60d652dd6b91fdcb7ecae2258 Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Tue, 9 Apr 2024 14:33:49 +0300 Subject: ASoC: SOF: Intel: lnl: Add fw_regs area to debugfs map Expose the firmware registers via debugfs. it can be of great help while debugging complex issues. Signed-off-by: Peter Ujfalusi Reviewed-by: Bard Liao Reviewed-by: Pierre-Louis Bossart Link: https://msgid.link/r/20240409113349.21623-4-peter.ujfalusi@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/intel/lnl.c | 1 + 1 file changed, 1 insertion(+) diff --git a/sound/soc/sof/intel/lnl.c b/sound/soc/sof/intel/lnl.c index 8aa5430e9576..ac64a9f9cf9d 100644 --- a/sound/soc/sof/intel/lnl.c +++ b/sound/soc/sof/intel/lnl.c @@ -28,6 +28,7 @@ static const struct snd_sof_debugfs_map lnl_dsp_debugfs[] = { {"hda", HDA_DSP_HDA_BAR, 0, 0x4000, SOF_DEBUGFS_ACCESS_ALWAYS}, {"pp", HDA_DSP_PP_BAR, 0, 0x1000, SOF_DEBUGFS_ACCESS_ALWAYS}, {"dsp", HDA_DSP_BAR, 0, 0x10000, SOF_DEBUGFS_ACCESS_ALWAYS}, + {"fw_regs", HDA_DSP_BAR, MTL_SRAM_WINDOW_OFFSET(0), 0x1000, SOF_DEBUGFS_ACCESS_D0_ONLY}, }; /* this helps allows the DSP to setup DMIC/SSP */ -- cgit v1.2.3 From 74043489fcb5e5ca4074133582b5b8011b67f9e7 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Mon, 8 Apr 2024 09:42:02 +0200 Subject: ipv6: fib: hide unused 'pn' variable When CONFIG_IPV6_SUBTREES is disabled, the only user is hidden, causing a 'make W=1' warning: net/ipv6/ip6_fib.c: In function 'fib6_add': net/ipv6/ip6_fib.c:1388:32: error: variable 'pn' set but not used [-Werror=unused-but-set-variable] Add another #ifdef around the variable declaration, matching the other uses in this file. Fixes: 66729e18df08 ("[IPV6] ROUTE: Make sure we have fn->leaf when adding a node on subtree.") Link: https://lore.kernel.org/netdev/20240322131746.904943-1-arnd@kernel.org/ Reviewed-by: David Ahern Signed-off-by: Arnd Bergmann Reviewed-by: Eric Dumazet Link: https://lore.kernel.org/r/20240408074219.3030256-1-arnd@kernel.org Signed-off-by: Paolo Abeni --- net/ipv6/ip6_fib.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/net/ipv6/ip6_fib.c b/net/ipv6/ip6_fib.c index 7209419cfb0e..c1f62352a481 100644 --- a/net/ipv6/ip6_fib.c +++ b/net/ipv6/ip6_fib.c @@ -1385,7 +1385,10 @@ int fib6_add(struct fib6_node *root, struct fib6_info *rt, struct nl_info *info, struct netlink_ext_ack *extack) { struct fib6_table *table = rt->fib6_table; - struct fib6_node *fn, *pn = NULL; + struct fib6_node *fn; +#ifdef CONFIG_IPV6_SUBTREES + struct fib6_node *pn = NULL; +#endif int err = -ENOMEM; int allow_create = 1; int replace_required = 0; @@ -1409,9 +1412,9 @@ int fib6_add(struct fib6_node *root, struct fib6_info *rt, goto out; } +#ifdef CONFIG_IPV6_SUBTREES pn = fn; -#ifdef CONFIG_IPV6_SUBTREES if (rt->fib6_src.plen) { struct fib6_node *sn; -- cgit v1.2.3 From cf1b7201df59fb936f40f4a807433fe3f2ce310a Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Mon, 8 Apr 2024 09:42:03 +0200 Subject: ipv4/route: avoid unused-but-set-variable warning The log_martians variable is only used in an #ifdef, causing a 'make W=1' warning with gcc: net/ipv4/route.c: In function 'ip_rt_send_redirect': net/ipv4/route.c:880:13: error: variable 'log_martians' set but not used [-Werror=unused-but-set-variable] Change the #ifdef to an equivalent IS_ENABLED() to let the compiler see where the variable is used. Fixes: 30038fc61adf ("net: ip_rt_send_redirect() optimization") Reviewed-by: David Ahern Signed-off-by: Arnd Bergmann Reviewed-by: Eric Dumazet Link: https://lore.kernel.org/r/20240408074219.3030256-2-arnd@kernel.org Signed-off-by: Paolo Abeni --- net/ipv4/route.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/net/ipv4/route.c b/net/ipv4/route.c index c8f76f56dc16..d36ace160d42 100644 --- a/net/ipv4/route.c +++ b/net/ipv4/route.c @@ -926,13 +926,11 @@ void ip_rt_send_redirect(struct sk_buff *skb) icmp_send(skb, ICMP_REDIRECT, ICMP_REDIR_HOST, gw); peer->rate_last = jiffies; ++peer->n_redirects; -#ifdef CONFIG_IP_ROUTE_VERBOSE - if (log_martians && + if (IS_ENABLED(CONFIG_IP_ROUTE_VERBOSE) && log_martians && peer->n_redirects == ip_rt_redirect_number) net_warn_ratelimited("host %pI4/if%d ignores redirects for %pI4 to %pI4\n", &ip_hdr(skb)->saddr, inet_iif(skb), &ip_hdr(skb)->daddr, &gw); -#endif } out_put_peer: inet_putpeer(peer); -- cgit v1.2.3 From 638441bed666619b4275f68bbca9d1cd731a2063 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Sat, 16 Mar 2024 12:30:09 +0300 Subject: serial: 8250_lpc18xx: disable clks on error in probe() Goto the clean up path to clean up a couple clocks before returning on this error path. Fixes: 0087b9e694ee ("serial: 8250_lpc18xx: Switch to use uart_read_port_properties()") Signed-off-by: Dan Carpenter Reviewed-by: Andy Shevchenko Link: https://lore.kernel.org/r/92646c10-e0b5-4117-a9ac-ce9987d33ce3@moroto.mountain Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/8250/8250_lpc18xx.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/tty/serial/8250/8250_lpc18xx.c b/drivers/tty/serial/8250/8250_lpc18xx.c index 7984ee05af1d..47e1a056a60c 100644 --- a/drivers/tty/serial/8250/8250_lpc18xx.c +++ b/drivers/tty/serial/8250/8250_lpc18xx.c @@ -151,7 +151,7 @@ static int lpc18xx_serial_probe(struct platform_device *pdev) ret = uart_read_port_properties(&uart.port); if (ret) - return ret; + goto dis_uart_clk; uart.port.iotype = UPIO_MEM32; uart.port.regshift = 2; -- cgit v1.2.3 From 7dfae6cbadc1ac99e38ad19fb08810b31ff167be Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Sun, 17 Mar 2024 22:41:23 +0100 Subject: serial: 8250_dw: Revert: Do not reclock if already at correct rate Commit e5d6bd25f93d ("serial: 8250_dw: Do not reclock if already at correct rate") breaks the dw UARTs on Intel Bay Trail (BYT) and Cherry Trail (CHT) SoCs. Before this change the RTL8732BS Bluetooth HCI which is found connected over the dw UART on both BYT and CHT boards works properly: Bluetooth: hci0: RTL: examining hci_ver=06 hci_rev=000b lmp_ver=06 lmp_subver=8723 Bluetooth: hci0: RTL: rom_version status=0 version=1 Bluetooth: hci0: RTL: loading rtl_bt/rtl8723bs_fw.bin Bluetooth: hci0: RTL: loading rtl_bt/rtl8723bs_config-OBDA8723.bin Bluetooth: hci0: RTL: cfg_sz 64, total sz 24508 Bluetooth: hci0: RTL: fw version 0x365d462e where as after this change probing it fails: Bluetooth: hci0: RTL: examining hci_ver=06 hci_rev=000b lmp_ver=06 lmp_subver=8723 Bluetooth: hci0: RTL: rom_version status=0 version=1 Bluetooth: hci0: RTL: loading rtl_bt/rtl8723bs_fw.bin Bluetooth: hci0: RTL: loading rtl_bt/rtl8723bs_config-OBDA8723.bin Bluetooth: hci0: RTL: cfg_sz 64, total sz 24508 Bluetooth: hci0: command 0xfc20 tx timeout Bluetooth: hci0: RTL: download fw command failed (-110) Revert the changes to fix this regression. Fixes: e5d6bd25f93d ("serial: 8250_dw: Do not reclock if already at correct rate") Cc: stable@vger.kernel.org Cc: Peter Collingbourne Signed-off-by: Hans de Goede Reviewed-by: Andy Shevchenko Acked-by: Peter Collingbourne Link: https://lore.kernel.org/r/20240317214123.34482-1-hdegoede@redhat.com Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/8250/8250_dw.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/tty/serial/8250/8250_dw.c b/drivers/tty/serial/8250/8250_dw.c index a3acbf0f5da1..1300c92b8702 100644 --- a/drivers/tty/serial/8250/8250_dw.c +++ b/drivers/tty/serial/8250/8250_dw.c @@ -356,9 +356,9 @@ static void dw8250_set_termios(struct uart_port *p, struct ktermios *termios, long rate; int ret; + clk_disable_unprepare(d->clk); rate = clk_round_rate(d->clk, newrate); - if (rate > 0 && p->uartclk != rate) { - clk_disable_unprepare(d->clk); + if (rate > 0) { /* * Note that any clock-notifer worker will block in * serial8250_update_uartclk() until we are done. @@ -366,8 +366,8 @@ static void dw8250_set_termios(struct uart_port *p, struct ktermios *termios, ret = clk_set_rate(d->clk, newrate); if (!ret) p->uartclk = rate; - clk_prepare_enable(d->clk); } + clk_prepare_enable(d->clk); dw8250_do_set_termios(p, termios, old); } -- cgit v1.2.3 From 54c4ec5f8c471b7c1137a1f769648549c423c026 Mon Sep 17 00:00:00 2001 From: Emil Kronborg Date: Wed, 20 Mar 2024 12:15:36 +0000 Subject: serial: mxs-auart: add spinlock around changing cts state The uart_handle_cts_change() function in serial_core expects the caller to hold uport->lock. For example, I have seen the below kernel splat, when the Bluetooth driver is loaded on an i.MX28 board. [ 85.119255] ------------[ cut here ]------------ [ 85.124413] WARNING: CPU: 0 PID: 27 at /drivers/tty/serial/serial_core.c:3453 uart_handle_cts_change+0xb4/0xec [ 85.134694] Modules linked in: hci_uart bluetooth ecdh_generic ecc wlcore_sdio configfs [ 85.143314] CPU: 0 PID: 27 Comm: kworker/u3:0 Not tainted 6.6.3-00021-gd62a2f068f92 #1 [ 85.151396] Hardware name: Freescale MXS (Device Tree) [ 85.156679] Workqueue: hci0 hci_power_on [bluetooth] (...) [ 85.191765] uart_handle_cts_change from mxs_auart_irq_handle+0x380/0x3f4 [ 85.198787] mxs_auart_irq_handle from __handle_irq_event_percpu+0x88/0x210 (...) Cc: stable@vger.kernel.org Fixes: 4d90bb147ef6 ("serial: core: Document and assert lock requirements for irq helpers") Reviewed-by: Frank Li Signed-off-by: Emil Kronborg Link: https://lore.kernel.org/r/20240320121530.11348-1-emil.kronborg@protonmail.com Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/mxs-auart.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/drivers/tty/serial/mxs-auart.c b/drivers/tty/serial/mxs-auart.c index 4749331fe618..1e8853eae504 100644 --- a/drivers/tty/serial/mxs-auart.c +++ b/drivers/tty/serial/mxs-auart.c @@ -1086,11 +1086,13 @@ static void mxs_auart_set_ldisc(struct uart_port *port, static irqreturn_t mxs_auart_irq_handle(int irq, void *context) { - u32 istat; + u32 istat, stat; struct mxs_auart_port *s = context; u32 mctrl_temp = s->mctrl_prev; - u32 stat = mxs_read(s, REG_STAT); + uart_port_lock(&s->port); + + stat = mxs_read(s, REG_STAT); istat = mxs_read(s, REG_INTR); /* ack irq */ @@ -1126,6 +1128,8 @@ static irqreturn_t mxs_auart_irq_handle(int irq, void *context) istat &= ~AUART_INTR_TXIS; } + uart_port_unlock(&s->port); + return IRQ_HANDLED; } -- cgit v1.2.3 From 5555980571cc744cd99b6455e3e388b54519db8f Mon Sep 17 00:00:00 2001 From: Tony Lindgren Date: Mon, 25 Mar 2024 09:16:47 +0200 Subject: serial: core: Fix regression when runtime PM is not enabled Commit 45a3a8ef8129 ("serial: core: Revert checks for tx runtime PM state") caused a regression for Sun Ultra 60 for the sunsab driver as reported by Nick Bowler . We need to add back the check runtime PM enabled state for serial port controller device, I wrongly assumed earlier we could just remove it. Fixes: 45a3a8ef8129 ("serial: core: Revert checks for tx runtime PM state") Cc: stable Reported-by: Nick Bowler Signed-off-by: Tony Lindgren Link: https://lore.kernel.org/r/20240325071649.27040-1-tony@atomide.com Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/serial_core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/tty/serial/serial_core.c b/drivers/tty/serial/serial_core.c index ff85ebd3a007..25a83820927a 100644 --- a/drivers/tty/serial/serial_core.c +++ b/drivers/tty/serial/serial_core.c @@ -156,7 +156,7 @@ static void __uart_start(struct uart_state *state) * enabled, serial_port_runtime_resume() calls start_tx() again * after enabling the device. */ - if (pm_runtime_active(&port_dev->dev)) + if (!pm_runtime_enabled(port->dev) || pm_runtime_active(&port_dev->dev)) port->ops->start_tx(port); pm_runtime_mark_last_busy(&port_dev->dev); pm_runtime_put_autosuspend(&port_dev->dev); -- cgit v1.2.3 From 90452456eb69297fe7ae34e56e40d8e47dc9e019 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Thu, 4 Apr 2024 01:41:52 +0300 Subject: serial: 8250_pci: Remove redundant PCI IDs Driver complains that PCI IDs are not needed for some of the LAVA cards: [ 0.297252] serial 0000:04:00.0: Redundant entry in serial pci_table. [ 0.297252] Please send the output of lspci -vv, this [ 0.297252] message (0x1407,0x0120,0x0000,0x0000), the [ 0.297252] manufacturer and name of serial board or [ 0.297252] modem board to . Do as suggested. Reported-by: Jimmy A Closes: https://lore.kernel.org/r/VI1P194MB052751BE157EFE9CEAB75725CE362@VI1P194MB0527.EURP194.PROD.OUTLOOK.COM Signed-off-by: Andy Shevchenko Link: https://lore.kernel.org/r/20240403224152.945099-1-andy.shevchenko@gmail.com Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/8250/8250_pci.c | 6 ------ 1 file changed, 6 deletions(-) diff --git a/drivers/tty/serial/8250/8250_pci.c b/drivers/tty/serial/8250/8250_pci.c index 0d35c77fad9e..e2e4f99f9d34 100644 --- a/drivers/tty/serial/8250/8250_pci.c +++ b/drivers/tty/serial/8250/8250_pci.c @@ -5010,12 +5010,6 @@ static const struct pci_device_id serial_pci_tbl[] = { { PCI_VENDOR_ID_LAVA, PCI_DEVICE_ID_LAVA_QUATRO_B, PCI_ANY_ID, PCI_ANY_ID, 0, 0, pbn_b0_bt_2_115200 }, - { PCI_VENDOR_ID_LAVA, PCI_DEVICE_ID_LAVA_QUATTRO_A, - PCI_ANY_ID, PCI_ANY_ID, 0, 0, - pbn_b0_bt_2_115200 }, - { PCI_VENDOR_ID_LAVA, PCI_DEVICE_ID_LAVA_QUATTRO_B, - PCI_ANY_ID, PCI_ANY_ID, 0, 0, - pbn_b0_bt_2_115200 }, { PCI_VENDOR_ID_LAVA, PCI_DEVICE_ID_LAVA_OCTO_A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, pbn_b0_bt_4_460800 }, -- cgit v1.2.3 From 1be3226445362bfbf461c92a5bcdb1723f2e4907 Mon Sep 17 00:00:00 2001 From: Finn Thain Date: Mon, 8 Apr 2024 19:23:43 +1000 Subject: serial/pmac_zilog: Remove flawed mitigation for rx irq flood The mitigation was intended to stop the irq completely. That may be better than a hard lock-up but it turns out that you get a crash anyway if you're using pmac_zilog as a serial console: ttyPZ0: pmz: rx irq flood ! BUG: spinlock recursion on CPU#0, swapper/0 That's because the pr_err() call in pmz_receive_chars() results in pmz_console_write() attempting to lock a spinlock already locked in pmz_interrupt(). With CONFIG_DEBUG_SPINLOCK=y, this produces a fatal BUG splat. The spinlock in question is the one in struct uart_port. Even when it's not fatal, the serial port rx function ceases to work. Also, the iteration limit doesn't play nicely with QEMU, as can be seen in the bug report linked below. A web search for other reports of the error message "pmz: rx irq flood" didn't produce anything. So I don't think this code is needed any more. Remove it. Cc: Benjamin Herrenschmidt Cc: Michael Ellerman Cc: Nicholas Piggin Cc: Christophe Leroy Cc: Aneesh Kumar K.V Cc: Naveen N. Rao Cc: Andy Shevchenko Cc: stable@kernel.org Cc: linux-m68k@lists.linux-m68k.org Link: https://github.com/vivier/qemu-m68k/issues/44 Link: https://lore.kernel.org/all/1078874617.9746.36.camel@gaston/ Acked-by: Michael Ellerman Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2") Cc: stable Signed-off-by: Finn Thain Link: https://lore.kernel.org/r/e853cf2c762f23101cd2ddec0cc0c2be0e72685f.1712568223.git.fthain@linux-m68k.org Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/pmac_zilog.c | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/drivers/tty/serial/pmac_zilog.c b/drivers/tty/serial/pmac_zilog.c index 05d97e89511e..92195f984de1 100644 --- a/drivers/tty/serial/pmac_zilog.c +++ b/drivers/tty/serial/pmac_zilog.c @@ -210,7 +210,6 @@ static bool pmz_receive_chars(struct uart_pmac_port *uap) { struct tty_port *port; unsigned char ch, r1, drop, flag; - int loops = 0; /* Sanity check, make sure the old bug is no longer happening */ if (uap->port.state == NULL) { @@ -291,24 +290,11 @@ static bool pmz_receive_chars(struct uart_pmac_port *uap) if (r1 & Rx_OVR) tty_insert_flip_char(port, 0, TTY_OVERRUN); next_char: - /* We can get stuck in an infinite loop getting char 0 when the - * line is in a wrong HW state, we break that here. - * When that happens, I disable the receive side of the driver. - * Note that what I've been experiencing is a real irq loop where - * I'm getting flooded regardless of the actual port speed. - * Something strange is going on with the HW - */ - if ((++loops) > 1000) - goto flood; ch = read_zsreg(uap, R0); if (!(ch & Rx_CH_AV)) break; } - return true; - flood: - pmz_interrupt_control(uap, 0); - pmz_error("pmz: rx irq flood !\n"); return true; } -- cgit v1.2.3 From d325a858a53b5816a60447887f7148eace999e00 Mon Sep 17 00:00:00 2001 From: Richard Genoud Date: Mon, 8 Apr 2024 12:13:29 +0200 Subject: MAINTAINERS: mailmap: update Richard Genoud's email address I'm working now at bootlin, so I'll use my bootlin address for kernel development from now on. Update also the yaml file for atmel-serial accordingly. Signed-off-by: Richard Genoud Reviewed-by: Nicolas Ferre Link: https://lore.kernel.org/r/20240408101329.9448-1-richard.genoud@bootlin.com Signed-off-by: Greg Kroah-Hartman --- .mailmap | 1 + Documentation/devicetree/bindings/serial/atmel,at91-usart.yaml | 2 +- MAINTAINERS | 2 +- 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/.mailmap b/.mailmap index 8284692f9610..71e28f4e0d4a 100644 --- a/.mailmap +++ b/.mailmap @@ -524,6 +524,7 @@ Rémi Denis-Courmont Ricardo Ribalda Ricardo Ribalda Ricardo Ribalda Delgado Ricardo Ribalda +Richard Genoud Richard Leitner Richard Leitner Richard Leitner diff --git a/Documentation/devicetree/bindings/serial/atmel,at91-usart.yaml b/Documentation/devicetree/bindings/serial/atmel,at91-usart.yaml index 65cb2e5c5eee..eb2992a447d7 100644 --- a/Documentation/devicetree/bindings/serial/atmel,at91-usart.yaml +++ b/Documentation/devicetree/bindings/serial/atmel,at91-usart.yaml @@ -8,7 +8,7 @@ $schema: http://devicetree.org/meta-schemas/core.yaml# title: Atmel Universal Synchronous Asynchronous Receiver/Transmitter (USART) maintainers: - - Richard Genoud + - Richard Genoud properties: compatible: diff --git a/MAINTAINERS b/MAINTAINERS index aea47e04c3a5..0dbdc81e46c6 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -14363,7 +14363,7 @@ F: drivers/dma/at_xdmac.c F: include/dt-bindings/dma/at91.h MICROCHIP AT91 SERIAL DRIVER -M: Richard Genoud +M: Richard Genoud S: Maintained F: Documentation/devicetree/bindings/serial/atmel,at91-usart.yaml F: drivers/tty/serial/atmel_serial.c -- cgit v1.2.3 From fbbdc255fbee59b4207a5398fdb4f04590681a79 Mon Sep 17 00:00:00 2001 From: Zhenhua Huang Date: Mon, 8 Apr 2024 21:43:57 -0700 Subject: fs/proc: remove redundant comments from /proc/bootconfig commit 717c7c894d4b ("fs/proc: Add boot loader arguments as comment to /proc/bootconfig") adds bootloader argument comments into /proc/bootconfig. /proc/bootconfig shows boot_command_line[] multiple times following every xbc key value pair, that's duplicated and not necessary. Remove redundant ones. Output before and after the fix is like: key1 = value1 *bootloader argument comments* key2 = value2 *bootloader argument comments* key3 = value3 *bootloader argument comments* ... key1 = value1 key2 = value2 key3 = value3 *bootloader argument comments* ... Link: https://lore.kernel.org/all/20240409044358.1156477-1-paulmck@kernel.org/ Fixes: 717c7c894d4b ("fs/proc: Add boot loader arguments as comment to /proc/bootconfig") Signed-off-by: Zhenhua Huang Signed-off-by: Paul E. McKenney Cc: Cc: Cc: stable@vger.kernel.org Acked-by: Masami Hiramatsu (Google) Signed-off-by: Masami Hiramatsu (Google) --- fs/proc/bootconfig.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/fs/proc/bootconfig.c b/fs/proc/bootconfig.c index 902b326e1e56..e5635a6b127b 100644 --- a/fs/proc/bootconfig.c +++ b/fs/proc/bootconfig.c @@ -62,12 +62,12 @@ static int __init copy_xbc_key_value_list(char *dst, size_t size) break; dst += ret; } - if (ret >= 0 && boot_command_line[0]) { - ret = snprintf(dst, rest(dst, end), "# Parameters from bootloader:\n# %s\n", - boot_command_line); - if (ret > 0) - dst += ret; - } + } + if (ret >= 0 && boot_command_line[0]) { + ret = snprintf(dst, rest(dst, end), "# Parameters from bootloader:\n# %s\n", + boot_command_line); + if (ret > 0) + dst += ret; } out: kfree(key); -- cgit v1.2.3 From c722cea208789d9e2660992bcd05fb9fac3adb56 Mon Sep 17 00:00:00 2001 From: Masami Hiramatsu Date: Mon, 8 Apr 2024 21:43:58 -0700 Subject: fs/proc: Skip bootloader comment if no embedded kernel parameters If the "bootconfig" kernel command-line argument was specified or if the kernel was built with CONFIG_BOOT_CONFIG_FORCE, but if there are no embedded kernel parameter, omit the "# Parameters from bootloader:" comment from the /proc/bootconfig file. This will cause automation to fall back to the /proc/cmdline file, which will be identical to the comment in this no-embedded-kernel-parameters case. Link: https://lore.kernel.org/all/20240409044358.1156477-2-paulmck@kernel.org/ Fixes: 8b8ce6c75430 ("fs/proc: remove redundant comments from /proc/bootconfig") Signed-off-by: Masami Hiramatsu Signed-off-by: Paul E. McKenney Cc: stable@vger.kernel.org Acked-by: Masami Hiramatsu (Google) Signed-off-by: Masami Hiramatsu (Google) --- fs/proc/bootconfig.c | 2 +- include/linux/bootconfig.h | 1 + init/main.c | 5 +++++ 3 files changed, 7 insertions(+), 1 deletion(-) diff --git a/fs/proc/bootconfig.c b/fs/proc/bootconfig.c index e5635a6b127b..87dcaae32ff8 100644 --- a/fs/proc/bootconfig.c +++ b/fs/proc/bootconfig.c @@ -63,7 +63,7 @@ static int __init copy_xbc_key_value_list(char *dst, size_t size) dst += ret; } } - if (ret >= 0 && boot_command_line[0]) { + if (cmdline_has_extra_options() && ret >= 0 && boot_command_line[0]) { ret = snprintf(dst, rest(dst, end), "# Parameters from bootloader:\n# %s\n", boot_command_line); if (ret > 0) diff --git a/include/linux/bootconfig.h b/include/linux/bootconfig.h index ca73940e26df..e5ee2c694401 100644 --- a/include/linux/bootconfig.h +++ b/include/linux/bootconfig.h @@ -10,6 +10,7 @@ #ifdef __KERNEL__ #include #include +bool __init cmdline_has_extra_options(void); #else /* !__KERNEL__ */ /* * NOTE: This is only for tools/bootconfig, because tools/bootconfig will diff --git a/init/main.c b/init/main.c index 2ca52474d0c3..881f6230ee59 100644 --- a/init/main.c +++ b/init/main.c @@ -487,6 +487,11 @@ static int __init warn_bootconfig(char *str) early_param("bootconfig", warn_bootconfig); +bool __init cmdline_has_extra_options(void) +{ + return extra_command_line || extra_init_args; +} + /* Change NUL term back to "=", to make "param" the whole string. */ static void __init repair_env_string(char *param, char *val) { -- cgit v1.2.3 From 4370b673ccf240bf7587b0cb8e6726a5ccaf1f17 Mon Sep 17 00:00:00 2001 From: Jiaxun Yang Date: Thu, 28 Mar 2024 14:27:56 +0000 Subject: MIPS: scall: Save thread_info.syscall unconditionally on entry thread_info.syscall is used by syscall_get_nr to supply syscall nr over a thread stack frame. Previously, thread_info.syscall is only saved at syscall_trace_enter when syscall tracing is enabled. However rest of the kernel code do expect syscall_get_nr to be available without syscall tracing. The previous design breaks collect_syscall. Move saving process to syscall entry to fix it. Reported-by: Xi Ruoyao Link: https://github.com/util-linux/util-linux/issues/2867 Signed-off-by: Jiaxun Yang Signed-off-by: Thomas Bogendoerfer --- arch/mips/include/asm/ptrace.h | 2 +- arch/mips/kernel/asm-offsets.c | 1 + arch/mips/kernel/ptrace.c | 15 ++++++--------- arch/mips/kernel/scall32-o32.S | 23 +++++++++++++---------- arch/mips/kernel/scall64-n32.S | 3 ++- arch/mips/kernel/scall64-n64.S | 3 ++- arch/mips/kernel/scall64-o32.S | 33 +++++++++++++++++---------------- 7 files changed, 42 insertions(+), 38 deletions(-) diff --git a/arch/mips/include/asm/ptrace.h b/arch/mips/include/asm/ptrace.h index d14d0e37ad02..4a2b40ce39e0 100644 --- a/arch/mips/include/asm/ptrace.h +++ b/arch/mips/include/asm/ptrace.h @@ -159,7 +159,7 @@ extern unsigned long exception_ip(struct pt_regs *regs); #define exception_ip(regs) exception_ip(regs) #define profile_pc(regs) instruction_pointer(regs) -extern asmlinkage long syscall_trace_enter(struct pt_regs *regs, long syscall); +extern asmlinkage long syscall_trace_enter(struct pt_regs *regs); extern asmlinkage void syscall_trace_leave(struct pt_regs *regs); extern void die(const char *, struct pt_regs *) __noreturn; diff --git a/arch/mips/kernel/asm-offsets.c b/arch/mips/kernel/asm-offsets.c index d1b11f66f748..cb1045ebab06 100644 --- a/arch/mips/kernel/asm-offsets.c +++ b/arch/mips/kernel/asm-offsets.c @@ -101,6 +101,7 @@ void output_thread_info_defines(void) OFFSET(TI_CPU, thread_info, cpu); OFFSET(TI_PRE_COUNT, thread_info, preempt_count); OFFSET(TI_REGS, thread_info, regs); + OFFSET(TI_SYSCALL, thread_info, syscall); DEFINE(_THREAD_SIZE, THREAD_SIZE); DEFINE(_THREAD_MASK, THREAD_MASK); DEFINE(_IRQ_STACK_SIZE, IRQ_STACK_SIZE); diff --git a/arch/mips/kernel/ptrace.c b/arch/mips/kernel/ptrace.c index 59288c13b581..61503a36067e 100644 --- a/arch/mips/kernel/ptrace.c +++ b/arch/mips/kernel/ptrace.c @@ -1317,16 +1317,13 @@ long arch_ptrace(struct task_struct *child, long request, * Notification of system call entry/exit * - triggered by current->work.syscall_trace */ -asmlinkage long syscall_trace_enter(struct pt_regs *regs, long syscall) +asmlinkage long syscall_trace_enter(struct pt_regs *regs) { user_exit(); - current_thread_info()->syscall = syscall; - if (test_thread_flag(TIF_SYSCALL_TRACE)) { if (ptrace_report_syscall_entry(regs)) return -1; - syscall = current_thread_info()->syscall; } #ifdef CONFIG_SECCOMP @@ -1335,7 +1332,7 @@ asmlinkage long syscall_trace_enter(struct pt_regs *regs, long syscall) struct seccomp_data sd; unsigned long args[6]; - sd.nr = syscall; + sd.nr = current_thread_info()->syscall; sd.arch = syscall_get_arch(current); syscall_get_arguments(current, regs, args); for (i = 0; i < 6; i++) @@ -1345,23 +1342,23 @@ asmlinkage long syscall_trace_enter(struct pt_regs *regs, long syscall) ret = __secure_computing(&sd); if (ret == -1) return ret; - syscall = current_thread_info()->syscall; } #endif if (unlikely(test_thread_flag(TIF_SYSCALL_TRACEPOINT))) trace_sys_enter(regs, regs->regs[2]); - audit_syscall_entry(syscall, regs->regs[4], regs->regs[5], + audit_syscall_entry(current_thread_info()->syscall, + regs->regs[4], regs->regs[5], regs->regs[6], regs->regs[7]); /* * Negative syscall numbers are mistaken for rejected syscalls, but * won't have had the return value set appropriately, so we do so now. */ - if (syscall < 0) + if (current_thread_info()->syscall < 0) syscall_set_return_value(current, regs, -ENOSYS, 0); - return syscall; + return current_thread_info()->syscall; } /* diff --git a/arch/mips/kernel/scall32-o32.S b/arch/mips/kernel/scall32-o32.S index 18dc9b345056..2c604717e630 100644 --- a/arch/mips/kernel/scall32-o32.S +++ b/arch/mips/kernel/scall32-o32.S @@ -77,6 +77,18 @@ loads_done: PTR_WD load_a7, bad_stack_a7 .previous + /* + * syscall number is in v0 unless we called syscall(__NR_###) + * where the real syscall number is in a0 + */ + subu t2, v0, __NR_O32_Linux + bnez t2, 1f /* __NR_syscall at offset 0 */ + LONG_S a0, TI_SYSCALL($28) # Save a0 as syscall number + b 2f +1: + LONG_S v0, TI_SYSCALL($28) # Save v0 as syscall number +2: + lw t0, TI_FLAGS($28) # syscall tracing enabled? li t1, _TIF_WORK_SYSCALL_ENTRY and t0, t1 @@ -114,16 +126,7 @@ syscall_trace_entry: SAVE_STATIC move a0, sp - /* - * syscall number is in v0 unless we called syscall(__NR_###) - * where the real syscall number is in a0 - */ - move a1, v0 - subu t2, v0, __NR_O32_Linux - bnez t2, 1f /* __NR_syscall at offset 0 */ - lw a1, PT_R4(sp) - -1: jal syscall_trace_enter + jal syscall_trace_enter bltz v0, 1f # seccomp failed? Skip syscall diff --git a/arch/mips/kernel/scall64-n32.S b/arch/mips/kernel/scall64-n32.S index 97456b2ca7dc..97788859238c 100644 --- a/arch/mips/kernel/scall64-n32.S +++ b/arch/mips/kernel/scall64-n32.S @@ -44,6 +44,8 @@ NESTED(handle_sysn32, PT_SIZE, sp) sd a3, PT_R26(sp) # save a3 for syscall restarting + LONG_S v0, TI_SYSCALL($28) # Store syscall number + li t1, _TIF_WORK_SYSCALL_ENTRY LONG_L t0, TI_FLAGS($28) # syscall tracing enabled? and t0, t1, t0 @@ -72,7 +74,6 @@ syscall_common: n32_syscall_trace_entry: SAVE_STATIC move a0, sp - move a1, v0 jal syscall_trace_enter bltz v0, 1f # seccomp failed? Skip syscall diff --git a/arch/mips/kernel/scall64-n64.S b/arch/mips/kernel/scall64-n64.S index e6264aa62e45..be11ea5cc67e 100644 --- a/arch/mips/kernel/scall64-n64.S +++ b/arch/mips/kernel/scall64-n64.S @@ -46,6 +46,8 @@ NESTED(handle_sys64, PT_SIZE, sp) sd a3, PT_R26(sp) # save a3 for syscall restarting + LONG_S v0, TI_SYSCALL($28) # Store syscall number + li t1, _TIF_WORK_SYSCALL_ENTRY LONG_L t0, TI_FLAGS($28) # syscall tracing enabled? and t0, t1, t0 @@ -82,7 +84,6 @@ n64_syscall_exit: syscall_trace_entry: SAVE_STATIC move a0, sp - move a1, v0 jal syscall_trace_enter bltz v0, 1f # seccomp failed? Skip syscall diff --git a/arch/mips/kernel/scall64-o32.S b/arch/mips/kernel/scall64-o32.S index d3c2616cba22..7a5abb73e531 100644 --- a/arch/mips/kernel/scall64-o32.S +++ b/arch/mips/kernel/scall64-o32.S @@ -79,6 +79,22 @@ loads_done: PTR_WD load_a7, bad_stack_a7 .previous + /* + * absolute syscall number is in v0 unless we called syscall(__NR_###) + * where the real syscall number is in a0 + * note: NR_syscall is the first O32 syscall but the macro is + * only defined when compiling with -mabi=32 (CONFIG_32BIT) + * therefore __NR_O32_Linux is used (4000) + */ + + subu t2, v0, __NR_O32_Linux + bnez t2, 1f /* __NR_syscall at offset 0 */ + LONG_S a0, TI_SYSCALL($28) # Save a0 as syscall number + b 2f +1: + LONG_S v0, TI_SYSCALL($28) # Save v0 as syscall number +2: + li t1, _TIF_WORK_SYSCALL_ENTRY LONG_L t0, TI_FLAGS($28) # syscall tracing enabled? and t0, t1, t0 @@ -113,22 +129,7 @@ trace_a_syscall: sd a7, PT_R11(sp) # For indirect syscalls move a0, sp - /* - * absolute syscall number is in v0 unless we called syscall(__NR_###) - * where the real syscall number is in a0 - * note: NR_syscall is the first O32 syscall but the macro is - * only defined when compiling with -mabi=32 (CONFIG_32BIT) - * therefore __NR_O32_Linux is used (4000) - */ - .set push - .set reorder - subu t1, v0, __NR_O32_Linux - move a1, v0 - bnez t1, 1f /* __NR_syscall at offset 0 */ - ld a1, PT_R4(sp) /* Arg1 for __NR_syscall case */ - .set pop - -1: jal syscall_trace_enter + jal syscall_trace_enter bltz v0, 1f # seccomp failed? Skip syscall -- cgit v1.2.3 From 9cf7ea2eeb745213dc2a04103e426b960e807940 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Thu, 4 Apr 2024 17:59:26 +0300 Subject: serial: core: Clearing the circular buffer before NULLifying it The circular buffer is NULLified in uart_tty_port_shutdown() under the spin lock. However, the PM or other timer based callbacks may still trigger after this event without knowning that buffer pointer is not valid. Since the serial code is a bit inconsistent in checking the buffer state (some rely on the head-tail positions, some on the buffer pointer), it's better to have both aligned, i.e. buffer pointer to be NULL and head-tail possitions to be the same, meaning it's empty. This will prevent asynchronous calls to dereference NULL pointer as reported recently in 8250 case: BUG: kernel NULL pointer dereference, address: 00000cf5 Workqueue: pm pm_runtime_work EIP: serial8250_tx_chars (drivers/tty/serial/8250/8250_port.c:1809) ... ? serial8250_tx_chars (drivers/tty/serial/8250/8250_port.c:1809) __start_tx (drivers/tty/serial/8250/8250_port.c:1551) serial8250_start_tx (drivers/tty/serial/8250/8250_port.c:1654) serial_port_runtime_suspend (include/linux/serial_core.h:667 drivers/tty/serial/serial_port.c:63) __rpm_callback (drivers/base/power/runtime.c:393) ? serial_port_remove (drivers/tty/serial/serial_port.c:50) rpm_suspend (drivers/base/power/runtime.c:447) The proposed change will prevent ->start_tx() to be called during suspend on shut down port. Fixes: 43066e32227e ("serial: port: Don't suspend if the port is still busy") Cc: stable Reported-by: kernel test robot Closes: https://lore.kernel.org/oe-lkp/202404031607.2e92eebe-lkp@intel.com Signed-off-by: Andy Shevchenko Link: https://lore.kernel.org/r/20240404150034.41648-1-andriy.shevchenko@linux.intel.com Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/serial_core.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/tty/serial/serial_core.c b/drivers/tty/serial/serial_core.c index 25a83820927a..2247efe97250 100644 --- a/drivers/tty/serial/serial_core.c +++ b/drivers/tty/serial/serial_core.c @@ -1788,6 +1788,7 @@ static void uart_tty_port_shutdown(struct tty_port *port) * Free the transmit buffer. */ uart_port_lock_irq(uport); + uart_circ_clear(&state->xmit); buf = state->xmit.buf; state->xmit.buf = NULL; uart_port_unlock_irq(uport); -- cgit v1.2.3 From 011d79ef1cfad701c2d8e7e80d8c77523af9c771 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Mon, 8 Apr 2024 09:32:34 +0200 Subject: MAINTAINERS: Change Krzysztof Kozlowski's email address Switch Krzysztof Kozlowski's to @kernel.org account. Link: https://lore.kernel.org/r/20240329174823.74918-1-krzysztof.kozlowski@linaro.org Signed-off-by: Krzysztof Kozlowski Signed-off-by: Arnd Bergmann --- MAINTAINERS | 38 +++++++++++++++++++------------------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/MAINTAINERS b/MAINTAINERS index 7c121493f43d..cb0049030acd 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -2708,7 +2708,7 @@ F: sound/soc/rockchip/ N: rockchip ARM/SAMSUNG S3C, S5P AND EXYNOS ARM ARCHITECTURES -M: Krzysztof Kozlowski +M: Krzysztof Kozlowski R: Alim Akhtar L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) L: linux-samsung-soc@vger.kernel.org @@ -5557,7 +5557,7 @@ F: drivers/cpuidle/cpuidle-big_little.c CPUIDLE DRIVER - ARM EXYNOS M: Daniel Lezcano M: Kukjin Kim -R: Krzysztof Kozlowski +R: Krzysztof Kozlowski L: linux-pm@vger.kernel.org L: linux-samsung-soc@vger.kernel.org S: Maintained @@ -9000,7 +9000,7 @@ F: drivers/i2c/muxes/i2c-mux-gpio.c F: include/linux/platform_data/i2c-mux-gpio.h GENERIC GPIO RESET DRIVER -M: Krzysztof Kozlowski +M: Krzysztof Kozlowski S: Maintained F: drivers/reset/reset-gpio.c @@ -13295,7 +13295,7 @@ F: drivers/iio/adc/max11205.c MAXIM MAX17040 FAMILY FUEL GAUGE DRIVERS R: Iskren Chernev -R: Krzysztof Kozlowski +R: Krzysztof Kozlowski R: Marek Szyprowski R: Matheus Castello L: linux-pm@vger.kernel.org @@ -13305,7 +13305,7 @@ F: drivers/power/supply/max17040_battery.c MAXIM MAX17042 FAMILY FUEL GAUGE DRIVERS R: Hans de Goede -R: Krzysztof Kozlowski +R: Krzysztof Kozlowski R: Marek Szyprowski R: Sebastian Krzyszkowiak R: Purism Kernel Team @@ -13363,7 +13363,7 @@ F: Documentation/devicetree/bindings/power/supply/maxim,max77976.yaml F: drivers/power/supply/max77976_charger.c MAXIM MUIC CHARGER DRIVERS FOR EXYNOS BASED BOARDS -M: Krzysztof Kozlowski +M: Krzysztof Kozlowski L: linux-pm@vger.kernel.org S: Maintained B: mailto:linux-samsung-soc@vger.kernel.org @@ -13374,7 +13374,7 @@ F: drivers/power/supply/max77693_charger.c MAXIM PMIC AND MUIC DRIVERS FOR EXYNOS BASED BOARDS M: Chanwoo Choi -M: Krzysztof Kozlowski +M: Krzysztof Kozlowski L: linux-kernel@vger.kernel.org S: Maintained B: mailto:linux-samsung-soc@vger.kernel.org @@ -14156,7 +14156,7 @@ F: mm/mm_init.c F: tools/testing/memblock/ MEMORY CONTROLLER DRIVERS -M: Krzysztof Kozlowski +M: Krzysztof Kozlowski L: linux-kernel@vger.kernel.org S: Maintained B: mailto:krzysztof.kozlowski@linaro.org @@ -15537,7 +15537,7 @@ F: include/uapi/linux/nexthop.h F: net/ipv4/nexthop.c NFC SUBSYSTEM -M: Krzysztof Kozlowski +M: Krzysztof Kozlowski L: netdev@vger.kernel.org S: Maintained F: Documentation/devicetree/bindings/net/nfc/ @@ -15914,7 +15914,7 @@ F: Documentation/devicetree/bindings/regulator/nxp,pf8x00-regulator.yaml F: drivers/regulator/pf8x00-regulator.c NXP PTN5150A CC LOGIC AND EXTCON DRIVER -M: Krzysztof Kozlowski +M: Krzysztof Kozlowski L: linux-kernel@vger.kernel.org S: Maintained F: Documentation/devicetree/bindings/extcon/extcon-ptn5150.yaml @@ -16525,7 +16525,7 @@ K: of_overlay_remove OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS M: Rob Herring -M: Krzysztof Kozlowski +M: Krzysztof Kozlowski M: Conor Dooley L: devicetree@vger.kernel.org S: Maintained @@ -17483,7 +17483,7 @@ F: Documentation/devicetree/bindings/pinctrl/renesas,* F: drivers/pinctrl/renesas/ PIN CONTROLLER - SAMSUNG -M: Krzysztof Kozlowski +M: Krzysztof Kozlowski M: Sylwester Nawrocki R: Alim Akhtar L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) @@ -19451,7 +19451,7 @@ F: Documentation/devicetree/bindings/sound/samsung* F: sound/soc/samsung/ SAMSUNG EXYNOS PSEUDO RANDOM NUMBER GENERATOR (RNG) DRIVER -M: Krzysztof Kozlowski +M: Krzysztof Kozlowski L: linux-crypto@vger.kernel.org L: linux-samsung-soc@vger.kernel.org S: Maintained @@ -19486,7 +19486,7 @@ S: Maintained F: drivers/platform/x86/samsung-laptop.c SAMSUNG MULTIFUNCTION PMIC DEVICE DRIVERS -M: Krzysztof Kozlowski +M: Krzysztof Kozlowski L: linux-kernel@vger.kernel.org L: linux-samsung-soc@vger.kernel.org S: Maintained @@ -19512,7 +19512,7 @@ F: drivers/media/platform/samsung/s3c-camif/ F: include/media/drv-intf/s3c_camif.h SAMSUNG S3FWRN5 NFC DRIVER -M: Krzysztof Kozlowski +M: Krzysztof Kozlowski S: Maintained F: Documentation/devicetree/bindings/net/nfc/samsung,s3fwrn5.yaml F: drivers/nfc/s3fwrn5 @@ -19533,7 +19533,7 @@ S: Supported F: drivers/media/i2c/s5k5baf.c SAMSUNG S5P Security SubSystem (SSS) DRIVER -M: Krzysztof Kozlowski +M: Krzysztof Kozlowski M: Vladimir Zapolskiy L: linux-crypto@vger.kernel.org L: linux-samsung-soc@vger.kernel.org @@ -19555,7 +19555,7 @@ F: Documentation/devicetree/bindings/media/samsung,fimc.yaml F: drivers/media/platform/samsung/exynos4-is/ SAMSUNG SOC CLOCK DRIVERS -M: Krzysztof Kozlowski +M: Krzysztof Kozlowski M: Sylwester Nawrocki M: Chanwoo Choi R: Alim Akhtar @@ -19587,7 +19587,7 @@ F: drivers/net/ethernet/samsung/sxgbe/ SAMSUNG THERMAL DRIVER M: Bartlomiej Zolnierkiewicz -M: Krzysztof Kozlowski +M: Krzysztof Kozlowski L: linux-pm@vger.kernel.org L: linux-samsung-soc@vger.kernel.org S: Maintained @@ -23782,7 +23782,7 @@ S: Orphan F: drivers/mmc/host/vub300.c W1 DALLAS'S 1-WIRE BUS -M: Krzysztof Kozlowski +M: Krzysztof Kozlowski S: Maintained F: Documentation/devicetree/bindings/w1/ F: Documentation/w1/ -- cgit v1.2.3 From fbdd90334a6205e8a99d0bc2dfc738ee438f00bc Mon Sep 17 00:00:00 2001 From: Uwe Kleine-König Date: Fri, 5 Apr 2024 09:20:41 +0200 Subject: MAINTAINERS: Drop Li Yang as their email address stopped working MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When sending a patch to (among others) Li Yang the nxp MTA replied that the address doesn't exist and so the mail couldn't be delivered. The error code was 550, so at least technically that's not a temporal issue. Signed-off-by: Uwe Kleine-König Link: https://lore.kernel.org/r/20240405072042.697182-2-u.kleine-koenig@pengutronix.de Signed-off-by: Greg Kroah-Hartman --- MAINTAINERS | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/MAINTAINERS b/MAINTAINERS index 3c78979fb819..da6b81a9e336 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -2191,7 +2191,6 @@ N: mxs ARM/FREESCALE LAYERSCAPE ARM ARCHITECTURE M: Shawn Guo -M: Li Yang L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) S: Maintained T: git git://git.kernel.org/pub/scm/linux/kernel/git/shawnguo/linux.git @@ -8523,7 +8522,6 @@ S: Maintained F: drivers/video/fbdev/fsl-diu-fb.* FREESCALE DMA DRIVER -M: Li Yang M: Zhang Wei L: linuxppc-dev@lists.ozlabs.org S: Maintained @@ -8688,10 +8686,9 @@ F: drivers/soc/fsl/qe/tsa.h F: include/dt-bindings/soc/cpm1-fsl,tsa.h FREESCALE QUICC ENGINE UCC ETHERNET DRIVER -M: Li Yang L: netdev@vger.kernel.org L: linuxppc-dev@lists.ozlabs.org -S: Maintained +S: Orphan F: drivers/net/ethernet/freescale/ucc_geth* FREESCALE QUICC ENGINE UCC HDLC DRIVER @@ -8708,10 +8705,9 @@ S: Maintained F: drivers/tty/serial/ucc_uart.c FREESCALE SOC DRIVERS -M: Li Yang L: linuxppc-dev@lists.ozlabs.org L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) -S: Maintained +S: Orphan F: Documentation/devicetree/bindings/misc/fsl,dpaa2-console.yaml F: Documentation/devicetree/bindings/soc/fsl/ F: drivers/soc/fsl/ @@ -8745,10 +8741,9 @@ F: Documentation/devicetree/bindings/sound/fsl,qmc-audio.yaml F: sound/soc/fsl/fsl_qmc_audio.c FREESCALE USB PERIPHERAL DRIVERS -M: Li Yang L: linux-usb@vger.kernel.org L: linuxppc-dev@lists.ozlabs.org -S: Maintained +S: Orphan F: drivers/usb/gadget/udc/fsl* FREESCALE USB PHY DRIVER -- cgit v1.2.3 From 3461e02066758b78a0731eb71faecfb1eccd0e6c Mon Sep 17 00:00:00 2001 From: AngeloGioacchino Del Regno Date: Tue, 9 Apr 2024 13:36:46 +0200 Subject: usb: typec: mux: it5205: Fix ChipID value typo The ChipID bytes are read in inverse order: invert the ChipID value defined as IT5205FN_CHIP_ID and used for validating the same. Fixes: 41fe9ea1696c ("usb: typec: mux: Add ITE IT5205 Alternate Mode Passive MUX driver") Signed-off-by: AngeloGioacchino Del Regno Link: https://lore.kernel.org/r/20240409113646.305105-1-angelogioacchino.delregno@collabora.com Signed-off-by: Greg Kroah-Hartman --- drivers/usb/typec/mux/it5205.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/usb/typec/mux/it5205.c b/drivers/usb/typec/mux/it5205.c index 5535932e42cd..4357cc67a867 100644 --- a/drivers/usb/typec/mux/it5205.c +++ b/drivers/usb/typec/mux/it5205.c @@ -22,7 +22,7 @@ #include #define IT5205_REG_CHIP_ID(x) (0x4 + (x)) -#define IT5205FN_CHIP_ID 0x35323035 /* "5205" */ +#define IT5205FN_CHIP_ID 0x35303235 /* "5025" -> "5205" */ /* MUX power down register */ #define IT5205_REG_MUXPDR 0x10 -- cgit v1.2.3 From eed04fa96c48790c1cce73c8a248e9d460b088f8 Mon Sep 17 00:00:00 2001 From: Minas Harutyunyan Date: Tue, 9 Apr 2024 12:27:54 +0000 Subject: usb: dwc2: host: Fix dereference issue in DDMA completion flow. Fixed variable dereference issue in DDMA completion flow. Fixes: b258e4268850 ("usb: dwc2: host: Fix ISOC flow in DDMA mode") CC: stable@vger.kernel.org Reported-by: Dan Carpenter Closes: https://lore.kernel.org/linux-usb/2024040834-ethically-rumble-701f@gregkh/T/#m4c4b83bef0ebb4b67fe2e0a7d6466cbb6f416e39 Signed-off-by: Minas Harutyunyan Link: https://lore.kernel.org/r/cc826d3ef53c934d8e6d98870f17f3cdc3d2755d.1712665387.git.Minas.Harutyunyan@synopsys.com Signed-off-by: Greg Kroah-Hartman --- drivers/usb/dwc2/hcd_ddma.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/usb/dwc2/hcd_ddma.c b/drivers/usb/dwc2/hcd_ddma.c index 79582b102c7e..994a78ad084b 100644 --- a/drivers/usb/dwc2/hcd_ddma.c +++ b/drivers/usb/dwc2/hcd_ddma.c @@ -867,13 +867,15 @@ static int dwc2_cmpl_host_isoc_dma_desc(struct dwc2_hsotg *hsotg, struct dwc2_dma_desc *dma_desc; struct dwc2_hcd_iso_packet_desc *frame_desc; u16 frame_desc_idx; - struct urb *usb_urb = qtd->urb->priv; + struct urb *usb_urb; u16 remain = 0; int rc = 0; if (!qtd->urb) return -EINVAL; + usb_urb = qtd->urb->priv; + dma_sync_single_for_cpu(hsotg->dev, qh->desc_list_dma + (idx * sizeof(struct dwc2_dma_desc)), sizeof(struct dwc2_dma_desc), -- cgit v1.2.3 From 9fd60615ad2835d8e0081fd2458721c8b994f28f Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Tue, 9 Apr 2024 17:34:56 +0200 Subject: ASoC: codecs: Rockchip on-SoC codecs should depend on ARCH_ROCKCHIP The various Rockchip embedded audio codecs are only present on Rockchip SoCs. Hence add dependencies on ARCH_ROCKCHIP, to prevent asking the user about these drivers when configuring a kernel without Rockchip SoC support. Signed-off-by: Geert Uytterhoeven Link: https://msgid.link/r/6cdbaf4afcf4d2059b257f6cb3a8a61bf5e17688.1712676714.git.geert+renesas@glider.be Signed-off-by: Mark Brown --- sound/soc/codecs/Kconfig | 3 +++ 1 file changed, 3 insertions(+) diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig index 4e47bb6850aa..995eab954dd5 100644 --- a/sound/soc/codecs/Kconfig +++ b/sound/soc/codecs/Kconfig @@ -1173,6 +1173,7 @@ config SND_SOC_IDT821034 config SND_SOC_INNO_RK3036 tristate "Inno codec driver for RK3036 SoC" + depends on ARCH_ROCKCHIP || COMPILE_TEST select REGMAP_MMIO config SND_SOC_ISABELLE @@ -1437,6 +1438,7 @@ config SND_SOC_PEB2466 config SND_SOC_RK3308 tristate "Rockchip RK3308 audio CODEC" depends on ARM64 || COMPILE_TEST + depends on ARCH_ROCKCHIP || COMPILE_TEST select REGMAP_MMIO help This is a device driver for the audio codec embedded in the @@ -1447,6 +1449,7 @@ config SND_SOC_RK3308 config SND_SOC_RK3328 tristate "Rockchip RK3328 audio CODEC" + depends on ARCH_ROCKCHIP || COMPILE_TEST select REGMAP_MMIO config SND_SOC_RK817 -- cgit v1.2.3 From 6d029c25b71f2de2838a6f093ce0fa0e69336154 Mon Sep 17 00:00:00 2001 From: Oleg Nesterov Date: Tue, 9 Apr 2024 15:38:03 +0200 Subject: selftests/timers/posix_timers: Reimplement check_timer_distribution() check_timer_distribution() runs ten threads in a busy loop and tries to test that the kernel distributes a process posix CPU timer signal to every thread over time. There is not guarantee that this is true even after commit bcb7ee79029d ("posix-timers: Prefer delivery of signals to the current thread") because that commit only avoids waking up the sleeping process leader thread, but that has nothing to do with the actual signal delivery. As the signal is process wide the first thread which observes sigpending and wins the race to lock sighand will deliver the signal. Testing shows that this hangs on a regular base because some threads never win the race. The comment "This primarily tests that the kernel does not favour any one." is wrong. The kernel does favour a thread which hits the timer interrupt when CLOCK_PROCESS_CPUTIME_ID expires. Rewrite the test so it only checks that the group leader sleeping in join() never receives SIGALRM and the thread which burns CPU cycles receives all signals. In older kernels which do not have commit bcb7ee79029d ("posix-timers: Prefer delivery of signals to the current thread") the test-case fails immediately, the very 1st tick wakes the leader up. Otherwise it quickly succeeds after 100 ticks. CI testing wants to use newer selftest versions on stable kernels. In this case the test is guaranteed to fail. So check in the failure case whether the kernel version is less than v6.3 and skip the test result in that case. [ tglx: Massaged change log, renamed the version check helper ] Fixes: e797203fb3ba ("selftests/timers/posix_timers: Test delivery of signals across threads") Signed-off-by: Oleg Nesterov Signed-off-by: Thomas Gleixner Cc: stable@vger.kernel.org Link: https://lore.kernel.org/r/20240409133802.GD29396@redhat.com --- tools/testing/selftests/kselftest.h | 13 ++++ tools/testing/selftests/timers/posix_timers.c | 103 ++++++++++++-------------- 2 files changed, 60 insertions(+), 56 deletions(-) diff --git a/tools/testing/selftests/kselftest.h b/tools/testing/selftests/kselftest.h index 541bf192e30e..973b18e156b2 100644 --- a/tools/testing/selftests/kselftest.h +++ b/tools/testing/selftests/kselftest.h @@ -51,6 +51,7 @@ #include #include #include +#include #endif #ifndef ARRAY_SIZE @@ -388,4 +389,16 @@ static inline __printf(1, 2) int ksft_exit_skip(const char *msg, ...) exit(KSFT_SKIP); } +static inline int ksft_min_kernel_version(unsigned int min_major, + unsigned int min_minor) +{ + unsigned int major, minor; + struct utsname info; + + if (uname(&info) || sscanf(info.release, "%u.%u.", &major, &minor) != 2) + ksft_exit_fail_msg("Can't parse kernel version\n"); + + return major > min_major || (major == min_major && minor >= min_minor); +} + #endif /* __KSELFTEST_H */ diff --git a/tools/testing/selftests/timers/posix_timers.c b/tools/testing/selftests/timers/posix_timers.c index d49dd3ffd0d9..d86a0e00711e 100644 --- a/tools/testing/selftests/timers/posix_timers.c +++ b/tools/testing/selftests/timers/posix_timers.c @@ -184,80 +184,71 @@ static int check_timer_create(int which) return 0; } -int remain; -__thread int got_signal; +static pthread_t ctd_thread; +static volatile int ctd_count, ctd_failed; -static void *distribution_thread(void *arg) +static void ctd_sighandler(int sig) { - while (__atomic_load_n(&remain, __ATOMIC_RELAXED)); - return NULL; + if (pthread_self() != ctd_thread) + ctd_failed = 1; + ctd_count--; } -static void distribution_handler(int nr) +static void *ctd_thread_func(void *arg) { - if (!__atomic_exchange_n(&got_signal, 1, __ATOMIC_RELAXED)) - __atomic_fetch_sub(&remain, 1, __ATOMIC_RELAXED); -} - -/* - * Test that all running threads _eventually_ receive CLOCK_PROCESS_CPUTIME_ID - * timer signals. This primarily tests that the kernel does not favour any one. - */ -static int check_timer_distribution(void) -{ - int err, i; - timer_t id; - const int nthreads = 10; - pthread_t threads[nthreads]; struct itimerspec val = { .it_value.tv_sec = 0, .it_value.tv_nsec = 1000 * 1000, .it_interval.tv_sec = 0, .it_interval.tv_nsec = 1000 * 1000, }; + timer_t id; - remain = nthreads + 1; /* worker threads + this thread */ - signal(SIGALRM, distribution_handler); - err = timer_create(CLOCK_PROCESS_CPUTIME_ID, NULL, &id); - if (err < 0) { - ksft_perror("Can't create timer"); - return -1; - } - err = timer_settime(id, 0, &val, NULL); - if (err < 0) { - ksft_perror("Can't set timer"); - return -1; - } + /* 1/10 seconds to ensure the leader sleeps */ + usleep(10000); - for (i = 0; i < nthreads; i++) { - err = pthread_create(&threads[i], NULL, distribution_thread, - NULL); - if (err) { - ksft_print_msg("Can't create thread: %s (%d)\n", - strerror(errno), errno); - return -1; - } - } + ctd_count = 100; + if (timer_create(CLOCK_PROCESS_CPUTIME_ID, NULL, &id)) + return "Can't create timer\n"; + if (timer_settime(id, 0, &val, NULL)) + return "Can't set timer\n"; - /* Wait for all threads to receive the signal. */ - while (__atomic_load_n(&remain, __ATOMIC_RELAXED)); + while (ctd_count > 0 && !ctd_failed) + ; - for (i = 0; i < nthreads; i++) { - err = pthread_join(threads[i], NULL); - if (err) { - ksft_print_msg("Can't join thread: %s (%d)\n", - strerror(errno), errno); - return -1; - } - } + if (timer_delete(id)) + return "Can't delete timer\n"; - if (timer_delete(id)) { - ksft_perror("Can't delete timer"); - return -1; - } + return NULL; +} + +/* + * Test that only the running thread receives the timer signal. + */ +static int check_timer_distribution(void) +{ + const char *errmsg; - ksft_test_result_pass("check_timer_distribution\n"); + signal(SIGALRM, ctd_sighandler); + + errmsg = "Can't create thread\n"; + if (pthread_create(&ctd_thread, NULL, ctd_thread_func, NULL)) + goto err; + + errmsg = "Can't join thread\n"; + if (pthread_join(ctd_thread, (void **)&errmsg) || errmsg) + goto err; + + if (!ctd_failed) + ksft_test_result_pass("check signal distribution\n"); + else if (ksft_min_kernel_version(6, 3)) + ksft_test_result_fail("check signal distribution\n"); + else + ksft_test_result_skip("check signal distribution (old kernel)\n"); return 0; +err: + ksft_print_msg(errmsg); + return -1; } int main(int argc, char **argv) -- cgit v1.2.3 From 22a1dd652de329394ca81dd2fe046444920c96dc Mon Sep 17 00:00:00 2001 From: Bastien Curutchet Date: Tue, 2 Apr 2024 09:12:01 +0200 Subject: ASoC: dt-bindings: davinci-mcbsp: convert McBSP bindings to yaml schema Convert the binding for McBSP controllers for TI SoCs from txt to YAML schema. Add properties 'clocks', 'clock-names', 'power-domains' and '#sound-dai-cells' which were missing from the txt file. Add '#sound-dai-cells' and 'clocks' in the example which were missing from the txt file. Signed-off-by: Bastien Curutchet Reviewed-by: Rob Herring Acked-by: Peter Ujfalusi Link: https://msgid.link/r/20240402071213.11671-2-bastien.curutchet@bootlin.com Signed-off-by: Mark Brown --- .../devicetree/bindings/sound/davinci-mcbsp.txt | 50 ------------ .../devicetree/bindings/sound/davinci-mcbsp.yaml | 95 ++++++++++++++++++++++ 2 files changed, 95 insertions(+), 50 deletions(-) delete mode 100644 Documentation/devicetree/bindings/sound/davinci-mcbsp.txt create mode 100644 Documentation/devicetree/bindings/sound/davinci-mcbsp.yaml diff --git a/Documentation/devicetree/bindings/sound/davinci-mcbsp.txt b/Documentation/devicetree/bindings/sound/davinci-mcbsp.txt deleted file mode 100644 index 3ffc2562fb31..000000000000 --- a/Documentation/devicetree/bindings/sound/davinci-mcbsp.txt +++ /dev/null @@ -1,50 +0,0 @@ -Texas Instruments DaVinci McBSP module -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -This binding describes the "Multi-channel Buffered Serial Port" (McBSP) -audio interface found in some TI DaVinci processors like the OMAP-L138 or AM180x. - - -Required properties: -~~~~~~~~~~~~~~~~~~~~ -- compatible : - "ti,da850-mcbsp" : for DA850, AM180x and OPAM-L138 platforms - -- reg : physical base address and length of the controller memory mapped - region(s). -- reg-names : Should contain: - * "mpu" for the main registers (required). - * "dat" for the data FIFO (optional). - -- dmas: three element list of DMA controller phandles, DMA request line and - TC channel ordered triplets. -- dma-names: identifier string for each DMA request line in the dmas property. - These strings correspond 1:1 with the ordered pairs in dmas. The dma - identifiers must be "rx" and "tx". - -Optional properties: -~~~~~~~~~~~~~~~~~~~~ -- interrupts : Interrupt numbers for McBSP -- interrupt-names : Known interrupt names are "rx" and "tx" - -- pinctrl-0: Should specify pin control group used for this controller. -- pinctrl-names: Should contain only one value - "default", for more details - please refer to pinctrl-bindings.txt - -Example (AM1808): -~~~~~~~~~~~~~~~~~ - -mcbsp0: mcbsp@1d10000 { - compatible = "ti,da850-mcbsp"; - pinctrl-names = "default"; - pinctrl-0 = <&mcbsp0_pins>; - - reg = <0x00110000 0x1000>, - <0x00310000 0x1000>; - reg-names = "mpu", "dat"; - interrupts = <97 98>; - interrupt-names = "rx", "tx"; - dmas = <&edma0 3 1 - &edma0 2 1>; - dma-names = "tx", "rx"; -}; diff --git a/Documentation/devicetree/bindings/sound/davinci-mcbsp.yaml b/Documentation/devicetree/bindings/sound/davinci-mcbsp.yaml new file mode 100644 index 000000000000..139b594dd192 --- /dev/null +++ b/Documentation/devicetree/bindings/sound/davinci-mcbsp.yaml @@ -0,0 +1,95 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/sound/davinci-mcbsp.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: McBSP Controller for TI SoCs + +maintainers: + - Bastien Curutchet + +allOf: + - $ref: dai-common.yaml# + +properties: + compatible: + enum: + - ti,da850-mcbsp + + reg: + minItems: 1 + items: + - description: CFG registers + - description: data registers + + reg-names: + minItems: 1 + items: + - const: mpu + - const: dat + + dmas: + items: + - description: transmission DMA channel + - description: reception DMA channel + + dma-names: + items: + - const: tx + - const: rx + + interrupts: + items: + - description: RX interrupt + - description: TX interrupt + + interrupt-names: + items: + - const: rx + - const: tx + + clocks: + items: + - description: functional clock + + clock-names: + items: + - const: fck + + power-domains: + maxItems: 1 + + "#sound-dai-cells": + const: 0 + +required: + - "#sound-dai-cells" + - compatible + - reg + - reg-names + - dmas + - dma-names + - clocks + +unevaluatedProperties: false + +examples: + - | + mcbsp0@1d10000 { + #sound-dai-cells = <0>; + compatible = "ti,da850-mcbsp"; + pinctrl-names = "default"; + pinctrl-0 = <&mcbsp0_pins>; + + reg = <0x111000 0x1000>, + <0x311000 0x1000>; + reg-names = "mpu", "dat"; + interrupts = <97>, <98>; + interrupt-names = "rx", "tx"; + dmas = <&edma0 3 1>, + <&edma0 2 1>; + dma-names = "tx", "rx"; + + clocks = <&psc1 14>; + }; -- cgit v1.2.3 From 6a4b6b062a5917d611c1bde7189c5147cf0ca832 Mon Sep 17 00:00:00 2001 From: Bastien Curutchet Date: Tue, 2 Apr 2024 09:12:02 +0200 Subject: ASoC: dt-bindings: davinci-mcbsp: Add optional clock The McBSP uses an internal sample rate generator to provide bit clock or frame clock. This sample rate generator can be programmed to be driven by McBSP's internal clock source or by an external clock source (located on CLKS pin). The external clock source is not described in the bindings. Add an optional clock item that allows to select an external clock as sample rate generator's input. Signed-off-by: Bastien Curutchet Reviewed-by: Rob Herring Acked-by: Peter Ujfalusi Link: https://msgid.link/r/20240402071213.11671-3-bastien.curutchet@bootlin.com Signed-off-by: Mark Brown --- Documentation/devicetree/bindings/sound/davinci-mcbsp.yaml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Documentation/devicetree/bindings/sound/davinci-mcbsp.yaml b/Documentation/devicetree/bindings/sound/davinci-mcbsp.yaml index 139b594dd192..0c2b1936c6a1 100644 --- a/Documentation/devicetree/bindings/sound/davinci-mcbsp.yaml +++ b/Documentation/devicetree/bindings/sound/davinci-mcbsp.yaml @@ -50,12 +50,16 @@ properties: - const: tx clocks: + minItems: 1 items: - description: functional clock + - description: external input clock for sample rate generator. clock-names: + minItems: 1 items: - const: fck + - const: clks power-domains: maxItems: 1 -- cgit v1.2.3 From 904fb8f843a99ae7473d184412b6c7bd46a51593 Mon Sep 17 00:00:00 2001 From: Bastien Curutchet Date: Tue, 2 Apr 2024 09:12:03 +0200 Subject: ASoC: ti: davinci-i2s: Remove the unused clk_input_pin attribute The clk_input_pin attribute of davinci_mcbsp_dev struct is not set since commit 257ade78b601 ("ASoC: davinci-i2s: Convert to use edma-pcm"). Remove the attribute. Keep the behaviour of the MCBSP_CLKR case as MCBSP_CLKR == 0. I can't test the BC_FP format so I added back the initial comment that was removed by commit ec6375533748 ("ASoC: DaVinci: Added selection of clk input pin for McBSP"). This was the last dependency to linux/platform_data/davinci_asp.h so it is not included anymore. Remove the enum mcbsp_clk_input_pin from davinci_asp.h as it is not used anywhere else. Signed-off-by: Bastien Curutchet Acked-by: Peter Ujfalusi Link: https://msgid.link/r/20240402071213.11671-4-bastien.curutchet@bootlin.com Signed-off-by: Mark Brown --- include/linux/platform_data/davinci_asp.h | 15 --------------- sound/soc/ti/davinci-i2s.c | 24 ++++-------------------- 2 files changed, 4 insertions(+), 35 deletions(-) diff --git a/include/linux/platform_data/davinci_asp.h b/include/linux/platform_data/davinci_asp.h index c8645b2ed3c0..b9c8520b4bd3 100644 --- a/include/linux/platform_data/davinci_asp.h +++ b/include/linux/platform_data/davinci_asp.h @@ -25,16 +25,6 @@ struct davinci_mcasp_pdata { unsigned sram_size_capture; struct gen_pool *sram_pool; - /* - * If McBSP peripheral gets the clock from an external pin, - * there are three chooses, that are MCBSP_CLKX, MCBSP_CLKR - * and MCBSP_CLKS. - * Depending on different hardware connections it is possible - * to use this setting to change the behaviour of McBSP - * driver. - */ - int clk_input_pin; - /* * This flag works when both clock and FS are outputs for the cpu * and makes clock more accurate (FS is not symmetrical and the @@ -91,11 +81,6 @@ enum { MCASP_VERSION_OMAP, /* OMAP4/5 */ }; -enum mcbsp_clk_input_pin { - MCBSP_CLKR = 0, /* as in DM365 */ - MCBSP_CLKS, -}; - #define INACTIVE_MODE 0 #define TX_MODE 1 #define RX_MODE 2 diff --git a/sound/soc/ti/davinci-i2s.c b/sound/soc/ti/davinci-i2s.c index 07c8b2259208..5c906641640e 100644 --- a/sound/soc/ti/davinci-i2s.c +++ b/sound/soc/ti/davinci-i2s.c @@ -19,7 +19,6 @@ #include #include #include -#include #include #include @@ -159,7 +158,6 @@ struct davinci_mcbsp_dev { unsigned int fmt; int clk_div; - int clk_input_pin; bool i2s_accurate_sck; }; @@ -239,26 +237,12 @@ static int davinci_i2s_set_dai_fmt(struct snd_soc_dai *cpu_dai, DAVINCI_MCBSP_PCR_CLKRM; break; case SND_SOC_DAIFMT_BC_FP: - pcr = DAVINCI_MCBSP_PCR_FSRM | DAVINCI_MCBSP_PCR_FSXM; /* - * Selection of the clock input pin that is the - * input for the Sample Rate Generator. - * McBSP FSR and FSX are driven by the Sample Rate - * Generator. + * McBSP CLKR pin is the input for the Sample Rate Generator. + * McBSP FSR and FSX are driven by the Sample Rate Generator. */ - switch (dev->clk_input_pin) { - case MCBSP_CLKS: - pcr |= DAVINCI_MCBSP_PCR_CLKXM | - DAVINCI_MCBSP_PCR_CLKRM; - break; - case MCBSP_CLKR: - pcr |= DAVINCI_MCBSP_PCR_SCLKME; - break; - default: - dev_err(dev->dev, "bad clk_input_pin\n"); - return -EINVAL; - } - + pcr = DAVINCI_MCBSP_PCR_FSRM | DAVINCI_MCBSP_PCR_FSXM; + pcr |= DAVINCI_MCBSP_PCR_SCLKME; break; case SND_SOC_DAIFMT_BC_FC: /* codec is master */ -- cgit v1.2.3 From 6b1517b30d6dc9442d92f0273726f1e7390eff2c Mon Sep 17 00:00:00 2001 From: Bastien Curutchet Date: Tue, 2 Apr 2024 09:12:04 +0200 Subject: ASoC: ti: davinci-i2s: Replace dev_err with dev_err_probe In probe(), the dev_err() is used for every returned error. Replace dev_err() with dev_err_probe() where -EPROBE_DEFER can be returned. Signed-off-by: Bastien Curutchet Acked-by: Peter Ujfalusi Link: https://msgid.link/r/20240402071213.11671-5-bastien.curutchet@bootlin.com Signed-off-by: Mark Brown --- sound/soc/ti/davinci-i2s.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/ti/davinci-i2s.c b/sound/soc/ti/davinci-i2s.c index 5c906641640e..cd64f1384e18 100644 --- a/sound/soc/ti/davinci-i2s.c +++ b/sound/soc/ti/davinci-i2s.c @@ -708,7 +708,7 @@ static int davinci_i2s_probe(struct platform_device *pdev) ret = edma_pcm_platform_register(&pdev->dev); if (ret) { - dev_err(&pdev->dev, "register PCM failed: %d\n", ret); + dev_err_probe(&pdev->dev, ret, "register PCM failed\n"); goto err_unregister_component; } -- cgit v1.2.3 From 714ffb8d36f94bdc6d576417b451e9c568c83894 Mon Sep 17 00:00:00 2001 From: Bastien Curutchet Date: Tue, 2 Apr 2024 09:12:05 +0200 Subject: ASoC: ti: davinci-i2s: Use external clock to drive sample rate generator McBSP's internal sample rate generator can be programed to be driven by its internal clock or by an external clock source located on CLKS pin. The external clock source case is not handled by the driver. Handle an optional clock related to this external clock source. If present, the driver uses the clock located on CLKS pin as input for the sample rate generator. Thus, the external clock rate is used to compute divisors. If this optional clock is not present, the sample rate generator is driven by the McBSP's functional clock. Signed-off-by: Bastien Curutchet Acked-by: Peter Ujfalusi Link: https://msgid.link/r/20240402071213.11671-6-bastien.curutchet@bootlin.com Signed-off-by: Mark Brown --- sound/soc/ti/davinci-i2s.c | 65 ++++++++++++++++++++++++++++++++++------------ 1 file changed, 49 insertions(+), 16 deletions(-) diff --git a/sound/soc/ti/davinci-i2s.c b/sound/soc/ti/davinci-i2s.c index cd64f1384e18..578b4ae28b71 100644 --- a/sound/soc/ti/davinci-i2s.c +++ b/sound/soc/ti/davinci-i2s.c @@ -134,6 +134,7 @@ struct davinci_mcbsp_dev { int mode; u32 pcr; struct clk *clk; + struct clk *ext_clk; /* * Combining both channels into 1 element will at least double the * amount of time between servicing the dma channel, increase @@ -364,7 +365,8 @@ static int davinci_i2s_hw_params(struct snd_pcm_substream *substream, struct davinci_mcbsp_dev *dev = snd_soc_dai_get_drvdata(dai); struct snd_interval *i = NULL; int mcbsp_word_length, master; - unsigned int rcr, xcr, srgr, clk_div, freq, framesize; + unsigned int rcr, xcr, clk_div, freq, framesize; + unsigned int srgr = 0; u32 spcr; snd_pcm_format_t fmt; unsigned element_cnt = 1; @@ -385,9 +387,13 @@ static int davinci_i2s_hw_params(struct snd_pcm_substream *substream, switch (master) { case SND_SOC_DAIFMT_BP_FP: - freq = clk_get_rate(dev->clk); - srgr = DAVINCI_MCBSP_SRGR_FSGM | - DAVINCI_MCBSP_SRGR_CLKSM; + if (dev->ext_clk) { + freq = clk_get_rate(dev->ext_clk); + } else { + freq = clk_get_rate(dev->clk); + srgr = DAVINCI_MCBSP_SRGR_CLKSM; + } + srgr |= DAVINCI_MCBSP_SRGR_FSGM; srgr |= DAVINCI_MCBSP_SRGR_FWID(mcbsp_word_length * 8 - 1); if (dev->i2s_accurate_sck) { @@ -691,12 +697,36 @@ static int davinci_i2s_probe(struct platform_device *pdev) return -ENODEV; } - dev->clk = clk_get(&pdev->dev, NULL); + /* + * The optional is there for backward compatibility. + * If 'fck' is not present, the clk_get(dev, NULL) that follows may find something + */ + dev->clk = devm_clk_get_optional(&pdev->dev, "fck"); if (IS_ERR(dev->clk)) - return -ENODEV; - ret = clk_enable(dev->clk); + return dev_err_probe(&pdev->dev, PTR_ERR(dev->clk), "Invalid functional clock\n"); + if (!dev->clk) { + dev->clk = devm_clk_get(&pdev->dev, NULL); + if (IS_ERR(dev->clk)) + return dev_err_probe(&pdev->dev, PTR_ERR(dev->clk), + "Missing functional clock\n"); + } + + dev->ext_clk = devm_clk_get_optional(&pdev->dev, "clks"); + if (IS_ERR(dev->ext_clk)) + return dev_err_probe(&pdev->dev, PTR_ERR(dev->ext_clk), "Invalid external clock\n"); + + ret = clk_prepare_enable(dev->clk); if (ret) - goto err_put_clk; + return ret; + + if (dev->ext_clk) { + dev_dbg(&pdev->dev, "External clock used for sample rate generator\n"); + ret = clk_prepare_enable(dev->ext_clk); + if (ret) { + dev_err_probe(&pdev->dev, ret, "Failed to enable external clock\n"); + goto err_disable_clk; + } + } dev->dev = &pdev->dev; dev_set_drvdata(&pdev->dev, dev); @@ -704,7 +734,7 @@ static int davinci_i2s_probe(struct platform_device *pdev) ret = snd_soc_register_component(&pdev->dev, &davinci_i2s_component, &davinci_i2s_dai, 1); if (ret != 0) - goto err_release_clk; + goto err_disable_ext_clk; ret = edma_pcm_platform_register(&pdev->dev); if (ret) { @@ -716,10 +746,12 @@ static int davinci_i2s_probe(struct platform_device *pdev) err_unregister_component: snd_soc_unregister_component(&pdev->dev); -err_release_clk: - clk_disable(dev->clk); -err_put_clk: - clk_put(dev->clk); +err_disable_ext_clk: + if (dev->ext_clk) + clk_disable_unprepare(dev->ext_clk); +err_disable_clk: + clk_disable_unprepare(dev->clk); + return ret; } @@ -729,9 +761,10 @@ static void davinci_i2s_remove(struct platform_device *pdev) snd_soc_unregister_component(&pdev->dev); - clk_disable(dev->clk); - clk_put(dev->clk); - dev->clk = NULL; + clk_disable_unprepare(dev->clk); + + if (dev->ext_clk) + clk_disable_unprepare(dev->ext_clk); } static const struct of_device_id davinci_i2s_match[] __maybe_unused = { -- cgit v1.2.3 From 7dd7a6d2648b0b253cb8be3cdf8e895a995548fe Mon Sep 17 00:00:00 2001 From: Bastien Curutchet Date: Tue, 2 Apr 2024 09:12:06 +0200 Subject: ASoC: ti: davinci-i2s: Delete unnecessary assignment In davinci_i2s_hw_params(), mcbsp_word_length is set twice to asp_word_length[fmt]. Remove second unnecessary assignment. Signed-off-by: Bastien Curutchet Acked-by: Peter Ujfalusi Link: https://msgid.link/r/20240402071213.11671-7-bastien.curutchet@bootlin.com Signed-off-by: Mark Brown --- sound/soc/ti/davinci-i2s.c | 1 - 1 file changed, 1 deletion(-) diff --git a/sound/soc/ti/davinci-i2s.c b/sound/soc/ti/davinci-i2s.c index 578b4ae28b71..a2c7c812ea50 100644 --- a/sound/soc/ti/davinci-i2s.c +++ b/sound/soc/ti/davinci-i2s.c @@ -479,7 +479,6 @@ static int davinci_i2s_hw_params(struct snd_pcm_substream *substream, return -EINVAL; } } - mcbsp_word_length = asp_word_length[fmt]; switch (master) { case SND_SOC_DAIFMT_BP_FP: -- cgit v1.2.3 From 37e313cda35aa16623ccae630530651c786a1392 Mon Sep 17 00:00:00 2001 From: Bastien Curutchet Date: Tue, 2 Apr 2024 09:12:07 +0200 Subject: ASoC: ti: davinci-i2s: Add TDM support TDM is not supported by the McBSP driver. The McBSP datasheet does not name explicitly TDM as a supported format but it is possible to configure the McBSP to do TDM if all slots are used by McBSP. Add TDM support. It uses single-phase frame. Slot width is used to compute the McBSP's word length. Implement the set_tdm_slot() hook of snd_soc_dai_ops struct. It only supports TDM if all slots are used by McBSP. The snd_soc_dai_driver's channels_max is updated from 2 to 128. This was tested with BP_FC format on a platform designed off of DAVINCI/OMAP_L138. A check is done in davinci_i2s_set_dai_fmt() to prevent TDM to be used with BC_FC and BC_FP formats. Signed-off-by: Bastien Curutchet Acked-by: Peter Ujfalusi Link: https://msgid.link/r/20240402071213.11671-8-bastien.curutchet@bootlin.com Signed-off-by: Mark Brown --- sound/soc/ti/davinci-i2s.c | 92 +++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 87 insertions(+), 5 deletions(-) diff --git a/sound/soc/ti/davinci-i2s.c b/sound/soc/ti/davinci-i2s.c index a2c7c812ea50..f9a67c2bc2f5 100644 --- a/sound/soc/ti/davinci-i2s.c +++ b/sound/soc/ti/davinci-i2s.c @@ -160,6 +160,9 @@ struct davinci_mcbsp_dev { unsigned int fmt; int clk_div; bool i2s_accurate_sck; + + int tdm_slots; + int slot_width; }; static inline void davinci_mcbsp_write_reg(struct davinci_mcbsp_dev *dev, @@ -213,6 +216,63 @@ static void davinci_mcbsp_stop(struct davinci_mcbsp_dev *dev, int playback) toggle_clock(dev, playback); } +static int davinci_i2s_tdm_word_length(int tdm_slot_width) +{ + switch (tdm_slot_width) { + case 8: + return DAVINCI_MCBSP_WORD_8; + case 12: + return DAVINCI_MCBSP_WORD_12; + case 16: + return DAVINCI_MCBSP_WORD_16; + case 20: + return DAVINCI_MCBSP_WORD_20; + case 24: + return DAVINCI_MCBSP_WORD_24; + case 32: + return DAVINCI_MCBSP_WORD_32; + default: + return -EINVAL; + } +} + +static int davinci_i2s_set_tdm_slot(struct snd_soc_dai *cpu_dai, + unsigned int tx_mask, + unsigned int rx_mask, + int slots, int slot_width) +{ + struct davinci_mcbsp_dev *dev = snd_soc_dai_get_drvdata(cpu_dai); + + dev_dbg(dev->dev, "slots %d, slot_width %d\n", slots, slot_width); + + if (slots > 128 || !slots) { + dev_err(dev->dev, "Invalid number of slots\n"); + return -EINVAL; + } + + if (rx_mask != (1 << slots) - 1) { + dev_err(dev->dev, "Invalid RX mask (0x%08x) : all slots must be used by McBSP\n", + rx_mask); + return -EINVAL; + } + + if (tx_mask != (1 << slots) - 1) { + dev_err(dev->dev, "Invalid TX mask (0x%08x) : all slots must be used by McBSP\n", + tx_mask); + return -EINVAL; + } + + if (davinci_i2s_tdm_word_length(slot_width) < 0) { + dev_err(dev->dev, "%s: Unsupported slot_width %d\n", __func__, slot_width); + return -EINVAL; + } + + dev->tdm_slots = slots; + dev->slot_width = slot_width; + + return 0; +} + #define DEFAULT_BITPERSAMPLE 16 static int davinci_i2s_set_dai_fmt(struct snd_soc_dai *cpu_dai, @@ -238,6 +298,11 @@ static int davinci_i2s_set_dai_fmt(struct snd_soc_dai *cpu_dai, DAVINCI_MCBSP_PCR_CLKRM; break; case SND_SOC_DAIFMT_BC_FP: + if (dev->tdm_slots || dev->slot_width) { + dev_err(dev->dev, "TDM is not supported for BC_FP format\n"); + return -EINVAL; + } + /* * McBSP CLKR pin is the input for the Sample Rate Generator. * McBSP FSR and FSX are driven by the Sample Rate Generator. @@ -246,6 +311,11 @@ static int davinci_i2s_set_dai_fmt(struct snd_soc_dai *cpu_dai, pcr |= DAVINCI_MCBSP_PCR_SCLKME; break; case SND_SOC_DAIFMT_BC_FC: + if (dev->tdm_slots || dev->slot_width) { + dev_err(dev->dev, "TDM is not supported for BC_FC format\n"); + return -EINVAL; + } + /* codec is master */ pcr = 0; break; @@ -383,7 +453,13 @@ static int davinci_i2s_hw_params(struct snd_pcm_substream *substream, master = dev->fmt & SND_SOC_DAIFMT_CLOCK_PROVIDER_MASK; fmt = params_format(params); - mcbsp_word_length = asp_word_length[fmt]; + if (dev->slot_width) + mcbsp_word_length = davinci_i2s_tdm_word_length(dev->slot_width); + else + mcbsp_word_length = asp_word_length[fmt]; + + if (mcbsp_word_length < 0) + return mcbsp_word_length; switch (master) { case SND_SOC_DAIFMT_BP_FP: @@ -483,8 +559,13 @@ static int davinci_i2s_hw_params(struct snd_pcm_substream *substream, switch (master) { case SND_SOC_DAIFMT_BP_FP: case SND_SOC_DAIFMT_BP_FC: - rcr |= DAVINCI_MCBSP_RCR_RFRLEN1(0); - xcr |= DAVINCI_MCBSP_XCR_XFRLEN1(0); + if (dev->tdm_slots > 0) { + rcr |= DAVINCI_MCBSP_RCR_RFRLEN1(dev->tdm_slots - 1); + xcr |= DAVINCI_MCBSP_XCR_XFRLEN1(dev->tdm_slots - 1); + } else { + rcr |= DAVINCI_MCBSP_RCR_RFRLEN1(0); + xcr |= DAVINCI_MCBSP_XCR_XFRLEN1(0); + } break; case SND_SOC_DAIFMT_BC_FC: case SND_SOC_DAIFMT_BC_FP: @@ -609,19 +690,20 @@ static const struct snd_soc_dai_ops davinci_i2s_dai_ops = { .hw_params = davinci_i2s_hw_params, .set_fmt = davinci_i2s_set_dai_fmt, .set_clkdiv = davinci_i2s_dai_set_clkdiv, + .set_tdm_slot = davinci_i2s_set_tdm_slot, }; static struct snd_soc_dai_driver davinci_i2s_dai = { .playback = { .channels_min = 2, - .channels_max = 2, + .channels_max = 128, .rates = DAVINCI_I2S_RATES, .formats = DAVINCI_I2S_FORMATS, }, .capture = { .channels_min = 2, - .channels_max = 2, + .channels_max = 128, .rates = DAVINCI_I2S_RATES, .formats = DAVINCI_I2S_FORMATS, }, -- cgit v1.2.3 From eff21f5f8ea01834835ebe35995dba40f8435795 Mon Sep 17 00:00:00 2001 From: Bastien Curutchet Date: Tue, 2 Apr 2024 09:12:08 +0200 Subject: ASoC: ti: davinci-i2s: Add handling of BP_FC format McBSP is able to drive bit clock and consume frame clock but BP_FC format is not handled by McBSP driver. Add BP_FC format support. When BP_FC is selected: - CLKX and CLKR are configured as outputs - The sample rate generator is configured to be able to provide bit clock. Signed-off-by: Bastien Curutchet Acked-by: Peter Ujfalusi Link: https://msgid.link/r/20240402071213.11671-9-bastien.curutchet@bootlin.com Signed-off-by: Mark Brown --- sound/soc/ti/davinci-i2s.c | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/sound/soc/ti/davinci-i2s.c b/sound/soc/ti/davinci-i2s.c index f9a67c2bc2f5..e51f05cda941 100644 --- a/sound/soc/ti/davinci-i2s.c +++ b/sound/soc/ti/davinci-i2s.c @@ -310,6 +310,12 @@ static int davinci_i2s_set_dai_fmt(struct snd_soc_dai *cpu_dai, pcr = DAVINCI_MCBSP_PCR_FSRM | DAVINCI_MCBSP_PCR_FSXM; pcr |= DAVINCI_MCBSP_PCR_SCLKME; break; + case SND_SOC_DAIFMT_BP_FC: + /* cpu is bitclock provider */ + pcr = DAVINCI_MCBSP_PCR_CLKXM | + DAVINCI_MCBSP_PCR_CLKRM; + break; + case SND_SOC_DAIFMT_BC_FC: if (dev->tdm_slots || dev->slot_width) { dev_err(dev->dev, "TDM is not supported for BC_FC format\n"); @@ -500,6 +506,23 @@ static int davinci_i2s_hw_params(struct snd_pcm_substream *substream, clk_div &= 0xFF; srgr |= clk_div; break; + case SND_SOC_DAIFMT_BP_FC: + if (dev->ext_clk) { + freq = clk_get_rate(dev->ext_clk); + } else { + freq = clk_get_rate(dev->clk); + srgr = DAVINCI_MCBSP_SRGR_CLKSM; + } + if (dev->tdm_slots && dev->slot_width) { + clk_div = freq / (params->rate_num * params->rate_den) + / (dev->tdm_slots * dev->slot_width) - 1; + } else { + clk_div = freq / (mcbsp_word_length * 16) / + params->rate_num * params->rate_den; + } + clk_div &= 0xFF; + srgr |= clk_div; + break; case SND_SOC_DAIFMT_BC_FC: /* Clock and frame sync given from external sources */ i = hw_param_interval(params, SNDRV_PCM_HW_PARAM_SAMPLE_BITS); -- cgit v1.2.3 From 94d57c541dbdd350a91baeee94d3f5148e1d4dd7 Mon Sep 17 00:00:00 2001 From: Bastien Curutchet Date: Tue, 2 Apr 2024 09:12:09 +0200 Subject: ASoC: ti: davinci-i2s: Enable unexpected frame pulses detection McBSP can generate a SYNCERR when unexpected frame pulses are detected. The driver always disables this feature and ignore the unexpected frame pulses. Enable the generation of SYNCERR by the McBSP. Unexpected frame pulses are not ignored anymore. Signed-off-by: Bastien Curutchet Acked-by: Peter Ujfalusi Link: https://msgid.link/r/20240402071213.11671-10-bastien.curutchet@bootlin.com Signed-off-by: Mark Brown --- sound/soc/ti/davinci-i2s.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/sound/soc/ti/davinci-i2s.c b/sound/soc/ti/davinci-i2s.c index e51f05cda941..82a0dfa07cec 100644 --- a/sound/soc/ti/davinci-i2s.c +++ b/sound/soc/ti/davinci-i2s.c @@ -441,8 +441,10 @@ static int davinci_i2s_hw_params(struct snd_pcm_substream *substream, struct davinci_mcbsp_dev *dev = snd_soc_dai_get_drvdata(dai); struct snd_interval *i = NULL; int mcbsp_word_length, master; - unsigned int rcr, xcr, clk_div, freq, framesize; + unsigned int clk_div, freq, framesize; unsigned int srgr = 0; + unsigned int rcr = 0; + unsigned int xcr = 0; u32 spcr; snd_pcm_format_t fmt; unsigned element_cnt = 1; @@ -539,8 +541,6 @@ static int davinci_i2s_hw_params(struct snd_pcm_substream *substream, } davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SRGR_REG, srgr); - rcr = DAVINCI_MCBSP_RCR_RFIG; - xcr = DAVINCI_MCBSP_XCR_XFIG; if (dev->mode == MOD_DSP_B) { rcr |= DAVINCI_MCBSP_RCR_RDATDLY(0); xcr |= DAVINCI_MCBSP_XCR_XDATDLY(0); -- cgit v1.2.3 From 091b440ffd7cb542fd45c39dddd56bd870f9e180 Mon Sep 17 00:00:00 2001 From: Bastien Curutchet Date: Tue, 2 Apr 2024 09:12:10 +0200 Subject: ASoC: ti: davinci-i2s: Link free-run mode to SND_SOC_DAIFMT_[GATED/CONT] McBSP has free-running mode where serial clocks continue to run during emulation halts. This mode is always enabled by the driver. Set free-running mode when SND_SOC_DAIFMT_CONT is selected by DAI format, unset it when SND_SOC_DAIFMT_GATED is selected. Signed-off-by: Bastien Curutchet Acked-by: Peter Ujfalusi Link: https://msgid.link/r/20240402071213.11671-11-bastien.curutchet@bootlin.com Signed-off-by: Mark Brown --- sound/soc/ti/davinci-i2s.c | 22 ++++++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) diff --git a/sound/soc/ti/davinci-i2s.c b/sound/soc/ti/davinci-i2s.c index 82a0dfa07cec..7fb41987175b 100644 --- a/sound/soc/ti/davinci-i2s.c +++ b/sound/soc/ti/davinci-i2s.c @@ -280,6 +280,7 @@ static int davinci_i2s_set_dai_fmt(struct snd_soc_dai *cpu_dai, { struct davinci_mcbsp_dev *dev = snd_soc_dai_get_drvdata(cpu_dai); unsigned int pcr; + unsigned int spcr; unsigned int srgr; bool inv_fs = false; /* Attention srgr is updated by hw_params! */ @@ -288,6 +289,23 @@ static int davinci_i2s_set_dai_fmt(struct snd_soc_dai *cpu_dai, DAVINCI_MCBSP_SRGR_FWID(DEFAULT_BITPERSAMPLE - 1); dev->fmt = fmt; + + spcr = davinci_mcbsp_read_reg(dev, DAVINCI_MCBSP_SPCR_REG); + switch (fmt & SND_SOC_DAIFMT_CLOCK_MASK) { + case SND_SOC_DAIFMT_CONT: + spcr |= DAVINCI_MCBSP_SPCR_FREE; + dev_dbg(dev->dev, "Free-running mode ON\n"); + break; + case SND_SOC_DAIFMT_GATED: + spcr &= ~DAVINCI_MCBSP_SPCR_FREE; + dev_dbg(dev->dev, "Free-running mode OFF\n"); + break; + default: + dev_err(dev->dev, "Invalid clock gating\n"); + return -EINVAL; + } + davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SPCR_REG, spcr); + /* set master/slave audio interface */ switch (fmt & SND_SOC_DAIFMT_CLOCK_PROVIDER_MASK) { case SND_SOC_DAIFMT_BP_FP: @@ -452,10 +470,10 @@ static int davinci_i2s_hw_params(struct snd_pcm_substream *substream, /* general line settings */ spcr = davinci_mcbsp_read_reg(dev, DAVINCI_MCBSP_SPCR_REG); if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) { - spcr |= DAVINCI_MCBSP_SPCR_RINTM(3) | DAVINCI_MCBSP_SPCR_FREE; + spcr |= DAVINCI_MCBSP_SPCR_RINTM(3); davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SPCR_REG, spcr); } else { - spcr |= DAVINCI_MCBSP_SPCR_XINTM(3) | DAVINCI_MCBSP_SPCR_FREE; + spcr |= DAVINCI_MCBSP_SPCR_XINTM(3); davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SPCR_REG, spcr); } -- cgit v1.2.3 From 92e7bb2b6aa374c130dcf052f2c52f63c5b75d38 Mon Sep 17 00:00:00 2001 From: Bastien Curutchet Date: Tue, 2 Apr 2024 09:12:11 +0200 Subject: ASoC: ti: davinci-i2s: Add S24_LE to supported formats S24_LE is supported by McBSP but not by the driver. Add S24_LE to driver's supported formats. Using it enables the sign extension in DRR (Data Receive Register). The other formats are kept with the zero extension in DRR. Remove data_type table as it is no longer used. Signed-off-by: Bastien Curutchet Acked-by: Peter Ujfalusi Link: https://msgid.link/r/20240402071213.11671-12-bastien.curutchet@bootlin.com Signed-off-by: Mark Brown --- sound/soc/ti/davinci-i2s.c | 34 +++++++++++++++++++++------------- 1 file changed, 21 insertions(+), 13 deletions(-) diff --git a/sound/soc/ti/davinci-i2s.c b/sound/soc/ti/davinci-i2s.c index 7fb41987175b..fb1e09c78bdf 100644 --- a/sound/soc/ti/davinci-i2s.c +++ b/sound/soc/ti/davinci-i2s.c @@ -61,6 +61,9 @@ #define DAVINCI_MCBSP_SPCR_RRST (1 << 0) #define DAVINCI_MCBSP_SPCR_RINTM(v) ((v) << 4) +#define DAVINCI_MCBSP_SPCR_RJUST(v) ((v) << 13) +#define DAVINCI_MCBSP_SPCR_RJUST_Z_LE DAVINCI_MCBSP_SPCR_RJUST(0) +#define DAVINCI_MCBSP_SPCR_RJUST_S_LE DAVINCI_MCBSP_SPCR_RJUST(1) #define DAVINCI_MCBSP_SPCR_XRST (1 << 16) #define DAVINCI_MCBSP_SPCR_XINTM(v) ((v) << 20) #define DAVINCI_MCBSP_SPCR_GRST (1 << 22) @@ -107,15 +110,10 @@ enum { DAVINCI_MCBSP_WORD_32, }; -static const unsigned char data_type[SNDRV_PCM_FORMAT_S32_LE + 1] = { - [SNDRV_PCM_FORMAT_S8] = 1, - [SNDRV_PCM_FORMAT_S16_LE] = 2, - [SNDRV_PCM_FORMAT_S32_LE] = 4, -}; - static const unsigned char asp_word_length[SNDRV_PCM_FORMAT_S32_LE + 1] = { [SNDRV_PCM_FORMAT_S8] = DAVINCI_MCBSP_WORD_8, [SNDRV_PCM_FORMAT_S16_LE] = DAVINCI_MCBSP_WORD_16, + [SNDRV_PCM_FORMAT_S24_LE] = DAVINCI_MCBSP_WORD_24, [SNDRV_PCM_FORMAT_S32_LE] = DAVINCI_MCBSP_WORD_32, }; @@ -467,8 +465,23 @@ static int davinci_i2s_hw_params(struct snd_pcm_substream *substream, snd_pcm_format_t fmt; unsigned element_cnt = 1; - /* general line settings */ spcr = davinci_mcbsp_read_reg(dev, DAVINCI_MCBSP_SPCR_REG); + + /* Determine xfer data type */ + fmt = params_format(params); + switch (fmt) { + case SNDRV_PCM_FORMAT_S16_LE: + case SNDRV_PCM_FORMAT_S32_LE: + break; + case SNDRV_PCM_FORMAT_S24_LE: + spcr |= DAVINCI_MCBSP_SPCR_RJUST_S_LE; + break; + default: + dev_warn(dev->dev, "davinci-i2s: unsupported PCM format\n"); + return -EINVAL; + } + + /* general line settings */ if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) { spcr |= DAVINCI_MCBSP_SPCR_RINTM(3); davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SPCR_REG, spcr); @@ -566,12 +579,6 @@ static int davinci_i2s_hw_params(struct snd_pcm_substream *substream, rcr |= DAVINCI_MCBSP_RCR_RDATDLY(1); xcr |= DAVINCI_MCBSP_XCR_XDATDLY(1); } - /* Determine xfer data type */ - fmt = params_format(params); - if ((fmt > SNDRV_PCM_FORMAT_S32_LE) || !data_type[fmt]) { - printk(KERN_WARNING "davinci-i2s: unsupported PCM format\n"); - return -EINVAL; - } if (params_channels(params) == 2) { element_cnt = 2; @@ -710,6 +717,7 @@ static void davinci_i2s_shutdown(struct snd_pcm_substream *substream, #define DAVINCI_I2S_RATES SNDRV_PCM_RATE_8000_96000 #define DAVINCI_I2S_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | \ + SNDRV_PCM_FMTBIT_S24_LE | \ SNDRV_PCM_FMTBIT_S32_LE) static int davinci_i2s_dai_probe(struct snd_soc_dai *dai) -- cgit v1.2.3 From 609302ca04a3177463b0fbf4d5fc55a3ab4f900d Mon Sep 17 00:00:00 2001 From: Bastien Curutchet Date: Tue, 2 Apr 2024 09:12:12 +0200 Subject: ASoC: dt-bindings: davinci-mcbsp: Add the 'ti,T1-framing-{rx/tx}' flags McBSP's data delay can be configured from 0 to 2 bit clock periods. 0 is used for DSP_B format, 1 for DSP_A format. A data delay of 2 bit clock periods can be used to interface to 'T1 framing' devices where data stream is preceded by a 'framing bit'. This 2 bit clock data delay is not described in the bindings. Add two flags 'ti,T1-framing-[rx/tx]' to enable a data delay of 2 bit clock periods in reception or transmission. Signed-off-by: Bastien Curutchet Reviewed-by: Rob Herring Acked-by: Peter Ujfalusi Link: https://msgid.link/r/20240402071213.11671-13-bastien.curutchet@bootlin.com Signed-off-by: Mark Brown --- Documentation/devicetree/bindings/sound/davinci-mcbsp.yaml | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/Documentation/devicetree/bindings/sound/davinci-mcbsp.yaml b/Documentation/devicetree/bindings/sound/davinci-mcbsp.yaml index 0c2b1936c6a1..4fa677023827 100644 --- a/Documentation/devicetree/bindings/sound/davinci-mcbsp.yaml +++ b/Documentation/devicetree/bindings/sound/davinci-mcbsp.yaml @@ -67,6 +67,20 @@ properties: "#sound-dai-cells": const: 0 + ti,T1-framing-tx: + $ref: /schemas/types.yaml#/definitions/flag + description: + If the property is present, tx data delay is set to 2 bit clock periods. + McBSP will insert a blank period (high-impedance period) before the first + data bit. This can be used to interface to T1-framing devices. + + ti,T1-framing-rx: + $ref: /schemas/types.yaml#/definitions/flag + description: + If the property is present, rx data delay is set to 2 bit clock periods. + McBSP will discard the bit preceding the data stream (called framing bit). + This can be used to interface to T1-framing devices. + required: - "#sound-dai-cells" - compatible -- cgit v1.2.3 From 08e02fa48429c34db231cc3b58b940de2f7caf35 Mon Sep 17 00:00:00 2001 From: Bastien Curutchet Date: Tue, 2 Apr 2024 09:12:13 +0200 Subject: ASoC: ti: davinci-i2s: Add T1 framing support McBSP's data delay can be configured from 0 to 2 bit clock periods. 0 is used for DSP_B format, 1 is used for DSP_A format, 2 is unused. A data delay of 2 bit clock periods can be used to interface to 'T1 framing' devices where data stream is preceded by a 'framing bit'. On transmission, McBSP inserts a blank period (high-impedance period) before the first data bit to leave an opportunity for other devices to set this 'framing bit'. On reception, McBSP discards the 'framing bit' that precedes the data stream. Add support for the 'framing bit' according to the 'ti,T1-framing-[tx/rx]' device-tree properties. If a flag is present, the data delay is set to 2 bit clock periods regardless of the selected DAI format. Signed-off-by: Bastien Curutchet Acked-by: Peter Ujfalusi Link: https://msgid.link/r/20240402071213.11671-14-bastien.curutchet@bootlin.com Signed-off-by: Mark Brown --- sound/soc/ti/davinci-i2s.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/sound/soc/ti/davinci-i2s.c b/sound/soc/ti/davinci-i2s.c index fb1e09c78bdf..0f15a743c798 100644 --- a/sound/soc/ti/davinci-i2s.c +++ b/sound/soc/ti/davinci-i2s.c @@ -161,6 +161,9 @@ struct davinci_mcbsp_dev { int tdm_slots; int slot_width; + + bool tx_framing_bit; + bool rx_framing_bit; }; static inline void davinci_mcbsp_write_reg(struct davinci_mcbsp_dev *dev, @@ -580,6 +583,15 @@ static int davinci_i2s_hw_params(struct snd_pcm_substream *substream, xcr |= DAVINCI_MCBSP_XCR_XDATDLY(1); } + if (dev->tx_framing_bit) { + xcr &= ~DAVINCI_MCBSP_XCR_XDATDLY(1); + xcr |= DAVINCI_MCBSP_XCR_XDATDLY(2); + } + if (dev->rx_framing_bit) { + rcr &= ~DAVINCI_MCBSP_RCR_RDATDLY(1); + rcr |= DAVINCI_MCBSP_RCR_RDATDLY(2); + } + if (params_channels(params) == 2) { element_cnt = 2; if (double_fmt[fmt] && dev->enable_channel_combine) { @@ -796,6 +808,9 @@ static int davinci_i2s_probe(struct platform_device *pdev) dev->base = io_base; + dev->tx_framing_bit = of_property_read_bool(pdev->dev.of_node, "ti,T1-framing-tx"); + dev->rx_framing_bit = of_property_read_bool(pdev->dev.of_node, "ti,T1-framing-rx"); + /* setup DMA, first TX, then RX */ dma_data = &dev->dma_data[SNDRV_PCM_STREAM_PLAYBACK]; dma_data->addr = (dma_addr_t)(mem->start + DAVINCI_MCBSP_DXR_REG); -- cgit v1.2.3 From d7a62d0a9a17e97ce2d4d40431094e09956a0568 Mon Sep 17 00:00:00 2001 From: Thorsten Blum Date: Tue, 9 Apr 2024 17:46:23 +0200 Subject: compiler.h: Add missing quote in macro comment Add a missing doublequote in the __is_constexpr() macro comment. Signed-off-by: Thorsten Blum Signed-off-by: Linus Torvalds --- include/linux/compiler.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/linux/compiler.h b/include/linux/compiler.h index c00cc6c0878a..8c252e073bd8 100644 --- a/include/linux/compiler.h +++ b/include/linux/compiler.h @@ -268,7 +268,7 @@ static inline void *offset_to_ptr(const int *off) * - When one operand is a null pointer constant (i.e. when x is an integer * constant expression) and the other is an object pointer (i.e. our * third operand), the conditional operator returns the type of the - * object pointer operand (i.e. "int *). Here, within the sizeof(), we + * object pointer operand (i.e. "int *"). Here, within the sizeof(), we * would then get: * sizeof(*((int *)(...)) == sizeof(int) == 4 * - When one operand is a void pointer (i.e. when x is not an integer -- cgit v1.2.3 From 56437a561fefab2be708dfebf80e31c4715eb52e Mon Sep 17 00:00:00 2001 From: Vijendar Mukunda Date: Mon, 8 Apr 2024 23:32:26 +0530 Subject: ASoC: amd: fix for soundwire build dependencies for legacy stack The SND_SOC_AMD_SOUNDWIRE Kconfig symbol has build dependency on SOUNDWIRE_AMD. It gets it wrong for a configuration involving SND_SOC_AMD_SOUNDWIRE_LINK_BASELINE=y,SND_SOC_AMD_PS=y and SOUNDWIRE_AMD=m, which results in a link failure: ld: vmlinux.o: in function `amd_sdw_probe': >> sound/soc/amd/ps/pci-ps.c:271:(.text+0x1d51eff): undefined reference to `sdw_amd_probe' ld: vmlinux.o: in function `acp63_sdw_machine_select': >> sound/soc/amd/ps/pci-ps.c:294:(.text+0x1d525d5): undefined reference to `sdw_amd_get_slave_info' ld: vmlinux.o: in function `amd_sdw_exit': >> sound/soc/amd/ps/pci-ps.c:280:(.text+0x1d538ce): undefined reference to `sdw_amd_exit' Add a top level check config that forbids any of the AMD ACP drivers with version >= 6.3 from being built-in with CONFIG_SOUNDWIRE_AMD=m. Move SND_AMD_ACP_CONFIG common dependency config to SND_SOC_AMD_ACP63_TOPLEVEL config. Reported-by: kernel test robot Closes: https://lore.kernel.org/oe-kbuild-all/202404061257.khJml82D-lkp@intel.com/ Fixes: a806793f231e ("ASoC: amd: simplify soundwire dependencies for legacy stack") Signed-off-by: Vijendar Mukunda Link: https://msgid.link/r/20240408180229.3287220-1-Vijendar.Mukunda@amd.com Signed-off-by: Mark Brown --- sound/soc/amd/Kconfig | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/sound/soc/amd/Kconfig b/sound/soc/amd/Kconfig index 3508f5a96b75..6dec44f516c1 100644 --- a/sound/soc/amd/Kconfig +++ b/sound/soc/amd/Kconfig @@ -132,6 +132,19 @@ config SND_SOC_AMD_RPL_ACP6x Say m if you have such a device. If unsure select "N". +config SND_SOC_AMD_ACP63_TOPLEVEL + tristate "support for AMD platforms with ACP version >= 6.3" + default SND_AMD_ACP_CONFIG + depends on SND_AMD_ACP_CONFIG + depends on SOUNDWIRE_AMD || !SOUNDWIRE_AMD + depends on X86 || COMPILE_TEST + help + This adds support for AMD platforms with ACP version >= 6.3. + Say Y if you have such a device. + If unsure select "N". + +if SND_SOC_AMD_ACP63_TOPLEVEL + config SND_SOC_AMD_SOUNDWIRE_LINK_BASELINE tristate select SND_AMD_SOUNDWIRE_ACPI if ACPI @@ -149,7 +162,6 @@ config SND_SOC_AMD_SOUNDWIRE config SND_SOC_AMD_PS tristate "AMD Audio Coprocessor-v6.3 Pink Sardine support" - select SND_AMD_ACP_CONFIG select SND_SOC_AMD_SOUNDWIRE_LINK_BASELINE depends on X86 && PCI && ACPI help @@ -170,3 +182,5 @@ config SND_SOC_AMD_PS_MACH DMIC can be connected directly to ACP IP. Say m if you have such a device. If unsure select "N". + +endif -- cgit v1.2.3 From 4710e4fc3e2afa6c092db2c65eef365b0836d6db Mon Sep 17 00:00:00 2001 From: Christophe JAILLET Date: Sat, 9 Mar 2024 18:15:45 +0100 Subject: KVM: SVM: Remove a useless zeroing of allocated memory Remove KVM's unnecessary zeroing of memory when allocating the pages array in sev_pin_memory() via __vmalloc(), as the array is only used to hold kernel pointers. The kmalloc() path for "small" regions doesn't zero the array, and if KVM leaks state and/or accesses uninitialized data, then the kernel has bigger problems. Signed-off-by: Christophe JAILLET Link: https://lore.kernel.org/r/c7619a3d3cbb36463531a7c73ccbde9db587986c.1710004509.git.christophe.jaillet@wanadoo.fr [sean: massage changelog] Signed-off-by: Sean Christopherson --- arch/x86/kvm/svm/sev.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/x86/kvm/svm/sev.c b/arch/x86/kvm/svm/sev.c index 61a7531d41b0..759581bb2128 100644 --- a/arch/x86/kvm/svm/sev.c +++ b/arch/x86/kvm/svm/sev.c @@ -434,7 +434,7 @@ static struct page **sev_pin_memory(struct kvm *kvm, unsigned long uaddr, /* Avoid using vmalloc for smaller buffers. */ size = npages * sizeof(struct page *); if (size > PAGE_SIZE) - pages = __vmalloc(size, GFP_KERNEL_ACCOUNT | __GFP_ZERO); + pages = __vmalloc(size, GFP_KERNEL_ACCOUNT); else pages = kmalloc(size, GFP_KERNEL_ACCOUNT); -- cgit v1.2.3 From 19597a71a0c8603f8c8599686ac9b0ff4b846716 Mon Sep 17 00:00:00 2001 From: Sean Christopherson Date: Fri, 23 Feb 2024 12:42:26 -0800 Subject: KVM: SVM: Create a stack frame in __svm_vcpu_run() for unwinding Unconditionally create a stack frame in __svm_vcpu_run() to play nice with unwinding via frame pointers, at least until the point where RBP is loaded with the guest's value. Don't bother conditioning the code on CONFIG_FRAME_POINTER=y, as RBP needs to be saved and restored anyways (due to it being clobbered with the guest's value); omitting the "MOV RSP, RBP" is not worth the extra #ifdef. Creating a stack frame will allow removing the OBJECT_FILES_NON_STANDARD tag from vmenter.S once __svm_sev_es_vcpu_run() is fixed to not stomp all over RBP for no reason. Reviewed-by: Tom Lendacky Link: https://lore.kernel.org/r/20240223204233.3337324-2-seanjc@google.com Signed-off-by: Sean Christopherson --- arch/x86/kvm/svm/vmenter.S | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/x86/kvm/svm/vmenter.S b/arch/x86/kvm/svm/vmenter.S index 187018c424bf..82637abf0b7e 100644 --- a/arch/x86/kvm/svm/vmenter.S +++ b/arch/x86/kvm/svm/vmenter.S @@ -99,6 +99,7 @@ */ SYM_FUNC_START(__svm_vcpu_run) push %_ASM_BP + mov %_ASM_SP, %_ASM_BP #ifdef CONFIG_X86_64 push %r15 push %r14 -- cgit v1.2.3 From 7774c8f32e99b1f314c0df7c204a897792b4f378 Mon Sep 17 00:00:00 2001 From: Sean Christopherson Date: Fri, 23 Feb 2024 12:42:27 -0800 Subject: KVM: SVM: Wrap __svm_sev_es_vcpu_run() with #ifdef CONFIG_KVM_AMD_SEV Compile (and link) __svm_sev_es_vcpu_run() if and only if SEV support is actually enabled. This will allow dropping non-existent 32-bit "support" from __svm_sev_es_vcpu_run() without causing undue confusion. Intentionally don't provide a stub (but keep the declaration), as any sane compiler, even with things like KASAN enabled, should eliminate the call to __svm_sev_es_vcpu_run() since sev_es_guest() unconditionally returns "false" if CONFIG_KVM_AMD_SEV=n. Reviewed-by: Tom Lendacky Link: https://lore.kernel.org/r/20240223204233.3337324-3-seanjc@google.com Signed-off-by: Sean Christopherson --- arch/x86/kvm/svm/vmenter.S | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/x86/kvm/svm/vmenter.S b/arch/x86/kvm/svm/vmenter.S index 82637abf0b7e..6f57d496867a 100644 --- a/arch/x86/kvm/svm/vmenter.S +++ b/arch/x86/kvm/svm/vmenter.S @@ -291,6 +291,7 @@ SYM_FUNC_START(__svm_vcpu_run) SYM_FUNC_END(__svm_vcpu_run) +#ifdef CONFIG_KVM_AMD_SEV /** * __svm_sev_es_vcpu_run - Run a SEV-ES vCPU via a transition to SVM guest mode * @svm: struct vcpu_svm * @@ -389,3 +390,4 @@ SYM_FUNC_START(__svm_sev_es_vcpu_run) _ASM_EXTABLE(1b, 3b) SYM_FUNC_END(__svm_sev_es_vcpu_run) +#endif /* CONFIG_KVM_AMD_SEV */ -- cgit v1.2.3 From 331282fdb15edaf1beb1d27a64d3f65a34d7394d Mon Sep 17 00:00:00 2001 From: Sean Christopherson Date: Fri, 23 Feb 2024 12:42:28 -0800 Subject: KVM: SVM: Drop 32-bit "support" from __svm_sev_es_vcpu_run() Drop 32-bit "support" from __svm_sev_es_vcpu_run(), as SEV/SEV-ES firmly 64-bit only. The "support" was purely the result of bad copy+paste from __svm_vcpu_run(), which in turn was slightly less bad copy+paste from __vmx_vcpu_run(). Opportunistically convert to unadulterated register accesses so that it's easier (but still not easy) to follow which registers hold what arguments, and when. Reviewed-by: Tom Lendacky Link: https://lore.kernel.org/r/20240223204233.3337324-4-seanjc@google.com Signed-off-by: Sean Christopherson --- arch/x86/kvm/svm/vmenter.S | 44 +++++++++++++------------------------------- 1 file changed, 13 insertions(+), 31 deletions(-) diff --git a/arch/x86/kvm/svm/vmenter.S b/arch/x86/kvm/svm/vmenter.S index 6f57d496867a..c057866a459b 100644 --- a/arch/x86/kvm/svm/vmenter.S +++ b/arch/x86/kvm/svm/vmenter.S @@ -298,17 +298,12 @@ SYM_FUNC_END(__svm_vcpu_run) * @spec_ctrl_intercepted: bool */ SYM_FUNC_START(__svm_sev_es_vcpu_run) - push %_ASM_BP -#ifdef CONFIG_X86_64 + push %rbp push %r15 push %r14 push %r13 push %r12 -#else - push %edi - push %esi -#endif - push %_ASM_BX + push %rbx /* * Save variables needed after vmexit on the stack, in inverse @@ -316,39 +311,31 @@ SYM_FUNC_START(__svm_sev_es_vcpu_run) */ /* Accessed directly from the stack in RESTORE_HOST_SPEC_CTRL. */ - push %_ASM_ARG2 + push %rsi /* Save @svm. */ - push %_ASM_ARG1 - -.ifnc _ASM_ARG1, _ASM_DI - /* - * Stash @svm in RDI early. On 32-bit, arguments are in RAX, RCX - * and RDX which are clobbered by RESTORE_GUEST_SPEC_CTRL. - */ - mov %_ASM_ARG1, %_ASM_DI -.endif + push %rdi /* Clobbers RAX, RCX, RDX. */ RESTORE_GUEST_SPEC_CTRL /* Get svm->current_vmcb->pa into RAX. */ - mov SVM_current_vmcb(%_ASM_DI), %_ASM_AX - mov KVM_VMCB_pa(%_ASM_AX), %_ASM_AX + mov SVM_current_vmcb(%rdi), %rax + mov KVM_VMCB_pa(%rax), %rax /* Enter guest mode */ sti -1: vmrun %_ASM_AX +1: vmrun %rax 2: cli /* Pop @svm to RDI, guest registers have been saved already. */ - pop %_ASM_DI + pop %rdi #ifdef CONFIG_MITIGATION_RETPOLINE /* IMPORTANT: Stuff the RSB immediately after VM-Exit, before RET! */ - FILL_RETURN_BUFFER %_ASM_AX, RSB_CLEAR_LOOPS, X86_FEATURE_RETPOLINE + FILL_RETURN_BUFFER %rax, RSB_CLEAR_LOOPS, X86_FEATURE_RETPOLINE #endif /* Clobbers RAX, RCX, RDX. */ @@ -364,26 +351,21 @@ SYM_FUNC_START(__svm_sev_es_vcpu_run) UNTRAIN_RET_VM /* "Pop" @spec_ctrl_intercepted. */ - pop %_ASM_BX + pop %rbx - pop %_ASM_BX + pop %rbx -#ifdef CONFIG_X86_64 pop %r12 pop %r13 pop %r14 pop %r15 -#else - pop %esi - pop %edi -#endif - pop %_ASM_BP + pop %rbp RET RESTORE_GUEST_SPEC_CTRL_BODY RESTORE_HOST_SPEC_CTRL_BODY -3: cmpb $0, _ASM_RIP(kvm_rebooting) +3: cmpb $0, kvm_rebooting(%rip) jne 2b ud2 -- cgit v1.2.3 From 87e8e360a05fd29465691aeac179bcf585600c59 Mon Sep 17 00:00:00 2001 From: Sean Christopherson Date: Fri, 23 Feb 2024 12:42:29 -0800 Subject: KVM: SVM: Clobber RAX instead of RBX when discarding spec_ctrl_intercepted POP @spec_ctrl_intercepted into RAX instead of RBX when discarding it from the stack so that __svm_sev_es_vcpu_run() doesn't modify any non-volatile registers. __svm_sev_es_vcpu_run() doesn't return a value, and RAX is already are clobbered multiple times in the #VMEXIT path. This will allowing using the host save area to save/restore non-volatile registers in __svm_sev_es_vcpu_run(). Reviewed-by: Tom Lendacky Link: https://lore.kernel.org/r/20240223204233.3337324-5-seanjc@google.com Signed-off-by: Sean Christopherson --- arch/x86/kvm/svm/vmenter.S | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/x86/kvm/svm/vmenter.S b/arch/x86/kvm/svm/vmenter.S index c057866a459b..db94fb6f610a 100644 --- a/arch/x86/kvm/svm/vmenter.S +++ b/arch/x86/kvm/svm/vmenter.S @@ -350,8 +350,8 @@ SYM_FUNC_START(__svm_sev_es_vcpu_run) */ UNTRAIN_RET_VM - /* "Pop" @spec_ctrl_intercepted. */ - pop %rbx + /* "Pop" and discard @spec_ctrl_intercepted. */ + pop %rax pop %rbx -- cgit v1.2.3 From c92be2fd8edf7b300a758c185fe032fd0257b886 Mon Sep 17 00:00:00 2001 From: Sean Christopherson Date: Fri, 23 Feb 2024 12:42:30 -0800 Subject: KVM: SVM: Save/restore non-volatile GPRs in SEV-ES VMRUN via host save area Use the host save area to save/restore non-volatile (callee-saved) registers in __svm_sev_es_vcpu_run() to take advantage of hardware loading all registers from the save area on #VMEXIT. KVM still needs to save the registers it wants restored, but the loads are handled automatically by hardware. Aside from less assembly code, letting hardware do the restoration means stack frames are preserved for the entirety of __svm_sev_es_vcpu_run(). Opportunistically add a comment to call out why @svm needs to be saved across VMRUN->#VMEXIT, as it's not easy to decipher that from the macro hell. Cc: Tom Lendacky Cc: Michael Roth Cc: Alexey Kardashevskiy Reviewed-by: Tom Lendacky Link: https://lore.kernel.org/r/20240223204233.3337324-6-seanjc@google.com Signed-off-by: Sean Christopherson --- arch/x86/kvm/svm/svm.c | 17 ++++++++++------- arch/x86/kvm/svm/svm.h | 3 ++- arch/x86/kvm/svm/vmenter.S | 41 +++++++++++++++++++++++------------------ 3 files changed, 35 insertions(+), 26 deletions(-) diff --git a/arch/x86/kvm/svm/svm.c b/arch/x86/kvm/svm/svm.c index d1a9f9951635..9aaf83c8d57d 100644 --- a/arch/x86/kvm/svm/svm.c +++ b/arch/x86/kvm/svm/svm.c @@ -1503,6 +1503,11 @@ static void svm_vcpu_free(struct kvm_vcpu *vcpu) __free_pages(virt_to_page(svm->msrpm), get_order(MSRPM_SIZE)); } +static struct sev_es_save_area *sev_es_host_save_area(struct svm_cpu_data *sd) +{ + return page_address(sd->save_area) + 0x400; +} + static void svm_prepare_switch_to_guest(struct kvm_vcpu *vcpu) { struct vcpu_svm *svm = to_svm(vcpu); @@ -1519,12 +1524,8 @@ static void svm_prepare_switch_to_guest(struct kvm_vcpu *vcpu) * or subsequent vmload of host save area. */ vmsave(sd->save_area_pa); - if (sev_es_guest(vcpu->kvm)) { - struct sev_es_save_area *hostsa; - hostsa = (struct sev_es_save_area *)(page_address(sd->save_area) + 0x400); - - sev_es_prepare_switch_to_guest(hostsa); - } + if (sev_es_guest(vcpu->kvm)) + sev_es_prepare_switch_to_guest(sev_es_host_save_area(sd)); if (tsc_scaling) __svm_write_tsc_multiplier(vcpu->arch.tsc_scaling_ratio); @@ -4101,6 +4102,7 @@ static fastpath_t svm_exit_handlers_fastpath(struct kvm_vcpu *vcpu) static noinstr void svm_vcpu_enter_exit(struct kvm_vcpu *vcpu, bool spec_ctrl_intercepted) { + struct svm_cpu_data *sd = per_cpu_ptr(&svm_data, vcpu->cpu); struct vcpu_svm *svm = to_svm(vcpu); guest_state_enter_irqoff(); @@ -4108,7 +4110,8 @@ static noinstr void svm_vcpu_enter_exit(struct kvm_vcpu *vcpu, bool spec_ctrl_in amd_clear_divider(); if (sev_es_guest(vcpu->kvm)) - __svm_sev_es_vcpu_run(svm, spec_ctrl_intercepted); + __svm_sev_es_vcpu_run(svm, spec_ctrl_intercepted, + sev_es_host_save_area(sd)); else __svm_vcpu_run(svm, spec_ctrl_intercepted); diff --git a/arch/x86/kvm/svm/svm.h b/arch/x86/kvm/svm/svm.h index 7f1fbd874c45..33878efdebc8 100644 --- a/arch/x86/kvm/svm/svm.h +++ b/arch/x86/kvm/svm/svm.h @@ -698,7 +698,8 @@ struct page *snp_safe_alloc_page(struct kvm_vcpu *vcpu); /* vmenter.S */ -void __svm_sev_es_vcpu_run(struct vcpu_svm *svm, bool spec_ctrl_intercepted); +void __svm_sev_es_vcpu_run(struct vcpu_svm *svm, bool spec_ctrl_intercepted, + struct sev_es_save_area *hostsa); void __svm_vcpu_run(struct vcpu_svm *svm, bool spec_ctrl_intercepted); #define DEFINE_KVM_GHCB_ACCESSORS(field) \ diff --git a/arch/x86/kvm/svm/vmenter.S b/arch/x86/kvm/svm/vmenter.S index db94fb6f610a..7f627d535afc 100644 --- a/arch/x86/kvm/svm/vmenter.S +++ b/arch/x86/kvm/svm/vmenter.S @@ -292,23 +292,35 @@ SYM_FUNC_START(__svm_vcpu_run) SYM_FUNC_END(__svm_vcpu_run) #ifdef CONFIG_KVM_AMD_SEV + + +#ifdef CONFIG_X86_64 +#define SEV_ES_GPRS_BASE 0x300 +#define SEV_ES_RBX (SEV_ES_GPRS_BASE + __VCPU_REGS_RBX * WORD_SIZE) +#define SEV_ES_RBP (SEV_ES_GPRS_BASE + __VCPU_REGS_RBP * WORD_SIZE) +#define SEV_ES_R12 (SEV_ES_GPRS_BASE + __VCPU_REGS_R12 * WORD_SIZE) +#define SEV_ES_R13 (SEV_ES_GPRS_BASE + __VCPU_REGS_R13 * WORD_SIZE) +#define SEV_ES_R14 (SEV_ES_GPRS_BASE + __VCPU_REGS_R14 * WORD_SIZE) +#define SEV_ES_R15 (SEV_ES_GPRS_BASE + __VCPU_REGS_R15 * WORD_SIZE) +#endif + /** * __svm_sev_es_vcpu_run - Run a SEV-ES vCPU via a transition to SVM guest mode * @svm: struct vcpu_svm * * @spec_ctrl_intercepted: bool */ SYM_FUNC_START(__svm_sev_es_vcpu_run) - push %rbp - push %r15 - push %r14 - push %r13 - push %r12 - push %rbx - /* - * Save variables needed after vmexit on the stack, in inverse - * order compared to when they are needed. + * Save non-volatile (callee-saved) registers to the host save area. + * Except for RAX and RSP, all GPRs are restored on #VMEXIT, but not + * saved on VMRUN. */ + mov %rbp, SEV_ES_RBP (%rdx) + mov %r15, SEV_ES_R15 (%rdx) + mov %r14, SEV_ES_R14 (%rdx) + mov %r13, SEV_ES_R13 (%rdx) + mov %r12, SEV_ES_R12 (%rdx) + mov %rbx, SEV_ES_RBX (%rdx) /* Accessed directly from the stack in RESTORE_HOST_SPEC_CTRL. */ push %rsi @@ -316,7 +328,7 @@ SYM_FUNC_START(__svm_sev_es_vcpu_run) /* Save @svm. */ push %rdi - /* Clobbers RAX, RCX, RDX. */ + /* Clobbers RAX, RCX, RDX (@hostsa). */ RESTORE_GUEST_SPEC_CTRL /* Get svm->current_vmcb->pa into RAX. */ @@ -338,7 +350,7 @@ SYM_FUNC_START(__svm_sev_es_vcpu_run) FILL_RETURN_BUFFER %rax, RSB_CLEAR_LOOPS, X86_FEATURE_RETPOLINE #endif - /* Clobbers RAX, RCX, RDX. */ + /* Clobbers RAX, RCX, RDX, consumes RDI (@svm). */ RESTORE_HOST_SPEC_CTRL /* @@ -353,13 +365,6 @@ SYM_FUNC_START(__svm_sev_es_vcpu_run) /* "Pop" and discard @spec_ctrl_intercepted. */ pop %rax - pop %rbx - - pop %r12 - pop %r13 - pop %r14 - pop %r15 - pop %rbp RET RESTORE_GUEST_SPEC_CTRL_BODY -- cgit v1.2.3 From adac42bf42c1608f23938c03e3ca53fa6c87f337 Mon Sep 17 00:00:00 2001 From: Sean Christopherson Date: Fri, 23 Feb 2024 12:42:31 -0800 Subject: KVM: SVM: Save/restore args across SEV-ES VMRUN via host save area Use the host save area to preserve volatile registers that are used in __svm_sev_es_vcpu_run() to access function parameters after #VMEXIT. Like saving/restoring non-volatile registers, there's no reason not to take advantage of hardware restoring registers on #VMEXIT, as doing so shaves a few instructions and the save area is going to be accessed no matter what. Converting all register save/restore code to use the host save area also make it easier to follow the SEV-ES VMRUN flow in its entirety, as opposed to having a mix of stack-based versus host save area save/restore. Add a parameter to RESTORE_HOST_SPEC_CTRL_BODY so that the SEV-ES path doesn't need to write @spec_ctrl_intercepted to memory just to play nice with the common macro. Reviewed-by: Tom Lendacky Link: https://lore.kernel.org/r/20240223204233.3337324-7-seanjc@google.com Signed-off-by: Sean Christopherson --- arch/x86/kvm/svm/vmenter.S | 29 +++++++++++++---------------- 1 file changed, 13 insertions(+), 16 deletions(-) diff --git a/arch/x86/kvm/svm/vmenter.S b/arch/x86/kvm/svm/vmenter.S index 7f627d535afc..d1613395dd39 100644 --- a/arch/x86/kvm/svm/vmenter.S +++ b/arch/x86/kvm/svm/vmenter.S @@ -67,7 +67,7 @@ "", X86_FEATURE_V_SPEC_CTRL 901: .endm -.macro RESTORE_HOST_SPEC_CTRL_BODY +.macro RESTORE_HOST_SPEC_CTRL_BODY spec_ctrl_intercepted:req 900: /* Same for after vmexit. */ mov $MSR_IA32_SPEC_CTRL, %ecx @@ -76,7 +76,7 @@ * Load the value that the guest had written into MSR_IA32_SPEC_CTRL, * if it was not intercepted during guest execution. */ - cmpb $0, (%_ASM_SP) + cmpb $0, \spec_ctrl_intercepted jnz 998f rdmsr movl %eax, SVM_spec_ctrl(%_ASM_DI) @@ -269,7 +269,7 @@ SYM_FUNC_START(__svm_vcpu_run) RET RESTORE_GUEST_SPEC_CTRL_BODY - RESTORE_HOST_SPEC_CTRL_BODY + RESTORE_HOST_SPEC_CTRL_BODY (%_ASM_SP) 10: cmpb $0, _ASM_RIP(kvm_rebooting) jne 2b @@ -298,6 +298,8 @@ SYM_FUNC_END(__svm_vcpu_run) #define SEV_ES_GPRS_BASE 0x300 #define SEV_ES_RBX (SEV_ES_GPRS_BASE + __VCPU_REGS_RBX * WORD_SIZE) #define SEV_ES_RBP (SEV_ES_GPRS_BASE + __VCPU_REGS_RBP * WORD_SIZE) +#define SEV_ES_RSI (SEV_ES_GPRS_BASE + __VCPU_REGS_RSI * WORD_SIZE) +#define SEV_ES_RDI (SEV_ES_GPRS_BASE + __VCPU_REGS_RDI * WORD_SIZE) #define SEV_ES_R12 (SEV_ES_GPRS_BASE + __VCPU_REGS_R12 * WORD_SIZE) #define SEV_ES_R13 (SEV_ES_GPRS_BASE + __VCPU_REGS_R13 * WORD_SIZE) #define SEV_ES_R14 (SEV_ES_GPRS_BASE + __VCPU_REGS_R14 * WORD_SIZE) @@ -322,11 +324,12 @@ SYM_FUNC_START(__svm_sev_es_vcpu_run) mov %r12, SEV_ES_R12 (%rdx) mov %rbx, SEV_ES_RBX (%rdx) - /* Accessed directly from the stack in RESTORE_HOST_SPEC_CTRL. */ - push %rsi - - /* Save @svm. */ - push %rdi + /* + * Save volatile registers that hold arguments that are needed after + * #VMEXIT (RDI=@svm and RSI=@spec_ctrl_intercepted). + */ + mov %rdi, SEV_ES_RDI (%rdx) + mov %rsi, SEV_ES_RSI (%rdx) /* Clobbers RAX, RCX, RDX (@hostsa). */ RESTORE_GUEST_SPEC_CTRL @@ -342,15 +345,12 @@ SYM_FUNC_START(__svm_sev_es_vcpu_run) 2: cli - /* Pop @svm to RDI, guest registers have been saved already. */ - pop %rdi - #ifdef CONFIG_MITIGATION_RETPOLINE /* IMPORTANT: Stuff the RSB immediately after VM-Exit, before RET! */ FILL_RETURN_BUFFER %rax, RSB_CLEAR_LOOPS, X86_FEATURE_RETPOLINE #endif - /* Clobbers RAX, RCX, RDX, consumes RDI (@svm). */ + /* Clobbers RAX, RCX, RDX, consumes RDI (@svm) and RSI (@spec_ctrl_intercepted). */ RESTORE_HOST_SPEC_CTRL /* @@ -362,13 +362,10 @@ SYM_FUNC_START(__svm_sev_es_vcpu_run) */ UNTRAIN_RET_VM - /* "Pop" and discard @spec_ctrl_intercepted. */ - pop %rax - RET RESTORE_GUEST_SPEC_CTRL_BODY - RESTORE_HOST_SPEC_CTRL_BODY + RESTORE_HOST_SPEC_CTRL_BODY %sil 3: cmpb $0, kvm_rebooting(%rip) jne 2b -- cgit v1.2.3 From 4367a75887ec8d68932cd84ea9cffe24d7a55fa0 Mon Sep 17 00:00:00 2001 From: Sean Christopherson Date: Fri, 23 Feb 2024 12:42:32 -0800 Subject: KVM: SVM: Create a stack frame in __svm_sev_es_vcpu_run() Now that KVM uses the host save area to context switch RBP, i.e. preserves RBP for the entirety of __svm_sev_es_vcpu_run(), create a stack frame using the standared FRAME_{BEGIN,END} macros. Note, __svm_sev_es_vcpu_run() is subtly not a leaf function as it can call into ibpb_feature() via UNTRAIN_RET_VM. Reviewed-by: Tom Lendacky Link: https://lore.kernel.org/r/20240223204233.3337324-8-seanjc@google.com Signed-off-by: Sean Christopherson --- arch/x86/kvm/svm/vmenter.S | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/arch/x86/kvm/svm/vmenter.S b/arch/x86/kvm/svm/vmenter.S index d1613395dd39..a0c8eb37d3e1 100644 --- a/arch/x86/kvm/svm/vmenter.S +++ b/arch/x86/kvm/svm/vmenter.S @@ -3,6 +3,7 @@ #include #include #include +#include #include #include #include "kvm-asm-offsets.h" @@ -312,6 +313,8 @@ SYM_FUNC_END(__svm_vcpu_run) * @spec_ctrl_intercepted: bool */ SYM_FUNC_START(__svm_sev_es_vcpu_run) + FRAME_BEGIN + /* * Save non-volatile (callee-saved) registers to the host save area. * Except for RAX and RSP, all GPRs are restored on #VMEXIT, but not @@ -362,6 +365,7 @@ SYM_FUNC_START(__svm_sev_es_vcpu_run) */ UNTRAIN_RET_VM + FRAME_END RET RESTORE_GUEST_SPEC_CTRL_BODY -- cgit v1.2.3 From 27ca867042affef7eba692d3bac7b51ee85e36ad Mon Sep 17 00:00:00 2001 From: Sean Christopherson Date: Fri, 23 Feb 2024 12:42:33 -0800 Subject: KVM: x86: Stop compiling vmenter.S with OBJECT_FILES_NON_STANDARD Stop compiling vmenter.S with OBJECT_FILES_NON_STANDARD to skip objtool's stack validation now that __svm_vcpu_run() and __svm_sev_es_vcpu_run() create stack frames (though the former's effectiveness is dubious). Note, due to a quirk in how OBJECT_FILES_NON_STANDARD was handled by the build system prior to commit bf48d9b756b9 ("kbuild: change tool coverage variables to take the path relative to $(obj)"), vmx/vmenter.S got lumped in with svm/vmenter.S. __vmx_vcpu_run() already plays nice with frame pointers, i.e. it was collateral damage when commit 7f4b5cde2409 ("kvm: Disable objtool frame pointer checking for vmenter.S") added the OBJECT_FILES_NON_STANDARD hack-a-fix. Link: https://lore.kernel.org/all/20240217055504.2059803-1-masahiroy@kernel.org Reviewed-by: Tom Lendacky Link: https://lore.kernel.org/r/20240223204233.3337324-9-seanjc@google.com Signed-off-by: Sean Christopherson --- arch/x86/kvm/Makefile | 5 ----- 1 file changed, 5 deletions(-) diff --git a/arch/x86/kvm/Makefile b/arch/x86/kvm/Makefile index a88bb14266b6..addc44fc7187 100644 --- a/arch/x86/kvm/Makefile +++ b/arch/x86/kvm/Makefile @@ -3,11 +3,6 @@ ccflags-y += -I $(srctree)/arch/x86/kvm ccflags-$(CONFIG_KVM_WERROR) += -Werror -ifeq ($(CONFIG_FRAME_POINTER),y) -OBJECT_FILES_NON_STANDARD_vmx/vmenter.o := y -OBJECT_FILES_NON_STANDARD_svm/vmenter.o := y -endif - include $(srctree)/virt/kvm/Makefile.kvm kvm-y += x86.o emulate.o i8259.o irq.o lapic.o \ -- cgit v1.2.3 From 4c08f01934ab67d1d283d5cbaa52b923abcfe4cd Mon Sep 17 00:00:00 2001 From: Zack Rusin Date: Sun, 7 Apr 2024 22:28:02 -0400 Subject: drm/vmwgfx: Enable DMA mappings with SEV Enable DMA mappings in vmwgfx after TTM has been fixed in commit 3bf3710e3718 ("drm/ttm: Add a generic TTM memcpy move for page-based iomem") This enables full guest-backed memory support and in particular allows usage of screen targets as the presentation mechanism. Signed-off-by: Zack Rusin Reported-by: Ye Li Tested-by: Ye Li Fixes: 3b0d6458c705 ("drm/vmwgfx: Refuse DMA operation when SEV encryption is active") Cc: Broadcom internal kernel review list Cc: dri-devel@lists.freedesktop.org Cc: # v6.6+ Reviewed-by: Martin Krastev Link: https://patchwork.freedesktop.org/patch/msgid/20240408022802.358641-1-zack.rusin@broadcom.com --- drivers/gpu/drm/vmwgfx/vmwgfx_drv.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c index c7d90f96d16a..0a304706e013 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c @@ -666,11 +666,12 @@ static int vmw_dma_select_mode(struct vmw_private *dev_priv) [vmw_dma_map_populate] = "Caching DMA mappings.", [vmw_dma_map_bind] = "Giving up DMA mappings early."}; - /* TTM currently doesn't fully support SEV encryption. */ - if (cc_platform_has(CC_ATTR_MEM_ENCRYPT)) - return -EINVAL; - - if (vmw_force_coherent) + /* + * When running with SEV we always want dma mappings, because + * otherwise ttm tt pool pages will bounce through swiotlb running + * out of available space. + */ + if (vmw_force_coherent || cc_platform_has(CC_ATTR_MEM_ENCRYPT)) dev_priv->map_mode = vmw_dma_alloc_coherent; else if (vmw_restrict_iommu) dev_priv->map_mode = vmw_dma_map_bind; -- cgit v1.2.3 From 05a2f07db8883b027c0b4a475fcc586278922b8d Mon Sep 17 00:00:00 2001 From: Patryk Wlazlyn Date: Tue, 5 Mar 2024 12:27:27 +0100 Subject: tools/power turbostat: read RAPL counters via perf Some of the future Intel platforms will require reading the RAPL counters via perf and not MSR. On current platforms we can still read them using both ways. Signed-off-by: Patryk Wlazlyn Signed-off-by: Len Brown --- tools/power/x86/turbostat/turbostat.c | 786 ++++++++++++++++++++++++++++------ 1 file changed, 649 insertions(+), 137 deletions(-) diff --git a/tools/power/x86/turbostat/turbostat.c b/tools/power/x86/turbostat/turbostat.c index a380829c5890..283dffb987b5 100644 --- a/tools/power/x86/turbostat/turbostat.c +++ b/tools/power/x86/turbostat/turbostat.c @@ -37,6 +37,7 @@ #include #include #include +#include #define UNUSED(x) (void)(x) @@ -60,6 +61,7 @@ enum counter_scope { SCOPE_CPU, SCOPE_CORE, SCOPE_PACKAGE }; enum counter_type { COUNTER_ITEMS, COUNTER_CYCLES, COUNTER_SECONDS, COUNTER_USEC }; enum counter_format { FORMAT_RAW, FORMAT_DELTA, FORMAT_PERCENT }; enum amperf_source { AMPERF_SOURCE_PERF, AMPERF_SOURCE_MSR }; +enum rapl_source { RAPL_SOURCE_NONE, RAPL_SOURCE_PERF, RAPL_SOURCE_MSR }; struct msr_counter { unsigned int msr_num; @@ -958,6 +960,175 @@ size_t cpu_present_setsize, cpu_effective_setsize, cpu_allowed_setsize, cpu_affi #define MAX_ADDED_THREAD_COUNTERS 24 #define BITMASK_SIZE 32 +/* Indexes used to map data read from perf and MSRs into global variables */ +enum rapl_rci_index { + RAPL_RCI_INDEX_ENERGY_PKG = 0, + RAPL_RCI_INDEX_ENERGY_CORES = 1, + RAPL_RCI_INDEX_DRAM = 2, + RAPL_RCI_INDEX_GFX = 3, + RAPL_RCI_INDEX_PKG_PERF_STATUS = 4, + RAPL_RCI_INDEX_DRAM_PERF_STATUS = 5, + RAPL_RCI_INDEX_CORE_ENERGY = 6, + NUM_RAPL_COUNTERS, +}; + +enum rapl_unit { + RAPL_UNIT_INVALID, + RAPL_UNIT_JOULES, + RAPL_UNIT_WATTS, +}; + +struct rapl_counter_info_t { + unsigned long long data[NUM_RAPL_COUNTERS]; + enum rapl_source source[NUM_RAPL_COUNTERS]; + unsigned long long flags[NUM_RAPL_COUNTERS]; + double scale[NUM_RAPL_COUNTERS]; + enum rapl_unit unit[NUM_RAPL_COUNTERS]; + + union { + /* Active when source == RAPL_SOURCE_MSR */ + struct { + unsigned long long msr[NUM_RAPL_COUNTERS]; + unsigned long long msr_mask[NUM_RAPL_COUNTERS]; + int msr_shift[NUM_RAPL_COUNTERS]; + }; + }; + + int fd_perf; +}; + +/* struct rapl_counter_info_t for each RAPL domain */ +struct rapl_counter_info_t *rapl_counter_info_perdomain; + +#define RAPL_COUNTER_FLAG_USE_MSR_SUM (1u << 1) + +struct rapl_counter_arch_info { + int feature_mask; /* Mask for testing if the counter is supported on host */ + const char *perf_subsys; + const char *perf_name; + unsigned long long msr; + unsigned long long msr_mask; + int msr_shift; /* Positive mean shift right, negative mean shift left */ + double *platform_rapl_msr_scale; /* Scale applied to values read by MSR (platform dependent, filled at runtime) */ + unsigned int rci_index; /* Maps data from perf counters to global variables */ + unsigned long long bic; + double compat_scale; /* Some counters require constant scaling to be in the same range as other, similar ones */ + unsigned long long flags; +}; + +static const struct rapl_counter_arch_info rapl_counter_arch_infos[] = { + { + .feature_mask = RAPL_PKG, + .perf_subsys = "power", + .perf_name = "energy-pkg", + .msr = MSR_PKG_ENERGY_STATUS, + .msr_mask = 0xFFFFFFFFFFFFFFFF, + .msr_shift = 0, + .platform_rapl_msr_scale = &rapl_energy_units, + .rci_index = RAPL_RCI_INDEX_ENERGY_PKG, + .bic = BIC_PkgWatt | BIC_Pkg_J, + .compat_scale = 1.0, + .flags = RAPL_COUNTER_FLAG_USE_MSR_SUM, + }, + { + .feature_mask = RAPL_AMD_F17H, + .perf_subsys = "power", + .perf_name = "energy-pkg", + .msr = MSR_PKG_ENERGY_STAT, + .msr_mask = 0xFFFFFFFFFFFFFFFF, + .msr_shift = 0, + .platform_rapl_msr_scale = &rapl_energy_units, + .rci_index = RAPL_RCI_INDEX_ENERGY_PKG, + .bic = BIC_PkgWatt | BIC_Pkg_J, + .compat_scale = 1.0, + .flags = RAPL_COUNTER_FLAG_USE_MSR_SUM, + }, + { + .feature_mask = RAPL_CORE_ENERGY_STATUS, + .perf_subsys = "power", + .perf_name = "energy-cores", + .msr = MSR_PP0_ENERGY_STATUS, + .msr_mask = 0xFFFFFFFFFFFFFFFF, + .msr_shift = 0, + .platform_rapl_msr_scale = &rapl_energy_units, + .rci_index = RAPL_RCI_INDEX_ENERGY_CORES, + .bic = BIC_CorWatt | BIC_Cor_J, + .compat_scale = 1.0, + .flags = RAPL_COUNTER_FLAG_USE_MSR_SUM, + }, + { + .feature_mask = RAPL_DRAM, + .perf_subsys = "power", + .perf_name = "energy-ram", + .msr = MSR_DRAM_ENERGY_STATUS, + .msr_mask = 0xFFFFFFFFFFFFFFFF, + .msr_shift = 0, + .platform_rapl_msr_scale = &rapl_dram_energy_units, + .rci_index = RAPL_RCI_INDEX_DRAM, + .bic = BIC_RAMWatt | BIC_RAM_J, + .compat_scale = 1.0, + .flags = RAPL_COUNTER_FLAG_USE_MSR_SUM, + }, + { + .feature_mask = RAPL_GFX, + .perf_subsys = "power", + .perf_name = "energy-gpu", + .msr = MSR_PP1_ENERGY_STATUS, + .msr_mask = 0xFFFFFFFFFFFFFFFF, + .msr_shift = 0, + .platform_rapl_msr_scale = &rapl_energy_units, + .rci_index = RAPL_RCI_INDEX_GFX, + .bic = BIC_GFXWatt | BIC_GFX_J, + .compat_scale = 1.0, + .flags = RAPL_COUNTER_FLAG_USE_MSR_SUM, + }, + { + .feature_mask = RAPL_PKG_PERF_STATUS, + .perf_subsys = NULL, + .perf_name = NULL, + .msr = MSR_PKG_PERF_STATUS, + .msr_mask = 0xFFFFFFFFFFFFFFFF, + .msr_shift = 0, + .platform_rapl_msr_scale = &rapl_time_units, + .rci_index = RAPL_RCI_INDEX_PKG_PERF_STATUS, + .bic = BIC_PKG__, + .compat_scale = 100.0, + .flags = RAPL_COUNTER_FLAG_USE_MSR_SUM, + }, + { + .feature_mask = RAPL_DRAM_PERF_STATUS, + .perf_subsys = NULL, + .perf_name = NULL, + .msr = MSR_DRAM_PERF_STATUS, + .msr_mask = 0xFFFFFFFFFFFFFFFF, + .msr_shift = 0, + .platform_rapl_msr_scale = &rapl_time_units, + .rci_index = RAPL_RCI_INDEX_DRAM_PERF_STATUS, + .bic = BIC_RAM__, + .compat_scale = 100.0, + .flags = RAPL_COUNTER_FLAG_USE_MSR_SUM, + }, + { + .feature_mask = RAPL_AMD_F17H, + .perf_subsys = NULL, + .perf_name = NULL, + .msr = MSR_CORE_ENERGY_STAT, + .msr_mask = 0xFFFFFFFF, + .msr_shift = 0, + .platform_rapl_msr_scale = &rapl_energy_units, + .rci_index = RAPL_RCI_INDEX_CORE_ENERGY, + .bic = BIC_CorWatt | BIC_Cor_J, + .compat_scale = 1.0, + .flags = 0, + }, +}; + +struct rapl_counter { + unsigned long long raw_value; + enum rapl_unit unit; + double scale; +}; + struct thread_data { struct timeval tv_begin; struct timeval tv_end; @@ -984,7 +1155,7 @@ struct core_data { unsigned long long c7; unsigned long long mc6_us; /* duplicate as per-core for now, even though per module */ unsigned int core_temp_c; - unsigned int core_energy; /* MSR_CORE_ENERGY_STAT */ + struct rapl_counter core_energy; /* MSR_CORE_ENERGY_STAT */ unsigned int core_id; unsigned long long core_throt_cnt; unsigned long long counter[MAX_ADDED_COUNTERS]; @@ -1009,12 +1180,12 @@ struct pkg_data { unsigned int gfx_mhz; unsigned int gfx_act_mhz; unsigned int package_id; - unsigned long long energy_pkg; /* MSR_PKG_ENERGY_STATUS */ - unsigned long long energy_dram; /* MSR_DRAM_ENERGY_STATUS */ - unsigned long long energy_cores; /* MSR_PP0_ENERGY_STATUS */ - unsigned long long energy_gfx; /* MSR_PP1_ENERGY_STATUS */ - unsigned long long rapl_pkg_perf_status; /* MSR_PKG_PERF_STATUS */ - unsigned long long rapl_dram_perf_status; /* MSR_DRAM_PERF_STATUS */ + struct rapl_counter energy_pkg; /* MSR_PKG_ENERGY_STATUS */ + struct rapl_counter energy_dram; /* MSR_DRAM_ENERGY_STATUS */ + struct rapl_counter energy_cores; /* MSR_PP0_ENERGY_STATUS */ + struct rapl_counter energy_gfx; /* MSR_PP1_ENERGY_STATUS */ + struct rapl_counter rapl_pkg_perf_status; /* MSR_PKG_PERF_STATUS */ + struct rapl_counter rapl_dram_perf_status; /* MSR_DRAM_PERF_STATUS */ unsigned int pkg_temp_c; unsigned int uncore_mhz; unsigned long long counter[MAX_ADDED_COUNTERS]; @@ -1403,6 +1574,21 @@ int get_msr(int cpu, off_t offset, unsigned long long *msr) return 0; } +int probe_msr(int cpu, off_t offset) +{ + ssize_t retval; + unsigned long long dummy; + + assert(!no_msr); + + retval = pread(get_msr_fd(cpu), &dummy, sizeof(dummy), offset); + + if (retval != sizeof(dummy)) + return 1; + + return 0; +} + #define MAX_DEFERRED 16 char *deferred_add_names[MAX_DEFERRED]; char *deferred_skip_names[MAX_DEFERRED]; @@ -1755,7 +1941,11 @@ int dump_counters(struct thread_data *t, struct core_data *c, struct pkg_data *p outp += sprintf(outp, "c7: %016llX\n", c->c7); outp += sprintf(outp, "DTS: %dC\n", c->core_temp_c); outp += sprintf(outp, "cpu_throt_count: %016llX\n", c->core_throt_cnt); - outp += sprintf(outp, "Joules: %0X\n", c->core_energy); + + const unsigned long long energy_value = c->core_energy.raw_value * c->core_energy.scale; + const double energy_scale = c->core_energy.scale; + if (c->core_energy.unit == RAPL_UNIT_JOULES) + outp += sprintf(outp, "Joules: %0llX (scale: %lf)\n", energy_value, energy_scale); for (i = 0, mp = sys.cp; mp; i++, mp = mp->next) { outp += @@ -1785,12 +1975,12 @@ int dump_counters(struct thread_data *t, struct core_data *c, struct pkg_data *p outp += sprintf(outp, "pc10: %016llX\n", p->pc10); outp += sprintf(outp, "cpu_lpi: %016llX\n", p->cpu_lpi); outp += sprintf(outp, "sys_lpi: %016llX\n", p->sys_lpi); - outp += sprintf(outp, "Joules PKG: %0llX\n", p->energy_pkg); - outp += sprintf(outp, "Joules COR: %0llX\n", p->energy_cores); - outp += sprintf(outp, "Joules GFX: %0llX\n", p->energy_gfx); - outp += sprintf(outp, "Joules RAM: %0llX\n", p->energy_dram); - outp += sprintf(outp, "Throttle PKG: %0llX\n", p->rapl_pkg_perf_status); - outp += sprintf(outp, "Throttle RAM: %0llX\n", p->rapl_dram_perf_status); + outp += sprintf(outp, "Joules PKG: %0llX\n", p->energy_pkg.raw_value); + outp += sprintf(outp, "Joules COR: %0llX\n", p->energy_cores.raw_value); + outp += sprintf(outp, "Joules GFX: %0llX\n", p->energy_gfx.raw_value); + outp += sprintf(outp, "Joules RAM: %0llX\n", p->energy_dram.raw_value); + outp += sprintf(outp, "Throttle PKG: %0llX\n", p->rapl_pkg_perf_status.raw_value); + outp += sprintf(outp, "Throttle RAM: %0llX\n", p->rapl_dram_perf_status.raw_value); outp += sprintf(outp, "PTM: %dC\n", p->pkg_temp_c); for (i = 0, mp = sys.pp; mp; i++, mp = mp->next) { @@ -1805,6 +1995,23 @@ int dump_counters(struct thread_data *t, struct core_data *c, struct pkg_data *p return 0; } +double rapl_counter_get_value(const struct rapl_counter *c, enum rapl_unit desired_unit, double interval) +{ + assert(desired_unit != RAPL_UNIT_INVALID); + + /* + * For now we don't expect anything other than joules, + * so just simplify the logic. + */ + assert(c->unit == RAPL_UNIT_JOULES); + + const double scaled = c->raw_value * c->scale; + + if (desired_unit == RAPL_UNIT_WATTS) + return scaled / interval; + return scaled; +} + /* * column formatting convention & formats */ @@ -1998,9 +2205,11 @@ int format_counters(struct thread_data *t, struct core_data *c, struct pkg_data if (DO_BIC(BIC_CorWatt) && platform->has_per_core_rapl) outp += - sprintf(outp, fmt8, (printed++ ? delim : ""), c->core_energy * rapl_energy_units / interval_float); + sprintf(outp, fmt8, (printed++ ? delim : ""), + rapl_counter_get_value(&c->core_energy, RAPL_UNIT_WATTS, interval_float)); if (DO_BIC(BIC_Cor_J) && platform->has_per_core_rapl) - outp += sprintf(outp, fmt8, (printed++ ? delim : ""), c->core_energy * rapl_energy_units); + outp += sprintf(outp, fmt8, (printed++ ? delim : ""), + rapl_counter_get_value(&c->core_energy, RAPL_UNIT_JOULES, interval_float)); /* print per-package data only for 1st core in package */ if (!is_cpu_first_core_in_package(t, c, p)) @@ -2072,34 +2281,40 @@ int format_counters(struct thread_data *t, struct core_data *c, struct pkg_data if (DO_BIC(BIC_PkgWatt)) outp += - sprintf(outp, fmt8, (printed++ ? delim : ""), p->energy_pkg * rapl_energy_units / interval_float); - + sprintf(outp, fmt8, (printed++ ? delim : ""), + rapl_counter_get_value(&p->energy_pkg, RAPL_UNIT_WATTS, interval_float)); if (DO_BIC(BIC_CorWatt) && !platform->has_per_core_rapl) outp += - sprintf(outp, fmt8, (printed++ ? delim : ""), p->energy_cores * rapl_energy_units / interval_float); + sprintf(outp, fmt8, (printed++ ? delim : ""), + rapl_counter_get_value(&p->energy_cores, RAPL_UNIT_WATTS, interval_float)); if (DO_BIC(BIC_GFXWatt)) outp += - sprintf(outp, fmt8, (printed++ ? delim : ""), p->energy_gfx * rapl_energy_units / interval_float); + sprintf(outp, fmt8, (printed++ ? delim : ""), + rapl_counter_get_value(&p->energy_gfx, RAPL_UNIT_WATTS, interval_float)); if (DO_BIC(BIC_RAMWatt)) outp += sprintf(outp, fmt8, (printed++ ? delim : ""), - p->energy_dram * rapl_dram_energy_units / interval_float); + rapl_counter_get_value(&p->energy_dram, RAPL_UNIT_WATTS, interval_float)); if (DO_BIC(BIC_Pkg_J)) - outp += sprintf(outp, fmt8, (printed++ ? delim : ""), p->energy_pkg * rapl_energy_units); + outp += sprintf(outp, fmt8, (printed++ ? delim : ""), + rapl_counter_get_value(&p->energy_pkg, RAPL_UNIT_JOULES, interval_float)); if (DO_BIC(BIC_Cor_J) && !platform->has_per_core_rapl) - outp += sprintf(outp, fmt8, (printed++ ? delim : ""), p->energy_cores * rapl_energy_units); + outp += sprintf(outp, fmt8, (printed++ ? delim : ""), + rapl_counter_get_value(&p->energy_cores, RAPL_UNIT_JOULES, interval_float)); if (DO_BIC(BIC_GFX_J)) - outp += sprintf(outp, fmt8, (printed++ ? delim : ""), p->energy_gfx * rapl_energy_units); + outp += sprintf(outp, fmt8, (printed++ ? delim : ""), + rapl_counter_get_value(&p->energy_gfx, RAPL_UNIT_JOULES, interval_float)); if (DO_BIC(BIC_RAM_J)) - outp += sprintf(outp, fmt8, (printed++ ? delim : ""), p->energy_dram * rapl_dram_energy_units); + outp += sprintf(outp, fmt8, (printed++ ? delim : ""), + rapl_counter_get_value(&p->energy_dram, RAPL_UNIT_JOULES, interval_float)); if (DO_BIC(BIC_PKG__)) outp += sprintf(outp, fmt8, (printed++ ? delim : ""), - 100.0 * p->rapl_pkg_perf_status * rapl_time_units / interval_float); + rapl_counter_get_value(&p->rapl_pkg_perf_status, RAPL_UNIT_WATTS, interval_float)); if (DO_BIC(BIC_RAM__)) outp += sprintf(outp, fmt8, (printed++ ? delim : ""), - 100.0 * p->rapl_dram_perf_status * rapl_time_units / interval_float); + rapl_counter_get_value(&p->rapl_dram_perf_status, RAPL_UNIT_WATTS, interval_float)); /* UncMHz */ if (DO_BIC(BIC_UNCORE_MHZ)) outp += sprintf(outp, "%s%d", (printed++ ? delim : ""), p->uncore_mhz); @@ -2208,12 +2423,13 @@ int delta_package(struct pkg_data *new, struct pkg_data *old) old->gfx_mhz = new->gfx_mhz; old->gfx_act_mhz = new->gfx_act_mhz; - old->energy_pkg = new->energy_pkg - old->energy_pkg; - old->energy_cores = new->energy_cores - old->energy_cores; - old->energy_gfx = new->energy_gfx - old->energy_gfx; - old->energy_dram = new->energy_dram - old->energy_dram; - old->rapl_pkg_perf_status = new->rapl_pkg_perf_status - old->rapl_pkg_perf_status; - old->rapl_dram_perf_status = new->rapl_dram_perf_status - old->rapl_dram_perf_status; + old->energy_pkg.raw_value = new->energy_pkg.raw_value - old->energy_pkg.raw_value; + old->energy_cores.raw_value = new->energy_cores.raw_value - old->energy_cores.raw_value; + old->energy_gfx.raw_value = new->energy_gfx.raw_value - old->energy_gfx.raw_value; + old->energy_dram.raw_value = new->energy_dram.raw_value - old->energy_dram.raw_value; + old->rapl_pkg_perf_status.raw_value = new->rapl_pkg_perf_status.raw_value - old->rapl_pkg_perf_status.raw_value; + old->rapl_dram_perf_status.raw_value = + new->rapl_dram_perf_status.raw_value - old->rapl_dram_perf_status.raw_value; for (i = 0, mp = sys.pp; mp; i++, mp = mp->next) { if (mp->format == FORMAT_RAW) @@ -2237,7 +2453,7 @@ void delta_core(struct core_data *new, struct core_data *old) old->core_throt_cnt = new->core_throt_cnt; old->mc6_us = new->mc6_us - old->mc6_us; - DELTA_WRAP32(new->core_energy, old->core_energy); + DELTA_WRAP32(new->core_energy.raw_value, old->core_energy.raw_value); for (i = 0, mp = sys.cp; mp; i++, mp = mp->next) { if (mp->format == FORMAT_RAW) @@ -2364,6 +2580,13 @@ int delta_cpu(struct thread_data *t, struct core_data *c, return retval; } +void rapl_counter_clear(struct rapl_counter *c) +{ + c->raw_value = 0; + c->scale = 0.0; + c->unit = RAPL_UNIT_INVALID; +} + void clear_counters(struct thread_data *t, struct core_data *c, struct pkg_data *p) { int i; @@ -2391,7 +2614,7 @@ void clear_counters(struct thread_data *t, struct core_data *c, struct pkg_data c->c7 = 0; c->mc6_us = 0; c->core_temp_c = 0; - c->core_energy = 0; + rapl_counter_clear(&c->core_energy); c->core_throt_cnt = 0; p->pkg_wtd_core_c0 = 0; @@ -2412,12 +2635,12 @@ void clear_counters(struct thread_data *t, struct core_data *c, struct pkg_data p->cpu_lpi = 0; p->sys_lpi = 0; - p->energy_pkg = 0; - p->energy_dram = 0; - p->energy_cores = 0; - p->energy_gfx = 0; - p->rapl_pkg_perf_status = 0; - p->rapl_dram_perf_status = 0; + rapl_counter_clear(&p->energy_pkg); + rapl_counter_clear(&p->energy_dram); + rapl_counter_clear(&p->energy_cores); + rapl_counter_clear(&p->energy_gfx); + rapl_counter_clear(&p->rapl_pkg_perf_status); + rapl_counter_clear(&p->rapl_dram_perf_status); p->pkg_temp_c = 0; p->gfx_rc6_ms = 0; @@ -2434,6 +2657,20 @@ void clear_counters(struct thread_data *t, struct core_data *c, struct pkg_data p->counter[i] = 0; } +void rapl_counter_accumulate(struct rapl_counter *dst, const struct rapl_counter *src) +{ + /* Copy unit and scale from src if dst is not initialized */ + if (dst->unit == RAPL_UNIT_INVALID) { + dst->unit = src->unit; + dst->scale = src->scale; + } + + assert(dst->unit == src->unit); + assert(dst->scale == src->scale); + + dst->raw_value += src->raw_value; +} + int sum_counters(struct thread_data *t, struct core_data *c, struct pkg_data *p) { int i; @@ -2480,7 +2717,7 @@ int sum_counters(struct thread_data *t, struct core_data *c, struct pkg_data *p) average.cores.core_temp_c = MAX(average.cores.core_temp_c, c->core_temp_c); average.cores.core_throt_cnt = MAX(average.cores.core_throt_cnt, c->core_throt_cnt); - average.cores.core_energy += c->core_energy; + rapl_counter_accumulate(&average.cores.core_energy, &c->core_energy); for (i = 0, mp = sys.cp; mp; i++, mp = mp->next) { if (mp->format == FORMAT_RAW) @@ -2515,10 +2752,10 @@ int sum_counters(struct thread_data *t, struct core_data *c, struct pkg_data *p) average.packages.cpu_lpi = p->cpu_lpi; average.packages.sys_lpi = p->sys_lpi; - average.packages.energy_pkg += p->energy_pkg; - average.packages.energy_dram += p->energy_dram; - average.packages.energy_cores += p->energy_cores; - average.packages.energy_gfx += p->energy_gfx; + rapl_counter_accumulate(&average.packages.energy_pkg, &p->energy_pkg); + rapl_counter_accumulate(&average.packages.energy_dram, &p->energy_dram); + rapl_counter_accumulate(&average.packages.energy_cores, &p->energy_cores); + rapl_counter_accumulate(&average.packages.energy_gfx, &p->energy_gfx); average.packages.gfx_rc6_ms = p->gfx_rc6_ms; average.packages.uncore_mhz = p->uncore_mhz; @@ -2527,8 +2764,8 @@ int sum_counters(struct thread_data *t, struct core_data *c, struct pkg_data *p) average.packages.pkg_temp_c = MAX(average.packages.pkg_temp_c, p->pkg_temp_c); - average.packages.rapl_pkg_perf_status += p->rapl_pkg_perf_status; - average.packages.rapl_dram_perf_status += p->rapl_dram_perf_status; + rapl_counter_accumulate(&average.packages.rapl_pkg_perf_status, &p->rapl_pkg_perf_status); + rapl_counter_accumulate(&average.packages.rapl_dram_perf_status, &p->rapl_dram_perf_status); for (i = 0, mp = sys.pp; mp; i++, mp = mp->next) { if ((mp->format == FORMAT_RAW) && (topo.num_packages == 0)) @@ -2797,25 +3034,53 @@ struct amperf_group_fd { int mperf; }; -static unsigned int read_perf_counter_info(const char *const path, const char *const parse_format) +static int read_perf_counter_info(const char *const path, const char *const parse_format, void *value_ptr) { int fdmt; - char buf[16]; - unsigned int v; + int bytes_read; + char buf[64]; + int ret = -1; fdmt = open(path, O_RDONLY, 0); - if (fdmt == -1) - errx(1, "Failed to read perf counter info %s\n", path); + if (fdmt == -1) { + if (debug) + fprintf(stderr, "Failed to parse perf counter info %s\n", path); + ret = -1; + goto cleanup_and_exit; + } - if (read(fdmt, buf, sizeof(buf)) <= 0) - return 0; + bytes_read = read(fdmt, buf, sizeof(buf) - 1); + if (bytes_read <= 0 || bytes_read >= (int)sizeof(buf)) { + if (debug) + fprintf(stderr, "Failed to parse perf counter info %s\n", path); + ret = -1; + goto cleanup_and_exit; + } - buf[sizeof(buf) - 1] = '\0'; + buf[bytes_read] = '\0'; - if (sscanf(buf, parse_format, &v) != 1) - errx(1, "Failed to parse perf counter info %s\n", path); + if (sscanf(buf, parse_format, value_ptr) != 1) { + if (debug) + fprintf(stderr, "Failed to parse perf counter info %s\n", path); + ret = -1; + goto cleanup_and_exit; + } + ret = 0; + +cleanup_and_exit: close(fdmt); + return ret; +} + +static unsigned int read_perf_counter_info_n(const char *const path, const char *const parse_format) +{ + unsigned int v; + int status; + + status = read_perf_counter_info(path, parse_format, &v); + if (status) + v = -1; return v; } @@ -2825,7 +3090,7 @@ static unsigned read_msr_type(void) const char *const path = "/sys/bus/event_source/devices/msr/type"; const char *const format = "%u"; - return read_perf_counter_info(path, format); + return read_perf_counter_info_n(path, format); } static unsigned read_aperf_config(void) @@ -2833,7 +3098,7 @@ static unsigned read_aperf_config(void) const char *const path = "/sys/bus/event_source/devices/msr/events/aperf"; const char *const format = "event=%x"; - return read_perf_counter_info(path, format); + return read_perf_counter_info_n(path, format); } static unsigned read_mperf_config(void) @@ -2841,7 +3106,60 @@ static unsigned read_mperf_config(void) const char *const path = "/sys/bus/event_source/devices/msr/events/mperf"; const char *const format = "event=%x"; - return read_perf_counter_info(path, format); + return read_perf_counter_info_n(path, format); +} + +static unsigned read_perf_type(const char *subsys) +{ + const char *const path_format = "/sys/bus/event_source/devices/%s/type"; + const char *const format = "%u"; + char path[128]; + + snprintf(path, sizeof(path), path_format, subsys); + + return read_perf_counter_info_n(path, format); +} + +static unsigned read_rapl_config(const char *subsys, const char *event_name) +{ + const char *const path_format = "/sys/bus/event_source/devices/%s/events/%s"; + const char *const format = "event=%x"; + char path[128]; + + snprintf(path, sizeof(path), path_format, subsys, event_name); + + return read_perf_counter_info_n(path, format); +} + +static unsigned read_perf_rapl_unit(const char *subsys, const char *event_name) +{ + const char *const path_format = "/sys/bus/event_source/devices/%s/events/%s.unit"; + const char *const format = "%s"; + char path[128]; + char unit_buffer[16]; + + snprintf(path, sizeof(path), path_format, subsys, event_name); + + read_perf_counter_info(path, format, &unit_buffer); + if (strcmp("Joules", unit_buffer) == 0) + return RAPL_UNIT_JOULES; + + return RAPL_UNIT_INVALID; +} + +static double read_perf_rapl_scale(const char *subsys, const char *event_name) +{ + const char *const path_format = "/sys/bus/event_source/devices/%s/events/%s.scale"; + const char *const format = "%lf"; + char path[128]; + double scale; + + snprintf(path, sizeof(path), path_format, subsys, event_name); + + if (read_perf_counter_info(path, format, &scale)) + return 0.0; + + return scale; } static struct amperf_group_fd open_amperf_fd(int cpu) @@ -2961,6 +3279,99 @@ retry: return 0; } +size_t rapl_counter_info_count_perf(const struct rapl_counter_info_t *rci) +{ + size_t ret = 0; + + for (int i = 0; i < NUM_RAPL_COUNTERS; ++i) + if (rci->source[i] == RAPL_SOURCE_PERF) + ++ret; + + return ret; +} + +void write_rapl_counter(struct rapl_counter *rc, struct rapl_counter_info_t *rci, unsigned int idx) +{ + rc->raw_value = rci->data[idx]; + rc->unit = rci->unit[idx]; + rc->scale = rci->scale[idx]; +} + +int get_rapl_counters(int cpu, int domain, struct core_data *c, struct pkg_data *p) +{ + unsigned long long perf_data[NUM_RAPL_COUNTERS + 1]; + struct rapl_counter_info_t *rci = &rapl_counter_info_perdomain[domain]; + + if (debug) + fprintf(stderr, "get_rapl_counters: cpu%d domain%d\n", cpu, domain); + + assert(rapl_counter_info_perdomain); + + /* + * If we have any perf counters to read, read them all now, in bulk + */ + if (rci->fd_perf != -1) { + size_t num_perf_counters = rapl_counter_info_count_perf(rci); + const ssize_t expected_read_size = (num_perf_counters + 1) * sizeof(unsigned long long); + const ssize_t actual_read_size = read(rci->fd_perf, &perf_data[0], sizeof(perf_data)); + if (actual_read_size != expected_read_size) + err(-1, "get_rapl_counters: failed to read perf_data (%zu %zu)", expected_read_size, + actual_read_size); + } + + for (unsigned int i = 0, pi = 1; i < NUM_RAPL_COUNTERS; ++i) { + switch (rci->source[i]) { + case RAPL_SOURCE_NONE: + break; + + case RAPL_SOURCE_PERF: + assert(pi < ARRAY_SIZE(perf_data)); + assert(rci->fd_perf != -1); + + if (debug) + fprintf(stderr, "Reading rapl counter via perf at %u (%llu %e %lf)\n", + i, perf_data[pi], rci->scale[i], perf_data[pi] * rci->scale[i]); + + rci->data[i] = perf_data[pi]; + + ++pi; + break; + + case RAPL_SOURCE_MSR: + if (debug) + fprintf(stderr, "Reading rapl counter via msr at %u\n", i); + + assert(!no_msr); + if (rci->flags[i] & RAPL_COUNTER_FLAG_USE_MSR_SUM) { + if (get_msr_sum(cpu, rci->msr[i], &rci->data[i])) + return -13 - i; + } else { + if (get_msr(cpu, rci->msr[i], &rci->data[i])) + return -13 - i; + } + + rci->data[i] &= rci->msr_mask[i]; + if (rci->msr_shift[i] >= 0) + rci->data[i] >>= abs(rci->msr_shift[i]); + else + rci->data[i] <<= abs(rci->msr_shift[i]); + + break; + } + } + + _Static_assert(NUM_RAPL_COUNTERS == 7); + write_rapl_counter(&p->energy_pkg, rci, RAPL_RCI_INDEX_ENERGY_PKG); + write_rapl_counter(&p->energy_cores, rci, RAPL_RCI_INDEX_ENERGY_CORES); + write_rapl_counter(&p->energy_dram, rci, RAPL_RCI_INDEX_DRAM); + write_rapl_counter(&p->energy_gfx, rci, RAPL_RCI_INDEX_GFX); + write_rapl_counter(&p->rapl_pkg_perf_status, rci, RAPL_RCI_INDEX_PKG_PERF_STATUS); + write_rapl_counter(&p->rapl_dram_perf_status, rci, RAPL_RCI_INDEX_DRAM_PERF_STATUS); + write_rapl_counter(&c->core_energy, rci, RAPL_RCI_INDEX_CORE_ENERGY); + + return 0; +} + /* * get_counters(...) * migrate to cpu @@ -2972,6 +3383,7 @@ int get_counters(struct thread_data *t, struct core_data *c, struct pkg_data *p) unsigned long long msr; struct msr_counter *mp; int i; + int status; if (cpu_migrate(cpu)) { fprintf(outf, "get_counters: Could not migrate to CPU %d\n", cpu); @@ -3029,6 +3441,12 @@ int get_counters(struct thread_data *t, struct core_data *c, struct pkg_data *p) if (!is_cpu_first_thread_in_core(t, c, p)) goto done; + if (platform->has_per_core_rapl) { + status = get_rapl_counters(cpu, c->core_id, c, p); + if (status != 0) + return status; + } + if (DO_BIC(BIC_CPU_c3) || soft_c1_residency_display(BIC_CPU_c3)) { if (get_msr(cpu, MSR_CORE_C3_RESIDENCY, &c->c3)) return -6; @@ -3069,12 +3487,6 @@ int get_counters(struct thread_data *t, struct core_data *c, struct pkg_data *p) if (DO_BIC(BIC_CORE_THROT_CNT)) get_core_throt_cnt(cpu, &c->core_throt_cnt); - if ((platform->rapl_msrs & RAPL_AMD_F17H) && !no_msr) { - if (get_msr(cpu, MSR_CORE_ENERGY_STAT, &msr)) - return -14; - c->core_energy = msr & 0xFFFFFFFF; - } - for (i = 0, mp = sys.cp; mp; i++, mp = mp->next) { if (get_mp(cpu, mp, &c->counter[i])) return -10; @@ -3134,42 +3546,10 @@ int get_counters(struct thread_data *t, struct core_data *c, struct pkg_data *p) if (DO_BIC(BIC_SYS_LPI)) p->sys_lpi = cpuidle_cur_sys_lpi_us; - if (!no_msr) { - if (platform->rapl_msrs & RAPL_PKG) { - if (get_msr_sum(cpu, MSR_PKG_ENERGY_STATUS, &msr)) - return -13; - p->energy_pkg = msr; - } - if (platform->rapl_msrs & RAPL_CORE_ENERGY_STATUS) { - if (get_msr_sum(cpu, MSR_PP0_ENERGY_STATUS, &msr)) - return -14; - p->energy_cores = msr; - } - if (platform->rapl_msrs & RAPL_DRAM) { - if (get_msr_sum(cpu, MSR_DRAM_ENERGY_STATUS, &msr)) - return -15; - p->energy_dram = msr; - } - if (platform->rapl_msrs & RAPL_GFX) { - if (get_msr_sum(cpu, MSR_PP1_ENERGY_STATUS, &msr)) - return -16; - p->energy_gfx = msr; - } - if (platform->rapl_msrs & RAPL_PKG_PERF_STATUS) { - if (get_msr_sum(cpu, MSR_PKG_PERF_STATUS, &msr)) - return -16; - p->rapl_pkg_perf_status = msr; - } - if (platform->rapl_msrs & RAPL_DRAM_PERF_STATUS) { - if (get_msr_sum(cpu, MSR_DRAM_PERF_STATUS, &msr)) - return -16; - p->rapl_dram_perf_status = msr; - } - if (platform->rapl_msrs & RAPL_AMD_F17H) { - if (get_msr_sum(cpu, MSR_PKG_ENERGY_STAT, &msr)) - return -13; - p->energy_pkg = msr; - } + if (!platform->has_per_core_rapl) { + status = get_rapl_counters(cpu, p->package_id, c, p); + if (status != 0) + return status; } if (DO_BIC(BIC_PkgTmp)) { @@ -3714,6 +4094,21 @@ void free_fd_instr_count_percpu(void) fd_instr_count_percpu = NULL; } +void free_fd_rapl_percpu(void) +{ + if (!rapl_counter_info_perdomain) + return; + + const int num_domains = platform->has_per_core_rapl ? topo.num_cores : topo.num_packages; + + for (int domain_id = 0; domain_id < num_domains; ++domain_id) { + if (rapl_counter_info_perdomain[domain_id].fd_perf != -1) + close(rapl_counter_info_perdomain[domain_id].fd_perf); + } + + free(rapl_counter_info_perdomain); +} + void free_all_buffers(void) { int i; @@ -3757,6 +4152,7 @@ void free_all_buffers(void) free_fd_percpu(); free_fd_instr_count_percpu(); free_fd_amperf_percpu(); + free_fd_rapl_percpu(); free(irq_column_2_cpu); free(irqs_per_cpu); @@ -4091,12 +4487,14 @@ static void update_effective_set(bool startup) } void linux_perf_init(void); +void rapl_perf_init(void); void re_initialize(void) { free_all_buffers(); setup_all_buffers(false); linux_perf_init(); + rapl_perf_init(); fprintf(outf, "turbostat: re-initialized with num_cpus %d, allowed_cpus %d\n", topo.num_cpus, topo.allowed_cpus); } @@ -5315,31 +5713,18 @@ void rapl_probe_intel(void) unsigned long long msr; unsigned int time_unit; double tdp; + const unsigned long long bic_watt_bits = BIC_PkgWatt | BIC_CorWatt | BIC_RAMWatt | BIC_GFXWatt; + const unsigned long long bic_joules_bits = BIC_Pkg_J | BIC_Cor_J | BIC_RAM_J | BIC_GFX_J; - if (rapl_joules) { - if (platform->rapl_msrs & RAPL_PKG_ENERGY_STATUS) - BIC_PRESENT(BIC_Pkg_J); - if (platform->rapl_msrs & RAPL_CORE_ENERGY_STATUS) - BIC_PRESENT(BIC_Cor_J); - if (platform->rapl_msrs & RAPL_DRAM_ENERGY_STATUS) - BIC_PRESENT(BIC_RAM_J); - if (platform->rapl_msrs & RAPL_GFX_ENERGY_STATUS) - BIC_PRESENT(BIC_GFX_J); - } else { - if (platform->rapl_msrs & RAPL_PKG_ENERGY_STATUS) - BIC_PRESENT(BIC_PkgWatt); - if (platform->rapl_msrs & RAPL_CORE_ENERGY_STATUS) - BIC_PRESENT(BIC_CorWatt); - if (platform->rapl_msrs & RAPL_DRAM_ENERGY_STATUS) - BIC_PRESENT(BIC_RAMWatt); - if (platform->rapl_msrs & RAPL_GFX_ENERGY_STATUS) - BIC_PRESENT(BIC_GFXWatt); - } + if (rapl_joules) + bic_enabled &= ~bic_watt_bits; + else + bic_enabled &= ~bic_joules_bits; - if (platform->rapl_msrs & RAPL_PKG_PERF_STATUS) - BIC_PRESENT(BIC_PKG__); - if (platform->rapl_msrs & RAPL_DRAM_PERF_STATUS) - BIC_PRESENT(BIC_RAM__); + if (!(platform->rapl_msrs & RAPL_PKG_PERF_STATUS)) + bic_enabled &= ~BIC_PKG__; + if (!(platform->rapl_msrs & RAPL_DRAM_PERF_STATUS)) + bic_enabled &= ~BIC_RAM__; /* units on package 0, verify later other packages match */ if (get_msr(base_cpu, MSR_RAPL_POWER_UNIT, &msr)) @@ -5373,14 +5758,13 @@ void rapl_probe_amd(void) { unsigned long long msr; double tdp; + const unsigned long long bic_watt_bits = BIC_PkgWatt | BIC_CorWatt; + const unsigned long long bic_joules_bits = BIC_Pkg_J | BIC_Cor_J; - if (rapl_joules) { - BIC_PRESENT(BIC_Pkg_J); - BIC_PRESENT(BIC_Cor_J); - } else { - BIC_PRESENT(BIC_PkgWatt); - BIC_PRESENT(BIC_CorWatt); - } + if (rapl_joules) + bic_enabled &= ~bic_watt_bits; + else + bic_enabled &= ~bic_joules_bits; if (get_msr(base_cpu, MSR_RAPL_PWR_UNIT, &msr)) return; @@ -5885,6 +6269,48 @@ bool is_aperf_access_required(void) || BIC_IS_ENABLED(BIC_IPC); } +int add_rapl_perf_counter_(int cpu, struct rapl_counter_info_t *rci, const struct rapl_counter_arch_info *cai, + double *scale_, enum rapl_unit *unit_) +{ + if (no_perf) + return -1; + + const double scale = read_perf_rapl_scale(cai->perf_subsys, cai->perf_name); + if (scale == 0.0) + return -1; + + const enum rapl_unit unit = read_perf_rapl_unit(cai->perf_subsys, cai->perf_name); + if (unit == RAPL_UNIT_INVALID) + return -1; + + const unsigned rapl_type = read_perf_type(cai->perf_subsys); + const unsigned rapl_energy_pkg_config = read_rapl_config(cai->perf_subsys, cai->perf_name); + + const int fd_counter = + open_perf_counter(cpu, rapl_type, rapl_energy_pkg_config, rci->fd_perf, PERF_FORMAT_GROUP); + if (fd_counter == -1) + return -1; + + /* If it's the first counter opened, make it a group descriptor */ + if (rci->fd_perf == -1) + rci->fd_perf = fd_counter; + + *scale_ = scale; + *unit_ = unit; + return fd_counter; +} + +int add_rapl_perf_counter(int cpu, struct rapl_counter_info_t *rci, const struct rapl_counter_arch_info *cai, + double *scale, enum rapl_unit *unit) +{ + int ret = add_rapl_perf_counter_(cpu, rci, cai, scale, unit); + + if (debug) + fprintf(stderr, "add_rapl_perf_counter: %d (cpu: %d)\n", ret, cpu); + + return ret; +} + /* * Linux-perf manages the HW instructions-retired counter * by enabling when requested, and hiding rollover @@ -5908,17 +6334,101 @@ void linux_perf_init(void) } } -static int has_amperf_access_via_msr(void) +void rapl_perf_init(void) { - unsigned long long dummy; + const int num_domains = platform->has_per_core_rapl ? topo.num_cores : topo.num_packages; + bool *domain_visited = calloc(num_domains, sizeof(bool)); + + rapl_counter_info_perdomain = calloc(num_domains, sizeof(*rapl_counter_info_perdomain)); + if (rapl_counter_info_perdomain == NULL) + err(-1, "calloc rapl_counter_info_percpu"); + /* + * Initialize rapl_counter_info_percpu + */ + for (int domain_id = 0; domain_id < num_domains; ++domain_id) { + struct rapl_counter_info_t *rci = &rapl_counter_info_perdomain[domain_id]; + rci->fd_perf = -1; + for (size_t i = 0; i < NUM_RAPL_COUNTERS; ++i) { + rci->data[i] = 0; + rci->source[i] = RAPL_SOURCE_NONE; + } + } + + /* + * Open/probe the counters + * If can't get it via perf, fallback to MSR + */ + for (size_t i = 0; i < ARRAY_SIZE(rapl_counter_arch_infos); ++i) { + + const struct rapl_counter_arch_info *const cai = &rapl_counter_arch_infos[i]; + bool has_counter = 0; + double scale; + enum rapl_unit unit; + int next_domain; + + memset(domain_visited, 0, num_domains * sizeof(*domain_visited)); + + for (int cpu = 0; cpu < topo.max_cpu_num + 1; ++cpu) { + + if (cpu_is_not_allowed(cpu)) + continue; + + /* Skip already seen and handled RAPL domains */ + next_domain = + platform->has_per_core_rapl ? cpus[cpu].physical_core_id : cpus[cpu].physical_package_id; + + if (domain_visited[next_domain]) + continue; + + domain_visited[next_domain] = 1; + + struct rapl_counter_info_t *rci = &rapl_counter_info_perdomain[next_domain]; + + /* Check if the counter is enabled and accessible */ + if (BIC_IS_ENABLED(cai->bic) && (platform->rapl_msrs & cai->feature_mask)) { + + /* Use perf API for this counter */ + if (!no_perf && cai->perf_name + && add_rapl_perf_counter(cpu, rci, cai, &scale, &unit) != -1) { + rci->source[cai->rci_index] = RAPL_SOURCE_PERF; + rci->scale[cai->rci_index] = scale * cai->compat_scale; + rci->unit[cai->rci_index] = unit; + rci->flags[cai->rci_index] = cai->flags; + + /* Use MSR for this counter */ + } else if (!no_msr && cai->msr && probe_msr(cpu, cai->msr) == 0) { + rci->source[cai->rci_index] = RAPL_SOURCE_MSR; + rci->msr[cai->rci_index] = cai->msr; + rci->msr_mask[cai->rci_index] = cai->msr_mask; + rci->msr_shift[cai->rci_index] = cai->msr_shift; + rci->unit[cai->rci_index] = RAPL_UNIT_JOULES; + rci->scale[cai->rci_index] = *cai->platform_rapl_msr_scale * cai->compat_scale; + rci->flags[cai->rci_index] = cai->flags; + } + } + + if (rci->source[cai->rci_index] != RAPL_SOURCE_NONE) + has_counter = 1; + } + + /* If any CPU has access to the counter, make it present */ + if (has_counter) + BIC_PRESENT(cai->bic); + } + + free(domain_visited); +} + +static int has_amperf_access_via_msr(void) +{ if (no_msr) return 0; - if (get_msr(base_cpu, MSR_IA32_APERF, &dummy)) + if (probe_msr(base_cpu, MSR_IA32_APERF)) return 0; - if (get_msr(base_cpu, MSR_IA32_MPERF, &dummy)) + if (probe_msr(base_cpu, MSR_IA32_MPERF)) return 0; return 1; @@ -6696,6 +7206,7 @@ bool is_msr_access_required(void) || BIC_IS_ENABLED(BIC_Pkgpc8) || BIC_IS_ENABLED(BIC_Pkgpc9) || BIC_IS_ENABLED(BIC_Pkgpc10) + /* TODO: Multiplex access with perf */ || BIC_IS_ENABLED(BIC_CorWatt) || BIC_IS_ENABLED(BIC_Cor_J) || BIC_IS_ENABLED(BIC_PkgWatt) @@ -6749,6 +7260,7 @@ void turbostat_init() probe_pm_features(); set_amperf_source(); linux_perf_init(); + rapl_perf_init(); for_all_cpus(get_cpu_type, ODD_COUNTERS); for_all_cpus(get_cpu_type, EVEN_COUNTERS); -- cgit v1.2.3 From 17d1ea136be86f53be0461b0c33daf6b58e6cbf7 Mon Sep 17 00:00:00 2001 From: Patryk Wlazlyn Date: Thu, 7 Mar 2024 17:00:35 +0100 Subject: tools/power turbostat: Add selftests Signed-off-by: Patryk Wlazlyn Signed-off-by: Len Brown --- tools/testing/selftests/turbostat/defcolumns.py | 59 +++++++++++++++++++++++++ 1 file changed, 59 insertions(+) create mode 100755 tools/testing/selftests/turbostat/defcolumns.py diff --git a/tools/testing/selftests/turbostat/defcolumns.py b/tools/testing/selftests/turbostat/defcolumns.py new file mode 100755 index 000000000000..70d3b7780311 --- /dev/null +++ b/tools/testing/selftests/turbostat/defcolumns.py @@ -0,0 +1,59 @@ +#!/bin/env python3 + +import subprocess +from shutil import which + +turbostat = which('turbostat') +if turbostat is None: + print('Could not find turbostat binary') + exit(1) + +timeout = which('timeout') +if timeout is None: + print('Could not find timeout binary') + exit(1) + +proc_turbostat = subprocess.run([turbostat, '--list'], capture_output = True) +if proc_turbostat.returncode != 0: + print(f'turbostat failed with {proc_turbostat.returncode}') + exit(1) + +# +# By default --list reports also "usec" and "Time_Of_Day_Seconds" columns +# which are only visible when running with --debug. +# +expected_columns_debug = proc_turbostat.stdout.replace(b',', b'\t').strip() +expected_columns = expected_columns_debug.replace(b'usec\t', b'').replace(b'Time_Of_Day_Seconds\t', b'').replace(b'X2APIC\t', b'').replace(b'APIC\t', b'') + +# +# Run turbostat with no options for 10 seconds and send SIGINT +# +timeout_argv = [timeout, '--preserve-status', '-s', 'SIGINT', '-k', '3', '1s'] +turbostat_argv = [turbostat, '-i', '0.250'] + +print(f'Running turbostat with {turbostat_argv=}... ', end = '', flush = True) +proc_turbostat = subprocess.run(timeout_argv + turbostat_argv, capture_output = True) +if proc_turbostat.returncode != 0: + print(f'turbostat failed with {proc_turbostat.returncode}') + exit(1) +actual_columns = proc_turbostat.stdout.split(b'\n')[0] +if expected_columns != actual_columns: + print(f'turbostat column check failed\n{expected_columns=}\n{actual_columns=}') + exit(1) +print('OK') + +# +# Same, but with --debug +# +turbostat_argv.append('--debug') + +print(f'Running turbostat with {turbostat_argv=}... ', end = '', flush = True) +proc_turbostat = subprocess.run(timeout_argv + turbostat_argv, capture_output = True) +if proc_turbostat.returncode != 0: + print(f'turbostat failed with {proc_turbostat.returncode}') + exit(1) +actual_columns = proc_turbostat.stdout.split(b'\n')[0] +if expected_columns_debug != actual_columns: + print(f'turbostat column check failed\n{expected_columns_debug=}\n{actual_columns=}') + exit(1) +print('OK') -- cgit v1.2.3 From bb5db22c13125b38b0740e19c18ae94f8e5a0eb6 Mon Sep 17 00:00:00 2001 From: Zhang Rui Date: Tue, 12 Mar 2024 11:19:15 +0800 Subject: tools/power/turbostat: Enable MSR_CORE_C1_RES support for ICX Enable Core C1 hardware residency counter (MSR_CORE_C1_RES) on ICX. Signed-off-by: Zhang Rui Signed-off-by: Len Brown --- tools/power/x86/turbostat/turbostat.c | 1 + 1 file changed, 1 insertion(+) diff --git a/tools/power/x86/turbostat/turbostat.c b/tools/power/x86/turbostat/turbostat.c index 283dffb987b5..372f67a70d8a 100644 --- a/tools/power/x86/turbostat/turbostat.c +++ b/tools/power/x86/turbostat/turbostat.c @@ -664,6 +664,7 @@ static const struct platform_features icx_features = { .bclk_freq = BCLK_100MHZ, .supported_cstates = CC1 | CC6 | PC2 | PC6, .cst_limit = CST_LIMIT_ICX, + .has_msr_core_c1_res = 1, .has_irtl_msrs = 1, .has_cst_prewake_bit = 1, .trl_msrs = TRL_BASE | TRL_CORECOUNT, -- cgit v1.2.3 From 4e2bbbf78cf7144204214fd0bd7cca309acd8f89 Mon Sep 17 00:00:00 2001 From: Zhang Rui Date: Tue, 12 Mar 2024 14:23:37 +0800 Subject: tools/power/turbostat: Cache graphics sysfs path Graphics drivers (i915/Xe) have different sysfs knobs on different platforms, and it is possible that different sysfs knobs fit into the same turbostat columns. Instead of specifying different sysfs knobs every time, detect them once and cache the path for future use. No functional change. Signed-off-by: Zhang Rui Signed-off-by: Len Brown --- tools/power/x86/turbostat/turbostat.c | 45 +++++++++++++++++++++++++---------- 1 file changed, 32 insertions(+), 13 deletions(-) diff --git a/tools/power/x86/turbostat/turbostat.c b/tools/power/x86/turbostat/turbostat.c index 372f67a70d8a..78db4f65a237 100644 --- a/tools/power/x86/turbostat/turbostat.c +++ b/tools/power/x86/turbostat/turbostat.c @@ -276,6 +276,19 @@ bool no_msr; bool no_perf; enum amperf_source amperf_source; +enum gfx_sysfs_idx { + GFX_rc6, + GFX_MHz, + GFX_ACTMHz, + GFX_MAX +}; + +struct gfx_sysfs_info { + const char *path; +}; + +static struct gfx_sysfs_info gfx_info[GFX_MAX]; + int get_msr(int cpu, off_t offset, unsigned long long *msr); /* Model specific support Start */ @@ -4620,7 +4633,7 @@ int snapshot_gfx_rc6_ms(void) FILE *fp; int retval; - fp = fopen_or_die("/sys/class/drm/card0/power/rc6_residency_ms", "r"); + fp = fopen_or_die(gfx_info[GFX_rc6].path, "r"); retval = fscanf(fp, "%lld", &gfx_cur_rc6_ms); if (retval != 1) @@ -4645,9 +4658,7 @@ int snapshot_gfx_mhz(void) int retval; if (fp == NULL) { - fp = fopen("/sys/class/drm/card0/gt_cur_freq_mhz", "r"); - if (!fp) - fp = fopen_or_die("/sys/class/graphics/fb0/device/drm/card0/gt_cur_freq_mhz", "r"); + fp = fopen_or_die(gfx_info[GFX_MHz].path, "r"); } else { rewind(fp); fflush(fp); @@ -4674,9 +4685,7 @@ int snapshot_gfx_act_mhz(void) int retval; if (fp == NULL) { - fp = fopen("/sys/class/drm/card0/gt_act_freq_mhz", "r"); - if (!fp) - fp = fopen_or_die("/sys/class/graphics/fb0/device/drm/card0/gt_act_freq_mhz", "r"); + fp = fopen_or_die(gfx_info[GFX_ACTMHz].path, "r"); } else { rewind(fp); fflush(fp); @@ -5338,14 +5347,24 @@ probe_cluster: static void probe_graphics(void) { if (!access("/sys/class/drm/card0/power/rc6_residency_ms", R_OK)) - BIC_PRESENT(BIC_GFX_rc6); + gfx_info[GFX_rc6].path = "/sys/class/drm/card0/power/rc6_residency_ms"; - if (!access("/sys/class/drm/card0/gt_cur_freq_mhz", R_OK) || - !access("/sys/class/graphics/fb0/device/drm/card0/gt_cur_freq_mhz", R_OK)) - BIC_PRESENT(BIC_GFXMHz); + if (!access("/sys/class/drm/card0/gt_cur_freq_mhz", R_OK)) + gfx_info[GFX_MHz].path = "/sys/class/drm/card0/gt_cur_freq_mhz"; + else if (!access("/sys/class/graphics/fb0/device/drm/card0/gt_cur_freq_mhz", R_OK)) + gfx_info[GFX_MHz].path = "/sys/class/graphics/fb0/device/drm/card0/gt_cur_freq_mhz"; + + + if (!access("/sys/class/drm/card0/gt_act_freq_mhz", R_OK)) + gfx_info[GFX_ACTMHz].path = "/sys/class/drm/card0/gt_act_freq_mhz"; + else if (!access("/sys/class/graphics/fb0/device/drm/card0/gt_act_freq_mhz", R_OK)) + gfx_info[GFX_ACTMHz].path = "/sys/class/graphics/fb0/device/drm/card0/gt_act_freq_mhz"; - if (!access("/sys/class/drm/card0/gt_act_freq_mhz", R_OK) || - !access("/sys/class/graphics/fb0/device/drm/card0/gt_act_freq_mhz", R_OK)) + if (gfx_info[GFX_rc6].path) + BIC_PRESENT(BIC_GFX_rc6); + if (gfx_info[GFX_MHz].path) + BIC_PRESENT(BIC_GFXMHz); + if (gfx_info[GFX_ACTMHz].path) BIC_PRESENT(BIC_GFXACTMHz); } -- cgit v1.2.3 From de39d38c06eb047954c5ad20a3f9acb6d3c78498 Mon Sep 17 00:00:00 2001 From: Zhang Rui Date: Wed, 13 Mar 2024 10:12:19 +0800 Subject: tools/power/turbostat: Unify graphics sysfs snapshots Graphics sysfs snapshots share similar logic. Combine them into one function to avoid code duplication. No functional change. Signed-off-by: Zhang Rui Signed-off-by: Len Brown --- tools/power/x86/turbostat/turbostat.c | 109 +++++++++++----------------------- 1 file changed, 34 insertions(+), 75 deletions(-) diff --git a/tools/power/x86/turbostat/turbostat.c b/tools/power/x86/turbostat/turbostat.c index 78db4f65a237..e5b6161fef48 100644 --- a/tools/power/x86/turbostat/turbostat.c +++ b/tools/power/x86/turbostat/turbostat.c @@ -251,11 +251,8 @@ char *output_buffer, *outp; unsigned int do_dts; unsigned int do_ptm; unsigned int do_ipc; -unsigned long long gfx_cur_rc6_ms; unsigned long long cpuidle_cur_cpu_lpi_us; unsigned long long cpuidle_cur_sys_lpi_us; -unsigned int gfx_cur_mhz; -unsigned int gfx_act_mhz; unsigned int tj_max; unsigned int tj_max_override; double rapl_power_units, rapl_time_units; @@ -285,6 +282,9 @@ enum gfx_sysfs_idx { struct gfx_sysfs_info { const char *path; + FILE *fp; + unsigned int val; + unsigned long long val_ull; }; static struct gfx_sysfs_info gfx_info[GFX_MAX]; @@ -3573,17 +3573,17 @@ int get_counters(struct thread_data *t, struct core_data *c, struct pkg_data *p) } if (DO_BIC(BIC_GFX_rc6)) - p->gfx_rc6_ms = gfx_cur_rc6_ms; + p->gfx_rc6_ms = gfx_info[GFX_rc6].val_ull; /* n.b. assume die0 uncore frequency applies to whole package */ if (DO_BIC(BIC_UNCORE_MHZ)) p->uncore_mhz = get_uncore_mhz(p->package_id, 0); if (DO_BIC(BIC_GFXMHz)) - p->gfx_mhz = gfx_cur_mhz; + p->gfx_mhz = gfx_info[GFX_MHz].val; if (DO_BIC(BIC_GFXACTMHz)) - p->gfx_act_mhz = gfx_act_mhz; + p->gfx_act_mhz = gfx_info[GFX_ACTMHz].val; for (i = 0, mp = sys.pp; mp; i++, mp = mp->next) { if (get_mp(cpu, mp, &p->counter[i])) @@ -4621,81 +4621,40 @@ int snapshot_proc_interrupts(void) } /* - * snapshot_gfx_rc6_ms() + * snapshot_graphics() * - * record snapshot of - * /sys/class/drm/card0/power/rc6_residency_ms + * record snapshot of specified graphics sysfs knob * * return 1 if config change requires a restart, else return 0 */ -int snapshot_gfx_rc6_ms(void) +int snapshot_graphics(int idx) { FILE *fp; int retval; - fp = fopen_or_die(gfx_info[GFX_rc6].path, "r"); - - retval = fscanf(fp, "%lld", &gfx_cur_rc6_ms); - if (retval != 1) - err(1, "GFX rc6"); - - fclose(fp); - - return 0; -} - -/* - * snapshot_gfx_mhz() - * - * fall back to /sys/class/graphics/fb0/device/drm/card0/gt_cur_freq_mhz - * when /sys/class/drm/card0/gt_cur_freq_mhz is not available. - * - * return 1 if config change requires a restart, else return 0 - */ -int snapshot_gfx_mhz(void) -{ - static FILE *fp; - int retval; - - if (fp == NULL) { - fp = fopen_or_die(gfx_info[GFX_MHz].path, "r"); - } else { - rewind(fp); - fflush(fp); - } - - retval = fscanf(fp, "%d", &gfx_cur_mhz); - if (retval != 1) - err(1, "GFX MHz"); - - return 0; -} - -/* - * snapshot_gfx_cur_mhz() - * - * fall back to /sys/class/graphics/fb0/device/drm/card0/gt_act_freq_mhz - * when /sys/class/drm/card0/gt_act_freq_mhz is not available. - * - * return 1 if config change requires a restart, else return 0 - */ -int snapshot_gfx_act_mhz(void) -{ - static FILE *fp; - int retval; - - if (fp == NULL) { - fp = fopen_or_die(gfx_info[GFX_ACTMHz].path, "r"); - } else { - rewind(fp); - fflush(fp); + switch (idx) { + case GFX_rc6: + fp = fopen_or_die(gfx_info[idx].path, "r"); + retval = fscanf(fp, "%lld", &gfx_info[idx].val_ull); + if (retval != 1) + err(1, "rc6"); + fclose(fp); + return 0; + case GFX_MHz: + case GFX_ACTMHz: + if (gfx_info[idx].fp == NULL) { + gfx_info[idx].fp = fopen_or_die(gfx_info[idx].path, "r"); + } else { + rewind(gfx_info[idx].fp); + fflush(gfx_info[idx].fp); + } + retval = fscanf(gfx_info[idx].fp, "%d", &gfx_info[idx].val); + if (retval != 1) + err(1, "MHz"); + return 0; + default: + return -EINVAL; } - - retval = fscanf(fp, "%d", &gfx_act_mhz); - if (retval != 1) - err(1, "GFX ACT MHz"); - - return 0; } /* @@ -4760,13 +4719,13 @@ int snapshot_proc_sysfs_files(void) return 1; if (DO_BIC(BIC_GFX_rc6)) - snapshot_gfx_rc6_ms(); + snapshot_graphics(GFX_rc6); if (DO_BIC(BIC_GFXMHz)) - snapshot_gfx_mhz(); + snapshot_graphics(GFX_MHz); if (DO_BIC(BIC_GFXACTMHz)) - snapshot_gfx_act_mhz(); + snapshot_graphics(GFX_ACTMHz); if (DO_BIC(BIC_CPU_LPI)) snapshot_cpu_lpi_us(); -- cgit v1.2.3 From 60add818ab2543b7e4f2bfeaacf2504743c1eb50 Mon Sep 17 00:00:00 2001 From: Justin Ernst Date: Tue, 2 Apr 2024 13:40:29 -0400 Subject: tools/power/turbostat: Fix uncore frequency file string Running turbostat on a 16 socket HPE Scale-up Compute 3200 (SapphireRapids) fails with: turbostat: /sys/devices/system/cpu/intel_uncore_frequency/package_010_die_00/current_freq_khz: open failed: No such file or directory We observe the sysfs uncore frequency directories named: ... package_09_die_00/ package_10_die_00/ package_11_die_00/ ... package_15_die_00/ The culprit is an incorrect sprintf format string "package_0%d_die_0%d" used with each instance of reading uncore frequency files. uncore-frequency-common.c creates the sysfs directory with the format "package_%02d_die_%02d". Once the package value reaches double digits, the formats diverge. Change each instance of "package_0%d_die_0%d" to "package_%02d_die_%02d". [lenb: deleted the probe part of this patch, as it was already fixed] Signed-off-by: Justin Ernst Reviewed-by: Thomas Renninger Signed-off-by: Len Brown --- tools/power/x86/turbostat/turbostat.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/power/x86/turbostat/turbostat.c b/tools/power/x86/turbostat/turbostat.c index e5b6161fef48..016a5c7dc9bf 100644 --- a/tools/power/x86/turbostat/turbostat.c +++ b/tools/power/x86/turbostat/turbostat.c @@ -2939,7 +2939,7 @@ unsigned long long get_uncore_mhz(int package, int die) { char path[128]; - sprintf(path, "/sys/devices/system/cpu/intel_uncore_frequency/package_0%d_die_0%d/current_freq_khz", package, + sprintf(path, "/sys/devices/system/cpu/intel_uncore_frequency/package_%02d_die_%02d/current_freq_khz", package, die); return (snapshot_sysfs_counter(path) / 1000); -- cgit v1.2.3 From f78bf2c933c9cb3b61215378664f83c5abd25374 Mon Sep 17 00:00:00 2001 From: Dragan Simic Date: Tue, 9 Apr 2024 19:56:36 +0200 Subject: ASoC: pcm: perform power-down delay checks a bit faster When checking whether the power-down delay should be ignored for a specific PCM runtime, there's no need to keep going through all DAI link components after any of them is found to be configured to use the power-down delay. While there, fix a small typo in one of the comment blocks. Signed-off-by: Dragan Simic Link: https://msgid.link/r/90ae761a5b99640ece48363a7099ac2cf402bd37.1712684592.git.dsimic@manjaro.org Signed-off-by: Mark Brown --- sound/soc/soc-pcm.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c index 77ee103b7cd1..b0e1bd7f588b 100644 --- a/sound/soc/soc-pcm.c +++ b/sound/soc/soc-pcm.c @@ -315,23 +315,24 @@ EXPORT_SYMBOL_GPL(snd_soc_runtime_action); * @rtd: The ASoC PCM runtime that should be checked. * * This function checks whether the power down delay should be ignored for a - * specific PCM runtime. Returns true if the delay is 0, if it the DAI link has + * specific PCM runtime. Returns true if the delay is 0, if the DAI link has * been configured to ignore the delay, or if none of the components benefits * from having the delay. */ bool snd_soc_runtime_ignore_pmdown_time(struct snd_soc_pcm_runtime *rtd) { struct snd_soc_component *component; - bool ignore = true; int i; if (!rtd->pmdown_time || rtd->dai_link->ignore_pmdown_time) return true; for_each_rtd_components(rtd, i, component) - ignore &= !component->driver->use_pmdown_time; + if (component->driver->use_pmdown_time) + /* No need to go through all components */ + return false; - return ignore; + return true; } /** -- cgit v1.2.3 From ff81dade48608363136d52bb2493a6df76458b28 Mon Sep 17 00:00:00 2001 From: Haiyue Wang Date: Wed, 10 Apr 2024 01:35:28 +0800 Subject: io-uring: correct typo in comment for IOU_F_TWQ_LAZY_WAKE The 'r' key is near to 't' key, that makes 'with' to be 'wirh' ? :) Signed-off-by: Haiyue Wang Link: https://lore.kernel.org/r/20240409173531.846714-1-haiyue.wang@intel.com Signed-off-by: Jens Axboe --- include/linux/io_uring_types.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/linux/io_uring_types.h b/include/linux/io_uring_types.h index 05df0e399d7c..ac333ea81d31 100644 --- a/include/linux/io_uring_types.h +++ b/include/linux/io_uring_types.h @@ -13,7 +13,7 @@ enum { * A hint to not wake right away but delay until there are enough of * tw's queued to match the number of CQEs the task is waiting for. * - * Must not be used wirh requests generating more than one CQE. + * Must not be used with requests generating more than one CQE. * It's also ignored unless IORING_SETUP_DEFER_TASKRUN is set. */ IOU_F_TWQ_LAZY_WAKE = 1, -- cgit v1.2.3 From 68879386180c0efd5a11e800b0525a01068c9457 Mon Sep 17 00:00:00 2001 From: Naohiro Aota Date: Tue, 26 Mar 2024 14:39:20 +0900 Subject: btrfs: zoned: do not flag ZEROOUT on non-dirty extent buffer Btrfs clears the content of an extent buffer marked as EXTENT_BUFFER_ZONED_ZEROOUT before the bio submission. This mechanism is introduced to prevent a write hole of an extent buffer, which is once allocated, marked dirty, but turns out unnecessary and cleaned up within one transaction operation. Currently, btrfs_clear_buffer_dirty() marks the extent buffer as EXTENT_BUFFER_ZONED_ZEROOUT, and skips the entry function. If this call happens while the buffer is under IO (with the WRITEBACK flag set, without the DIRTY flag), we can add the ZEROOUT flag and clear the buffer's content just before a bio submission. As a result: 1) it can lead to adding faulty delayed reference item which leads to a FS corrupted (EUCLEAN) error, and 2) it writes out cleared tree node on disk The former issue is previously discussed in [1]. The corruption happens when it runs a delayed reference update. So, on-disk data is safe. [1] https://lore.kernel.org/linux-btrfs/3f4f2a0ff1a6c818050434288925bdcf3cd719e5.1709124777.git.naohiro.aota@wdc.com/ The latter one can reach on-disk data. But, as that node is already processed by btrfs_clear_buffer_dirty(), that will be invalidated in the next transaction commit anyway. So, the chance of hitting the corruption is relatively small. Anyway, we should skip flagging ZEROOUT on a non-DIRTY extent buffer, to keep the content under IO intact. Fixes: aa6313e6ff2b ("btrfs: zoned: don't clear dirty flag of extent buffer") CC: stable@vger.kernel.org # 6.8 Link: https://lore.kernel.org/linux-btrfs/oadvdekkturysgfgi4qzuemd57zudeasynswurjxw3ocdfsef6@sjyufeugh63f/ Reviewed-by: Johannes Thumshirn Signed-off-by: Naohiro Aota Reviewed-by: David Sterba Signed-off-by: David Sterba --- fs/btrfs/extent_io.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/btrfs/extent_io.c b/fs/btrfs/extent_io.c index 61594eaf1f89..df3fe36126f9 100644 --- a/fs/btrfs/extent_io.c +++ b/fs/btrfs/extent_io.c @@ -4154,7 +4154,7 @@ void btrfs_clear_buffer_dirty(struct btrfs_trans_handle *trans, * The actual zeroout of the buffer will happen later in * btree_csum_one_bio. */ - if (btrfs_is_zoned(fs_info)) { + if (btrfs_is_zoned(fs_info) && test_bit(EXTENT_BUFFER_DIRTY, &eb->bflags)) { set_bit(EXTENT_BUFFER_ZONED_ZEROOUT, &eb->bflags); return; } -- cgit v1.2.3 From 073bda7a541731f41ed08f32d286394236c74005 Mon Sep 17 00:00:00 2001 From: Naohiro Aota Date: Tue, 26 Mar 2024 14:39:21 +0900 Subject: btrfs: zoned: add ASSERT and WARN for EXTENT_BUFFER_ZONED_ZEROOUT handling Add an ASSERT to catch a faulty delayed reference item resulting from prematurely cleared extent buffer. Also, add a WARN to detect if we try to dirty a ZEROOUT buffer again, which is suspicious as its update will be lost. Reviewed-by: Johannes Thumshirn Signed-off-by: Naohiro Aota Reviewed-by: David Sterba Signed-off-by: David Sterba --- fs/btrfs/extent-tree.c | 8 ++++++++ fs/btrfs/extent_io.c | 1 + 2 files changed, 9 insertions(+) diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c index beedd6ed64d3..257d044bca91 100644 --- a/fs/btrfs/extent-tree.c +++ b/fs/btrfs/extent-tree.c @@ -3464,6 +3464,14 @@ void btrfs_free_tree_block(struct btrfs_trans_handle *trans, if (root_id != BTRFS_TREE_LOG_OBJECTID) { struct btrfs_ref generic_ref = { 0 }; + /* + * Assert that the extent buffer is not cleared due to + * EXTENT_BUFFER_ZONED_ZEROOUT. Please refer + * btrfs_clear_buffer_dirty() and btree_csum_one_bio() for + * detail. + */ + ASSERT(btrfs_header_bytenr(buf) != 0); + btrfs_init_generic_ref(&generic_ref, BTRFS_DROP_DELAYED_REF, buf->start, buf->len, parent, btrfs_header_owner(buf)); diff --git a/fs/btrfs/extent_io.c b/fs/btrfs/extent_io.c index df3fe36126f9..b18034f2ab80 100644 --- a/fs/btrfs/extent_io.c +++ b/fs/btrfs/extent_io.c @@ -4193,6 +4193,7 @@ void set_extent_buffer_dirty(struct extent_buffer *eb) num_folios = num_extent_folios(eb); WARN_ON(atomic_read(&eb->refs) == 0); WARN_ON(!test_bit(EXTENT_BUFFER_TREE_REF, &eb->bflags)); + WARN_ON(test_bit(EXTENT_BUFFER_ZONED_ZEROOUT, &eb->bflags)); if (!was_dirty) { bool subpage = eb->fs_info->nodesize < PAGE_SIZE; -- cgit v1.2.3 From 1db7959aacd905e6487d0478ac01d89f86eb1e51 Mon Sep 17 00:00:00 2001 From: Qu Wenruo Date: Tue, 26 Mar 2024 09:16:46 +1030 Subject: btrfs: do not wait for short bulk allocation [BUG] There is a recent report that when memory pressure is high (including cached pages), btrfs can spend most of its time on memory allocation in btrfs_alloc_page_array() for compressed read/write. [CAUSE] For btrfs_alloc_page_array() we always go alloc_pages_bulk_array(), and even if the bulk allocation failed (fell back to single page allocation) we still retry but with extra memalloc_retry_wait(). If the bulk alloc only returned one page a time, we would spend a lot of time on the retry wait. The behavior was introduced in commit 395cb57e8560 ("btrfs: wait between incomplete batch memory allocations"). [FIX] Although the commit mentioned that other filesystems do the wait, it's not the case at least nowadays. All the mainlined filesystems only call memalloc_retry_wait() if they failed to allocate any page (not only for bulk allocation). If there is any progress, they won't call memalloc_retry_wait() at all. For example, xfs_buf_alloc_pages() would only call memalloc_retry_wait() if there is no allocation progress at all, and the call is not for metadata readahead. So I don't believe we should call memalloc_retry_wait() unconditionally for short allocation. Call memalloc_retry_wait() if it fails to allocate any page for tree block allocation (which goes with __GFP_NOFAIL and may not need the special handling anyway), and reduce the latency for btrfs_alloc_page_array(). Reported-by: Julian Taylor Tested-by: Julian Taylor Link: https://lore.kernel.org/all/8966c095-cbe7-4d22-9784-a647d1bf27c3@1und1.de/ Fixes: 395cb57e8560 ("btrfs: wait between incomplete batch memory allocations") CC: stable@vger.kernel.org # 6.1+ Reviewed-by: Sweet Tea Dorminy Reviewed-by: Filipe Manana Signed-off-by: Qu Wenruo Reviewed-by: David Sterba Signed-off-by: David Sterba --- fs/btrfs/extent_io.c | 18 ++++-------------- 1 file changed, 4 insertions(+), 14 deletions(-) diff --git a/fs/btrfs/extent_io.c b/fs/btrfs/extent_io.c index b18034f2ab80..2776112dbdf8 100644 --- a/fs/btrfs/extent_io.c +++ b/fs/btrfs/extent_io.c @@ -681,31 +681,21 @@ static void end_bbio_data_read(struct btrfs_bio *bbio) int btrfs_alloc_page_array(unsigned int nr_pages, struct page **page_array, gfp_t extra_gfp) { + const gfp_t gfp = GFP_NOFS | extra_gfp; unsigned int allocated; for (allocated = 0; allocated < nr_pages;) { unsigned int last = allocated; - allocated = alloc_pages_bulk_array(GFP_NOFS | extra_gfp, - nr_pages, page_array); - - if (allocated == nr_pages) - return 0; - - /* - * During this iteration, no page could be allocated, even - * though alloc_pages_bulk_array() falls back to alloc_page() - * if it could not bulk-allocate. So we must be out of memory. - */ - if (allocated == last) { + allocated = alloc_pages_bulk_array(gfp, nr_pages, page_array); + if (unlikely(allocated == last)) { + /* No progress, fail and do cleanup. */ for (int i = 0; i < allocated; i++) { __free_page(page_array[i]); page_array[i] = NULL; } return -ENOMEM; } - - memalloc_retry_wait(GFP_NOFS); } return 0; } -- cgit v1.2.3 From 60b703c71fa80de0c2e14af66e57e234019b7da2 Mon Sep 17 00:00:00 2001 From: Thorsten Blum Date: Tue, 2 Apr 2024 12:17:16 +0200 Subject: zonefs: Use str_plural() to fix Coccinelle warning Fixes the following Coccinelle/coccicheck warning reported by string_choices.cocci: opportunity for str_plural(zgroup->g_nr_zones) Signed-off-by: Thorsten Blum Signed-off-by: Damien Le Moal --- fs/zonefs/super.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/zonefs/super.c b/fs/zonefs/super.c index c6a124e8d565..964fa7f24003 100644 --- a/fs/zonefs/super.c +++ b/fs/zonefs/super.c @@ -1048,7 +1048,7 @@ static int zonefs_init_zgroup(struct super_block *sb, zonefs_info(sb, "Zone group \"%s\" has %u file%s\n", zonefs_zgroup_name(ztype), zgroup->g_nr_zones, - zgroup->g_nr_zones > 1 ? "s" : ""); + str_plural(zgroup->g_nr_zones)); return 0; } -- cgit v1.2.3 From 9b31152fd74eeb10a20345909e542fef6f1d98e2 Mon Sep 17 00:00:00 2001 From: Kent Overstreet Date: Tue, 9 Apr 2024 18:50:27 -0400 Subject: bcachefs: btree_node_scan: Respect member.data_allowed If a device wasn't used for btree nodes, no need to scan for them. Signed-off-by: Kent Overstreet --- fs/bcachefs/btree_node_scan.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/fs/bcachefs/btree_node_scan.c b/fs/bcachefs/btree_node_scan.c index a7d0593b3871..556f76f5c84e 100644 --- a/fs/bcachefs/btree_node_scan.c +++ b/fs/bcachefs/btree_node_scan.c @@ -216,6 +216,9 @@ static int read_btree_nodes(struct find_btree_nodes *f) closure_init_stack(&cl); for_each_online_member(c, ca) { + if (!(ca->mi.data_allowed & BIT(BCH_DATA_btree))) + continue; + struct find_btree_nodes_worker *w = kmalloc(sizeof(*w), GFP_KERNEL); struct task_struct *t; -- cgit v1.2.3 From 6e45a30fe5e7cf5d42ac07262a3d97644f23dc68 Mon Sep 17 00:00:00 2001 From: Eric Van Hensbergen Date: Tue, 9 Apr 2024 23:53:00 +0000 Subject: fs/9p: remove erroneous nlink init from legacy stat2inode In 9p2000 legacy mode, stat2inode initializes nlink to 1, which is redundant with what alloc_inode should have already set. 9p2000.u overrides this with extensions if present in the stat structure, and 9p2000.L incorporates nlink into its stat structure. At the very least this probably messes with directory nlink accounting in legacy mode. Signed-off-by: Eric Van Hensbergen --- fs/9p/vfs_inode.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/fs/9p/vfs_inode.c b/fs/9p/vfs_inode.c index c5b4d3631c47..47bd77199e20 100644 --- a/fs/9p/vfs_inode.c +++ b/fs/9p/vfs_inode.c @@ -1064,8 +1064,6 @@ v9fs_stat2inode(struct p9_wstat *stat, struct inode *inode, struct v9fs_session_info *v9ses = sb->s_fs_info; struct v9fs_inode *v9inode = V9FS_I(inode); - set_nlink(inode, 1); - inode_set_atime(inode, stat->atime, 0); inode_set_mtime(inode, stat->mtime, 0); inode_set_ctime(inode, stat->mtime, 0); -- cgit v1.2.3 From 6309863b31dd80317cd7d6824820b44e254e2a9c Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Mon, 8 Apr 2024 08:28:43 +0000 Subject: net: add copy_safe_from_sockptr() helper copy_from_sockptr() helper is unsafe, unless callers did the prior check against user provided optlen. Too many callers get this wrong, lets add a helper to fix them and avoid future copy/paste bugs. Instead of : if (optlen < sizeof(opt)) { err = -EINVAL; break; } if (copy_from_sockptr(&opt, optval, sizeof(opt)) { err = -EFAULT; break; } Use : err = copy_safe_from_sockptr(&opt, sizeof(opt), optval, optlen); if (err) break; Signed-off-by: Eric Dumazet Link: https://lore.kernel.org/r/20240408082845.3957374-2-edumazet@google.com Signed-off-by: Jakub Kicinski --- include/linux/sockptr.h | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/include/linux/sockptr.h b/include/linux/sockptr.h index 307961b41541..317200cd3a60 100644 --- a/include/linux/sockptr.h +++ b/include/linux/sockptr.h @@ -50,11 +50,36 @@ static inline int copy_from_sockptr_offset(void *dst, sockptr_t src, return 0; } +/* Deprecated. + * This is unsafe, unless caller checked user provided optlen. + * Prefer copy_safe_from_sockptr() instead. + */ static inline int copy_from_sockptr(void *dst, sockptr_t src, size_t size) { return copy_from_sockptr_offset(dst, src, 0, size); } +/** + * copy_safe_from_sockptr: copy a struct from sockptr + * @dst: Destination address, in kernel space. This buffer must be @ksize + * bytes long. + * @ksize: Size of @dst struct. + * @optval: Source address. (in user or kernel space) + * @optlen: Size of @optval data. + * + * Returns: + * * -EINVAL: @optlen < @ksize + * * -EFAULT: access to userspace failed. + * * 0 : @ksize bytes were copied + */ +static inline int copy_safe_from_sockptr(void *dst, size_t ksize, + sockptr_t optval, unsigned int optlen) +{ + if (optlen < ksize) + return -EINVAL; + return copy_from_sockptr(dst, optval, ksize); +} + static inline int copy_struct_from_sockptr(void *dst, size_t ksize, sockptr_t src, size_t usize) { -- cgit v1.2.3 From 138b787804f4a10417618e8d1e6e2700539fd88c Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Mon, 8 Apr 2024 08:28:44 +0000 Subject: mISDN: fix MISDN_TIME_STAMP handling syzbot reports one unsafe call to copy_from_sockptr() [1] Use copy_safe_from_sockptr() instead. [1] BUG: KASAN: slab-out-of-bounds in copy_from_sockptr_offset include/linux/sockptr.h:49 [inline] BUG: KASAN: slab-out-of-bounds in copy_from_sockptr include/linux/sockptr.h:55 [inline] BUG: KASAN: slab-out-of-bounds in data_sock_setsockopt+0x46c/0x4cc drivers/isdn/mISDN/socket.c:417 Read of size 4 at addr ffff0000c6d54083 by task syz-executor406/6167 CPU: 1 PID: 6167 Comm: syz-executor406 Not tainted 6.8.0-rc7-syzkaller-g707081b61156 #0 Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 03/27/2024 Call trace: dump_backtrace+0x1b8/0x1e4 arch/arm64/kernel/stacktrace.c:291 show_stack+0x2c/0x3c arch/arm64/kernel/stacktrace.c:298 __dump_stack lib/dump_stack.c:88 [inline] dump_stack_lvl+0xd0/0x124 lib/dump_stack.c:106 print_address_description mm/kasan/report.c:377 [inline] print_report+0x178/0x518 mm/kasan/report.c:488 kasan_report+0xd8/0x138 mm/kasan/report.c:601 __asan_report_load_n_noabort+0x1c/0x28 mm/kasan/report_generic.c:391 copy_from_sockptr_offset include/linux/sockptr.h:49 [inline] copy_from_sockptr include/linux/sockptr.h:55 [inline] data_sock_setsockopt+0x46c/0x4cc drivers/isdn/mISDN/socket.c:417 do_sock_setsockopt+0x2a0/0x4e0 net/socket.c:2311 __sys_setsockopt+0x128/0x1a8 net/socket.c:2334 __do_sys_setsockopt net/socket.c:2343 [inline] __se_sys_setsockopt net/socket.c:2340 [inline] __arm64_sys_setsockopt+0xb8/0xd4 net/socket.c:2340 __invoke_syscall arch/arm64/kernel/syscall.c:34 [inline] invoke_syscall+0x98/0x2b8 arch/arm64/kernel/syscall.c:48 el0_svc_common+0x130/0x23c arch/arm64/kernel/syscall.c:133 do_el0_svc+0x48/0x58 arch/arm64/kernel/syscall.c:152 el0_svc+0x54/0x168 arch/arm64/kernel/entry-common.c:712 el0t_64_sync_handler+0x84/0xfc arch/arm64/kernel/entry-common.c:730 el0t_64_sync+0x190/0x194 arch/arm64/kernel/entry.S:598 Fixes: 1b2b03f8e514 ("Add mISDN core files") Signed-off-by: Eric Dumazet Reported-by: syzbot Cc: Karsten Keil Link: https://lore.kernel.org/r/20240408082845.3957374-3-edumazet@google.com Signed-off-by: Jakub Kicinski --- drivers/isdn/mISDN/socket.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/isdn/mISDN/socket.c b/drivers/isdn/mISDN/socket.c index 2776ca5fc33f..b215b28cad7b 100644 --- a/drivers/isdn/mISDN/socket.c +++ b/drivers/isdn/mISDN/socket.c @@ -401,23 +401,23 @@ data_sock_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) } static int data_sock_setsockopt(struct socket *sock, int level, int optname, - sockptr_t optval, unsigned int len) + sockptr_t optval, unsigned int optlen) { struct sock *sk = sock->sk; int err = 0, opt = 0; if (*debug & DEBUG_SOCKET) printk(KERN_DEBUG "%s(%p, %d, %x, optval, %d)\n", __func__, sock, - level, optname, len); + level, optname, optlen); lock_sock(sk); switch (optname) { case MISDN_TIME_STAMP: - if (copy_from_sockptr(&opt, optval, sizeof(int))) { - err = -EFAULT; + err = copy_safe_from_sockptr(&opt, sizeof(opt), + optval, optlen); + if (err) break; - } if (opt) _pms(sk)->cmask |= MISDN_TIME_STAMP; -- cgit v1.2.3 From 7a87441c9651ba37842f4809224aca13a554a26f Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Mon, 8 Apr 2024 08:28:45 +0000 Subject: nfc: llcp: fix nfc_llcp_setsockopt() unsafe copies syzbot reported unsafe calls to copy_from_sockptr() [1] Use copy_safe_from_sockptr() instead. [1] BUG: KASAN: slab-out-of-bounds in copy_from_sockptr_offset include/linux/sockptr.h:49 [inline] BUG: KASAN: slab-out-of-bounds in copy_from_sockptr include/linux/sockptr.h:55 [inline] BUG: KASAN: slab-out-of-bounds in nfc_llcp_setsockopt+0x6c2/0x850 net/nfc/llcp_sock.c:255 Read of size 4 at addr ffff88801caa1ec3 by task syz-executor459/5078 CPU: 0 PID: 5078 Comm: syz-executor459 Not tainted 6.8.0-syzkaller-08951-gfe46a7dd189e #0 Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 03/27/2024 Call Trace: __dump_stack lib/dump_stack.c:88 [inline] dump_stack_lvl+0x241/0x360 lib/dump_stack.c:114 print_address_description mm/kasan/report.c:377 [inline] print_report+0x169/0x550 mm/kasan/report.c:488 kasan_report+0x143/0x180 mm/kasan/report.c:601 copy_from_sockptr_offset include/linux/sockptr.h:49 [inline] copy_from_sockptr include/linux/sockptr.h:55 [inline] nfc_llcp_setsockopt+0x6c2/0x850 net/nfc/llcp_sock.c:255 do_sock_setsockopt+0x3b1/0x720 net/socket.c:2311 __sys_setsockopt+0x1ae/0x250 net/socket.c:2334 __do_sys_setsockopt net/socket.c:2343 [inline] __se_sys_setsockopt net/socket.c:2340 [inline] __x64_sys_setsockopt+0xb5/0xd0 net/socket.c:2340 do_syscall_64+0xfd/0x240 entry_SYSCALL_64_after_hwframe+0x6d/0x75 RIP: 0033:0x7f7fac07fd89 Code: 28 00 00 00 75 05 48 83 c4 28 c3 e8 91 18 00 00 90 48 89 f8 48 89 f7 48 89 d6 48 89 ca 4d 89 c2 4d 89 c8 4c 8b 4c 24 08 0f 05 <48> 3d 01 f0 ff ff 73 01 c3 48 c7 c1 b8 ff ff ff f7 d8 64 89 01 48 RSP: 002b:00007fff660eb788 EFLAGS: 00000246 ORIG_RAX: 0000000000000036 RAX: ffffffffffffffda RBX: 0000000000000003 RCX: 00007f7fac07fd89 RDX: 0000000000000000 RSI: 0000000000000118 RDI: 0000000000000004 RBP: 0000000000000000 R08: 0000000000000002 R09: 0000000000000000 R10: 0000000020000a80 R11: 0000000000000246 R12: 0000000000000000 R13: 0000000000000000 R14: 0000000000000000 R15: 0000000000000000 Signed-off-by: Eric Dumazet Reported-by: syzbot Reviewed-by: Krzysztof Kozlowski Link: https://lore.kernel.org/r/20240408082845.3957374-4-edumazet@google.com Signed-off-by: Jakub Kicinski --- net/nfc/llcp_sock.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/net/nfc/llcp_sock.c b/net/nfc/llcp_sock.c index 819157bbb5a2..d5344563e525 100644 --- a/net/nfc/llcp_sock.c +++ b/net/nfc/llcp_sock.c @@ -252,10 +252,10 @@ static int nfc_llcp_setsockopt(struct socket *sock, int level, int optname, break; } - if (copy_from_sockptr(&opt, optval, sizeof(u32))) { - err = -EFAULT; + err = copy_safe_from_sockptr(&opt, sizeof(opt), + optval, optlen); + if (err) break; - } if (opt > LLCP_MAX_RW) { err = -EINVAL; @@ -274,10 +274,10 @@ static int nfc_llcp_setsockopt(struct socket *sock, int level, int optname, break; } - if (copy_from_sockptr(&opt, optval, sizeof(u32))) { - err = -EFAULT; + err = copy_safe_from_sockptr(&opt, sizeof(opt), + optval, optlen); + if (err) break; - } if (opt > LLCP_MAX_MIUX) { err = -EINVAL; -- cgit v1.2.3 From 7633c4da919ad51164acbf1aa322cc1a3ead6129 Mon Sep 17 00:00:00 2001 From: Jiri Benc Date: Mon, 8 Apr 2024 16:18:21 +0200 Subject: ipv6: fix race condition between ipv6_get_ifaddr and ipv6_del_addr Although ipv6_get_ifaddr walks inet6_addr_lst under the RCU lock, it still means hlist_for_each_entry_rcu can return an item that got removed from the list. The memory itself of such item is not freed thanks to RCU but nothing guarantees the actual content of the memory is sane. In particular, the reference count can be zero. This can happen if ipv6_del_addr is called in parallel. ipv6_del_addr removes the entry from inet6_addr_lst (hlist_del_init_rcu(&ifp->addr_lst)) and drops all references (__in6_ifa_put(ifp) + in6_ifa_put(ifp)). With bad enough timing, this can happen: 1. In ipv6_get_ifaddr, hlist_for_each_entry_rcu returns an entry. 2. Then, the whole ipv6_del_addr is executed for the given entry. The reference count drops to zero and kfree_rcu is scheduled. 3. ipv6_get_ifaddr continues and tries to increments the reference count (in6_ifa_hold). 4. The rcu is unlocked and the entry is freed. 5. The freed entry is returned. Prevent increasing of the reference count in such case. The name in6_ifa_hold_safe is chosen to mimic the existing fib6_info_hold_safe. [ 41.506330] refcount_t: addition on 0; use-after-free. [ 41.506760] WARNING: CPU: 0 PID: 595 at lib/refcount.c:25 refcount_warn_saturate+0xa5/0x130 [ 41.507413] Modules linked in: veth bridge stp llc [ 41.507821] CPU: 0 PID: 595 Comm: python3 Not tainted 6.9.0-rc2.main-00208-g49563be82afa #14 [ 41.508479] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996) [ 41.509163] RIP: 0010:refcount_warn_saturate+0xa5/0x130 [ 41.509586] Code: ad ff 90 0f 0b 90 90 c3 cc cc cc cc 80 3d c0 30 ad 01 00 75 a0 c6 05 b7 30 ad 01 01 90 48 c7 c7 38 cc 7a 8c e8 cc 18 ad ff 90 <0f> 0b 90 90 c3 cc cc cc cc 80 3d 98 30 ad 01 00 0f 85 75 ff ff ff [ 41.510956] RSP: 0018:ffffbda3c026baf0 EFLAGS: 00010282 [ 41.511368] RAX: 0000000000000000 RBX: ffff9e9c46914800 RCX: 0000000000000000 [ 41.511910] RDX: ffff9e9c7ec29c00 RSI: ffff9e9c7ec1c900 RDI: ffff9e9c7ec1c900 [ 41.512445] RBP: ffff9e9c43660c9c R08: 0000000000009ffb R09: 00000000ffffdfff [ 41.512998] R10: 00000000ffffdfff R11: ffffffff8ca58a40 R12: ffff9e9c4339a000 [ 41.513534] R13: 0000000000000001 R14: ffff9e9c438a0000 R15: ffffbda3c026bb48 [ 41.514086] FS: 00007fbc4cda1740(0000) GS:ffff9e9c7ec00000(0000) knlGS:0000000000000000 [ 41.514726] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 [ 41.515176] CR2: 000056233b337d88 CR3: 000000000376e006 CR4: 0000000000370ef0 [ 41.515713] DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 [ 41.516252] DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400 [ 41.516799] Call Trace: [ 41.517037] [ 41.517249] ? __warn+0x7b/0x120 [ 41.517535] ? refcount_warn_saturate+0xa5/0x130 [ 41.517923] ? report_bug+0x164/0x190 [ 41.518240] ? handle_bug+0x3d/0x70 [ 41.518541] ? exc_invalid_op+0x17/0x70 [ 41.520972] ? asm_exc_invalid_op+0x1a/0x20 [ 41.521325] ? refcount_warn_saturate+0xa5/0x130 [ 41.521708] ipv6_get_ifaddr+0xda/0xe0 [ 41.522035] inet6_rtm_getaddr+0x342/0x3f0 [ 41.522376] ? __pfx_inet6_rtm_getaddr+0x10/0x10 [ 41.522758] rtnetlink_rcv_msg+0x334/0x3d0 [ 41.523102] ? netlink_unicast+0x30f/0x390 [ 41.523445] ? __pfx_rtnetlink_rcv_msg+0x10/0x10 [ 41.523832] netlink_rcv_skb+0x53/0x100 [ 41.524157] netlink_unicast+0x23b/0x390 [ 41.524484] netlink_sendmsg+0x1f2/0x440 [ 41.524826] __sys_sendto+0x1d8/0x1f0 [ 41.525145] __x64_sys_sendto+0x1f/0x30 [ 41.525467] do_syscall_64+0xa5/0x1b0 [ 41.525794] entry_SYSCALL_64_after_hwframe+0x72/0x7a [ 41.526213] RIP: 0033:0x7fbc4cfcea9a [ 41.526528] Code: d8 64 89 02 48 c7 c0 ff ff ff ff eb b8 0f 1f 00 f3 0f 1e fa 41 89 ca 64 8b 04 25 18 00 00 00 85 c0 75 15 b8 2c 00 00 00 0f 05 <48> 3d 00 f0 ff ff 77 7e c3 0f 1f 44 00 00 41 54 48 83 ec 30 44 89 [ 41.527942] RSP: 002b:00007ffcf54012a8 EFLAGS: 00000246 ORIG_RAX: 000000000000002c [ 41.528593] RAX: ffffffffffffffda RBX: 00007ffcf5401368 RCX: 00007fbc4cfcea9a [ 41.529173] RDX: 000000000000002c RSI: 00007fbc4b9d9bd0 RDI: 0000000000000005 [ 41.529786] RBP: 00007fbc4bafb040 R08: 00007ffcf54013e0 R09: 000000000000000c [ 41.530375] R10: 0000000000000000 R11: 0000000000000246 R12: 0000000000000000 [ 41.530977] R13: ffffffffc4653600 R14: 0000000000000001 R15: 00007fbc4ca85d1b [ 41.531573] Fixes: 5c578aedcb21d ("IPv6: convert addrconf hash list to RCU") Reviewed-by: Eric Dumazet Reviewed-by: David Ahern Signed-off-by: Jiri Benc Link: https://lore.kernel.org/r/8ab821e36073a4a406c50ec83c9e8dc586c539e4.1712585809.git.jbenc@redhat.com Signed-off-by: Jakub Kicinski --- include/net/addrconf.h | 4 ++++ net/ipv6/addrconf.c | 7 ++++--- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/include/net/addrconf.h b/include/net/addrconf.h index 9d06eb945509..62a407db1bf5 100644 --- a/include/net/addrconf.h +++ b/include/net/addrconf.h @@ -438,6 +438,10 @@ static inline void in6_ifa_hold(struct inet6_ifaddr *ifp) refcount_inc(&ifp->refcnt); } +static inline bool in6_ifa_hold_safe(struct inet6_ifaddr *ifp) +{ + return refcount_inc_not_zero(&ifp->refcnt); +} /* * compute link-local solicited-node multicast address diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c index 92db9b474f2b..779aa6ecdd49 100644 --- a/net/ipv6/addrconf.c +++ b/net/ipv6/addrconf.c @@ -2091,9 +2091,10 @@ struct inet6_ifaddr *ipv6_get_ifaddr(struct net *net, const struct in6_addr *add if (ipv6_addr_equal(&ifp->addr, addr)) { if (!dev || ifp->idev->dev == dev || !(ifp->scope&(IFA_LINK|IFA_HOST) || strict)) { - result = ifp; - in6_ifa_hold(ifp); - break; + if (in6_ifa_hold_safe(ifp)) { + result = ifp; + break; + } } } } -- cgit v1.2.3 From 8bdfb4ea95ca738d33ef71376c21eba20130f2eb Mon Sep 17 00:00:00 2001 From: Harish Kasiviswanathan Date: Tue, 26 Mar 2024 15:32:46 -0400 Subject: drm/amdkfd: Reset GPU on queue preemption failure Currently, with F32 HWS GPU reset is only when unmap queue fails. However, if compute queue doesn't repond to preemption request in time unmap will return without any error. In this case, only preemption error is logged and Reset is not triggered. Call GPU reset in this case also. Reviewed-by: Alex Deucher Signed-off-by: Harish Kasiviswanathan Reviewed-by: Mukul Joshi Signed-off-by: Alex Deucher Cc: stable@vger.kernel.org --- drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c b/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c index f4d395e38683..0b655555e167 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c @@ -2001,6 +2001,7 @@ static int unmap_queues_cpsch(struct device_queue_manager *dqm, dev_err(dev, "HIQ MQD's queue_doorbell_id0 is not 0, Queue preemption time out\n"); while (halt_if_hws_hang) schedule(); + kfd_hws_hang(dqm); return -ETIME; } -- cgit v1.2.3 From 65ff8092e4802f96d87d3d7cde146961f5228265 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Sat, 23 Mar 2024 20:46:53 -0400 Subject: drm/amdgpu: always force full reset for SOC21 There are cases where soft reset seems to succeed, but does not, so always use mode1/2 for now. Reviewed-by: Harish Kasiviswanathan Signed-off-by: Alex Deucher Cc: stable@vger.kernel.org --- drivers/gpu/drm/amd/amdgpu/soc21.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/soc21.c b/drivers/gpu/drm/amd/amdgpu/soc21.c index 581a3bd11481..8526282f4da1 100644 --- a/drivers/gpu/drm/amd/amdgpu/soc21.c +++ b/drivers/gpu/drm/amd/amdgpu/soc21.c @@ -457,10 +457,8 @@ static bool soc21_need_full_reset(struct amdgpu_device *adev) { switch (amdgpu_ip_version(adev, GC_HWIP, 0)) { case IP_VERSION(11, 0, 0): - return amdgpu_ras_is_supported(adev, AMDGPU_RAS_BLOCK__UMC); case IP_VERSION(11, 0, 2): case IP_VERSION(11, 0, 3): - return false; default: return true; } -- cgit v1.2.3 From 4b18a91faf1752f9bd69a4ed3aed2c8f6e5b0528 Mon Sep 17 00:00:00 2001 From: Lijo Lazar Date: Thu, 21 Mar 2024 17:46:36 +0530 Subject: drm/amdgpu: Refine IB schedule error logging MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Downgrade to debug information when IBs are skipped. Also, use dev_* to identify the device. Signed-off-by: Lijo Lazar Reviewed-by: Christian König Reviewed-by: Asad Kamal Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_job.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_job.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_job.c index 4b3000c21ef2..e4742b65032d 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_job.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_job.c @@ -304,12 +304,15 @@ static struct dma_fence *amdgpu_job_run(struct drm_sched_job *sched_job) dma_fence_set_error(finished, -ECANCELED); if (finished->error < 0) { - DRM_INFO("Skip scheduling IBs!\n"); + dev_dbg(adev->dev, "Skip scheduling IBs in ring(%s)", + ring->name); } else { r = amdgpu_ib_schedule(ring, job->num_ibs, job->ibs, job, &fence); if (r) - DRM_ERROR("Error scheduling IBs (%d)\n", r); + dev_err(adev->dev, + "Error scheduling IBs (%d) in ring(%s)", r, + ring->name); } job->job_run_counter++; -- cgit v1.2.3 From 0f1bbcc2bab25d5fb2dfb1ee3e08131437690d3d Mon Sep 17 00:00:00 2001 From: Lang Yu Date: Mon, 25 Mar 2024 13:24:31 +0800 Subject: drm/amdgpu/umsch: reinitialize write pointer in hw init Otherwise the old one will be used during GPU reset. That's not expected. Signed-off-by: Lang Yu Reviewed-by: Feifei Xu Signed-off-by: Alex Deucher Cc: stable@vger.kernel.org --- drivers/gpu/drm/amd/amdgpu/umsch_mm_v4_0.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/gpu/drm/amd/amdgpu/umsch_mm_v4_0.c b/drivers/gpu/drm/amd/amdgpu/umsch_mm_v4_0.c index 84368cf1e175..bd57896ab85d 100644 --- a/drivers/gpu/drm/amd/amdgpu/umsch_mm_v4_0.c +++ b/drivers/gpu/drm/amd/amdgpu/umsch_mm_v4_0.c @@ -225,6 +225,8 @@ static int umsch_mm_v4_0_ring_start(struct amdgpu_umsch_mm *umsch) WREG32_SOC15(VCN, 0, regVCN_UMSCH_RB_SIZE, ring->ring_size); + ring->wptr = 0; + data = RREG32_SOC15(VCN, 0, regVCN_RB_ENABLE); data &= ~(VCN_RB_ENABLE__AUDIO_RB_EN_MASK); WREG32_SOC15(VCN, 0, regVCN_RB_ENABLE, data); -- cgit v1.2.3 From 8b2be55f4d6c1099d7f629b0ed7535a5be788c83 Mon Sep 17 00:00:00 2001 From: Lijo Lazar Date: Wed, 14 Feb 2024 17:55:54 +0530 Subject: drm/amdgpu: Reset dGPU if suspend got aborted For SOC21 ASICs, there is an issue in re-enabling PM features if a suspend got aborted. In such cases, reset the device during resume phase. This is a workaround till a proper solution is finalized. Signed-off-by: Lijo Lazar Reviewed-by: Alex Deucher Reviewed-by: Yang Wang Reviewed-by: Hawking Zhang Signed-off-by: Alex Deucher Cc: stable@vger.kernel.org --- drivers/gpu/drm/amd/amdgpu/soc21.c | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/drivers/gpu/drm/amd/amdgpu/soc21.c b/drivers/gpu/drm/amd/amdgpu/soc21.c index 8526282f4da1..abe319b0f063 100644 --- a/drivers/gpu/drm/amd/amdgpu/soc21.c +++ b/drivers/gpu/drm/amd/amdgpu/soc21.c @@ -867,10 +867,35 @@ static int soc21_common_suspend(void *handle) return soc21_common_hw_fini(adev); } +static bool soc21_need_reset_on_resume(struct amdgpu_device *adev) +{ + u32 sol_reg1, sol_reg2; + + /* Will reset for the following suspend abort cases. + * 1) Only reset dGPU side. + * 2) S3 suspend got aborted and TOS is active. + */ + if (!(adev->flags & AMD_IS_APU) && adev->in_s3 && + !adev->suspend_complete) { + sol_reg1 = RREG32_SOC15(MP0, 0, regMP0_SMN_C2PMSG_81); + msleep(100); + sol_reg2 = RREG32_SOC15(MP0, 0, regMP0_SMN_C2PMSG_81); + + return (sol_reg1 != sol_reg2); + } + + return false; +} + static int soc21_common_resume(void *handle) { struct amdgpu_device *adev = (struct amdgpu_device *)handle; + if (soc21_need_reset_on_resume(adev)) { + dev_info(adev->dev, "S3 suspend aborted, resetting..."); + soc21_asic_reset(adev); + } + return soc21_common_hw_init(adev); } -- cgit v1.2.3 From d4396924c3d44f34d0643f650e70892e07f3677f Mon Sep 17 00:00:00 2001 From: Li Ma Date: Thu, 28 Mar 2024 10:55:10 +0800 Subject: drm/amd/display: add DCN 351 version for microcode load There is a new DCN veriosn 3.5.1 need to load Signed-off-by: Li Ma Reviewed-by: Yifan Zhang Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index 71d2d44681b2..173438fc7537 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -148,6 +148,9 @@ MODULE_FIRMWARE(FIRMWARE_NAVI12_DMCU); #define FIRMWARE_DCN_35_DMUB "amdgpu/dcn_3_5_dmcub.bin" MODULE_FIRMWARE(FIRMWARE_DCN_35_DMUB); +#define FIRMWARE_DCN_351_DMUB "amdgpu/dcn_3_5_1_dmcub.bin" +MODULE_FIRMWARE(FIRMWARE_DCN_351_DMUB); + /* Number of bytes in PSP header for firmware. */ #define PSP_HEADER_BYTES 0x100 @@ -4820,9 +4823,11 @@ static int dm_init_microcode(struct amdgpu_device *adev) fw_name_dmub = FIRMWARE_DCN_V3_2_1_DMCUB; break; case IP_VERSION(3, 5, 0): - case IP_VERSION(3, 5, 1): fw_name_dmub = FIRMWARE_DCN_35_DMUB; break; + case IP_VERSION(3, 5, 1): + fw_name_dmub = FIRMWARE_DCN_351_DMUB; + break; default: /* ASIC doesn't support DMUB. */ return 0; -- cgit v1.2.3 From 31729e8c21ecfd671458e02b6511eb68c2225113 Mon Sep 17 00:00:00 2001 From: Tim Huang Date: Wed, 27 Mar 2024 13:10:37 +0800 Subject: drm/amd/pm: fixes a random hang in S4 for SMU v13.0.4/11 While doing multiple S4 stress tests, GC/RLC/PMFW get into an invalid state resulting into hard hangs. Adding a GFX reset as workaround just before sending the MP1_UNLOAD message avoids this failure. Signed-off-by: Tim Huang Acked-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_4_ppt.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_4_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_4_ppt.c index bb98156b2fa1..949131bd1ecb 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_4_ppt.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_4_ppt.c @@ -226,8 +226,18 @@ static int smu_v13_0_4_system_features_control(struct smu_context *smu, bool en) struct amdgpu_device *adev = smu->adev; int ret = 0; - if (!en && !adev->in_s0ix) + if (!en && !adev->in_s0ix) { + /* Adds a GFX reset as workaround just before sending the + * MP1_UNLOAD message to prevent GC/RLC/PMFW from entering + * an invalid state. + */ + ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_GfxDeviceDriverReset, + SMU_RESET_MODE_2, NULL); + if (ret) + return ret; + ret = smu_cmn_send_smc_msg(smu, SMU_MSG_PrepareMp1ForUnload, NULL); + } return ret; } -- cgit v1.2.3 From a3a4c0b12346a2493b41c8790d85141844a04e28 Mon Sep 17 00:00:00 2001 From: shaoyunl Date: Fri, 22 Mar 2024 12:25:16 -0400 Subject: drm/amdgpu : Add mes_log_enable to control mes log feature The MES log might slow down the performance for extra step of log the data, disable it by default and introduce a parameter can enable it when necessary Signed-off-by: shaoyunl Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu.h | 1 + drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c | 10 ++++++++++ drivers/gpu/drm/amd/amdgpu/amdgpu_mes.c | 5 ++++- drivers/gpu/drm/amd/amdgpu/mes_v11_0.c | 7 +++++-- 4 files changed, 20 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu.h b/drivers/gpu/drm/amd/amdgpu/amdgpu.h index 9c62552bec34..b3b84647207e 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu.h @@ -210,6 +210,7 @@ extern int amdgpu_async_gfx_ring; extern int amdgpu_mcbp; extern int amdgpu_discovery; extern int amdgpu_mes; +extern int amdgpu_mes_log_enable; extern int amdgpu_mes_kiq; extern int amdgpu_noretry; extern int amdgpu_force_asic_type; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c index 80b9642f2bc4..e4277298cf1a 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c @@ -195,6 +195,7 @@ int amdgpu_async_gfx_ring = 1; int amdgpu_mcbp = -1; int amdgpu_discovery = -1; int amdgpu_mes; +int amdgpu_mes_log_enable = 0; int amdgpu_mes_kiq; int amdgpu_noretry = -1; int amdgpu_force_asic_type = -1; @@ -667,6 +668,15 @@ MODULE_PARM_DESC(mes, "Enable Micro Engine Scheduler (0 = disabled (default), 1 = enabled)"); module_param_named(mes, amdgpu_mes, int, 0444); +/** + * DOC: mes_log_enable (int) + * Enable Micro Engine Scheduler log. This is used to enable/disable MES internal log. + * (0 = disabled (default), 1 = enabled) + */ +MODULE_PARM_DESC(mes_log_enable, + "Enable Micro Engine Scheduler log (0 = disabled (default), 1 = enabled)"); +module_param_named(mes_log_enable, amdgpu_mes_log_enable, int, 0444); + /** * DOC: mes_kiq (int) * Enable Micro Engine Scheduler KIQ. This is a new engine pipe for kiq. diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_mes.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_mes.c index a98e03e0a51f..cfd613ea39b3 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_mes.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_mes.c @@ -102,6 +102,9 @@ static int amdgpu_mes_event_log_init(struct amdgpu_device *adev) { int r; + if (!amdgpu_mes_log_enable) + return 0; + r = amdgpu_bo_create_kernel(adev, PAGE_SIZE, PAGE_SIZE, AMDGPU_GEM_DOMAIN_GTT, &adev->mes.event_log_gpu_obj, @@ -1565,7 +1568,7 @@ void amdgpu_debugfs_mes_event_log_init(struct amdgpu_device *adev) #if defined(CONFIG_DEBUG_FS) struct drm_minor *minor = adev_to_drm(adev)->primary; struct dentry *root = minor->debugfs_root; - if (adev->enable_mes) + if (adev->enable_mes && amdgpu_mes_log_enable) debugfs_create_file("amdgpu_mes_event_log", 0444, root, adev, &amdgpu_debugfs_mes_event_log_fops); diff --git a/drivers/gpu/drm/amd/amdgpu/mes_v11_0.c b/drivers/gpu/drm/amd/amdgpu/mes_v11_0.c index 072c478665ad..63f281a9984d 100644 --- a/drivers/gpu/drm/amd/amdgpu/mes_v11_0.c +++ b/drivers/gpu/drm/amd/amdgpu/mes_v11_0.c @@ -411,8 +411,11 @@ static int mes_v11_0_set_hw_resources(struct amdgpu_mes *mes) mes_set_hw_res_pkt.enable_reg_active_poll = 1; mes_set_hw_res_pkt.enable_level_process_quantum_check = 1; mes_set_hw_res_pkt.oversubscription_timer = 50; - mes_set_hw_res_pkt.enable_mes_event_int_logging = 1; - mes_set_hw_res_pkt.event_intr_history_gpu_mc_ptr = mes->event_log_gpu_addr; + if (amdgpu_mes_log_enable) { + mes_set_hw_res_pkt.enable_mes_event_int_logging = 1; + mes_set_hw_res_pkt.event_intr_history_gpu_mc_ptr = + mes->event_log_gpu_addr; + } return mes_v11_0_submit_pkt_and_poll_completion(mes, &mes_set_hw_res_pkt, sizeof(mes_set_hw_res_pkt), -- cgit v1.2.3 From 5b0cd091d905ee9da0a3ecdf06b9cbdd17ba711d Mon Sep 17 00:00:00 2001 From: shaoyunl Date: Fri, 22 Mar 2024 12:44:55 -0400 Subject: drm/amdgpu : Increase the mes log buffer size as per new MES FW version From MES version 0x54, the log entry increased and require the log buffer size to be increased. The 16k is maximum size agreed Signed-off-by: shaoyunl Acked-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_mes.c | 5 ++--- drivers/gpu/drm/amd/amdgpu/amdgpu_mes.h | 1 + 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_mes.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_mes.c index cfd613ea39b3..a00cf4756ad0 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_mes.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_mes.c @@ -105,7 +105,7 @@ static int amdgpu_mes_event_log_init(struct amdgpu_device *adev) if (!amdgpu_mes_log_enable) return 0; - r = amdgpu_bo_create_kernel(adev, PAGE_SIZE, PAGE_SIZE, + r = amdgpu_bo_create_kernel(adev, AMDGPU_MES_LOG_BUFFER_SIZE, PAGE_SIZE, AMDGPU_GEM_DOMAIN_GTT, &adev->mes.event_log_gpu_obj, &adev->mes.event_log_gpu_addr, @@ -1552,12 +1552,11 @@ static int amdgpu_debugfs_mes_event_log_show(struct seq_file *m, void *unused) uint32_t *mem = (uint32_t *)(adev->mes.event_log_cpu_addr); seq_hex_dump(m, "", DUMP_PREFIX_OFFSET, 32, 4, - mem, PAGE_SIZE, false); + mem, AMDGPU_MES_LOG_BUFFER_SIZE, false); return 0; } - DEFINE_SHOW_ATTRIBUTE(amdgpu_debugfs_mes_event_log); #endif diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_mes.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_mes.h index 7d4f93fea937..4c8fc3117ef8 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_mes.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_mes.h @@ -52,6 +52,7 @@ enum amdgpu_mes_priority_level { #define AMDGPU_MES_PROC_CTX_SIZE 0x1000 /* one page area */ #define AMDGPU_MES_GANG_CTX_SIZE 0x1000 /* one page area */ +#define AMDGPU_MES_LOG_BUFFER_SIZE 0x4000 /* Maximu log buffer size for MES */ struct amdgpu_mes_funcs; -- cgit v1.2.3 From c5b1ccff26950d50bf2043cb2af9bafb1f08bbaf Mon Sep 17 00:00:00 2001 From: lima1002 Date: Mon, 29 Jan 2024 20:17:54 +0800 Subject: drm/amd/swsmu: Update smu v14.0.0 headers to be 14.0.1 compatible update ppsmc.h pmfw.h and driver_if.h for smu v14_0_1 Reviewed-by: Alex Deucher Signed-off-by: lima1002 Signed-off-by: Alex Deucher --- .../pm/swsmu/inc/pmfw_if/smu14_driver_if_v14_0_0.h | 33 +- .../amd/pm/swsmu/inc/pmfw_if/smu_v14_0_0_pmfw.h | 55 +++- .../amd/pm/swsmu/inc/pmfw_if/smu_v14_0_0_ppsmc.h | 18 +- drivers/gpu/drm/amd/pm/swsmu/inc/smu_v14_0.h | 1 + drivers/gpu/drm/amd/pm/swsmu/smu14/smu_v14_0.c | 2 +- .../gpu/drm/amd/pm/swsmu/smu14/smu_v14_0_0_ppt.c | 347 +++++++++++++++++++-- 6 files changed, 413 insertions(+), 43 deletions(-) diff --git a/drivers/gpu/drm/amd/pm/swsmu/inc/pmfw_if/smu14_driver_if_v14_0_0.h b/drivers/gpu/drm/amd/pm/swsmu/inc/pmfw_if/smu14_driver_if_v14_0_0.h index 5bb7a63c0602..97522c085258 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/inc/pmfw_if/smu14_driver_if_v14_0_0.h +++ b/drivers/gpu/drm/amd/pm/swsmu/inc/pmfw_if/smu14_driver_if_v14_0_0.h @@ -144,6 +144,37 @@ typedef struct { uint32_t MaxGfxClk; } DpmClocks_t; +//Freq in MHz +//Voltage in milli volts with 2 fractional bits +typedef struct { + uint32_t DcfClocks[NUM_DCFCLK_DPM_LEVELS]; + uint32_t DispClocks[NUM_DISPCLK_DPM_LEVELS]; + uint32_t DppClocks[NUM_DPPCLK_DPM_LEVELS]; + uint32_t SocClocks[NUM_SOCCLK_DPM_LEVELS]; + uint32_t VClocks0[NUM_VCN_DPM_LEVELS]; + uint32_t VClocks1[NUM_VCN_DPM_LEVELS]; + uint32_t DClocks0[NUM_VCN_DPM_LEVELS]; + uint32_t DClocks1[NUM_VCN_DPM_LEVELS]; + uint32_t VPEClocks[NUM_VPE_DPM_LEVELS]; + uint32_t FclkClocks_Freq[NUM_FCLK_DPM_LEVELS]; + uint32_t FclkClocks_Voltage[NUM_FCLK_DPM_LEVELS]; + uint32_t SocVoltage[NUM_SOC_VOLTAGE_LEVELS]; + MemPstateTable_t MemPstateTable[NUM_MEM_PSTATE_LEVELS]; + + uint8_t NumDcfClkLevelsEnabled; + uint8_t NumDispClkLevelsEnabled; //Applies to both Dispclk and Dppclk + uint8_t NumSocClkLevelsEnabled; + uint8_t Vcn0ClkLevelsEnabled; //Applies to both Vclk0 and Dclk0 + uint8_t Vcn1ClkLevelsEnabled; //Applies to both Vclk1 and Dclk1 + uint8_t VpeClkLevelsEnabled; + uint8_t NumMemPstatesEnabled; + uint8_t NumFclkLevelsEnabled; + uint8_t spare; + + uint32_t MinGfxClk; + uint32_t MaxGfxClk; +} DpmClocks_t_v14_0_1; + typedef struct { uint16_t CoreFrequency[16]; //Target core frequency [MHz] uint16_t CorePower[16]; //CAC calculated core power [mW] @@ -224,7 +255,7 @@ typedef enum { #define TABLE_CUSTOM_DPM 2 // Called by Driver #define TABLE_BIOS_GPIO_CONFIG 3 // Called by BIOS #define TABLE_DPMCLOCKS 4 // Called by Driver and VBIOS -#define TABLE_SPARE0 5 // Unused +#define TABLE_MOMENTARY_PM 5 // Called by Tools #define TABLE_MODERN_STDBY 6 // Called by Tools for Modern Standby Log #define TABLE_SMU_METRICS 7 // Called by Driver and SMF/PMF #define TABLE_COUNT 8 diff --git a/drivers/gpu/drm/amd/pm/swsmu/inc/pmfw_if/smu_v14_0_0_pmfw.h b/drivers/gpu/drm/amd/pm/swsmu/inc/pmfw_if/smu_v14_0_0_pmfw.h index 356e0f57a426..ddb625860083 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/inc/pmfw_if/smu_v14_0_0_pmfw.h +++ b/drivers/gpu/drm/amd/pm/swsmu/inc/pmfw_if/smu_v14_0_0_pmfw.h @@ -42,7 +42,7 @@ #define FEATURE_EDC_BIT 7 #define FEATURE_PLL_POWER_DOWN_BIT 8 #define FEATURE_VDDOFF_BIT 9 -#define FEATURE_VCN_DPM_BIT 10 +#define FEATURE_VCN_DPM_BIT 10 /* this is for both VCN0 and VCN1 */ #define FEATURE_DS_MPM_BIT 11 #define FEATURE_FCLK_DPM_BIT 12 #define FEATURE_SOCCLK_DPM_BIT 13 @@ -56,9 +56,9 @@ #define FEATURE_DS_GFXCLK_BIT 21 #define FEATURE_DS_SOCCLK_BIT 22 #define FEATURE_DS_LCLK_BIT 23 -#define FEATURE_LOW_POWER_DCNCLKS_BIT 24 // for all DISP clks +#define FEATURE_LOW_POWER_DCNCLKS_BIT 24 #define FEATURE_DS_SHUBCLK_BIT 25 -#define FEATURE_SPARE0_BIT 26 //SPARE +#define FEATURE_RESERVED0_BIT 26 #define FEATURE_ZSTATES_BIT 27 #define FEATURE_IOMMUL2_PG_BIT 28 #define FEATURE_DS_FCLK_BIT 29 @@ -66,8 +66,8 @@ #define FEATURE_DS_MP1CLK_BIT 31 #define FEATURE_WHISPER_MODE_BIT 32 #define FEATURE_SMU_LOW_POWER_BIT 33 -#define FEATURE_SMART_L3_RINSER_BIT 34 -#define FEATURE_SPARE1_BIT 35 //SPARE +#define FEATURE_RESERVED1_BIT 34 /* v14_0_0 SMART_L3_RINSER; v14_0_1 RESERVED1 */ +#define FEATURE_GFX_DEM_BIT 35 /* v14_0_0 SPARE; v14_0_1 GFX_DEM */ #define FEATURE_PSI_BIT 36 #define FEATURE_PROCHOT_BIT 37 #define FEATURE_CPUOFF_BIT 38 @@ -77,11 +77,11 @@ #define FEATURE_PERF_LIMIT_BIT 42 #define FEATURE_CORE_DLDO_BIT 43 #define FEATURE_DVO_BIT 44 -#define FEATURE_DS_VCN_BIT 45 +#define FEATURE_DS_VCN_BIT 45 /* v14_0_1 this is for both VCN0 and VCN1 */ #define FEATURE_CPPC_BIT 46 #define FEATURE_CPPC_PREFERRED_CORES 47 #define FEATURE_DF_CSTATES_BIT 48 -#define FEATURE_SPARE2_BIT 49 //SPARE +#define FEATURE_FAST_PSTATE_CLDO_BIT 49 /* v14_0_0 SPARE */ #define FEATURE_ATHUB_PG_BIT 50 #define FEATURE_VDDOFF_ECO_BIT 51 #define FEATURE_ZSTATES_ECO_BIT 52 @@ -93,8 +93,8 @@ #define FEATURE_DS_IPUCLK_BIT 58 #define FEATURE_DS_VPECLK_BIT 59 #define FEATURE_VPE_DPM_BIT 60 -#define FEATURE_SPARE_61 61 -#define FEATURE_FP_DIDT 62 +#define FEATURE_SMART_L3_RINSER_BIT 61 /* v14_0_0 SPARE*/ +#define FEATURE_PCC_BIT 62 /* v14_0_0 FP_DIDT v14_0_1 PCC_BIT */ #define NUM_FEATURES 63 // Firmware Header/Footer @@ -151,6 +151,43 @@ typedef struct { // MP1_EXT_SCRATCH7 = RTOS Current Job } FwStatus_t; +typedef struct { + // MP1_EXT_SCRATCH0 + uint32_t DpmHandlerID : 8; + uint32_t ActivityMonitorID : 8; + uint32_t DpmTimerID : 8; + uint32_t DpmHubID : 4; + uint32_t DpmHubTask : 4; + // MP1_EXT_SCRATCH1 + uint32_t CclkSyncStatus : 8; + uint32_t ZstateStatus : 4; + uint32_t Cpu1VddOff : 4; + uint32_t DstateFun : 4; + uint32_t DstateDev : 4; + uint32_t GfxOffStatus : 2; + uint32_t Cpu0Off : 2; + uint32_t Cpu1Off : 2; + uint32_t Cpu0VddOff : 2; + // MP1_EXT_SCRATCH2 + uint32_t P2JobHandler :32; + // MP1_EXT_SCRATCH3 + uint32_t PostCode :32; + // MP1_EXT_SCRATCH4 + uint32_t MsgPortBusy :15; + uint32_t RsmuPmiP1Pending : 1; + uint32_t RsmuPmiP2PendingCnt : 8; + uint32_t DfCstateExitPending : 1; + uint32_t Pc6EntryPending : 1; + uint32_t Pc6ExitPending : 1; + uint32_t WarmResetPending : 1; + uint32_t Mp0ClkPending : 1; + uint32_t InWhisperMode : 1; + uint32_t spare2 : 2; + // MP1_EXT_SCRATCH5 + uint32_t IdleMask :32; + // MP1_EXT_SCRATCH6 = RTOS threads' status + // MP1_EXT_SCRATCH7 = RTOS Current Job +} FwStatus_t_v14_0_1; #pragma pack(pop) diff --git a/drivers/gpu/drm/amd/pm/swsmu/inc/pmfw_if/smu_v14_0_0_ppsmc.h b/drivers/gpu/drm/amd/pm/swsmu/inc/pmfw_if/smu_v14_0_0_ppsmc.h index ca7ce4251482..c4dc5881d8df 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/inc/pmfw_if/smu_v14_0_0_ppsmc.h +++ b/drivers/gpu/drm/amd/pm/swsmu/inc/pmfw_if/smu_v14_0_0_ppsmc.h @@ -72,23 +72,19 @@ #define PPSMC_MSG_SetHardMinSocclkByFreq 0x13 ///< Set hard min for SOC CLK #define PPSMC_MSG_SetSoftMinFclk 0x14 ///< Set hard min for FCLK #define PPSMC_MSG_SetSoftMinVcn0 0x15 ///< Set soft min for VCN0 clocks (VCLK0 and DCLK0) - #define PPSMC_MSG_EnableGfxImu 0x16 ///< Enable GFX IMU - -#define PPSMC_MSG_spare_0x17 0x17 -#define PPSMC_MSG_spare_0x18 0x18 +#define PPSMC_MSG_spare_0x17 0x17 ///< Get GFX clock frequency +#define PPSMC_MSG_spare_0x18 0x18 ///< Get FCLK frequency #define PPSMC_MSG_AllowGfxOff 0x19 ///< Inform PMFW of allowing GFXOFF entry #define PPSMC_MSG_DisallowGfxOff 0x1A ///< Inform PMFW of disallowing GFXOFF entry #define PPSMC_MSG_SetSoftMaxGfxClk 0x1B ///< Set soft max for GFX CLK #define PPSMC_MSG_SetHardMinGfxClk 0x1C ///< Set hard min for GFX CLK - #define PPSMC_MSG_SetSoftMaxSocclkByFreq 0x1D ///< Set soft max for SOC CLK #define PPSMC_MSG_SetSoftMaxFclkByFreq 0x1E ///< Set soft max for FCLK #define PPSMC_MSG_SetSoftMaxVcn0 0x1F ///< Set soft max for VCN0 clocks (VCLK0 and DCLK0) -#define PPSMC_MSG_spare_0x20 0x20 +#define PPSMC_MSG_spare_0x20 0x20 ///< Set power limit percentage #define PPSMC_MSG_PowerDownJpeg0 0x21 ///< Power down Jpeg of VCN0 #define PPSMC_MSG_PowerUpJpeg0 0x22 ///< Power up Jpeg of VCN0; VCN0 is power gated by default - #define PPSMC_MSG_SetHardMinFclkByFreq 0x23 ///< Set hard min for FCLK #define PPSMC_MSG_SetSoftMinSocclkByFreq 0x24 ///< Set soft min for SOC CLK #define PPSMC_MSG_AllowZstates 0x25 ///< Inform PMFM of allowing Zstate entry, i.e. no Miracast activity @@ -99,8 +95,8 @@ #define PPSMC_MSG_PowerUpIspByTile 0x2A ///< This message is used to power up ISP tiles and enable the ISP DPM #define PPSMC_MSG_SetHardMinIspiclkByFreq 0x2B ///< Set HardMin by frequency for ISPICLK #define PPSMC_MSG_SetHardMinIspxclkByFreq 0x2C ///< Set HardMin by frequency for ISPXCLK -#define PPSMC_MSG_PowerDownUmsch 0x2D ///< Power down VCN.UMSCH (aka VSCH) scheduler -#define PPSMC_MSG_PowerUpUmsch 0x2E ///< Power up VCN.UMSCH (aka VSCH) scheduler +#define PPSMC_MSG_PowerDownUmsch 0x2D ///< Power down VCN0.UMSCH (aka VSCH) scheduler +#define PPSMC_MSG_PowerUpUmsch 0x2E ///< Power up VCN0.UMSCH (aka VSCH) scheduler #define PPSMC_Message_IspStutterOn_MmhubPgDis 0x2F ///< ISP StutterOn mmHub PgDis #define PPSMC_Message_IspStutterOff_MmhubPgEn 0x30 ///< ISP StufferOff mmHub PgEn #define PPSMC_MSG_PowerUpVpe 0x31 ///< Power up VPE @@ -110,7 +106,9 @@ #define PPSMC_MSG_DisableLSdma 0x35 ///< Disable LSDMA #define PPSMC_MSG_SetSoftMaxVpe 0x36 ///< #define PPSMC_MSG_SetSoftMinVpe 0x37 ///< -#define PPSMC_Message_Count 0x38 ///< Total number of PPSMC messages +#define PPSMC_MSG_AllocMALLCache 0x38 ///< Allocating MALL Cache +#define PPSMC_MSG_ReleaseMALLCache 0x39 ///< Releasing MALL Cache +#define PPSMC_Message_Count 0x3A ///< Total number of PPSMC messages /** @}*/ /** diff --git a/drivers/gpu/drm/amd/pm/swsmu/inc/smu_v14_0.h b/drivers/gpu/drm/amd/pm/swsmu/inc/smu_v14_0.h index 3f7463c1c1a9..4af1985ae446 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/inc/smu_v14_0.h +++ b/drivers/gpu/drm/amd/pm/swsmu/inc/smu_v14_0.h @@ -27,6 +27,7 @@ #define SMU14_DRIVER_IF_VERSION_INV 0xFFFFFFFF #define SMU14_DRIVER_IF_VERSION_SMU_V14_0_0 0x7 +#define SMU14_DRIVER_IF_VERSION_SMU_V14_0_1 0x6 #define SMU14_DRIVER_IF_VERSION_SMU_V14_0_2 0x1 #define FEATURE_MASK(feature) (1ULL << feature) diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu14/smu_v14_0.c b/drivers/gpu/drm/amd/pm/swsmu/smu14/smu_v14_0.c index 9e39f99154f9..07a65e005785 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu14/smu_v14_0.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu14/smu_v14_0.c @@ -234,7 +234,7 @@ int smu_v14_0_check_fw_version(struct smu_context *smu) smu->smc_driver_if_version = SMU14_DRIVER_IF_VERSION_SMU_V14_0_0; break; case IP_VERSION(14, 0, 1): - smu->smc_driver_if_version = SMU14_DRIVER_IF_VERSION_SMU_V14_0_0; + smu->smc_driver_if_version = SMU14_DRIVER_IF_VERSION_SMU_V14_0_1; break; default: diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu14/smu_v14_0_0_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu14/smu_v14_0_0_ppt.c index d6de6d97286c..63399c00cc28 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu14/smu_v14_0_0_ppt.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu14/smu_v14_0_0_ppt.c @@ -161,7 +161,7 @@ static int smu_v14_0_0_init_smc_tables(struct smu_context *smu) SMU_TABLE_INIT(tables, SMU_TABLE_WATERMARKS, sizeof(Watermarks_t), PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM); - SMU_TABLE_INIT(tables, SMU_TABLE_DPMCLOCKS, sizeof(DpmClocks_t), + SMU_TABLE_INIT(tables, SMU_TABLE_DPMCLOCKS, max(sizeof(DpmClocks_t), sizeof(DpmClocks_t_v14_0_1)), PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM); SMU_TABLE_INIT(tables, SMU_TABLE_SMU_METRICS, sizeof(SmuMetrics_t), PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM); @@ -171,7 +171,7 @@ static int smu_v14_0_0_init_smc_tables(struct smu_context *smu) goto err0_out; smu_table->metrics_time = 0; - smu_table->clocks_table = kzalloc(sizeof(DpmClocks_t), GFP_KERNEL); + smu_table->clocks_table = kzalloc(max(sizeof(DpmClocks_t), sizeof(DpmClocks_t_v14_0_1)), GFP_KERNEL); if (!smu_table->clocks_table) goto err1_out; @@ -593,6 +593,60 @@ static int smu_v14_0_0_mode2_reset(struct smu_context *smu) return ret; } +static int smu_v14_0_1_get_dpm_freq_by_index(struct smu_context *smu, + enum smu_clk_type clk_type, + uint32_t dpm_level, + uint32_t *freq) +{ + DpmClocks_t_v14_0_1 *clk_table = smu->smu_table.clocks_table; + + if (!clk_table || clk_type >= SMU_CLK_COUNT) + return -EINVAL; + + switch (clk_type) { + case SMU_SOCCLK: + if (dpm_level >= clk_table->NumSocClkLevelsEnabled) + return -EINVAL; + *freq = clk_table->SocClocks[dpm_level]; + break; + case SMU_VCLK: + if (dpm_level >= clk_table->Vcn0ClkLevelsEnabled) + return -EINVAL; + *freq = clk_table->VClocks0[dpm_level]; + break; + case SMU_DCLK: + if (dpm_level >= clk_table->Vcn0ClkLevelsEnabled) + return -EINVAL; + *freq = clk_table->DClocks0[dpm_level]; + break; + case SMU_VCLK1: + if (dpm_level >= clk_table->Vcn1ClkLevelsEnabled) + return -EINVAL; + *freq = clk_table->VClocks1[dpm_level]; + break; + case SMU_DCLK1: + if (dpm_level >= clk_table->Vcn1ClkLevelsEnabled) + return -EINVAL; + *freq = clk_table->DClocks1[dpm_level]; + break; + case SMU_UCLK: + case SMU_MCLK: + if (dpm_level >= clk_table->NumMemPstatesEnabled) + return -EINVAL; + *freq = clk_table->MemPstateTable[dpm_level].MemClk; + break; + case SMU_FCLK: + if (dpm_level >= clk_table->NumFclkLevelsEnabled) + return -EINVAL; + *freq = clk_table->FclkClocks_Freq[dpm_level]; + break; + default: + return -EINVAL; + } + + return 0; +} + static int smu_v14_0_0_get_dpm_freq_by_index(struct smu_context *smu, enum smu_clk_type clk_type, uint32_t dpm_level, @@ -637,6 +691,19 @@ static int smu_v14_0_0_get_dpm_freq_by_index(struct smu_context *smu, return 0; } +static int smu_v14_0_common_get_dpm_freq_by_index(struct smu_context *smu, + enum smu_clk_type clk_type, + uint32_t dpm_level, + uint32_t *freq) +{ + if (amdgpu_ip_version(smu->adev, MP1_HWIP, 0) == IP_VERSION(14, 0, 0)) + smu_v14_0_0_get_dpm_freq_by_index(smu, clk_type, dpm_level, freq); + else if (amdgpu_ip_version(smu->adev, MP1_HWIP, 0) == IP_VERSION(14, 0, 1)) + smu_v14_0_1_get_dpm_freq_by_index(smu, clk_type, dpm_level, freq); + + return 0; +} + static bool smu_v14_0_0_clk_dpm_is_enabled(struct smu_context *smu, enum smu_clk_type clk_type) { @@ -657,6 +724,8 @@ static bool smu_v14_0_0_clk_dpm_is_enabled(struct smu_context *smu, break; case SMU_VCLK: case SMU_DCLK: + case SMU_VCLK1: + case SMU_DCLK1: feature_id = SMU_FEATURE_VCN_DPM_BIT; break; default: @@ -666,6 +735,126 @@ static bool smu_v14_0_0_clk_dpm_is_enabled(struct smu_context *smu, return smu_cmn_feature_is_enabled(smu, feature_id); } +static int smu_v14_0_1_get_dpm_ultimate_freq(struct smu_context *smu, + enum smu_clk_type clk_type, + uint32_t *min, + uint32_t *max) +{ + DpmClocks_t_v14_0_1 *clk_table = smu->smu_table.clocks_table; + uint32_t clock_limit; + uint32_t max_dpm_level, min_dpm_level; + int ret = 0; + + if (!smu_v14_0_0_clk_dpm_is_enabled(smu, clk_type)) { + switch (clk_type) { + case SMU_MCLK: + case SMU_UCLK: + clock_limit = smu->smu_table.boot_values.uclk; + break; + case SMU_FCLK: + clock_limit = smu->smu_table.boot_values.fclk; + break; + case SMU_GFXCLK: + case SMU_SCLK: + clock_limit = smu->smu_table.boot_values.gfxclk; + break; + case SMU_SOCCLK: + clock_limit = smu->smu_table.boot_values.socclk; + break; + case SMU_VCLK: + case SMU_VCLK1: + clock_limit = smu->smu_table.boot_values.vclk; + break; + case SMU_DCLK: + case SMU_DCLK1: + clock_limit = smu->smu_table.boot_values.dclk; + break; + default: + clock_limit = 0; + break; + } + + /* clock in Mhz unit */ + if (min) + *min = clock_limit / 100; + if (max) + *max = clock_limit / 100; + + return 0; + } + + if (max) { + switch (clk_type) { + case SMU_GFXCLK: + case SMU_SCLK: + *max = clk_table->MaxGfxClk; + break; + case SMU_MCLK: + case SMU_UCLK: + case SMU_FCLK: + max_dpm_level = 0; + break; + case SMU_SOCCLK: + max_dpm_level = clk_table->NumSocClkLevelsEnabled - 1; + break; + case SMU_VCLK: + case SMU_DCLK: + max_dpm_level = clk_table->Vcn0ClkLevelsEnabled - 1; + break; + case SMU_VCLK1: + case SMU_DCLK1: + max_dpm_level = clk_table->Vcn1ClkLevelsEnabled - 1; + break; + default: + ret = -EINVAL; + goto failed; + } + + if (clk_type != SMU_GFXCLK && clk_type != SMU_SCLK) { + ret = smu_v14_0_common_get_dpm_freq_by_index(smu, clk_type, max_dpm_level, max); + if (ret) + goto failed; + } + } + + if (min) { + switch (clk_type) { + case SMU_GFXCLK: + case SMU_SCLK: + *min = clk_table->MinGfxClk; + break; + case SMU_MCLK: + case SMU_UCLK: + min_dpm_level = clk_table->NumMemPstatesEnabled - 1; + break; + case SMU_FCLK: + min_dpm_level = clk_table->NumFclkLevelsEnabled - 1; + break; + case SMU_SOCCLK: + min_dpm_level = 0; + break; + case SMU_VCLK: + case SMU_DCLK: + case SMU_VCLK1: + case SMU_DCLK1: + min_dpm_level = 0; + break; + default: + ret = -EINVAL; + goto failed; + } + + if (clk_type != SMU_GFXCLK && clk_type != SMU_SCLK) { + ret = smu_v14_0_common_get_dpm_freq_by_index(smu, clk_type, min_dpm_level, min); + if (ret) + goto failed; + } + } + +failed: + return ret; +} + static int smu_v14_0_0_get_dpm_ultimate_freq(struct smu_context *smu, enum smu_clk_type clk_type, uint32_t *min, @@ -736,7 +925,7 @@ static int smu_v14_0_0_get_dpm_ultimate_freq(struct smu_context *smu, } if (clk_type != SMU_GFXCLK && clk_type != SMU_SCLK) { - ret = smu_v14_0_0_get_dpm_freq_by_index(smu, clk_type, max_dpm_level, max); + ret = smu_v14_0_common_get_dpm_freq_by_index(smu, clk_type, max_dpm_level, max); if (ret) goto failed; } @@ -768,7 +957,7 @@ static int smu_v14_0_0_get_dpm_ultimate_freq(struct smu_context *smu, } if (clk_type != SMU_GFXCLK && clk_type != SMU_SCLK) { - ret = smu_v14_0_0_get_dpm_freq_by_index(smu, clk_type, min_dpm_level, min); + ret = smu_v14_0_common_get_dpm_freq_by_index(smu, clk_type, min_dpm_level, min); if (ret) goto failed; } @@ -778,6 +967,19 @@ failed: return ret; } +static int smu_v14_0_common_get_dpm_ultimate_freq(struct smu_context *smu, + enum smu_clk_type clk_type, + uint32_t *min, + uint32_t *max) +{ + if (amdgpu_ip_version(smu->adev, MP1_HWIP, 0) == IP_VERSION(14, 0, 0)) + smu_v14_0_0_get_dpm_ultimate_freq(smu, clk_type, min, max); + else if (amdgpu_ip_version(smu->adev, MP1_HWIP, 0) == IP_VERSION(14, 0, 1)) + smu_v14_0_1_get_dpm_ultimate_freq(smu, clk_type, min, max); + + return 0; +} + static int smu_v14_0_0_get_current_clk_freq(struct smu_context *smu, enum smu_clk_type clk_type, uint32_t *value) @@ -811,6 +1013,37 @@ static int smu_v14_0_0_get_current_clk_freq(struct smu_context *smu, return smu_v14_0_0_get_smu_metrics_data(smu, member_type, value); } +static int smu_v14_0_1_get_dpm_level_count(struct smu_context *smu, + enum smu_clk_type clk_type, + uint32_t *count) +{ + DpmClocks_t_v14_0_1 *clk_table = smu->smu_table.clocks_table; + + switch (clk_type) { + case SMU_SOCCLK: + *count = clk_table->NumSocClkLevelsEnabled; + break; + case SMU_VCLK: + case SMU_DCLK: + *count = clk_table->Vcn0ClkLevelsEnabled; + break; + case SMU_VCLK1: + case SMU_DCLK1: + *count = clk_table->Vcn1ClkLevelsEnabled; + break; + case SMU_MCLK: + *count = clk_table->NumMemPstatesEnabled; + break; + case SMU_FCLK: + *count = clk_table->NumFclkLevelsEnabled; + break; + default: + break; + } + + return 0; +} + static int smu_v14_0_0_get_dpm_level_count(struct smu_context *smu, enum smu_clk_type clk_type, uint32_t *count) @@ -840,6 +1073,18 @@ static int smu_v14_0_0_get_dpm_level_count(struct smu_context *smu, return 0; } +static int smu_v14_0_common_get_dpm_level_count(struct smu_context *smu, + enum smu_clk_type clk_type, + uint32_t *count) +{ + if (amdgpu_ip_version(smu->adev, MP1_HWIP, 0) == IP_VERSION(14, 0, 0)) + smu_v14_0_0_get_dpm_level_count(smu, clk_type, count); + else if (amdgpu_ip_version(smu->adev, MP1_HWIP, 0) == IP_VERSION(14, 0, 1)) + smu_v14_0_1_get_dpm_level_count(smu, clk_type, count); + + return 0; +} + static int smu_v14_0_0_print_clk_levels(struct smu_context *smu, enum smu_clk_type clk_type, char *buf) { @@ -866,18 +1111,20 @@ static int smu_v14_0_0_print_clk_levels(struct smu_context *smu, case SMU_SOCCLK: case SMU_VCLK: case SMU_DCLK: + case SMU_VCLK1: + case SMU_DCLK1: case SMU_MCLK: case SMU_FCLK: ret = smu_v14_0_0_get_current_clk_freq(smu, clk_type, &cur_value); if (ret) break; - ret = smu_v14_0_0_get_dpm_level_count(smu, clk_type, &count); + ret = smu_v14_0_common_get_dpm_level_count(smu, clk_type, &count); if (ret) break; for (i = 0; i < count; i++) { - ret = smu_v14_0_0_get_dpm_freq_by_index(smu, clk_type, i, &value); + ret = smu_v14_0_common_get_dpm_freq_by_index(smu, clk_type, i, &value); if (ret) break; @@ -940,8 +1187,13 @@ static int smu_v14_0_0_set_soft_freq_limited_range(struct smu_context *smu, break; case SMU_VCLK: case SMU_DCLK: - msg_set_min = SMU_MSG_SetHardMinVcn; - msg_set_max = SMU_MSG_SetSoftMaxVcn; + msg_set_min = SMU_MSG_SetHardMinVcn0; + msg_set_max = SMU_MSG_SetSoftMaxVcn0; + break; + case SMU_VCLK1: + case SMU_DCLK1: + msg_set_min = SMU_MSG_SetHardMinVcn1; + msg_set_max = SMU_MSG_SetSoftMaxVcn1; break; default: return -EINVAL; @@ -971,11 +1223,11 @@ static int smu_v14_0_0_force_clk_levels(struct smu_context *smu, case SMU_FCLK: case SMU_VCLK: case SMU_DCLK: - ret = smu_v14_0_0_get_dpm_freq_by_index(smu, clk_type, soft_min_level, &min_freq); + ret = smu_v14_0_common_get_dpm_freq_by_index(smu, clk_type, soft_min_level, &min_freq); if (ret) break; - ret = smu_v14_0_0_get_dpm_freq_by_index(smu, clk_type, soft_max_level, &max_freq); + ret = smu_v14_0_common_get_dpm_freq_by_index(smu, clk_type, soft_max_level, &max_freq); if (ret) break; @@ -1000,25 +1252,25 @@ static int smu_v14_0_0_set_performance_level(struct smu_context *smu, switch (level) { case AMD_DPM_FORCED_LEVEL_HIGH: - smu_v14_0_0_get_dpm_ultimate_freq(smu, SMU_SCLK, NULL, &sclk_max); - smu_v14_0_0_get_dpm_ultimate_freq(smu, SMU_FCLK, NULL, &fclk_max); - smu_v14_0_0_get_dpm_ultimate_freq(smu, SMU_SOCCLK, NULL, &socclk_max); + smu_v14_0_common_get_dpm_ultimate_freq(smu, SMU_SCLK, NULL, &sclk_max); + smu_v14_0_common_get_dpm_ultimate_freq(smu, SMU_FCLK, NULL, &fclk_max); + smu_v14_0_common_get_dpm_ultimate_freq(smu, SMU_SOCCLK, NULL, &socclk_max); sclk_min = sclk_max; fclk_min = fclk_max; socclk_min = socclk_max; break; case AMD_DPM_FORCED_LEVEL_LOW: - smu_v14_0_0_get_dpm_ultimate_freq(smu, SMU_SCLK, &sclk_min, NULL); - smu_v14_0_0_get_dpm_ultimate_freq(smu, SMU_FCLK, &fclk_min, NULL); - smu_v14_0_0_get_dpm_ultimate_freq(smu, SMU_SOCCLK, &socclk_min, NULL); + smu_v14_0_common_get_dpm_ultimate_freq(smu, SMU_SCLK, &sclk_min, NULL); + smu_v14_0_common_get_dpm_ultimate_freq(smu, SMU_FCLK, &fclk_min, NULL); + smu_v14_0_common_get_dpm_ultimate_freq(smu, SMU_SOCCLK, &socclk_min, NULL); sclk_max = sclk_min; fclk_max = fclk_min; socclk_max = socclk_min; break; case AMD_DPM_FORCED_LEVEL_AUTO: - smu_v14_0_0_get_dpm_ultimate_freq(smu, SMU_SCLK, &sclk_min, &sclk_max); - smu_v14_0_0_get_dpm_ultimate_freq(smu, SMU_FCLK, &fclk_min, &fclk_max); - smu_v14_0_0_get_dpm_ultimate_freq(smu, SMU_SOCCLK, &socclk_min, &socclk_max); + smu_v14_0_common_get_dpm_ultimate_freq(smu, SMU_SCLK, &sclk_min, &sclk_max); + smu_v14_0_common_get_dpm_ultimate_freq(smu, SMU_FCLK, &fclk_min, &fclk_max); + smu_v14_0_common_get_dpm_ultimate_freq(smu, SMU_SOCCLK, &socclk_min, &socclk_max); break; case AMD_DPM_FORCED_LEVEL_PROFILE_STANDARD: case AMD_DPM_FORCED_LEVEL_PROFILE_MIN_SCLK: @@ -1067,6 +1319,18 @@ static int smu_v14_0_0_set_performance_level(struct smu_context *smu, return ret; } +static int smu_v14_0_1_set_fine_grain_gfx_freq_parameters(struct smu_context *smu) +{ + DpmClocks_t_v14_0_1 *clk_table = smu->smu_table.clocks_table; + + smu->gfx_default_hard_min_freq = clk_table->MinGfxClk; + smu->gfx_default_soft_max_freq = clk_table->MaxGfxClk; + smu->gfx_actual_hard_min_freq = 0; + smu->gfx_actual_soft_max_freq = 0; + + return 0; +} + static int smu_v14_0_0_set_fine_grain_gfx_freq_parameters(struct smu_context *smu) { DpmClocks_t *clk_table = smu->smu_table.clocks_table; @@ -1079,6 +1343,16 @@ static int smu_v14_0_0_set_fine_grain_gfx_freq_parameters(struct smu_context *sm return 0; } +static int smu_v14_0_common_set_fine_grain_gfx_freq_parameters(struct smu_context *smu) +{ + if (amdgpu_ip_version(smu->adev, MP1_HWIP, 0) == IP_VERSION(14, 0, 0)) + smu_v14_0_0_set_fine_grain_gfx_freq_parameters(smu); + else if (amdgpu_ip_version(smu->adev, MP1_HWIP, 0) == IP_VERSION(14, 0, 1)) + smu_v14_0_1_set_fine_grain_gfx_freq_parameters(smu); + + return 0; +} + static int smu_v14_0_0_set_vpe_enable(struct smu_context *smu, bool enable) { @@ -1095,6 +1369,25 @@ static int smu_v14_0_0_set_umsch_mm_enable(struct smu_context *smu, 0, NULL); } +static int smu_14_0_1_get_dpm_table(struct smu_context *smu, struct dpm_clocks *clock_table) +{ + DpmClocks_t_v14_0_1 *clk_table = smu->smu_table.clocks_table; + uint8_t idx; + + /* Only the Clock information of SOC and VPE is copied to provide VPE DPM settings for use. */ + for (idx = 0; idx < NUM_SOCCLK_DPM_LEVELS; idx++) { + clock_table->SocClocks[idx].Freq = (idx < clk_table->NumSocClkLevelsEnabled) ? clk_table->SocClocks[idx]:0; + clock_table->SocClocks[idx].Vol = 0; + } + + for (idx = 0; idx < NUM_VPE_DPM_LEVELS; idx++) { + clock_table->VPEClocks[idx].Freq = (idx < clk_table->VpeClkLevelsEnabled) ? clk_table->VPEClocks[idx]:0; + clock_table->VPEClocks[idx].Vol = 0; + } + + return 0; +} + static int smu_14_0_0_get_dpm_table(struct smu_context *smu, struct dpm_clocks *clock_table) { DpmClocks_t *clk_table = smu->smu_table.clocks_table; @@ -1114,6 +1407,16 @@ static int smu_14_0_0_get_dpm_table(struct smu_context *smu, struct dpm_clocks * return 0; } +static int smu_v14_0_common_get_dpm_table(struct smu_context *smu, struct dpm_clocks *clock_table) +{ + if (amdgpu_ip_version(smu->adev, MP1_HWIP, 0) == IP_VERSION(14, 0, 0)) + smu_14_0_0_get_dpm_table(smu, clock_table); + else if (amdgpu_ip_version(smu->adev, MP1_HWIP, 0) == IP_VERSION(14, 0, 1)) + smu_14_0_1_get_dpm_table(smu, clock_table); + + return 0; +} + static const struct pptable_funcs smu_v14_0_0_ppt_funcs = { .check_fw_status = smu_v14_0_check_fw_status, .check_fw_version = smu_v14_0_check_fw_version, @@ -1135,16 +1438,16 @@ static const struct pptable_funcs smu_v14_0_0_ppt_funcs = { .set_driver_table_location = smu_v14_0_set_driver_table_location, .gfx_off_control = smu_v14_0_gfx_off_control, .mode2_reset = smu_v14_0_0_mode2_reset, - .get_dpm_ultimate_freq = smu_v14_0_0_get_dpm_ultimate_freq, + .get_dpm_ultimate_freq = smu_v14_0_common_get_dpm_ultimate_freq, .od_edit_dpm_table = smu_v14_0_od_edit_dpm_table, .print_clk_levels = smu_v14_0_0_print_clk_levels, .force_clk_levels = smu_v14_0_0_force_clk_levels, .set_performance_level = smu_v14_0_0_set_performance_level, - .set_fine_grain_gfx_freq_parameters = smu_v14_0_0_set_fine_grain_gfx_freq_parameters, + .set_fine_grain_gfx_freq_parameters = smu_v14_0_common_set_fine_grain_gfx_freq_parameters, .set_gfx_power_up_by_imu = smu_v14_0_set_gfx_power_up_by_imu, .dpm_set_vpe_enable = smu_v14_0_0_set_vpe_enable, .dpm_set_umsch_mm_enable = smu_v14_0_0_set_umsch_mm_enable, - .get_dpm_clock_table = smu_14_0_0_get_dpm_table, + .get_dpm_clock_table = smu_v14_0_common_get_dpm_table, }; static void smu_v14_0_0_set_smu_mailbox_registers(struct smu_context *smu) -- cgit v1.2.3 From 533eefb9be76c3b23d220ee18edfda8eb56cefff Mon Sep 17 00:00:00 2001 From: Yifan Zhang Date: Tue, 12 Dec 2023 17:17:05 +0800 Subject: drm/amdgpu: add smu 14.0.1 discovery support This patch to add smu 14.0.1 support Reviewed-by: Alex Deucher Signed-off-by: Yifan Zhang Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.c index fdd36fb027ab..ac5bf01fe8d2 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.c @@ -1896,6 +1896,7 @@ static int amdgpu_discovery_set_smu_ip_blocks(struct amdgpu_device *adev) amdgpu_device_ip_block_add(adev, &smu_v13_0_ip_block); break; case IP_VERSION(14, 0, 0): + case IP_VERSION(14, 0, 1): amdgpu_device_ip_block_add(adev, &smu_v14_0_ip_block); break; default: -- cgit v1.2.3 From f886b49feaae30acd599e37d4284836024b0f3ed Mon Sep 17 00:00:00 2001 From: Tao Zhou Date: Thu, 28 Mar 2024 18:22:10 +0800 Subject: drm/amdgpu: implement IRQ_STATE_ENABLE for SDMA v4.4.2 SDMA_CNTL is not set in some cases, driver configures it by itself. v2: simplify code Signed-off-by: Tao Zhou Reviewed-by: Hawking Zhang Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/sdma_v4_4_2.c | 16 +++------------- 1 file changed, 3 insertions(+), 13 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/sdma_v4_4_2.c b/drivers/gpu/drm/amd/amdgpu/sdma_v4_4_2.c index 34237a1b1f2e..82eab49be82b 100644 --- a/drivers/gpu/drm/amd/amdgpu/sdma_v4_4_2.c +++ b/drivers/gpu/drm/amd/amdgpu/sdma_v4_4_2.c @@ -1602,19 +1602,9 @@ static int sdma_v4_4_2_set_ecc_irq_state(struct amdgpu_device *adev, u32 sdma_cntl; sdma_cntl = RREG32_SDMA(type, regSDMA_CNTL); - switch (state) { - case AMDGPU_IRQ_STATE_DISABLE: - sdma_cntl = REG_SET_FIELD(sdma_cntl, SDMA_CNTL, - DRAM_ECC_INT_ENABLE, 0); - WREG32_SDMA(type, regSDMA_CNTL, sdma_cntl); - break; - /* sdma ecc interrupt is enabled by default - * driver doesn't need to do anything to - * enable the interrupt */ - case AMDGPU_IRQ_STATE_ENABLE: - default: - break; - } + sdma_cntl = REG_SET_FIELD(sdma_cntl, SDMA_CNTL, DRAM_ECC_INT_ENABLE, + state == AMDGPU_IRQ_STATE_ENABLE ? 1 : 0); + WREG32_SDMA(type, regSDMA_CNTL, sdma_cntl); return 0; } -- cgit v1.2.3 From ecedd99a9369fb5cde601ae9abd58bca2739f1ae Mon Sep 17 00:00:00 2001 From: Alex Hung Date: Fri, 15 Mar 2024 21:25:25 -0600 Subject: drm/amd/display: Skip on writeback when it's not applicable [WHY] dynamic memory safety error detector (KASAN) catches and generates error messages "BUG: KASAN: slab-out-of-bounds" as writeback connector does not support certain features which are not initialized. [HOW] Skip them when connector type is DRM_MODE_CONNECTOR_WRITEBACK. Link: https://gitlab.freedesktop.org/drm/amd/-/issues/3199 Reviewed-by: Harry Wentland Reviewed-by: Rodrigo Siqueira Acked-by: Roman Li Signed-off-by: Alex Hung Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index 173438fc7537..6cf0d5f276fe 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -3047,6 +3047,10 @@ static int dm_resume(void *handle) /* Do mst topology probing after resuming cached state*/ drm_connector_list_iter_begin(ddev, &iter); drm_for_each_connector_iter(connector, &iter) { + + if (connector->connector_type == DRM_MODE_CONNECTOR_WRITEBACK) + continue; + aconnector = to_amdgpu_dm_connector(connector); if (aconnector->dc_link->type != dc_connection_mst_branch || aconnector->mst_root) @@ -5926,6 +5930,9 @@ get_highest_refresh_rate_mode(struct amdgpu_dm_connector *aconnector, &aconnector->base.probed_modes : &aconnector->base.modes; + if (aconnector->base.connector_type == DRM_MODE_CONNECTOR_WRITEBACK) + return NULL; + if (aconnector->freesync_vid_base.clock != 0) return &aconnector->freesync_vid_base; @@ -8767,10 +8774,10 @@ static void amdgpu_dm_commit_audio(struct drm_device *dev, if (!drm_atomic_crtc_needs_modeset(new_crtc_state)) continue; +notify: if (connector->connector_type == DRM_MODE_CONNECTOR_WRITEBACK) continue; -notify: aconnector = to_amdgpu_dm_connector(connector); mutex_lock(&adev->dm.audio_lock); -- cgit v1.2.3 From 3818708e9c9712e2ba4006bc23502ee7b031bd3f Mon Sep 17 00:00:00 2001 From: Kenneth Feng Date: Thu, 28 Mar 2024 11:00:50 +0800 Subject: drm/amd/pm: fix the high voltage issue after unload fix the high voltage issue after unload on smu 13.0.10 Signed-off-by: Kenneth Feng Reviewed-by: Hawking Zhang Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_device.c | 26 ++++++++++++--------- drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c | 27 ++++++++++++++++++++-- drivers/gpu/drm/amd/pm/swsmu/inc/amdgpu_smu.h | 1 + .../gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_0_ppt.c | 8 ++++++- 4 files changed, 48 insertions(+), 14 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c index aa16d51dd842..7753a2e64d41 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c @@ -4135,18 +4135,22 @@ int amdgpu_device_init(struct amdgpu_device *adev, adev->ip_blocks[i].status.hw = true; } } + } else if (amdgpu_ip_version(adev, MP1_HWIP, 0) == IP_VERSION(13, 0, 10) && + !amdgpu_device_has_display_hardware(adev)) { + r = psp_gpu_reset(adev); } else { - tmp = amdgpu_reset_method; - /* It should do a default reset when loading or reloading the driver, - * regardless of the module parameter reset_method. - */ - amdgpu_reset_method = AMD_RESET_METHOD_NONE; - r = amdgpu_asic_reset(adev); - amdgpu_reset_method = tmp; - if (r) { - dev_err(adev->dev, "asic reset on init failed\n"); - goto failed; - } + tmp = amdgpu_reset_method; + /* It should do a default reset when loading or reloading the driver, + * regardless of the module parameter reset_method. + */ + amdgpu_reset_method = AMD_RESET_METHOD_NONE; + r = amdgpu_asic_reset(adev); + amdgpu_reset_method = tmp; + } + + if (r) { + dev_err(adev->dev, "asic reset on init failed\n"); + goto failed; } } diff --git a/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c b/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c index 246b211b1e85..65333141b1c1 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c +++ b/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c @@ -735,7 +735,7 @@ static int smu_early_init(void *handle) smu->adev = adev; smu->pm_enabled = !!amdgpu_dpm; smu->is_apu = false; - smu->smu_baco.state = SMU_BACO_STATE_EXIT; + smu->smu_baco.state = SMU_BACO_STATE_NONE; smu->smu_baco.platform_support = false; smu->user_dpm_profile.fan_mode = -1; @@ -1966,10 +1966,25 @@ static int smu_smc_hw_cleanup(struct smu_context *smu) return 0; } +static int smu_reset_mp1_state(struct smu_context *smu) +{ + struct amdgpu_device *adev = smu->adev; + int ret = 0; + + if ((!adev->in_runpm) && (!adev->in_suspend) && + (!amdgpu_in_reset(adev)) && amdgpu_ip_version(adev, MP1_HWIP, 0) == + IP_VERSION(13, 0, 10) && + !amdgpu_device_has_display_hardware(adev)) + ret = smu_set_mp1_state(smu, PP_MP1_STATE_UNLOAD); + + return ret; +} + static int smu_hw_fini(void *handle) { struct amdgpu_device *adev = (struct amdgpu_device *)handle; struct smu_context *smu = adev->powerplay.pp_handle; + int ret; if (amdgpu_sriov_vf(adev) && !amdgpu_sriov_is_pp_one_vf(adev)) return 0; @@ -1987,7 +2002,15 @@ static int smu_hw_fini(void *handle) adev->pm.dpm_enabled = false; - return smu_smc_hw_cleanup(smu); + ret = smu_smc_hw_cleanup(smu); + if (ret) + return ret; + + ret = smu_reset_mp1_state(smu); + if (ret) + return ret; + + return 0; } static void smu_late_fini(void *handle) diff --git a/drivers/gpu/drm/amd/pm/swsmu/inc/amdgpu_smu.h b/drivers/gpu/drm/amd/pm/swsmu/inc/amdgpu_smu.h index a870bdd49a4e..1fa81575788c 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/inc/amdgpu_smu.h +++ b/drivers/gpu/drm/amd/pm/swsmu/inc/amdgpu_smu.h @@ -424,6 +424,7 @@ enum smu_reset_mode { enum smu_baco_state { SMU_BACO_STATE_ENTER = 0, SMU_BACO_STATE_EXIT, + SMU_BACO_STATE_NONE, }; struct smu_baco_context { diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_0_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_0_ppt.c index 9c03296f92cd..67117ced7c6a 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_0_ppt.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_0_ppt.c @@ -2751,7 +2751,13 @@ static int smu_v13_0_0_set_mp1_state(struct smu_context *smu, switch (mp1_state) { case PP_MP1_STATE_UNLOAD: - ret = smu_cmn_set_mp1_state(smu, mp1_state); + ret = smu_cmn_send_smc_msg_with_param(smu, + SMU_MSG_PrepareMp1ForUnload, + 0x55, NULL); + + if (!ret && smu->smu_baco.state == SMU_BACO_STATE_EXIT) + ret = smu_v13_0_disable_pmfw_state(smu); + break; default: /* Ignore others */ -- cgit v1.2.3 From f7e232de51bb1b45646e5b7dc4ebcf13510f2630 Mon Sep 17 00:00:00 2001 From: Lijo Lazar Date: Wed, 6 Mar 2024 17:05:07 +0530 Subject: drm/amdgpu: Fix VCN allocation in CPX partition VCN need not be shared in CPX mode always for all GFX 9.4.3 SOC SKUs. In certain configs, VCN instance can be exclusively allocated to a partition even under CPX mode. Signed-off-by: Lijo Lazar Reviewed-by: James Zhu Reviewed-by: Asad Kamal Acked-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/aqua_vanjaram.c | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/aqua_vanjaram.c b/drivers/gpu/drm/amd/amdgpu/aqua_vanjaram.c index d6f808acfb17..fbb43ae7624f 100644 --- a/drivers/gpu/drm/amd/amdgpu/aqua_vanjaram.c +++ b/drivers/gpu/drm/amd/amdgpu/aqua_vanjaram.c @@ -62,6 +62,11 @@ void aqua_vanjaram_doorbell_index_init(struct amdgpu_device *adev) adev->doorbell_index.max_assignment = AMDGPU_DOORBELL_LAYOUT1_MAX_ASSIGNMENT << 1; } +static bool aqua_vanjaram_xcp_vcn_shared(struct amdgpu_device *adev) +{ + return (adev->xcp_mgr->num_xcps > adev->vcn.num_vcn_inst); +} + static void aqua_vanjaram_set_xcp_id(struct amdgpu_device *adev, uint32_t inst_idx, struct amdgpu_ring *ring) { @@ -87,7 +92,7 @@ static void aqua_vanjaram_set_xcp_id(struct amdgpu_device *adev, case AMDGPU_RING_TYPE_VCN_ENC: case AMDGPU_RING_TYPE_VCN_JPEG: ip_blk = AMDGPU_XCP_VCN; - if (adev->xcp_mgr->mode == AMDGPU_CPX_PARTITION_MODE) + if (aqua_vanjaram_xcp_vcn_shared(adev)) inst_mask = 1 << (inst_idx * 2); break; default: @@ -140,10 +145,12 @@ static int aqua_vanjaram_xcp_sched_list_update( aqua_vanjaram_xcp_gpu_sched_update(adev, ring, ring->xcp_id); - /* VCN is shared by two partitions under CPX MODE */ + /* VCN may be shared by two partitions under CPX MODE in certain + * configs. + */ if ((ring->funcs->type == AMDGPU_RING_TYPE_VCN_ENC || - ring->funcs->type == AMDGPU_RING_TYPE_VCN_JPEG) && - adev->xcp_mgr->mode == AMDGPU_CPX_PARTITION_MODE) + ring->funcs->type == AMDGPU_RING_TYPE_VCN_JPEG) && + aqua_vanjaram_xcp_vcn_shared(adev)) aqua_vanjaram_xcp_gpu_sched_update(adev, ring, ring->xcp_id + 1); } -- cgit v1.2.3 From e33997e18d0fddd217a0fce988abbfd015338631 Mon Sep 17 00:00:00 2001 From: ZhenGuo Yin Date: Tue, 2 Apr 2024 11:41:05 +0800 Subject: drm/amdgpu: clear set_q_mode_offs when VM changed MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [Why] set_q_mode_offs don't get cleared after GPU reset, nexting SET_Q_MODE packet to init shadow memory will be skiped, hence there has a page fault. [How] VM flush is needed after GPU reset, clear set_q_mode_offs when emitting VM flush. Fixes: 8bc75586ea01 ("drm/amdgpu: workaround to avoid SET_Q_MODE packets v2") Reviewed-by: Christian König Signed-off-by: ZhenGuo Yin Signed-off-by: Alex Deucher Cc: stable@vger.kernel.org --- drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c index 1770e496c1b7..2c82e2741619 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c @@ -5465,6 +5465,7 @@ static void gfx_v11_0_ring_emit_vm_flush(struct amdgpu_ring *ring, /* Make sure that we can't skip the SET_Q_MODE packets when the VM * changed in any way. */ + ring->set_q_mode_offs = 0; ring->set_q_mode_ptr = NULL; } -- cgit v1.2.3 From d06af584be5a769d124b7302b32a033e9559761d Mon Sep 17 00:00:00 2001 From: Zhigang Luo Date: Mon, 18 Mar 2024 14:13:10 -0400 Subject: amd/amdkfd: sync all devices to wait all processes being evicted If there are more than one device doing reset in parallel, the first device will call kfd_suspend_all_processes() to evict all processes on all devices, this call takes time to finish. other device will start reset and recover without waiting. if the process has not been evicted before doing recover, it will be restored, then caused page fault. Signed-off-by: Zhigang Luo Reviewed-by: Felix Kuehling Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdkfd/kfd_device.c | 17 ++++++----------- 1 file changed, 6 insertions(+), 11 deletions(-) diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_device.c b/drivers/gpu/drm/amd/amdkfd/kfd_device.c index 041ec3de55e7..719d6d365e15 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_device.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_device.c @@ -960,7 +960,6 @@ void kgd2kfd_suspend(struct kfd_dev *kfd, bool run_pm) { struct kfd_node *node; int i; - int count; if (!kfd->init_complete) return; @@ -968,12 +967,10 @@ void kgd2kfd_suspend(struct kfd_dev *kfd, bool run_pm) /* for runtime suspend, skip locking kfd */ if (!run_pm) { mutex_lock(&kfd_processes_mutex); - count = ++kfd_locked; - mutex_unlock(&kfd_processes_mutex); - /* For first KFD device suspend all the KFD processes */ - if (count == 1) + if (++kfd_locked == 1) kfd_suspend_all_processes(); + mutex_unlock(&kfd_processes_mutex); } for (i = 0; i < kfd->num_nodes; i++) { @@ -984,7 +981,7 @@ void kgd2kfd_suspend(struct kfd_dev *kfd, bool run_pm) int kgd2kfd_resume(struct kfd_dev *kfd, bool run_pm) { - int ret, count, i; + int ret, i; if (!kfd->init_complete) return 0; @@ -998,12 +995,10 @@ int kgd2kfd_resume(struct kfd_dev *kfd, bool run_pm) /* for runtime resume, skip unlocking kfd */ if (!run_pm) { mutex_lock(&kfd_processes_mutex); - count = --kfd_locked; - mutex_unlock(&kfd_processes_mutex); - - WARN_ONCE(count < 0, "KFD suspend / resume ref. error"); - if (count == 0) + if (--kfd_locked == 0) ret = kfd_resume_all_processes(); + WARN_ONCE(kfd_locked < 0, "KFD suspend / resume ref. error"); + mutex_unlock(&kfd_processes_mutex); } return ret; -- cgit v1.2.3 From 2cc69a10d83180f3de9f5afe3a98e972b1453d4c Mon Sep 17 00:00:00 2001 From: Alex Hung Date: Sat, 23 Mar 2024 12:02:54 -0600 Subject: drm/amd/display: Return max resolution supported by DWB mode_config's max width x height is 4096x2160 and is higher than DWB's max resolution 3840x2160 which is returned instead. Cc: stable@vger.kernel.org Reviewed-by: Harry Wentland Acked-by: Hamza Mahfooz Signed-off-by: Alex Hung Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_wb.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_wb.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_wb.c index 16e72d623630..08c494a7a21b 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_wb.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_wb.c @@ -76,10 +76,8 @@ static int amdgpu_dm_wb_encoder_atomic_check(struct drm_encoder *encoder, static int amdgpu_dm_wb_connector_get_modes(struct drm_connector *connector) { - struct drm_device *dev = connector->dev; - - return drm_add_modes_noedid(connector, dev->mode_config.max_width, - dev->mode_config.max_height); + /* Maximum resolution supported by DWB */ + return drm_add_modes_noedid(connector, 3840, 2160); } static int amdgpu_dm_wb_prepare_job(struct drm_writeback_connector *wb_connector, -- cgit v1.2.3 From bbca7f414ae9a12ea231cdbafd79c607e3337ea8 Mon Sep 17 00:00:00 2001 From: Tim Huang Date: Wed, 3 Apr 2024 17:28:44 +0800 Subject: drm/amdgpu: fix incorrect number of active RBs for gfx11 The RB bitmap should be global active RB bitmap & active RB bitmap based on active SA. Signed-off-by: Tim Huang Reviewed-by: Yifan Zhang Signed-off-by: Alex Deucher Cc: stable@vger.kernel.org --- drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c index 2c82e2741619..f7325b02a191 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c @@ -1635,7 +1635,7 @@ static void gfx_v11_0_setup_rb(struct amdgpu_device *adev) active_rb_bitmap |= (0x3 << (i * rb_bitmap_width_per_sa)); } - active_rb_bitmap |= global_active_rb_bitmap; + active_rb_bitmap &= global_active_rb_bitmap; adev->gfx.config.backend_enable_mask = active_rb_bitmap; adev->gfx.config.num_rbs = hweight32(active_rb_bitmap); } -- cgit v1.2.3 From 81901d8d0472e9a19d294ae1dea76b950548195d Mon Sep 17 00:00:00 2001 From: Wenjing Liu Date: Fri, 22 Mar 2024 15:02:45 -0400 Subject: drm/amd/display: always reset ODM mode in context when adding first plane [why] In current implemenation ODM mode is only reset when the last plane is removed from dc state. For any dc validate we will always remove all current planes and add new planes. However when switching from no planes to 1 plane, ODM mode is not reset because no planes get removed. This has caused an issue where we kept ODM combine when it should have been remove when a plane is added. The change is to reset ODM mode when adding the first plane. Cc: stable@vger.kernel.org Reviewed-by: Alvin Lee Acked-by: Hamza Mahfooz Signed-off-by: Wenjing Liu Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_state.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_state.c b/drivers/gpu/drm/amd/display/dc/core/dc_state.c index 5cc7f8da209c..61986e5cb491 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_state.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_state.c @@ -436,6 +436,15 @@ bool dc_state_add_plane( goto out; } + if (stream_status->plane_count == 0 && dc->config.enable_windowed_mpo_odm) + /* ODM combine could prevent us from supporting more planes + * we will reset ODM slice count back to 1 when all planes have + * been removed to maximize the amount of planes supported when + * new planes are added. + */ + resource_update_pipes_for_stream_with_slice_count( + state, dc->current_state, dc->res_pool, stream, 1); + otg_master_pipe = resource_get_otg_master_for_stream( &state->res_ctx, stream); if (otg_master_pipe) -- cgit v1.2.3 From 953927587f37b731abdeabe46ad44a3b3ec67a52 Mon Sep 17 00:00:00 2001 From: Dillon Varone Date: Thu, 21 Mar 2024 13:49:43 -0400 Subject: drm/amd/display: Do not recursively call manual trigger programming [WHY&HOW] We should not be recursively calling the manual trigger programming function when FAMS is not in use. Cc: stable@vger.kernel.org Reviewed-by: Alvin Lee Acked-by: Hamza Mahfooz Signed-off-by: Dillon Varone Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/optc/dcn32/dcn32_optc.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/optc/dcn32/dcn32_optc.c b/drivers/gpu/drm/amd/display/dc/optc/dcn32/dcn32_optc.c index f07a4c7e48bc..52eab8fccb7f 100644 --- a/drivers/gpu/drm/amd/display/dc/optc/dcn32/dcn32_optc.c +++ b/drivers/gpu/drm/amd/display/dc/optc/dcn32/dcn32_optc.c @@ -267,9 +267,6 @@ static void optc32_setup_manual_trigger(struct timing_generator *optc) OTG_V_TOTAL_MAX_SEL, 1, OTG_FORCE_LOCK_ON_EVENT, 0, OTG_SET_V_TOTAL_MIN_MASK, (1 << 1)); /* TRIGA */ - - // Setup manual flow control for EOF via TRIG_A - optc->funcs->setup_manual_trigger(optc); } } -- cgit v1.2.3 From cf79814cb0bf5749b9f0db53ca231aa540c02768 Mon Sep 17 00:00:00 2001 From: Fudongwang Date: Tue, 26 Mar 2024 16:03:16 +0800 Subject: drm/amd/display: fix disable otg wa logic in DCN316 [Why] Wrong logic cause screen corruption. [How] Port logic from DCN35/314. Cc: stable@vger.kernel.org Reviewed-by: Nicholas Kazlauskas Acked-by: Hamza Mahfooz Signed-off-by: Fudongwang Signed-off-by: Alex Deucher --- .../amd/display/dc/clk_mgr/dcn316/dcn316_clk_mgr.c | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn316/dcn316_clk_mgr.c b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn316/dcn316_clk_mgr.c index 12f3e8aa46d8..6ad4f4efec5d 100644 --- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn316/dcn316_clk_mgr.c +++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn316/dcn316_clk_mgr.c @@ -99,20 +99,25 @@ static int dcn316_get_active_display_cnt_wa( return display_count; } -static void dcn316_disable_otg_wa(struct clk_mgr *clk_mgr_base, struct dc_state *context, bool disable) +static void dcn316_disable_otg_wa(struct clk_mgr *clk_mgr_base, struct dc_state *context, + bool safe_to_lower, bool disable) { struct dc *dc = clk_mgr_base->ctx->dc; int i; for (i = 0; i < dc->res_pool->pipe_count; ++i) { - struct pipe_ctx *pipe = &dc->current_state->res_ctx.pipe_ctx[i]; + struct pipe_ctx *pipe = safe_to_lower + ? &context->res_ctx.pipe_ctx[i] + : &dc->current_state->res_ctx.pipe_ctx[i]; if (pipe->top_pipe || pipe->prev_odm_pipe) continue; - if (pipe->stream && (pipe->stream->dpms_off || pipe->plane_state == NULL || - dc_is_virtual_signal(pipe->stream->signal))) { + if (pipe->stream && (pipe->stream->dpms_off || dc_is_virtual_signal(pipe->stream->signal) || + !pipe->stream->link_enc)) { if (disable) { - pipe->stream_res.tg->funcs->immediate_disable_crtc(pipe->stream_res.tg); + if (pipe->stream_res.tg && pipe->stream_res.tg->funcs->immediate_disable_crtc) + pipe->stream_res.tg->funcs->immediate_disable_crtc(pipe->stream_res.tg); + reset_sync_context_for_pipe(dc, context, i); } else pipe->stream_res.tg->funcs->enable_crtc(pipe->stream_res.tg); @@ -207,11 +212,11 @@ static void dcn316_update_clocks(struct clk_mgr *clk_mgr_base, } if (should_set_clock(safe_to_lower, new_clocks->dispclk_khz, clk_mgr_base->clks.dispclk_khz)) { - dcn316_disable_otg_wa(clk_mgr_base, context, true); + dcn316_disable_otg_wa(clk_mgr_base, context, safe_to_lower, true); clk_mgr_base->clks.dispclk_khz = new_clocks->dispclk_khz; dcn316_smu_set_dispclk(clk_mgr, clk_mgr_base->clks.dispclk_khz); - dcn316_disable_otg_wa(clk_mgr_base, context, false); + dcn316_disable_otg_wa(clk_mgr_base, context, safe_to_lower, false); update_dispclk = true; } -- cgit v1.2.3 From 9e61ef8d219877202d4ee51d0d2ad9072c99a262 Mon Sep 17 00:00:00 2001 From: Harry Wentland Date: Tue, 12 Mar 2024 11:55:52 -0400 Subject: drm/amd/display: Program VSC SDP colorimetry for all DP sinks >= 1.4 In order for display colorimetry to work correctly on DP displays we need to send the VSC SDP packet. We should only do so for panels with DPCD revision greater or equal to 1.4 as older receivers might have problems with it. Cc: stable@vger.kernel.org Cc: Joshua Ashton Cc: Xaver Hugl Cc: Melissa Wen Cc: Agustin Gutierrez Reviewed-by: Agustin Gutierrez Acked-by: Hamza Mahfooz Signed-off-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index 6cf0d5f276fe..d112ce6c812c 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -6318,7 +6318,9 @@ create_stream_for_sink(struct drm_connector *connector, if (stream->signal == SIGNAL_TYPE_HDMI_TYPE_A) mod_build_hf_vsif_infopacket(stream, &stream->vsp_infopacket); - if (stream->link->psr_settings.psr_feature_enabled || stream->link->replay_settings.replay_feature_enabled) { + if (stream->signal == SIGNAL_TYPE_DISPLAY_PORT || + stream->signal == SIGNAL_TYPE_DISPLAY_PORT_MST || + stream->signal == SIGNAL_TYPE_EDP) { // // should decide stream support vsc sdp colorimetry capability // before building vsc info packet @@ -6328,7 +6330,8 @@ create_stream_for_sink(struct drm_connector *connector, stream->use_vsc_sdp_for_colorimetry = aconnector->dc_sink->is_vsc_sdp_colorimetry_supported; } else { - if (stream->link->dpcd_caps.dprx_feature.bits.VSC_SDP_COLORIMETRY_SUPPORTED) + if (stream->link->dpcd_caps.dpcd_rev.raw >= 0x14 && + stream->link->dpcd_caps.dprx_feature.bits.VSC_SDP_COLORIMETRY_SUPPORTED) stream->use_vsc_sdp_for_colorimetry = true; } if (stream->out_transfer_func->tf == TRANSFER_FUNCTION_GAMMA22) -- cgit v1.2.3 From c3e2a5f2da904a18661335e8be2b961738574998 Mon Sep 17 00:00:00 2001 From: Harry Wentland Date: Thu, 21 Mar 2024 11:13:38 -0400 Subject: drm/amd/display: Set VSC SDP Colorimetry same way for MST and SST The previous check for the is_vsc_sdp_colorimetry_supported flag for MST sink signals did nothing. Simplify the code and use the same check for MST and SST. Cc: stable@vger.kernel.org Reviewed-by: Agustin Gutierrez Acked-by: Hamza Mahfooz Signed-off-by: Harry Wentland Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index d112ce6c812c..6d2f60c61dec 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -6325,15 +6325,9 @@ create_stream_for_sink(struct drm_connector *connector, // should decide stream support vsc sdp colorimetry capability // before building vsc info packet // - stream->use_vsc_sdp_for_colorimetry = false; - if (aconnector->dc_sink->sink_signal == SIGNAL_TYPE_DISPLAY_PORT_MST) { - stream->use_vsc_sdp_for_colorimetry = - aconnector->dc_sink->is_vsc_sdp_colorimetry_supported; - } else { - if (stream->link->dpcd_caps.dpcd_rev.raw >= 0x14 && - stream->link->dpcd_caps.dprx_feature.bits.VSC_SDP_COLORIMETRY_SUPPORTED) - stream->use_vsc_sdp_for_colorimetry = true; - } + stream->use_vsc_sdp_for_colorimetry = stream->link->dpcd_caps.dpcd_rev.raw >= 0x14 && + stream->link->dpcd_caps.dprx_feature.bits.VSC_SDP_COLORIMETRY_SUPPORTED; + if (stream->out_transfer_func->tf == TRANSFER_FUNCTION_GAMMA22) tf = TRANSFER_FUNC_GAMMA_22; mod_build_vsc_infopacket(stream, &stream->vsc_infopacket, stream->output_color_space, tf); -- cgit v1.2.3 From e047dd448d2bc12b8c30d7e3e6e98cea1fc28a17 Mon Sep 17 00:00:00 2001 From: Zhongwei Date: Wed, 27 Mar 2024 13:49:40 +0800 Subject: drm/amd/display: Adjust dprefclk by down spread percentage. [Why] OLED panels show no display for large vtotal timings. [How] Check if ss is enabled and read from lut for spread spectrum percentage. Adjust dprefclk as required. DP_DTO adjustment is for edp only. Cc: stable@vger.kernel.org Reviewed-by: Nicholas Kazlauskas Acked-by: Hamza Mahfooz Signed-off-by: Zhongwei Signed-off-by: Alex Deucher --- .../amd/display/dc/clk_mgr/dcn35/dcn35_clk_mgr.c | 50 ++++++++++++++++++++++ .../gpu/drm/amd/display/dc/dce/dce_clock_source.c | 8 ++-- 2 files changed, 54 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn35/dcn35_clk_mgr.c b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn35/dcn35_clk_mgr.c index 101fe96287cb..d9c5692c86c2 100644 --- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn35/dcn35_clk_mgr.c +++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn35/dcn35_clk_mgr.c @@ -73,6 +73,12 @@ #define CLK1_CLK2_BYPASS_CNTL__CLK2_BYPASS_SEL_MASK 0x00000007L #define CLK1_CLK2_BYPASS_CNTL__CLK2_BYPASS_DIV_MASK 0x000F0000L +#define regCLK5_0_CLK5_spll_field_8 0x464b +#define regCLK5_0_CLK5_spll_field_8_BASE_IDX 0 + +#define CLK5_0_CLK5_spll_field_8__spll_ssc_en__SHIFT 0xd +#define CLK5_0_CLK5_spll_field_8__spll_ssc_en_MASK 0x00002000L + #define SMU_VER_THRESHOLD 0x5D4A00 //93.74.0 #define REG(reg_name) \ @@ -411,6 +417,17 @@ static void dcn35_dump_clk_registers(struct clk_state_registers_and_bypass *regs { } +static bool dcn35_is_spll_ssc_enabled(struct clk_mgr *clk_mgr_base) +{ + struct clk_mgr_internal *clk_mgr = TO_CLK_MGR_INTERNAL(clk_mgr_base); + struct dc_context *ctx = clk_mgr->base.ctx; + uint32_t ssc_enable; + + REG_GET(CLK5_0_CLK5_spll_field_8, spll_ssc_en, &ssc_enable); + + return ssc_enable == 1; +} + static void init_clk_states(struct clk_mgr *clk_mgr) { struct clk_mgr_internal *clk_mgr_int = TO_CLK_MGR_INTERNAL(clk_mgr); @@ -428,7 +445,16 @@ static void init_clk_states(struct clk_mgr *clk_mgr) void dcn35_init_clocks(struct clk_mgr *clk_mgr) { + struct clk_mgr_internal *clk_mgr_int = TO_CLK_MGR_INTERNAL(clk_mgr); init_clk_states(clk_mgr); + + // to adjust dp_dto reference clock if ssc is enable otherwise to apply dprefclk + if (dcn35_is_spll_ssc_enabled(clk_mgr)) + clk_mgr->dp_dto_source_clock_in_khz = + dce_adjust_dp_ref_freq_for_ss(clk_mgr_int, clk_mgr->dprefclk_khz); + else + clk_mgr->dp_dto_source_clock_in_khz = clk_mgr->dprefclk_khz; + } static struct clk_bw_params dcn35_bw_params = { .vram_type = Ddr4MemType, @@ -517,6 +543,28 @@ static DpmClocks_t_dcn35 dummy_clocks; static struct dcn35_watermarks dummy_wms = { 0 }; +static struct dcn35_ss_info_table ss_info_table = { + .ss_divider = 1000, + .ss_percentage = {0, 0, 375, 375, 375} +}; + +static void dcn35_read_ss_info_from_lut(struct clk_mgr_internal *clk_mgr) +{ + struct dc_context *ctx = clk_mgr->base.ctx; + uint32_t clock_source; + + REG_GET(CLK1_CLK2_BYPASS_CNTL, CLK2_BYPASS_SEL, &clock_source); + // If it's DFS mode, clock_source is 0. + if (dcn35_is_spll_ssc_enabled(&clk_mgr->base) && (clock_source < ARRAY_SIZE(ss_info_table.ss_percentage))) { + clk_mgr->dprefclk_ss_percentage = ss_info_table.ss_percentage[clock_source]; + + if (clk_mgr->dprefclk_ss_percentage != 0) { + clk_mgr->ss_on_dprefclk = true; + clk_mgr->dprefclk_ss_divider = ss_info_table.ss_divider; + } + } +} + static void dcn35_build_watermark_ranges(struct clk_bw_params *bw_params, struct dcn35_watermarks *table) { int i, num_valid_sets; @@ -1061,6 +1109,8 @@ void dcn35_clk_mgr_construct( dce_clock_read_ss_info(&clk_mgr->base); /*when clk src is from FCH, it could have ss, same clock src as DPREF clk*/ + dcn35_read_ss_info_from_lut(&clk_mgr->base); + clk_mgr->base.base.bw_params = &dcn35_bw_params; if (clk_mgr->base.base.ctx->dc->debug.pstate_enabled) { diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.c b/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.c index 970644b695cd..b5e0289d2fe8 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.c @@ -976,7 +976,10 @@ static bool dcn31_program_pix_clk( struct bp_pixel_clock_parameters bp_pc_params = {0}; enum transmitter_color_depth bp_pc_colour_depth = TRANSMITTER_COLOR_DEPTH_24; - if (clock_source->ctx->dc->clk_mgr->dp_dto_source_clock_in_khz != 0) + // Apply ssed(spread spectrum) dpref clock for edp only. + if (clock_source->ctx->dc->clk_mgr->dp_dto_source_clock_in_khz != 0 + && pix_clk_params->signal_type == SIGNAL_TYPE_EDP + && encoding == DP_8b_10b_ENCODING) dp_dto_ref_khz = clock_source->ctx->dc->clk_mgr->dp_dto_source_clock_in_khz; // For these signal types Driver to program DP_DTO without calling VBIOS Command table if (dc_is_dp_signal(pix_clk_params->signal_type) || dc_is_virtual_signal(pix_clk_params->signal_type)) { @@ -1093,9 +1096,6 @@ static bool get_pixel_clk_frequency_100hz( unsigned int modulo_hz = 0; unsigned int dp_dto_ref_khz = clock_source->ctx->dc->clk_mgr->dprefclk_khz; - if (clock_source->ctx->dc->clk_mgr->dp_dto_source_clock_in_khz != 0) - dp_dto_ref_khz = clock_source->ctx->dc->clk_mgr->dp_dto_source_clock_in_khz; - if (clock_source->id == CLOCK_SOURCE_ID_DP_DTO) { clock_hz = REG_READ(PHASE[inst]); -- cgit v1.2.3 From 6dba20d23e85034901ccb765a7ca71199bcca4df Mon Sep 17 00:00:00 2001 From: Yifan Zhang Date: Sun, 7 Apr 2024 22:01:35 +0800 Subject: drm/amdgpu: differentiate external rev id for gfx 11.5.0 This patch to differentiate external rev id for gfx 11.5.0. Signed-off-by: Yifan Zhang Reviewed-by: Tim Huang Signed-off-by: Alex Deucher Cc: stable@vger.kernel.org --- drivers/gpu/drm/amd/amdgpu/soc21.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/amdgpu/soc21.c b/drivers/gpu/drm/amd/amdgpu/soc21.c index abe319b0f063..43ca63fe85ac 100644 --- a/drivers/gpu/drm/amd/amdgpu/soc21.c +++ b/drivers/gpu/drm/amd/amdgpu/soc21.c @@ -720,7 +720,10 @@ static int soc21_common_early_init(void *handle) AMD_PG_SUPPORT_VCN | AMD_PG_SUPPORT_JPEG | AMD_PG_SUPPORT_GFX_PG; - adev->external_rev_id = adev->rev_id + 0x1; + if (adev->rev_id == 0) + adev->external_rev_id = 0x1; + else + adev->external_rev_id = adev->rev_id + 0x10; break; case IP_VERSION(11, 5, 1): adev->cg_flags = -- cgit v1.2.3 From dec8ced871e17eea46f097542dd074d022be4bd1 Mon Sep 17 00:00:00 2001 From: Namhyung Kim Date: Tue, 5 Mar 2024 22:10:03 -0800 Subject: perf/x86: Fix out of range data On x86 each struct cpu_hw_events maintains a table for counter assignment but it missed to update one for the deleted event in x86_pmu_del(). This can make perf_clear_dirty_counters() reset used counter if it's called before event scheduling or enabling. Then it would return out of range data which doesn't make sense. The following code can reproduce the problem. $ cat repro.c #include #include #include #include #include #include #include #include struct perf_event_attr attr = { .type = PERF_TYPE_HARDWARE, .config = PERF_COUNT_HW_CPU_CYCLES, .disabled = 1, }; void *worker(void *arg) { int cpu = (long)arg; int fd1 = syscall(SYS_perf_event_open, &attr, -1, cpu, -1, 0); int fd2 = syscall(SYS_perf_event_open, &attr, -1, cpu, -1, 0); void *p; do { ioctl(fd1, PERF_EVENT_IOC_ENABLE, 0); p = mmap(NULL, 4096, PROT_READ, MAP_SHARED, fd1, 0); ioctl(fd2, PERF_EVENT_IOC_ENABLE, 0); ioctl(fd2, PERF_EVENT_IOC_DISABLE, 0); munmap(p, 4096); ioctl(fd1, PERF_EVENT_IOC_DISABLE, 0); } while (1); return NULL; } int main(void) { int i; int n = sysconf(_SC_NPROCESSORS_ONLN); pthread_t *th = calloc(n, sizeof(*th)); for (i = 0; i < n; i++) pthread_create(&th[i], NULL, worker, (void *)(long)i); for (i = 0; i < n; i++) pthread_join(th[i], NULL); free(th); return 0; } And you can see the out of range data using perf stat like this. Probably it'd be easier to see on a large machine. $ gcc -o repro repro.c -pthread $ ./repro & $ sudo perf stat -A -I 1000 2>&1 | awk '{ if (length($3) > 15) print }' 1.001028462 CPU6 196,719,295,683,763 cycles # 194290.996 GHz (71.54%) 1.001028462 CPU3 396,077,485,787,730 branch-misses # 15804359784.80% of all branches (71.07%) 1.001028462 CPU17 197,608,350,727,877 branch-misses # 14594186554.56% of all branches (71.22%) 2.020064073 CPU4 198,372,472,612,140 cycles # 194681.113 GHz (70.95%) 2.020064073 CPU6 199,419,277,896,696 cycles # 195720.007 GHz (70.57%) 2.020064073 CPU20 198,147,174,025,639 cycles # 194474.654 GHz (71.03%) 2.020064073 CPU20 198,421,240,580,145 stalled-cycles-frontend # 100.14% frontend cycles idle (70.93%) 3.037443155 CPU4 197,382,689,923,416 cycles # 194043.065 GHz (71.30%) 3.037443155 CPU20 196,324,797,879,414 cycles # 193003.773 GHz (71.69%) 3.037443155 CPU5 197,679,956,608,205 stalled-cycles-backend # 1315606428.66% backend cycles idle (71.19%) 3.037443155 CPU5 198,571,860,474,851 instructions # 13215422.58 insn per cycle It should move the contents in the cpuc->assign as well. Fixes: 5471eea5d3bf ("perf/x86: Reset the dirty counter to prevent the leak for an RDPMC task") Signed-off-by: Namhyung Kim Signed-off-by: Ingo Molnar Reviewed-by: Kan Liang Cc: stable@vger.kernel.org Link: https://lore.kernel.org/r/20240306061003.1894224-1-namhyung@kernel.org --- arch/x86/events/core.c | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/x86/events/core.c b/arch/x86/events/core.c index 09050641ce5d..5b0dd07b1ef1 100644 --- a/arch/x86/events/core.c +++ b/arch/x86/events/core.c @@ -1644,6 +1644,7 @@ static void x86_pmu_del(struct perf_event *event, int flags) while (++i < cpuc->n_events) { cpuc->event_list[i-1] = cpuc->event_list[i]; cpuc->event_constraint[i-1] = cpuc->event_constraint[i]; + cpuc->assign[i-1] = cpuc->assign[i]; } cpuc->event_constraint[i-1] = NULL; --cpuc->n_events; -- cgit v1.2.3 From 04f4230e2f86a4e961ea5466eda3db8c1762004d Mon Sep 17 00:00:00 2001 From: Daniel Sneddon Date: Tue, 9 Apr 2024 16:08:05 -0700 Subject: x86/bugs: Fix return type of spectre_bhi_state() The definition of spectre_bhi_state() incorrectly returns a const char * const. This causes the a compiler warning when building with W=1: warning: type qualifiers ignored on function return type [-Wignored-qualifiers] 2812 | static const char * const spectre_bhi_state(void) Remove the const qualifier from the pointer. Fixes: ec9404e40e8f ("x86/bhi: Add BHI mitigation knob") Reported-by: Sean Christopherson Signed-off-by: Daniel Sneddon Signed-off-by: Ingo Molnar Cc: Linus Torvalds Link: https://lore.kernel.org/r/20240409230806.1545822-1-daniel.sneddon@linux.intel.com --- arch/x86/kernel/cpu/bugs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/x86/kernel/cpu/bugs.c b/arch/x86/kernel/cpu/bugs.c index 295463707e68..27f5004a8e24 100644 --- a/arch/x86/kernel/cpu/bugs.c +++ b/arch/x86/kernel/cpu/bugs.c @@ -2809,7 +2809,7 @@ static char *pbrsb_eibrs_state(void) } } -static const char * const spectre_bhi_state(void) +static const char *spectre_bhi_state(void) { if (!boot_cpu_has_bug(X86_BUG_BHI)) return "; BHI: Not affected"; -- cgit v1.2.3 From 81665adf25d28a00a986533f1d3a5df76b79cad9 Mon Sep 17 00:00:00 2001 From: Brett Creeley Date: Mon, 8 Apr 2024 09:35:40 -0700 Subject: pds_core: Fix pdsc_check_pci_health function to use work thread When the driver notices fw_status == 0xff it tries to perform a PCI reset on itself via pci_reset_function() in the context of the driver's health thread. However, pdsc_reset_prepare calls pdsc_stop_health_thread(), which attempts to stop/flush the health thread. This results in a deadlock because the stop/flush will never complete since the driver called pci_reset_function() from the health thread context. Fix by changing the pdsc_check_pci_health_function() to queue a newly introduced pdsc_pci_reset_thread() on the pdsc's work queue. Unloading the driver in the fw_down/dead state uncovered another issue, which can be seen in the following trace: WARNING: CPU: 51 PID: 6914 at kernel/workqueue.c:1450 __queue_work+0x358/0x440 [...] RIP: 0010:__queue_work+0x358/0x440 [...] Call Trace: ? __warn+0x85/0x140 ? __queue_work+0x358/0x440 ? report_bug+0xfc/0x1e0 ? handle_bug+0x3f/0x70 ? exc_invalid_op+0x17/0x70 ? asm_exc_invalid_op+0x1a/0x20 ? __queue_work+0x358/0x440 queue_work_on+0x28/0x30 pdsc_devcmd_locked+0x96/0xe0 [pds_core] pdsc_devcmd_reset+0x71/0xb0 [pds_core] pdsc_teardown+0x51/0xe0 [pds_core] pdsc_remove+0x106/0x200 [pds_core] pci_device_remove+0x37/0xc0 device_release_driver_internal+0xae/0x140 driver_detach+0x48/0x90 bus_remove_driver+0x6d/0xf0 pci_unregister_driver+0x2e/0xa0 pdsc_cleanup_module+0x10/0x780 [pds_core] __x64_sys_delete_module+0x142/0x2b0 ? syscall_trace_enter.isra.18+0x126/0x1a0 do_syscall_64+0x3b/0x90 entry_SYSCALL_64_after_hwframe+0x72/0xdc RIP: 0033:0x7fbd9d03a14b [...] Fix this by preventing the devcmd reset if the FW is not running. Fixes: d9407ff11809 ("pds_core: Prevent health thread from running during reset/remove") Reviewed-by: Shannon Nelson Signed-off-by: Brett Creeley Reviewed-by: Jacob Keller Signed-off-by: David S. Miller --- drivers/net/ethernet/amd/pds_core/core.c | 13 ++++++++++++- drivers/net/ethernet/amd/pds_core/core.h | 2 ++ drivers/net/ethernet/amd/pds_core/dev.c | 3 +++ drivers/net/ethernet/amd/pds_core/main.c | 1 + 4 files changed, 18 insertions(+), 1 deletion(-) diff --git a/drivers/net/ethernet/amd/pds_core/core.c b/drivers/net/ethernet/amd/pds_core/core.c index 9662ee72814c..536635e57727 100644 --- a/drivers/net/ethernet/amd/pds_core/core.c +++ b/drivers/net/ethernet/amd/pds_core/core.c @@ -593,6 +593,16 @@ err_out: pdsc_teardown(pdsc, PDSC_TEARDOWN_RECOVERY); } +void pdsc_pci_reset_thread(struct work_struct *work) +{ + struct pdsc *pdsc = container_of(work, struct pdsc, pci_reset_work); + struct pci_dev *pdev = pdsc->pdev; + + pci_dev_get(pdev); + pci_reset_function(pdev); + pci_dev_put(pdev); +} + static void pdsc_check_pci_health(struct pdsc *pdsc) { u8 fw_status; @@ -607,7 +617,8 @@ static void pdsc_check_pci_health(struct pdsc *pdsc) if (fw_status != PDS_RC_BAD_PCI) return; - pci_reset_function(pdsc->pdev); + /* prevent deadlock between pdsc_reset_prepare and pdsc_health_thread */ + queue_work(pdsc->wq, &pdsc->pci_reset_work); } void pdsc_health_thread(struct work_struct *work) diff --git a/drivers/net/ethernet/amd/pds_core/core.h b/drivers/net/ethernet/amd/pds_core/core.h index 92d7657dd614..a3e17a0c187a 100644 --- a/drivers/net/ethernet/amd/pds_core/core.h +++ b/drivers/net/ethernet/amd/pds_core/core.h @@ -197,6 +197,7 @@ struct pdsc { struct pdsc_qcq notifyqcq; u64 last_eid; struct pdsc_viftype *viftype_status; + struct work_struct pci_reset_work; }; /** enum pds_core_dbell_bits - bitwise composition of dbell values. @@ -313,5 +314,6 @@ int pdsc_firmware_update(struct pdsc *pdsc, const struct firmware *fw, void pdsc_fw_down(struct pdsc *pdsc); void pdsc_fw_up(struct pdsc *pdsc); +void pdsc_pci_reset_thread(struct work_struct *work); #endif /* _PDSC_H_ */ diff --git a/drivers/net/ethernet/amd/pds_core/dev.c b/drivers/net/ethernet/amd/pds_core/dev.c index e494e1298dc9..495ef4ef8c10 100644 --- a/drivers/net/ethernet/amd/pds_core/dev.c +++ b/drivers/net/ethernet/amd/pds_core/dev.c @@ -229,6 +229,9 @@ int pdsc_devcmd_reset(struct pdsc *pdsc) .reset.opcode = PDS_CORE_CMD_RESET, }; + if (!pdsc_is_fw_running(pdsc)) + return 0; + return pdsc_devcmd(pdsc, &cmd, &comp, pdsc->devcmd_timeout); } diff --git a/drivers/net/ethernet/amd/pds_core/main.c b/drivers/net/ethernet/amd/pds_core/main.c index ab6133e7db42..660268ff9562 100644 --- a/drivers/net/ethernet/amd/pds_core/main.c +++ b/drivers/net/ethernet/amd/pds_core/main.c @@ -239,6 +239,7 @@ static int pdsc_init_pf(struct pdsc *pdsc) snprintf(wq_name, sizeof(wq_name), "%s.%d", PDS_CORE_DRV_NAME, pdsc->uid); pdsc->wq = create_singlethread_workqueue(wq_name); INIT_WORK(&pdsc->health_work, pdsc_health_thread); + INIT_WORK(&pdsc->pci_reset_work, pdsc_pci_reset_thread); timer_setup(&pdsc->wdtimer, pdsc_wdtimer_cb, 0); pdsc->wdtimer_period = PDSC_WATCHDOG_SECS * HZ; -- cgit v1.2.3 From c38fa07dc69f0b9e6f43ecab96dc7861a70c827c Mon Sep 17 00:00:00 2001 From: Gil Fine Date: Fri, 1 Mar 2024 15:22:53 +0200 Subject: thunderbolt: Fix wake configurations after device unplug Currently we don't configure correctly the wake events after unplug of device router. What can happen is that the downstream ports of host router will be configured to wake on: USB4-wake and wake-on-disconnect, but not on wake-on-connect. This may cause the later plugged device not to wake the domain and fail in enumeration. Fix this by clearing downstream port's "USB4 Port is Configured" bit, after unplug of a device router. Signed-off-by: Gil Fine Cc: stable@vger.kernel.org Signed-off-by: Mika Westerberg --- drivers/thunderbolt/switch.c | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/drivers/thunderbolt/switch.c b/drivers/thunderbolt/switch.c index 6ffc4e81ffed..4edfd6e34e31 100644 --- a/drivers/thunderbolt/switch.c +++ b/drivers/thunderbolt/switch.c @@ -3180,22 +3180,29 @@ void tb_switch_unconfigure_link(struct tb_switch *sw) { struct tb_port *up, *down; - if (sw->is_unplugged) - return; if (!tb_route(sw) || tb_switch_is_icm(sw)) return; + /* + * Unconfigure downstream port so that wake-on-connect can be + * configured after router unplug. No need to unconfigure upstream port + * since its router is unplugged. + */ up = tb_upstream_port(sw); - if (tb_switch_is_usb4(up->sw)) - usb4_port_unconfigure(up); - else - tb_lc_unconfigure_port(up); - down = up->remote; if (tb_switch_is_usb4(down->sw)) usb4_port_unconfigure(down); else tb_lc_unconfigure_port(down); + + if (sw->is_unplugged) + return; + + up = tb_upstream_port(sw); + if (tb_switch_is_usb4(up->sw)) + usb4_port_unconfigure(up); + else + tb_lc_unconfigure_port(up); } static void tb_switch_credits_init(struct tb_switch *sw) -- cgit v1.2.3 From dcd12acaf384c30437fa5a9a1f71df06fc9835fd Mon Sep 17 00:00:00 2001 From: Gil Fine Date: Fri, 1 Mar 2024 15:11:18 +0200 Subject: thunderbolt: Avoid notify PM core about runtime PM resume Currently we notify PM core about occurred wakes after any resume. This is not actually needed after resume from runtime suspend. Hence, notify PM core about occurred wakes only after resume from system sleep. Also, if the wake occurred in USB4 router upstream port, we don't notify the PM core about it since it is not actually needed and can cause unexpected autowake (e.g. if /sys/power/wakeup_count is used). While there add the missing kernel-doc for tb_switch_resume(). Signed-off-by: Gil Fine Cc: stable@vger.kernel.org Signed-off-by: Mika Westerberg --- drivers/thunderbolt/switch.c | 27 +++++++++++++++++++++++++-- drivers/thunderbolt/tb.c | 4 ++-- drivers/thunderbolt/tb.h | 3 ++- drivers/thunderbolt/usb4.c | 13 +++++++------ 4 files changed, 36 insertions(+), 11 deletions(-) diff --git a/drivers/thunderbolt/switch.c b/drivers/thunderbolt/switch.c index 4edfd6e34e31..326433df5880 100644 --- a/drivers/thunderbolt/switch.c +++ b/drivers/thunderbolt/switch.c @@ -3448,7 +3448,26 @@ static int tb_switch_set_wake(struct tb_switch *sw, unsigned int flags) return tb_lc_set_wake(sw, flags); } -int tb_switch_resume(struct tb_switch *sw) +static void tb_switch_check_wakes(struct tb_switch *sw) +{ + if (device_may_wakeup(&sw->dev)) { + if (tb_switch_is_usb4(sw)) + usb4_switch_check_wakes(sw); + } +} + +/** + * tb_switch_resume() - Resume a switch after sleep + * @sw: Switch to resume + * @runtime: Is this resume from runtime suspend or system sleep + * + * Resumes and re-enumerates router (and all its children), if still plugged + * after suspend. Don't enumerate device router whose UID was changed during + * suspend. If this is resume from system sleep, notifies PM core about the + * wakes occurred during suspend. Disables all wakes, except USB4 wake of + * upstream port for USB4 routers that shall be always enabled. + */ +int tb_switch_resume(struct tb_switch *sw, bool runtime) { struct tb_port *port; int err; @@ -3497,6 +3516,9 @@ int tb_switch_resume(struct tb_switch *sw) if (err) return err; + if (!runtime) + tb_switch_check_wakes(sw); + /* Disable wakes */ tb_switch_set_wake(sw, 0); @@ -3526,7 +3548,8 @@ int tb_switch_resume(struct tb_switch *sw) */ if (tb_port_unlock(port)) tb_port_warn(port, "failed to unlock port\n"); - if (port->remote && tb_switch_resume(port->remote->sw)) { + if (port->remote && + tb_switch_resume(port->remote->sw, runtime)) { tb_port_warn(port, "lost during suspend, disconnecting\n"); tb_sw_set_unplugged(port->remote->sw); diff --git a/drivers/thunderbolt/tb.c b/drivers/thunderbolt/tb.c index 360cb95f39aa..3e44c78ac409 100644 --- a/drivers/thunderbolt/tb.c +++ b/drivers/thunderbolt/tb.c @@ -2942,7 +2942,7 @@ static int tb_resume_noirq(struct tb *tb) if (!tb_switch_is_usb4(tb->root_switch)) tb_switch_reset(tb->root_switch); - tb_switch_resume(tb->root_switch); + tb_switch_resume(tb->root_switch, false); tb_free_invalid_tunnels(tb); tb_free_unplugged_children(tb->root_switch); tb_restore_children(tb->root_switch); @@ -3068,7 +3068,7 @@ static int tb_runtime_resume(struct tb *tb) struct tb_tunnel *tunnel, *n; mutex_lock(&tb->lock); - tb_switch_resume(tb->root_switch); + tb_switch_resume(tb->root_switch, true); tb_free_invalid_tunnels(tb); tb_restore_children(tb->root_switch); list_for_each_entry_safe(tunnel, n, &tcm->tunnel_list, list) diff --git a/drivers/thunderbolt/tb.h b/drivers/thunderbolt/tb.h index feed8ecaf712..18aae4ccaed5 100644 --- a/drivers/thunderbolt/tb.h +++ b/drivers/thunderbolt/tb.h @@ -827,7 +827,7 @@ int tb_switch_configuration_valid(struct tb_switch *sw); int tb_switch_add(struct tb_switch *sw); void tb_switch_remove(struct tb_switch *sw); void tb_switch_suspend(struct tb_switch *sw, bool runtime); -int tb_switch_resume(struct tb_switch *sw); +int tb_switch_resume(struct tb_switch *sw, bool runtime); int tb_switch_reset(struct tb_switch *sw); int tb_switch_wait_for_bit(struct tb_switch *sw, u32 offset, u32 bit, u32 value, int timeout_msec); @@ -1288,6 +1288,7 @@ static inline bool tb_switch_is_usb4(const struct tb_switch *sw) return usb4_switch_version(sw) > 0; } +void usb4_switch_check_wakes(struct tb_switch *sw); int usb4_switch_setup(struct tb_switch *sw); int usb4_switch_configuration_valid(struct tb_switch *sw); int usb4_switch_read_uid(struct tb_switch *sw, u64 *uid); diff --git a/drivers/thunderbolt/usb4.c b/drivers/thunderbolt/usb4.c index 9860b49d7a2b..78b06e922fda 100644 --- a/drivers/thunderbolt/usb4.c +++ b/drivers/thunderbolt/usb4.c @@ -155,7 +155,13 @@ static inline int usb4_switch_op_data(struct tb_switch *sw, u16 opcode, tx_dwords, rx_data, rx_dwords); } -static void usb4_switch_check_wakes(struct tb_switch *sw) +/** + * usb4_switch_check_wakes() - Check for wakes and notify PM core about them + * @sw: Router whose wakes to check + * + * Checks wakes occurred during suspend and notify the PM core about them. + */ +void usb4_switch_check_wakes(struct tb_switch *sw) { bool wakeup_usb4 = false; struct usb4_port *usb4; @@ -163,9 +169,6 @@ static void usb4_switch_check_wakes(struct tb_switch *sw) bool wakeup = false; u32 val; - if (!device_may_wakeup(&sw->dev)) - return; - if (tb_route(sw)) { if (tb_sw_read(sw, &val, TB_CFG_SWITCH, ROUTER_CS_6, 1)) return; @@ -244,8 +247,6 @@ int usb4_switch_setup(struct tb_switch *sw) u32 val = 0; int ret; - usb4_switch_check_wakes(sw); - if (!tb_route(sw)) return 0; -- cgit v1.2.3 From f87cbcb345d059f0377b4fa0ba1b766a17fc3710 Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Tue, 9 Apr 2024 12:29:12 +0200 Subject: timekeeping: Use READ/WRITE_ONCE() for tick_do_timer_cpu tick_do_timer_cpu is used lockless to check which CPU needs to take care of the per tick timekeeping duty. This is done to avoid a thundering herd problem on jiffies_lock. The read and writes are not annotated so KCSAN complains about data races: BUG: KCSAN: data-race in tick_nohz_idle_stop_tick / tick_nohz_next_event write to 0xffffffff8a2bda30 of 4 bytes by task 0 on cpu 26: tick_nohz_idle_stop_tick+0x3b1/0x4a0 do_idle+0x1e3/0x250 read to 0xffffffff8a2bda30 of 4 bytes by task 0 on cpu 16: tick_nohz_next_event+0xe7/0x1e0 tick_nohz_get_sleep_length+0xa7/0xe0 menu_select+0x82/0xb90 cpuidle_select+0x44/0x60 do_idle+0x1c2/0x250 value changed: 0x0000001a -> 0xffffffff Annotate them with READ/WRITE_ONCE() to document the intentional data race. Reported-by: Mirsad Todorovac Signed-off-by: Thomas Gleixner Signed-off-by: Ingo Molnar Tested-by: Sean Anderson Link: https://lore.kernel.org/r/87cyqy7rt3.ffs@tglx --- kernel/time/tick-common.c | 17 +++++++++-------- kernel/time/tick-sched.c | 36 ++++++++++++++++++++++-------------- 2 files changed, 31 insertions(+), 22 deletions(-) diff --git a/kernel/time/tick-common.c b/kernel/time/tick-common.c index fb0fdec8719a..d88b13076b79 100644 --- a/kernel/time/tick-common.c +++ b/kernel/time/tick-common.c @@ -7,6 +7,7 @@ * Copyright(C) 2005-2007, Red Hat, Inc., Ingo Molnar * Copyright(C) 2006-2007, Timesys Corp., Thomas Gleixner */ +#include #include #include #include @@ -84,7 +85,7 @@ int tick_is_oneshot_available(void) */ static void tick_periodic(int cpu) { - if (tick_do_timer_cpu == cpu) { + if (READ_ONCE(tick_do_timer_cpu) == cpu) { raw_spin_lock(&jiffies_lock); write_seqcount_begin(&jiffies_seq); @@ -215,8 +216,8 @@ static void tick_setup_device(struct tick_device *td, * If no cpu took the do_timer update, assign it to * this cpu: */ - if (tick_do_timer_cpu == TICK_DO_TIMER_BOOT) { - tick_do_timer_cpu = cpu; + if (READ_ONCE(tick_do_timer_cpu) == TICK_DO_TIMER_BOOT) { + WRITE_ONCE(tick_do_timer_cpu, cpu); tick_next_period = ktime_get(); #ifdef CONFIG_NO_HZ_FULL /* @@ -232,7 +233,7 @@ static void tick_setup_device(struct tick_device *td, !tick_nohz_full_cpu(cpu)) { tick_take_do_timer_from_boot(); tick_do_timer_boot_cpu = -1; - WARN_ON(tick_do_timer_cpu != cpu); + WARN_ON(READ_ONCE(tick_do_timer_cpu) != cpu); #endif } @@ -406,10 +407,10 @@ void tick_assert_timekeeping_handover(void) int tick_cpu_dying(unsigned int dying_cpu) { /* - * If the current CPU is the timekeeper, it's the only one that - * can safely hand over its duty. Also all online CPUs are in - * stop machine, guaranteed not to be idle, therefore it's safe - * to pick any online successor. + * If the current CPU is the timekeeper, it's the only one that can + * safely hand over its duty. Also all online CPUs are in stop + * machine, guaranteed not to be idle, therefore there is no + * concurrency and it's safe to pick any online successor. */ if (tick_do_timer_cpu == dying_cpu) tick_do_timer_cpu = cpumask_first(cpu_online_mask); diff --git a/kernel/time/tick-sched.c b/kernel/time/tick-sched.c index 1331216a9cae..71a792cd8936 100644 --- a/kernel/time/tick-sched.c +++ b/kernel/time/tick-sched.c @@ -8,6 +8,7 @@ * * Started by: Thomas Gleixner and Ingo Molnar */ +#include #include #include #include @@ -204,7 +205,7 @@ static inline void tick_sched_flag_clear(struct tick_sched *ts, static void tick_sched_do_timer(struct tick_sched *ts, ktime_t now) { - int cpu = smp_processor_id(); + int tick_cpu, cpu = smp_processor_id(); /* * Check if the do_timer duty was dropped. We don't care about @@ -216,16 +217,18 @@ static void tick_sched_do_timer(struct tick_sched *ts, ktime_t now) * If nohz_full is enabled, this should not happen because the * 'tick_do_timer_cpu' CPU never relinquishes. */ - if (IS_ENABLED(CONFIG_NO_HZ_COMMON) && - unlikely(tick_do_timer_cpu == TICK_DO_TIMER_NONE)) { + tick_cpu = READ_ONCE(tick_do_timer_cpu); + + if (IS_ENABLED(CONFIG_NO_HZ_COMMON) && unlikely(tick_cpu == TICK_DO_TIMER_NONE)) { #ifdef CONFIG_NO_HZ_FULL WARN_ON_ONCE(tick_nohz_full_running); #endif - tick_do_timer_cpu = cpu; + WRITE_ONCE(tick_do_timer_cpu, cpu); + tick_cpu = cpu; } /* Check if jiffies need an update */ - if (tick_do_timer_cpu == cpu) + if (tick_cpu == cpu) tick_do_update_jiffies64(now); /* @@ -610,7 +613,7 @@ bool tick_nohz_cpu_hotpluggable(unsigned int cpu) * timers, workqueues, timekeeping, ...) on behalf of full dynticks * CPUs. It must remain online when nohz full is enabled. */ - if (tick_nohz_full_running && tick_do_timer_cpu == cpu) + if (tick_nohz_full_running && READ_ONCE(tick_do_timer_cpu) == cpu) return false; return true; } @@ -891,6 +894,7 @@ static ktime_t tick_nohz_next_event(struct tick_sched *ts, int cpu) { u64 basemono, next_tick, delta, expires; unsigned long basejiff; + int tick_cpu; basemono = get_jiffies_update(&basejiff); ts->last_jiffies = basejiff; @@ -947,9 +951,9 @@ static ktime_t tick_nohz_next_event(struct tick_sched *ts, int cpu) * Otherwise we can sleep as long as we want. */ delta = timekeeping_max_deferment(); - if (cpu != tick_do_timer_cpu && - (tick_do_timer_cpu != TICK_DO_TIMER_NONE || - !tick_sched_flag_test(ts, TS_FLAG_DO_TIMER_LAST))) + tick_cpu = READ_ONCE(tick_do_timer_cpu); + if (tick_cpu != cpu && + (tick_cpu != TICK_DO_TIMER_NONE || !tick_sched_flag_test(ts, TS_FLAG_DO_TIMER_LAST))) delta = KTIME_MAX; /* Calculate the next expiry time */ @@ -970,6 +974,7 @@ static void tick_nohz_stop_tick(struct tick_sched *ts, int cpu) unsigned long basejiff = ts->last_jiffies; u64 basemono = ts->timer_expires_base; bool timer_idle = tick_sched_flag_test(ts, TS_FLAG_STOPPED); + int tick_cpu; u64 expires; /* Make sure we won't be trying to stop it twice in a row. */ @@ -1007,10 +1012,11 @@ static void tick_nohz_stop_tick(struct tick_sched *ts, int cpu) * do_timer() never gets invoked. Keep track of the fact that it * was the one which had the do_timer() duty last. */ - if (cpu == tick_do_timer_cpu) { - tick_do_timer_cpu = TICK_DO_TIMER_NONE; + tick_cpu = READ_ONCE(tick_do_timer_cpu); + if (tick_cpu == cpu) { + WRITE_ONCE(tick_do_timer_cpu, TICK_DO_TIMER_NONE); tick_sched_flag_set(ts, TS_FLAG_DO_TIMER_LAST); - } else if (tick_do_timer_cpu != TICK_DO_TIMER_NONE) { + } else if (tick_cpu != TICK_DO_TIMER_NONE) { tick_sched_flag_clear(ts, TS_FLAG_DO_TIMER_LAST); } @@ -1173,15 +1179,17 @@ static bool can_stop_idle_tick(int cpu, struct tick_sched *ts) return false; if (tick_nohz_full_enabled()) { + int tick_cpu = READ_ONCE(tick_do_timer_cpu); + /* * Keep the tick alive to guarantee timekeeping progression * if there are full dynticks CPUs around */ - if (tick_do_timer_cpu == cpu) + if (tick_cpu == cpu) return false; /* Should not happen for nohz-full */ - if (WARN_ON_ONCE(tick_do_timer_cpu == TICK_DO_TIMER_NONE)) + if (WARN_ON_ONCE(tick_cpu == TICK_DO_TIMER_NONE)) return false; } -- cgit v1.2.3 From 19fa4f2a85d777a8052e869c1b892a2f7556569d Mon Sep 17 00:00:00 2001 From: Heiner Kallweit Date: Mon, 8 Apr 2024 20:47:40 +0200 Subject: r8169: fix LED-related deadlock on module removal Binding devm_led_classdev_register() to the netdev is problematic because on module removal we get a RTNL-related deadlock. Fix this by avoiding the device-managed LED functions. Note: We can safely call led_classdev_unregister() for a LED even if registering it failed, because led_classdev_unregister() detects this and is a no-op in this case. Fixes: 18764b883e15 ("r8169: add support for LED's on RTL8168/RTL8101") Cc: stable@vger.kernel.org Reported-by: Lukas Wunner Signed-off-by: Heiner Kallweit Reviewed-by: Andrew Lunn Signed-off-by: David S. Miller --- drivers/net/ethernet/realtek/r8169.h | 6 ++++-- drivers/net/ethernet/realtek/r8169_leds.c | 35 ++++++++++++++++++++----------- drivers/net/ethernet/realtek/r8169_main.c | 8 +++++-- 3 files changed, 33 insertions(+), 16 deletions(-) diff --git a/drivers/net/ethernet/realtek/r8169.h b/drivers/net/ethernet/realtek/r8169.h index 4c043052198d..00882ffc7a02 100644 --- a/drivers/net/ethernet/realtek/r8169.h +++ b/drivers/net/ethernet/realtek/r8169.h @@ -73,6 +73,7 @@ enum mac_version { }; struct rtl8169_private; +struct r8169_led_classdev; void r8169_apply_firmware(struct rtl8169_private *tp); u16 rtl8168h_2_get_adc_bias_ioffset(struct rtl8169_private *tp); @@ -84,7 +85,8 @@ void r8169_get_led_name(struct rtl8169_private *tp, int idx, char *buf, int buf_len); int rtl8168_get_led_mode(struct rtl8169_private *tp); int rtl8168_led_mod_ctrl(struct rtl8169_private *tp, u16 mask, u16 val); -void rtl8168_init_leds(struct net_device *ndev); +struct r8169_led_classdev *rtl8168_init_leds(struct net_device *ndev); int rtl8125_get_led_mode(struct rtl8169_private *tp, int index); int rtl8125_set_led_mode(struct rtl8169_private *tp, int index, u16 mode); -void rtl8125_init_leds(struct net_device *ndev); +struct r8169_led_classdev *rtl8125_init_leds(struct net_device *ndev); +void r8169_remove_leds(struct r8169_led_classdev *leds); diff --git a/drivers/net/ethernet/realtek/r8169_leds.c b/drivers/net/ethernet/realtek/r8169_leds.c index 7c5dc9d0df85..e10bee706bc6 100644 --- a/drivers/net/ethernet/realtek/r8169_leds.c +++ b/drivers/net/ethernet/realtek/r8169_leds.c @@ -146,22 +146,22 @@ static void rtl8168_setup_ldev(struct r8169_led_classdev *ldev, led_cdev->hw_control_get_device = r8169_led_hw_control_get_device; /* ignore errors */ - devm_led_classdev_register(&ndev->dev, led_cdev); + led_classdev_register(&ndev->dev, led_cdev); } -void rtl8168_init_leds(struct net_device *ndev) +struct r8169_led_classdev *rtl8168_init_leds(struct net_device *ndev) { - /* bind resource mgmt to netdev */ - struct device *dev = &ndev->dev; struct r8169_led_classdev *leds; int i; - leds = devm_kcalloc(dev, RTL8168_NUM_LEDS, sizeof(*leds), GFP_KERNEL); + leds = kcalloc(RTL8168_NUM_LEDS + 1, sizeof(*leds), GFP_KERNEL); if (!leds) - return; + return NULL; for (i = 0; i < RTL8168_NUM_LEDS; i++) rtl8168_setup_ldev(leds + i, ndev, i); + + return leds; } static int rtl8125_led_hw_control_is_supported(struct led_classdev *led_cdev, @@ -245,20 +245,31 @@ static void rtl8125_setup_led_ldev(struct r8169_led_classdev *ldev, led_cdev->hw_control_get_device = r8169_led_hw_control_get_device; /* ignore errors */ - devm_led_classdev_register(&ndev->dev, led_cdev); + led_classdev_register(&ndev->dev, led_cdev); } -void rtl8125_init_leds(struct net_device *ndev) +struct r8169_led_classdev *rtl8125_init_leds(struct net_device *ndev) { - /* bind resource mgmt to netdev */ - struct device *dev = &ndev->dev; struct r8169_led_classdev *leds; int i; - leds = devm_kcalloc(dev, RTL8125_NUM_LEDS, sizeof(*leds), GFP_KERNEL); + leds = kcalloc(RTL8125_NUM_LEDS + 1, sizeof(*leds), GFP_KERNEL); if (!leds) - return; + return NULL; for (i = 0; i < RTL8125_NUM_LEDS; i++) rtl8125_setup_led_ldev(leds + i, ndev, i); + + return leds; +} + +void r8169_remove_leds(struct r8169_led_classdev *leds) +{ + if (!leds) + return; + + for (struct r8169_led_classdev *l = leds; l->ndev; l++) + led_classdev_unregister(&l->led); + + kfree(leds); } diff --git a/drivers/net/ethernet/realtek/r8169_main.c b/drivers/net/ethernet/realtek/r8169_main.c index 6f1e6f386b7b..8a27328eae34 100644 --- a/drivers/net/ethernet/realtek/r8169_main.c +++ b/drivers/net/ethernet/realtek/r8169_main.c @@ -647,6 +647,8 @@ struct rtl8169_private { const char *fw_name; struct rtl_fw *rtl_fw; + struct r8169_led_classdev *leds; + u32 ocp_base; }; @@ -5044,6 +5046,8 @@ static void rtl_remove_one(struct pci_dev *pdev) cancel_work_sync(&tp->wk.work); + r8169_remove_leds(tp->leds); + unregister_netdev(tp->dev); if (tp->dash_type != RTL_DASH_NONE) @@ -5501,9 +5505,9 @@ static int rtl_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) if (IS_ENABLED(CONFIG_R8169_LEDS)) { if (rtl_is_8125(tp)) - rtl8125_init_leds(dev); + tp->leds = rtl8125_init_leds(dev); else if (tp->mac_version > RTL_GIGA_MAC_VER_06) - rtl8168_init_leds(dev); + tp->leds = rtl8168_init_leds(dev); } netdev_info(dev, "%s, %pM, XID %03x, IRQ %d\n", -- cgit v1.2.3 From 3bbb331c1d34fdd5520a050fce35f71579430485 Mon Sep 17 00:00:00 2001 From: Zhang Rui Date: Wed, 13 Mar 2024 10:30:04 +0800 Subject: tools/power/turbostat: Introduce BIC_SAM_mc6/BIC_SAMMHz/BIC_SAMACTMHz Graphics driver (i915/Xe) on mordern platforms splits GFX and SA Media information via different sysfs knobs. Existing BIC_GFX_rc6/BIC_GFXMHz/BIC_GFXACTMHz columns can be reused for GFX. Introduce BIC_SAM_mc6/BIC_SAMMHz/BIC_SAMACTMHz columns for SA Media. Signed-off-by: Zhang Rui --- tools/power/x86/turbostat/turbostat.8 | 12 ++++- tools/power/x86/turbostat/turbostat.c | 91 +++++++++++++++++++++++++++++++++-- 2 files changed, 96 insertions(+), 7 deletions(-) diff --git a/tools/power/x86/turbostat/turbostat.8 b/tools/power/x86/turbostat/turbostat.8 index 567327b004e6..0d3672e5d9ed 100644 --- a/tools/power/x86/turbostat/turbostat.8 +++ b/tools/power/x86/turbostat/turbostat.8 @@ -129,9 +129,17 @@ The system configuration dump (if --quiet is not used) is followed by statistics .PP \fBPkgTmp\fP Degrees Celsius reported by the per-package Package Thermal Monitor. .PP -\fBGFX%rc6\fP The percentage of time the GPU is in the "render C6" state, rc6, during the measurement interval. From /sys/class/drm/card0/power/rc6_residency_ms. +\fBGFX%rc6\fP The percentage of time the GPU is in the "render C6" state, rc6, during the measurement interval. From /sys/class/drm/card0/power/rc6_residency_ms or /sys/class/drm/card0/gt/gt0/rc6_residency_ms or /sys/class/drm/card0/device/tile0/gtN/gtidle/idle_residency_ms depending on the graphics driver being used. .PP -\fBGFXMHz\fP Instantaneous snapshot of what sysfs presents at the end of the measurement interval. From /sys/class/graphics/fb0/device/drm/card0/gt_cur_freq_mhz. +\fBGFXMHz\fP Instantaneous snapshot of what sysfs presents at the end of the measurement interval. From /sys/class/graphics/fb0/device/drm/card0/gt_cur_freq_mhz or /sys/class/drm/card0/gt_cur_freq_mhz or /sys/class/drm/card0/gt/gt0/rps_cur_freq_mhz or /sys/class/drm/card0/device/tile0/gtN/freq0/cur_freq depending on the graphics driver being used. +.PP +\fBGFXAMHz\fP Instantaneous snapshot of what sysfs presents at the end of the measurement interval. From /sys/class/graphics/fb0/device/drm/card0/gt_act_freq_mhz or /sys/class/drm/card0/gt_act_freq_mhz or /sys/class/drm/card0/gt/gt0/rps_act_freq_mhz or /sys/class/drm/card0/device/tile0/gtN/freq0/act_freq depending on the graphics driver being used. +.PP +\fBSAM%mc6\fP The percentage of time the SA Media is in the "module C6" state, mc6, during the measurement interval. From /sys/class/drm/card0/gt/gt1/rc6_residency_ms or /sys/class/drm/card0/device/tile0/gtN/gtidle/idle_residency_ms depending on the graphics driver being used. +.PP +\fBSAMMHz\fP Instantaneous snapshot of what sysfs presents at the end of the measurement interval. From /sys/class/drm/card0/gt/gt1/rps_cur_freq_mhz or /sys/class/drm/card0/device/tile0/gtN/freq0/cur_freq depending on the graphics driver being used. +.PP +\fBSAMAMHz\fP Instantaneous snapshot of what sysfs presents at the end of the measurement interval. From /sys/class/drm/card0/gt/gt1/rps_act_freq_mhz or /sys/class/drm/card0/device/tile0/gtN/freq0/act_freq depending on the graphics driver being used. .PP \fBPkg%pc2, Pkg%pc3, Pkg%pc6, Pkg%pc7\fP percentage residency in hardware package idle states. These numbers are from hardware residency counters. .PP diff --git a/tools/power/x86/turbostat/turbostat.c b/tools/power/x86/turbostat/turbostat.c index 016a5c7dc9bf..4fa2810da1a3 100644 --- a/tools/power/x86/turbostat/turbostat.c +++ b/tools/power/x86/turbostat/turbostat.c @@ -133,6 +133,9 @@ struct msr_counter bic[] = { { 0x0, "IPC", "", 0, 0, 0, NULL, 0 }, { 0x0, "CoreThr", "", 0, 0, 0, NULL, 0 }, { 0x0, "UncMHz", "", 0, 0, 0, NULL, 0 }, + { 0x0, "SAM%mc6", "", 0, 0, 0, NULL, 0 }, + { 0x0, "SAMMHz", "", 0, 0, 0, NULL, 0 }, + { 0x0, "SAMAMHz", "", 0, 0, 0, NULL, 0 }, }; #define MAX_BIC (sizeof(bic) / sizeof(struct msr_counter)) @@ -191,11 +194,14 @@ struct msr_counter bic[] = { #define BIC_IPC (1ULL << 52) #define BIC_CORE_THROT_CNT (1ULL << 53) #define BIC_UNCORE_MHZ (1ULL << 54) +#define BIC_SAM_mc6 (1ULL << 55) +#define BIC_SAMMHz (1ULL << 56) +#define BIC_SAMACTMHz (1ULL << 57) #define BIC_TOPOLOGY (BIC_Package | BIC_Node | BIC_CoreCnt | BIC_PkgCnt | BIC_Core | BIC_CPU | BIC_Die ) #define BIC_THERMAL_PWR ( BIC_CoreTmp | BIC_PkgTmp | BIC_PkgWatt | BIC_CorWatt | BIC_GFXWatt | BIC_RAMWatt | BIC_PKG__ | BIC_RAM__) -#define BIC_FREQUENCY ( BIC_Avg_MHz | BIC_Busy | BIC_Bzy_MHz | BIC_TSC_MHz | BIC_GFXMHz | BIC_GFXACTMHz | BIC_UNCORE_MHZ) -#define BIC_IDLE ( BIC_sysfs | BIC_CPU_c1 | BIC_CPU_c3 | BIC_CPU_c6 | BIC_CPU_c7 | BIC_GFX_rc6 | BIC_Pkgpc2 | BIC_Pkgpc3 | BIC_Pkgpc6 | BIC_Pkgpc7 | BIC_Pkgpc8 | BIC_Pkgpc9 | BIC_Pkgpc10 | BIC_CPU_LPI | BIC_SYS_LPI | BIC_Mod_c6 | BIC_Totl_c0 | BIC_Any_c0 | BIC_GFX_c0 | BIC_CPUGFX) +#define BIC_FREQUENCY (BIC_Avg_MHz | BIC_Busy | BIC_Bzy_MHz | BIC_TSC_MHz | BIC_GFXMHz | BIC_GFXACTMHz | BIC_SAMMHz | BIC_SAMACTMHz | BIC_UNCORE_MHZ) +#define BIC_IDLE (BIC_sysfs | BIC_CPU_c1 | BIC_CPU_c3 | BIC_CPU_c6 | BIC_CPU_c7 | BIC_GFX_rc6 | BIC_Pkgpc2 | BIC_Pkgpc3 | BIC_Pkgpc6 | BIC_Pkgpc7 | BIC_Pkgpc8 | BIC_Pkgpc9 | BIC_Pkgpc10 | BIC_CPU_LPI | BIC_SYS_LPI | BIC_Mod_c6 | BIC_Totl_c0 | BIC_Any_c0 | BIC_GFX_c0 | BIC_CPUGFX | BIC_SAM_mc6) #define BIC_OTHER ( BIC_IRQ | BIC_SMI | BIC_ThreadC | BIC_CoreTmp | BIC_IPC) #define BIC_DISABLED_BY_DEFAULT (BIC_USEC | BIC_TOD | BIC_APIC | BIC_X2APIC) @@ -277,6 +283,9 @@ enum gfx_sysfs_idx { GFX_rc6, GFX_MHz, GFX_ACTMHz, + SAM_mc6, + SAM_MHz, + SAM_ACTMHz, GFX_MAX }; @@ -1193,6 +1202,9 @@ struct pkg_data { long long gfx_rc6_ms; unsigned int gfx_mhz; unsigned int gfx_act_mhz; + long long sam_mc6_ms; + unsigned int sam_mhz; + unsigned int sam_act_mhz; unsigned int package_id; struct rapl_counter energy_pkg; /* MSR_PKG_ENERGY_STATUS */ struct rapl_counter energy_dram; /* MSR_DRAM_ENERGY_STATUS */ @@ -1844,6 +1856,15 @@ void print_header(char *delim) if (DO_BIC(BIC_GFXACTMHz)) outp += sprintf(outp, "%sGFXAMHz", (printed++ ? delim : "")); + if (DO_BIC(BIC_SAM_mc6)) + outp += sprintf(outp, "%sSAM%%mc6", (printed++ ? delim : "")); + + if (DO_BIC(BIC_SAMMHz)) + outp += sprintf(outp, "%sSAMMHz", (printed++ ? delim : "")); + + if (DO_BIC(BIC_SAMACTMHz)) + outp += sprintf(outp, "%sSAMAMHz", (printed++ ? delim : "")); + if (DO_BIC(BIC_Totl_c0)) outp += sprintf(outp, "%sTotl%%C0", (printed++ ? delim : "")); if (DO_BIC(BIC_Any_c0)) @@ -2251,6 +2272,24 @@ int format_counters(struct thread_data *t, struct core_data *c, struct pkg_data if (DO_BIC(BIC_GFXACTMHz)) outp += sprintf(outp, "%s%d", (printed++ ? delim : ""), p->gfx_act_mhz); + /* SAMmc6 */ + if (DO_BIC(BIC_SAM_mc6)) { + if (p->sam_mc6_ms == -1) { /* detect GFX counter reset */ + outp += sprintf(outp, "%s**.**", (printed++ ? delim : "")); + } else { + outp += sprintf(outp, "%s%.2f", (printed++ ? delim : ""), + p->sam_mc6_ms / 10.0 / interval_float); + } + } + + /* SAMMHz */ + if (DO_BIC(BIC_SAMMHz)) + outp += sprintf(outp, "%s%d", (printed++ ? delim : ""), p->sam_mhz); + + /* SAMACTMHz */ + if (DO_BIC(BIC_SAMACTMHz)) + outp += sprintf(outp, "%s%d", (printed++ ? delim : ""), p->sam_act_mhz); + /* Totl%C0, Any%C0 GFX%C0 CPUGFX% */ if (DO_BIC(BIC_Totl_c0)) outp += sprintf(outp, "%s%.2f", (printed++ ? delim : ""), 100.0 * p->pkg_wtd_core_c0 / tsc); @@ -2437,6 +2476,15 @@ int delta_package(struct pkg_data *new, struct pkg_data *old) old->gfx_mhz = new->gfx_mhz; old->gfx_act_mhz = new->gfx_act_mhz; + /* flag an error when mc6 counter resets/wraps */ + if (old->sam_mc6_ms > new->sam_mc6_ms) + old->sam_mc6_ms = -1; + else + old->sam_mc6_ms = new->sam_mc6_ms - old->sam_mc6_ms; + + old->sam_mhz = new->sam_mhz; + old->sam_act_mhz = new->sam_act_mhz; + old->energy_pkg.raw_value = new->energy_pkg.raw_value - old->energy_pkg.raw_value; old->energy_cores.raw_value = new->energy_cores.raw_value - old->energy_cores.raw_value; old->energy_gfx.raw_value = new->energy_gfx.raw_value - old->energy_gfx.raw_value; @@ -2661,6 +2709,9 @@ void clear_counters(struct thread_data *t, struct core_data *c, struct pkg_data p->uncore_mhz = 0; p->gfx_mhz = 0; p->gfx_act_mhz = 0; + p->sam_mc6_ms = 0; + p->sam_mhz = 0; + p->sam_act_mhz = 0; for (i = 0, mp = sys.tp; mp; i++, mp = mp->next) t->counter[i] = 0; @@ -2775,6 +2826,9 @@ int sum_counters(struct thread_data *t, struct core_data *c, struct pkg_data *p) average.packages.uncore_mhz = p->uncore_mhz; average.packages.gfx_mhz = p->gfx_mhz; average.packages.gfx_act_mhz = p->gfx_act_mhz; + average.packages.sam_mc6_ms = p->sam_mc6_ms; + average.packages.sam_mhz = p->sam_mhz; + average.packages.sam_act_mhz = p->sam_act_mhz; average.packages.pkg_temp_c = MAX(average.packages.pkg_temp_c, p->pkg_temp_c); @@ -3572,19 +3626,28 @@ int get_counters(struct thread_data *t, struct core_data *c, struct pkg_data *p) p->pkg_temp_c = tj_max - ((msr >> 16) & 0x7F); } - if (DO_BIC(BIC_GFX_rc6)) - p->gfx_rc6_ms = gfx_info[GFX_rc6].val_ull; - /* n.b. assume die0 uncore frequency applies to whole package */ if (DO_BIC(BIC_UNCORE_MHZ)) p->uncore_mhz = get_uncore_mhz(p->package_id, 0); + if (DO_BIC(BIC_GFX_rc6)) + p->gfx_rc6_ms = gfx_info[GFX_rc6].val_ull; + if (DO_BIC(BIC_GFXMHz)) p->gfx_mhz = gfx_info[GFX_MHz].val; if (DO_BIC(BIC_GFXACTMHz)) p->gfx_act_mhz = gfx_info[GFX_ACTMHz].val; + if (DO_BIC(BIC_SAM_mc6)) + p->sam_mc6_ms = gfx_info[SAM_mc6].val_ull; + + if (DO_BIC(BIC_SAMMHz)) + p->sam_mhz = gfx_info[SAM_MHz].val; + + if (DO_BIC(BIC_SAMACTMHz)) + p->sam_act_mhz = gfx_info[SAM_ACTMHz].val; + for (i = 0, mp = sys.pp; mp; i++, mp = mp->next) { if (get_mp(cpu, mp, &p->counter[i])) return -10; @@ -4634,6 +4697,7 @@ int snapshot_graphics(int idx) switch (idx) { case GFX_rc6: + case SAM_mc6: fp = fopen_or_die(gfx_info[idx].path, "r"); retval = fscanf(fp, "%lld", &gfx_info[idx].val_ull); if (retval != 1) @@ -4642,6 +4706,8 @@ int snapshot_graphics(int idx) return 0; case GFX_MHz: case GFX_ACTMHz: + case SAM_MHz: + case SAM_ACTMHz: if (gfx_info[idx].fp == NULL) { gfx_info[idx].fp = fopen_or_die(gfx_info[idx].path, "r"); } else { @@ -4727,6 +4793,15 @@ int snapshot_proc_sysfs_files(void) if (DO_BIC(BIC_GFXACTMHz)) snapshot_graphics(GFX_ACTMHz); + if (DO_BIC(BIC_SAM_mc6)) + snapshot_graphics(SAM_mc6); + + if (DO_BIC(BIC_SAMMHz)) + snapshot_graphics(SAM_MHz); + + if (DO_BIC(BIC_SAMACTMHz)) + snapshot_graphics(SAM_ACTMHz); + if (DO_BIC(BIC_CPU_LPI)) snapshot_cpu_lpi_us(); @@ -5325,6 +5400,12 @@ static void probe_graphics(void) BIC_PRESENT(BIC_GFXMHz); if (gfx_info[GFX_ACTMHz].path) BIC_PRESENT(BIC_GFXACTMHz); + if (gfx_info[SAM_mc6].path) + BIC_PRESENT(BIC_SAM_mc6); + if (gfx_info[SAM_MHz].path) + BIC_PRESENT(BIC_SAMMHz); + if (gfx_info[SAM_ACTMHz].path) + BIC_PRESENT(BIC_SAMACTMHz); } static void dump_sysfs_cstate_config(void) -- cgit v1.2.3 From dc02dc937a3ef819c5da10e97084af6977be26bf Mon Sep 17 00:00:00 2001 From: Zhang Rui Date: Fri, 22 Mar 2024 09:52:24 +0800 Subject: tools/power/turbostat: Add support for new i915 sysfs knobs On Meteorlake platform, i915 driver supports the traditional graphics sysfs knobs including /sys/class/drm/card0/power/rc6_residency_ms /sys/class/drm/card0/gt_cur_freq_mhz /sys/class/drm/card0/gt_act_freq_mhz At the same time, it also supports /sys/class/drm/card0/gt/gt0/rc6_residency_ms /sys/class/drm/card0/gt/gt0/rps_cur_freq_mhz /sys/class/drm/card0/gt/gt0/rps_act_freq_mhz /sys/class/drm/card0/gt/gt1/rc6_residency_ms /sys/class/drm/card0/gt/gt1/rps_cur_freq_mhz /sys/class/drm/card0/gt/gt1/rps_act_freq_mhz gt0 is for GFX and gt1 is for SA Media. Enhance turbostat to prefer the i915 new sysfs knobs. Export gt0 via BIC_GFX_rc6/BIC_GFXMHz/BIC_GFXACTMHz. Export gt1 via BIC_SMA_mc6/BIC_SMAMHz/BIC_SMAACTMHz. Signed-off-by: Zhang Rui --- tools/power/x86/turbostat/turbostat.c | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/tools/power/x86/turbostat/turbostat.c b/tools/power/x86/turbostat/turbostat.c index 4fa2810da1a3..feca7f4cb5cd 100644 --- a/tools/power/x86/turbostat/turbostat.c +++ b/tools/power/x86/turbostat/turbostat.c @@ -5380,6 +5380,29 @@ probe_cluster: static void probe_graphics(void) { + /* New i915 graphics sysfs knobs */ + if (!access("/sys/class/drm/card0/gt/gt0/rc6_residency_ms", R_OK)) { + gfx_info[GFX_rc6].path = "/sys/class/drm/card0/gt/gt0/rc6_residency_ms"; + + if (!access("/sys/class/drm/card0/gt/gt0/rps_cur_freq_mhz", R_OK)) + gfx_info[GFX_MHz].path = "/sys/class/drm/card0/gt/gt0/rps_cur_freq_mhz"; + + if (!access("/sys/class/drm/card0/gt/gt0/rps_act_freq_mhz", R_OK)) + gfx_info[GFX_ACTMHz].path = "/sys/class/drm/card0/gt/gt0/rps_act_freq_mhz"; + + if (!access("/sys/class/drm/card0/gt/gt1/rc6_residency_ms", R_OK)) + gfx_info[SAM_mc6].path = "/sys/class/drm/card0/gt/gt1/rc6_residency_ms"; + + if (!access("/sys/class/drm/card0/gt/gt1/rps_cur_freq_mhz", R_OK)) + gfx_info[SAM_MHz].path = "/sys/class/drm/card0/gt/gt1/rps_cur_freq_mhz"; + + if (!access("/sys/class/drm/card0/gt/gt1/rps_act_freq_mhz", R_OK)) + gfx_info[SAM_ACTMHz].path = "/sys/class/drm/card0/gt/gt1/rps_act_freq_mhz"; + + goto end; + } + + /* Fall back to traditional i915 graphics sysfs knobs */ if (!access("/sys/class/drm/card0/power/rc6_residency_ms", R_OK)) gfx_info[GFX_rc6].path = "/sys/class/drm/card0/power/rc6_residency_ms"; @@ -5394,6 +5417,7 @@ static void probe_graphics(void) else if (!access("/sys/class/graphics/fb0/device/drm/card0/gt_act_freq_mhz", R_OK)) gfx_info[GFX_ACTMHz].path = "/sys/class/graphics/fb0/device/drm/card0/gt_act_freq_mhz"; +end: if (gfx_info[GFX_rc6].path) BIC_PRESENT(BIC_GFX_rc6); if (gfx_info[GFX_MHz].path) -- cgit v1.2.3 From 91a91d389543a86963beec148d98d37875154bd4 Mon Sep 17 00:00:00 2001 From: Zhang Rui Date: Tue, 12 Mar 2024 23:56:02 +0800 Subject: tools/power/turbostat: Add support for Xe sysfs knobs Xe graphics driver uses different graphics sysfs knobs including /sys/class/drm/card0/device/tile0/gt0/gtidle/idle_residency_ms /sys/class/drm/card0/device/tile0/gt0/freq0/cur_freq /sys/class/drm/card0/device/tile0/gt0/freq0/act_freq /sys/class/drm/card0/device/tile0/gt1/gtidle/idle_residency_ms /sys/class/drm/card0/device/tile0/gt1/freq0/cur_freq /sys/class/drm/card0/device/tile0/gt1/freq0/act_freq Plus that, /sys/class/drm/card0/device/tile0/gt/gtidle/name returns either gt-rc or gt-mc. rc is for GFX and mc is SA Media. Enhance turbostat to prefer the Xe sysfs knobs when they are available. Export gt-rc via BIC_GFX_rc6/BIC_GFXMHz/BIC_GFXACTMHz. Export gt-mc via BIC_SMA_mc6/BIC_SMAMHz/BIC_SMAACTMHz. Signed-off-by: Zhang Rui --- tools/power/x86/turbostat/turbostat.c | 51 +++++++++++++++++++++++++++++++++++ 1 file changed, 51 insertions(+) diff --git a/tools/power/x86/turbostat/turbostat.c b/tools/power/x86/turbostat/turbostat.c index feca7f4cb5cd..bc103851df70 100644 --- a/tools/power/x86/turbostat/turbostat.c +++ b/tools/power/x86/turbostat/turbostat.c @@ -5380,6 +5380,57 @@ probe_cluster: static void probe_graphics(void) { + /* Xe graphics sysfs knobs */ + if (!access("/sys/class/drm/card0/device/tile0/gt0/gtidle/idle_residency_ms", R_OK)) { + FILE *fp; + char buf[8]; + bool gt0_is_gt; + int idx; + + fp = fopen("/sys/class/drm/card0/device/tile0/gt0/gtidle/name", "r"); + if (!fp) + goto next; + + if (!fread(buf, sizeof(char), 7, fp)) { + fclose(fp); + goto next; + } + fclose(fp); + + if (!strncmp(buf, "gt0-rc", strlen("gt0-rc"))) + gt0_is_gt = true; + else if (!strncmp(buf, "gt0-mc", strlen("gt0-mc"))) + gt0_is_gt = false; + else + goto next; + + idx = gt0_is_gt ? GFX_rc6 : SAM_mc6; + gfx_info[idx].path = "/sys/class/drm/card0/device/tile0/gt0/gtidle/idle_residency_ms"; + + idx = gt0_is_gt ? GFX_MHz : SAM_MHz; + if (!access("/sys/class/drm/card0/device/tile0/gt0/freq0/cur_freq", R_OK)) + gfx_info[idx].path = "/sys/class/drm/card0/device/tile0/gt0/freq0/cur_freq"; + + idx = gt0_is_gt ? GFX_ACTMHz : SAM_ACTMHz; + if (!access("/sys/class/drm/card0/device/tile0/gt0/freq0/act_freq", R_OK)) + gfx_info[idx].path = "/sys/class/drm/card0/device/tile0/gt0/freq0/act_freq"; + + idx = gt0_is_gt ? SAM_mc6 : GFX_rc6; + if (!access("/sys/class/drm/card0/device/tile0/gt1/gtidle/idle_residency_ms", R_OK)) + gfx_info[idx].path = "/sys/class/drm/card0/device/tile0/gt1/gtidle/idle_residency_ms"; + + idx = gt0_is_gt ? SAM_MHz : GFX_MHz; + if (!access("/sys/class/drm/card0/device/tile0/gt1/freq0/cur_freq", R_OK)) + gfx_info[idx].path = "/sys/class/drm/card0/device/tile0/gt1/freq0/cur_freq"; + + idx = gt0_is_gt ? SAM_ACTMHz : GFX_ACTMHz; + if (!access("/sys/class/drm/card0/device/tile0/gt1/freq0/act_freq", R_OK)) + gfx_info[idx].path = "/sys/class/drm/card0/device/tile0/gt1/freq0/act_freq"; + + goto end; + } + +next: /* New i915 graphics sysfs knobs */ if (!access("/sys/class/drm/card0/gt/gt0/rc6_residency_ms", R_OK)) { gfx_info[GFX_rc6].path = "/sys/class/drm/card0/gt/gt0/rc6_residency_ms"; -- cgit v1.2.3 From 3ab7296a7e6aa34634dcc2926af933107a117996 Mon Sep 17 00:00:00 2001 From: Len Brown Date: Mon, 8 Apr 2024 19:32:58 -0400 Subject: tools/power turbostat: v2024.04.10 Much of turbostat can now run with perf, rather than using the MSR driver Some of turbostat can now run as a regular non-root user. Add some new output columns for some new GFX hardware. [This patch updates the version, but otherwise changes no function; it touches up some checkpatch issues from previous patches] Signed-off-by: Len Brown --- MAINTAINERS | 1 + tools/power/x86/turbostat/turbostat.c | 41 ++++++++++++++++--------- tools/testing/selftests/turbostat/defcolumns.py | 1 + 3 files changed, 28 insertions(+), 15 deletions(-) diff --git a/MAINTAINERS b/MAINTAINERS index a7c4cf8201e0..b8582a466128 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -22116,6 +22116,7 @@ Q: https://patchwork.kernel.org/project/linux-pm/list/ B: https://bugzilla.kernel.org T: git git://git.kernel.org/pub/scm/linux/kernel/git/lenb/linux.git turbostat F: tools/power/x86/turbostat/ +F: tools/testing/selftests/turbostat/ TW5864 VIDEO4LINUX DRIVER M: Bluecherry Maintainers diff --git a/tools/power/x86/turbostat/turbostat.c b/tools/power/x86/turbostat/turbostat.c index bc103851df70..98256468e248 100644 --- a/tools/power/x86/turbostat/turbostat.c +++ b/tools/power/x86/turbostat/turbostat.c @@ -3,7 +3,7 @@ * turbostat -- show CPU frequency and C-state residency * on modern Intel and AMD processors. * - * Copyright (c) 2023 Intel Corporation. + * Copyright (c) 2024 Intel Corporation. * Len Brown */ @@ -1360,6 +1360,7 @@ struct sys_counters { void free_sys_counters(void) { struct msr_counter *p = sys.tp, *pnext = NULL; + while (p) { pnext = p->next; free(p); @@ -1979,6 +1980,7 @@ int dump_counters(struct thread_data *t, struct core_data *c, struct pkg_data *p const unsigned long long energy_value = c->core_energy.raw_value * c->core_energy.scale; const double energy_scale = c->core_energy.scale; + if (c->core_energy.unit == RAPL_UNIT_JOULES) outp += sprintf(outp, "Joules: %0llX (scale: %lf)\n", energy_value, energy_scale); @@ -3153,7 +3155,7 @@ static unsigned int read_perf_counter_info_n(const char *const path, const char return v; } -static unsigned read_msr_type(void) +static unsigned int read_msr_type(void) { const char *const path = "/sys/bus/event_source/devices/msr/type"; const char *const format = "%u"; @@ -3161,7 +3163,7 @@ static unsigned read_msr_type(void) return read_perf_counter_info_n(path, format); } -static unsigned read_aperf_config(void) +static unsigned int read_aperf_config(void) { const char *const path = "/sys/bus/event_source/devices/msr/events/aperf"; const char *const format = "event=%x"; @@ -3169,7 +3171,7 @@ static unsigned read_aperf_config(void) return read_perf_counter_info_n(path, format); } -static unsigned read_mperf_config(void) +static unsigned int read_mperf_config(void) { const char *const path = "/sys/bus/event_source/devices/msr/events/mperf"; const char *const format = "event=%x"; @@ -3177,7 +3179,7 @@ static unsigned read_mperf_config(void) return read_perf_counter_info_n(path, format); } -static unsigned read_perf_type(const char *subsys) +static unsigned int read_perf_type(const char *subsys) { const char *const path_format = "/sys/bus/event_source/devices/%s/type"; const char *const format = "%u"; @@ -3188,7 +3190,7 @@ static unsigned read_perf_type(const char *subsys) return read_perf_counter_info_n(path, format); } -static unsigned read_rapl_config(const char *subsys, const char *event_name) +static unsigned int read_rapl_config(const char *subsys, const char *event_name) { const char *const path_format = "/sys/bus/event_source/devices/%s/events/%s"; const char *const format = "event=%x"; @@ -3199,7 +3201,7 @@ static unsigned read_rapl_config(const char *subsys, const char *event_name) return read_perf_counter_info_n(path, format); } -static unsigned read_perf_rapl_unit(const char *subsys, const char *event_name) +static unsigned int read_perf_rapl_unit(const char *subsys, const char *event_name) { const char *const path_format = "/sys/bus/event_source/devices/%s/events/%s.unit"; const char *const format = "%s"; @@ -3235,7 +3237,7 @@ static struct amperf_group_fd open_amperf_fd(int cpu) const unsigned int msr_type = read_msr_type(); const unsigned int aperf_config = read_aperf_config(); const unsigned int mperf_config = read_mperf_config(); - struct amperf_group_fd fds = {.aperf = -1,.mperf = -1 }; + struct amperf_group_fd fds = {.aperf = -1, .mperf = -1 }; fds.aperf = open_perf_counter(cpu, msr_type, aperf_config, -1, PERF_FORMAT_GROUP); fds.mperf = open_perf_counter(cpu, msr_type, mperf_config, fds.aperf, PERF_FORMAT_GROUP); @@ -3277,6 +3279,7 @@ static int read_aperf_mperf_tsc_perf(struct thread_data *t, int cpu) t->tsc = rdtsc(); const int n = read(fd_amperf, &cnt.as_array[0], sizeof(cnt.as_array)); + if (n != sizeof(cnt.as_array)) return -2; @@ -3371,7 +3374,7 @@ int get_rapl_counters(int cpu, int domain, struct core_data *c, struct pkg_data struct rapl_counter_info_t *rci = &rapl_counter_info_perdomain[domain]; if (debug) - fprintf(stderr, "get_rapl_counters: cpu%d domain%d\n", cpu, domain); + fprintf(stderr, "%s: cpu%d domain%d\n", __func__, cpu, domain); assert(rapl_counter_info_perdomain); @@ -3382,8 +3385,9 @@ int get_rapl_counters(int cpu, int domain, struct core_data *c, struct pkg_data size_t num_perf_counters = rapl_counter_info_count_perf(rci); const ssize_t expected_read_size = (num_perf_counters + 1) * sizeof(unsigned long long); const ssize_t actual_read_size = read(rci->fd_perf, &perf_data[0], sizeof(perf_data)); + if (actual_read_size != expected_read_size) - err(-1, "get_rapl_counters: failed to read perf_data (%zu %zu)", expected_read_size, + err(-1, "%s: failed to read perf_data (%zu %zu)", __func__, expected_read_size, actual_read_size); } @@ -3454,7 +3458,7 @@ int get_counters(struct thread_data *t, struct core_data *c, struct pkg_data *p) int status; if (cpu_migrate(cpu)) { - fprintf(outf, "get_counters: Could not migrate to CPU %d\n", cpu); + fprintf(outf, "%s: Could not migrate to CPU %d\n", __func__, cpu); return -1; } @@ -6411,15 +6415,17 @@ int add_rapl_perf_counter_(int cpu, struct rapl_counter_info_t *rci, const struc return -1; const double scale = read_perf_rapl_scale(cai->perf_subsys, cai->perf_name); + if (scale == 0.0) return -1; const enum rapl_unit unit = read_perf_rapl_unit(cai->perf_subsys, cai->perf_name); + if (unit == RAPL_UNIT_INVALID) return -1; - const unsigned rapl_type = read_perf_type(cai->perf_subsys); - const unsigned rapl_energy_pkg_config = read_rapl_config(cai->perf_subsys, cai->perf_name); + const unsigned int rapl_type = read_perf_type(cai->perf_subsys); + const unsigned int rapl_energy_pkg_config = read_rapl_config(cai->perf_subsys, cai->perf_name); const int fd_counter = open_perf_counter(cpu, rapl_type, rapl_energy_pkg_config, rci->fd_perf, PERF_FORMAT_GROUP); @@ -6441,7 +6447,7 @@ int add_rapl_perf_counter(int cpu, struct rapl_counter_info_t *rci, const struct int ret = add_rapl_perf_counter_(cpu, rci, cai, scale, unit); if (debug) - fprintf(stderr, "add_rapl_perf_counter: %d (cpu: %d)\n", ret, cpu); + fprintf(stderr, "%s: %d (cpu: %d)\n", __func__, ret, cpu); return ret; } @@ -6462,6 +6468,7 @@ void linux_perf_init(void) } const bool aperf_required = is_aperf_access_required(); + if (aperf_required && has_aperf && amperf_source == AMPERF_SOURCE_PERF) { fd_amperf_percpu = calloc(topo.max_cpu_num + 1, sizeof(*fd_amperf_percpu)); if (fd_amperf_percpu == NULL) @@ -6483,6 +6490,7 @@ void rapl_perf_init(void) */ for (int domain_id = 0; domain_id < num_domains; ++domain_id) { struct rapl_counter_info_t *rci = &rapl_counter_info_perdomain[domain_id]; + rci->fd_perf = -1; for (size_t i = 0; i < NUM_RAPL_COUNTERS; ++i) { rci->data[i] = 0; @@ -7296,6 +7304,7 @@ static void set_amperf_source(void) amperf_source = AMPERF_SOURCE_PERF; const bool aperf_required = is_aperf_access_required(); + if (no_perf || !aperf_required || !has_amperf_access_via_perf()) amperf_source = AMPERF_SOURCE_MSR; @@ -7373,10 +7382,12 @@ void check_msr_access(void) void check_perf_access(void) { const bool intrcount_required = BIC_IS_ENABLED(BIC_IPC); + if (no_perf || !intrcount_required || !has_instr_count_access()) bic_enabled &= ~BIC_IPC; const bool aperf_required = is_aperf_access_required(); + if (!aperf_required || !has_amperf_access()) { bic_enabled &= ~BIC_Avg_MHz; bic_enabled &= ~BIC_Busy; @@ -7486,7 +7497,7 @@ int get_and_dump_counters(void) void print_version() { - fprintf(outf, "turbostat version 2023.11.07 - Len Brown \n"); + fprintf(outf, "turbostat version 2024.04.08 - Len Brown \n"); } #define COMMAND_LINE_SIZE 2048 diff --git a/tools/testing/selftests/turbostat/defcolumns.py b/tools/testing/selftests/turbostat/defcolumns.py index 70d3b7780311..d9b042097da7 100755 --- a/tools/testing/selftests/turbostat/defcolumns.py +++ b/tools/testing/selftests/turbostat/defcolumns.py @@ -1,4 +1,5 @@ #!/bin/env python3 +# SPDX-License-Identifier: GPL-2.0 import subprocess from shutil import which -- cgit v1.2.3 From 0871bc0129d403747ea0272a4384895d7ad37a6c Mon Sep 17 00:00:00 2001 From: Huacai Chen Date: Wed, 10 Apr 2024 21:08:51 +0800 Subject: mm: Move lowmem_page_address() a little later LoongArch will override page_to_virt() which use page_address() in the KFENCE case (by defining WANT_PAGE_VIRTUAL/HASHED_PAGE_VIRTUAL). So move lowmem_page_address() a little later to avoid such build errors: error: implicit declaration of function 'page_address'. Acked-by: Andrew Morton Signed-off-by: Huacai Chen --- include/linux/mm.h | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/include/linux/mm.h b/include/linux/mm.h index 0436b919f1c7..7b0ee64225de 100644 --- a/include/linux/mm.h +++ b/include/linux/mm.h @@ -2207,11 +2207,6 @@ static inline int arch_make_folio_accessible(struct folio *folio) */ #include -static __always_inline void *lowmem_page_address(const struct page *page) -{ - return page_to_virt(page); -} - #if defined(CONFIG_HIGHMEM) && !defined(WANT_PAGE_VIRTUAL) #define HASHED_PAGE_VIRTUAL #endif @@ -2234,6 +2229,11 @@ void set_page_address(struct page *page, void *virtual); void page_address_init(void); #endif +static __always_inline void *lowmem_page_address(const struct page *page) +{ + return page_to_virt(page); +} + #if !defined(HASHED_PAGE_VIRTUAL) && !defined(WANT_PAGE_VIRTUAL) #define page_address(page) lowmem_page_address(page) #define set_page_address(page, address) do { } while(0) -- cgit v1.2.3 From 0ca84aeaee150796d4b5577b1b0ae52a947e7813 Mon Sep 17 00:00:00 2001 From: Huacai Chen Date: Wed, 10 Apr 2024 21:08:51 +0800 Subject: LoongArch: Make {virt, phys, page, pfn} translation work with KFENCE KFENCE changes virt_to_page() to be able to translate tlb mapped virtual addresses, but forget to change virt_to_phys()/phys_to_virt() and other translation functions as well. This patch fix it, otherwise some drivers (such as nvme and virtio-blk) cannot work with KFENCE. All {virt, phys, page, pfn} translation functions are updated: 1, virt_to_pfn()/pfn_to_virt(); 2, virt_to_page()/page_to_virt(); 3, virt_to_phys()/phys_to_virt(). DMW/TLB mapped addresses are distinguished by comparing the vaddress with vm_map_base in virt_to_xyz(), and we define WANT_PAGE_VIRTUAL in the KFENCE case for the reverse translations, xyz_to_virt(). Signed-off-by: Huacai Chen --- arch/loongarch/include/asm/io.h | 20 +++++++++++++++----- arch/loongarch/include/asm/kfence.h | 9 +++++++++ arch/loongarch/include/asm/page.h | 26 +++++++++++++++++++++++++- arch/loongarch/mm/pgtable.c | 4 ++-- 4 files changed, 51 insertions(+), 8 deletions(-) diff --git a/arch/loongarch/include/asm/io.h b/arch/loongarch/include/asm/io.h index 4a8adcca329b..c2f9979b2979 100644 --- a/arch/loongarch/include/asm/io.h +++ b/arch/loongarch/include/asm/io.h @@ -14,11 +14,6 @@ #include #include -/* - * Change "struct page" to physical address. - */ -#define page_to_phys(page) ((phys_addr_t)page_to_pfn(page) << PAGE_SHIFT) - extern void __init __iomem *early_ioremap(u64 phys_addr, unsigned long size); extern void __init early_iounmap(void __iomem *addr, unsigned long size); @@ -73,6 +68,21 @@ extern void __memcpy_fromio(void *to, const volatile void __iomem *from, size_t #define __io_aw() mmiowb() +#ifdef CONFIG_KFENCE +#define virt_to_phys(kaddr) \ +({ \ + (likely((unsigned long)kaddr < vm_map_base)) ? __pa((unsigned long)kaddr) : \ + page_to_phys(tlb_virt_to_page((unsigned long)kaddr)) + offset_in_page((unsigned long)kaddr);\ +}) + +#define phys_to_virt(paddr) \ +({ \ + extern char *__kfence_pool; \ + (unlikely(__kfence_pool == NULL)) ? __va((unsigned long)paddr) : \ + page_address(phys_to_page((unsigned long)paddr)) + offset_in_page((unsigned long)paddr);\ +}) +#endif + #include #define ARCH_HAS_VALID_PHYS_ADDR_RANGE diff --git a/arch/loongarch/include/asm/kfence.h b/arch/loongarch/include/asm/kfence.h index 6c82aea1c993..a6a5760da3a3 100644 --- a/arch/loongarch/include/asm/kfence.h +++ b/arch/loongarch/include/asm/kfence.h @@ -16,6 +16,7 @@ static inline bool arch_kfence_init_pool(void) { int err; + char *kaddr, *vaddr; char *kfence_pool = __kfence_pool; struct vm_struct *area; @@ -35,6 +36,14 @@ static inline bool arch_kfence_init_pool(void) return false; } + kaddr = kfence_pool; + vaddr = __kfence_pool; + while (kaddr < kfence_pool + KFENCE_POOL_SIZE) { + set_page_address(virt_to_page(kaddr), vaddr); + kaddr += PAGE_SIZE; + vaddr += PAGE_SIZE; + } + return true; } diff --git a/arch/loongarch/include/asm/page.h b/arch/loongarch/include/asm/page.h index 44027060c54a..e85df33f11c7 100644 --- a/arch/loongarch/include/asm/page.h +++ b/arch/loongarch/include/asm/page.h @@ -78,7 +78,26 @@ typedef struct { unsigned long pgprot; } pgprot_t; struct page *dmw_virt_to_page(unsigned long kaddr); struct page *tlb_virt_to_page(unsigned long kaddr); -#define virt_to_pfn(kaddr) PFN_DOWN(PHYSADDR(kaddr)) +#define pfn_to_phys(pfn) __pfn_to_phys(pfn) +#define phys_to_pfn(paddr) __phys_to_pfn(paddr) + +#define page_to_phys(page) pfn_to_phys(page_to_pfn(page)) +#define phys_to_page(paddr) pfn_to_page(phys_to_pfn(paddr)) + +#ifndef CONFIG_KFENCE + +#define page_to_virt(page) __va(page_to_phys(page)) +#define virt_to_page(kaddr) phys_to_page(__pa(kaddr)) + +#else + +#define WANT_PAGE_VIRTUAL + +#define page_to_virt(page) \ +({ \ + extern char *__kfence_pool; \ + (__kfence_pool == NULL) ? __va(page_to_phys(page)) : page_address(page); \ +}) #define virt_to_page(kaddr) \ ({ \ @@ -86,6 +105,11 @@ struct page *tlb_virt_to_page(unsigned long kaddr); dmw_virt_to_page((unsigned long)kaddr) : tlb_virt_to_page((unsigned long)kaddr);\ }) +#endif + +#define pfn_to_virt(pfn) page_to_virt(pfn_to_page(pfn)) +#define virt_to_pfn(kaddr) page_to_pfn(virt_to_page(kaddr)) + extern int __virt_addr_valid(volatile void *kaddr); #define virt_addr_valid(kaddr) __virt_addr_valid((volatile void *)(kaddr)) diff --git a/arch/loongarch/mm/pgtable.c b/arch/loongarch/mm/pgtable.c index 2aae72e63871..bda018150000 100644 --- a/arch/loongarch/mm/pgtable.c +++ b/arch/loongarch/mm/pgtable.c @@ -11,13 +11,13 @@ struct page *dmw_virt_to_page(unsigned long kaddr) { - return pfn_to_page(virt_to_pfn(kaddr)); + return phys_to_page(__pa(kaddr)); } EXPORT_SYMBOL(dmw_virt_to_page); struct page *tlb_virt_to_page(unsigned long kaddr) { - return pfn_to_page(pte_pfn(*virt_to_kpte(kaddr))); + return phys_to_page(pfn_to_phys(pte_pfn(*virt_to_kpte(kaddr)))); } EXPORT_SYMBOL(tlb_virt_to_page); -- cgit v1.2.3 From 1a629fe4cca0fc4cf546b4ca2e9d4b75bbfde9ff Mon Sep 17 00:00:00 2001 From: Huacai Chen Date: Wed, 10 Apr 2024 21:08:51 +0800 Subject: LoongArch: Make virt_addr_valid()/__virt_addr_valid() work with KFENCE When enabling both CONFIG_KFENCE and CONFIG_DEBUG_SG, I get the following backtraces when running LongArch kernels. [ 2.496257] kernel BUG at include/linux/scatterlist.h:187! ... [ 2.501925] Call Trace: [ 2.501950] [<9000000004ad59c4>] sg_init_one+0xac/0xc0 [ 2.502204] [<9000000004a438f8>] do_test_kpp+0x278/0x6e4 [ 2.502353] [<9000000004a43dd4>] alg_test_kpp+0x70/0xf4 [ 2.502494] [<9000000004a41b48>] alg_test+0x128/0x690 [ 2.502631] [<9000000004a3d898>] cryptomgr_test+0x20/0x40 [ 2.502775] [<90000000041b4508>] kthread+0x138/0x158 [ 2.502912] [<9000000004161c48>] ret_from_kernel_thread+0xc/0xa4 The backtrace is always similar but not exactly the same. It is always triggered from cryptomgr_test, but not always from the same test. Analysis shows that with CONFIG_KFENCE active, the address returned from kmalloc() and friends is not always below vm_map_base. It is allocated by kfence_alloc() which at least sometimes seems to get its memory from an address space above vm_map_base. This causes __virt_addr_valid() to return false for the affected objects. Let __virt_addr_valid() return 1 for kfence pool addresses, this make virt_addr_valid()/__virt_addr_valid() work with KFENCE. Reported-by: Guenter Roeck Suggested-by: Guenter Roeck Signed-off-by: Huacai Chen --- arch/loongarch/mm/mmap.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/arch/loongarch/mm/mmap.c b/arch/loongarch/mm/mmap.c index a9630a81b38a..89af7c12e8c0 100644 --- a/arch/loongarch/mm/mmap.c +++ b/arch/loongarch/mm/mmap.c @@ -4,6 +4,7 @@ */ #include #include +#include #include #include #include @@ -111,6 +112,9 @@ int __virt_addr_valid(volatile void *kaddr) { unsigned long vaddr = (unsigned long)kaddr; + if (is_kfence_address((void *)kaddr)) + return 1; + if ((vaddr < PAGE_OFFSET) || (vaddr >= vm_map_base)) return 0; -- cgit v1.2.3 From ec2bbc575e44909fd333328537519145852927a6 Mon Sep 17 00:00:00 2001 From: Huacai Chen Date: Wed, 10 Apr 2024 21:08:51 +0800 Subject: LoongArch: Update dts for Loongson-2K1000 to support ISA/LPC Some Loongson-2K1000 platforms have ISA/LPC devices such as Super-IO, define an ISA node in the dts file to avoid access error. Signed-off-by: Huacai Chen --- arch/loongarch/boot/dts/loongson-2k1000.dtsi | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/arch/loongarch/boot/dts/loongson-2k1000.dtsi b/arch/loongarch/boot/dts/loongson-2k1000.dtsi index 49a70f8c3cab..b6aeb1f70e2a 100644 --- a/arch/loongarch/boot/dts/loongson-2k1000.dtsi +++ b/arch/loongarch/boot/dts/loongson-2k1000.dtsi @@ -100,6 +100,13 @@ #size-cells = <2>; dma-coherent; + isa@18000000 { + compatible = "isa"; + #size-cells = <1>; + #address-cells = <2>; + ranges = <1 0x0 0x0 0x18000000 0x4000>; + }; + liointc0: interrupt-controller@1fe01400 { compatible = "loongson,liointc-2.0"; reg = <0x0 0x1fe01400 0x0 0x40>, -- cgit v1.2.3 From b07b9f353d750ae503fc9fcbdc5f29dc38553605 Mon Sep 17 00:00:00 2001 From: Huacai Chen Date: Wed, 10 Apr 2024 21:08:51 +0800 Subject: LoongArch: Update dts for Loongson-2K2000 to support ISA/LPC Some Loongson-2K2000 platforms have ISA/LPC devices such as Super-IO, define an ISA node in the dts file to avoid access error. Also adjust the PCI io resource range to avoid confliction. Signed-off-by: Huacai Chen --- arch/loongarch/boot/dts/loongson-2k2000.dtsi | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/arch/loongarch/boot/dts/loongson-2k2000.dtsi b/arch/loongarch/boot/dts/loongson-2k2000.dtsi index a231949b5f55..dcee9f3783fd 100644 --- a/arch/loongarch/boot/dts/loongson-2k2000.dtsi +++ b/arch/loongarch/boot/dts/loongson-2k2000.dtsi @@ -51,6 +51,13 @@ #address-cells = <2>; #size-cells = <2>; + isa@18400000 { + compatible = "isa"; + #size-cells = <1>; + #address-cells = <2>; + ranges = <1 0x0 0x0 0x18400000 0x4000>; + }; + pmc: power-management@100d0000 { compatible = "loongson,ls2k2000-pmc", "loongson,ls2k0500-pmc", "syscon"; reg = <0x0 0x100d0000 0x0 0x58>; @@ -141,7 +148,7 @@ #size-cells = <2>; device_type = "pci"; bus-range = <0x0 0xff>; - ranges = <0x01000000 0x0 0x00008000 0x0 0x18400000 0x0 0x00008000>, + ranges = <0x01000000 0x0 0x00008000 0x0 0x18408000 0x0 0x00008000>, <0x02000000 0x0 0x60000000 0x0 0x60000000 0x0 0x20000000>; gmac0: ethernet@3,0 { -- cgit v1.2.3 From 84892cebdc7fd5d6d70ba5b667a7440dfed2d032 Mon Sep 17 00:00:00 2001 From: Huacai Chen Date: Wed, 10 Apr 2024 21:08:51 +0800 Subject: LoongArch: Update dts for Loongson-2K2000 to support PCI-MSI Current dts file for Loongson-2K2000 misses the interrupt-controller & interrupt-cells descriptions in the msi-controller node, and misses the msi-parent link in the pci root node. Add them to support PCI-MSI. Signed-off-by: Huacai Chen --- arch/loongarch/boot/dts/loongson-2k2000.dtsi | 3 +++ 1 file changed, 3 insertions(+) diff --git a/arch/loongarch/boot/dts/loongson-2k2000.dtsi b/arch/loongarch/boot/dts/loongson-2k2000.dtsi index dcee9f3783fd..481c6c869a8b 100644 --- a/arch/loongarch/boot/dts/loongson-2k2000.dtsi +++ b/arch/loongarch/boot/dts/loongson-2k2000.dtsi @@ -116,6 +116,8 @@ msi: msi-controller@1fe01140 { compatible = "loongson,pch-msi-1.0"; reg = <0x0 0x1fe01140 0x0 0x8>; + interrupt-controller; + #interrupt-cells = <1>; msi-controller; loongson,msi-base-vec = <64>; loongson,msi-num-vecs = <192>; @@ -147,6 +149,7 @@ #address-cells = <3>; #size-cells = <2>; device_type = "pci"; + msi-parent = <&msi>; bus-range = <0x0 0xff>; ranges = <0x01000000 0x0 0x00008000 0x0 0x18408000 0x0 0x00008000>, <0x02000000 0x0 0x60000000 0x0 0x60000000 0x0 0x20000000>; -- cgit v1.2.3 From 3744e0ee80251149135aac59870147e9ed6faae7 Mon Sep 17 00:00:00 2001 From: Huacai Chen Date: Wed, 10 Apr 2024 21:08:51 +0800 Subject: LoongArch: Update dts for Loongson-2K2000 to support GMAC/GNET Current dts file for Loongson-2K2000's GMAC/GNET is incomplete, both irq and phy descriptions are missing. Add them to make GMAC/GNET work. Signed-off-by: Huacai Chen --- arch/loongarch/boot/dts/loongson-2k2000-ref.dts | 33 +++++++++++++++++++++++++ arch/loongarch/boot/dts/loongson-2k2000.dtsi | 12 ++++++--- 2 files changed, 42 insertions(+), 3 deletions(-) diff --git a/arch/loongarch/boot/dts/loongson-2k2000-ref.dts b/arch/loongarch/boot/dts/loongson-2k2000-ref.dts index dca91caf895e..74b99bd234cc 100644 --- a/arch/loongarch/boot/dts/loongson-2k2000-ref.dts +++ b/arch/loongarch/boot/dts/loongson-2k2000-ref.dts @@ -61,12 +61,45 @@ &gmac0 { status = "okay"; + + phy-mode = "gmii"; + phy-handle = <&phy0>; + mdio { + compatible = "snps,dwmac-mdio"; + #address-cells = <1>; + #size-cells = <0>; + phy0: ethernet-phy@0 { + reg = <2>; + }; + }; }; &gmac1 { status = "okay"; + + phy-mode = "gmii"; + phy-handle = <&phy1>; + mdio { + compatible = "snps,dwmac-mdio"; + #address-cells = <1>; + #size-cells = <0>; + phy1: ethernet-phy@1 { + reg = <2>; + }; + }; }; &gmac2 { status = "okay"; + + phy-mode = "rgmii"; + phy-handle = <&phy2>; + mdio { + compatible = "snps,dwmac-mdio"; + #address-cells = <1>; + #size-cells = <0>; + phy2: ethernet-phy@2 { + reg = <0>; + }; + }; }; diff --git a/arch/loongarch/boot/dts/loongson-2k2000.dtsi b/arch/loongarch/boot/dts/loongson-2k2000.dtsi index 481c6c869a8b..9eab2d02cbe8 100644 --- a/arch/loongarch/boot/dts/loongson-2k2000.dtsi +++ b/arch/loongarch/boot/dts/loongson-2k2000.dtsi @@ -156,21 +156,27 @@ gmac0: ethernet@3,0 { reg = <0x1800 0x0 0x0 0x0 0x0>; - interrupts = <12 IRQ_TYPE_LEVEL_HIGH>; + interrupts = <12 IRQ_TYPE_LEVEL_HIGH>, + <13 IRQ_TYPE_LEVEL_HIGH>; + interrupt-names = "macirq", "eth_lpi"; interrupt-parent = <&pic>; status = "disabled"; }; gmac1: ethernet@3,1 { reg = <0x1900 0x0 0x0 0x0 0x0>; - interrupts = <14 IRQ_TYPE_LEVEL_HIGH>; + interrupts = <14 IRQ_TYPE_LEVEL_HIGH>, + <15 IRQ_TYPE_LEVEL_HIGH>; + interrupt-names = "macirq", "eth_lpi"; interrupt-parent = <&pic>; status = "disabled"; }; gmac2: ethernet@3,2 { reg = <0x1a00 0x0 0x0 0x0 0x0>; - interrupts = <17 IRQ_TYPE_LEVEL_HIGH>; + interrupts = <17 IRQ_TYPE_LEVEL_HIGH>, + <18 IRQ_TYPE_LEVEL_HIGH>; + interrupt-names = "macirq", "eth_lpi"; interrupt-parent = <&pic>; status = "disabled"; }; -- cgit v1.2.3 From a07c772fa658645887119184de48b255bf19a46e Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Wed, 10 Apr 2024 21:08:51 +0800 Subject: LoongArch: Include linux/sizes.h in addrspace.h to prevent build errors LoongArch's include/asm/addrspace.h uses SZ_32M and SZ_16K, so add to provide those macros to prevent build errors: In file included from ../arch/loongarch/include/asm/io.h:11, from ../include/linux/io.h:13, from ../include/linux/io-64-nonatomic-lo-hi.h:5, from ../drivers/cxl/pci.c:4: ../include/asm-generic/io.h: In function 'ioport_map': ../arch/loongarch/include/asm/addrspace.h:124:25: error: 'SZ_32M' undeclared (first use in this function); did you mean 'PS_32M'? 124 | #define PCI_IOSIZE SZ_32M Signed-off-by: Randy Dunlap Signed-off-by: Huacai Chen --- arch/loongarch/include/asm/addrspace.h | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/loongarch/include/asm/addrspace.h b/arch/loongarch/include/asm/addrspace.h index b24437e28c6e..7bd47d65bf7a 100644 --- a/arch/loongarch/include/asm/addrspace.h +++ b/arch/loongarch/include/asm/addrspace.h @@ -11,6 +11,7 @@ #define _ASM_ADDRSPACE_H #include +#include #include -- cgit v1.2.3 From a9025cd1c673a8d6eefc79d911075b8b452eba8f Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Mon, 8 Apr 2024 15:22:01 +0200 Subject: x86/topology: Don't update cpu_possible_map in topo_set_cpuids() topo_set_cpuids() updates cpu_present_map and cpu_possible map. It is invoked during enumeration and "physical hotplug" operations. In the latter case this results in a kernel crash because cpu_possible_map is marked read only after init completes. There is no reason to update cpu_possible_map in that function. During enumeration cpu_possible_map is not relevant and gets fully initialized after enumeration completed. On "physical hotplug" the bit is already set because the kernel allows only CPUs to be plugged which have been enumerated and associated to a CPU number during early boot. Remove the bogus update of cpu_possible_map. Fixes: 0e53e7b656cf ("x86/cpu/topology: Sanitize the APIC admission logic") Reported-by: Jonathan Cameron Signed-off-by: Thomas Gleixner Link: https://lore.kernel.org/r/87ttkc6kwx.ffs@tglx --- arch/x86/kernel/cpu/topology.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/arch/x86/kernel/cpu/topology.c b/arch/x86/kernel/cpu/topology.c index aaca8d235dc2..d17c9b71eb4a 100644 --- a/arch/x86/kernel/cpu/topology.c +++ b/arch/x86/kernel/cpu/topology.c @@ -123,7 +123,6 @@ static void topo_set_cpuids(unsigned int cpu, u32 apic_id, u32 acpi_id) early_per_cpu(x86_cpu_to_apicid, cpu) = apic_id; early_per_cpu(x86_cpu_to_acpiid, cpu) = acpi_id; #endif - set_cpu_possible(cpu, true); set_cpu_present(cpu, true); } @@ -210,7 +209,11 @@ static __init void topo_register_apic(u32 apic_id, u32 acpi_id, bool present) topo_info.nr_disabled_cpus++; } - /* Register present and possible CPUs in the domain maps */ + /* + * Register present and possible CPUs in the domain + * maps. cpu_possible_map will be updated in + * topology_init_possible_cpus() after enumeration is done. + */ for (dom = TOPO_SMT_DOMAIN; dom < TOPO_MAX_DOMAIN; dom++) set_bit(topo_apicid(apic_id, dom), apic_maps[dom].map); } -- cgit v1.2.3 From f337a6a21e2fd67eadea471e93d05dd37baaa9be Mon Sep 17 00:00:00 2001 From: Sean Christopherson Date: Tue, 9 Apr 2024 10:51:05 -0700 Subject: x86/cpu: Actually turn off mitigations by default for SPECULATION_MITIGATIONS=n MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Initialize cpu_mitigations to CPU_MITIGATIONS_OFF if the kernel is built with CONFIG_SPECULATION_MITIGATIONS=n, as the help text quite clearly states that disabling SPECULATION_MITIGATIONS is supposed to turn off all mitigations by default. │ If you say N, all mitigations will be disabled. You really │ should know what you are doing to say so. As is, the kernel still defaults to CPU_MITIGATIONS_AUTO, which results in some mitigations being enabled in spite of SPECULATION_MITIGATIONS=n. Fixes: f43b9876e857 ("x86/retbleed: Add fine grained Kconfig knobs") Signed-off-by: Sean Christopherson Signed-off-by: Ingo Molnar Reviewed-by: Daniel Sneddon Cc: stable@vger.kernel.org Cc: Linus Torvalds Link: https://lore.kernel.org/r/20240409175108.1512861-2-seanjc@google.com --- kernel/cpu.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/kernel/cpu.c b/kernel/cpu.c index 8f6affd051f7..07ad53b7f119 100644 --- a/kernel/cpu.c +++ b/kernel/cpu.c @@ -3207,7 +3207,8 @@ enum cpu_mitigations { }; static enum cpu_mitigations cpu_mitigations __ro_after_init = - CPU_MITIGATIONS_AUTO; + IS_ENABLED(CONFIG_SPECULATION_MITIGATIONS) ? CPU_MITIGATIONS_AUTO : + CPU_MITIGATIONS_OFF; static int __init mitigations_parse_cmdline(char *arg) { -- cgit v1.2.3 From 325f3fb551f8cd672dbbfc4cf58b14f9ee3fc9e8 Mon Sep 17 00:00:00 2001 From: Zheng Yejian Date: Wed, 10 Apr 2024 09:58:02 +0800 Subject: kprobes: Fix possible use-after-free issue on kprobe registration When unloading a module, its state is changing MODULE_STATE_LIVE -> MODULE_STATE_GOING -> MODULE_STATE_UNFORMED. Each change will take a time. `is_module_text_address()` and `__module_text_address()` works with MODULE_STATE_LIVE and MODULE_STATE_GOING. If we use `is_module_text_address()` and `__module_text_address()` separately, there is a chance that the first one is succeeded but the next one is failed because module->state becomes MODULE_STATE_UNFORMED between those operations. In `check_kprobe_address_safe()`, if the second `__module_text_address()` is failed, that is ignored because it expected a kernel_text address. But it may have failed simply because module->state has been changed to MODULE_STATE_UNFORMED. In this case, arm_kprobe() will try to modify non-exist module text address (use-after-free). To fix this problem, we should not use separated `is_module_text_address()` and `__module_text_address()`, but use only `__module_text_address()` once and do `try_module_get(module)` which is only available with MODULE_STATE_LIVE. Link: https://lore.kernel.org/all/20240410015802.265220-1-zhengyejian1@huawei.com/ Fixes: 28f6c37a2910 ("kprobes: Forbid probing on trampoline and BPF code areas") Cc: stable@vger.kernel.org Signed-off-by: Zheng Yejian Signed-off-by: Masami Hiramatsu (Google) --- kernel/kprobes.c | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/kernel/kprobes.c b/kernel/kprobes.c index 9d9095e81792..65adc815fc6e 100644 --- a/kernel/kprobes.c +++ b/kernel/kprobes.c @@ -1567,10 +1567,17 @@ static int check_kprobe_address_safe(struct kprobe *p, jump_label_lock(); preempt_disable(); - /* Ensure it is not in reserved area nor out of text */ - if (!(core_kernel_text((unsigned long) p->addr) || - is_module_text_address((unsigned long) p->addr)) || - in_gate_area_no_mm((unsigned long) p->addr) || + /* Ensure the address is in a text area, and find a module if exists. */ + *probed_mod = NULL; + if (!core_kernel_text((unsigned long) p->addr)) { + *probed_mod = __module_text_address((unsigned long) p->addr); + if (!(*probed_mod)) { + ret = -EINVAL; + goto out; + } + } + /* Ensure it is not in reserved area. */ + if (in_gate_area_no_mm((unsigned long) p->addr) || within_kprobe_blacklist((unsigned long) p->addr) || jump_label_text_reserved(p->addr, p->addr) || static_call_text_reserved(p->addr, p->addr) || @@ -1580,8 +1587,7 @@ static int check_kprobe_address_safe(struct kprobe *p, goto out; } - /* Check if 'p' is probing a module. */ - *probed_mod = __module_text_address((unsigned long) p->addr); + /* Get module refcount and reject __init functions for loaded modules. */ if (*probed_mod) { /* * We must hold a refcount of the probed module while updating -- cgit v1.2.3 From 4693b120299a5893034d1882ddbbe08af1d2ff07 Mon Sep 17 00:00:00 2001 From: Richard Fitzgerald Date: Wed, 10 Apr 2024 17:13:12 +0100 Subject: ASoC: wm_adsp: Include array_size.h Explicitly #include array_size.h for the ARRAY_SIZE() macro. Signed-off-by: Richard Fitzgerald Link: https://msgid.link/r/20240410161312.22313-1-rf@opensource.cirrus.com Signed-off-by: Mark Brown --- sound/soc/codecs/wm_adsp.c | 1 + 1 file changed, 1 insertion(+) diff --git a/sound/soc/codecs/wm_adsp.c b/sound/soc/codecs/wm_adsp.c index 6e348d49a89c..c9d9a7b28efb 100644 --- a/sound/soc/codecs/wm_adsp.c +++ b/sound/soc/codecs/wm_adsp.c @@ -7,6 +7,7 @@ * Author: Mark Brown */ +#include #include #include #include -- cgit v1.2.3 From 28d31ffac3d3ef6d60c4eb392a47d5e19dbb15e8 Mon Sep 17 00:00:00 2001 From: Richard Fitzgerald Date: Wed, 10 Apr 2024 17:08:33 +0100 Subject: ASoC: cs35l56: Include array_size.h Explicitly #include array_size.h for the source files that use ARRAY_SIZE(). Signed-off-by: Richard Fitzgerald Link: https://msgid.link/r/20240410160833.20837-1-rf@opensource.cirrus.com Signed-off-by: Mark Brown --- sound/soc/codecs/cs35l56-shared.c | 1 + sound/soc/codecs/cs35l56.c | 1 + 2 files changed, 2 insertions(+) diff --git a/sound/soc/codecs/cs35l56-shared.c b/sound/soc/codecs/cs35l56-shared.c index 08cac58e3ab2..ac2a760aeae1 100644 --- a/sound/soc/codecs/cs35l56-shared.c +++ b/sound/soc/codecs/cs35l56-shared.c @@ -5,6 +5,7 @@ // Copyright (C) 2023 Cirrus Logic, Inc. and // Cirrus Logic International Semiconductor Ltd. +#include #include #include #include diff --git a/sound/soc/codecs/cs35l56.c b/sound/soc/codecs/cs35l56.c index 8d2f021fb362..5a0b55e31e3c 100644 --- a/sound/soc/codecs/cs35l56.c +++ b/sound/soc/codecs/cs35l56.c @@ -6,6 +6,7 @@ // Cirrus Logic International Semiconductor Ltd. #include +#include #include #include #include -- cgit v1.2.3 From e3ba51ab24fddef79fc212f9840de54db8fd1685 Mon Sep 17 00:00:00 2001 From: Gavin Shan Date: Fri, 5 Apr 2024 13:58:50 +1000 Subject: arm64: tlb: Fix TLBI RANGE operand KVM/arm64 relies on TLBI RANGE feature to flush TLBs when the dirty pages are collected by VMM and the page table entries become write protected during live migration. Unfortunately, the operand passed to the TLBI RANGE instruction isn't correctly sorted out due to the commit 117940aa6e5f ("KVM: arm64: Define kvm_tlb_flush_vmid_range()"). It leads to crash on the destination VM after live migration because TLBs aren't flushed completely and some of the dirty pages are missed. For example, I have a VM where 8GB memory is assigned, starting from 0x40000000 (1GB). Note that the host has 4KB as the base page size. In the middile of migration, kvm_tlb_flush_vmid_range() is executed to flush TLBs. It passes MAX_TLBI_RANGE_PAGES as the argument to __kvm_tlb_flush_vmid_range() and __flush_s2_tlb_range_op(). SCALE#3 and NUM#31, corresponding to MAX_TLBI_RANGE_PAGES, isn't supported by __TLBI_RANGE_NUM(). In this specific case, -1 has been returned from __TLBI_RANGE_NUM() for SCALE#3/2/1/0 and rejected by the loop in the __flush_tlb_range_op() until the variable @scale underflows and becomes -9, 0xffff708000040000 is set as the operand. The operand is wrong since it's sorted out by __TLBI_VADDR_RANGE() according to invalid @scale and @num. Fix it by extending __TLBI_RANGE_NUM() to support the combination of SCALE#3 and NUM#31. With the changes, [-1 31] instead of [-1 30] can be returned from the macro, meaning the TLBs for 0x200000 pages in the above example can be flushed in one shoot with SCALE#3 and NUM#31. The macro TLBI_RANGE_MASK is dropped since no one uses it any more. The comments are also adjusted accordingly. Fixes: 117940aa6e5f ("KVM: arm64: Define kvm_tlb_flush_vmid_range()") Cc: stable@kernel.org # v6.6+ Reported-by: Yihuang Yu Suggested-by: Marc Zyngier Signed-off-by: Gavin Shan Reviewed-by: Catalin Marinas Reviewed-by: Ryan Roberts Reviewed-by: Anshuman Khandual Reviewed-by: Shaoqin Huang Link: https://lore.kernel.org/r/20240405035852.1532010-2-gshan@redhat.com Signed-off-by: Catalin Marinas --- arch/arm64/include/asm/tlbflush.h | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/arch/arm64/include/asm/tlbflush.h b/arch/arm64/include/asm/tlbflush.h index 3b0e8248e1a4..a75de2665d84 100644 --- a/arch/arm64/include/asm/tlbflush.h +++ b/arch/arm64/include/asm/tlbflush.h @@ -161,12 +161,18 @@ static inline unsigned long get_trans_granule(void) #define MAX_TLBI_RANGE_PAGES __TLBI_RANGE_PAGES(31, 3) /* - * Generate 'num' values from -1 to 30 with -1 rejected by the - * __flush_tlb_range() loop below. + * Generate 'num' values from -1 to 31 with -1 rejected by the + * __flush_tlb_range() loop below. Its return value is only + * significant for a maximum of MAX_TLBI_RANGE_PAGES pages. If + * 'pages' is more than that, you must iterate over the overall + * range. */ -#define TLBI_RANGE_MASK GENMASK_ULL(4, 0) -#define __TLBI_RANGE_NUM(pages, scale) \ - ((((pages) >> (5 * (scale) + 1)) & TLBI_RANGE_MASK) - 1) +#define __TLBI_RANGE_NUM(pages, scale) \ + ({ \ + int __pages = min((pages), \ + __TLBI_RANGE_PAGES(31, (scale))); \ + (__pages >> (5 * (scale) + 1)) - 1; \ + }) /* * TLB Invalidation @@ -379,10 +385,6 @@ static inline void arch_tlbbatch_flush(struct arch_tlbflush_unmap_batch *batch) * 3. If there is 1 page remaining, flush it through non-range operations. Range * operations can only span an even number of pages. We save this for last to * ensure 64KB start alignment is maintained for the LPA2 case. - * - * Note that certain ranges can be represented by either num = 31 and - * scale or num = 0 and scale + 1. The loop below favours the latter - * since num is limited to 30 by the __TLBI_RANGE_NUM() macro. */ #define __flush_tlb_range_op(op, start, pages, stride, \ asid, tlb_level, tlbi_user, lpa2) \ -- cgit v1.2.3 From b37cab587aa3c9ab29c6b10aa55627dad713011f Mon Sep 17 00:00:00 2001 From: Luiz Augusto von Dentz Date: Wed, 13 Mar 2024 15:43:18 -0400 Subject: Bluetooth: ISO: Don't reject BT_ISO_QOS if parameters are unset Consider certain values (0x00) as unset and load proper default if an application has not set them properly. Fixes: 0fe8c8d07134 ("Bluetooth: Split bt_iso_qos into dedicated structures") Signed-off-by: Luiz Augusto von Dentz --- net/bluetooth/iso.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/net/bluetooth/iso.c b/net/bluetooth/iso.c index c8793e57f4b5..d24148ea883c 100644 --- a/net/bluetooth/iso.c +++ b/net/bluetooth/iso.c @@ -1451,8 +1451,8 @@ static bool check_ucast_qos(struct bt_iso_qos *qos) static bool check_bcast_qos(struct bt_iso_qos *qos) { - if (qos->bcast.sync_factor == 0x00) - return false; + if (!qos->bcast.sync_factor) + qos->bcast.sync_factor = 0x01; if (qos->bcast.packing > 0x01) return false; @@ -1475,6 +1475,9 @@ static bool check_bcast_qos(struct bt_iso_qos *qos) if (qos->bcast.skip > 0x01f3) return false; + if (!qos->bcast.sync_timeout) + qos->bcast.sync_timeout = BT_ISO_SYNC_TIMEOUT; + if (qos->bcast.sync_timeout < 0x000a || qos->bcast.sync_timeout > 0x4000) return false; @@ -1484,6 +1487,9 @@ static bool check_bcast_qos(struct bt_iso_qos *qos) if (qos->bcast.mse > 0x1f) return false; + if (!qos->bcast.timeout) + qos->bcast.sync_timeout = BT_ISO_SYNC_TIMEOUT; + if (qos->bcast.timeout < 0x000a || qos->bcast.timeout > 0x4000) return false; -- cgit v1.2.3 From 53cb4197e63ab2363aa28c3029061e4d516e7626 Mon Sep 17 00:00:00 2001 From: Luiz Augusto von Dentz Date: Thu, 28 Mar 2024 15:58:10 -0400 Subject: Bluetooth: hci_sync: Fix using the same interval and window for Coded PHY Coded PHY recommended intervals are 3 time bigger than the 1M PHY so this aligns with that by multiplying by 3 the values given to 1M PHY since the code already used recommended values for that. Fixes: 288c90224eec ("Bluetooth: Enable all supported LE PHY by default") Signed-off-by: Luiz Augusto von Dentz --- net/bluetooth/hci_sync.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/net/bluetooth/hci_sync.c b/net/bluetooth/hci_sync.c index 8fe02921adf1..c5d8799046cc 100644 --- a/net/bluetooth/hci_sync.c +++ b/net/bluetooth/hci_sync.c @@ -2814,8 +2814,8 @@ static int hci_le_set_ext_scan_param_sync(struct hci_dev *hdev, u8 type, if (qos->bcast.in.phy & BT_ISO_PHY_CODED) { cp->scanning_phys |= LE_SCAN_PHY_CODED; hci_le_scan_phy_params(phy, type, - interval, - window); + interval * 3, + window * 3); num_phy++; phy++; } @@ -2835,7 +2835,7 @@ static int hci_le_set_ext_scan_param_sync(struct hci_dev *hdev, u8 type, if (scan_coded(hdev)) { cp->scanning_phys |= LE_SCAN_PHY_CODED; - hci_le_scan_phy_params(phy, type, interval, window); + hci_le_scan_phy_params(phy, type, interval * 3, window * 3); num_phy++; phy++; } -- cgit v1.2.3 From 45d355a926ab40f3ae7bc0b0a00cb0e3e8a5a810 Mon Sep 17 00:00:00 2001 From: Dmitry Antipov Date: Tue, 2 Apr 2024 14:32:05 +0300 Subject: Bluetooth: Fix memory leak in hci_req_sync_complete() In 'hci_req_sync_complete()', always free the previous sync request state before assigning reference to a new one. Reported-by: syzbot+39ec16ff6cc18b1d066d@syzkaller.appspotmail.com Closes: https://syzkaller.appspot.com/bug?extid=39ec16ff6cc18b1d066d Cc: stable@vger.kernel.org Fixes: f60cb30579d3 ("Bluetooth: Convert hci_req_sync family of function to new request API") Signed-off-by: Dmitry Antipov Signed-off-by: Luiz Augusto von Dentz --- net/bluetooth/hci_request.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/net/bluetooth/hci_request.c b/net/bluetooth/hci_request.c index 00e02138003e..efea25eb56ce 100644 --- a/net/bluetooth/hci_request.c +++ b/net/bluetooth/hci_request.c @@ -105,8 +105,10 @@ void hci_req_sync_complete(struct hci_dev *hdev, u8 result, u16 opcode, if (hdev->req_status == HCI_REQ_PEND) { hdev->req_result = result; hdev->req_status = HCI_REQ_DONE; - if (skb) + if (skb) { + kfree_skb(hdev->req_skb); hdev->req_skb = skb_get(skb); + } wake_up_interruptible(&hdev->req_wait_q); } } -- cgit v1.2.3 From 51eda36d33e43201e7a4fd35232e069b2c850b01 Mon Sep 17 00:00:00 2001 From: Luiz Augusto von Dentz Date: Fri, 5 Apr 2024 15:41:52 -0400 Subject: Bluetooth: SCO: Fix not validating setsockopt user input syzbot reported sco_sock_setsockopt() is copying data without checking user input length. BUG: KASAN: slab-out-of-bounds in copy_from_sockptr_offset include/linux/sockptr.h:49 [inline] BUG: KASAN: slab-out-of-bounds in copy_from_sockptr include/linux/sockptr.h:55 [inline] BUG: KASAN: slab-out-of-bounds in sco_sock_setsockopt+0xc0b/0xf90 net/bluetooth/sco.c:893 Read of size 4 at addr ffff88805f7b15a3 by task syz-executor.5/12578 Fixes: ad10b1a48754 ("Bluetooth: Add Bluetooth socket voice option") Fixes: b96e9c671b05 ("Bluetooth: Add BT_DEFER_SETUP option to sco socket") Fixes: 00398e1d5183 ("Bluetooth: Add support for BT_PKT_STATUS CMSG data for SCO connections") Fixes: f6873401a608 ("Bluetooth: Allow setting of codec for HFP offload use case") Reported-by: syzbot Signed-off-by: Eric Dumazet Signed-off-by: Luiz Augusto von Dentz --- include/net/bluetooth/bluetooth.h | 9 +++++++++ net/bluetooth/sco.c | 23 ++++++++++------------- 2 files changed, 19 insertions(+), 13 deletions(-) diff --git a/include/net/bluetooth/bluetooth.h b/include/net/bluetooth/bluetooth.h index 9fe95a22abeb..eaec5d6caa29 100644 --- a/include/net/bluetooth/bluetooth.h +++ b/include/net/bluetooth/bluetooth.h @@ -585,6 +585,15 @@ static inline struct sk_buff *bt_skb_sendmmsg(struct sock *sk, return skb; } +static inline int bt_copy_from_sockptr(void *dst, size_t dst_size, + sockptr_t src, size_t src_size) +{ + if (dst_size > src_size) + return -EINVAL; + + return copy_from_sockptr(dst, src, dst_size); +} + int bt_to_errno(u16 code); __u8 bt_status(int err); diff --git a/net/bluetooth/sco.c b/net/bluetooth/sco.c index 43daf965a01e..368e026f4d15 100644 --- a/net/bluetooth/sco.c +++ b/net/bluetooth/sco.c @@ -824,7 +824,7 @@ static int sco_sock_setsockopt(struct socket *sock, int level, int optname, sockptr_t optval, unsigned int optlen) { struct sock *sk = sock->sk; - int len, err = 0; + int err = 0; struct bt_voice voice; u32 opt; struct bt_codecs *codecs; @@ -843,10 +843,9 @@ static int sco_sock_setsockopt(struct socket *sock, int level, int optname, break; } - if (copy_from_sockptr(&opt, optval, sizeof(u32))) { - err = -EFAULT; + err = bt_copy_from_sockptr(&opt, sizeof(opt), optval, optlen); + if (err) break; - } if (opt) set_bit(BT_SK_DEFER_SETUP, &bt_sk(sk)->flags); @@ -863,11 +862,10 @@ static int sco_sock_setsockopt(struct socket *sock, int level, int optname, voice.setting = sco_pi(sk)->setting; - len = min_t(unsigned int, sizeof(voice), optlen); - if (copy_from_sockptr(&voice, optval, len)) { - err = -EFAULT; + err = bt_copy_from_sockptr(&voice, sizeof(voice), optval, + optlen); + if (err) break; - } /* Explicitly check for these values */ if (voice.setting != BT_VOICE_TRANSPARENT && @@ -890,10 +888,9 @@ static int sco_sock_setsockopt(struct socket *sock, int level, int optname, break; case BT_PKT_STATUS: - if (copy_from_sockptr(&opt, optval, sizeof(u32))) { - err = -EFAULT; + err = bt_copy_from_sockptr(&opt, sizeof(opt), optval, optlen); + if (err) break; - } if (opt) set_bit(BT_SK_PKT_STATUS, &bt_sk(sk)->flags); @@ -934,9 +931,9 @@ static int sco_sock_setsockopt(struct socket *sock, int level, int optname, break; } - if (copy_from_sockptr(buffer, optval, optlen)) { + err = bt_copy_from_sockptr(buffer, optlen, optval, optlen); + if (err) { hci_dev_put(hdev); - err = -EFAULT; break; } -- cgit v1.2.3 From a97de7bff13b1cc825c1b1344eaed8d6c2d3e695 Mon Sep 17 00:00:00 2001 From: Luiz Augusto von Dentz Date: Fri, 5 Apr 2024 15:43:45 -0400 Subject: Bluetooth: RFCOMM: Fix not validating setsockopt user input syzbot reported rfcomm_sock_setsockopt_old() is copying data without checking user input length. BUG: KASAN: slab-out-of-bounds in copy_from_sockptr_offset include/linux/sockptr.h:49 [inline] BUG: KASAN: slab-out-of-bounds in copy_from_sockptr include/linux/sockptr.h:55 [inline] BUG: KASAN: slab-out-of-bounds in rfcomm_sock_setsockopt_old net/bluetooth/rfcomm/sock.c:632 [inline] BUG: KASAN: slab-out-of-bounds in rfcomm_sock_setsockopt+0x893/0xa70 net/bluetooth/rfcomm/sock.c:673 Read of size 4 at addr ffff8880209a8bc3 by task syz-executor632/5064 Fixes: 9f2c8a03fbb3 ("Bluetooth: Replace RFCOMM link mode with security level") Fixes: bb23c0ab8246 ("Bluetooth: Add support for deferring RFCOMM connection setup") Reported-by: syzbot Signed-off-by: Eric Dumazet Signed-off-by: Luiz Augusto von Dentz --- net/bluetooth/rfcomm/sock.c | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/net/bluetooth/rfcomm/sock.c b/net/bluetooth/rfcomm/sock.c index b54e8a530f55..29aa07e9db9d 100644 --- a/net/bluetooth/rfcomm/sock.c +++ b/net/bluetooth/rfcomm/sock.c @@ -629,7 +629,7 @@ static int rfcomm_sock_setsockopt_old(struct socket *sock, int optname, switch (optname) { case RFCOMM_LM: - if (copy_from_sockptr(&opt, optval, sizeof(u32))) { + if (bt_copy_from_sockptr(&opt, sizeof(opt), optval, optlen)) { err = -EFAULT; break; } @@ -664,7 +664,6 @@ static int rfcomm_sock_setsockopt(struct socket *sock, int level, int optname, struct sock *sk = sock->sk; struct bt_security sec; int err = 0; - size_t len; u32 opt; BT_DBG("sk %p", sk); @@ -686,11 +685,9 @@ static int rfcomm_sock_setsockopt(struct socket *sock, int level, int optname, sec.level = BT_SECURITY_LOW; - len = min_t(unsigned int, sizeof(sec), optlen); - if (copy_from_sockptr(&sec, optval, len)) { - err = -EFAULT; + err = bt_copy_from_sockptr(&sec, sizeof(sec), optval, optlen); + if (err) break; - } if (sec.level > BT_SECURITY_HIGH) { err = -EINVAL; @@ -706,10 +703,9 @@ static int rfcomm_sock_setsockopt(struct socket *sock, int level, int optname, break; } - if (copy_from_sockptr(&opt, optval, sizeof(u32))) { - err = -EFAULT; + err = bt_copy_from_sockptr(&opt, sizeof(opt), optval, optlen); + if (err) break; - } if (opt) set_bit(BT_SK_DEFER_SETUP, &bt_sk(sk)->flags); -- cgit v1.2.3 From 4f3951242ace5efc7131932e2e01e6ac6baed846 Mon Sep 17 00:00:00 2001 From: Luiz Augusto von Dentz Date: Fri, 5 Apr 2024 15:50:47 -0400 Subject: Bluetooth: L2CAP: Fix not validating setsockopt user input Check user input length before copying data. Fixes: 33575df7be67 ("Bluetooth: move l2cap_sock_setsockopt() to l2cap_sock.c") Fixes: 3ee7b7cd8390 ("Bluetooth: Add BT_MODE socket option") Signed-off-by: Eric Dumazet Signed-off-by: Luiz Augusto von Dentz --- net/bluetooth/l2cap_sock.c | 52 ++++++++++++++++++---------------------------- 1 file changed, 20 insertions(+), 32 deletions(-) diff --git a/net/bluetooth/l2cap_sock.c b/net/bluetooth/l2cap_sock.c index 4287aa6cc988..e7d810b23082 100644 --- a/net/bluetooth/l2cap_sock.c +++ b/net/bluetooth/l2cap_sock.c @@ -727,7 +727,7 @@ static int l2cap_sock_setsockopt_old(struct socket *sock, int optname, struct sock *sk = sock->sk; struct l2cap_chan *chan = l2cap_pi(sk)->chan; struct l2cap_options opts; - int len, err = 0; + int err = 0; u32 opt; BT_DBG("sk %p", sk); @@ -754,11 +754,9 @@ static int l2cap_sock_setsockopt_old(struct socket *sock, int optname, opts.max_tx = chan->max_tx; opts.txwin_size = chan->tx_win; - len = min_t(unsigned int, sizeof(opts), optlen); - if (copy_from_sockptr(&opts, optval, len)) { - err = -EFAULT; + err = bt_copy_from_sockptr(&opts, sizeof(opts), optval, optlen); + if (err) break; - } if (opts.txwin_size > L2CAP_DEFAULT_EXT_WINDOW) { err = -EINVAL; @@ -801,10 +799,9 @@ static int l2cap_sock_setsockopt_old(struct socket *sock, int optname, break; case L2CAP_LM: - if (copy_from_sockptr(&opt, optval, sizeof(u32))) { - err = -EFAULT; + err = bt_copy_from_sockptr(&opt, sizeof(opt), optval, optlen); + if (err) break; - } if (opt & L2CAP_LM_FIPS) { err = -EINVAL; @@ -885,7 +882,7 @@ static int l2cap_sock_setsockopt(struct socket *sock, int level, int optname, struct bt_security sec; struct bt_power pwr; struct l2cap_conn *conn; - int len, err = 0; + int err = 0; u32 opt; u16 mtu; u8 mode; @@ -911,11 +908,9 @@ static int l2cap_sock_setsockopt(struct socket *sock, int level, int optname, sec.level = BT_SECURITY_LOW; - len = min_t(unsigned int, sizeof(sec), optlen); - if (copy_from_sockptr(&sec, optval, len)) { - err = -EFAULT; + err = bt_copy_from_sockptr(&sec, sizeof(sec), optval, optlen); + if (err) break; - } if (sec.level < BT_SECURITY_LOW || sec.level > BT_SECURITY_FIPS) { @@ -960,10 +955,9 @@ static int l2cap_sock_setsockopt(struct socket *sock, int level, int optname, break; } - if (copy_from_sockptr(&opt, optval, sizeof(u32))) { - err = -EFAULT; + err = bt_copy_from_sockptr(&opt, sizeof(opt), optval, optlen); + if (err) break; - } if (opt) { set_bit(BT_SK_DEFER_SETUP, &bt_sk(sk)->flags); @@ -975,10 +969,9 @@ static int l2cap_sock_setsockopt(struct socket *sock, int level, int optname, break; case BT_FLUSHABLE: - if (copy_from_sockptr(&opt, optval, sizeof(u32))) { - err = -EFAULT; + err = bt_copy_from_sockptr(&opt, sizeof(opt), optval, optlen); + if (err) break; - } if (opt > BT_FLUSHABLE_ON) { err = -EINVAL; @@ -1010,11 +1003,9 @@ static int l2cap_sock_setsockopt(struct socket *sock, int level, int optname, pwr.force_active = BT_POWER_FORCE_ACTIVE_ON; - len = min_t(unsigned int, sizeof(pwr), optlen); - if (copy_from_sockptr(&pwr, optval, len)) { - err = -EFAULT; + err = bt_copy_from_sockptr(&pwr, sizeof(pwr), optval, optlen); + if (err) break; - } if (pwr.force_active) set_bit(FLAG_FORCE_ACTIVE, &chan->flags); @@ -1023,10 +1014,9 @@ static int l2cap_sock_setsockopt(struct socket *sock, int level, int optname, break; case BT_CHANNEL_POLICY: - if (copy_from_sockptr(&opt, optval, sizeof(u32))) { - err = -EFAULT; + err = bt_copy_from_sockptr(&opt, sizeof(opt), optval, optlen); + if (err) break; - } err = -EOPNOTSUPP; break; @@ -1055,10 +1045,9 @@ static int l2cap_sock_setsockopt(struct socket *sock, int level, int optname, break; } - if (copy_from_sockptr(&mtu, optval, sizeof(u16))) { - err = -EFAULT; + err = bt_copy_from_sockptr(&mtu, sizeof(mtu), optval, optlen); + if (err) break; - } if (chan->mode == L2CAP_MODE_EXT_FLOWCTL && sk->sk_state == BT_CONNECTED) @@ -1086,10 +1075,9 @@ static int l2cap_sock_setsockopt(struct socket *sock, int level, int optname, break; } - if (copy_from_sockptr(&mode, optval, sizeof(u8))) { - err = -EFAULT; + err = bt_copy_from_sockptr(&mode, sizeof(mode), optval, optlen); + if (err) break; - } BT_DBG("mode %u", mode); -- cgit v1.2.3 From 9e8742cdfc4b0e65266bb4a901a19462bda9285e Mon Sep 17 00:00:00 2001 From: Luiz Augusto von Dentz Date: Fri, 5 Apr 2024 15:56:50 -0400 Subject: Bluetooth: ISO: Fix not validating setsockopt user input Check user input length before copying data. Fixes: ccf74f2390d6 ("Bluetooth: Add BTPROTO_ISO socket type") Fixes: 0731c5ab4d51 ("Bluetooth: ISO: Add support for BT_PKT_STATUS") Fixes: f764a6c2c1e4 ("Bluetooth: ISO: Add broadcast support") Signed-off-by: Eric Dumazet Signed-off-by: Luiz Augusto von Dentz --- net/bluetooth/iso.c | 36 ++++++++++++------------------------ 1 file changed, 12 insertions(+), 24 deletions(-) diff --git a/net/bluetooth/iso.c b/net/bluetooth/iso.c index d24148ea883c..ef0cc80b4c0c 100644 --- a/net/bluetooth/iso.c +++ b/net/bluetooth/iso.c @@ -1500,7 +1500,7 @@ static int iso_sock_setsockopt(struct socket *sock, int level, int optname, sockptr_t optval, unsigned int optlen) { struct sock *sk = sock->sk; - int len, err = 0; + int err = 0; struct bt_iso_qos qos = default_qos; u32 opt; @@ -1515,10 +1515,9 @@ static int iso_sock_setsockopt(struct socket *sock, int level, int optname, break; } - if (copy_from_sockptr(&opt, optval, sizeof(u32))) { - err = -EFAULT; + err = bt_copy_from_sockptr(&opt, sizeof(opt), optval, optlen); + if (err) break; - } if (opt) set_bit(BT_SK_DEFER_SETUP, &bt_sk(sk)->flags); @@ -1527,10 +1526,9 @@ static int iso_sock_setsockopt(struct socket *sock, int level, int optname, break; case BT_PKT_STATUS: - if (copy_from_sockptr(&opt, optval, sizeof(u32))) { - err = -EFAULT; + err = bt_copy_from_sockptr(&opt, sizeof(opt), optval, optlen); + if (err) break; - } if (opt) set_bit(BT_SK_PKT_STATUS, &bt_sk(sk)->flags); @@ -1545,17 +1543,9 @@ static int iso_sock_setsockopt(struct socket *sock, int level, int optname, break; } - len = min_t(unsigned int, sizeof(qos), optlen); - - if (copy_from_sockptr(&qos, optval, len)) { - err = -EFAULT; - break; - } - - if (len == sizeof(qos.ucast) && !check_ucast_qos(&qos)) { - err = -EINVAL; + err = bt_copy_from_sockptr(&qos, sizeof(qos), optval, optlen); + if (err) break; - } iso_pi(sk)->qos = qos; iso_pi(sk)->qos_user_set = true; @@ -1570,18 +1560,16 @@ static int iso_sock_setsockopt(struct socket *sock, int level, int optname, } if (optlen > sizeof(iso_pi(sk)->base)) { - err = -EOVERFLOW; + err = -EINVAL; break; } - len = min_t(unsigned int, sizeof(iso_pi(sk)->base), optlen); - - if (copy_from_sockptr(iso_pi(sk)->base, optval, len)) { - err = -EFAULT; + err = bt_copy_from_sockptr(iso_pi(sk)->base, optlen, optval, + optlen); + if (err) break; - } - iso_pi(sk)->base_len = len; + iso_pi(sk)->base_len = optlen; break; -- cgit v1.2.3 From b2186061d6043d6345a97100460363e990af0d46 Mon Sep 17 00:00:00 2001 From: Luiz Augusto von Dentz Date: Fri, 5 Apr 2024 16:46:50 -0400 Subject: Bluetooth: hci_sock: Fix not validating setsockopt user input Check user input length before copying data. Fixes: 09572fca7223 ("Bluetooth: hci_sock: Add support for BT_{SND,RCV}BUF") Signed-off-by: Luiz Augusto von Dentz --- net/bluetooth/hci_sock.c | 21 ++++++++------------- 1 file changed, 8 insertions(+), 13 deletions(-) diff --git a/net/bluetooth/hci_sock.c b/net/bluetooth/hci_sock.c index 4ee1b976678b..703b84bd48d5 100644 --- a/net/bluetooth/hci_sock.c +++ b/net/bluetooth/hci_sock.c @@ -1946,10 +1946,9 @@ static int hci_sock_setsockopt_old(struct socket *sock, int level, int optname, switch (optname) { case HCI_DATA_DIR: - if (copy_from_sockptr(&opt, optval, sizeof(opt))) { - err = -EFAULT; + err = bt_copy_from_sockptr(&opt, sizeof(opt), optval, len); + if (err) break; - } if (opt) hci_pi(sk)->cmsg_mask |= HCI_CMSG_DIR; @@ -1958,10 +1957,9 @@ static int hci_sock_setsockopt_old(struct socket *sock, int level, int optname, break; case HCI_TIME_STAMP: - if (copy_from_sockptr(&opt, optval, sizeof(opt))) { - err = -EFAULT; + err = bt_copy_from_sockptr(&opt, sizeof(opt), optval, len); + if (err) break; - } if (opt) hci_pi(sk)->cmsg_mask |= HCI_CMSG_TSTAMP; @@ -1979,11 +1977,9 @@ static int hci_sock_setsockopt_old(struct socket *sock, int level, int optname, uf.event_mask[1] = *((u32 *) f->event_mask + 1); } - len = min_t(unsigned int, len, sizeof(uf)); - if (copy_from_sockptr(&uf, optval, len)) { - err = -EFAULT; + err = bt_copy_from_sockptr(&uf, sizeof(uf), optval, len); + if (err) break; - } if (!capable(CAP_NET_RAW)) { uf.type_mask &= hci_sec_filter.type_mask; @@ -2042,10 +2038,9 @@ static int hci_sock_setsockopt(struct socket *sock, int level, int optname, goto done; } - if (copy_from_sockptr(&opt, optval, sizeof(opt))) { - err = -EFAULT; + err = bt_copy_from_sockptr(&opt, sizeof(opt), optval, len); + if (err) break; - } hci_pi(sk)->mtu = opt; break; -- cgit v1.2.3 From 600b0bbe73d3a9a264694da0e4c2c0800309141e Mon Sep 17 00:00:00 2001 From: Archie Pusaka Date: Thu, 4 Apr 2024 18:50:23 +0800 Subject: Bluetooth: l2cap: Don't double set the HCI_CONN_MGMT_CONNECTED bit The bit is set and tested inside mgmt_device_connected(), therefore we must not set it just outside the function. Fixes: eeda1bf97bb5 ("Bluetooth: hci_event: Fix not indicating new connection for BIG Sync") Signed-off-by: Archie Pusaka Reviewed-by: Manish Mandlik Signed-off-by: Luiz Augusto von Dentz --- net/bluetooth/l2cap_core.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c index 467b242d8be0..dc0897408793 100644 --- a/net/bluetooth/l2cap_core.c +++ b/net/bluetooth/l2cap_core.c @@ -4054,8 +4054,7 @@ static int l2cap_connect_req(struct l2cap_conn *conn, return -EPROTO; hci_dev_lock(hdev); - if (hci_dev_test_flag(hdev, HCI_MGMT) && - !test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &hcon->flags)) + if (hci_dev_test_flag(hdev, HCI_MGMT)) mgmt_device_connected(hdev, hcon, NULL, 0); hci_dev_unlock(hdev); -- cgit v1.2.3 From 5284984a4fbacb0883bfebe905902cdda2891a07 Mon Sep 17 00:00:00 2001 From: Adrian Hunter Date: Wed, 10 Apr 2024 18:32:12 +0300 Subject: bug: Fix no-return-statement warning with !CONFIG_BUG MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit BUG() does not return, and arch implementations of BUG() use unreachable() or other non-returning code. However with !CONFIG_BUG, the default implementation is often used instead, and that does not do that. x86 always uses its own implementation, but powerpc with !CONFIG_BUG gives a build error: kernel/time/timekeeping.c: In function ‘timekeeping_debug_get_ns’: kernel/time/timekeeping.c:286:1: error: no return statement in function returning non-void [-Werror=return-type] Add unreachable() to default !CONFIG_BUG BUG() implementation. Fixes: e8e9d21a5df6 ("timekeeping: Refactor timekeeping helpers") Reported-by: Naresh Kamboju Signed-off-by: Adrian Hunter Signed-off-by: Thomas Gleixner Tested-by: Linux Kernel Functional Testing Link: https://lore.kernel.org/r/20240410153212.127477-1-adrian.hunter@intel.com Closes: https://lore.kernel.org/all/CA+G9fYvjdZCW=7ZGxS6A_3bysjQ56YF7S-+PNLQ_8a4DKh1Bhg@mail.gmail.com/ --- include/asm-generic/bug.h | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/include/asm-generic/bug.h b/include/asm-generic/bug.h index 6e794420bd39..b7de3a4eade1 100644 --- a/include/asm-generic/bug.h +++ b/include/asm-generic/bug.h @@ -156,7 +156,10 @@ extern __printf(1, 2) void __warn_printk(const char *fmt, ...); #else /* !CONFIG_BUG */ #ifndef HAVE_ARCH_BUG -#define BUG() do {} while (1) +#define BUG() do { \ + do {} while (1); \ + unreachable(); \ +} while (0) #endif #ifndef HAVE_ARCH_BUG_ON -- cgit v1.2.3 From 076361362122a6d8a4c45f172ced5576b2d4a50d Mon Sep 17 00:00:00 2001 From: John Stultz Date: Tue, 9 Apr 2024 13:22:12 -0700 Subject: selftests: timers: Fix valid-adjtimex signed left-shift undefined behavior The struct adjtimex freq field takes a signed value who's units are in shifted (<<16) parts-per-million. Unfortunately for negative adjustments, the straightforward use of: freq = ppm << 16 trips undefined behavior warnings with clang: valid-adjtimex.c:66:6: warning: shifting a negative signed value is undefined [-Wshift-negative-value] -499<<16, ~~~~^ valid-adjtimex.c:67:6: warning: shifting a negative signed value is undefined [-Wshift-negative-value] -450<<16, ~~~~^ .. Fix it by using a multiply by (1 << 16) instead of shifting negative values in the valid-adjtimex test case. Align the values for better readability. Reported-by: Lee Jones Reported-by: Muhammad Usama Anjum Signed-off-by: John Stultz Signed-off-by: Thomas Gleixner Reviewed-by: Muhammad Usama Anjum Link: https://lore.kernel.org/r/20240409202222.2830476-1-jstultz@google.com Link: https://lore.kernel.org/lkml/0c6d4f0d-2064-4444-986b-1d1ed782135f@collabora.com/ --- tools/testing/selftests/timers/valid-adjtimex.c | 73 ++++++++++++------------- 1 file changed, 36 insertions(+), 37 deletions(-) diff --git a/tools/testing/selftests/timers/valid-adjtimex.c b/tools/testing/selftests/timers/valid-adjtimex.c index 48b9a803235a..d13ebde20322 100644 --- a/tools/testing/selftests/timers/valid-adjtimex.c +++ b/tools/testing/selftests/timers/valid-adjtimex.c @@ -21,9 +21,6 @@ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. */ - - - #include #include #include @@ -62,45 +59,47 @@ int clear_time_state(void) #define NUM_FREQ_OUTOFRANGE 4 #define NUM_FREQ_INVALID 2 +#define SHIFTED_PPM (1 << 16) + long valid_freq[NUM_FREQ_VALID] = { - -499<<16, - -450<<16, - -400<<16, - -350<<16, - -300<<16, - -250<<16, - -200<<16, - -150<<16, - -100<<16, - -75<<16, - -50<<16, - -25<<16, - -10<<16, - -5<<16, - -1<<16, + -499 * SHIFTED_PPM, + -450 * SHIFTED_PPM, + -400 * SHIFTED_PPM, + -350 * SHIFTED_PPM, + -300 * SHIFTED_PPM, + -250 * SHIFTED_PPM, + -200 * SHIFTED_PPM, + -150 * SHIFTED_PPM, + -100 * SHIFTED_PPM, + -75 * SHIFTED_PPM, + -50 * SHIFTED_PPM, + -25 * SHIFTED_PPM, + -10 * SHIFTED_PPM, + -5 * SHIFTED_PPM, + -1 * SHIFTED_PPM, -1000, - 1<<16, - 5<<16, - 10<<16, - 25<<16, - 50<<16, - 75<<16, - 100<<16, - 150<<16, - 200<<16, - 250<<16, - 300<<16, - 350<<16, - 400<<16, - 450<<16, - 499<<16, + 1 * SHIFTED_PPM, + 5 * SHIFTED_PPM, + 10 * SHIFTED_PPM, + 25 * SHIFTED_PPM, + 50 * SHIFTED_PPM, + 75 * SHIFTED_PPM, + 100 * SHIFTED_PPM, + 150 * SHIFTED_PPM, + 200 * SHIFTED_PPM, + 250 * SHIFTED_PPM, + 300 * SHIFTED_PPM, + 350 * SHIFTED_PPM, + 400 * SHIFTED_PPM, + 450 * SHIFTED_PPM, + 499 * SHIFTED_PPM, }; long outofrange_freq[NUM_FREQ_OUTOFRANGE] = { - -1000<<16, - -550<<16, - 550<<16, - 1000<<16, + -1000 * SHIFTED_PPM, + -550 * SHIFTED_PPM, + 550 * SHIFTED_PPM, + 1000 * SHIFTED_PPM, }; #define LONG_MAX (~0UL>>1) -- cgit v1.2.3 From d9ea7a3f66a5c7e1a2f73cf4b20f5eff3ced4ff8 Mon Sep 17 00:00:00 2001 From: Li Zhijian Date: Tue, 19 Mar 2024 11:43:50 +0800 Subject: hv: vmbus: Convert sprintf() family to sysfs_emit() family Per filesystems/sysfs.rst, show() should only use sysfs_emit() or sysfs_emit_at() when formatting the value to be returned to user space. Coccinelle complains that there are still a couple of functions that use snprintf(). Convert them to sysfs_emit(). sprintf() and scnprintf() will be converted as well if these files have such abused cases. This patch is generated by make coccicheck M= MODE=patch \ COCCI=scripts/coccinelle/api/device_attr_show.cocci No functional change intended. CC: "K. Y. Srinivasan" CC: Haiyang Zhang CC: Wei Liu CC: Dexuan Cui CC: linux-hyperv@vger.kernel.org Signed-off-by: Li Zhijian Link: https://lore.kernel.org/r/20240319034350.1574454-1-lizhijian@fujitsu.com Signed-off-by: Wei Liu Message-ID: <20240319034350.1574454-1-lizhijian@fujitsu.com> --- drivers/hv/vmbus_drv.c | 94 ++++++++++++++++++++++---------------------------- 1 file changed, 42 insertions(+), 52 deletions(-) diff --git a/drivers/hv/vmbus_drv.c b/drivers/hv/vmbus_drv.c index 7f7965f3d187..121f1ab32b51 100644 --- a/drivers/hv/vmbus_drv.c +++ b/drivers/hv/vmbus_drv.c @@ -131,7 +131,7 @@ static ssize_t id_show(struct device *dev, struct device_attribute *dev_attr, if (!hv_dev->channel) return -ENODEV; - return sprintf(buf, "%d\n", hv_dev->channel->offermsg.child_relid); + return sysfs_emit(buf, "%d\n", hv_dev->channel->offermsg.child_relid); } static DEVICE_ATTR_RO(id); @@ -142,7 +142,7 @@ static ssize_t state_show(struct device *dev, struct device_attribute *dev_attr, if (!hv_dev->channel) return -ENODEV; - return sprintf(buf, "%d\n", hv_dev->channel->state); + return sysfs_emit(buf, "%d\n", hv_dev->channel->state); } static DEVICE_ATTR_RO(state); @@ -153,7 +153,7 @@ static ssize_t monitor_id_show(struct device *dev, if (!hv_dev->channel) return -ENODEV; - return sprintf(buf, "%d\n", hv_dev->channel->offermsg.monitorid); + return sysfs_emit(buf, "%d\n", hv_dev->channel->offermsg.monitorid); } static DEVICE_ATTR_RO(monitor_id); @@ -164,8 +164,8 @@ static ssize_t class_id_show(struct device *dev, if (!hv_dev->channel) return -ENODEV; - return sprintf(buf, "{%pUl}\n", - &hv_dev->channel->offermsg.offer.if_type); + return sysfs_emit(buf, "{%pUl}\n", + &hv_dev->channel->offermsg.offer.if_type); } static DEVICE_ATTR_RO(class_id); @@ -176,8 +176,8 @@ static ssize_t device_id_show(struct device *dev, if (!hv_dev->channel) return -ENODEV; - return sprintf(buf, "{%pUl}\n", - &hv_dev->channel->offermsg.offer.if_instance); + return sysfs_emit(buf, "{%pUl}\n", + &hv_dev->channel->offermsg.offer.if_instance); } static DEVICE_ATTR_RO(device_id); @@ -186,7 +186,7 @@ static ssize_t modalias_show(struct device *dev, { struct hv_device *hv_dev = device_to_hv_device(dev); - return sprintf(buf, "vmbus:%*phN\n", UUID_SIZE, &hv_dev->dev_type); + return sysfs_emit(buf, "vmbus:%*phN\n", UUID_SIZE, &hv_dev->dev_type); } static DEVICE_ATTR_RO(modalias); @@ -199,7 +199,7 @@ static ssize_t numa_node_show(struct device *dev, if (!hv_dev->channel) return -ENODEV; - return sprintf(buf, "%d\n", cpu_to_node(hv_dev->channel->target_cpu)); + return sysfs_emit(buf, "%d\n", cpu_to_node(hv_dev->channel->target_cpu)); } static DEVICE_ATTR_RO(numa_node); #endif @@ -212,9 +212,8 @@ static ssize_t server_monitor_pending_show(struct device *dev, if (!hv_dev->channel) return -ENODEV; - return sprintf(buf, "%d\n", - channel_pending(hv_dev->channel, - vmbus_connection.monitor_pages[0])); + return sysfs_emit(buf, "%d\n", channel_pending(hv_dev->channel, + vmbus_connection.monitor_pages[0])); } static DEVICE_ATTR_RO(server_monitor_pending); @@ -226,9 +225,8 @@ static ssize_t client_monitor_pending_show(struct device *dev, if (!hv_dev->channel) return -ENODEV; - return sprintf(buf, "%d\n", - channel_pending(hv_dev->channel, - vmbus_connection.monitor_pages[1])); + return sysfs_emit(buf, "%d\n", channel_pending(hv_dev->channel, + vmbus_connection.monitor_pages[1])); } static DEVICE_ATTR_RO(client_monitor_pending); @@ -240,9 +238,8 @@ static ssize_t server_monitor_latency_show(struct device *dev, if (!hv_dev->channel) return -ENODEV; - return sprintf(buf, "%d\n", - channel_latency(hv_dev->channel, - vmbus_connection.monitor_pages[0])); + return sysfs_emit(buf, "%d\n", channel_latency(hv_dev->channel, + vmbus_connection.monitor_pages[0])); } static DEVICE_ATTR_RO(server_monitor_latency); @@ -254,9 +251,8 @@ static ssize_t client_monitor_latency_show(struct device *dev, if (!hv_dev->channel) return -ENODEV; - return sprintf(buf, "%d\n", - channel_latency(hv_dev->channel, - vmbus_connection.monitor_pages[1])); + return sysfs_emit(buf, "%d\n", channel_latency(hv_dev->channel, + vmbus_connection.monitor_pages[1])); } static DEVICE_ATTR_RO(client_monitor_latency); @@ -268,9 +264,8 @@ static ssize_t server_monitor_conn_id_show(struct device *dev, if (!hv_dev->channel) return -ENODEV; - return sprintf(buf, "%d\n", - channel_conn_id(hv_dev->channel, - vmbus_connection.monitor_pages[0])); + return sysfs_emit(buf, "%d\n", channel_conn_id(hv_dev->channel, + vmbus_connection.monitor_pages[0])); } static DEVICE_ATTR_RO(server_monitor_conn_id); @@ -282,9 +277,8 @@ static ssize_t client_monitor_conn_id_show(struct device *dev, if (!hv_dev->channel) return -ENODEV; - return sprintf(buf, "%d\n", - channel_conn_id(hv_dev->channel, - vmbus_connection.monitor_pages[1])); + return sysfs_emit(buf, "%d\n", channel_conn_id(hv_dev->channel, + vmbus_connection.monitor_pages[1])); } static DEVICE_ATTR_RO(client_monitor_conn_id); @@ -303,7 +297,7 @@ static ssize_t out_intr_mask_show(struct device *dev, if (ret < 0) return ret; - return sprintf(buf, "%d\n", outbound.current_interrupt_mask); + return sysfs_emit(buf, "%d\n", outbound.current_interrupt_mask); } static DEVICE_ATTR_RO(out_intr_mask); @@ -321,7 +315,7 @@ static ssize_t out_read_index_show(struct device *dev, &outbound); if (ret < 0) return ret; - return sprintf(buf, "%d\n", outbound.current_read_index); + return sysfs_emit(buf, "%d\n", outbound.current_read_index); } static DEVICE_ATTR_RO(out_read_index); @@ -340,7 +334,7 @@ static ssize_t out_write_index_show(struct device *dev, &outbound); if (ret < 0) return ret; - return sprintf(buf, "%d\n", outbound.current_write_index); + return sysfs_emit(buf, "%d\n", outbound.current_write_index); } static DEVICE_ATTR_RO(out_write_index); @@ -359,7 +353,7 @@ static ssize_t out_read_bytes_avail_show(struct device *dev, &outbound); if (ret < 0) return ret; - return sprintf(buf, "%d\n", outbound.bytes_avail_toread); + return sysfs_emit(buf, "%d\n", outbound.bytes_avail_toread); } static DEVICE_ATTR_RO(out_read_bytes_avail); @@ -378,7 +372,7 @@ static ssize_t out_write_bytes_avail_show(struct device *dev, &outbound); if (ret < 0) return ret; - return sprintf(buf, "%d\n", outbound.bytes_avail_towrite); + return sysfs_emit(buf, "%d\n", outbound.bytes_avail_towrite); } static DEVICE_ATTR_RO(out_write_bytes_avail); @@ -396,7 +390,7 @@ static ssize_t in_intr_mask_show(struct device *dev, if (ret < 0) return ret; - return sprintf(buf, "%d\n", inbound.current_interrupt_mask); + return sysfs_emit(buf, "%d\n", inbound.current_interrupt_mask); } static DEVICE_ATTR_RO(in_intr_mask); @@ -414,7 +408,7 @@ static ssize_t in_read_index_show(struct device *dev, if (ret < 0) return ret; - return sprintf(buf, "%d\n", inbound.current_read_index); + return sysfs_emit(buf, "%d\n", inbound.current_read_index); } static DEVICE_ATTR_RO(in_read_index); @@ -432,7 +426,7 @@ static ssize_t in_write_index_show(struct device *dev, if (ret < 0) return ret; - return sprintf(buf, "%d\n", inbound.current_write_index); + return sysfs_emit(buf, "%d\n", inbound.current_write_index); } static DEVICE_ATTR_RO(in_write_index); @@ -451,7 +445,7 @@ static ssize_t in_read_bytes_avail_show(struct device *dev, if (ret < 0) return ret; - return sprintf(buf, "%d\n", inbound.bytes_avail_toread); + return sysfs_emit(buf, "%d\n", inbound.bytes_avail_toread); } static DEVICE_ATTR_RO(in_read_bytes_avail); @@ -470,7 +464,7 @@ static ssize_t in_write_bytes_avail_show(struct device *dev, if (ret < 0) return ret; - return sprintf(buf, "%d\n", inbound.bytes_avail_towrite); + return sysfs_emit(buf, "%d\n", inbound.bytes_avail_towrite); } static DEVICE_ATTR_RO(in_write_bytes_avail); @@ -480,7 +474,7 @@ static ssize_t channel_vp_mapping_show(struct device *dev, { struct hv_device *hv_dev = device_to_hv_device(dev); struct vmbus_channel *channel = hv_dev->channel, *cur_sc; - int buf_size = PAGE_SIZE, n_written, tot_written; + int n_written; struct list_head *cur; if (!channel) @@ -488,25 +482,21 @@ static ssize_t channel_vp_mapping_show(struct device *dev, mutex_lock(&vmbus_connection.channel_mutex); - tot_written = snprintf(buf, buf_size, "%u:%u\n", - channel->offermsg.child_relid, channel->target_cpu); + n_written = sysfs_emit(buf, "%u:%u\n", + channel->offermsg.child_relid, + channel->target_cpu); list_for_each(cur, &channel->sc_list) { - if (tot_written >= buf_size - 1) - break; cur_sc = list_entry(cur, struct vmbus_channel, sc_list); - n_written = scnprintf(buf + tot_written, - buf_size - tot_written, - "%u:%u\n", - cur_sc->offermsg.child_relid, - cur_sc->target_cpu); - tot_written += n_written; + n_written += sysfs_emit_at(buf, n_written, "%u:%u\n", + cur_sc->offermsg.child_relid, + cur_sc->target_cpu); } mutex_unlock(&vmbus_connection.channel_mutex); - return tot_written; + return n_written; } static DEVICE_ATTR_RO(channel_vp_mapping); @@ -516,7 +506,7 @@ static ssize_t vendor_show(struct device *dev, { struct hv_device *hv_dev = device_to_hv_device(dev); - return sprintf(buf, "0x%x\n", hv_dev->vendor_id); + return sysfs_emit(buf, "0x%x\n", hv_dev->vendor_id); } static DEVICE_ATTR_RO(vendor); @@ -526,7 +516,7 @@ static ssize_t device_show(struct device *dev, { struct hv_device *hv_dev = device_to_hv_device(dev); - return sprintf(buf, "0x%x\n", hv_dev->device_id); + return sysfs_emit(buf, "0x%x\n", hv_dev->device_id); } static DEVICE_ATTR_RO(device); @@ -551,7 +541,7 @@ static ssize_t driver_override_show(struct device *dev, ssize_t len; device_lock(dev); - len = snprintf(buf, PAGE_SIZE, "%s\n", hv_dev->driver_override); + len = sysfs_emit(buf, "%s\n", hv_dev->driver_override); device_unlock(dev); return len; -- cgit v1.2.3 From f971f6dd3742d22dd13710306fb4365ea7bcb536 Mon Sep 17 00:00:00 2001 From: Shradha Gupta Date: Fri, 22 Mar 2024 06:46:02 -0700 Subject: hv/hv_kvp_daemon: Handle IPv4 and Ipv6 combination for keyfile format If the network configuration strings are passed as a combination of IPv4 and IPv6 addresses, the current KVP daemon does not handle processing for the keyfile configuration format. With these changes, the keyfile config generation logic scans through the list twice to generate IPv4 and IPv6 sections for the configuration files to handle this support. Testcases ran:Rhel 9, Hyper-V VMs (IPv4 only, IPv6 only, IPv4 and IPv6 combination) Co-developed-by: Ani Sinha Signed-off-by: Ani Sinha Signed-off-by: Shradha Gupta Reviewed-by: Easwar Hariharan Tested-by: Ani Sinha Reviewed-by: Ani Sinha Link: https://lore.kernel.org/r/1711115162-11629-1-git-send-email-shradhagupta@linux.microsoft.com Signed-off-by: Wei Liu Message-ID: <1711115162-11629-1-git-send-email-shradhagupta@linux.microsoft.com> --- tools/hv/hv_kvp_daemon.c | 213 ++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 172 insertions(+), 41 deletions(-) diff --git a/tools/hv/hv_kvp_daemon.c b/tools/hv/hv_kvp_daemon.c index 318e2dad27e0..ae57bf69ad4a 100644 --- a/tools/hv/hv_kvp_daemon.c +++ b/tools/hv/hv_kvp_daemon.c @@ -76,6 +76,12 @@ enum { DNS }; +enum { + IPV4 = 1, + IPV6, + IP_TYPE_MAX +}; + static int in_hand_shake; static char *os_name = ""; @@ -102,6 +108,11 @@ static struct utsname uts_buf; #define MAX_FILE_NAME 100 #define ENTRIES_PER_BLOCK 50 +/* + * Change this entry if the number of addresses increases in future + */ +#define MAX_IP_ENTRIES 64 +#define OUTSTR_BUF_SIZE ((INET6_ADDRSTRLEN + 1) * MAX_IP_ENTRIES) struct kvp_record { char key[HV_KVP_EXCHANGE_MAX_KEY_SIZE]; @@ -1171,6 +1182,18 @@ static int process_ip_string(FILE *f, char *ip_string, int type) return 0; } +int ip_version_check(const char *input_addr) +{ + struct in6_addr addr; + + if (inet_pton(AF_INET, input_addr, &addr)) + return IPV4; + else if (inet_pton(AF_INET6, input_addr, &addr)) + return IPV6; + + return -EINVAL; +} + /* * Only IPv4 subnet strings needs to be converted to plen * For IPv6 the subnet is already privided in plen format @@ -1197,14 +1220,75 @@ static int kvp_subnet_to_plen(char *subnet_addr_str) return plen; } +static int process_dns_gateway_nm(FILE *f, char *ip_string, int type, + int ip_sec) +{ + char addr[INET6_ADDRSTRLEN], *output_str; + int ip_offset = 0, error = 0, ip_ver; + char *param_name; + + if (type == DNS) + param_name = "dns"; + else if (type == GATEWAY) + param_name = "gateway"; + else + return -EINVAL; + + output_str = (char *)calloc(OUTSTR_BUF_SIZE, sizeof(char)); + if (!output_str) + return -ENOMEM; + + while (1) { + memset(addr, 0, sizeof(addr)); + + if (!parse_ip_val_buffer(ip_string, &ip_offset, addr, + (MAX_IP_ADDR_SIZE * 2))) + break; + + ip_ver = ip_version_check(addr); + if (ip_ver < 0) + continue; + + if ((ip_ver == IPV4 && ip_sec == IPV4) || + (ip_ver == IPV6 && ip_sec == IPV6)) { + /* + * do a bound check to avoid out-of bound writes + */ + if ((OUTSTR_BUF_SIZE - strlen(output_str)) > + (strlen(addr) + 1)) { + strncat(output_str, addr, + OUTSTR_BUF_SIZE - + strlen(output_str) - 1); + strncat(output_str, ",", + OUTSTR_BUF_SIZE - + strlen(output_str) - 1); + } + } else { + continue; + } + } + + if (strlen(output_str)) { + /* + * This is to get rid of that extra comma character + * in the end of the string + */ + output_str[strlen(output_str) - 1] = '\0'; + error = fprintf(f, "%s=%s\n", param_name, output_str); + } + + free(output_str); + return error; +} + static int process_ip_string_nm(FILE *f, char *ip_string, char *subnet, - int is_ipv6) + int ip_sec) { char addr[INET6_ADDRSTRLEN]; char subnet_addr[INET6_ADDRSTRLEN]; - int error, i = 0; + int error = 0, i = 0; int ip_offset = 0, subnet_offset = 0; - int plen; + int plen, ip_ver; memset(addr, 0, sizeof(addr)); memset(subnet_addr, 0, sizeof(subnet_addr)); @@ -1216,10 +1300,16 @@ static int process_ip_string_nm(FILE *f, char *ip_string, char *subnet, subnet_addr, (MAX_IP_ADDR_SIZE * 2))) { - if (!is_ipv6) + ip_ver = ip_version_check(addr); + if (ip_ver < 0) + continue; + + if (ip_ver == IPV4 && ip_sec == IPV4) plen = kvp_subnet_to_plen((char *)subnet_addr); - else + else if (ip_ver == IPV6 && ip_sec == IPV6) plen = atoi(subnet_addr); + else + continue; if (plen < 0) return plen; @@ -1233,17 +1323,16 @@ static int process_ip_string_nm(FILE *f, char *ip_string, char *subnet, memset(subnet_addr, 0, sizeof(subnet_addr)); } - return 0; + return error; } static int kvp_set_ip_info(char *if_name, struct hv_kvp_ipaddr_value *new_val) { - int error = 0; + int error = 0, ip_ver; char if_filename[PATH_MAX]; char nm_filename[PATH_MAX]; FILE *ifcfg_file, *nmfile; char cmd[PATH_MAX]; - int is_ipv6 = 0; char *mac_addr; int str_len; @@ -1421,52 +1510,94 @@ static int kvp_set_ip_info(char *if_name, struct hv_kvp_ipaddr_value *new_val) if (error) goto setval_error; - if (new_val->addr_family & ADDR_FAMILY_IPV6) { - error = fprintf(nmfile, "\n[ipv6]\n"); - if (error < 0) - goto setval_error; - is_ipv6 = 1; - } else { - error = fprintf(nmfile, "\n[ipv4]\n"); - if (error < 0) - goto setval_error; - } - /* * Now we populate the keyfile format + * + * The keyfile format expects the IPv6 and IPv4 configuration in + * different sections. Therefore we iterate through the list twice, + * once to populate the IPv4 section and the next time for IPv6 */ + ip_ver = IPV4; + do { + if (ip_ver == IPV4) { + error = fprintf(nmfile, "\n[ipv4]\n"); + if (error < 0) + goto setval_error; + } else { + error = fprintf(nmfile, "\n[ipv6]\n"); + if (error < 0) + goto setval_error; + } - if (new_val->dhcp_enabled) { - error = kvp_write_file(nmfile, "method", "", "auto"); - if (error < 0) - goto setval_error; - } else { - error = kvp_write_file(nmfile, "method", "", "manual"); + /* + * Write the configuration for ipaddress, netmask, gateway and + * name services + */ + error = process_ip_string_nm(nmfile, (char *)new_val->ip_addr, + (char *)new_val->sub_net, + ip_ver); if (error < 0) goto setval_error; - } - /* - * Write the configuration for ipaddress, netmask, gateway and - * name services - */ - error = process_ip_string_nm(nmfile, (char *)new_val->ip_addr, - (char *)new_val->sub_net, is_ipv6); - if (error < 0) - goto setval_error; + /* + * As dhcp_enabled is only valid for ipv4, we do not set dhcp + * methods for ipv6 based on dhcp_enabled flag. + * + * For ipv4, set method to manual only when dhcp_enabled is + * false and specific ipv4 addresses are configured. If neither + * dhcp_enabled is true and no ipv4 addresses are configured, + * set method to 'disabled'. + * + * For ipv6, set method to manual when we configure ipv6 + * addresses. Otherwise set method to 'auto' so that SLAAC from + * RA may be used. + */ + if (ip_ver == IPV4) { + if (new_val->dhcp_enabled) { + error = kvp_write_file(nmfile, "method", "", + "auto"); + if (error < 0) + goto setval_error; + } else if (error) { + error = kvp_write_file(nmfile, "method", "", + "manual"); + if (error < 0) + goto setval_error; + } else { + error = kvp_write_file(nmfile, "method", "", + "disabled"); + if (error < 0) + goto setval_error; + } + } else if (ip_ver == IPV6) { + if (error) { + error = kvp_write_file(nmfile, "method", "", + "manual"); + if (error < 0) + goto setval_error; + } else { + error = kvp_write_file(nmfile, "method", "", + "auto"); + if (error < 0) + goto setval_error; + } + } - /* we do not want ipv4 addresses in ipv6 section and vice versa */ - if (is_ipv6 != is_ipv4((char *)new_val->gate_way)) { - error = fprintf(nmfile, "gateway=%s\n", (char *)new_val->gate_way); + error = process_dns_gateway_nm(nmfile, + (char *)new_val->gate_way, + GATEWAY, ip_ver); if (error < 0) goto setval_error; - } - if (is_ipv6 != is_ipv4((char *)new_val->dns_addr)) { - error = fprintf(nmfile, "dns=%s\n", (char *)new_val->dns_addr); + error = process_dns_gateway_nm(nmfile, + (char *)new_val->dns_addr, DNS, + ip_ver); if (error < 0) goto setval_error; - } + + ip_ver++; + } while (ip_ver < IP_TYPE_MAX); + fclose(nmfile); fclose(ifcfg_file); -- cgit v1.2.3 From 03f5a999adba062456c8c818a683beb1b498983a Mon Sep 17 00:00:00 2001 From: Rick Edgecombe Date: Mon, 11 Mar 2024 09:15:54 -0700 Subject: Drivers: hv: vmbus: Leak pages if set_memory_encrypted() fails In CoCo VMs it is possible for the untrusted host to cause set_memory_encrypted() or set_memory_decrypted() to fail such that an error is returned and the resulting memory is shared. Callers need to take care to handle these errors to avoid returning decrypted (shared) memory to the page allocator, which could lead to functional or security issues. VMBus code could free decrypted pages if set_memory_encrypted()/decrypted() fails. Leak the pages if this happens. Signed-off-by: Rick Edgecombe Signed-off-by: Michael Kelley Reviewed-by: Kuppuswamy Sathyanarayanan Acked-by: Kirill A. Shutemov Link: https://lore.kernel.org/r/20240311161558.1310-2-mhklinux@outlook.com Signed-off-by: Wei Liu Message-ID: <20240311161558.1310-2-mhklinux@outlook.com> --- drivers/hv/connection.c | 29 ++++++++++++++++++++++------- 1 file changed, 22 insertions(+), 7 deletions(-) diff --git a/drivers/hv/connection.c b/drivers/hv/connection.c index 3cabeeabb1ca..f001ae880e1d 100644 --- a/drivers/hv/connection.c +++ b/drivers/hv/connection.c @@ -237,8 +237,17 @@ int vmbus_connect(void) vmbus_connection.monitor_pages[0], 1); ret |= set_memory_decrypted((unsigned long) vmbus_connection.monitor_pages[1], 1); - if (ret) + if (ret) { + /* + * If set_memory_decrypted() fails, the encryption state + * of the memory is unknown. So leak the memory instead + * of risking returning decrypted memory to the free list. + * For simplicity, always handle both pages the same. + */ + vmbus_connection.monitor_pages[0] = NULL; + vmbus_connection.monitor_pages[1] = NULL; goto cleanup; + } /* * Set_memory_decrypted() will change the memory contents if @@ -337,13 +346,19 @@ void vmbus_disconnect(void) vmbus_connection.int_page = NULL; } - set_memory_encrypted((unsigned long)vmbus_connection.monitor_pages[0], 1); - set_memory_encrypted((unsigned long)vmbus_connection.monitor_pages[1], 1); + if (vmbus_connection.monitor_pages[0]) { + if (!set_memory_encrypted( + (unsigned long)vmbus_connection.monitor_pages[0], 1)) + hv_free_hyperv_page(vmbus_connection.monitor_pages[0]); + vmbus_connection.monitor_pages[0] = NULL; + } - hv_free_hyperv_page(vmbus_connection.monitor_pages[0]); - hv_free_hyperv_page(vmbus_connection.monitor_pages[1]); - vmbus_connection.monitor_pages[0] = NULL; - vmbus_connection.monitor_pages[1] = NULL; + if (vmbus_connection.monitor_pages[1]) { + if (!set_memory_encrypted( + (unsigned long)vmbus_connection.monitor_pages[1], 1)) + hv_free_hyperv_page(vmbus_connection.monitor_pages[1]); + vmbus_connection.monitor_pages[1] = NULL; + } } /* -- cgit v1.2.3 From 211f514ebf1ef5de37b1cf6df9d28a56cfd242ca Mon Sep 17 00:00:00 2001 From: Rick Edgecombe Date: Mon, 11 Mar 2024 09:15:55 -0700 Subject: Drivers: hv: vmbus: Track decrypted status in vmbus_gpadl In CoCo VMs it is possible for the untrusted host to cause set_memory_encrypted() or set_memory_decrypted() to fail such that an error is returned and the resulting memory is shared. Callers need to take care to handle these errors to avoid returning decrypted (shared) memory to the page allocator, which could lead to functional or security issues. In order to make sure callers of vmbus_establish_gpadl() and vmbus_teardown_gpadl() don't return decrypted/shared pages to allocators, add a field in struct vmbus_gpadl to keep track of the decryption status of the buffers. This will allow the callers to know if they should free or leak the pages. Signed-off-by: Rick Edgecombe Signed-off-by: Michael Kelley Reviewed-by: Kuppuswamy Sathyanarayanan Acked-by: Kirill A. Shutemov Link: https://lore.kernel.org/r/20240311161558.1310-3-mhklinux@outlook.com Signed-off-by: Wei Liu Message-ID: <20240311161558.1310-3-mhklinux@outlook.com> --- drivers/hv/channel.c | 25 +++++++++++++++++++++---- include/linux/hyperv.h | 1 + 2 files changed, 22 insertions(+), 4 deletions(-) diff --git a/drivers/hv/channel.c b/drivers/hv/channel.c index adbf674355b2..98259b492502 100644 --- a/drivers/hv/channel.c +++ b/drivers/hv/channel.c @@ -436,9 +436,18 @@ static int __vmbus_establish_gpadl(struct vmbus_channel *channel, (atomic_inc_return(&vmbus_connection.next_gpadl_handle) - 1); ret = create_gpadl_header(type, kbuffer, size, send_offset, &msginfo); - if (ret) + if (ret) { + gpadl->decrypted = false; return ret; + } + /* + * Set the "decrypted" flag to true for the set_memory_decrypted() + * success case. In the failure case, the encryption state of the + * memory is unknown. Leave "decrypted" as true to ensure the + * memory will be leaked instead of going back on the free list. + */ + gpadl->decrypted = true; ret = set_memory_decrypted((unsigned long)kbuffer, PFN_UP(size)); if (ret) { @@ -527,9 +536,15 @@ cleanup: kfree(msginfo); - if (ret) - set_memory_encrypted((unsigned long)kbuffer, - PFN_UP(size)); + if (ret) { + /* + * If set_memory_encrypted() fails, the decrypted flag is + * left as true so the memory is leaked instead of being + * put back on the free list. + */ + if (!set_memory_encrypted((unsigned long)kbuffer, PFN_UP(size))) + gpadl->decrypted = false; + } return ret; } @@ -850,6 +865,8 @@ post_msg_err: if (ret) pr_warn("Fail to set mem host visibility in GPADL teardown %d.\n", ret); + gpadl->decrypted = ret; + return ret; } EXPORT_SYMBOL_GPL(vmbus_teardown_gpadl); diff --git a/include/linux/hyperv.h b/include/linux/hyperv.h index 6ef0557b4bff..96ceb4095425 100644 --- a/include/linux/hyperv.h +++ b/include/linux/hyperv.h @@ -832,6 +832,7 @@ struct vmbus_gpadl { u32 gpadl_handle; u32 size; void *buffer; + bool decrypted; }; struct vmbus_channel { -- cgit v1.2.3 From bbf9ac34677b57506a13682b31a2a718934c0e31 Mon Sep 17 00:00:00 2001 From: Rick Edgecombe Date: Mon, 11 Mar 2024 09:15:56 -0700 Subject: hv_netvsc: Don't free decrypted memory In CoCo VMs it is possible for the untrusted host to cause set_memory_encrypted() or set_memory_decrypted() to fail such that an error is returned and the resulting memory is shared. Callers need to take care to handle these errors to avoid returning decrypted (shared) memory to the page allocator, which could lead to functional or security issues. The netvsc driver could free decrypted/shared pages if set_memory_decrypted() fails. Check the decrypted field in the gpadl to decide whether to free the memory. Signed-off-by: Rick Edgecombe Signed-off-by: Michael Kelley Reviewed-by: Kuppuswamy Sathyanarayanan Acked-by: Kirill A. Shutemov Link: https://lore.kernel.org/r/20240311161558.1310-4-mhklinux@outlook.com Signed-off-by: Wei Liu Message-ID: <20240311161558.1310-4-mhklinux@outlook.com> --- drivers/net/hyperv/netvsc.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/drivers/net/hyperv/netvsc.c b/drivers/net/hyperv/netvsc.c index a6fcbda64ecc..2b6ec979a62f 100644 --- a/drivers/net/hyperv/netvsc.c +++ b/drivers/net/hyperv/netvsc.c @@ -154,8 +154,11 @@ static void free_netvsc_device(struct rcu_head *head) int i; kfree(nvdev->extension); - vfree(nvdev->recv_buf); - vfree(nvdev->send_buf); + + if (!nvdev->recv_buf_gpadl_handle.decrypted) + vfree(nvdev->recv_buf); + if (!nvdev->send_buf_gpadl_handle.decrypted) + vfree(nvdev->send_buf); bitmap_free(nvdev->send_section_map); for (i = 0; i < VRSS_CHANNEL_MAX; i++) { -- cgit v1.2.3 From 3d788b2fbe6a1a1a9e3db09742b90809d51638b7 Mon Sep 17 00:00:00 2001 From: Rick Edgecombe Date: Mon, 11 Mar 2024 09:15:57 -0700 Subject: uio_hv_generic: Don't free decrypted memory In CoCo VMs it is possible for the untrusted host to cause set_memory_encrypted() or set_memory_decrypted() to fail such that an error is returned and the resulting memory is shared. Callers need to take care to handle these errors to avoid returning decrypted (shared) memory to the page allocator, which could lead to functional or security issues. The VMBus device UIO driver could free decrypted/shared pages if set_memory_decrypted() fails. Check the decrypted field in the gpadl to decide whether to free the memory. Signed-off-by: Rick Edgecombe Signed-off-by: Michael Kelley Reviewed-by: Kuppuswamy Sathyanarayanan Acked-by: Kirill A. Shutemov Link: https://lore.kernel.org/r/20240311161558.1310-5-mhklinux@outlook.com Signed-off-by: Wei Liu Message-ID: <20240311161558.1310-5-mhklinux@outlook.com> --- drivers/uio/uio_hv_generic.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/drivers/uio/uio_hv_generic.c b/drivers/uio/uio_hv_generic.c index 20d9762331bd..6be3462b109f 100644 --- a/drivers/uio/uio_hv_generic.c +++ b/drivers/uio/uio_hv_generic.c @@ -181,12 +181,14 @@ hv_uio_cleanup(struct hv_device *dev, struct hv_uio_private_data *pdata) { if (pdata->send_gpadl.gpadl_handle) { vmbus_teardown_gpadl(dev->channel, &pdata->send_gpadl); - vfree(pdata->send_buf); + if (!pdata->send_gpadl.decrypted) + vfree(pdata->send_buf); } if (pdata->recv_gpadl.gpadl_handle) { vmbus_teardown_gpadl(dev->channel, &pdata->recv_gpadl); - vfree(pdata->recv_buf); + if (!pdata->recv_gpadl.decrypted) + vfree(pdata->recv_buf); } } @@ -295,7 +297,8 @@ hv_uio_probe(struct hv_device *dev, ret = vmbus_establish_gpadl(channel, pdata->recv_buf, RECV_BUFFER_SIZE, &pdata->recv_gpadl); if (ret) { - vfree(pdata->recv_buf); + if (!pdata->recv_gpadl.decrypted) + vfree(pdata->recv_buf); goto fail_close; } @@ -317,7 +320,8 @@ hv_uio_probe(struct hv_device *dev, ret = vmbus_establish_gpadl(channel, pdata->send_buf, SEND_BUFFER_SIZE, &pdata->send_gpadl); if (ret) { - vfree(pdata->send_buf); + if (!pdata->send_gpadl.decrypted) + vfree(pdata->send_buf); goto fail_close; } -- cgit v1.2.3 From 30d18df6567be09c1433e81993e35e3da573ac48 Mon Sep 17 00:00:00 2001 From: Michael Kelley Date: Mon, 11 Mar 2024 09:15:58 -0700 Subject: Drivers: hv: vmbus: Don't free ring buffers that couldn't be re-encrypted In CoCo VMs it is possible for the untrusted host to cause set_memory_encrypted() or set_memory_decrypted() to fail such that an error is returned and the resulting memory is shared. Callers need to take care to handle these errors to avoid returning decrypted (shared) memory to the page allocator, which could lead to functional or security issues. The VMBus ring buffer code could free decrypted/shared pages if set_memory_decrypted() fails. Check the decrypted field in the struct vmbus_gpadl for the ring buffers to decide whether to free the memory. Signed-off-by: Michael Kelley Reviewed-by: Kuppuswamy Sathyanarayanan Acked-by: Kirill A. Shutemov Link: https://lore.kernel.org/r/20240311161558.1310-6-mhklinux@outlook.com Signed-off-by: Wei Liu Message-ID: <20240311161558.1310-6-mhklinux@outlook.com> --- drivers/hv/channel.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/hv/channel.c b/drivers/hv/channel.c index 98259b492502..fb8cd8469328 100644 --- a/drivers/hv/channel.c +++ b/drivers/hv/channel.c @@ -153,7 +153,9 @@ void vmbus_free_ring(struct vmbus_channel *channel) hv_ringbuffer_cleanup(&channel->inbound); if (channel->ringbuffer_page) { - __free_pages(channel->ringbuffer_page, + /* In a CoCo VM leak the memory if it didn't get re-encrypted */ + if (!channel->ringbuffer_gpadlhandle.decrypted) + __free_pages(channel->ringbuffer_page, get_order(channel->ringbuffer_pagecount << PAGE_SHIFT)); channel->ringbuffer_page = NULL; -- cgit v1.2.3 From a4833e3abae132d613ce7da0e0c9a9465d1681fa Mon Sep 17 00:00:00 2001 From: "Steven Rostedt (Google)" Date: Wed, 10 Apr 2024 12:38:13 -0400 Subject: SUNRPC: Fix rpcgss_context trace event acceptor field The rpcgss_context trace event acceptor field is a dynamically sized string that records the "data" parameter. But this parameter is also dependent on the "len" field to determine the size of the data. It needs to use __string_len() helper macro where the length can be passed in. It also incorrectly uses strncpy() to save it instead of __assign_str(). As these macros can change, it is not wise to open code them in trace events. As of commit c759e609030c ("tracing: Remove __assign_str_len()"), __assign_str() can be used for both __string() and __string_len() fields. Before that commit, __assign_str_len() is required to be used. This needs to be noted for backporting. (In actuality, commit c1fa617caeb0 ("tracing: Rework __assign_str() and __string() to not duplicate getting the string") is the commit that makes __string_str_len() obsolete). Cc: stable@vger.kernel.org Fixes: 0c77668ddb4e ("SUNRPC: Introduce trace points in rpc_auth_gss.ko") Signed-off-by: Steven Rostedt (Google) Signed-off-by: Chuck Lever --- include/trace/events/rpcgss.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/trace/events/rpcgss.h b/include/trace/events/rpcgss.h index ba2d96a1bc2f..f50fcafc69de 100644 --- a/include/trace/events/rpcgss.h +++ b/include/trace/events/rpcgss.h @@ -609,7 +609,7 @@ TRACE_EVENT(rpcgss_context, __field(unsigned int, timeout) __field(u32, window_size) __field(int, len) - __string(acceptor, data) + __string_len(acceptor, data, len) ), TP_fast_assign( @@ -618,7 +618,7 @@ TRACE_EVENT(rpcgss_context, __entry->timeout = timeout; __entry->window_size = window_size; __entry->len = len; - strncpy(__get_str(acceptor), data, len); + __assign_str(acceptor, data); ), TP_printk("win_size=%u expiry=%lu now=%lu timeout=%u acceptor=%.*s", -- cgit v1.2.3 From ec4535b2a1d709d3a1fbec26739c672f13c98a7b Mon Sep 17 00:00:00 2001 From: Paulo Alcantara Date: Mon, 8 Apr 2024 18:32:17 -0300 Subject: smb: client: fix NULL ptr deref in cifs_mark_open_handles_for_deleted_file() cifs_get_fattr() may be called with a NULL inode, so check for a non-NULL inode before calling cifs_mark_open_handles_for_deleted_file(). This fixes the following oops: mount.cifs //srv/share /mnt -o ...,vers=3.1.1 cd /mnt touch foo; tail -f foo & rm foo cat foo BUG: kernel NULL pointer dereference, address: 00000000000005c0 #PF: supervisor read access in kernel mode #PF: error_code(0x0000) - not-present page PGD 0 P4D 0 Oops: 0000 [#1] PREEMPT SMP NOPTI CPU: 2 PID: 696 Comm: cat Not tainted 6.9.0-rc2 #1 Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS 1.16.3-1.fc39 04/01/2014 RIP: 0010:__lock_acquire+0x5d/0x1c70 Code: 00 00 44 8b a4 24 a0 00 00 00 45 85 f6 0f 84 bb 06 00 00 8b 2d 48 e2 95 01 45 89 c3 41 89 d2 45 89 c8 85 ed 0 0 <48> 81 3f 40 7a 76 83 44 0f 44 d8 83 fe 01 0f 86 1b 03 00 00 31 d2 RSP: 0018:ffffc90000b37490 EFLAGS: 00010002 RAX: 0000000000000000 RBX: ffff888110021ec0 RCX: 0000000000000000 RDX: 0000000000000000 RSI: 0000000000000000 RDI: 00000000000005c0 RBP: 0000000000000001 R08: 0000000000000000 R09: 0000000000000000 R10: 0000000000000000 R11: 0000000000000001 R12: 0000000000000000 R13: 0000000000000000 R14: 0000000000000001 R15: 0000000000000200 FS: 00007f2a1fa08740(0000) GS:ffff888157a00000(0000) knlGS:0000000000000000 CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 CR2: 00000000000005c0 CR3: 000000011ac7c000 CR4: 0000000000750ef0 PKRU: 55555554 Call Trace: ? __die+0x23/0x70 ? page_fault_oops+0x180/0x490 ? srso_alias_return_thunk+0x5/0xfbef5 ? exc_page_fault+0x70/0x230 ? asm_exc_page_fault+0x26/0x30 ? __lock_acquire+0x5d/0x1c70 ? srso_alias_return_thunk+0x5/0xfbef5 ? srso_alias_return_thunk+0x5/0xfbef5 lock_acquire+0xc0/0x2d0 ? cifs_mark_open_handles_for_deleted_file+0x3a/0x100 [cifs] ? srso_alias_return_thunk+0x5/0xfbef5 ? kmem_cache_alloc+0x2d9/0x370 _raw_spin_lock+0x34/0x80 ? cifs_mark_open_handles_for_deleted_file+0x3a/0x100 [cifs] cifs_mark_open_handles_for_deleted_file+0x3a/0x100 [cifs] cifs_get_fattr+0x24c/0x940 [cifs] ? srso_alias_return_thunk+0x5/0xfbef5 cifs_get_inode_info+0x96/0x120 [cifs] cifs_lookup+0x16e/0x800 [cifs] cifs_atomic_open+0xc7/0x5d0 [cifs] ? lookup_open.isra.0+0x3ce/0x5f0 ? __pfx_cifs_atomic_open+0x10/0x10 [cifs] lookup_open.isra.0+0x3ce/0x5f0 path_openat+0x42b/0xc30 ? srso_alias_return_thunk+0x5/0xfbef5 ? srso_alias_return_thunk+0x5/0xfbef5 ? srso_alias_return_thunk+0x5/0xfbef5 do_filp_open+0xc4/0x170 do_sys_openat2+0xab/0xe0 __x64_sys_openat+0x57/0xa0 do_syscall_64+0xc1/0x1e0 entry_SYSCALL_64_after_hwframe+0x72/0x7a Fixes: ffceb7640cbf ("smb: client: do not defer close open handles to deleted files") Reviewed-by: Meetakshi Setiya Reviewed-by: Bharath SM Signed-off-by: Paulo Alcantara (Red Hat) Signed-off-by: Steve French --- fs/smb/client/inode.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/fs/smb/client/inode.c b/fs/smb/client/inode.c index 91b07ef9e25c..60afab5c83d4 100644 --- a/fs/smb/client/inode.c +++ b/fs/smb/client/inode.c @@ -1105,7 +1105,8 @@ static int cifs_get_fattr(struct cifs_open_info_data *data, } else { cifs_open_info_to_fattr(fattr, data, sb); } - if (!rc && fattr->cf_flags & CIFS_FATTR_DELETE_PENDING) + if (!rc && *inode && + (fattr->cf_flags & CIFS_FATTR_DELETE_PENDING)) cifs_mark_open_handles_for_deleted_file(*inode, full_path); break; case -EREMOTE: -- cgit v1.2.3 From 06dfcd4098cfdc4d4577d94793a4f9125386da8b Mon Sep 17 00:00:00 2001 From: Arınç ÜNAL Date: Mon, 8 Apr 2024 10:08:53 +0300 Subject: net: dsa: mt7530: fix enabling EEE on MT7531 switch on all boards MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The commit 40b5d2f15c09 ("net: dsa: mt7530: Add support for EEE features") brought EEE support but did not enable EEE on MT7531 switch MACs. EEE is enabled on MT7531 switch MACs by pulling the LAN2LED0 pin low on the board (bootstrapping), unsetting the EEE_DIS bit on the trap register, or setting the internal EEE switch bit on the CORE_PLL_GROUP4 register. Thanks to SkyLake Huang (黃啟澤) from MediaTek for providing information on the internal EEE switch bit. There are existing boards that were not designed to pull the pin low. Because of that, the EEE status currently depends on the board design. The EEE_DIS bit on the trap pertains to the LAN2LED0 pin which is usually used to control an LED. Once the bit is unset, the pin will be low. That will make the active low LED turn on. The pin is controlled by the switch PHY. It seems that the PHY controls the pin in the way that it inverts the pin state. That means depending on the wiring of the LED connected to LAN2LED0 on the board, the LED may be on without an active link. To not cause this unwanted behaviour whilst enabling EEE on all boards, set the internal EEE switch bit on the CORE_PLL_GROUP4 register. My testing on MT7531 shows a certain amount of traffic loss when EEE is enabled. That said, I haven't come across a board that enables EEE. So enable EEE on the switch MACs but disable EEE advertisement on the switch PHYs. This way, we don't change the behaviour of the majority of the boards that have this switch. The mediatek-ge PHY driver already disables EEE advertisement on the switch PHYs but my testing shows that it is somehow enabled afterwards. Disabling EEE advertisement before the PHY driver initialises keeps it off. With this change, EEE can now be enabled using ethtool. Fixes: 40b5d2f15c09 ("net: dsa: mt7530: Add support for EEE features") Reviewed-by: Florian Fainelli Signed-off-by: Arınç ÜNAL Tested-by: Daniel Golle Reviewed-by: Daniel Golle Link: https://lore.kernel.org/r/20240408-for-net-mt7530-fix-eee-for-mt7531-mt7988-v3-1-84fdef1f008b@arinc9.com Signed-off-by: Jakub Kicinski --- drivers/net/dsa/mt7530.c | 17 ++++++++++++----- drivers/net/dsa/mt7530.h | 1 + 2 files changed, 13 insertions(+), 5 deletions(-) diff --git a/drivers/net/dsa/mt7530.c b/drivers/net/dsa/mt7530.c index 1035820c2377..451ff0620c2e 100644 --- a/drivers/net/dsa/mt7530.c +++ b/drivers/net/dsa/mt7530.c @@ -2505,18 +2505,25 @@ mt7531_setup(struct dsa_switch *ds) mt7530_rmw(priv, MT7531_GPIO_MODE0, MT7531_GPIO0_MASK, MT7531_GPIO0_INTERRUPT); - /* Enable PHY core PLL, since phy_device has not yet been created - * provided for phy_[read,write]_mmd_indirect is called, we provide - * our own mt7531_ind_mmd_phy_[read,write] to complete this - * function. + /* Enable Energy-Efficient Ethernet (EEE) and PHY core PLL, since + * phy_device has not yet been created provided for + * phy_[read,write]_mmd_indirect is called, we provide our own + * mt7531_ind_mmd_phy_[read,write] to complete this function. */ val = mt7531_ind_c45_phy_read(priv, MT753X_CTRL_PHY_ADDR, MDIO_MMD_VEND2, CORE_PLL_GROUP4); - val |= MT7531_PHY_PLL_BYPASS_MODE; + val |= MT7531_RG_SYSPLL_DMY2 | MT7531_PHY_PLL_BYPASS_MODE; val &= ~MT7531_PHY_PLL_OFF; mt7531_ind_c45_phy_write(priv, MT753X_CTRL_PHY_ADDR, MDIO_MMD_VEND2, CORE_PLL_GROUP4, val); + /* Disable EEE advertisement on the switch PHYs. */ + for (i = MT753X_CTRL_PHY_ADDR; + i < MT753X_CTRL_PHY_ADDR + MT7530_NUM_PHYS; i++) { + mt7531_ind_c45_phy_write(priv, i, MDIO_MMD_AN, MDIO_AN_EEE_ADV, + 0); + } + mt7531_setup_common(ds); /* Setup VLAN ID 0 for VLAN-unaware bridges */ diff --git a/drivers/net/dsa/mt7530.h b/drivers/net/dsa/mt7530.h index d17b318e6ee4..9439db495001 100644 --- a/drivers/net/dsa/mt7530.h +++ b/drivers/net/dsa/mt7530.h @@ -616,6 +616,7 @@ enum mt7531_clk_skew { #define RG_SYSPLL_DDSFBK_EN BIT(12) #define RG_SYSPLL_BIAS_EN BIT(11) #define RG_SYSPLL_BIAS_LPF_EN BIT(10) +#define MT7531_RG_SYSPLL_DMY2 BIT(6) #define MT7531_PHY_PLL_OFF BIT(5) #define MT7531_PHY_PLL_BYPASS_MODE BIT(4) -- cgit v1.2.3 From 5e700b384ec13f5bcac9855cb28fcc674f1d3593 Mon Sep 17 00:00:00 2001 From: Noah Loomans Date: Wed, 10 Apr 2024 20:26:19 +0200 Subject: platform/chrome: cros_ec_uart: properly fix race condition The cros_ec_uart_probe() function calls devm_serdev_device_open() before it calls serdev_device_set_client_ops(). This can trigger a NULL pointer dereference: BUG: kernel NULL pointer dereference, address: 0000000000000000 ... Call Trace: ... ? ttyport_receive_buf A simplified version of crashing code is as follows: static inline size_t serdev_controller_receive_buf(struct serdev_controller *ctrl, const u8 *data, size_t count) { struct serdev_device *serdev = ctrl->serdev; if (!serdev || !serdev->ops->receive_buf) // CRASH! return 0; return serdev->ops->receive_buf(serdev, data, count); } It assumes that if SERPORT_ACTIVE is set and serdev exists, serdev->ops will also exist. This conflicts with the existing cros_ec_uart_probe() logic, as it first calls devm_serdev_device_open() (which sets SERPORT_ACTIVE), and only later sets serdev->ops via serdev_device_set_client_ops(). Commit 01f95d42b8f4 ("platform/chrome: cros_ec_uart: fix race condition") attempted to fix a similar race condition, but while doing so, made the window of error for this race condition to happen much wider. Attempt to fix the race condition again, making sure we fully setup before calling devm_serdev_device_open(). Fixes: 01f95d42b8f4 ("platform/chrome: cros_ec_uart: fix race condition") Cc: stable@vger.kernel.org Signed-off-by: Noah Loomans Reviewed-by: Guenter Roeck Link: https://lore.kernel.org/r/20240410182618.169042-2-noah@noahloomans.com Signed-off-by: Tzung-Bi Shih --- drivers/platform/chrome/cros_ec_uart.c | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/drivers/platform/chrome/cros_ec_uart.c b/drivers/platform/chrome/cros_ec_uart.c index 68d80559fddc..eb5eddeb73f7 100644 --- a/drivers/platform/chrome/cros_ec_uart.c +++ b/drivers/platform/chrome/cros_ec_uart.c @@ -263,12 +263,6 @@ static int cros_ec_uart_probe(struct serdev_device *serdev) if (!ec_dev) return -ENOMEM; - ret = devm_serdev_device_open(dev, serdev); - if (ret) { - dev_err(dev, "Unable to open UART device"); - return ret; - } - serdev_device_set_drvdata(serdev, ec_dev); init_waitqueue_head(&ec_uart->response.wait_queue); @@ -280,14 +274,6 @@ static int cros_ec_uart_probe(struct serdev_device *serdev) return ret; } - ret = serdev_device_set_baudrate(serdev, ec_uart->baudrate); - if (ret < 0) { - dev_err(dev, "Failed to set up host baud rate (%d)", ret); - return ret; - } - - serdev_device_set_flow_control(serdev, ec_uart->flowcontrol); - /* Initialize ec_dev for cros_ec */ ec_dev->phys_name = dev_name(dev); ec_dev->dev = dev; @@ -301,6 +287,20 @@ static int cros_ec_uart_probe(struct serdev_device *serdev) serdev_device_set_client_ops(serdev, &cros_ec_uart_client_ops); + ret = devm_serdev_device_open(dev, serdev); + if (ret) { + dev_err(dev, "Unable to open UART device"); + return ret; + } + + ret = serdev_device_set_baudrate(serdev, ec_uart->baudrate); + if (ret < 0) { + dev_err(dev, "Failed to set up host baud rate (%d)", ret); + return ret; + } + + serdev_device_set_flow_control(serdev, ec_uart->flowcontrol); + return cros_ec_register(ec_dev); } -- cgit v1.2.3 From 97e176fcbbf3c0f2bd410c9b241177c051f57176 Mon Sep 17 00:00:00 2001 From: Heiner Kallweit Date: Wed, 10 Apr 2024 15:11:28 +0200 Subject: r8169: add missing conditional compiling for call to r8169_remove_leds Add missing dependency on CONFIG_R8169_LEDS. As-is a link error occurs if config option CONFIG_R8169_LEDS isn't enabled. Fixes: 19fa4f2a85d7 ("r8169: fix LED-related deadlock on module removal") Reported-by: Venkat Rao Bagalkote Signed-off-by: Heiner Kallweit Tested-By: Venkat Rao Bagalkote Link: https://lore.kernel.org/r/d080038c-eb6b-45ac-9237-b8c1cdd7870f@gmail.com Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/realtek/r8169_main.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/net/ethernet/realtek/r8169_main.c b/drivers/net/ethernet/realtek/r8169_main.c index 8a27328eae34..0fc5fe564ae5 100644 --- a/drivers/net/ethernet/realtek/r8169_main.c +++ b/drivers/net/ethernet/realtek/r8169_main.c @@ -5046,7 +5046,8 @@ static void rtl_remove_one(struct pci_dev *pdev) cancel_work_sync(&tp->wk.work); - r8169_remove_leds(tp->leds); + if (IS_ENABLED(CONFIG_R8169_LEDS)) + r8169_remove_leds(tp->leds); unregister_netdev(tp->dev); -- cgit v1.2.3 From beccf29114886f1604e26f739cd108f048878ca8 Mon Sep 17 00:00:00 2001 From: Kent Overstreet Date: Wed, 10 Apr 2024 12:53:28 -0400 Subject: bcachefs: Fix a race in btree_update_nodes_written() One btree update might have terminated in a node update, and then while it is in flight another btree update might free that original node. This race has to be handled in btree_update_nodes_written() - we were missing a READ_ONCE(). Signed-off-by: Kent Overstreet --- fs/bcachefs/btree_update_interior.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/fs/bcachefs/btree_update_interior.c b/fs/bcachefs/btree_update_interior.c index a4a63e363047..c4a5e83a56a4 100644 --- a/fs/bcachefs/btree_update_interior.c +++ b/fs/bcachefs/btree_update_interior.c @@ -704,9 +704,13 @@ static void btree_update_nodes_written(struct btree_update *as) bch2_fs_fatal_err_on(ret && !bch2_journal_error(&c->journal), c, "%s", bch2_err_str(ret)); err: - if (as->b) { - - b = as->b; + /* + * We have to be careful because another thread might be getting ready + * to free as->b and calling btree_update_reparent() on us - we'll + * recheck under btree_update_lock below: + */ + b = READ_ONCE(as->b); + if (b) { btree_path_idx_t path_idx = get_unlocked_mut_path(trans, as->btree_id, b->c.level, b->key.k.p); struct btree_path *path = trans->paths + path_idx; -- cgit v1.2.3 From 517236cb3e2f77bc785f06802dfbcca19dffd9ad Mon Sep 17 00:00:00 2001 From: Kent Overstreet Date: Wed, 10 Apr 2024 00:10:18 -0400 Subject: bcachefs: Kill read lock dropping in bch2_btree_node_lock_write_nofail() dropping read locks in bch2_btree_node_lock_write_nofail() dates from before we had the cycle detector; we can now tell the cycle detector directly when taking a lock may not fail because we can't handle transaction restarts. This is needed for adding should_be_locked asserts. Signed-off-by: Kent Overstreet --- fs/bcachefs/btree_locking.c | 28 +--------------------------- 1 file changed, 1 insertion(+), 27 deletions(-) diff --git a/fs/bcachefs/btree_locking.c b/fs/bcachefs/btree_locking.c index b9b151e693ed..f2caf491957e 100644 --- a/fs/bcachefs/btree_locking.c +++ b/fs/bcachefs/btree_locking.c @@ -440,33 +440,7 @@ void bch2_btree_node_lock_write_nofail(struct btree_trans *trans, struct btree_path *path, struct btree_bkey_cached_common *b) { - struct btree_path *linked; - unsigned i, iter; - int ret; - - /* - * XXX BIG FAT NOTICE - * - * Drop all read locks before taking a write lock: - * - * This is a hack, because bch2_btree_node_lock_write_nofail() is a - * hack - but by dropping read locks first, this should never fail, and - * we only use this in code paths where whatever read locks we've - * already taken are no longer needed: - */ - - trans_for_each_path(trans, linked, iter) { - if (!linked->nodes_locked) - continue; - - for (i = 0; i < BTREE_MAX_DEPTH; i++) - if (btree_node_read_locked(linked, i)) { - btree_node_unlock(trans, linked, i); - btree_path_set_dirty(linked, BTREE_ITER_NEED_RELOCK); - } - } - - ret = __btree_node_lock_write(trans, path, b, true); + int ret = __btree_node_lock_write(trans, path, b, true); BUG_ON(ret); } -- cgit v1.2.3 From 1189bdda6c991cbf9342d84410042dd5f3a792e0 Mon Sep 17 00:00:00 2001 From: Kent Overstreet Date: Wed, 10 Apr 2024 01:30:22 -0400 Subject: bcachefs: Fix __bch2_btree_and_journal_iter_init_node_iter() We weren't respecting trans->journal_replay_not_finished - we shouldn't be searching the journal keys unless we have a ref on them. Signed-off-by: Kent Overstreet --- fs/bcachefs/btree_journal_iter.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/fs/bcachefs/btree_journal_iter.c b/fs/bcachefs/btree_journal_iter.c index a6413a8747d3..1e8cf49a6935 100644 --- a/fs/bcachefs/btree_journal_iter.c +++ b/fs/bcachefs/btree_journal_iter.c @@ -469,10 +469,15 @@ void __bch2_btree_and_journal_iter_init_node_iter(struct btree_trans *trans, iter->trans = trans; iter->b = b; iter->node_iter = node_iter; - bch2_journal_iter_init(trans->c, &iter->journal, b->c.btree_id, b->c.level, pos); - INIT_LIST_HEAD(&iter->journal.list); iter->pos = b->data->min_key; iter->at_end = false; + INIT_LIST_HEAD(&iter->journal.list); + + if (trans->journal_replay_not_finished) { + bch2_journal_iter_init(trans->c, &iter->journal, b->c.btree_id, b->c.level, pos); + if (!test_bit(BCH_FS_may_go_rw, &trans->c->flags)) + list_add(&iter->journal.list, &trans->c->journal_iters); + } } /* @@ -487,9 +492,6 @@ void bch2_btree_and_journal_iter_init_node_iter(struct btree_trans *trans, bch2_btree_node_iter_init_from_start(&node_iter, b); __bch2_btree_and_journal_iter_init_node_iter(trans, iter, b, node_iter, b->data->min_key); - if (trans->journal_replay_not_finished && - !test_bit(BCH_FS_may_go_rw, &trans->c->flags)) - list_add(&iter->journal.list, &trans->c->journal_iters); } /* sort and dedup all keys in the journal: */ -- cgit v1.2.3 From 65acf6e0501ac8880a4f73980d01b5d27648b956 Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Tue, 9 Apr 2024 12:07:41 +0000 Subject: netfilter: complete validation of user input In my recent commit, I missed that do_replace() handlers use copy_from_sockptr() (which I fixed), followed by unsafe copy_from_sockptr_offset() calls. In all functions, we can perform the @optlen validation before even calling xt_alloc_table_info() with the following check: if ((u64)optlen < (u64)tmp.size + sizeof(tmp)) return -EINVAL; Fixes: 0c83842df40f ("netfilter: validate user input for expected length") Reported-by: syzbot Signed-off-by: Eric Dumazet Reviewed-by: Pablo Neira Ayuso Link: https://lore.kernel.org/r/20240409120741.3538135-1-edumazet@google.com Signed-off-by: Jakub Kicinski --- net/ipv4/netfilter/arp_tables.c | 4 ++++ net/ipv4/netfilter/ip_tables.c | 4 ++++ net/ipv6/netfilter/ip6_tables.c | 4 ++++ 3 files changed, 12 insertions(+) diff --git a/net/ipv4/netfilter/arp_tables.c b/net/ipv4/netfilter/arp_tables.c index b150c9929b12..14365b20f1c5 100644 --- a/net/ipv4/netfilter/arp_tables.c +++ b/net/ipv4/netfilter/arp_tables.c @@ -966,6 +966,8 @@ static int do_replace(struct net *net, sockptr_t arg, unsigned int len) return -ENOMEM; if (tmp.num_counters == 0) return -EINVAL; + if ((u64)len < (u64)tmp.size + sizeof(tmp)) + return -EINVAL; tmp.name[sizeof(tmp.name)-1] = 0; @@ -1266,6 +1268,8 @@ static int compat_do_replace(struct net *net, sockptr_t arg, unsigned int len) return -ENOMEM; if (tmp.num_counters == 0) return -EINVAL; + if ((u64)len < (u64)tmp.size + sizeof(tmp)) + return -EINVAL; tmp.name[sizeof(tmp.name)-1] = 0; diff --git a/net/ipv4/netfilter/ip_tables.c b/net/ipv4/netfilter/ip_tables.c index 487670759578..fe89a056eb06 100644 --- a/net/ipv4/netfilter/ip_tables.c +++ b/net/ipv4/netfilter/ip_tables.c @@ -1118,6 +1118,8 @@ do_replace(struct net *net, sockptr_t arg, unsigned int len) return -ENOMEM; if (tmp.num_counters == 0) return -EINVAL; + if ((u64)len < (u64)tmp.size + sizeof(tmp)) + return -EINVAL; tmp.name[sizeof(tmp.name)-1] = 0; @@ -1504,6 +1506,8 @@ compat_do_replace(struct net *net, sockptr_t arg, unsigned int len) return -ENOMEM; if (tmp.num_counters == 0) return -EINVAL; + if ((u64)len < (u64)tmp.size + sizeof(tmp)) + return -EINVAL; tmp.name[sizeof(tmp.name)-1] = 0; diff --git a/net/ipv6/netfilter/ip6_tables.c b/net/ipv6/netfilter/ip6_tables.c index 636b360311c5..131f7bb2110d 100644 --- a/net/ipv6/netfilter/ip6_tables.c +++ b/net/ipv6/netfilter/ip6_tables.c @@ -1135,6 +1135,8 @@ do_replace(struct net *net, sockptr_t arg, unsigned int len) return -ENOMEM; if (tmp.num_counters == 0) return -EINVAL; + if ((u64)len < (u64)tmp.size + sizeof(tmp)) + return -EINVAL; tmp.name[sizeof(tmp.name)-1] = 0; @@ -1513,6 +1515,8 @@ compat_do_replace(struct net *net, sockptr_t arg, unsigned int len) return -ENOMEM; if (tmp.num_counters == 0) return -EINVAL; + if ((u64)len < (u64)tmp.size + sizeof(tmp)) + return -EINVAL; tmp.name[sizeof(tmp.name)-1] = 0; -- cgit v1.2.3 From 0553e753ea9ee724acaf6b3dfc7354702af83567 Mon Sep 17 00:00:00 2001 From: Shay Drory Date: Tue, 9 Apr 2024 22:08:09 +0300 Subject: net/mlx5: E-switch, store eswitch pointer before registering devlink_param Next patch will move devlink register to be first. Therefore, whenever mlx5 will register a param, the user will be notified. In order to notify the user, devlink is using the get() callback of the param. Hence, resources that are being used by the get() callback must be set before the devlink param is registered. Therefore, store eswitch pointer inside mdev before registering the param. Signed-off-by: Shay Drory Reviewed-by: Moshe Shemesh Signed-off-by: Saeed Mahameed Signed-off-by: Tariq Toukan Link: https://lore.kernel.org/r/20240409190820.227554-2-tariqt@nvidia.com Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/mellanox/mlx5/core/eswitch.c | 9 +++------ drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c | 4 ++++ 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/drivers/net/ethernet/mellanox/mlx5/core/eswitch.c b/drivers/net/ethernet/mellanox/mlx5/core/eswitch.c index 3047d7015c52..1789800faaeb 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/eswitch.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/eswitch.c @@ -1868,6 +1868,7 @@ int mlx5_eswitch_init(struct mlx5_core_dev *dev) if (err) goto abort; + dev->priv.eswitch = esw; err = esw_offloads_init(esw); if (err) goto reps_err; @@ -1892,11 +1893,6 @@ int mlx5_eswitch_init(struct mlx5_core_dev *dev) esw->offloads.encap = DEVLINK_ESWITCH_ENCAP_MODE_BASIC; else esw->offloads.encap = DEVLINK_ESWITCH_ENCAP_MODE_NONE; - if (MLX5_ESWITCH_MANAGER(dev) && - mlx5_esw_vport_match_metadata_supported(esw)) - esw->flags |= MLX5_ESWITCH_VPORT_MATCH_METADATA; - - dev->priv.eswitch = esw; BLOCKING_INIT_NOTIFIER_HEAD(&esw->n_head); esw_info(dev, @@ -1908,6 +1904,7 @@ int mlx5_eswitch_init(struct mlx5_core_dev *dev) reps_err: mlx5_esw_vports_cleanup(esw); + dev->priv.eswitch = NULL; abort: if (esw->work_queue) destroy_workqueue(esw->work_queue); @@ -1926,7 +1923,6 @@ void mlx5_eswitch_cleanup(struct mlx5_eswitch *esw) esw_info(esw->dev, "cleanup\n"); - esw->dev->priv.eswitch = NULL; destroy_workqueue(esw->work_queue); WARN_ON(refcount_read(&esw->qos.refcnt)); mutex_destroy(&esw->state_lock); @@ -1937,6 +1933,7 @@ void mlx5_eswitch_cleanup(struct mlx5_eswitch *esw) mutex_destroy(&esw->offloads.encap_tbl_lock); mutex_destroy(&esw->offloads.decap_tbl_lock); esw_offloads_cleanup(esw); + esw->dev->priv.eswitch = NULL; mlx5_esw_vports_cleanup(esw); debugfs_remove_recursive(esw->debugfs_root); devl_params_unregister(priv_to_devlink(esw->dev), mlx5_eswitch_params, diff --git a/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c b/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c index baaae628b0a0..e3cce110e52f 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c @@ -2476,6 +2476,10 @@ int esw_offloads_init(struct mlx5_eswitch *esw) if (err) return err; + if (MLX5_ESWITCH_MANAGER(esw->dev) && + mlx5_esw_vport_match_metadata_supported(esw)) + esw->flags |= MLX5_ESWITCH_VPORT_MATCH_METADATA; + err = devl_params_register(priv_to_devlink(esw->dev), esw_devlink_params, ARRAY_SIZE(esw_devlink_params)); -- cgit v1.2.3 From c6e77aa9dd82bc18a89bf49418f8f7e961cfccc8 Mon Sep 17 00:00:00 2001 From: Shay Drory Date: Tue, 9 Apr 2024 22:08:10 +0300 Subject: net/mlx5: Register devlink first under devlink lock In case device is having a non fatal FW error during probe, the driver will report the error to user via devlink. This will trigger a WARN_ON, since mlx5 is calling devlink_register() last. In order to avoid the WARN_ON[1], change mlx5 to invoke devl_register() first under devlink lock. [1] WARNING: CPU: 5 PID: 227 at net/devlink/health.c:483 devlink_recover_notify.constprop.0+0xb8/0xc0 CPU: 5 PID: 227 Comm: kworker/u16:3 Not tainted 6.4.0-rc5_for_upstream_min_debug_2023_06_12_12_38 #1 Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS rel-1.13.0-0-gf21b5a4aeb02-prebuilt.qemu.org 04/01/2014 Workqueue: mlx5_health0000:08:00.0 mlx5_fw_reporter_err_work [mlx5_core] RIP: 0010:devlink_recover_notify.constprop.0+0xb8/0xc0 Call Trace: ? __warn+0x79/0x120 ? devlink_recover_notify.constprop.0+0xb8/0xc0 ? report_bug+0x17c/0x190 ? handle_bug+0x3c/0x60 ? exc_invalid_op+0x14/0x70 ? asm_exc_invalid_op+0x16/0x20 ? devlink_recover_notify.constprop.0+0xb8/0xc0 devlink_health_report+0x4a/0x1c0 mlx5_fw_reporter_err_work+0xa4/0xd0 [mlx5_core] process_one_work+0x1bb/0x3c0 ? process_one_work+0x3c0/0x3c0 worker_thread+0x4d/0x3c0 ? process_one_work+0x3c0/0x3c0 kthread+0xc6/0xf0 ? kthread_complete_and_exit+0x20/0x20 ret_from_fork+0x1f/0x30 Fixes: cf530217408e ("devlink: Notify users when objects are accessible") Signed-off-by: Shay Drory Reviewed-by: Moshe Shemesh Signed-off-by: Saeed Mahameed Signed-off-by: Tariq Toukan Link: https://lore.kernel.org/r/20240409190820.227554-3-tariqt@nvidia.com Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/mellanox/mlx5/core/main.c | 37 ++++++++++++---------- .../ethernet/mellanox/mlx5/core/sf/dev/driver.c | 1 - 2 files changed, 20 insertions(+), 18 deletions(-) diff --git a/drivers/net/ethernet/mellanox/mlx5/core/main.c b/drivers/net/ethernet/mellanox/mlx5/core/main.c index c2593625c09a..59806553889e 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/main.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/main.c @@ -1480,6 +1480,14 @@ int mlx5_init_one_devl_locked(struct mlx5_core_dev *dev) if (err) goto err_register; + err = mlx5_crdump_enable(dev); + if (err) + mlx5_core_err(dev, "mlx5_crdump_enable failed with error code %d\n", err); + + err = mlx5_hwmon_dev_register(dev); + if (err) + mlx5_core_err(dev, "mlx5_hwmon_dev_register failed with error code %d\n", err); + mutex_unlock(&dev->intf_state_mutex); return 0; @@ -1505,7 +1513,10 @@ int mlx5_init_one(struct mlx5_core_dev *dev) int err; devl_lock(devlink); + devl_register(devlink); err = mlx5_init_one_devl_locked(dev); + if (err) + devl_unregister(devlink); devl_unlock(devlink); return err; } @@ -1517,6 +1528,8 @@ void mlx5_uninit_one(struct mlx5_core_dev *dev) devl_lock(devlink); mutex_lock(&dev->intf_state_mutex); + mlx5_hwmon_dev_unregister(dev); + mlx5_crdump_disable(dev); mlx5_unregister_device(dev); if (!test_bit(MLX5_INTERFACE_STATE_UP, &dev->intf_state)) { @@ -1534,6 +1547,7 @@ void mlx5_uninit_one(struct mlx5_core_dev *dev) mlx5_function_teardown(dev, true); out: mutex_unlock(&dev->intf_state_mutex); + devl_unregister(devlink); devl_unlock(devlink); } @@ -1680,16 +1694,20 @@ int mlx5_init_one_light(struct mlx5_core_dev *dev) } devl_lock(devlink); + devl_register(devlink); + err = mlx5_devlink_params_register(priv_to_devlink(dev)); - devl_unlock(devlink); if (err) { mlx5_core_warn(dev, "mlx5_devlink_param_reg err = %d\n", err); goto query_hca_caps_err; } + devl_unlock(devlink); return 0; query_hca_caps_err: + devl_unregister(devlink); + devl_unlock(devlink); mlx5_function_disable(dev, true); out: dev->state = MLX5_DEVICE_STATE_INTERNAL_ERROR; @@ -1702,6 +1720,7 @@ void mlx5_uninit_one_light(struct mlx5_core_dev *dev) devl_lock(devlink); mlx5_devlink_params_unregister(priv_to_devlink(dev)); + devl_unregister(devlink); devl_unlock(devlink); if (dev->state != MLX5_DEVICE_STATE_UP) return; @@ -1943,16 +1962,7 @@ static int probe_one(struct pci_dev *pdev, const struct pci_device_id *id) goto err_init_one; } - err = mlx5_crdump_enable(dev); - if (err) - dev_err(&pdev->dev, "mlx5_crdump_enable failed with error code %d\n", err); - - err = mlx5_hwmon_dev_register(dev); - if (err) - mlx5_core_err(dev, "mlx5_hwmon_dev_register failed with error code %d\n", err); - pci_save_state(pdev); - devlink_register(devlink); return 0; err_init_one: @@ -1973,16 +1983,9 @@ static void remove_one(struct pci_dev *pdev) struct devlink *devlink = priv_to_devlink(dev); set_bit(MLX5_BREAK_FW_WAIT, &dev->intf_state); - /* mlx5_drain_fw_reset() and mlx5_drain_health_wq() are using - * devlink notify APIs. - * Hence, we must drain them before unregistering the devlink. - */ mlx5_drain_fw_reset(dev); mlx5_drain_health_wq(dev); - devlink_unregister(devlink); mlx5_sriov_disable(pdev, false); - mlx5_hwmon_dev_unregister(dev); - mlx5_crdump_disable(dev); mlx5_uninit_one(dev); mlx5_pci_close(dev); mlx5_mdev_uninit(dev); diff --git a/drivers/net/ethernet/mellanox/mlx5/core/sf/dev/driver.c b/drivers/net/ethernet/mellanox/mlx5/core/sf/dev/driver.c index bc863e1f062e..e3bf8c7e4baa 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/sf/dev/driver.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/sf/dev/driver.c @@ -101,7 +101,6 @@ static void mlx5_sf_dev_remove(struct auxiliary_device *adev) devlink = priv_to_devlink(mdev); set_bit(MLX5_BREAK_FW_WAIT, &mdev->intf_state); mlx5_drain_health_wq(mdev); - devlink_unregister(devlink); if (mlx5_dev_is_lightweight(mdev)) mlx5_uninit_one_light(mdev); else -- cgit v1.2.3 From 9f7e8fbb91f8fa29548e2f6ab50c03b628c67ede Mon Sep 17 00:00:00 2001 From: Michael Liang Date: Tue, 9 Apr 2024 22:08:11 +0300 Subject: net/mlx5: offset comp irq index in name by one The mlx5 comp irq name scheme is changed a little bit between commit 3663ad34bc70 ("net/mlx5: Shift control IRQ to the last index") and commit 3354822cde5a ("net/mlx5: Use dynamic msix vectors allocation"). The index in the comp irq name used to start from 0 but now it starts from 1. There is nothing critical here, but it's harmless to change back to the old behavior, a.k.a starting from 0. Fixes: 3354822cde5a ("net/mlx5: Use dynamic msix vectors allocation") Reviewed-by: Mohamed Khalfella Reviewed-by: Yuanyuan Zhong Signed-off-by: Michael Liang Reviewed-by: Shay Drory Signed-off-by: Saeed Mahameed Signed-off-by: Tariq Toukan Link: https://lore.kernel.org/r/20240409190820.227554-4-tariqt@nvidia.com Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/mellanox/mlx5/core/pci_irq.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/net/ethernet/mellanox/mlx5/core/pci_irq.c b/drivers/net/ethernet/mellanox/mlx5/core/pci_irq.c index 4dcf995cb1a2..6bac8ad70ba6 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/pci_irq.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/pci_irq.c @@ -19,6 +19,7 @@ #define MLX5_IRQ_CTRL_SF_MAX 8 /* min num of vectors for SFs to be enabled */ #define MLX5_IRQ_VEC_COMP_BASE_SF 2 +#define MLX5_IRQ_VEC_COMP_BASE 1 #define MLX5_EQ_SHARE_IRQ_MAX_COMP (8) #define MLX5_EQ_SHARE_IRQ_MAX_CTRL (UINT_MAX) @@ -246,6 +247,7 @@ static void irq_set_name(struct mlx5_irq_pool *pool, char *name, int vecidx) return; } + vecidx -= MLX5_IRQ_VEC_COMP_BASE; snprintf(name, MLX5_MAX_IRQ_NAME, "mlx5_comp%d", vecidx); } @@ -585,7 +587,7 @@ struct mlx5_irq *mlx5_irq_request_vector(struct mlx5_core_dev *dev, u16 cpu, struct mlx5_irq_table *table = mlx5_irq_table_get(dev); struct mlx5_irq_pool *pool = table->pcif_pool; struct irq_affinity_desc af_desc; - int offset = 1; + int offset = MLX5_IRQ_VEC_COMP_BASE; if (!pool->xa_num_irqs.max) offset = 0; -- cgit v1.2.3 From 7c6782ad4911cbee874e85630226ed389ff2e453 Mon Sep 17 00:00:00 2001 From: Cosmin Ratiu Date: Tue, 9 Apr 2024 22:08:12 +0300 Subject: net/mlx5: Properly link new fs rules into the tree Previously, add_rule_fg would only add newly created rules from the handle into the tree when they had a refcount of 1. On the other hand, create_flow_handle tries hard to find and reference already existing identical rules instead of creating new ones. These two behaviors can result in a situation where create_flow_handle 1) creates a new rule and references it, then 2) in a subsequent step during the same handle creation references it again, resulting in a rule with a refcount of 2 that is not linked into the tree, will have a NULL parent and root and will result in a crash when the flow group is deleted because del_sw_hw_rule, invoked on rule deletion, assumes node->parent is != NULL. This happened in the wild, due to another bug related to incorrect handling of duplicate pkt_reformat ids, which lead to the code in create_flow_handle incorrectly referencing a just-added rule in the same flow handle, resulting in the problem described above. Full details are at [1]. This patch changes add_rule_fg to add new rules without parents into the tree, properly initializing them and avoiding the crash. This makes it more consistent with how rules are added to an FTE in create_flow_handle. Fixes: 74491de93712 ("net/mlx5: Add multi dest support") Link: https://lore.kernel.org/netdev/ea5264d6-6b55-4449-a602-214c6f509c1e@163.com/T/#u [1] Signed-off-by: Cosmin Ratiu Reviewed-by: Tariq Toukan Reviewed-by: Mark Bloch Signed-off-by: Saeed Mahameed Signed-off-by: Tariq Toukan Link: https://lore.kernel.org/r/20240409190820.227554-5-tariqt@nvidia.com Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/mellanox/mlx5/core/fs_core.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/net/ethernet/mellanox/mlx5/core/fs_core.c b/drivers/net/ethernet/mellanox/mlx5/core/fs_core.c index e6bfa7e4f146..2a9421342a50 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/fs_core.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/fs_core.c @@ -1808,8 +1808,9 @@ static struct mlx5_flow_handle *add_rule_fg(struct mlx5_flow_group *fg, } trace_mlx5_fs_set_fte(fte, false); + /* Link newly added rules into the tree. */ for (i = 0; i < handle->num_rules; i++) { - if (refcount_read(&handle->rule[i]->node.refcount) == 1) { + if (!handle->rule[i]->node.parent) { tree_add_node(&handle->rule[i]->node, &fte->node); trace_mlx5_fs_add_rule(handle->rule[i]); } -- cgit v1.2.3 From 9eca93f4d5ab03905516a68683674d9c50ff95bd Mon Sep 17 00:00:00 2001 From: Cosmin Ratiu Date: Tue, 9 Apr 2024 22:08:13 +0300 Subject: net/mlx5: Correctly compare pkt reformat ids struct mlx5_pkt_reformat contains a naked union of a u32 id and a dr_action pointer which is used when the action is SW-managed (when pkt_reformat.owner is set to MLX5_FLOW_RESOURCE_OWNER_SW). Using id directly in that case is incorrect, as it maps to the least significant 32 bits of the 64-bit pointer in mlx5_fs_dr_action and not to the pkt reformat id allocated in firmware. For the purpose of comparing whether two rules are identical, interpreting the least significant 32 bits of the mlx5_fs_dr_action pointer as an id mostly works... until it breaks horribly and produces the outcome described in [1]. This patch fixes mlx5_flow_dests_cmp to correctly compare ids using mlx5_fs_dr_action_get_pkt_reformat_id for the SW-managed rules. Link: https://lore.kernel.org/netdev/ea5264d6-6b55-4449-a602-214c6f509c1e@163.com/T/#u [1] Fixes: 6a48faeeca10 ("net/mlx5: Add direct rule fs_cmd implementation") Signed-off-by: Cosmin Ratiu Reviewed-by: Mark Bloch Reviewed-by: Tariq Toukan Signed-off-by: Saeed Mahameed Signed-off-by: Tariq Toukan Link: https://lore.kernel.org/r/20240409190820.227554-6-tariqt@nvidia.com Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/mellanox/mlx5/core/fs_core.c | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/drivers/net/ethernet/mellanox/mlx5/core/fs_core.c b/drivers/net/ethernet/mellanox/mlx5/core/fs_core.c index 2a9421342a50..cf085a478e3e 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/fs_core.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/fs_core.c @@ -1664,6 +1664,16 @@ static int create_auto_flow_group(struct mlx5_flow_table *ft, return err; } +static bool mlx5_pkt_reformat_cmp(struct mlx5_pkt_reformat *p1, + struct mlx5_pkt_reformat *p2) +{ + return p1->owner == p2->owner && + (p1->owner == MLX5_FLOW_RESOURCE_OWNER_FW ? + p1->id == p2->id : + mlx5_fs_dr_action_get_pkt_reformat_id(p1) == + mlx5_fs_dr_action_get_pkt_reformat_id(p2)); +} + static bool mlx5_flow_dests_cmp(struct mlx5_flow_destination *d1, struct mlx5_flow_destination *d2) { @@ -1675,8 +1685,8 @@ static bool mlx5_flow_dests_cmp(struct mlx5_flow_destination *d1, ((d1->vport.flags & MLX5_FLOW_DEST_VPORT_VHCA_ID) ? (d1->vport.vhca_id == d2->vport.vhca_id) : true) && ((d1->vport.flags & MLX5_FLOW_DEST_VPORT_REFORMAT_ID) ? - (d1->vport.pkt_reformat->id == - d2->vport.pkt_reformat->id) : true)) || + mlx5_pkt_reformat_cmp(d1->vport.pkt_reformat, + d2->vport.pkt_reformat) : true)) || (d1->type == MLX5_FLOW_DESTINATION_TYPE_FLOW_TABLE && d1->ft == d2->ft) || (d1->type == MLX5_FLOW_DESTINATION_TYPE_TIR && -- cgit v1.2.3 From ee3572409f74a838154af74ce1e56e62c17786a8 Mon Sep 17 00:00:00 2001 From: Carolina Jubran Date: Tue, 9 Apr 2024 22:08:14 +0300 Subject: net/mlx5e: RSS, Block changing channels number when RXFH is configured Changing the channels number after configuring the receive flow hash indirection table may affect the RSS table size. The previous configuration may no longer be compatible with the new receive flow hash indirection table. Block changing the channels number when RXFH is configured and changing the channels number requires resizing the RSS table size. Fixes: 74a8dadac17e ("net/mlx5e: Preparations for supporting larger number of channels") Signed-off-by: Carolina Jubran Reviewed-by: Tariq Toukan Signed-off-by: Saeed Mahameed Signed-off-by: Tariq Toukan Link: https://lore.kernel.org/r/20240409190820.227554-7-tariqt@nvidia.com Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c b/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c index cc51ce16df14..93461b0c5703 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c @@ -451,6 +451,23 @@ int mlx5e_ethtool_set_channels(struct mlx5e_priv *priv, mutex_lock(&priv->state_lock); + /* If RXFH is configured, changing the channels number is allowed only if + * it does not require resizing the RSS table. This is because the previous + * configuration may no longer be compatible with the new RSS table. + */ + if (netif_is_rxfh_configured(priv->netdev)) { + int cur_rqt_size = mlx5e_rqt_size(priv->mdev, cur_params->num_channels); + int new_rqt_size = mlx5e_rqt_size(priv->mdev, count); + + if (new_rqt_size != cur_rqt_size) { + err = -EINVAL; + netdev_err(priv->netdev, + "%s: RXFH is configured, block changing channels number that affects RSS table size (new: %d, current: %d)\n", + __func__, new_rqt_size, cur_rqt_size); + goto out; + } + } + /* Don't allow changing the number of channels if HTB offload is active, * because the numeration of the QoS SQs will change, while per-queue * qdiscs are attached. -- cgit v1.2.3 From ecb829459a841198e142f72fadab56424ae96519 Mon Sep 17 00:00:00 2001 From: Carolina Jubran Date: Tue, 9 Apr 2024 22:08:15 +0300 Subject: net/mlx5e: Fix mlx5e_priv_init() cleanup flow When mlx5e_priv_init() fails, the cleanup flow calls mlx5e_selq_cleanup which calls mlx5e_selq_apply() that assures that the `priv->state_lock` is held using lockdep_is_held(). Acquire the state_lock in mlx5e_selq_cleanup(). Kernel log: ============================= WARNING: suspicious RCU usage 6.8.0-rc3_net_next_841a9b5 #1 Not tainted ----------------------------- drivers/net/ethernet/mellanox/mlx5/core/en/selq.c:124 suspicious rcu_dereference_protected() usage! other info that might help us debug this: rcu_scheduler_active = 2, debug_locks = 1 2 locks held by systemd-modules/293: #0: ffffffffa05067b0 (devices_rwsem){++++}-{3:3}, at: ib_register_client+0x109/0x1b0 [ib_core] #1: ffff8881096c65c0 (&device->client_data_rwsem){++++}-{3:3}, at: add_client_context+0x104/0x1c0 [ib_core] stack backtrace: CPU: 4 PID: 293 Comm: systemd-modules Not tainted 6.8.0-rc3_net_next_841a9b5 #1 Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS rel-1.13.0-0-gf21b5a4aeb02-prebuilt.qemu.org 04/01/2014 Call Trace: dump_stack_lvl+0x8a/0xa0 lockdep_rcu_suspicious+0x154/0x1a0 mlx5e_selq_apply+0x94/0xa0 [mlx5_core] mlx5e_selq_cleanup+0x3a/0x60 [mlx5_core] mlx5e_priv_init+0x2be/0x2f0 [mlx5_core] mlx5_rdma_setup_rn+0x7c/0x1a0 [mlx5_core] rdma_init_netdev+0x4e/0x80 [ib_core] ? mlx5_rdma_netdev_free+0x70/0x70 [mlx5_core] ipoib_intf_init+0x64/0x550 [ib_ipoib] ipoib_intf_alloc+0x4e/0xc0 [ib_ipoib] ipoib_add_one+0xb0/0x360 [ib_ipoib] add_client_context+0x112/0x1c0 [ib_core] ib_register_client+0x166/0x1b0 [ib_core] ? 0xffffffffa0573000 ipoib_init_module+0xeb/0x1a0 [ib_ipoib] do_one_initcall+0x61/0x250 do_init_module+0x8a/0x270 init_module_from_file+0x8b/0xd0 idempotent_init_module+0x17d/0x230 __x64_sys_finit_module+0x61/0xb0 do_syscall_64+0x71/0x140 entry_SYSCALL_64_after_hwframe+0x46/0x4e Fixes: 8bf30be75069 ("net/mlx5e: Introduce select queue parameters") Signed-off-by: Carolina Jubran Reviewed-by: Tariq Toukan Reviewed-by: Dragos Tatulea Signed-off-by: Saeed Mahameed Signed-off-by: Tariq Toukan Link: https://lore.kernel.org/r/20240409190820.227554-8-tariqt@nvidia.com Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/mellanox/mlx5/core/en/selq.c | 2 ++ drivers/net/ethernet/mellanox/mlx5/core/en_main.c | 2 -- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/selq.c b/drivers/net/ethernet/mellanox/mlx5/core/en/selq.c index f675b1926340..f66bbc846464 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en/selq.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en/selq.c @@ -57,6 +57,7 @@ int mlx5e_selq_init(struct mlx5e_selq *selq, struct mutex *state_lock) void mlx5e_selq_cleanup(struct mlx5e_selq *selq) { + mutex_lock(selq->state_lock); WARN_ON_ONCE(selq->is_prepared); kvfree(selq->standby); @@ -67,6 +68,7 @@ void mlx5e_selq_cleanup(struct mlx5e_selq *selq) kvfree(selq->standby); selq->standby = NULL; + mutex_unlock(selq->state_lock); } void mlx5e_selq_prepare_params(struct mlx5e_selq *selq, struct mlx5e_params *params) diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c index 91848eae4565..b375ef268671 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c @@ -5726,9 +5726,7 @@ void mlx5e_priv_cleanup(struct mlx5e_priv *priv) kfree(priv->tx_rates); kfree(priv->txq2sq); destroy_workqueue(priv->wq); - mutex_lock(&priv->state_lock); mlx5e_selq_cleanup(&priv->selq); - mutex_unlock(&priv->state_lock); free_cpumask_var(priv->scratchpad.cpumask); for (i = 0; i < priv->htb_max_qos_sqs; i++) -- cgit v1.2.3 From 2f436f1869771d46e1a9f85738d5a1a7c5653a4e Mon Sep 17 00:00:00 2001 From: Carolina Jubran Date: Tue, 9 Apr 2024 22:08:16 +0300 Subject: net/mlx5e: HTB, Fix inconsistencies with QoS SQs number When creating a new HTB class while the interface is down, the variable that follows the number of QoS SQs (htb_max_qos_sqs) may not be consistent with the number of HTB classes. Previously, we compared these two values to ensure that the node_qid is lower than the number of QoS SQs, and we allocated stats for that SQ when they are equal. Change the check to compare the node_qid with the current number of leaf nodes and fix the checking conditions to ensure allocation of stats_list and stats for each node. Fixes: 214baf22870c ("net/mlx5e: Support HTB offload") Signed-off-by: Carolina Jubran Reviewed-by: Tariq Toukan Reviewed-by: Dragos Tatulea Signed-off-by: Saeed Mahameed Signed-off-by: Tariq Toukan Link: https://lore.kernel.org/r/20240409190820.227554-9-tariqt@nvidia.com Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/mellanox/mlx5/core/en/qos.c | 33 ++++++++++++------------ 1 file changed, 17 insertions(+), 16 deletions(-) diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/qos.c b/drivers/net/ethernet/mellanox/mlx5/core/en/qos.c index e87e26f2c669..6743806b8480 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en/qos.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en/qos.c @@ -83,24 +83,25 @@ int mlx5e_open_qos_sq(struct mlx5e_priv *priv, struct mlx5e_channels *chs, txq_ix = mlx5e_qid_from_qos(chs, node_qid); - WARN_ON(node_qid > priv->htb_max_qos_sqs); - if (node_qid == priv->htb_max_qos_sqs) { - struct mlx5e_sq_stats *stats, **stats_list = NULL; - - if (priv->htb_max_qos_sqs == 0) { - stats_list = kvcalloc(mlx5e_qos_max_leaf_nodes(priv->mdev), - sizeof(*stats_list), - GFP_KERNEL); - if (!stats_list) - return -ENOMEM; - } + WARN_ON(node_qid >= mlx5e_htb_cur_leaf_nodes(priv->htb)); + if (!priv->htb_qos_sq_stats) { + struct mlx5e_sq_stats **stats_list; + + stats_list = kvcalloc(mlx5e_qos_max_leaf_nodes(priv->mdev), + sizeof(*stats_list), GFP_KERNEL); + if (!stats_list) + return -ENOMEM; + + WRITE_ONCE(priv->htb_qos_sq_stats, stats_list); + } + + if (!priv->htb_qos_sq_stats[node_qid]) { + struct mlx5e_sq_stats *stats; + stats = kzalloc(sizeof(*stats), GFP_KERNEL); - if (!stats) { - kvfree(stats_list); + if (!stats) return -ENOMEM; - } - if (stats_list) - WRITE_ONCE(priv->htb_qos_sq_stats, stats_list); + WRITE_ONCE(priv->htb_qos_sq_stats[node_qid], stats); /* Order htb_max_qos_sqs increment after writing the array pointer. * Pairs with smp_load_acquire in en_stats.c. -- cgit v1.2.3 From 86b0ca5b118d3a0bae5e5645a13e66f8a4f6c525 Mon Sep 17 00:00:00 2001 From: Rahul Rameshbabu Date: Tue, 9 Apr 2024 22:08:17 +0300 Subject: net/mlx5e: Do not produce metadata freelist entries in Tx port ts WQE xmit Free Tx port timestamping metadata entries in the NAPI poll context and consume metadata enties in the WQE xmit path. Do not free a Tx port timestamping metadata entry in the WQE xmit path even in the error path to avoid a race between two metadata entry producers. Fixes: 3178308ad4ca ("net/mlx5e: Make tx_port_ts logic resilient to out-of-order CQEs") Signed-off-by: Rahul Rameshbabu Reviewed-by: Tariq Toukan Signed-off-by: Saeed Mahameed Signed-off-by: Tariq Toukan Link: https://lore.kernel.org/r/20240409190820.227554-10-tariqt@nvidia.com Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/mellanox/mlx5/core/en/ptp.h | 8 +++++++- drivers/net/ethernet/mellanox/mlx5/core/en_tx.c | 7 +++---- 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/ptp.h b/drivers/net/ethernet/mellanox/mlx5/core/en/ptp.h index 86f1854698b4..883c044852f1 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en/ptp.h +++ b/drivers/net/ethernet/mellanox/mlx5/core/en/ptp.h @@ -95,9 +95,15 @@ static inline void mlx5e_ptp_metadata_fifo_push(struct mlx5e_ptp_metadata_fifo * } static inline u8 +mlx5e_ptp_metadata_fifo_peek(struct mlx5e_ptp_metadata_fifo *fifo) +{ + return fifo->data[fifo->mask & fifo->cc]; +} + +static inline void mlx5e_ptp_metadata_fifo_pop(struct mlx5e_ptp_metadata_fifo *fifo) { - return fifo->data[fifo->mask & fifo->cc++]; + fifo->cc++; } static inline void diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_tx.c b/drivers/net/ethernet/mellanox/mlx5/core/en_tx.c index 2fa076b23fbe..e21a3b4128ce 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_tx.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_tx.c @@ -398,6 +398,8 @@ mlx5e_txwqe_complete(struct mlx5e_txqsq *sq, struct sk_buff *skb, (skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP))) { u8 metadata_index = be32_to_cpu(eseg->flow_table_metadata); + mlx5e_ptp_metadata_fifo_pop(&sq->ptpsq->metadata_freelist); + mlx5e_skb_cb_hwtstamp_init(skb); mlx5e_ptp_metadata_map_put(&sq->ptpsq->metadata_map, skb, metadata_index); @@ -496,9 +498,6 @@ mlx5e_sq_xmit_wqe(struct mlx5e_txqsq *sq, struct sk_buff *skb, err_drop: stats->dropped++; - if (unlikely(sq->ptpsq && (skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP))) - mlx5e_ptp_metadata_fifo_push(&sq->ptpsq->metadata_freelist, - be32_to_cpu(eseg->flow_table_metadata)); dev_kfree_skb_any(skb); mlx5e_tx_flush(sq); } @@ -657,7 +656,7 @@ static void mlx5e_cqe_ts_id_eseg(struct mlx5e_ptpsq *ptpsq, struct sk_buff *skb, { if (unlikely(skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP)) eseg->flow_table_metadata = - cpu_to_be32(mlx5e_ptp_metadata_fifo_pop(&ptpsq->metadata_freelist)); + cpu_to_be32(mlx5e_ptp_metadata_fifo_peek(&ptpsq->metadata_freelist)); } static void mlx5e_txwqe_build_eseg(struct mlx5e_priv *priv, struct mlx5e_txqsq *sq, -- cgit v1.2.3 From 49e6c9387051716169ff6a6c5ddd4d9f358db2e9 Mon Sep 17 00:00:00 2001 From: Carolina Jubran Date: Tue, 9 Apr 2024 22:08:18 +0300 Subject: net/mlx5e: RSS, Block XOR hash with over 128 channels When supporting more than 128 channels, the RQT size is calculated by multiplying the number of channels by 2 and rounding up to the nearest power of 2. The index of the RQT is derived from the RSS hash calculations. If XOR8 is used as the RSS hash function, there are only 256 possible hash results, and therefore, only 256 indexes can be reached in the RQT. Block setting the RSS hash function to XOR when the number of channels exceeds 128. Fixes: 74a8dadac17e ("net/mlx5e: Preparations for supporting larger number of channels") Signed-off-by: Carolina Jubran Signed-off-by: Tariq Toukan Link: https://lore.kernel.org/r/20240409190820.227554-11-tariqt@nvidia.com Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/mellanox/mlx5/core/en/rqt.c | 7 ++++++ drivers/net/ethernet/mellanox/mlx5/core/en/rqt.h | 1 + .../net/ethernet/mellanox/mlx5/core/en_ethtool.c | 28 ++++++++++++++++++++-- 3 files changed, 34 insertions(+), 2 deletions(-) diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/rqt.c b/drivers/net/ethernet/mellanox/mlx5/core/en/rqt.c index bcafb4bf9415..8d9a3b5ec973 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en/rqt.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en/rqt.c @@ -179,6 +179,13 @@ u32 mlx5e_rqt_size(struct mlx5_core_dev *mdev, unsigned int num_channels) return min_t(u32, rqt_size, max_cap_rqt_size); } +#define MLX5E_MAX_RQT_SIZE_ALLOWED_WITH_XOR8_HASH 256 + +unsigned int mlx5e_rqt_max_num_channels_allowed_for_xor8(void) +{ + return MLX5E_MAX_RQT_SIZE_ALLOWED_WITH_XOR8_HASH / MLX5E_UNIFORM_SPREAD_RQT_FACTOR; +} + void mlx5e_rqt_destroy(struct mlx5e_rqt *rqt) { mlx5_core_destroy_rqt(rqt->mdev, rqt->rqtn); diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/rqt.h b/drivers/net/ethernet/mellanox/mlx5/core/en/rqt.h index e0bc30308c77..2f9e04a8418f 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en/rqt.h +++ b/drivers/net/ethernet/mellanox/mlx5/core/en/rqt.h @@ -38,6 +38,7 @@ static inline u32 mlx5e_rqt_get_rqtn(struct mlx5e_rqt *rqt) } u32 mlx5e_rqt_size(struct mlx5_core_dev *mdev, unsigned int num_channels); +unsigned int mlx5e_rqt_max_num_channels_allowed_for_xor8(void); int mlx5e_rqt_redirect_direct(struct mlx5e_rqt *rqt, u32 rqn, u32 *vhca_id); int mlx5e_rqt_redirect_indir(struct mlx5e_rqt *rqt, u32 *rqns, u32 *vhca_ids, unsigned int num_rqns, diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c b/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c index 93461b0c5703..8f101181648c 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c @@ -451,6 +451,17 @@ int mlx5e_ethtool_set_channels(struct mlx5e_priv *priv, mutex_lock(&priv->state_lock); + if (mlx5e_rx_res_get_current_hash(priv->rx_res).hfunc == ETH_RSS_HASH_XOR) { + unsigned int xor8_max_channels = mlx5e_rqt_max_num_channels_allowed_for_xor8(); + + if (count > xor8_max_channels) { + err = -EINVAL; + netdev_err(priv->netdev, "%s: Requested number of channels (%d) exceeds the maximum allowed by the XOR8 RSS hfunc (%d)\n", + __func__, count, xor8_max_channels); + goto out; + } + } + /* If RXFH is configured, changing the channels number is allowed only if * it does not require resizing the RSS table. This is because the previous * configuration may no longer be compatible with the new RSS table. @@ -1298,17 +1309,30 @@ int mlx5e_set_rxfh(struct net_device *dev, struct ethtool_rxfh_param *rxfh, struct mlx5e_priv *priv = netdev_priv(dev); u32 *rss_context = &rxfh->rss_context; u8 hfunc = rxfh->hfunc; + unsigned int count; int err; mutex_lock(&priv->state_lock); + + count = priv->channels.params.num_channels; + + if (hfunc == ETH_RSS_HASH_XOR) { + unsigned int xor8_max_channels = mlx5e_rqt_max_num_channels_allowed_for_xor8(); + + if (count > xor8_max_channels) { + err = -EINVAL; + netdev_err(priv->netdev, "%s: Cannot set RSS hash function to XOR, current number of channels (%d) exceeds the maximum allowed for XOR8 RSS hfunc (%d)\n", + __func__, count, xor8_max_channels); + goto unlock; + } + } + if (*rss_context && rxfh->rss_delete) { err = mlx5e_rx_res_rss_destroy(priv->rx_res, *rss_context); goto unlock; } if (*rss_context == ETH_RXFH_CONTEXT_ALLOC) { - unsigned int count = priv->channels.params.num_channels; - err = mlx5e_rx_res_rss_init(priv->rx_res, rss_context, count); if (err) goto unlock; -- cgit v1.2.3 From 7772dc7460e8ef359f3eee88c3b708cb403e19af Mon Sep 17 00:00:00 2001 From: Tariq Toukan Date: Tue, 9 Apr 2024 22:08:19 +0300 Subject: net/mlx5: Disallow SRIOV switchdev mode when in multi-PF netdev Adaptations need to be made for the auxiliary device management in the core driver level. Block this combination for now. Fixes: 678eb448055a ("net/mlx5: SD, Implement basic query and instantiation") Signed-off-by: Tariq Toukan Reviewed-by: Dragos Tatulea Reviewed-by: Gal Pressman Link: https://lore.kernel.org/r/20240409190820.227554-12-tariqt@nvidia.com Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c b/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c index e3cce110e52f..1f60954c12f7 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c @@ -43,6 +43,7 @@ #include "rdma.h" #include "en.h" #include "fs_core.h" +#include "lib/mlx5.h" #include "lib/devcom.h" #include "lib/eq.h" #include "lib/fs_chains.h" @@ -3711,6 +3712,12 @@ int mlx5_devlink_eswitch_mode_set(struct devlink *devlink, u16 mode, if (esw_mode_from_devlink(mode, &mlx5_mode)) return -EINVAL; + if (mode == DEVLINK_ESWITCH_MODE_SWITCHDEV && mlx5_get_sd(esw->dev)) { + NL_SET_ERR_MSG_MOD(extack, + "Can't change E-Switch mode to switchdev when multi-PF netdev (Socket Direct) is configured."); + return -EPERM; + } + mlx5_lag_disable_change(esw->dev); err = mlx5_esw_try_lock(esw); if (err < 0) { -- cgit v1.2.3 From fe87922cee6161f066f4b9dd542033e048eeedaf Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Mon, 8 Apr 2024 09:41:10 +0200 Subject: net/mlx5: fix possible stack overflows A couple of debug functions use a 512 byte temporary buffer and call another function that has another buffer of the same size, which in turn exceeds the usual warning limit for excessive stack usage: drivers/net/ethernet/mellanox/mlx5/core/steering/dr_dbg.c:1073:1: error: stack frame size (1448) exceeds limit (1024) in 'dr_dump_start' [-Werror,-Wframe-larger-than] dr_dump_start(struct seq_file *file, loff_t *pos) drivers/net/ethernet/mellanox/mlx5/core/steering/dr_dbg.c:1009:1: error: stack frame size (1120) exceeds limit (1024) in 'dr_dump_domain' [-Werror,-Wframe-larger-than] dr_dump_domain(struct seq_file *file, struct mlx5dr_domain *dmn) drivers/net/ethernet/mellanox/mlx5/core/steering/dr_dbg.c:705:1: error: stack frame size (1104) exceeds limit (1024) in 'dr_dump_matcher_rx_tx' [-Werror,-Wframe-larger-than] dr_dump_matcher_rx_tx(struct seq_file *file, bool is_rx, Rework these so that each of the various code paths only ever has one of these buffers in it, and exactly the functions that declare one have the 'noinline_for_stack' annotation that prevents them from all being inlined into the same caller. Fixes: 917d1e799ddf ("net/mlx5: DR, Change SWS usage to debug fs seq_file interface") Reviewed-by: Simon Horman Reviewed-by: Jiri Pirko Link: https://lore.kernel.org/all/20240219100506.648089-1-arnd@kernel.org/ Signed-off-by: Arnd Bergmann Acked-by: Tariq Toukan Link: https://lore.kernel.org/r/20240408074142.3007036-1-arnd@kernel.org Signed-off-by: Jakub Kicinski --- .../ethernet/mellanox/mlx5/core/steering/dr_dbg.c | 82 +++++++++++----------- 1 file changed, 41 insertions(+), 41 deletions(-) diff --git a/drivers/net/ethernet/mellanox/mlx5/core/steering/dr_dbg.c b/drivers/net/ethernet/mellanox/mlx5/core/steering/dr_dbg.c index 64f4cc284aea..030a5776c937 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/steering/dr_dbg.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/steering/dr_dbg.c @@ -205,12 +205,11 @@ dr_dump_hex_print(char hex[DR_HEX_SIZE], char *src, u32 size) } static int -dr_dump_rule_action_mem(struct seq_file *file, const u64 rule_id, +dr_dump_rule_action_mem(struct seq_file *file, char *buff, const u64 rule_id, struct mlx5dr_rule_action_member *action_mem) { struct mlx5dr_action *action = action_mem->action; const u64 action_id = DR_DBG_PTR_TO_ID(action); - char buff[MLX5DR_DEBUG_DUMP_BUFF_LENGTH]; u64 hit_tbl_ptr, miss_tbl_ptr; u32 hit_tbl_id, miss_tbl_id; int ret; @@ -488,10 +487,9 @@ dr_dump_rule_action_mem(struct seq_file *file, const u64 rule_id, } static int -dr_dump_rule_mem(struct seq_file *file, struct mlx5dr_ste *ste, +dr_dump_rule_mem(struct seq_file *file, char *buff, struct mlx5dr_ste *ste, bool is_rx, const u64 rule_id, u8 format_ver) { - char buff[MLX5DR_DEBUG_DUMP_BUFF_LENGTH]; char hw_ste_dump[DR_HEX_SIZE]; u32 mem_rec_type; int ret; @@ -522,7 +520,8 @@ dr_dump_rule_mem(struct seq_file *file, struct mlx5dr_ste *ste, } static int -dr_dump_rule_rx_tx(struct seq_file *file, struct mlx5dr_rule_rx_tx *rule_rx_tx, +dr_dump_rule_rx_tx(struct seq_file *file, char *buff, + struct mlx5dr_rule_rx_tx *rule_rx_tx, bool is_rx, const u64 rule_id, u8 format_ver) { struct mlx5dr_ste *ste_arr[DR_RULE_MAX_STES + DR_ACTION_MAX_STES]; @@ -533,7 +532,7 @@ dr_dump_rule_rx_tx(struct seq_file *file, struct mlx5dr_rule_rx_tx *rule_rx_tx, return 0; while (i--) { - ret = dr_dump_rule_mem(file, ste_arr[i], is_rx, rule_id, + ret = dr_dump_rule_mem(file, buff, ste_arr[i], is_rx, rule_id, format_ver); if (ret < 0) return ret; @@ -542,7 +541,8 @@ dr_dump_rule_rx_tx(struct seq_file *file, struct mlx5dr_rule_rx_tx *rule_rx_tx, return 0; } -static int dr_dump_rule(struct seq_file *file, struct mlx5dr_rule *rule) +static noinline_for_stack int +dr_dump_rule(struct seq_file *file, struct mlx5dr_rule *rule) { struct mlx5dr_rule_action_member *action_mem; const u64 rule_id = DR_DBG_PTR_TO_ID(rule); @@ -565,19 +565,19 @@ static int dr_dump_rule(struct seq_file *file, struct mlx5dr_rule *rule) return ret; if (rx->nic_matcher) { - ret = dr_dump_rule_rx_tx(file, rx, true, rule_id, format_ver); + ret = dr_dump_rule_rx_tx(file, buff, rx, true, rule_id, format_ver); if (ret < 0) return ret; } if (tx->nic_matcher) { - ret = dr_dump_rule_rx_tx(file, tx, false, rule_id, format_ver); + ret = dr_dump_rule_rx_tx(file, buff, tx, false, rule_id, format_ver); if (ret < 0) return ret; } list_for_each_entry(action_mem, &rule->rule_actions_list, list) { - ret = dr_dump_rule_action_mem(file, rule_id, action_mem); + ret = dr_dump_rule_action_mem(file, buff, rule_id, action_mem); if (ret < 0) return ret; } @@ -586,10 +586,10 @@ static int dr_dump_rule(struct seq_file *file, struct mlx5dr_rule *rule) } static int -dr_dump_matcher_mask(struct seq_file *file, struct mlx5dr_match_param *mask, +dr_dump_matcher_mask(struct seq_file *file, char *buff, + struct mlx5dr_match_param *mask, u8 criteria, const u64 matcher_id) { - char buff[MLX5DR_DEBUG_DUMP_BUFF_LENGTH]; char dump[DR_HEX_SIZE]; int ret; @@ -681,10 +681,10 @@ dr_dump_matcher_mask(struct seq_file *file, struct mlx5dr_match_param *mask, } static int -dr_dump_matcher_builder(struct seq_file *file, struct mlx5dr_ste_build *builder, +dr_dump_matcher_builder(struct seq_file *file, char *buff, + struct mlx5dr_ste_build *builder, u32 index, bool is_rx, const u64 matcher_id) { - char buff[MLX5DR_DEBUG_DUMP_BUFF_LENGTH]; int ret; ret = snprintf(buff, MLX5DR_DEBUG_DUMP_BUFF_LENGTH, @@ -702,11 +702,10 @@ dr_dump_matcher_builder(struct seq_file *file, struct mlx5dr_ste_build *builder, } static int -dr_dump_matcher_rx_tx(struct seq_file *file, bool is_rx, +dr_dump_matcher_rx_tx(struct seq_file *file, char *buff, bool is_rx, struct mlx5dr_matcher_rx_tx *matcher_rx_tx, const u64 matcher_id) { - char buff[MLX5DR_DEBUG_DUMP_BUFF_LENGTH]; enum dr_dump_rec_type rec_type; u64 s_icm_addr, e_icm_addr; int i, ret; @@ -731,7 +730,7 @@ dr_dump_matcher_rx_tx(struct seq_file *file, bool is_rx, return ret; for (i = 0; i < matcher_rx_tx->num_of_builders; i++) { - ret = dr_dump_matcher_builder(file, + ret = dr_dump_matcher_builder(file, buff, &matcher_rx_tx->ste_builder[i], i, is_rx, matcher_id); if (ret < 0) @@ -741,7 +740,7 @@ dr_dump_matcher_rx_tx(struct seq_file *file, bool is_rx, return 0; } -static int +static noinline_for_stack int dr_dump_matcher(struct seq_file *file, struct mlx5dr_matcher *matcher) { struct mlx5dr_matcher_rx_tx *rx = &matcher->rx; @@ -763,19 +762,19 @@ dr_dump_matcher(struct seq_file *file, struct mlx5dr_matcher *matcher) if (ret) return ret; - ret = dr_dump_matcher_mask(file, &matcher->mask, + ret = dr_dump_matcher_mask(file, buff, &matcher->mask, matcher->match_criteria, matcher_id); if (ret < 0) return ret; if (rx->nic_tbl) { - ret = dr_dump_matcher_rx_tx(file, true, rx, matcher_id); + ret = dr_dump_matcher_rx_tx(file, buff, true, rx, matcher_id); if (ret < 0) return ret; } if (tx->nic_tbl) { - ret = dr_dump_matcher_rx_tx(file, false, tx, matcher_id); + ret = dr_dump_matcher_rx_tx(file, buff, false, tx, matcher_id); if (ret < 0) return ret; } @@ -803,11 +802,10 @@ dr_dump_matcher_all(struct seq_file *file, struct mlx5dr_matcher *matcher) } static int -dr_dump_table_rx_tx(struct seq_file *file, bool is_rx, +dr_dump_table_rx_tx(struct seq_file *file, char *buff, bool is_rx, struct mlx5dr_table_rx_tx *table_rx_tx, const u64 table_id) { - char buff[MLX5DR_DEBUG_DUMP_BUFF_LENGTH]; enum dr_dump_rec_type rec_type; u64 s_icm_addr; int ret; @@ -829,7 +827,8 @@ dr_dump_table_rx_tx(struct seq_file *file, bool is_rx, return 0; } -static int dr_dump_table(struct seq_file *file, struct mlx5dr_table *table) +static noinline_for_stack int +dr_dump_table(struct seq_file *file, struct mlx5dr_table *table) { struct mlx5dr_table_rx_tx *rx = &table->rx; struct mlx5dr_table_rx_tx *tx = &table->tx; @@ -848,14 +847,14 @@ static int dr_dump_table(struct seq_file *file, struct mlx5dr_table *table) return ret; if (rx->nic_dmn) { - ret = dr_dump_table_rx_tx(file, true, rx, + ret = dr_dump_table_rx_tx(file, buff, true, rx, DR_DBG_PTR_TO_ID(table)); if (ret < 0) return ret; } if (tx->nic_dmn) { - ret = dr_dump_table_rx_tx(file, false, tx, + ret = dr_dump_table_rx_tx(file, buff, false, tx, DR_DBG_PTR_TO_ID(table)); if (ret < 0) return ret; @@ -881,10 +880,10 @@ static int dr_dump_table_all(struct seq_file *file, struct mlx5dr_table *tbl) } static int -dr_dump_send_ring(struct seq_file *file, struct mlx5dr_send_ring *ring, +dr_dump_send_ring(struct seq_file *file, char *buff, + struct mlx5dr_send_ring *ring, const u64 domain_id) { - char buff[MLX5DR_DEBUG_DUMP_BUFF_LENGTH]; int ret; ret = snprintf(buff, MLX5DR_DEBUG_DUMP_BUFF_LENGTH, @@ -902,13 +901,13 @@ dr_dump_send_ring(struct seq_file *file, struct mlx5dr_send_ring *ring, return 0; } -static noinline_for_stack int +static int dr_dump_domain_info_flex_parser(struct seq_file *file, + char *buff, const char *flex_parser_name, const u8 flex_parser_value, const u64 domain_id) { - char buff[MLX5DR_DEBUG_DUMP_BUFF_LENGTH]; int ret; ret = snprintf(buff, MLX5DR_DEBUG_DUMP_BUFF_LENGTH, @@ -925,11 +924,11 @@ dr_dump_domain_info_flex_parser(struct seq_file *file, return 0; } -static noinline_for_stack int -dr_dump_domain_info_caps(struct seq_file *file, struct mlx5dr_cmd_caps *caps, +static int +dr_dump_domain_info_caps(struct seq_file *file, char *buff, + struct mlx5dr_cmd_caps *caps, const u64 domain_id) { - char buff[MLX5DR_DEBUG_DUMP_BUFF_LENGTH]; struct mlx5dr_cmd_vport_cap *vport_caps; unsigned long i, vports_num; int ret; @@ -969,34 +968,35 @@ dr_dump_domain_info_caps(struct seq_file *file, struct mlx5dr_cmd_caps *caps, } static int -dr_dump_domain_info(struct seq_file *file, struct mlx5dr_domain_info *info, +dr_dump_domain_info(struct seq_file *file, char *buff, + struct mlx5dr_domain_info *info, const u64 domain_id) { int ret; - ret = dr_dump_domain_info_caps(file, &info->caps, domain_id); + ret = dr_dump_domain_info_caps(file, buff, &info->caps, domain_id); if (ret < 0) return ret; - ret = dr_dump_domain_info_flex_parser(file, "icmp_dw0", + ret = dr_dump_domain_info_flex_parser(file, buff, "icmp_dw0", info->caps.flex_parser_id_icmp_dw0, domain_id); if (ret < 0) return ret; - ret = dr_dump_domain_info_flex_parser(file, "icmp_dw1", + ret = dr_dump_domain_info_flex_parser(file, buff, "icmp_dw1", info->caps.flex_parser_id_icmp_dw1, domain_id); if (ret < 0) return ret; - ret = dr_dump_domain_info_flex_parser(file, "icmpv6_dw0", + ret = dr_dump_domain_info_flex_parser(file, buff, "icmpv6_dw0", info->caps.flex_parser_id_icmpv6_dw0, domain_id); if (ret < 0) return ret; - ret = dr_dump_domain_info_flex_parser(file, "icmpv6_dw1", + ret = dr_dump_domain_info_flex_parser(file, buff, "icmpv6_dw1", info->caps.flex_parser_id_icmpv6_dw1, domain_id); if (ret < 0) @@ -1032,12 +1032,12 @@ dr_dump_domain(struct seq_file *file, struct mlx5dr_domain *dmn) if (ret) return ret; - ret = dr_dump_domain_info(file, &dmn->info, domain_id); + ret = dr_dump_domain_info(file, buff, &dmn->info, domain_id); if (ret < 0) return ret; if (dmn->info.supp_sw_steering) { - ret = dr_dump_send_ring(file, dmn->send_ring, domain_id); + ret = dr_dump_send_ring(file, buff, dmn->send_ring, domain_id); if (ret < 0) return ret; } -- cgit v1.2.3 From 2f7b1d8b5505efb0057cd1ab85fca206063ea4c3 Mon Sep 17 00:00:00 2001 From: Pin-yen Lin Date: Tue, 12 Mar 2024 19:51:55 +0800 Subject: clk: mediatek: Do a runtime PM get on controllers during probe mt8183-mfgcfg has a mutual dependency with genpd during the probing stage, which leads to a deadlock in the following call stack: CPU0: genpd_lock --> clk_prepare_lock genpd_power_off_work_fn() genpd_lock() generic_pm_domain::power_off() clk_unprepare() clk_prepare_lock() CPU1: clk_prepare_lock --> genpd_lock clk_register() __clk_core_init() clk_prepare_lock() clk_pm_runtime_get() genpd_lock() Do a runtime PM get at the probe function to make sure clk_register() won't acquire the genpd lock. Instead of only modifying mt8183-mfgcfg, do this on all mediatek clock controller probings because we don't believe this would cause any regression. Verified on MT8183 and MT8192 Chromebooks. Fixes: acddfc2c261b ("clk: mediatek: Add MT8183 clock support") Signed-off-by: Pin-yen Lin Link: https://lore.kernel.org/r/20240312115249.3341654-1-treapking@chromium.org Reviewed-by: AngeloGioacchino Del Regno Tested-by: AngeloGioacchino Del Regno Signed-off-by: Stephen Boyd --- drivers/clk/mediatek/clk-mtk.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/drivers/clk/mediatek/clk-mtk.c b/drivers/clk/mediatek/clk-mtk.c index 2e55368dc4d8..bd37ab4d1a9b 100644 --- a/drivers/clk/mediatek/clk-mtk.c +++ b/drivers/clk/mediatek/clk-mtk.c @@ -13,6 +13,7 @@ #include #include #include +#include #include #include "clk-mtk.h" @@ -494,6 +495,16 @@ static int __mtk_clk_simple_probe(struct platform_device *pdev, return IS_ERR(base) ? PTR_ERR(base) : -ENOMEM; } + + devm_pm_runtime_enable(&pdev->dev); + /* + * Do a pm_runtime_resume_and_get() to workaround a possible + * deadlock between clk_register() and the genpd framework. + */ + r = pm_runtime_resume_and_get(&pdev->dev); + if (r) + return r; + /* Calculate how many clk_hw_onecell_data entries to allocate */ num_clks = mcd->num_clks + mcd->num_composite_clks; num_clks += mcd->num_fixed_clks + mcd->num_factor_clks; @@ -574,6 +585,8 @@ static int __mtk_clk_simple_probe(struct platform_device *pdev, goto unregister_clks; } + pm_runtime_put(&pdev->dev); + return r; unregister_clks: @@ -604,6 +617,8 @@ free_data: free_base: if (mcd->shared_io && base) iounmap(base); + + pm_runtime_put(&pdev->dev); return r; } -- cgit v1.2.3 From d3e8a91a848a5941e3c31ecebd6b2612b37e01a6 Mon Sep 17 00:00:00 2001 From: Daniel Golle Date: Wed, 13 Mar 2024 22:05:37 +0000 Subject: clk: mediatek: mt7988-infracfg: fix clocks for 2nd PCIe port Due to what seems to be an undocumented oddity in MediaTek's MT7988 SoC design the CLK_INFRA_PCIE_PERI_26M_CK_P2 clock requires CLK_INFRA_PCIE_PERI_26M_CK_P3 to be enabled. This currently leads to PCIe port 2 not working in Linux. Reflect the apparent relationship in the clk driver to make sure PCIe port 2 of the MT7988 SoC works. Fixes: 4b4719437d85f ("clk: mediatek: add drivers for MT7988 SoC") Suggested-by: Sam Shih Signed-off-by: Daniel Golle Link: https://lore.kernel.org/r/1da2506a51f970706bf4ec9509dd04e0471065e5.1710367453.git.daniel@makrotopia.org Reviewed-by: AngeloGioacchino Del Regno Signed-off-by: Stephen Boyd --- drivers/clk/mediatek/clk-mt7988-infracfg.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/clk/mediatek/clk-mt7988-infracfg.c b/drivers/clk/mediatek/clk-mt7988-infracfg.c index 449041f8abbc..c8c023afe3e5 100644 --- a/drivers/clk/mediatek/clk-mt7988-infracfg.c +++ b/drivers/clk/mediatek/clk-mt7988-infracfg.c @@ -156,7 +156,7 @@ static const struct mtk_gate infra_clks[] = { GATE_INFRA0(CLK_INFRA_PCIE_PERI_26M_CK_P1, "infra_pcie_peri_ck_26m_ck_p1", "csw_infra_f26m_sel", 8), GATE_INFRA0(CLK_INFRA_PCIE_PERI_26M_CK_P2, "infra_pcie_peri_ck_26m_ck_p2", - "csw_infra_f26m_sel", 9), + "infra_pcie_peri_ck_26m_ck_p3", 9), GATE_INFRA0(CLK_INFRA_PCIE_PERI_26M_CK_P3, "infra_pcie_peri_ck_26m_ck_p3", "csw_infra_f26m_sel", 10), /* INFRA1 */ -- cgit v1.2.3 From 33623113a48ea906f1955cbf71094f6aa4462e8f Mon Sep 17 00:00:00 2001 From: Daniel Machon Date: Tue, 9 Apr 2024 12:41:59 +0200 Subject: net: sparx5: fix wrong config being used when reconfiguring PCS The wrong port config is being used if the PCS is reconfigured. Fix this by correctly using the new config instead of the old one. Fixes: 946e7fd5053a ("net: sparx5: add port module support") Signed-off-by: Daniel Machon Reviewed-by: Jacob Keller Link: https://lore.kernel.org/r/20240409-link-mode-reconfiguration-fix-v2-1-db6a507f3627@microchip.com Signed-off-by: Paolo Abeni --- drivers/net/ethernet/microchip/sparx5/sparx5_port.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/ethernet/microchip/sparx5/sparx5_port.c b/drivers/net/ethernet/microchip/sparx5/sparx5_port.c index 3a1b1a1f5a19..60dd2fd603a8 100644 --- a/drivers/net/ethernet/microchip/sparx5/sparx5_port.c +++ b/drivers/net/ethernet/microchip/sparx5/sparx5_port.c @@ -731,7 +731,7 @@ static int sparx5_port_pcs_low_set(struct sparx5 *sparx5, bool sgmii = false, inband_aneg = false; int err; - if (port->conf.inband) { + if (conf->inband) { if (conf->portmode == PHY_INTERFACE_MODE_SGMII || conf->portmode == PHY_INTERFACE_MODE_QSGMII) inband_aneg = true; /* Cisco-SGMII in-band-aneg */ @@ -948,7 +948,7 @@ int sparx5_port_pcs_set(struct sparx5 *sparx5, if (err) return -EINVAL; - if (port->conf.inband) { + if (conf->inband) { /* Enable/disable 1G counters in ASM */ spx5_rmw(ASM_PORT_CFG_CSC_STAT_DIS_SET(high_speed_dev), ASM_PORT_CFG_CSC_STAT_DIS, -- cgit v1.2.3 From d51dc8dd6ab6f93a894ff8b38d3b8d02c98eb9fb Mon Sep 17 00:00:00 2001 From: Gerd Bayer Date: Tue, 9 Apr 2024 13:37:53 +0200 Subject: Revert "s390/ism: fix receive message buffer allocation" This reverts commit 58effa3476536215530c9ec4910ffc981613b413. Review was not finished on this patch. So it's not ready for upstreaming. Signed-off-by: Gerd Bayer Link: https://lore.kernel.org/r/20240409113753.2181368-1-gbayer@linux.ibm.com Fixes: 58effa347653 ("s390/ism: fix receive message buffer allocation") Signed-off-by: Paolo Abeni --- drivers/s390/net/ism_drv.c | 38 +++++++++----------------------------- 1 file changed, 9 insertions(+), 29 deletions(-) diff --git a/drivers/s390/net/ism_drv.c b/drivers/s390/net/ism_drv.c index affb05521e14..2c8e964425dc 100644 --- a/drivers/s390/net/ism_drv.c +++ b/drivers/s390/net/ism_drv.c @@ -14,8 +14,6 @@ #include #include #include -#include -#include #include "ism.h" @@ -294,15 +292,13 @@ out: static void ism_free_dmb(struct ism_dev *ism, struct ism_dmb *dmb) { clear_bit(dmb->sba_idx, ism->sba_bitmap); - dma_unmap_page(&ism->pdev->dev, dmb->dma_addr, dmb->dmb_len, - DMA_FROM_DEVICE); - folio_put(virt_to_folio(dmb->cpu_addr)); + dma_free_coherent(&ism->pdev->dev, dmb->dmb_len, + dmb->cpu_addr, dmb->dma_addr); } static int ism_alloc_dmb(struct ism_dev *ism, struct ism_dmb *dmb) { unsigned long bit; - int rc; if (PAGE_ALIGN(dmb->dmb_len) > dma_get_max_seg_size(&ism->pdev->dev)) return -EINVAL; @@ -319,30 +315,14 @@ static int ism_alloc_dmb(struct ism_dev *ism, struct ism_dmb *dmb) test_and_set_bit(dmb->sba_idx, ism->sba_bitmap)) return -EINVAL; - dmb->cpu_addr = - folio_address(folio_alloc(GFP_KERNEL | __GFP_NOWARN | - __GFP_NOMEMALLOC | __GFP_NORETRY, - get_order(dmb->dmb_len))); + dmb->cpu_addr = dma_alloc_coherent(&ism->pdev->dev, dmb->dmb_len, + &dmb->dma_addr, + GFP_KERNEL | __GFP_NOWARN | + __GFP_NOMEMALLOC | __GFP_NORETRY); + if (!dmb->cpu_addr) + clear_bit(dmb->sba_idx, ism->sba_bitmap); - if (!dmb->cpu_addr) { - rc = -ENOMEM; - goto out_bit; - } - dmb->dma_addr = dma_map_page(&ism->pdev->dev, - virt_to_page(dmb->cpu_addr), 0, - dmb->dmb_len, DMA_FROM_DEVICE); - if (dma_mapping_error(&ism->pdev->dev, dmb->dma_addr)) { - rc = -ENOMEM; - goto out_free; - } - - return 0; - -out_free: - kfree(dmb->cpu_addr); -out_bit: - clear_bit(dmb->sba_idx, ism->sba_bitmap); - return rc; + return dmb->cpu_addr ? 0 : -ENOMEM; } int ism_register_dmb(struct ism_dev *ism, struct ism_dmb *dmb, -- cgit v1.2.3 From 17c560113231ddc20088553c7b499b289b664311 Mon Sep 17 00:00:00 2001 From: Arınç ÜNAL Date: Tue, 9 Apr 2024 18:01:14 +0300 Subject: net: dsa: mt7530: trap link-local frames regardless of ST Port State MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In Clause 5 of IEEE Std 802-2014, two sublayers of the data link layer (DLL) of the Open Systems Interconnection basic reference model (OSI/RM) are described; the medium access control (MAC) and logical link control (LLC) sublayers. The MAC sublayer is the one facing the physical layer. In 8.2 of IEEE Std 802.1Q-2022, the Bridge architecture is described. A Bridge component comprises a MAC Relay Entity for interconnecting the Ports of the Bridge, at least two Ports, and higher layer entities with at least a Spanning Tree Protocol Entity included. Each Bridge Port also functions as an end station and shall provide the MAC Service to an LLC Entity. Each instance of the MAC Service is provided to a distinct LLC Entity that supports protocol identification, multiplexing, and demultiplexing, for protocol data unit (PDU) transmission and reception by one or more higher layer entities. It is described in 8.13.9 of IEEE Std 802.1Q-2022 that in a Bridge, the LLC Entity associated with each Bridge Port is modeled as being directly connected to the attached Local Area Network (LAN). On the switch with CPU port architecture, CPU port functions as Management Port, and the Management Port functionality is provided by software which functions as an end station. Software is connected to an IEEE 802 LAN that is wholly contained within the system that incorporates the Bridge. Software provides access to the LLC Entity associated with each Bridge Port by the value of the source port field on the special tag on the frame received by software. We call frames that carry control information to determine the active topology and current extent of each Virtual Local Area Network (VLAN), i.e., spanning tree or Shortest Path Bridging (SPB) and Multiple VLAN Registration Protocol Data Units (MVRPDUs), and frames from other link constrained protocols, such as Extensible Authentication Protocol over LAN (EAPOL) and Link Layer Discovery Protocol (LLDP), link-local frames. They are not forwarded by a Bridge. Permanently configured entries in the filtering database (FDB) ensure that such frames are discarded by the Forwarding Process. In 8.6.3 of IEEE Std 802.1Q-2022, this is described in detail: Each of the reserved MAC addresses specified in Table 8-1 (01-80-C2-00-00-[00,01,02,03,04,05,06,07,08,09,0A,0B,0C,0D,0E,0F]) shall be permanently configured in the FDB in C-VLAN components and ERs. Each of the reserved MAC addresses specified in Table 8-2 (01-80-C2-00-00-[01,02,03,04,05,06,07,08,09,0A,0E]) shall be permanently configured in the FDB in S-VLAN components. Each of the reserved MAC addresses specified in Table 8-3 (01-80-C2-00-00-[01,02,04,0E]) shall be permanently configured in the FDB in TPMR components. The FDB entries for reserved MAC addresses shall specify filtering for all Bridge Ports and all VIDs. Management shall not provide the capability to modify or remove entries for reserved MAC addresses. The addresses in Table 8-1, Table 8-2, and Table 8-3 determine the scope of propagation of PDUs within a Bridged Network, as follows: The Nearest Bridge group address (01-80-C2-00-00-0E) is an address that no conformant Two-Port MAC Relay (TPMR) component, Service VLAN (S-VLAN) component, Customer VLAN (C-VLAN) component, or MAC Bridge can forward. PDUs transmitted using this destination address, or any other addresses that appear in Table 8-1, Table 8-2, and Table 8-3 (01-80-C2-00-00-[00,01,02,03,04,05,06,07,08,09,0A,0B,0C,0D,0E,0F]), can therefore travel no further than those stations that can be reached via a single individual LAN from the originating station. The Nearest non-TPMR Bridge group address (01-80-C2-00-00-03), is an address that no conformant S-VLAN component, C-VLAN component, or MAC Bridge can forward; however, this address is relayed by a TPMR component. PDUs using this destination address, or any of the other addresses that appear in both Table 8-1 and Table 8-2 but not in Table 8-3 (01-80-C2-00-00-[00,03,05,06,07,08,09,0A,0B,0C,0D,0F]), will be relayed by any TPMRs but will propagate no further than the nearest S-VLAN component, C-VLAN component, or MAC Bridge. The Nearest Customer Bridge group address (01-80-C2-00-00-00) is an address that no conformant C-VLAN component, MAC Bridge can forward; however, it is relayed by TPMR components and S-VLAN components. PDUs using this destination address, or any of the other addresses that appear in Table 8-1 but not in either Table 8-2 or Table 8-3 (01-80-C2-00-00-[00,0B,0C,0D,0F]), will be relayed by TPMR components and S-VLAN components but will propagate no further than the nearest C-VLAN component or MAC Bridge. Because the LLC Entity associated with each Bridge Port is provided via CPU port, we must not filter these frames but forward them to CPU port. In a Bridge, the transmission Port is majorly decided by ingress and egress rules, FDB, and spanning tree Port State functions of the Forwarding Process. For link-local frames, only CPU port should be designated as destination port in the FDB, and the other functions of the Forwarding Process must not interfere with the decision of the transmission Port. We call this process trapping frames to CPU port. Therefore, on the switch with CPU port architecture, link-local frames must be trapped to CPU port, and certain link-local frames received by a Port of a Bridge comprising a TPMR component or an S-VLAN component must be excluded from it. A Bridge of the switch with CPU port architecture cannot comprise a Two-Port MAC Relay (TPMR) component as a TPMR component supports only a subset of the functionality of a MAC Bridge. A Bridge comprising two Ports (Management Port doesn't count) of this architecture will either function as a standard MAC Bridge or a standard VLAN Bridge. Therefore, a Bridge of this architecture can only comprise S-VLAN components, C-VLAN components, or MAC Bridge components. Since there's no TPMR component, we don't need to relay PDUs using the destination addresses specified on the Nearest non-TPMR section, and the proportion of the Nearest Customer Bridge section where they must be relayed by TPMR components. One option to trap link-local frames to CPU port is to add static FDB entries with CPU port designated as destination port. However, because that Independent VLAN Learning (IVL) is being used on every VID, each entry only applies to a single VLAN Identifier (VID). For a Bridge comprising a MAC Bridge component or a C-VLAN component, there would have to be 16 times 4096 entries. This switch intellectual property can only hold a maximum of 2048 entries. Using this option, there also isn't a mechanism to prevent link-local frames from being discarded when the spanning tree Port State of the reception Port is discarding. The remaining option is to utilise the BPC, RGAC1, RGAC2, RGAC3, and RGAC4 registers. Whilst this applies to every VID, it doesn't contain all of the reserved MAC addresses without affecting the remaining Standard Group MAC Addresses. The REV_UN frame tag utilised using the RGAC4 register covers the remaining 01-80-C2-00-00-[04,05,06,07,08,09,0A,0B,0C,0D,0F] destination addresses. It also includes the 01-80-C2-00-00-22 to 01-80-C2-00-00-FF destination addresses which may be relayed by MAC Bridges or VLAN Bridges. The latter option provides better but not complete conformance. This switch intellectual property also does not provide a mechanism to trap link-local frames with specific destination addresses to CPU port by Bridge, to conform to the filtering rules for the distinct Bridge components. Therefore, regardless of the type of the Bridge component, link-local frames with these destination addresses will be trapped to CPU port: 01-80-C2-00-00-[00,01,02,03,0E] In a Bridge comprising a MAC Bridge component or a C-VLAN component: Link-local frames with these destination addresses won't be trapped to CPU port which won't conform to IEEE Std 802.1Q-2022: 01-80-C2-00-00-[04,05,06,07,08,09,0A,0B,0C,0D,0F] In a Bridge comprising an S-VLAN component: Link-local frames with these destination addresses will be trapped to CPU port which won't conform to IEEE Std 802.1Q-2022: 01-80-C2-00-00-00 Link-local frames with these destination addresses won't be trapped to CPU port which won't conform to IEEE Std 802.1Q-2022: 01-80-C2-00-00-[04,05,06,07,08,09,0A] Currently on this switch intellectual property, if the spanning tree Port State of the reception Port is discarding, link-local frames will be discarded. To trap link-local frames regardless of the spanning tree Port State, make the switch regard them as Bridge Protocol Data Units (BPDUs). This switch intellectual property only lets the frames regarded as BPDUs bypass the spanning tree Port State function of the Forwarding Process. With this change, the only remaining interference is the ingress rules. When the reception Port has no PVID assigned on software, VLAN-untagged frames won't be allowed in. There doesn't seem to be a mechanism on the switch intellectual property to have link-local frames bypass this function of the Forwarding Process. Fixes: b8f126a8d543 ("net-next: dsa: add dsa support for Mediatek MT7530 switch") Reviewed-by: Daniel Golle Signed-off-by: Arınç ÜNAL Link: https://lore.kernel.org/r/20240409-b4-for-net-mt7530-fix-link-local-when-stp-discarding-v2-1-07b1150164ac@arinc9.com Signed-off-by: Paolo Abeni --- drivers/net/dsa/mt7530.c | 229 ++++++++++++++++++++++++++++++++++++++++------- drivers/net/dsa/mt7530.h | 5 ++ 2 files changed, 200 insertions(+), 34 deletions(-) diff --git a/drivers/net/dsa/mt7530.c b/drivers/net/dsa/mt7530.c index 451ff0620c2e..c0d0bce0b594 100644 --- a/drivers/net/dsa/mt7530.c +++ b/drivers/net/dsa/mt7530.c @@ -950,20 +950,173 @@ static void mt7530_setup_port5(struct dsa_switch *ds, phy_interface_t interface) mutex_unlock(&priv->reg_mutex); } -/* On page 205, section "8.6.3 Frame filtering" of the active standard, IEEE Std - * 802.1Q™-2022, it is stated that frames with 01:80:C2:00:00:00-0F as MAC DA - * must only be propagated to C-VLAN and MAC Bridge components. That means - * VLAN-aware and VLAN-unaware bridges. On the switch designs with CPU ports, - * these frames are supposed to be processed by the CPU (software). So we make - * the switch only forward them to the CPU port. And if received from a CPU - * port, forward to a single port. The software is responsible of making the - * switch conform to the latter by setting a single port as destination port on - * the special tag. +/* In Clause 5 of IEEE Std 802-2014, two sublayers of the data link layer (DLL) + * of the Open Systems Interconnection basic reference model (OSI/RM) are + * described; the medium access control (MAC) and logical link control (LLC) + * sublayers. The MAC sublayer is the one facing the physical layer. * - * This switch intellectual property cannot conform to this part of the standard - * fully. Whilst the REV_UN frame tag covers the remaining :04-0D and :0F MAC - * DAs, it also includes :22-FF which the scope of propagation is not supposed - * to be restricted for these MAC DAs. + * In 8.2 of IEEE Std 802.1Q-2022, the Bridge architecture is described. A + * Bridge component comprises a MAC Relay Entity for interconnecting the Ports + * of the Bridge, at least two Ports, and higher layer entities with at least a + * Spanning Tree Protocol Entity included. + * + * Each Bridge Port also functions as an end station and shall provide the MAC + * Service to an LLC Entity. Each instance of the MAC Service is provided to a + * distinct LLC Entity that supports protocol identification, multiplexing, and + * demultiplexing, for protocol data unit (PDU) transmission and reception by + * one or more higher layer entities. + * + * It is described in 8.13.9 of IEEE Std 802.1Q-2022 that in a Bridge, the LLC + * Entity associated with each Bridge Port is modeled as being directly + * connected to the attached Local Area Network (LAN). + * + * On the switch with CPU port architecture, CPU port functions as Management + * Port, and the Management Port functionality is provided by software which + * functions as an end station. Software is connected to an IEEE 802 LAN that is + * wholly contained within the system that incorporates the Bridge. Software + * provides access to the LLC Entity associated with each Bridge Port by the + * value of the source port field on the special tag on the frame received by + * software. + * + * We call frames that carry control information to determine the active + * topology and current extent of each Virtual Local Area Network (VLAN), i.e., + * spanning tree or Shortest Path Bridging (SPB) and Multiple VLAN Registration + * Protocol Data Units (MVRPDUs), and frames from other link constrained + * protocols, such as Extensible Authentication Protocol over LAN (EAPOL) and + * Link Layer Discovery Protocol (LLDP), link-local frames. They are not + * forwarded by a Bridge. Permanently configured entries in the filtering + * database (FDB) ensure that such frames are discarded by the Forwarding + * Process. In 8.6.3 of IEEE Std 802.1Q-2022, this is described in detail: + * + * Each of the reserved MAC addresses specified in Table 8-1 + * (01-80-C2-00-00-[00,01,02,03,04,05,06,07,08,09,0A,0B,0C,0D,0E,0F]) shall be + * permanently configured in the FDB in C-VLAN components and ERs. + * + * Each of the reserved MAC addresses specified in Table 8-2 + * (01-80-C2-00-00-[01,02,03,04,05,06,07,08,09,0A,0E]) shall be permanently + * configured in the FDB in S-VLAN components. + * + * Each of the reserved MAC addresses specified in Table 8-3 + * (01-80-C2-00-00-[01,02,04,0E]) shall be permanently configured in the FDB in + * TPMR components. + * + * The FDB entries for reserved MAC addresses shall specify filtering for all + * Bridge Ports and all VIDs. Management shall not provide the capability to + * modify or remove entries for reserved MAC addresses. + * + * The addresses in Table 8-1, Table 8-2, and Table 8-3 determine the scope of + * propagation of PDUs within a Bridged Network, as follows: + * + * The Nearest Bridge group address (01-80-C2-00-00-0E) is an address that no + * conformant Two-Port MAC Relay (TPMR) component, Service VLAN (S-VLAN) + * component, Customer VLAN (C-VLAN) component, or MAC Bridge can forward. + * PDUs transmitted using this destination address, or any other addresses + * that appear in Table 8-1, Table 8-2, and Table 8-3 + * (01-80-C2-00-00-[00,01,02,03,04,05,06,07,08,09,0A,0B,0C,0D,0E,0F]), can + * therefore travel no further than those stations that can be reached via a + * single individual LAN from the originating station. + * + * The Nearest non-TPMR Bridge group address (01-80-C2-00-00-03), is an + * address that no conformant S-VLAN component, C-VLAN component, or MAC + * Bridge can forward; however, this address is relayed by a TPMR component. + * PDUs using this destination address, or any of the other addresses that + * appear in both Table 8-1 and Table 8-2 but not in Table 8-3 + * (01-80-C2-00-00-[00,03,05,06,07,08,09,0A,0B,0C,0D,0F]), will be relayed by + * any TPMRs but will propagate no further than the nearest S-VLAN component, + * C-VLAN component, or MAC Bridge. + * + * The Nearest Customer Bridge group address (01-80-C2-00-00-00) is an address + * that no conformant C-VLAN component, MAC Bridge can forward; however, it is + * relayed by TPMR components and S-VLAN components. PDUs using this + * destination address, or any of the other addresses that appear in Table 8-1 + * but not in either Table 8-2 or Table 8-3 (01-80-C2-00-00-[00,0B,0C,0D,0F]), + * will be relayed by TPMR components and S-VLAN components but will propagate + * no further than the nearest C-VLAN component or MAC Bridge. + * + * Because the LLC Entity associated with each Bridge Port is provided via CPU + * port, we must not filter these frames but forward them to CPU port. + * + * In a Bridge, the transmission Port is majorly decided by ingress and egress + * rules, FDB, and spanning tree Port State functions of the Forwarding Process. + * For link-local frames, only CPU port should be designated as destination port + * in the FDB, and the other functions of the Forwarding Process must not + * interfere with the decision of the transmission Port. We call this process + * trapping frames to CPU port. + * + * Therefore, on the switch with CPU port architecture, link-local frames must + * be trapped to CPU port, and certain link-local frames received by a Port of a + * Bridge comprising a TPMR component or an S-VLAN component must be excluded + * from it. + * + * A Bridge of the switch with CPU port architecture cannot comprise a Two-Port + * MAC Relay (TPMR) component as a TPMR component supports only a subset of the + * functionality of a MAC Bridge. A Bridge comprising two Ports (Management Port + * doesn't count) of this architecture will either function as a standard MAC + * Bridge or a standard VLAN Bridge. + * + * Therefore, a Bridge of this architecture can only comprise S-VLAN components, + * C-VLAN components, or MAC Bridge components. Since there's no TPMR component, + * we don't need to relay PDUs using the destination addresses specified on the + * Nearest non-TPMR section, and the proportion of the Nearest Customer Bridge + * section where they must be relayed by TPMR components. + * + * One option to trap link-local frames to CPU port is to add static FDB entries + * with CPU port designated as destination port. However, because that + * Independent VLAN Learning (IVL) is being used on every VID, each entry only + * applies to a single VLAN Identifier (VID). For a Bridge comprising a MAC + * Bridge component or a C-VLAN component, there would have to be 16 times 4096 + * entries. This switch intellectual property can only hold a maximum of 2048 + * entries. Using this option, there also isn't a mechanism to prevent + * link-local frames from being discarded when the spanning tree Port State of + * the reception Port is discarding. + * + * The remaining option is to utilise the BPC, RGAC1, RGAC2, RGAC3, and RGAC4 + * registers. Whilst this applies to every VID, it doesn't contain all of the + * reserved MAC addresses without affecting the remaining Standard Group MAC + * Addresses. The REV_UN frame tag utilised using the RGAC4 register covers the + * remaining 01-80-C2-00-00-[04,05,06,07,08,09,0A,0B,0C,0D,0F] destination + * addresses. It also includes the 01-80-C2-00-00-22 to 01-80-C2-00-00-FF + * destination addresses which may be relayed by MAC Bridges or VLAN Bridges. + * The latter option provides better but not complete conformance. + * + * This switch intellectual property also does not provide a mechanism to trap + * link-local frames with specific destination addresses to CPU port by Bridge, + * to conform to the filtering rules for the distinct Bridge components. + * + * Therefore, regardless of the type of the Bridge component, link-local frames + * with these destination addresses will be trapped to CPU port: + * + * 01-80-C2-00-00-[00,01,02,03,0E] + * + * In a Bridge comprising a MAC Bridge component or a C-VLAN component: + * + * Link-local frames with these destination addresses won't be trapped to CPU + * port which won't conform to IEEE Std 802.1Q-2022: + * + * 01-80-C2-00-00-[04,05,06,07,08,09,0A,0B,0C,0D,0F] + * + * In a Bridge comprising an S-VLAN component: + * + * Link-local frames with these destination addresses will be trapped to CPU + * port which won't conform to IEEE Std 802.1Q-2022: + * + * 01-80-C2-00-00-00 + * + * Link-local frames with these destination addresses won't be trapped to CPU + * port which won't conform to IEEE Std 802.1Q-2022: + * + * 01-80-C2-00-00-[04,05,06,07,08,09,0A] + * + * To trap link-local frames to CPU port as conformant as this switch + * intellectual property can allow, link-local frames are made to be regarded as + * Bridge Protocol Data Units (BPDUs). This is because this switch intellectual + * property only lets the frames regarded as BPDUs bypass the spanning tree Port + * State function of the Forwarding Process. + * + * The only remaining interference is the ingress rules. When the reception Port + * has no PVID assigned on software, VLAN-untagged frames won't be allowed in. + * There doesn't seem to be a mechanism on the switch intellectual property to + * have link-local frames bypass this function of the Forwarding Process. */ static void mt753x_trap_frames(struct mt7530_priv *priv) @@ -971,35 +1124,43 @@ mt753x_trap_frames(struct mt7530_priv *priv) /* Trap 802.1X PAE frames and BPDUs to the CPU port(s) and egress them * VLAN-untagged. */ - mt7530_rmw(priv, MT753X_BPC, MT753X_PAE_EG_TAG_MASK | - MT753X_PAE_PORT_FW_MASK | MT753X_BPDU_EG_TAG_MASK | - MT753X_BPDU_PORT_FW_MASK, - MT753X_PAE_EG_TAG(MT7530_VLAN_EG_UNTAGGED) | - MT753X_PAE_PORT_FW(MT753X_BPDU_CPU_ONLY) | - MT753X_BPDU_EG_TAG(MT7530_VLAN_EG_UNTAGGED) | - MT753X_BPDU_CPU_ONLY); + mt7530_rmw(priv, MT753X_BPC, + MT753X_PAE_BPDU_FR | MT753X_PAE_EG_TAG_MASK | + MT753X_PAE_PORT_FW_MASK | MT753X_BPDU_EG_TAG_MASK | + MT753X_BPDU_PORT_FW_MASK, + MT753X_PAE_BPDU_FR | + MT753X_PAE_EG_TAG(MT7530_VLAN_EG_UNTAGGED) | + MT753X_PAE_PORT_FW(MT753X_BPDU_CPU_ONLY) | + MT753X_BPDU_EG_TAG(MT7530_VLAN_EG_UNTAGGED) | + MT753X_BPDU_CPU_ONLY); /* Trap frames with :01 and :02 MAC DAs to the CPU port(s) and egress * them VLAN-untagged. */ - mt7530_rmw(priv, MT753X_RGAC1, MT753X_R02_EG_TAG_MASK | - MT753X_R02_PORT_FW_MASK | MT753X_R01_EG_TAG_MASK | - MT753X_R01_PORT_FW_MASK, - MT753X_R02_EG_TAG(MT7530_VLAN_EG_UNTAGGED) | - MT753X_R02_PORT_FW(MT753X_BPDU_CPU_ONLY) | - MT753X_R01_EG_TAG(MT7530_VLAN_EG_UNTAGGED) | - MT753X_BPDU_CPU_ONLY); + mt7530_rmw(priv, MT753X_RGAC1, + MT753X_R02_BPDU_FR | MT753X_R02_EG_TAG_MASK | + MT753X_R02_PORT_FW_MASK | MT753X_R01_BPDU_FR | + MT753X_R01_EG_TAG_MASK | MT753X_R01_PORT_FW_MASK, + MT753X_R02_BPDU_FR | + MT753X_R02_EG_TAG(MT7530_VLAN_EG_UNTAGGED) | + MT753X_R02_PORT_FW(MT753X_BPDU_CPU_ONLY) | + MT753X_R01_BPDU_FR | + MT753X_R01_EG_TAG(MT7530_VLAN_EG_UNTAGGED) | + MT753X_BPDU_CPU_ONLY); /* Trap frames with :03 and :0E MAC DAs to the CPU port(s) and egress * them VLAN-untagged. */ - mt7530_rmw(priv, MT753X_RGAC2, MT753X_R0E_EG_TAG_MASK | - MT753X_R0E_PORT_FW_MASK | MT753X_R03_EG_TAG_MASK | - MT753X_R03_PORT_FW_MASK, - MT753X_R0E_EG_TAG(MT7530_VLAN_EG_UNTAGGED) | - MT753X_R0E_PORT_FW(MT753X_BPDU_CPU_ONLY) | - MT753X_R03_EG_TAG(MT7530_VLAN_EG_UNTAGGED) | - MT753X_BPDU_CPU_ONLY); + mt7530_rmw(priv, MT753X_RGAC2, + MT753X_R0E_BPDU_FR | MT753X_R0E_EG_TAG_MASK | + MT753X_R0E_PORT_FW_MASK | MT753X_R03_BPDU_FR | + MT753X_R03_EG_TAG_MASK | MT753X_R03_PORT_FW_MASK, + MT753X_R0E_BPDU_FR | + MT753X_R0E_EG_TAG(MT7530_VLAN_EG_UNTAGGED) | + MT753X_R0E_PORT_FW(MT753X_BPDU_CPU_ONLY) | + MT753X_R03_BPDU_FR | + MT753X_R03_EG_TAG(MT7530_VLAN_EG_UNTAGGED) | + MT753X_BPDU_CPU_ONLY); } static void diff --git a/drivers/net/dsa/mt7530.h b/drivers/net/dsa/mt7530.h index 9439db495001..585db03c0548 100644 --- a/drivers/net/dsa/mt7530.h +++ b/drivers/net/dsa/mt7530.h @@ -65,6 +65,7 @@ enum mt753x_id { /* Registers for BPDU and PAE frame control*/ #define MT753X_BPC 0x24 +#define MT753X_PAE_BPDU_FR BIT(25) #define MT753X_PAE_EG_TAG_MASK GENMASK(24, 22) #define MT753X_PAE_EG_TAG(x) FIELD_PREP(MT753X_PAE_EG_TAG_MASK, x) #define MT753X_PAE_PORT_FW_MASK GENMASK(18, 16) @@ -75,20 +76,24 @@ enum mt753x_id { /* Register for :01 and :02 MAC DA frame control */ #define MT753X_RGAC1 0x28 +#define MT753X_R02_BPDU_FR BIT(25) #define MT753X_R02_EG_TAG_MASK GENMASK(24, 22) #define MT753X_R02_EG_TAG(x) FIELD_PREP(MT753X_R02_EG_TAG_MASK, x) #define MT753X_R02_PORT_FW_MASK GENMASK(18, 16) #define MT753X_R02_PORT_FW(x) FIELD_PREP(MT753X_R02_PORT_FW_MASK, x) +#define MT753X_R01_BPDU_FR BIT(9) #define MT753X_R01_EG_TAG_MASK GENMASK(8, 6) #define MT753X_R01_EG_TAG(x) FIELD_PREP(MT753X_R01_EG_TAG_MASK, x) #define MT753X_R01_PORT_FW_MASK GENMASK(2, 0) /* Register for :03 and :0E MAC DA frame control */ #define MT753X_RGAC2 0x2c +#define MT753X_R0E_BPDU_FR BIT(25) #define MT753X_R0E_EG_TAG_MASK GENMASK(24, 22) #define MT753X_R0E_EG_TAG(x) FIELD_PREP(MT753X_R0E_EG_TAG_MASK, x) #define MT753X_R0E_PORT_FW_MASK GENMASK(18, 16) #define MT753X_R0E_PORT_FW(x) FIELD_PREP(MT753X_R0E_PORT_FW_MASK, x) +#define MT753X_R03_BPDU_FR BIT(9) #define MT753X_R03_EG_TAG_MASK GENMASK(8, 6) #define MT753X_R03_EG_TAG(x) FIELD_PREP(MT753X_R03_EG_TAG_MASK, x) #define MT753X_R03_PORT_FW_MASK GENMASK(2, 0) -- cgit v1.2.3 From 47d8ac011fe1c9251070e1bd64cb10b48193ec51 Mon Sep 17 00:00:00 2001 From: Michal Luczaj Date: Tue, 9 Apr 2024 22:09:39 +0200 Subject: af_unix: Fix garbage collector racing against connect() Garbage collector does not take into account the risk of embryo getting enqueued during the garbage collection. If such embryo has a peer that carries SCM_RIGHTS, two consecutive passes of scan_children() may see a different set of children. Leading to an incorrectly elevated inflight count, and then a dangling pointer within the gc_inflight_list. sockets are AF_UNIX/SOCK_STREAM S is an unconnected socket L is a listening in-flight socket bound to addr, not in fdtable V's fd will be passed via sendmsg(), gets inflight count bumped connect(S, addr) sendmsg(S, [V]); close(V) __unix_gc() ---------------- ------------------------- ----------- NS = unix_create1() skb1 = sock_wmalloc(NS) L = unix_find_other(addr) unix_state_lock(L) unix_peer(S) = NS // V count=1 inflight=0 NS = unix_peer(S) skb2 = sock_alloc() skb_queue_tail(NS, skb2[V]) // V became in-flight // V count=2 inflight=1 close(V) // V count=1 inflight=1 // GC candidate condition met for u in gc_inflight_list: if (total_refs == inflight_refs) add u to gc_candidates // gc_candidates={L, V} for u in gc_candidates: scan_children(u, dec_inflight) // embryo (skb1) was not // reachable from L yet, so V's // inflight remains unchanged __skb_queue_tail(L, skb1) unix_state_unlock(L) for u in gc_candidates: if (u.inflight) scan_children(u, inc_inflight_move_tail) // V count=1 inflight=2 (!) If there is a GC-candidate listening socket, lock/unlock its state. This makes GC wait until the end of any ongoing connect() to that socket. After flipping the lock, a possibly SCM-laden embryo is already enqueued. And if there is another embryo coming, it can not possibly carry SCM_RIGHTS. At this point, unix_inflight() can not happen because unix_gc_lock is already taken. Inflight graph remains unaffected. Fixes: 1fd05ba5a2f2 ("[AF_UNIX]: Rewrite garbage collector, fixes race.") Signed-off-by: Michal Luczaj Reviewed-by: Kuniyuki Iwashima Link: https://lore.kernel.org/r/20240409201047.1032217-1-mhal@rbox.co Signed-off-by: Paolo Abeni --- net/unix/garbage.c | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/net/unix/garbage.c b/net/unix/garbage.c index fa39b6265238..6433a414acf8 100644 --- a/net/unix/garbage.c +++ b/net/unix/garbage.c @@ -274,11 +274,22 @@ static void __unix_gc(struct work_struct *work) * receive queues. Other, non candidate sockets _can_ be * added to queue, so we must make sure only to touch * candidates. + * + * Embryos, though never candidates themselves, affect which + * candidates are reachable by the garbage collector. Before + * being added to a listener's queue, an embryo may already + * receive data carrying SCM_RIGHTS, potentially making the + * passed socket a candidate that is not yet reachable by the + * collector. It becomes reachable once the embryo is + * enqueued. Therefore, we must ensure that no SCM-laden + * embryo appears in a (candidate) listener's queue between + * consecutive scan_children() calls. */ list_for_each_entry_safe(u, next, &gc_inflight_list, link) { + struct sock *sk = &u->sk; long total_refs; - total_refs = file_count(u->sk.sk_socket->file); + total_refs = file_count(sk->sk_socket->file); WARN_ON_ONCE(!u->inflight); WARN_ON_ONCE(total_refs < u->inflight); @@ -286,6 +297,11 @@ static void __unix_gc(struct work_struct *work) list_move_tail(&u->link, &gc_candidates); __set_bit(UNIX_GC_CANDIDATE, &u->gc_flags); __set_bit(UNIX_GC_MAYBE_CYCLE, &u->gc_flags); + + if (sk->sk_state == TCP_LISTEN) { + unix_state_lock(sk); + unix_state_unlock(sk); + } } } -- cgit v1.2.3 From dfe648903f42296866d79f10d03f8c85c9dfba30 Mon Sep 17 00:00:00 2001 From: Josh Poimboeuf Date: Wed, 10 Apr 2024 22:40:45 -0700 Subject: x86/bugs: Fix BHI documentation Fix up some inaccuracies in the BHI documentation. Fixes: ec9404e40e8f ("x86/bhi: Add BHI mitigation knob") Signed-off-by: Josh Poimboeuf Signed-off-by: Ingo Molnar Reviewed-by: Nikolay Borisov Cc: Linus Torvalds Cc: Sean Christopherson Link: https://lore.kernel.org/r/8c84f7451bfe0dd08543c6082a383f390d4aa7e2.1712813475.git.jpoimboe@kernel.org --- Documentation/admin-guide/hw-vuln/spectre.rst | 15 ++++++++------- Documentation/admin-guide/kernel-parameters.txt | 12 +++++++----- 2 files changed, 15 insertions(+), 12 deletions(-) diff --git a/Documentation/admin-guide/hw-vuln/spectre.rst b/Documentation/admin-guide/hw-vuln/spectre.rst index b70b1d8bd8e6..3cf18e4a1d9a 100644 --- a/Documentation/admin-guide/hw-vuln/spectre.rst +++ b/Documentation/admin-guide/hw-vuln/spectre.rst @@ -439,11 +439,11 @@ The possible values in this file are: - System is protected by retpoline * - BHI: BHI_DIS_S - System is protected by BHI_DIS_S - * - BHI: SW loop; KVM SW loop + * - BHI: SW loop, KVM SW loop - System is protected by software clearing sequence * - BHI: Syscall hardening - Syscalls are hardened against BHI - * - BHI: Syscall hardening; KVM: SW loop + * - BHI: Syscall hardening, KVM: SW loop - System is protected from userspace attacks by syscall hardening; KVM is protected by software clearing sequence Full mitigation might require a microcode update from the CPU @@ -666,13 +666,14 @@ kernel command line. of the HW BHI control and the SW BHB clearing sequence. on - unconditionally enable. + (default) Enable the HW or SW mitigation as + needed. off - unconditionally disable. + Disable the mitigation. auto - enable if hardware mitigation - control(BHI_DIS_S) is available, otherwise - enable alternate mitigation in KVM. + Enable the HW mitigation if needed, but + *don't* enable the SW mitigation except for KVM. + The system may be vulnerable. For spectre_v2_user see Documentation/admin-guide/kernel-parameters.txt diff --git a/Documentation/admin-guide/kernel-parameters.txt b/Documentation/admin-guide/kernel-parameters.txt index 70046a019d42..a029ad6c4963 100644 --- a/Documentation/admin-guide/kernel-parameters.txt +++ b/Documentation/admin-guide/kernel-parameters.txt @@ -3444,6 +3444,7 @@ retbleed=off [X86] spec_rstack_overflow=off [X86] spec_store_bypass_disable=off [X86,PPC] + spectre_bhi=off [X86] spectre_v2_user=off [X86] srbds=off [X86,INTEL] ssbd=force-off [ARM64] @@ -6069,11 +6070,12 @@ deployment of the HW BHI control and the SW BHB clearing sequence. - on - unconditionally enable. - off - unconditionally disable. - auto - (default) enable hardware mitigation - (BHI_DIS_S) if available, otherwise enable - alternate mitigation in KVM. + on - (default) Enable the HW or SW mitigation + as needed. + off - Disable the mitigation. + auto - Enable the HW mitigation if needed, but + *don't* enable the SW mitigation except + for KVM. The system may be vulnerable. spectre_v2= [X86,EARLY] Control mitigation of Spectre variant 2 (indirect branch speculation) vulnerability. -- cgit v1.2.3 From cb2db5bb04d7f778fbc1a1ea2507aab436f1bff3 Mon Sep 17 00:00:00 2001 From: Josh Poimboeuf Date: Wed, 10 Apr 2024 22:40:46 -0700 Subject: x86/bugs: Cache the value of MSR_IA32_ARCH_CAPABILITIES There's no need to keep reading MSR_IA32_ARCH_CAPABILITIES over and over. It's even read in the BHI sysfs function which is a big no-no. Just read it once and cache it. Fixes: ec9404e40e8f ("x86/bhi: Add BHI mitigation knob") Signed-off-by: Josh Poimboeuf Signed-off-by: Ingo Molnar Reviewed-by: Nikolay Borisov Cc: Linus Torvalds Cc: Sean Christopherson Link: https://lore.kernel.org/r/9592a18a814368e75f8f4b9d74d3883aa4fd1eaf.1712813475.git.jpoimboe@kernel.org --- arch/x86/kernel/cpu/bugs.c | 22 +++++++--------------- 1 file changed, 7 insertions(+), 15 deletions(-) diff --git a/arch/x86/kernel/cpu/bugs.c b/arch/x86/kernel/cpu/bugs.c index 27f5004a8e24..ff59fa8bb610 100644 --- a/arch/x86/kernel/cpu/bugs.c +++ b/arch/x86/kernel/cpu/bugs.c @@ -61,6 +61,8 @@ EXPORT_PER_CPU_SYMBOL_GPL(x86_spec_ctrl_current); u64 x86_pred_cmd __ro_after_init = PRED_CMD_IBPB; EXPORT_SYMBOL_GPL(x86_pred_cmd); +static u64 __ro_after_init ia32_cap; + static DEFINE_MUTEX(spec_ctrl_mutex); void (*x86_return_thunk)(void) __ro_after_init = __x86_return_thunk; @@ -144,6 +146,8 @@ void __init cpu_select_mitigations(void) x86_spec_ctrl_base &= ~SPEC_CTRL_MITIGATIONS_MASK; } + ia32_cap = x86_read_arch_cap_msr(); + /* Select the proper CPU mitigations before patching alternatives: */ spectre_v1_select_mitigation(); spectre_v2_select_mitigation(); @@ -301,8 +305,6 @@ static const char * const taa_strings[] = { static void __init taa_select_mitigation(void) { - u64 ia32_cap; - if (!boot_cpu_has_bug(X86_BUG_TAA)) { taa_mitigation = TAA_MITIGATION_OFF; return; @@ -341,7 +343,6 @@ static void __init taa_select_mitigation(void) * On MDS_NO=1 CPUs if ARCH_CAP_TSX_CTRL_MSR is not set, microcode * update is required. */ - ia32_cap = x86_read_arch_cap_msr(); if ( (ia32_cap & ARCH_CAP_MDS_NO) && !(ia32_cap & ARCH_CAP_TSX_CTRL_MSR)) taa_mitigation = TAA_MITIGATION_UCODE_NEEDED; @@ -401,8 +402,6 @@ static const char * const mmio_strings[] = { static void __init mmio_select_mitigation(void) { - u64 ia32_cap; - if (!boot_cpu_has_bug(X86_BUG_MMIO_STALE_DATA) || boot_cpu_has_bug(X86_BUG_MMIO_UNKNOWN) || cpu_mitigations_off()) { @@ -413,8 +412,6 @@ static void __init mmio_select_mitigation(void) if (mmio_mitigation == MMIO_MITIGATION_OFF) return; - ia32_cap = x86_read_arch_cap_msr(); - /* * Enable CPU buffer clear mitigation for host and VMM, if also affected * by MDS or TAA. Otherwise, enable mitigation for VMM only. @@ -508,7 +505,7 @@ static void __init rfds_select_mitigation(void) if (rfds_mitigation == RFDS_MITIGATION_OFF) return; - if (x86_read_arch_cap_msr() & ARCH_CAP_RFDS_CLEAR) + if (ia32_cap & ARCH_CAP_RFDS_CLEAR) setup_force_cpu_cap(X86_FEATURE_CLEAR_CPU_BUF); else rfds_mitigation = RFDS_MITIGATION_UCODE_NEEDED; @@ -659,8 +656,6 @@ void update_srbds_msr(void) static void __init srbds_select_mitigation(void) { - u64 ia32_cap; - if (!boot_cpu_has_bug(X86_BUG_SRBDS)) return; @@ -669,7 +664,6 @@ static void __init srbds_select_mitigation(void) * are only exposed to SRBDS when TSX is enabled or when CPU is affected * by Processor MMIO Stale Data vulnerability. */ - ia32_cap = x86_read_arch_cap_msr(); if ((ia32_cap & ARCH_CAP_MDS_NO) && !boot_cpu_has(X86_FEATURE_RTM) && !boot_cpu_has_bug(X86_BUG_MMIO_STALE_DATA)) srbds_mitigation = SRBDS_MITIGATION_TSX_OFF; @@ -813,7 +807,7 @@ static void __init gds_select_mitigation(void) /* Will verify below that mitigation _can_ be disabled */ /* No microcode */ - if (!(x86_read_arch_cap_msr() & ARCH_CAP_GDS_CTRL)) { + if (!(ia32_cap & ARCH_CAP_GDS_CTRL)) { if (gds_mitigation == GDS_MITIGATION_FORCE) { /* * This only needs to be done on the boot CPU so do it @@ -1908,8 +1902,6 @@ static void update_indir_branch_cond(void) /* Update the static key controlling the MDS CPU buffer clear in idle */ static void update_mds_branch_idle(void) { - u64 ia32_cap = x86_read_arch_cap_msr(); - /* * Enable the idle clearing if SMT is active on CPUs which are * affected only by MSBDS and not any other MDS variant. @@ -2818,7 +2810,7 @@ static const char *spectre_bhi_state(void) else if (boot_cpu_has(X86_FEATURE_CLEAR_BHB_LOOP)) return "; BHI: SW loop, KVM: SW loop"; else if (boot_cpu_has(X86_FEATURE_RETPOLINE) && - !(x86_read_arch_cap_msr() & ARCH_CAP_RRSBA)) + !(ia32_cap & ARCH_CAP_RRSBA)) return "; BHI: Retpoline"; else if (boot_cpu_has(X86_FEATURE_CLEAR_BHB_LOOP_ON_VMEXIT)) return "; BHI: Syscall hardening, KVM: SW loop"; -- cgit v1.2.3 From d0485730d2189ffe5d986d4e9e191f1e4d5ffd24 Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Thu, 11 Apr 2024 09:25:36 +0200 Subject: x86/bugs: Rename various 'ia32_cap' variables to 'x86_arch_cap_msr' So we are using the 'ia32_cap' value in a number of places, which got its name from MSR_IA32_ARCH_CAPABILITIES MSR register. But there's very little 'IA32' about it - this isn't 32-bit only code, nor does it originate from there, it's just a historic quirk that many Intel MSR names are prefixed with IA32_. This is already clear from the helper method around the MSR: x86_read_arch_cap_msr(), which doesn't have the IA32 prefix. So rename 'ia32_cap' to 'x86_arch_cap_msr' to be consistent with its role and with the naming of the helper function. Signed-off-by: Ingo Molnar Cc: Josh Poimboeuf Cc: Nikolay Borisov Cc: Linus Torvalds Cc: Sean Christopherson Link: https://lore.kernel.org/r/9592a18a814368e75f8f4b9d74d3883aa4fd1eaf.1712813475.git.jpoimboe@kernel.org --- arch/x86/kernel/apic/apic.c | 6 +++--- arch/x86/kernel/cpu/bugs.c | 30 +++++++++++++-------------- arch/x86/kernel/cpu/common.c | 48 ++++++++++++++++++++++---------------------- 3 files changed, 42 insertions(+), 42 deletions(-) diff --git a/arch/x86/kernel/apic/apic.c b/arch/x86/kernel/apic/apic.c index a42d8a6f7149..c342c4aa9c68 100644 --- a/arch/x86/kernel/apic/apic.c +++ b/arch/x86/kernel/apic/apic.c @@ -1687,11 +1687,11 @@ static int x2apic_state; static bool x2apic_hw_locked(void) { - u64 ia32_cap; + u64 x86_arch_cap_msr; u64 msr; - ia32_cap = x86_read_arch_cap_msr(); - if (ia32_cap & ARCH_CAP_XAPIC_DISABLE) { + x86_arch_cap_msr = x86_read_arch_cap_msr(); + if (x86_arch_cap_msr & ARCH_CAP_XAPIC_DISABLE) { rdmsrl(MSR_IA32_XAPIC_DISABLE_STATUS, msr); return (msr & LEGACY_XAPIC_DISABLED); } diff --git a/arch/x86/kernel/cpu/bugs.c b/arch/x86/kernel/cpu/bugs.c index ff59fa8bb610..1b0cfc136432 100644 --- a/arch/x86/kernel/cpu/bugs.c +++ b/arch/x86/kernel/cpu/bugs.c @@ -61,7 +61,7 @@ EXPORT_PER_CPU_SYMBOL_GPL(x86_spec_ctrl_current); u64 x86_pred_cmd __ro_after_init = PRED_CMD_IBPB; EXPORT_SYMBOL_GPL(x86_pred_cmd); -static u64 __ro_after_init ia32_cap; +static u64 __ro_after_init x86_arch_cap_msr; static DEFINE_MUTEX(spec_ctrl_mutex); @@ -146,7 +146,7 @@ void __init cpu_select_mitigations(void) x86_spec_ctrl_base &= ~SPEC_CTRL_MITIGATIONS_MASK; } - ia32_cap = x86_read_arch_cap_msr(); + x86_arch_cap_msr = x86_read_arch_cap_msr(); /* Select the proper CPU mitigations before patching alternatives: */ spectre_v1_select_mitigation(); @@ -343,8 +343,8 @@ static void __init taa_select_mitigation(void) * On MDS_NO=1 CPUs if ARCH_CAP_TSX_CTRL_MSR is not set, microcode * update is required. */ - if ( (ia32_cap & ARCH_CAP_MDS_NO) && - !(ia32_cap & ARCH_CAP_TSX_CTRL_MSR)) + if ( (x86_arch_cap_msr & ARCH_CAP_MDS_NO) && + !(x86_arch_cap_msr & ARCH_CAP_TSX_CTRL_MSR)) taa_mitigation = TAA_MITIGATION_UCODE_NEEDED; /* @@ -434,7 +434,7 @@ static void __init mmio_select_mitigation(void) * be propagated to uncore buffers, clearing the Fill buffers on idle * is required irrespective of SMT state. */ - if (!(ia32_cap & ARCH_CAP_FBSDP_NO)) + if (!(x86_arch_cap_msr & ARCH_CAP_FBSDP_NO)) static_branch_enable(&mds_idle_clear); /* @@ -444,10 +444,10 @@ static void __init mmio_select_mitigation(void) * FB_CLEAR or by the presence of both MD_CLEAR and L1D_FLUSH on MDS * affected systems. */ - if ((ia32_cap & ARCH_CAP_FB_CLEAR) || + if ((x86_arch_cap_msr & ARCH_CAP_FB_CLEAR) || (boot_cpu_has(X86_FEATURE_MD_CLEAR) && boot_cpu_has(X86_FEATURE_FLUSH_L1D) && - !(ia32_cap & ARCH_CAP_MDS_NO))) + !(x86_arch_cap_msr & ARCH_CAP_MDS_NO))) mmio_mitigation = MMIO_MITIGATION_VERW; else mmio_mitigation = MMIO_MITIGATION_UCODE_NEEDED; @@ -505,7 +505,7 @@ static void __init rfds_select_mitigation(void) if (rfds_mitigation == RFDS_MITIGATION_OFF) return; - if (ia32_cap & ARCH_CAP_RFDS_CLEAR) + if (x86_arch_cap_msr & ARCH_CAP_RFDS_CLEAR) setup_force_cpu_cap(X86_FEATURE_CLEAR_CPU_BUF); else rfds_mitigation = RFDS_MITIGATION_UCODE_NEEDED; @@ -664,7 +664,7 @@ static void __init srbds_select_mitigation(void) * are only exposed to SRBDS when TSX is enabled or when CPU is affected * by Processor MMIO Stale Data vulnerability. */ - if ((ia32_cap & ARCH_CAP_MDS_NO) && !boot_cpu_has(X86_FEATURE_RTM) && + if ((x86_arch_cap_msr & ARCH_CAP_MDS_NO) && !boot_cpu_has(X86_FEATURE_RTM) && !boot_cpu_has_bug(X86_BUG_MMIO_STALE_DATA)) srbds_mitigation = SRBDS_MITIGATION_TSX_OFF; else if (boot_cpu_has(X86_FEATURE_HYPERVISOR)) @@ -807,7 +807,7 @@ static void __init gds_select_mitigation(void) /* Will verify below that mitigation _can_ be disabled */ /* No microcode */ - if (!(ia32_cap & ARCH_CAP_GDS_CTRL)) { + if (!(x86_arch_cap_msr & ARCH_CAP_GDS_CTRL)) { if (gds_mitigation == GDS_MITIGATION_FORCE) { /* * This only needs to be done on the boot CPU so do it @@ -1541,14 +1541,14 @@ static enum spectre_v2_mitigation __init spectre_v2_select_retpoline(void) /* Disable in-kernel use of non-RSB RET predictors */ static void __init spec_ctrl_disable_kernel_rrsba(void) { - u64 ia32_cap; + u64 x86_arch_cap_msr; if (!boot_cpu_has(X86_FEATURE_RRSBA_CTRL)) return; - ia32_cap = x86_read_arch_cap_msr(); + x86_arch_cap_msr = x86_read_arch_cap_msr(); - if (ia32_cap & ARCH_CAP_RRSBA) { + if (x86_arch_cap_msr & ARCH_CAP_RRSBA) { x86_spec_ctrl_base |= SPEC_CTRL_RRSBA_DIS_S; update_spec_ctrl(x86_spec_ctrl_base); } @@ -1916,7 +1916,7 @@ static void update_mds_branch_idle(void) if (sched_smt_active()) { static_branch_enable(&mds_idle_clear); } else if (mmio_mitigation == MMIO_MITIGATION_OFF || - (ia32_cap & ARCH_CAP_FBSDP_NO)) { + (x86_arch_cap_msr & ARCH_CAP_FBSDP_NO)) { static_branch_disable(&mds_idle_clear); } } @@ -2810,7 +2810,7 @@ static const char *spectre_bhi_state(void) else if (boot_cpu_has(X86_FEATURE_CLEAR_BHB_LOOP)) return "; BHI: SW loop, KVM: SW loop"; else if (boot_cpu_has(X86_FEATURE_RETPOLINE) && - !(ia32_cap & ARCH_CAP_RRSBA)) + !(x86_arch_cap_msr & ARCH_CAP_RRSBA)) return "; BHI: Retpoline"; else if (boot_cpu_has(X86_FEATURE_CLEAR_BHB_LOOP_ON_VMEXIT)) return "; BHI: Syscall hardening, KVM: SW loop"; diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c index 754d91857d63..605c26c009c8 100644 --- a/arch/x86/kernel/cpu/common.c +++ b/arch/x86/kernel/cpu/common.c @@ -1284,25 +1284,25 @@ static bool __init cpu_matches(const struct x86_cpu_id *table, unsigned long whi u64 x86_read_arch_cap_msr(void) { - u64 ia32_cap = 0; + u64 x86_arch_cap_msr = 0; if (boot_cpu_has(X86_FEATURE_ARCH_CAPABILITIES)) - rdmsrl(MSR_IA32_ARCH_CAPABILITIES, ia32_cap); + rdmsrl(MSR_IA32_ARCH_CAPABILITIES, x86_arch_cap_msr); - return ia32_cap; + return x86_arch_cap_msr; } -static bool arch_cap_mmio_immune(u64 ia32_cap) +static bool arch_cap_mmio_immune(u64 x86_arch_cap_msr) { - return (ia32_cap & ARCH_CAP_FBSDP_NO && - ia32_cap & ARCH_CAP_PSDP_NO && - ia32_cap & ARCH_CAP_SBDR_SSDP_NO); + return (x86_arch_cap_msr & ARCH_CAP_FBSDP_NO && + x86_arch_cap_msr & ARCH_CAP_PSDP_NO && + x86_arch_cap_msr & ARCH_CAP_SBDR_SSDP_NO); } -static bool __init vulnerable_to_rfds(u64 ia32_cap) +static bool __init vulnerable_to_rfds(u64 x86_arch_cap_msr) { /* The "immunity" bit trumps everything else: */ - if (ia32_cap & ARCH_CAP_RFDS_NO) + if (x86_arch_cap_msr & ARCH_CAP_RFDS_NO) return false; /* @@ -1310,7 +1310,7 @@ static bool __init vulnerable_to_rfds(u64 ia32_cap) * indicate that mitigation is needed because guest is running on a * vulnerable hardware or may migrate to such hardware: */ - if (ia32_cap & ARCH_CAP_RFDS_CLEAR) + if (x86_arch_cap_msr & ARCH_CAP_RFDS_CLEAR) return true; /* Only consult the blacklist when there is no enumeration: */ @@ -1319,11 +1319,11 @@ static bool __init vulnerable_to_rfds(u64 ia32_cap) static void __init cpu_set_bug_bits(struct cpuinfo_x86 *c) { - u64 ia32_cap = x86_read_arch_cap_msr(); + u64 x86_arch_cap_msr = x86_read_arch_cap_msr(); /* Set ITLB_MULTIHIT bug if cpu is not in the whitelist and not mitigated */ if (!cpu_matches(cpu_vuln_whitelist, NO_ITLB_MULTIHIT) && - !(ia32_cap & ARCH_CAP_PSCHANGE_MC_NO)) + !(x86_arch_cap_msr & ARCH_CAP_PSCHANGE_MC_NO)) setup_force_cpu_bug(X86_BUG_ITLB_MULTIHIT); if (cpu_matches(cpu_vuln_whitelist, NO_SPECULATION)) @@ -1335,7 +1335,7 @@ static void __init cpu_set_bug_bits(struct cpuinfo_x86 *c) setup_force_cpu_bug(X86_BUG_SPECTRE_V2); if (!cpu_matches(cpu_vuln_whitelist, NO_SSB) && - !(ia32_cap & ARCH_CAP_SSB_NO) && + !(x86_arch_cap_msr & ARCH_CAP_SSB_NO) && !cpu_has(c, X86_FEATURE_AMD_SSB_NO)) setup_force_cpu_bug(X86_BUG_SPEC_STORE_BYPASS); @@ -1346,17 +1346,17 @@ static void __init cpu_set_bug_bits(struct cpuinfo_x86 *c) * Don't use AutoIBRS when SNP is enabled because it degrades host * userspace indirect branch performance. */ - if ((ia32_cap & ARCH_CAP_IBRS_ALL) || + if ((x86_arch_cap_msr & ARCH_CAP_IBRS_ALL) || (cpu_has(c, X86_FEATURE_AUTOIBRS) && !cpu_feature_enabled(X86_FEATURE_SEV_SNP))) { setup_force_cpu_cap(X86_FEATURE_IBRS_ENHANCED); if (!cpu_matches(cpu_vuln_whitelist, NO_EIBRS_PBRSB) && - !(ia32_cap & ARCH_CAP_PBRSB_NO)) + !(x86_arch_cap_msr & ARCH_CAP_PBRSB_NO)) setup_force_cpu_bug(X86_BUG_EIBRS_PBRSB); } if (!cpu_matches(cpu_vuln_whitelist, NO_MDS) && - !(ia32_cap & ARCH_CAP_MDS_NO)) { + !(x86_arch_cap_msr & ARCH_CAP_MDS_NO)) { setup_force_cpu_bug(X86_BUG_MDS); if (cpu_matches(cpu_vuln_whitelist, MSBDS_ONLY)) setup_force_cpu_bug(X86_BUG_MSBDS_ONLY); @@ -1375,9 +1375,9 @@ static void __init cpu_set_bug_bits(struct cpuinfo_x86 *c) * TSX_CTRL check alone is not sufficient for cases when the microcode * update is not present or running as guest that don't get TSX_CTRL. */ - if (!(ia32_cap & ARCH_CAP_TAA_NO) && + if (!(x86_arch_cap_msr & ARCH_CAP_TAA_NO) && (cpu_has(c, X86_FEATURE_RTM) || - (ia32_cap & ARCH_CAP_TSX_CTRL_MSR))) + (x86_arch_cap_msr & ARCH_CAP_TSX_CTRL_MSR))) setup_force_cpu_bug(X86_BUG_TAA); /* @@ -1403,7 +1403,7 @@ static void __init cpu_set_bug_bits(struct cpuinfo_x86 *c) * Set X86_BUG_MMIO_UNKNOWN for CPUs that are neither in the blacklist, * nor in the whitelist and also don't enumerate MSR ARCH_CAP MMIO bits. */ - if (!arch_cap_mmio_immune(ia32_cap)) { + if (!arch_cap_mmio_immune(x86_arch_cap_msr)) { if (cpu_matches(cpu_vuln_blacklist, MMIO)) setup_force_cpu_bug(X86_BUG_MMIO_STALE_DATA); else if (!cpu_matches(cpu_vuln_whitelist, NO_MMIO)) @@ -1411,7 +1411,7 @@ static void __init cpu_set_bug_bits(struct cpuinfo_x86 *c) } if (!cpu_has(c, X86_FEATURE_BTC_NO)) { - if (cpu_matches(cpu_vuln_blacklist, RETBLEED) || (ia32_cap & ARCH_CAP_RSBA)) + if (cpu_matches(cpu_vuln_blacklist, RETBLEED) || (x86_arch_cap_msr & ARCH_CAP_RSBA)) setup_force_cpu_bug(X86_BUG_RETBLEED); } @@ -1429,15 +1429,15 @@ static void __init cpu_set_bug_bits(struct cpuinfo_x86 *c) * disabling AVX2. The only way to do this in HW is to clear XCR0[2], * which means that AVX will be disabled. */ - if (cpu_matches(cpu_vuln_blacklist, GDS) && !(ia32_cap & ARCH_CAP_GDS_NO) && + if (cpu_matches(cpu_vuln_blacklist, GDS) && !(x86_arch_cap_msr & ARCH_CAP_GDS_NO) && boot_cpu_has(X86_FEATURE_AVX)) setup_force_cpu_bug(X86_BUG_GDS); - if (vulnerable_to_rfds(ia32_cap)) + if (vulnerable_to_rfds(x86_arch_cap_msr)) setup_force_cpu_bug(X86_BUG_RFDS); /* When virtualized, eIBRS could be hidden, assume vulnerable */ - if (!(ia32_cap & ARCH_CAP_BHI_NO) && + if (!(x86_arch_cap_msr & ARCH_CAP_BHI_NO) && !cpu_matches(cpu_vuln_whitelist, NO_BHI) && (boot_cpu_has(X86_FEATURE_IBRS_ENHANCED) || boot_cpu_has(X86_FEATURE_HYPERVISOR))) @@ -1447,7 +1447,7 @@ static void __init cpu_set_bug_bits(struct cpuinfo_x86 *c) return; /* Rogue Data Cache Load? No! */ - if (ia32_cap & ARCH_CAP_RDCL_NO) + if (x86_arch_cap_msr & ARCH_CAP_RDCL_NO) return; setup_force_cpu_bug(X86_BUG_CPU_MELTDOWN); -- cgit v1.2.3 From 1cea8a280dfd1016148a3820676f2f03e3f5b898 Mon Sep 17 00:00:00 2001 From: Josh Poimboeuf Date: Wed, 10 Apr 2024 22:40:47 -0700 Subject: x86/bugs: Fix BHI handling of RRSBA The ARCH_CAP_RRSBA check isn't correct: RRSBA may have already been disabled by the Spectre v2 mitigation (or can otherwise be disabled by the BHI mitigation itself if needed). In that case retpolines are fine. Fixes: ec9404e40e8f ("x86/bhi: Add BHI mitigation knob") Signed-off-by: Josh Poimboeuf Signed-off-by: Ingo Molnar Cc: Linus Torvalds Cc: Sean Christopherson Link: https://lore.kernel.org/r/6f56f13da34a0834b69163467449be7f58f253dc.1712813475.git.jpoimboe@kernel.org --- arch/x86/kernel/cpu/bugs.c | 30 ++++++++++++++++++------------ 1 file changed, 18 insertions(+), 12 deletions(-) diff --git a/arch/x86/kernel/cpu/bugs.c b/arch/x86/kernel/cpu/bugs.c index 1b0cfc136432..08dfb94fcb3a 100644 --- a/arch/x86/kernel/cpu/bugs.c +++ b/arch/x86/kernel/cpu/bugs.c @@ -1538,20 +1538,25 @@ static enum spectre_v2_mitigation __init spectre_v2_select_retpoline(void) return SPECTRE_V2_RETPOLINE; } +static bool __ro_after_init rrsba_disabled; + /* Disable in-kernel use of non-RSB RET predictors */ static void __init spec_ctrl_disable_kernel_rrsba(void) { - u64 x86_arch_cap_msr; + if (rrsba_disabled) + return; - if (!boot_cpu_has(X86_FEATURE_RRSBA_CTRL)) + if (!(x86_arch_cap_msr & ARCH_CAP_RRSBA)) { + rrsba_disabled = true; return; + } - x86_arch_cap_msr = x86_read_arch_cap_msr(); + if (!boot_cpu_has(X86_FEATURE_RRSBA_CTRL)) + return; - if (x86_arch_cap_msr & ARCH_CAP_RRSBA) { - x86_spec_ctrl_base |= SPEC_CTRL_RRSBA_DIS_S; - update_spec_ctrl(x86_spec_ctrl_base); - } + x86_spec_ctrl_base |= SPEC_CTRL_RRSBA_DIS_S; + update_spec_ctrl(x86_spec_ctrl_base); + rrsba_disabled = true; } static void __init spectre_v2_determine_rsb_fill_type_at_vmexit(enum spectre_v2_mitigation mode) @@ -1652,9 +1657,11 @@ static void __init bhi_select_mitigation(void) return; /* Retpoline mitigates against BHI unless the CPU has RRSBA behavior */ - if (cpu_feature_enabled(X86_FEATURE_RETPOLINE) && - !(x86_read_arch_cap_msr() & ARCH_CAP_RRSBA)) - return; + if (cpu_feature_enabled(X86_FEATURE_RETPOLINE)) { + spec_ctrl_disable_kernel_rrsba(); + if (rrsba_disabled) + return; + } if (spec_ctrl_bhi_dis()) return; @@ -2809,8 +2816,7 @@ static const char *spectre_bhi_state(void) return "; BHI: BHI_DIS_S"; else if (boot_cpu_has(X86_FEATURE_CLEAR_BHB_LOOP)) return "; BHI: SW loop, KVM: SW loop"; - else if (boot_cpu_has(X86_FEATURE_RETPOLINE) && - !(x86_arch_cap_msr & ARCH_CAP_RRSBA)) + else if (boot_cpu_has(X86_FEATURE_RETPOLINE) && rrsba_disabled) return "; BHI: Retpoline"; else if (boot_cpu_has(X86_FEATURE_CLEAR_BHB_LOOP_ON_VMEXIT)) return "; BHI: Syscall hardening, KVM: SW loop"; -- cgit v1.2.3 From 5f882f3b0a8bf0788d5a0ee44b1191de5319bb8a Mon Sep 17 00:00:00 2001 From: Josh Poimboeuf Date: Wed, 10 Apr 2024 22:40:48 -0700 Subject: x86/bugs: Clarify that syscall hardening isn't a BHI mitigation While syscall hardening helps prevent some BHI attacks, there's still other low-hanging fruit remaining. Don't classify it as a mitigation and make it clear that the system may still be vulnerable if it doesn't have a HW or SW mitigation enabled. Fixes: ec9404e40e8f ("x86/bhi: Add BHI mitigation knob") Signed-off-by: Josh Poimboeuf Signed-off-by: Ingo Molnar Cc: Linus Torvalds Cc: Sean Christopherson Link: https://lore.kernel.org/r/b5951dae3fdee7f1520d5136a27be3bdfe95f88b.1712813475.git.jpoimboe@kernel.org --- Documentation/admin-guide/hw-vuln/spectre.rst | 11 +++++------ Documentation/admin-guide/kernel-parameters.txt | 3 +-- arch/x86/kernel/cpu/bugs.c | 6 +++--- 3 files changed, 9 insertions(+), 11 deletions(-) diff --git a/Documentation/admin-guide/hw-vuln/spectre.rst b/Documentation/admin-guide/hw-vuln/spectre.rst index 3cf18e4a1d9a..5a39acf82483 100644 --- a/Documentation/admin-guide/hw-vuln/spectre.rst +++ b/Documentation/admin-guide/hw-vuln/spectre.rst @@ -441,10 +441,10 @@ The possible values in this file are: - System is protected by BHI_DIS_S * - BHI: SW loop, KVM SW loop - System is protected by software clearing sequence - * - BHI: Syscall hardening - - Syscalls are hardened against BHI - * - BHI: Syscall hardening, KVM: SW loop - - System is protected from userspace attacks by syscall hardening; KVM is protected by software clearing sequence + * - BHI: Vulnerable + - System is vulnerable to BHI + * - BHI: Vulnerable, KVM: SW loop + - System is vulnerable; KVM is protected by software clearing sequence Full mitigation might require a microcode update from the CPU vendor. When the necessary microcode is not available, the kernel will @@ -661,8 +661,7 @@ kernel command line. spectre_bhi= [X86] Control mitigation of Branch History Injection - (BHI) vulnerability. Syscalls are hardened against BHI - regardless of this setting. This setting affects the deployment + (BHI) vulnerability. This setting affects the deployment of the HW BHI control and the SW BHB clearing sequence. on diff --git a/Documentation/admin-guide/kernel-parameters.txt b/Documentation/admin-guide/kernel-parameters.txt index a029ad6c4963..a3874cc97892 100644 --- a/Documentation/admin-guide/kernel-parameters.txt +++ b/Documentation/admin-guide/kernel-parameters.txt @@ -6065,8 +6065,7 @@ See Documentation/admin-guide/laptops/sonypi.rst spectre_bhi= [X86] Control mitigation of Branch History Injection - (BHI) vulnerability. Syscalls are hardened against BHI - reglardless of this setting. This setting affects the + (BHI) vulnerability. This setting affects the deployment of the HW BHI control and the SW BHB clearing sequence. diff --git a/arch/x86/kernel/cpu/bugs.c b/arch/x86/kernel/cpu/bugs.c index 08dfb94fcb3a..9eeb60f5fbb3 100644 --- a/arch/x86/kernel/cpu/bugs.c +++ b/arch/x86/kernel/cpu/bugs.c @@ -2818,10 +2818,10 @@ static const char *spectre_bhi_state(void) return "; BHI: SW loop, KVM: SW loop"; else if (boot_cpu_has(X86_FEATURE_RETPOLINE) && rrsba_disabled) return "; BHI: Retpoline"; - else if (boot_cpu_has(X86_FEATURE_CLEAR_BHB_LOOP_ON_VMEXIT)) - return "; BHI: Syscall hardening, KVM: SW loop"; + else if (boot_cpu_has(X86_FEATURE_CLEAR_BHB_LOOP_ON_VMEXIT)) + return "; BHI: Vulnerable, KVM: SW loop"; - return "; BHI: Vulnerable (Syscall hardening enabled)"; + return "; BHI: Vulnerable"; } static ssize_t spectre_v2_show_state(char *buf) -- cgit v1.2.3 From 713a85195aad25d8a26786a37b674e3e5ec09e3c Mon Sep 17 00:00:00 2001 From: David Arinzon Date: Wed, 10 Apr 2024 09:13:55 +0000 Subject: net: ena: Fix potential sign extension issue Small unsigned types are promoted to larger signed types in the case of multiplication, the result of which may overflow. In case the result of such a multiplication has its MSB turned on, it will be sign extended with '1's. This changes the multiplication result. Code example of the phenomenon: ------------------------------- u16 x, y; size_t z1, z2; x = y = 0xffff; printk("x=%x y=%x\n",x,y); z1 = x*y; z2 = (size_t)x*y; printk("z1=%lx z2=%lx\n", z1, z2); Output: ------- x=ffff y=ffff z1=fffffffffffe0001 z2=fffe0001 The expected result of ffff*ffff is fffe0001, and without the explicit casting to avoid the unwanted sign extension we got fffffffffffe0001. This commit adds an explicit casting to avoid the sign extension issue. Fixes: 689b2bdaaa14 ("net: ena: add functions for handling Low Latency Queues in ena_com") Signed-off-by: Arthur Kiyanovski Signed-off-by: David Arinzon Reviewed-by: Shannon Nelson Signed-off-by: Paolo Abeni --- drivers/net/ethernet/amazon/ena/ena_com.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/ethernet/amazon/ena/ena_com.c b/drivers/net/ethernet/amazon/ena/ena_com.c index 9e9e4a03f1a8..2d8a66ea82fa 100644 --- a/drivers/net/ethernet/amazon/ena/ena_com.c +++ b/drivers/net/ethernet/amazon/ena/ena_com.c @@ -351,7 +351,7 @@ static int ena_com_init_io_sq(struct ena_com_dev *ena_dev, ENA_COM_BOUNCE_BUFFER_CNTRL_CNT; io_sq->bounce_buf_ctrl.next_to_use = 0; - size = io_sq->bounce_buf_ctrl.buffer_size * + size = (size_t)io_sq->bounce_buf_ctrl.buffer_size * io_sq->bounce_buf_ctrl.buffers_num; dev_node = dev_to_node(ena_dev->dmadev); -- cgit v1.2.3 From f7e417180665234fdb7af2ebe33d89aaa434d16f Mon Sep 17 00:00:00 2001 From: David Arinzon Date: Wed, 10 Apr 2024 09:13:56 +0000 Subject: net: ena: Wrong missing IO completions check order Missing IO completions check is called every second (HZ jiffies). This commit fixes several issues with this check: 1. Duplicate queues check: Max of 4 queues are scanned on each check due to monitor budget. Once reaching the budget, this check exits under the assumption that the next check will continue to scan the remainder of the queues, but in practice, next check will first scan the last already scanned queue which is not necessary and may cause the full queue scan to last a couple of seconds longer. The fix is to start every check with the next queue to scan. For example, on 8 IO queues: Bug: [0,1,2,3], [3,4,5,6], [6,7] Fix: [0,1,2,3], [4,5,6,7] 2. Unbalanced queues check: In case the number of active IO queues is not a multiple of budget, there will be checks which don't utilize the full budget because the full scan exits when reaching the last queue id. The fix is to run every TX completion check with exact queue budget regardless of the queue id. For example, on 7 IO queues: Bug: [0,1,2,3], [4,5,6], [0,1,2,3] Fix: [0,1,2,3], [4,5,6,0], [1,2,3,4] The budget may be lowered in case the number of IO queues is less than the budget (4) to make sure there are no duplicate queues on the same check. For example, on 3 IO queues: Bug: [0,1,2,0], [1,2,0,1] Fix: [0,1,2], [0,1,2] Fixes: 1738cd3ed342 ("net: ena: Add a driver for Amazon Elastic Network Adapters (ENA)") Signed-off-by: Amit Bernstein Signed-off-by: David Arinzon Reviewed-by: Shannon Nelson Signed-off-by: Paolo Abeni --- drivers/net/ethernet/amazon/ena/ena_netdev.c | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/drivers/net/ethernet/amazon/ena/ena_netdev.c b/drivers/net/ethernet/amazon/ena/ena_netdev.c index 09e7da1a69c9..59befc0f463c 100644 --- a/drivers/net/ethernet/amazon/ena/ena_netdev.c +++ b/drivers/net/ethernet/amazon/ena/ena_netdev.c @@ -3481,10 +3481,11 @@ static void check_for_missing_completions(struct ena_adapter *adapter) { struct ena_ring *tx_ring; struct ena_ring *rx_ring; - int i, budget, rc; + int qid, budget, rc; int io_queue_count; io_queue_count = adapter->xdp_num_queues + adapter->num_io_queues; + /* Make sure the driver doesn't turn the device in other process */ smp_rmb(); @@ -3497,27 +3498,29 @@ static void check_for_missing_completions(struct ena_adapter *adapter) if (adapter->missing_tx_completion_to == ENA_HW_HINTS_NO_TIMEOUT) return; - budget = ENA_MONITORED_TX_QUEUES; + budget = min_t(u32, io_queue_count, ENA_MONITORED_TX_QUEUES); - for (i = adapter->last_monitored_tx_qid; i < io_queue_count; i++) { - tx_ring = &adapter->tx_ring[i]; - rx_ring = &adapter->rx_ring[i]; + qid = adapter->last_monitored_tx_qid; + + while (budget) { + qid = (qid + 1) % io_queue_count; + + tx_ring = &adapter->tx_ring[qid]; + rx_ring = &adapter->rx_ring[qid]; rc = check_missing_comp_in_tx_queue(adapter, tx_ring); if (unlikely(rc)) return; - rc = !ENA_IS_XDP_INDEX(adapter, i) ? + rc = !ENA_IS_XDP_INDEX(adapter, qid) ? check_for_rx_interrupt_queue(adapter, rx_ring) : 0; if (unlikely(rc)) return; budget--; - if (!budget) - break; } - adapter->last_monitored_tx_qid = i % io_queue_count; + adapter->last_monitored_tx_qid = qid; } /* trigger napi schedule after 2 consecutive detections */ -- cgit v1.2.3 From bf02d9fe00632d22fa91d34749c7aacf397b6cde Mon Sep 17 00:00:00 2001 From: David Arinzon Date: Wed, 10 Apr 2024 09:13:57 +0000 Subject: net: ena: Fix incorrect descriptor free behavior ENA has two types of TX queues: - queues which only process TX packets arriving from the network stack - queues which only process TX packets forwarded to it by XDP_REDIRECT or XDP_TX instructions The ena_free_tx_bufs() cycles through all descriptors in a TX queue and unmaps + frees every descriptor that hasn't been acknowledged yet by the device (uncompleted TX transactions). The function assumes that the processed TX queue is necessarily from the first category listed above and ends up using napi_consume_skb() for descriptors belonging to an XDP specific queue. This patch solves a bug in which, in case of a VF reset, the descriptors aren't freed correctly, leading to crashes. Fixes: 548c4940b9f1 ("net: ena: Implement XDP_TX action") Signed-off-by: Shay Agroskin Signed-off-by: David Arinzon Reviewed-by: Shannon Nelson Signed-off-by: Paolo Abeni --- drivers/net/ethernet/amazon/ena/ena_netdev.c | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/drivers/net/ethernet/amazon/ena/ena_netdev.c b/drivers/net/ethernet/amazon/ena/ena_netdev.c index 59befc0f463c..be5acfa41ee0 100644 --- a/drivers/net/ethernet/amazon/ena/ena_netdev.c +++ b/drivers/net/ethernet/amazon/ena/ena_netdev.c @@ -718,8 +718,11 @@ void ena_unmap_tx_buff(struct ena_ring *tx_ring, static void ena_free_tx_bufs(struct ena_ring *tx_ring) { bool print_once = true; + bool is_xdp_ring; u32 i; + is_xdp_ring = ENA_IS_XDP_INDEX(tx_ring->adapter, tx_ring->qid); + for (i = 0; i < tx_ring->ring_size; i++) { struct ena_tx_buffer *tx_info = &tx_ring->tx_buffer_info[i]; @@ -739,10 +742,15 @@ static void ena_free_tx_bufs(struct ena_ring *tx_ring) ena_unmap_tx_buff(tx_ring, tx_info); - dev_kfree_skb_any(tx_info->skb); + if (is_xdp_ring) + xdp_return_frame(tx_info->xdpf); + else + dev_kfree_skb_any(tx_info->skb); } - netdev_tx_reset_queue(netdev_get_tx_queue(tx_ring->netdev, - tx_ring->qid)); + + if (!is_xdp_ring) + netdev_tx_reset_queue(netdev_get_tx_queue(tx_ring->netdev, + tx_ring->qid)); } static void ena_free_all_tx_bufs(struct ena_adapter *adapter) -- cgit v1.2.3 From 36a1ca01f0452f2549420e7279c2588729bd94df Mon Sep 17 00:00:00 2001 From: David Arinzon Date: Wed, 10 Apr 2024 09:13:58 +0000 Subject: net: ena: Set tx_info->xdpf value to NULL The patch mentioned in the `Fixes` tag removed the explicit assignment of tx_info->xdpf to NULL with the justification that there's no need to set tx_info->xdpf to NULL and tx_info->num_of_bufs to 0 in case of a mapping error. Both values won't be used once the mapping function returns an error, and their values would be overridden by the next transmitted packet. While both values do indeed get overridden in the next transmission call, the value of tx_info->xdpf is also used to check whether a TX descriptor's transmission has been completed (i.e. a completion for it was polled). An example scenario: 1. Mapping failed, tx_info->xdpf wasn't set to NULL 2. A VF reset occurred leading to IO resource destruction and a call to ena_free_tx_bufs() function 3. Although the descriptor whose mapping failed was freed by the transmission function, it still passes the check if (!tx_info->skb) (skb and xdp_frame are in a union) 4. The xdp_frame associated with the descriptor is freed twice This patch returns the assignment of NULL to tx_info->xdpf to make the cleaning function knows that the descriptor is already freed. Fixes: 504fd6a5390c ("net: ena: fix DMA mapping function issues in XDP") Signed-off-by: Shay Agroskin Signed-off-by: David Arinzon Reviewed-by: Shannon Nelson Signed-off-by: Paolo Abeni --- drivers/net/ethernet/amazon/ena/ena_xdp.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/net/ethernet/amazon/ena/ena_xdp.c b/drivers/net/ethernet/amazon/ena/ena_xdp.c index 337c435d3ce9..5b175e7e92a1 100644 --- a/drivers/net/ethernet/amazon/ena/ena_xdp.c +++ b/drivers/net/ethernet/amazon/ena/ena_xdp.c @@ -89,7 +89,7 @@ int ena_xdp_xmit_frame(struct ena_ring *tx_ring, rc = ena_xdp_tx_map_frame(tx_ring, tx_info, xdpf, &ena_tx_ctx); if (unlikely(rc)) - return rc; + goto err; ena_tx_ctx.req_id = req_id; @@ -112,7 +112,9 @@ int ena_xdp_xmit_frame(struct ena_ring *tx_ring, error_unmap_dma: ena_unmap_tx_buff(tx_ring, tx_info); +err: tx_info->xdpf = NULL; + return rc; } -- cgit v1.2.3 From f969eb84ce482331a991079ab7a5c4dc3b7f89bf Mon Sep 17 00:00:00 2001 From: Ziyang Xuan Date: Sun, 7 Apr 2024 14:56:04 +0800 Subject: netfilter: nf_tables: Fix potential data-race in __nft_expr_type_get() nft_unregister_expr() can concurrent with __nft_expr_type_get(), and there is not any protection when iterate over nf_tables_expressions list in __nft_expr_type_get(). Therefore, there is potential data-race of nf_tables_expressions list entry. Use list_for_each_entry_rcu() to iterate over nf_tables_expressions list in __nft_expr_type_get(), and use rcu_read_lock() in the caller nft_expr_type_get() to protect the entire type query process. Fixes: ef1f7df9170d ("netfilter: nf_tables: expression ops overloading") Signed-off-by: Ziyang Xuan Signed-off-by: Pablo Neira Ayuso --- net/netfilter/nf_tables_api.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/net/netfilter/nf_tables_api.c b/net/netfilter/nf_tables_api.c index d89d77946719..53b8c00863ad 100644 --- a/net/netfilter/nf_tables_api.c +++ b/net/netfilter/nf_tables_api.c @@ -3060,7 +3060,7 @@ static const struct nft_expr_type *__nft_expr_type_get(u8 family, { const struct nft_expr_type *type, *candidate = NULL; - list_for_each_entry(type, &nf_tables_expressions, list) { + list_for_each_entry_rcu(type, &nf_tables_expressions, list) { if (!nla_strcmp(nla, type->name)) { if (!type->family && !candidate) candidate = type; @@ -3092,9 +3092,13 @@ static const struct nft_expr_type *nft_expr_type_get(struct net *net, if (nla == NULL) return ERR_PTR(-EINVAL); + rcu_read_lock(); type = __nft_expr_type_get(family, nla); - if (type != NULL && try_module_get(type->owner)) + if (type != NULL && try_module_get(type->owner)) { + rcu_read_unlock(); return type; + } + rcu_read_unlock(); lockdep_nfnl_nft_mutex_not_held(); #ifdef CONFIG_MODULES -- cgit v1.2.3 From d78d867dcea69c328db30df665be5be7d0148484 Mon Sep 17 00:00:00 2001 From: Ziyang Xuan Date: Sun, 7 Apr 2024 14:56:05 +0800 Subject: netfilter: nf_tables: Fix potential data-race in __nft_obj_type_get() nft_unregister_obj() can concurrent with __nft_obj_type_get(), and there is not any protection when iterate over nf_tables_objects list in __nft_obj_type_get(). Therefore, there is potential data-race of nf_tables_objects list entry. Use list_for_each_entry_rcu() to iterate over nf_tables_objects list in __nft_obj_type_get(), and use rcu_read_lock() in the caller nft_obj_type_get() to protect the entire type query process. Fixes: e50092404c1b ("netfilter: nf_tables: add stateful objects") Signed-off-by: Ziyang Xuan Signed-off-by: Pablo Neira Ayuso --- net/netfilter/nf_tables_api.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/net/netfilter/nf_tables_api.c b/net/netfilter/nf_tables_api.c index 53b8c00863ad..f11d0c0a2c73 100644 --- a/net/netfilter/nf_tables_api.c +++ b/net/netfilter/nf_tables_api.c @@ -7611,7 +7611,7 @@ static const struct nft_object_type *__nft_obj_type_get(u32 objtype, u8 family) { const struct nft_object_type *type; - list_for_each_entry(type, &nf_tables_objects, list) { + list_for_each_entry_rcu(type, &nf_tables_objects, list) { if (type->family != NFPROTO_UNSPEC && type->family != family) continue; @@ -7627,9 +7627,13 @@ nft_obj_type_get(struct net *net, u32 objtype, u8 family) { const struct nft_object_type *type; + rcu_read_lock(); type = __nft_obj_type_get(objtype, family); - if (type != NULL && try_module_get(type->owner)) + if (type != NULL && try_module_get(type->owner)) { + rcu_read_unlock(); return type; + } + rcu_read_unlock(); lockdep_nfnl_nft_mutex_not_held(); #ifdef CONFIG_MODULES -- cgit v1.2.3 From 751de2012eafa4d46d8081056761fa0e9cc8a178 Mon Sep 17 00:00:00 2001 From: Pablo Neira Ayuso Date: Tue, 9 Apr 2024 11:24:59 +0200 Subject: netfilter: br_netfilter: skip conntrack input hook for promisc packets For historical reasons, when bridge device is in promisc mode, packets that are directed to the taps follow bridge input hook path. This patch adds a workaround to reset conntrack for these packets. Jianbo Liu reports warning splats in their test infrastructure where cloned packets reach the br_netfilter input hook to confirm the conntrack object. Scratch one bit from BR_INPUT_SKB_CB to annotate that this packet has reached the input hook because it is passed up to the bridge device to reach the taps. [ 57.571874] WARNING: CPU: 1 PID: 0 at net/bridge/br_netfilter_hooks.c:616 br_nf_local_in+0x157/0x180 [br_netfilter] [ 57.572749] Modules linked in: xt_MASQUERADE nf_conntrack_netlink nfnetlink iptable_nat xt_addrtype xt_conntrack nf_nat br_netfilter rpcsec_gss_krb5 auth_rpcgss oid_registry overlay rpcrdma rdma_ucm ib_iser libiscsi scsi_transport_isc si ib_umad rdma_cm ib_ipoib iw_cm ib_cm mlx5_ib ib_uverbs ib_core mlx5ctl mlx5_core [ 57.575158] CPU: 1 PID: 0 Comm: swapper/1 Not tainted 6.8.0+ #19 [ 57.575700] Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS rel-1.13.0-0-gf21b5a4aeb02-prebuilt.qemu.org 04/01/2014 [ 57.576662] RIP: 0010:br_nf_local_in+0x157/0x180 [br_netfilter] [ 57.577195] Code: fe ff ff 41 bd 04 00 00 00 be 04 00 00 00 e9 4a ff ff ff be 04 00 00 00 48 89 ef e8 f3 a9 3c e1 66 83 ad b4 00 00 00 04 eb 91 <0f> 0b e9 f1 fe ff ff 0f 0b e9 df fe ff ff 48 89 df e8 b3 53 47 e1 [ 57.578722] RSP: 0018:ffff88885f845a08 EFLAGS: 00010202 [ 57.579207] RAX: 0000000000000002 RBX: ffff88812dfe8000 RCX: 0000000000000000 [ 57.579830] RDX: ffff88885f845a60 RSI: ffff8881022dc300 RDI: 0000000000000000 [ 57.580454] RBP: ffff88885f845a60 R08: 0000000000000001 R09: 0000000000000003 [ 57.581076] R10: 00000000ffff1300 R11: 0000000000000002 R12: 0000000000000000 [ 57.581695] R13: ffff8881047ffe00 R14: ffff888108dbee00 R15: ffff88814519b800 [ 57.582313] FS: 0000000000000000(0000) GS:ffff88885f840000(0000) knlGS:0000000000000000 [ 57.583040] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 [ 57.583564] CR2: 000000c4206aa000 CR3: 0000000103847001 CR4: 0000000000370eb0 [ 57.584194] DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 [ 57.584820] DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400 [ 57.585440] Call Trace: [ 57.585721] [ 57.585976] ? __warn+0x7d/0x130 [ 57.586323] ? br_nf_local_in+0x157/0x180 [br_netfilter] [ 57.586811] ? report_bug+0xf1/0x1c0 [ 57.587177] ? handle_bug+0x3f/0x70 [ 57.587539] ? exc_invalid_op+0x13/0x60 [ 57.587929] ? asm_exc_invalid_op+0x16/0x20 [ 57.588336] ? br_nf_local_in+0x157/0x180 [br_netfilter] [ 57.588825] nf_hook_slow+0x3d/0xd0 [ 57.589188] ? br_handle_vlan+0x4b/0x110 [ 57.589579] br_pass_frame_up+0xfc/0x150 [ 57.589970] ? br_port_flags_change+0x40/0x40 [ 57.590396] br_handle_frame_finish+0x346/0x5e0 [ 57.590837] ? ipt_do_table+0x32e/0x430 [ 57.591221] ? br_handle_local_finish+0x20/0x20 [ 57.591656] br_nf_hook_thresh+0x4b/0xf0 [br_netfilter] [ 57.592286] ? br_handle_local_finish+0x20/0x20 [ 57.592802] br_nf_pre_routing_finish+0x178/0x480 [br_netfilter] [ 57.593348] ? br_handle_local_finish+0x20/0x20 [ 57.593782] ? nf_nat_ipv4_pre_routing+0x25/0x60 [nf_nat] [ 57.594279] br_nf_pre_routing+0x24c/0x550 [br_netfilter] [ 57.594780] ? br_nf_hook_thresh+0xf0/0xf0 [br_netfilter] [ 57.595280] br_handle_frame+0x1f3/0x3d0 [ 57.595676] ? br_handle_local_finish+0x20/0x20 [ 57.596118] ? br_handle_frame_finish+0x5e0/0x5e0 [ 57.596566] __netif_receive_skb_core+0x25b/0xfc0 [ 57.597017] ? __napi_build_skb+0x37/0x40 [ 57.597418] __netif_receive_skb_list_core+0xfb/0x220 Fixes: 62e7151ae3eb ("netfilter: bridge: confirm multicast packets before passing them up the stack") Reported-by: Jianbo Liu Signed-off-by: Pablo Neira Ayuso --- net/bridge/br_input.c | 15 +++++++++++---- net/bridge/br_netfilter_hooks.c | 6 ++++++ net/bridge/br_private.h | 1 + net/bridge/netfilter/nf_conntrack_bridge.c | 14 ++++++++++---- 4 files changed, 28 insertions(+), 8 deletions(-) diff --git a/net/bridge/br_input.c b/net/bridge/br_input.c index f21097e73482..ceaa5a89b947 100644 --- a/net/bridge/br_input.c +++ b/net/bridge/br_input.c @@ -30,7 +30,7 @@ br_netif_receive_skb(struct net *net, struct sock *sk, struct sk_buff *skb) return netif_receive_skb(skb); } -static int br_pass_frame_up(struct sk_buff *skb) +static int br_pass_frame_up(struct sk_buff *skb, bool promisc) { struct net_device *indev, *brdev = BR_INPUT_SKB_CB(skb)->brdev; struct net_bridge *br = netdev_priv(brdev); @@ -65,6 +65,8 @@ static int br_pass_frame_up(struct sk_buff *skb) br_multicast_count(br, NULL, skb, br_multicast_igmp_type(skb), BR_MCAST_DIR_TX); + BR_INPUT_SKB_CB(skb)->promisc = promisc; + return NF_HOOK(NFPROTO_BRIDGE, NF_BR_LOCAL_IN, dev_net(indev), NULL, skb, indev, NULL, br_netif_receive_skb); @@ -82,6 +84,7 @@ int br_handle_frame_finish(struct net *net, struct sock *sk, struct sk_buff *skb struct net_bridge_mcast *brmctx; struct net_bridge_vlan *vlan; struct net_bridge *br; + bool promisc; u16 vid = 0; u8 state; @@ -137,7 +140,9 @@ int br_handle_frame_finish(struct net *net, struct sock *sk, struct sk_buff *skb if (p->flags & BR_LEARNING) br_fdb_update(br, p, eth_hdr(skb)->h_source, vid, 0); - local_rcv = !!(br->dev->flags & IFF_PROMISC); + promisc = !!(br->dev->flags & IFF_PROMISC); + local_rcv = promisc; + if (is_multicast_ether_addr(eth_hdr(skb)->h_dest)) { /* by definition the broadcast is also a multicast address */ if (is_broadcast_ether_addr(eth_hdr(skb)->h_dest)) { @@ -200,7 +205,7 @@ int br_handle_frame_finish(struct net *net, struct sock *sk, struct sk_buff *skb unsigned long now = jiffies; if (test_bit(BR_FDB_LOCAL, &dst->flags)) - return br_pass_frame_up(skb); + return br_pass_frame_up(skb, false); if (now != dst->used) dst->used = now; @@ -213,7 +218,7 @@ int br_handle_frame_finish(struct net *net, struct sock *sk, struct sk_buff *skb } if (local_rcv) - return br_pass_frame_up(skb); + return br_pass_frame_up(skb, promisc); out: return 0; @@ -386,6 +391,8 @@ static rx_handler_result_t br_handle_frame(struct sk_buff **pskb) goto forward; } + BR_INPUT_SKB_CB(skb)->promisc = false; + /* The else clause should be hit when nf_hook(): * - returns < 0 (drop/error) * - returns = 0 (stolen/nf_queue) diff --git a/net/bridge/br_netfilter_hooks.c b/net/bridge/br_netfilter_hooks.c index 35e10c5a766d..22e35623c148 100644 --- a/net/bridge/br_netfilter_hooks.c +++ b/net/bridge/br_netfilter_hooks.c @@ -600,11 +600,17 @@ static unsigned int br_nf_local_in(void *priv, struct sk_buff *skb, const struct nf_hook_state *state) { + bool promisc = BR_INPUT_SKB_CB(skb)->promisc; struct nf_conntrack *nfct = skb_nfct(skb); const struct nf_ct_hook *ct_hook; struct nf_conn *ct; int ret; + if (promisc) { + nf_reset_ct(skb); + return NF_ACCEPT; + } + if (!nfct || skb->pkt_type == PACKET_HOST) return NF_ACCEPT; diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h index 86ea5e6689b5..d4bedc87b1d8 100644 --- a/net/bridge/br_private.h +++ b/net/bridge/br_private.h @@ -589,6 +589,7 @@ struct br_input_skb_cb { #endif u8 proxyarp_replied:1; u8 src_port_isolated:1; + u8 promisc:1; #ifdef CONFIG_BRIDGE_VLAN_FILTERING u8 vlan_filtered:1; #endif diff --git a/net/bridge/netfilter/nf_conntrack_bridge.c b/net/bridge/netfilter/nf_conntrack_bridge.c index 6f877e31709b..c3c51b9a6826 100644 --- a/net/bridge/netfilter/nf_conntrack_bridge.c +++ b/net/bridge/netfilter/nf_conntrack_bridge.c @@ -294,18 +294,24 @@ static unsigned int nf_ct_bridge_pre(void *priv, struct sk_buff *skb, static unsigned int nf_ct_bridge_in(void *priv, struct sk_buff *skb, const struct nf_hook_state *state) { - enum ip_conntrack_info ctinfo; + bool promisc = BR_INPUT_SKB_CB(skb)->promisc; + struct nf_conntrack *nfct = skb_nfct(skb); struct nf_conn *ct; - if (skb->pkt_type == PACKET_HOST) + if (promisc) { + nf_reset_ct(skb); + return NF_ACCEPT; + } + + if (!nfct || skb->pkt_type == PACKET_HOST) return NF_ACCEPT; /* nf_conntrack_confirm() cannot handle concurrent clones, * this happens for broad/multicast frames with e.g. macvlan on top * of the bridge device. */ - ct = nf_ct_get(skb, &ctinfo); - if (!ct || nf_ct_is_confirmed(ct) || nf_ct_is_template(ct)) + ct = container_of(nfct, struct nf_conn, ct_general); + if (nf_ct_is_confirmed(ct) || nf_ct_is_template(ct)) return NF_ACCEPT; /* let inet prerouting call conntrack again */ -- cgit v1.2.3 From 29b359cf6d95fd60730533f7f10464e95bd17c73 Mon Sep 17 00:00:00 2001 From: Pablo Neira Ayuso Date: Wed, 10 Apr 2024 18:50:45 +0200 Subject: netfilter: nft_set_pipapo: walk over current view on netlink dump The generation mask can be updated while netlink dump is in progress. The pipapo set backend walk iterator cannot rely on it to infer what view of the datastructure is to be used. Add notation to specify if user wants to read/update the set. Based on patch from Florian Westphal. Fixes: 2b84e215f874 ("netfilter: nft_set_pipapo: .walk does not deal with generations") Signed-off-by: Pablo Neira Ayuso --- include/net/netfilter/nf_tables.h | 14 ++++++++++++++ net/netfilter/nf_tables_api.c | 6 ++++++ net/netfilter/nft_set_pipapo.c | 5 +++-- 3 files changed, 23 insertions(+), 2 deletions(-) diff --git a/include/net/netfilter/nf_tables.h b/include/net/netfilter/nf_tables.h index e27c28b612e4..3f1ed467f951 100644 --- a/include/net/netfilter/nf_tables.h +++ b/include/net/netfilter/nf_tables.h @@ -307,9 +307,23 @@ static inline void *nft_elem_priv_cast(const struct nft_elem_priv *priv) return (void *)priv; } + +/** + * enum nft_iter_type - nftables set iterator type + * + * @NFT_ITER_READ: read-only iteration over set elements + * @NFT_ITER_UPDATE: iteration under mutex to update set element state + */ +enum nft_iter_type { + NFT_ITER_UNSPEC, + NFT_ITER_READ, + NFT_ITER_UPDATE, +}; + struct nft_set; struct nft_set_iter { u8 genmask; + enum nft_iter_type type:8; unsigned int count; unsigned int skip; int err; diff --git a/net/netfilter/nf_tables_api.c b/net/netfilter/nf_tables_api.c index f11d0c0a2c73..a7a34db62ea9 100644 --- a/net/netfilter/nf_tables_api.c +++ b/net/netfilter/nf_tables_api.c @@ -626,6 +626,7 @@ static void nft_map_deactivate(const struct nft_ctx *ctx, struct nft_set *set) { struct nft_set_iter iter = { .genmask = nft_genmask_next(ctx->net), + .type = NFT_ITER_UPDATE, .fn = nft_mapelem_deactivate, }; @@ -5445,6 +5446,7 @@ int nf_tables_bind_set(const struct nft_ctx *ctx, struct nft_set *set, } iter.genmask = nft_genmask_next(ctx->net); + iter.type = NFT_ITER_UPDATE; iter.skip = 0; iter.count = 0; iter.err = 0; @@ -5518,6 +5520,7 @@ static void nft_map_activate(const struct nft_ctx *ctx, struct nft_set *set) { struct nft_set_iter iter = { .genmask = nft_genmask_next(ctx->net), + .type = NFT_ITER_UPDATE, .fn = nft_mapelem_activate, }; @@ -5892,6 +5895,7 @@ static int nf_tables_dump_set(struct sk_buff *skb, struct netlink_callback *cb) args.skb = skb; args.reset = dump_ctx->reset; args.iter.genmask = nft_genmask_cur(net); + args.iter.type = NFT_ITER_READ; args.iter.skip = cb->args[0]; args.iter.count = 0; args.iter.err = 0; @@ -7376,6 +7380,7 @@ static int nft_set_flush(struct nft_ctx *ctx, struct nft_set *set, u8 genmask) { struct nft_set_iter iter = { .genmask = genmask, + .type = NFT_ITER_UPDATE, .fn = nft_setelem_flush, }; @@ -10879,6 +10884,7 @@ static int nf_tables_check_loops(const struct nft_ctx *ctx, continue; iter.genmask = nft_genmask_next(ctx->net); + iter.type = NFT_ITER_UPDATE; iter.skip = 0; iter.count = 0; iter.err = 0; diff --git a/net/netfilter/nft_set_pipapo.c b/net/netfilter/nft_set_pipapo.c index df8de5090246..11e44e4dfb1f 100644 --- a/net/netfilter/nft_set_pipapo.c +++ b/net/netfilter/nft_set_pipapo.c @@ -2115,13 +2115,14 @@ static void nft_pipapo_walk(const struct nft_ctx *ctx, struct nft_set *set, struct nft_set_iter *iter) { struct nft_pipapo *priv = nft_set_priv(set); - struct net *net = read_pnet(&set->net); const struct nft_pipapo_match *m; const struct nft_pipapo_field *f; unsigned int i, r; + WARN_ON_ONCE(iter->type == NFT_ITER_UNSPEC); + rcu_read_lock(); - if (iter->genmask == nft_genmask_cur(net)) + if (iter->type == NFT_ITER_READ) m = rcu_dereference(priv->match); else m = priv->clone; -- cgit v1.2.3 From 3cfc9ec039af60dbd8965ae085b2c2ccdcfbe1cc Mon Sep 17 00:00:00 2001 From: Florian Westphal Date: Wed, 10 Apr 2024 21:05:13 +0200 Subject: netfilter: nft_set_pipapo: do not free live element Pablo reports a crash with large batches of elements with a back-to-back add/remove pattern. Quoting Pablo: add_elem("00000000") timeout 100 ms ... add_elem("0000000X") timeout 100 ms del_elem("0000000X") <---------------- delete one that was just added ... add_elem("00005000") timeout 100 ms 1) nft_pipapo_remove() removes element 0000000X Then, KASAN shows a splat. Looking at the remove function there is a chance that we will drop a rule that maps to a non-deactivated element. Removal happens in two steps, first we do a lookup for key k and return the to-be-removed element and mark it as inactive in the next generation. Then, in a second step, the element gets removed from the set/map. The _remove function does not work correctly if we have more than one element that share the same key. This can happen if we insert an element into a set when the set already holds an element with same key, but the element mapping to the existing key has timed out or is not active in the next generation. In such case its possible that removal will unmap the wrong element. If this happens, we will leak the non-deactivated element, it becomes unreachable. The element that got deactivated (and will be freed later) will remain reachable in the set data structure, this can result in a crash when such an element is retrieved during lookup (stale pointer). Add a check that the fully matching key does in fact map to the element that we have marked as inactive in the deactivation step. If not, we need to continue searching. Add a bug/warn trap at the end of the function as well, the remove function must not ever be called with an invisible/unreachable/non-existent element. v2: avoid uneeded temporary variable (Stefano) Fixes: 3c4287f62044 ("nf_tables: Add set type for arbitrary concatenation of ranges") Reported-by: Pablo Neira Ayuso Reviewed-by: Stefano Brivio Signed-off-by: Florian Westphal Signed-off-by: Pablo Neira Ayuso --- net/netfilter/nft_set_pipapo.c | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/net/netfilter/nft_set_pipapo.c b/net/netfilter/nft_set_pipapo.c index 11e44e4dfb1f..eeaf05ffba95 100644 --- a/net/netfilter/nft_set_pipapo.c +++ b/net/netfilter/nft_set_pipapo.c @@ -2077,6 +2077,8 @@ static void nft_pipapo_remove(const struct net *net, const struct nft_set *set, rules_fx = rules_f0; nft_pipapo_for_each_field(f, i, m) { + bool last = i == m->field_count - 1; + if (!pipapo_match_field(f, start, rules_fx, match_start, match_end)) break; @@ -2089,16 +2091,18 @@ static void nft_pipapo_remove(const struct net *net, const struct nft_set *set, match_start += NFT_PIPAPO_GROUPS_PADDED_SIZE(f); match_end += NFT_PIPAPO_GROUPS_PADDED_SIZE(f); - } - if (i == m->field_count) { - priv->dirty = true; - pipapo_drop(m, rulemap); - return; + if (last && f->mt[rulemap[i].to].e == e) { + priv->dirty = true; + pipapo_drop(m, rulemap); + return; + } } first_rule += rules_f0; } + + WARN_ON_ONCE(1); /* elem_priv not found */ } /** -- cgit v1.2.3 From 87b3593bed1868b2d9fe096c01bcdf0ea86cbebf Mon Sep 17 00:00:00 2001 From: Pablo Neira Ayuso Date: Tue, 9 Apr 2024 13:47:33 +0200 Subject: netfilter: flowtable: validate pppoe header Ensure there is sufficient room to access the protocol field of the PPPoe header. Validate it once before the flowtable lookup, then use a helper function to access protocol field. Reported-by: syzbot+b6f07e1c07ef40199081@syzkaller.appspotmail.com Fixes: 72efd585f714 ("netfilter: flowtable: add pppoe support") Signed-off-by: Pablo Neira Ayuso --- include/net/netfilter/nf_flow_table.h | 12 +++++++++++- net/netfilter/nf_flow_table_inet.c | 3 ++- net/netfilter/nf_flow_table_ip.c | 8 +++++--- 3 files changed, 18 insertions(+), 5 deletions(-) diff --git a/include/net/netfilter/nf_flow_table.h b/include/net/netfilter/nf_flow_table.h index a763dd327c6e..9abb7ee40d72 100644 --- a/include/net/netfilter/nf_flow_table.h +++ b/include/net/netfilter/nf_flow_table.h @@ -336,7 +336,7 @@ int nf_flow_rule_route_ipv6(struct net *net, struct flow_offload *flow, int nf_flow_table_offload_init(void); void nf_flow_table_offload_exit(void); -static inline __be16 nf_flow_pppoe_proto(const struct sk_buff *skb) +static inline __be16 __nf_flow_pppoe_proto(const struct sk_buff *skb) { __be16 proto; @@ -352,6 +352,16 @@ static inline __be16 nf_flow_pppoe_proto(const struct sk_buff *skb) return 0; } +static inline bool nf_flow_pppoe_proto(struct sk_buff *skb, __be16 *inner_proto) +{ + if (!pskb_may_pull(skb, PPPOE_SES_HLEN)) + return false; + + *inner_proto = __nf_flow_pppoe_proto(skb); + + return true; +} + #define NF_FLOW_TABLE_STAT_INC(net, count) __this_cpu_inc((net)->ft.stat->count) #define NF_FLOW_TABLE_STAT_DEC(net, count) __this_cpu_dec((net)->ft.stat->count) #define NF_FLOW_TABLE_STAT_INC_ATOMIC(net, count) \ diff --git a/net/netfilter/nf_flow_table_inet.c b/net/netfilter/nf_flow_table_inet.c index 9505f9d188ff..6eef15648b7b 100644 --- a/net/netfilter/nf_flow_table_inet.c +++ b/net/netfilter/nf_flow_table_inet.c @@ -21,7 +21,8 @@ nf_flow_offload_inet_hook(void *priv, struct sk_buff *skb, proto = veth->h_vlan_encapsulated_proto; break; case htons(ETH_P_PPP_SES): - proto = nf_flow_pppoe_proto(skb); + if (!nf_flow_pppoe_proto(skb, &proto)) + return NF_ACCEPT; break; default: proto = skb->protocol; diff --git a/net/netfilter/nf_flow_table_ip.c b/net/netfilter/nf_flow_table_ip.c index e45fade76409..9e9e105052da 100644 --- a/net/netfilter/nf_flow_table_ip.c +++ b/net/netfilter/nf_flow_table_ip.c @@ -273,10 +273,11 @@ static unsigned int nf_flow_xmit_xfrm(struct sk_buff *skb, return NF_STOLEN; } -static bool nf_flow_skb_encap_protocol(const struct sk_buff *skb, __be16 proto, +static bool nf_flow_skb_encap_protocol(struct sk_buff *skb, __be16 proto, u32 *offset) { struct vlan_ethhdr *veth; + __be16 inner_proto; switch (skb->protocol) { case htons(ETH_P_8021Q): @@ -287,7 +288,8 @@ static bool nf_flow_skb_encap_protocol(const struct sk_buff *skb, __be16 proto, } break; case htons(ETH_P_PPP_SES): - if (nf_flow_pppoe_proto(skb) == proto) { + if (nf_flow_pppoe_proto(skb, &inner_proto) && + inner_proto == proto) { *offset += PPPOE_SES_HLEN; return true; } @@ -316,7 +318,7 @@ static void nf_flow_encap_pop(struct sk_buff *skb, skb_reset_network_header(skb); break; case htons(ETH_P_PPP_SES): - skb->protocol = nf_flow_pppoe_proto(skb); + skb->protocol = __nf_flow_pppoe_proto(skb); skb_pull(skb, PPPOE_SES_HLEN); skb_reset_network_header(skb); break; -- cgit v1.2.3 From 6db5dc7b351b9569940cd1cf445e237c42cd6d27 Mon Sep 17 00:00:00 2001 From: Pablo Neira Ayuso Date: Thu, 11 Apr 2024 00:09:00 +0200 Subject: netfilter: flowtable: incorrect pppoe tuple pppoe traffic reaching ingress path does not match the flowtable entry because the pppoe header is expected to be at the network header offset. This bug causes a mismatch in the flow table lookup, so pppoe packets enter the classical forwarding path. Fixes: 72efd585f714 ("netfilter: flowtable: add pppoe support") Signed-off-by: Pablo Neira Ayuso --- net/netfilter/nf_flow_table_ip.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/netfilter/nf_flow_table_ip.c b/net/netfilter/nf_flow_table_ip.c index 9e9e105052da..5383bed3d3e0 100644 --- a/net/netfilter/nf_flow_table_ip.c +++ b/net/netfilter/nf_flow_table_ip.c @@ -157,7 +157,7 @@ static void nf_flow_tuple_encap(struct sk_buff *skb, tuple->encap[i].proto = skb->protocol; break; case htons(ETH_P_PPP_SES): - phdr = (struct pppoe_hdr *)skb_mac_header(skb); + phdr = (struct pppoe_hdr *)skb_network_header(skb); tuple->encap[i].id = ntohs(phdr->sid); tuple->encap[i].proto = skb->protocol; break; -- cgit v1.2.3 From 1aa4ad4eb695bac1b0a7ba542a16d6833c9c8dd8 Mon Sep 17 00:00:00 2001 From: Tony Lindgren Date: Thu, 11 Apr 2024 08:58:45 +0300 Subject: serial: core: Fix missing shutdown and startup for serial base port We are seeing start_tx being called after port shutdown as noted by Jiri. This happens because we are missing the startup and shutdown related functions for the serial base port. Let's fix the issue by adding startup and shutdown functions for the serial base port to block tx flushing for the serial base port when the port is not in use. Fixes: 84a9582fd203 ("serial: core: Start managing serial controllers to enable runtime PM") Cc: stable Reported-by: Jiri Slaby Signed-off-by: Tony Lindgren Link: https://lore.kernel.org/r/20240411055848.38190-1-tony@atomide.com Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/serial_base.h | 4 ++++ drivers/tty/serial/serial_core.c | 20 +++++++++++++++++--- drivers/tty/serial/serial_port.c | 34 ++++++++++++++++++++++++++++++++++ 3 files changed, 55 insertions(+), 3 deletions(-) diff --git a/drivers/tty/serial/serial_base.h b/drivers/tty/serial/serial_base.h index c74c548f0db6..b6c38d2edfd4 100644 --- a/drivers/tty/serial/serial_base.h +++ b/drivers/tty/serial/serial_base.h @@ -22,6 +22,7 @@ struct serial_ctrl_device { struct serial_port_device { struct device dev; struct uart_port *port; + unsigned int tx_enabled:1; }; int serial_base_ctrl_init(void); @@ -30,6 +31,9 @@ void serial_base_ctrl_exit(void); int serial_base_port_init(void); void serial_base_port_exit(void); +void serial_base_port_startup(struct uart_port *port); +void serial_base_port_shutdown(struct uart_port *port); + int serial_base_driver_register(struct device_driver *driver); void serial_base_driver_unregister(struct device_driver *driver); diff --git a/drivers/tty/serial/serial_core.c b/drivers/tty/serial/serial_core.c index 2247efe97250..c476d884356d 100644 --- a/drivers/tty/serial/serial_core.c +++ b/drivers/tty/serial/serial_core.c @@ -323,16 +323,26 @@ static int uart_startup(struct tty_struct *tty, struct uart_state *state, bool init_hw) { struct tty_port *port = &state->port; + struct uart_port *uport; int retval; if (tty_port_initialized(port)) - return 0; + goto out_base_port_startup; retval = uart_port_startup(tty, state, init_hw); - if (retval) + if (retval) { set_bit(TTY_IO_ERROR, &tty->flags); + return retval; + } - return retval; +out_base_port_startup: + uport = uart_port_check(state); + if (!uport) + return -EIO; + + serial_base_port_startup(uport); + + return 0; } /* @@ -355,6 +365,9 @@ static void uart_shutdown(struct tty_struct *tty, struct uart_state *state) if (tty) set_bit(TTY_IO_ERROR, &tty->flags); + if (uport) + serial_base_port_shutdown(uport); + if (tty_port_initialized(port)) { tty_port_set_initialized(port, false); @@ -1775,6 +1788,7 @@ static void uart_tty_port_shutdown(struct tty_port *port) uport->ops->stop_rx(uport); uart_port_unlock_irq(uport); + serial_base_port_shutdown(uport); uart_port_shutdown(port); /* diff --git a/drivers/tty/serial/serial_port.c b/drivers/tty/serial/serial_port.c index 22b9eeb23e68..7e3a1c7b097c 100644 --- a/drivers/tty/serial/serial_port.c +++ b/drivers/tty/serial/serial_port.c @@ -39,8 +39,12 @@ static int serial_port_runtime_resume(struct device *dev) /* Flush any pending TX for the port */ uart_port_lock_irqsave(port, &flags); + if (!port_dev->tx_enabled) + goto unlock; if (__serial_port_busy(port)) port->ops->start_tx(port); + +unlock: uart_port_unlock_irqrestore(port, flags); out: @@ -60,6 +64,11 @@ static int serial_port_runtime_suspend(struct device *dev) return 0; uart_port_lock_irqsave(port, &flags); + if (!port_dev->tx_enabled) { + uart_port_unlock_irqrestore(port, flags); + return 0; + } + busy = __serial_port_busy(port); if (busy) port->ops->start_tx(port); @@ -71,6 +80,31 @@ static int serial_port_runtime_suspend(struct device *dev) return busy ? -EBUSY : 0; } +static void serial_base_port_set_tx(struct uart_port *port, + struct serial_port_device *port_dev, + bool enabled) +{ + unsigned long flags; + + uart_port_lock_irqsave(port, &flags); + port_dev->tx_enabled = enabled; + uart_port_unlock_irqrestore(port, flags); +} + +void serial_base_port_startup(struct uart_port *port) +{ + struct serial_port_device *port_dev = port->port_dev; + + serial_base_port_set_tx(port, port_dev, true); +} + +void serial_base_port_shutdown(struct uart_port *port) +{ + struct serial_port_device *port_dev = port->port_dev; + + serial_base_port_set_tx(port, port_dev, false); +} + static DEFINE_RUNTIME_DEV_PM_OPS(serial_port_pm, serial_port_runtime_suspend, serial_port_runtime_resume, NULL); -- cgit v1.2.3 From 34b990e9bb54d20b9675ca9483be8668eed374d8 Mon Sep 17 00:00:00 2001 From: Fabio Estevam Date: Tue, 9 Apr 2024 13:29:10 -0300 Subject: usb: misc: onboard_usb_hub: Disable the USB hub clock on failure In case regulator_bulk_enable() fails, the previously enabled USB hub clock should be disabled. Fix it accordingly. Fixes: 65e62b8a955a ("usb: misc: onboard_usb_hub: Add support for clock input") Cc: stable Signed-off-by: Fabio Estevam Reviewed-by: Frieder Schrempf Acked-by: Matthias Kaehlcke Link: https://lore.kernel.org/r/20240409162910.2061640-1-festevam@gmail.com Signed-off-by: Greg Kroah-Hartman --- drivers/usb/misc/onboard_usb_hub.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/drivers/usb/misc/onboard_usb_hub.c b/drivers/usb/misc/onboard_usb_hub.c index c6101ed2d9d4..d8049275a023 100644 --- a/drivers/usb/misc/onboard_usb_hub.c +++ b/drivers/usb/misc/onboard_usb_hub.c @@ -78,7 +78,7 @@ static int onboard_hub_power_on(struct onboard_hub *hub) err = regulator_bulk_enable(hub->pdata->num_supplies, hub->supplies); if (err) { dev_err(hub->dev, "failed to enable supplies: %pe\n", ERR_PTR(err)); - return err; + goto disable_clk; } fsleep(hub->pdata->reset_us); @@ -87,6 +87,10 @@ static int onboard_hub_power_on(struct onboard_hub *hub) hub->is_powered_on = true; return 0; + +disable_clk: + clk_disable_unprepare(hub->clk); + return err; } static int onboard_hub_power_off(struct onboard_hub *hub) -- cgit v1.2.3 From 1d165c5a1c85747bf48f37a80636a4a73e1576a1 Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Thu, 11 Apr 2024 09:33:32 +0100 Subject: ASoC: codecs: tas2780: remove redundant assignments to variable ret Variable ret is being assigned a value that is never read in a couple of places. The variable is being re-assigned later on. The assignments are redundant and can be removed. Cleans up clang scan build warning: sound/soc/codecs/tas2780.c:84:2: warning: Value stored to 'ret' is never read [deadcode.DeadStores] Signed-off-by: Colin Ian King Link: https://msgid.link/r/20240411083332.304887-1-colin.i.king@gmail.com Signed-off-by: Mark Brown --- sound/soc/codecs/tas2780.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/sound/soc/codecs/tas2780.c b/sound/soc/codecs/tas2780.c index 41076be23854..972e8ea5ebde 100644 --- a/sound/soc/codecs/tas2780.c +++ b/sound/soc/codecs/tas2780.c @@ -71,7 +71,7 @@ static int tas2780_codec_resume(struct snd_soc_component *component) { struct tas2780_priv *tas2780 = snd_soc_component_get_drvdata(component); - int ret = 0; + int ret; ret = snd_soc_component_update_bits(component, TAS2780_PWR_CTRL, TAS2780_PWR_CTRL_MASK, TAS2780_PWR_CTRL_ACTIVE); @@ -81,7 +81,6 @@ static int tas2780_codec_resume(struct snd_soc_component *component) __func__, ret); goto err; } - ret = 0; regcache_cache_only(tas2780->regmap, false); ret = regcache_sync(tas2780->regmap); err: -- cgit v1.2.3 From c8d2f34ea96ea3bce6ba2535f867f0d4ee3b22e1 Mon Sep 17 00:00:00 2001 From: Samuel Thibault Date: Sat, 23 Mar 2024 17:48:43 +0100 Subject: speakup: Avoid crash on very long word In case a console is set up really large and contains a really long word (> 256 characters), we have to stop before the length of the word buffer. Signed-off-by: Samuel Thibault Fixes: c6e3fd22cd538 ("Staging: add speakup to the staging directory") Cc: stable@vger.kernel.org Link: https://lore.kernel.org/r/20240323164843.1426997-1-samuel.thibault@ens-lyon.org Signed-off-by: Greg Kroah-Hartman --- drivers/accessibility/speakup/main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/accessibility/speakup/main.c b/drivers/accessibility/speakup/main.c index 1fbc9b921c4f..736c2eb8c0f3 100644 --- a/drivers/accessibility/speakup/main.c +++ b/drivers/accessibility/speakup/main.c @@ -574,7 +574,7 @@ static u_long get_word(struct vc_data *vc) } attr_ch = get_char(vc, (u_short *)tmp_pos, &spk_attr); buf[cnt++] = attr_ch; - while (tmpx < vc->vc_cols - 1) { + while (tmpx < vc->vc_cols - 1 && cnt < sizeof(buf) - 1) { tmp_pos += 2; tmpx++; ch = get_char(vc, (u_short *)tmp_pos, &temp); -- cgit v1.2.3 From 0dc04112bee6fdd6eb847ccb32214703022c0269 Mon Sep 17 00:00:00 2001 From: Alexander Usyskin Date: Tue, 12 Mar 2024 07:19:58 +0200 Subject: mei: me: disable RPL-S on SPS and IGN firmwares Extend the quirk to disable MEI interface on Intel PCH Ignition (IGN) and SPS firmwares for RPL-S devices. These firmwares do not support the MEI protocol. Fixes: 3ed8c7d39cfe ("mei: me: add raptor lake point S DID") Cc: stable@vger.kernel.org Signed-off-by: Alexander Usyskin Signed-off-by: Tomas Winkler Link: https://lore.kernel.org/r/20240312051958.118478-1-tomas.winkler@intel.com Signed-off-by: Greg Kroah-Hartman --- drivers/misc/mei/pci-me.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/misc/mei/pci-me.c b/drivers/misc/mei/pci-me.c index b5757993c9b2..c39718042e2e 100644 --- a/drivers/misc/mei/pci-me.c +++ b/drivers/misc/mei/pci-me.c @@ -116,7 +116,7 @@ static const struct pci_device_id mei_me_pci_tbl[] = { {MEI_PCI_DEVICE(MEI_DEV_ID_ADP_P, MEI_ME_PCH15_CFG)}, {MEI_PCI_DEVICE(MEI_DEV_ID_ADP_N, MEI_ME_PCH15_CFG)}, - {MEI_PCI_DEVICE(MEI_DEV_ID_RPL_S, MEI_ME_PCH15_CFG)}, + {MEI_PCI_DEVICE(MEI_DEV_ID_RPL_S, MEI_ME_PCH15_SPS_CFG)}, {MEI_PCI_DEVICE(MEI_DEV_ID_MTL_M, MEI_ME_PCH15_CFG)}, {MEI_PCI_DEVICE(MEI_DEV_ID_ARL_S, MEI_ME_PCH15_CFG)}, -- cgit v1.2.3 From 26ac2df47d4c58f17210b7a59037e40f7eca693e Mon Sep 17 00:00:00 2001 From: Ricky Wu Date: Thu, 14 Mar 2024 14:51:13 +0800 Subject: misc: rtsx: Fix rts5264 driver status incorrect when card removed rts5264 driver not clean express link error and set EXTRA_CAPS_SD_EXPRESS capability back when card removed Fixes: 6a511c9b3a0d ("misc: rtsx: add to support new card reader rts5264") Cc: stable Signed-off-by: Ricky Wu Link: https://lore.kernel.org/r/20240314065113.5962-1-ricky_wu@realtek.com Signed-off-by: Greg Kroah-Hartman --- drivers/misc/cardreader/rtsx_pcr.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/misc/cardreader/rtsx_pcr.c b/drivers/misc/cardreader/rtsx_pcr.c index 1a64364700eb..0ad2ff9065aa 100644 --- a/drivers/misc/cardreader/rtsx_pcr.c +++ b/drivers/misc/cardreader/rtsx_pcr.c @@ -1002,7 +1002,7 @@ static irqreturn_t rtsx_pci_isr(int irq, void *dev_id) } else { pcr->card_removed |= SD_EXIST; pcr->card_inserted &= ~SD_EXIST; - if (PCI_PID(pcr) == PID_5261) { + if ((PCI_PID(pcr) == PID_5261) || (PCI_PID(pcr) == PID_5264)) { rtsx_pci_write_register(pcr, RTS5261_FW_STATUS, RTS5261_EXPRESS_LINK_FAIL_MASK, 0); pcr->extra_caps |= EXTRA_CAPS_SD_EXPRESS; -- cgit v1.2.3 From e3dc66d998d2b0c2734db9ca1d6c94c97349529a Mon Sep 17 00:00:00 2001 From: Sakari Ailus Date: Wed, 3 Apr 2024 13:13:40 +0800 Subject: Revert "mei: vsc: Call wake_up() in the threaded IRQ handler" This reverts commit 058a38acba15fd8e7b262ec6e17c4204cb15f984. It's not necessary to avoid a spinlock, a sleeping lock on PREEMPT_RT, in an interrupt handler as the interrupt handler itself would be called in a process context if PREEMPT_RT is enabled. So revert the patch. Cc: stable@vger.kernel.org # for 6.8 Signed-off-by: Sakari Ailus Acked-by: Tomas Winkler Link: https://lore.kernel.org/r/20240403051341.3534650-1-wentong.wu@intel.com Signed-off-by: Greg Kroah-Hartman --- drivers/misc/mei/vsc-tp.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/misc/mei/vsc-tp.c b/drivers/misc/mei/vsc-tp.c index ecfb70cd057c..968a92a7425d 100644 --- a/drivers/misc/mei/vsc-tp.c +++ b/drivers/misc/mei/vsc-tp.c @@ -419,6 +419,8 @@ static irqreturn_t vsc_tp_isr(int irq, void *data) atomic_inc(&tp->assert_cnt); + wake_up(&tp->xfer_wait); + return IRQ_WAKE_THREAD; } @@ -426,8 +428,6 @@ static irqreturn_t vsc_tp_thread_isr(int irq, void *data) { struct vsc_tp *tp = data; - wake_up(&tp->xfer_wait); - if (tp->event_notify) tp->event_notify(tp->event_notify_context); -- cgit v1.2.3 From f6085a96c97387154be7eaebd1a5420eb3cd55dc Mon Sep 17 00:00:00 2001 From: Sakari Ailus Date: Wed, 3 Apr 2024 13:13:41 +0800 Subject: mei: vsc: Unregister interrupt handler for system suspend Unregister the MEI VSC interrupt handler before system suspend and re-register it at system resume time. This mirrors implementation of other MEI devices. This patch fixes the bug that causes continuous stream of MEI VSC errors after system resume. Fixes: 386a766c4169 ("mei: Add MEI hardware support for IVSC device") Cc: stable@vger.kernel.org # for 6.8 Reported-by: Dominik Brodowski Signed-off-by: Wentong Wu Signed-off-by: Sakari Ailus Acked-by: Tomas Winkler Link: https://lore.kernel.org/r/20240403051341.3534650-2-wentong.wu@intel.com Signed-off-by: Greg Kroah-Hartman --- drivers/misc/mei/platform-vsc.c | 17 ++++++++- drivers/misc/mei/vsc-tp.c | 84 +++++++++++++++++++++++++++++------------ drivers/misc/mei/vsc-tp.h | 3 ++ 3 files changed, 78 insertions(+), 26 deletions(-) diff --git a/drivers/misc/mei/platform-vsc.c b/drivers/misc/mei/platform-vsc.c index 6c9f00bcb94b..b543e6b9f3cf 100644 --- a/drivers/misc/mei/platform-vsc.c +++ b/drivers/misc/mei/platform-vsc.c @@ -400,25 +400,40 @@ static void mei_vsc_remove(struct platform_device *pdev) static int mei_vsc_suspend(struct device *dev) { struct mei_device *mei_dev = dev_get_drvdata(dev); + struct mei_vsc_hw *hw = mei_dev_to_vsc_hw(mei_dev); mei_stop(mei_dev); + mei_disable_interrupts(mei_dev); + + vsc_tp_free_irq(hw->tp); + return 0; } static int mei_vsc_resume(struct device *dev) { struct mei_device *mei_dev = dev_get_drvdata(dev); + struct mei_vsc_hw *hw = mei_dev_to_vsc_hw(mei_dev); int ret; - ret = mei_restart(mei_dev); + ret = vsc_tp_request_irq(hw->tp); if (ret) return ret; + ret = mei_restart(mei_dev); + if (ret) + goto err_free; + /* start timer if stopped in suspend */ schedule_delayed_work(&mei_dev->timer_work, HZ); return 0; + +err_free: + vsc_tp_free_irq(hw->tp); + + return ret; } static DEFINE_SIMPLE_DEV_PM_OPS(mei_vsc_pm_ops, mei_vsc_suspend, mei_vsc_resume); diff --git a/drivers/misc/mei/vsc-tp.c b/drivers/misc/mei/vsc-tp.c index 968a92a7425d..e6a98dba8a73 100644 --- a/drivers/misc/mei/vsc-tp.c +++ b/drivers/misc/mei/vsc-tp.c @@ -94,6 +94,27 @@ static const struct acpi_gpio_mapping vsc_tp_acpi_gpios[] = { {} }; +static irqreturn_t vsc_tp_isr(int irq, void *data) +{ + struct vsc_tp *tp = data; + + atomic_inc(&tp->assert_cnt); + + wake_up(&tp->xfer_wait); + + return IRQ_WAKE_THREAD; +} + +static irqreturn_t vsc_tp_thread_isr(int irq, void *data) +{ + struct vsc_tp *tp = data; + + if (tp->event_notify) + tp->event_notify(tp->event_notify_context); + + return IRQ_HANDLED; +} + /* wakeup firmware and wait for response */ static int vsc_tp_wakeup_request(struct vsc_tp *tp) { @@ -383,6 +404,37 @@ int vsc_tp_register_event_cb(struct vsc_tp *tp, vsc_tp_event_cb_t event_cb, } EXPORT_SYMBOL_NS_GPL(vsc_tp_register_event_cb, VSC_TP); +/** + * vsc_tp_request_irq - request irq for vsc_tp device + * @tp: vsc_tp device handle + */ +int vsc_tp_request_irq(struct vsc_tp *tp) +{ + struct spi_device *spi = tp->spi; + struct device *dev = &spi->dev; + int ret; + + irq_set_status_flags(spi->irq, IRQ_DISABLE_UNLAZY); + ret = request_threaded_irq(spi->irq, vsc_tp_isr, vsc_tp_thread_isr, + IRQF_TRIGGER_FALLING | IRQF_ONESHOT, + dev_name(dev), tp); + if (ret) + return ret; + + return 0; +} +EXPORT_SYMBOL_NS_GPL(vsc_tp_request_irq, VSC_TP); + +/** + * vsc_tp_free_irq - free irq for vsc_tp device + * @tp: vsc_tp device handle + */ +void vsc_tp_free_irq(struct vsc_tp *tp) +{ + free_irq(tp->spi->irq, tp); +} +EXPORT_SYMBOL_NS_GPL(vsc_tp_free_irq, VSC_TP); + /** * vsc_tp_intr_synchronize - synchronize vsc_tp interrupt * @tp: vsc_tp device handle @@ -413,27 +465,6 @@ void vsc_tp_intr_disable(struct vsc_tp *tp) } EXPORT_SYMBOL_NS_GPL(vsc_tp_intr_disable, VSC_TP); -static irqreturn_t vsc_tp_isr(int irq, void *data) -{ - struct vsc_tp *tp = data; - - atomic_inc(&tp->assert_cnt); - - wake_up(&tp->xfer_wait); - - return IRQ_WAKE_THREAD; -} - -static irqreturn_t vsc_tp_thread_isr(int irq, void *data) -{ - struct vsc_tp *tp = data; - - if (tp->event_notify) - tp->event_notify(tp->event_notify_context); - - return IRQ_HANDLED; -} - static int vsc_tp_match_any(struct acpi_device *adev, void *data) { struct acpi_device **__adev = data; @@ -490,10 +521,9 @@ static int vsc_tp_probe(struct spi_device *spi) tp->spi = spi; irq_set_status_flags(spi->irq, IRQ_DISABLE_UNLAZY); - ret = devm_request_threaded_irq(dev, spi->irq, vsc_tp_isr, - vsc_tp_thread_isr, - IRQF_TRIGGER_FALLING | IRQF_ONESHOT, - dev_name(dev), tp); + ret = request_threaded_irq(spi->irq, vsc_tp_isr, vsc_tp_thread_isr, + IRQF_TRIGGER_FALLING | IRQF_ONESHOT, + dev_name(dev), tp); if (ret) return ret; @@ -522,6 +552,8 @@ static int vsc_tp_probe(struct spi_device *spi) err_destroy_lock: mutex_destroy(&tp->mutex); + free_irq(spi->irq, tp); + return ret; } @@ -532,6 +564,8 @@ static void vsc_tp_remove(struct spi_device *spi) platform_device_unregister(tp->pdev); mutex_destroy(&tp->mutex); + + free_irq(spi->irq, tp); } static const struct acpi_device_id vsc_tp_acpi_ids[] = { diff --git a/drivers/misc/mei/vsc-tp.h b/drivers/misc/mei/vsc-tp.h index f9513ddc3e40..14ca195cbddc 100644 --- a/drivers/misc/mei/vsc-tp.h +++ b/drivers/misc/mei/vsc-tp.h @@ -37,6 +37,9 @@ int vsc_tp_xfer(struct vsc_tp *tp, u8 cmd, const void *obuf, size_t olen, int vsc_tp_register_event_cb(struct vsc_tp *tp, vsc_tp_event_cb_t event_cb, void *context); +int vsc_tp_request_irq(struct vsc_tp *tp); +void vsc_tp_free_irq(struct vsc_tp *tp); + void vsc_tp_intr_enable(struct vsc_tp *tp); void vsc_tp_intr_disable(struct vsc_tp *tp); void vsc_tp_intr_synchronize(struct vsc_tp *tp); -- cgit v1.2.3 From d1718530e3f640b7d5f0050e725216eab57a85d8 Mon Sep 17 00:00:00 2001 From: Nikita Zhandarovich Date: Mon, 8 Apr 2024 10:16:33 -0700 Subject: comedi: vmk80xx: fix incomplete endpoint checking While vmk80xx does have endpoint checking implemented, some things can fall through the cracks. Depending on the hardware model, URBs can have either bulk or interrupt type, and current version of vmk80xx_find_usb_endpoints() function does not take that fully into account. While this warning does not seem to be too harmful, at the very least it will crash systems with 'panic_on_warn' set on them. Fix the issue found by Syzkaller [1] by somewhat simplifying the endpoint checking process with usb_find_common_endpoints() and ensuring that only expected endpoint types are present. This patch has not been tested on real hardware. [1] Syzkaller report: usb 1-1: BOGUS urb xfer, pipe 1 != type 3 WARNING: CPU: 0 PID: 781 at drivers/usb/core/urb.c:504 usb_submit_urb+0xc4e/0x18c0 drivers/usb/core/urb.c:503 ... Call Trace: usb_start_wait_urb+0x113/0x520 drivers/usb/core/message.c:59 vmk80xx_reset_device drivers/comedi/drivers/vmk80xx.c:227 [inline] vmk80xx_auto_attach+0xa1c/0x1a40 drivers/comedi/drivers/vmk80xx.c:818 comedi_auto_config+0x238/0x380 drivers/comedi/drivers.c:1067 usb_probe_interface+0x5cd/0xb00 drivers/usb/core/driver.c:399 ... Similar issue also found by Syzkaller: Link: https://syzkaller.appspot.com/bug?extid=5205eb2f17de3e01946e Reported-and-tested-by: syzbot+5f29dc6a889fc42bd896@syzkaller.appspotmail.com Cc: stable Fixes: 49253d542cc0 ("staging: comedi: vmk80xx: factor out usb endpoint detection") Reviewed-by: Ian Abbott Signed-off-by: Nikita Zhandarovich Link: https://lore.kernel.org/r/20240408171633.31649-1-n.zhandarovich@fintech.ru Signed-off-by: Greg Kroah-Hartman --- drivers/comedi/drivers/vmk80xx.c | 35 ++++++++++++----------------------- 1 file changed, 12 insertions(+), 23 deletions(-) diff --git a/drivers/comedi/drivers/vmk80xx.c b/drivers/comedi/drivers/vmk80xx.c index 4536ed43f65b..84dce5184a77 100644 --- a/drivers/comedi/drivers/vmk80xx.c +++ b/drivers/comedi/drivers/vmk80xx.c @@ -641,33 +641,22 @@ static int vmk80xx_find_usb_endpoints(struct comedi_device *dev) struct vmk80xx_private *devpriv = dev->private; struct usb_interface *intf = comedi_to_usb_interface(dev); struct usb_host_interface *iface_desc = intf->cur_altsetting; - struct usb_endpoint_descriptor *ep_desc; - int i; - - if (iface_desc->desc.bNumEndpoints != 2) - return -ENODEV; - - for (i = 0; i < iface_desc->desc.bNumEndpoints; i++) { - ep_desc = &iface_desc->endpoint[i].desc; - - if (usb_endpoint_is_int_in(ep_desc) || - usb_endpoint_is_bulk_in(ep_desc)) { - if (!devpriv->ep_rx) - devpriv->ep_rx = ep_desc; - continue; - } + struct usb_endpoint_descriptor *ep_rx_desc, *ep_tx_desc; + int ret; - if (usb_endpoint_is_int_out(ep_desc) || - usb_endpoint_is_bulk_out(ep_desc)) { - if (!devpriv->ep_tx) - devpriv->ep_tx = ep_desc; - continue; - } - } + if (devpriv->model == VMK8061_MODEL) + ret = usb_find_common_endpoints(iface_desc, &ep_rx_desc, + &ep_tx_desc, NULL, NULL); + else + ret = usb_find_common_endpoints(iface_desc, NULL, NULL, + &ep_rx_desc, &ep_tx_desc); - if (!devpriv->ep_rx || !devpriv->ep_tx) + if (ret) return -ENODEV; + devpriv->ep_rx = ep_rx_desc; + devpriv->ep_tx = ep_tx_desc; + if (!usb_endpoint_maxp(devpriv->ep_rx) || !usb_endpoint_maxp(devpriv->ep_tx)) return -EINVAL; -- cgit v1.2.3 From a90bca2228c0646fc29a72689d308e5fe03e6d78 Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Wed, 13 Mar 2024 17:43:41 -0400 Subject: fs: sysfs: Fix reference leak in sysfs_break_active_protection() The sysfs_break_active_protection() routine has an obvious reference leak in its error path. If the call to kernfs_find_and_get() fails then kn will be NULL, so the companion sysfs_unbreak_active_protection() routine won't get called (and would only cause an access violation by trying to dereference kn->parent if it was called). As a result, the reference to kobj acquired at the start of the function will never be released. Fix the leak by adding an explicit kobject_put() call when kn is NULL. Signed-off-by: Alan Stern Fixes: 2afc9166f79b ("scsi: sysfs: Introduce sysfs_{un,}break_active_protection()") Cc: Bart Van Assche Cc: stable@vger.kernel.org Reviewed-by: Bart Van Assche Acked-by: Tejun Heo Link: https://lore.kernel.org/r/8a4d3f0f-c5e3-4b70-a188-0ca433f9e6f9@rowland.harvard.edu Signed-off-by: Greg Kroah-Hartman --- fs/sysfs/file.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/fs/sysfs/file.c b/fs/sysfs/file.c index 6b7652fb8050..7cd64021d453 100644 --- a/fs/sysfs/file.c +++ b/fs/sysfs/file.c @@ -463,6 +463,8 @@ struct kernfs_node *sysfs_break_active_protection(struct kobject *kobj, kn = kernfs_find_and_get(kobj->sd, attr->name); if (kn) kernfs_break_active_protection(kn); + else + kobject_put(kobj); return kn; } EXPORT_SYMBOL_GPL(sysfs_break_active_protection); -- cgit v1.2.3 From aaef73821a3b0194a01bd23ca77774f704a04d40 Mon Sep 17 00:00:00 2001 From: Carlos Llamas Date: Sat, 30 Mar 2024 19:01:14 +0000 Subject: binder: check offset alignment in binder_get_object() Commit 6d98eb95b450 ("binder: avoid potential data leakage when copying txn") introduced changes to how binder objects are copied. In doing so, it unintentionally removed an offset alignment check done through calls to binder_alloc_copy_from_buffer() -> check_buffer(). These calls were replaced in binder_get_object() with copy_from_user(), so now an explicit offset alignment check is needed here. This avoids later complications when unwinding the objects gets harder. It is worth noting this check existed prior to commit 7a67a39320df ("binder: add function to copy binder object from buffer"), likely removed due to redundancy at the time. Fixes: 6d98eb95b450 ("binder: avoid potential data leakage when copying txn") Cc: stable@vger.kernel.org Signed-off-by: Carlos Llamas Acked-by: Todd Kjos Link: https://lore.kernel.org/r/20240330190115.1877819-1-cmllamas@google.com Signed-off-by: Greg Kroah-Hartman --- drivers/android/binder.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/android/binder.c b/drivers/android/binder.c index bad28cf42010..dd6923d37931 100644 --- a/drivers/android/binder.c +++ b/drivers/android/binder.c @@ -1708,8 +1708,10 @@ static size_t binder_get_object(struct binder_proc *proc, size_t object_size = 0; read_size = min_t(size_t, sizeof(*object), buffer->data_size - offset); - if (offset > buffer->data_size || read_size < sizeof(*hdr)) + if (offset > buffer->data_size || read_size < sizeof(*hdr) || + !IS_ALIGNED(offset, sizeof(u32))) return 0; + if (u) { if (copy_from_user(object, u + offset, read_size)) return 0; -- cgit v1.2.3 From f488138b526715c6d2568d7329c4477911be4210 Mon Sep 17 00:00:00 2001 From: Vasily Gorbik Date: Thu, 11 Apr 2024 11:45:57 +0200 Subject: NFSD: fix endianness issue in nfsd4_encode_fattr4 The nfs4 mount fails with EIO on 64-bit big endian architectures since v6.7. The issue arises from employing a union in the nfsd4_encode_fattr4() function to overlay a 32-bit array with a 64-bit values based bitmap, which does not function as intended. Address the endianness issue by utilizing bitmap_from_arr32() to copy 32-bit attribute masks into a bitmap in an endianness-agnostic manner. Cc: stable@vger.kernel.org Fixes: fce7913b13d0 ("NFSD: Use a bitmask loop to encode FATTR4 results") Link: https://bugs.launchpad.net/ubuntu/+source/nfs-utils/+bug/2060217 Signed-off-by: Vasily Gorbik Reviewed-by: Jeff Layton Signed-off-by: Chuck Lever --- fs/nfsd/nfs4xdr.c | 47 +++++++++++++++++++++++------------------------ 1 file changed, 23 insertions(+), 24 deletions(-) diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c index fac938f563ad..1955481832e0 100644 --- a/fs/nfsd/nfs4xdr.c +++ b/fs/nfsd/nfs4xdr.c @@ -3490,11 +3490,13 @@ nfsd4_encode_fattr4(struct svc_rqst *rqstp, struct xdr_stream *xdr, struct dentry *dentry, const u32 *bmval, int ignore_crossmnt) { + DECLARE_BITMAP(attr_bitmap, ARRAY_SIZE(nfsd4_enc_fattr4_encode_ops)); struct nfsd4_fattr_args args; struct svc_fh *tempfh = NULL; int starting_len = xdr->buf->len; __be32 *attrlen_p, status; int attrlen_offset; + u32 attrmask[3]; int err; struct nfsd4_compoundres *resp = rqstp->rq_resp; u32 minorversion = resp->cstate.minorversion; @@ -3502,10 +3504,6 @@ nfsd4_encode_fattr4(struct svc_rqst *rqstp, struct xdr_stream *xdr, .mnt = exp->ex_path.mnt, .dentry = dentry, }; - union { - u32 attrmask[3]; - unsigned long mask[2]; - } u; unsigned long bit; bool file_modified = false; u64 size = 0; @@ -3521,20 +3519,19 @@ nfsd4_encode_fattr4(struct svc_rqst *rqstp, struct xdr_stream *xdr, /* * Make a local copy of the attribute bitmap that can be modified. */ - memset(&u, 0, sizeof(u)); - u.attrmask[0] = bmval[0]; - u.attrmask[1] = bmval[1]; - u.attrmask[2] = bmval[2]; + attrmask[0] = bmval[0]; + attrmask[1] = bmval[1]; + attrmask[2] = bmval[2]; args.rdattr_err = 0; if (exp->ex_fslocs.migrated) { - status = fattr_handle_absent_fs(&u.attrmask[0], &u.attrmask[1], - &u.attrmask[2], &args.rdattr_err); + status = fattr_handle_absent_fs(&attrmask[0], &attrmask[1], + &attrmask[2], &args.rdattr_err); if (status) goto out; } args.size = 0; - if (u.attrmask[0] & (FATTR4_WORD0_CHANGE | FATTR4_WORD0_SIZE)) { + if (attrmask[0] & (FATTR4_WORD0_CHANGE | FATTR4_WORD0_SIZE)) { status = nfsd4_deleg_getattr_conflict(rqstp, d_inode(dentry), &file_modified, &size); if (status) @@ -3553,16 +3550,16 @@ nfsd4_encode_fattr4(struct svc_rqst *rqstp, struct xdr_stream *xdr, if (!(args.stat.result_mask & STATX_BTIME)) /* underlying FS does not offer btime so we can't share it */ - u.attrmask[1] &= ~FATTR4_WORD1_TIME_CREATE; - if ((u.attrmask[0] & (FATTR4_WORD0_FILES_AVAIL | FATTR4_WORD0_FILES_FREE | + attrmask[1] &= ~FATTR4_WORD1_TIME_CREATE; + if ((attrmask[0] & (FATTR4_WORD0_FILES_AVAIL | FATTR4_WORD0_FILES_FREE | FATTR4_WORD0_FILES_TOTAL | FATTR4_WORD0_MAXNAME)) || - (u.attrmask[1] & (FATTR4_WORD1_SPACE_AVAIL | FATTR4_WORD1_SPACE_FREE | + (attrmask[1] & (FATTR4_WORD1_SPACE_AVAIL | FATTR4_WORD1_SPACE_FREE | FATTR4_WORD1_SPACE_TOTAL))) { err = vfs_statfs(&path, &args.statfs); if (err) goto out_nfserr; } - if ((u.attrmask[0] & (FATTR4_WORD0_FILEHANDLE | FATTR4_WORD0_FSID)) && + if ((attrmask[0] & (FATTR4_WORD0_FILEHANDLE | FATTR4_WORD0_FSID)) && !fhp) { tempfh = kmalloc(sizeof(struct svc_fh), GFP_KERNEL); status = nfserr_jukebox; @@ -3577,10 +3574,10 @@ nfsd4_encode_fattr4(struct svc_rqst *rqstp, struct xdr_stream *xdr, args.fhp = fhp; args.acl = NULL; - if (u.attrmask[0] & FATTR4_WORD0_ACL) { + if (attrmask[0] & FATTR4_WORD0_ACL) { err = nfsd4_get_nfs4_acl(rqstp, dentry, &args.acl); if (err == -EOPNOTSUPP) - u.attrmask[0] &= ~FATTR4_WORD0_ACL; + attrmask[0] &= ~FATTR4_WORD0_ACL; else if (err == -EINVAL) { status = nfserr_attrnotsupp; goto out; @@ -3592,17 +3589,17 @@ nfsd4_encode_fattr4(struct svc_rqst *rqstp, struct xdr_stream *xdr, #ifdef CONFIG_NFSD_V4_SECURITY_LABEL args.context = NULL; - if ((u.attrmask[2] & FATTR4_WORD2_SECURITY_LABEL) || - u.attrmask[0] & FATTR4_WORD0_SUPPORTED_ATTRS) { + if ((attrmask[2] & FATTR4_WORD2_SECURITY_LABEL) || + attrmask[0] & FATTR4_WORD0_SUPPORTED_ATTRS) { if (exp->ex_flags & NFSEXP_SECURITY_LABEL) err = security_inode_getsecctx(d_inode(dentry), &args.context, &args.contextlen); else err = -EOPNOTSUPP; args.contextsupport = (err == 0); - if (u.attrmask[2] & FATTR4_WORD2_SECURITY_LABEL) { + if (attrmask[2] & FATTR4_WORD2_SECURITY_LABEL) { if (err == -EOPNOTSUPP) - u.attrmask[2] &= ~FATTR4_WORD2_SECURITY_LABEL; + attrmask[2] &= ~FATTR4_WORD2_SECURITY_LABEL; else if (err) goto out_nfserr; } @@ -3610,8 +3607,8 @@ nfsd4_encode_fattr4(struct svc_rqst *rqstp, struct xdr_stream *xdr, #endif /* CONFIG_NFSD_V4_SECURITY_LABEL */ /* attrmask */ - status = nfsd4_encode_bitmap4(xdr, u.attrmask[0], - u.attrmask[1], u.attrmask[2]); + status = nfsd4_encode_bitmap4(xdr, attrmask[0], attrmask[1], + attrmask[2]); if (status) goto out; @@ -3620,7 +3617,9 @@ nfsd4_encode_fattr4(struct svc_rqst *rqstp, struct xdr_stream *xdr, attrlen_p = xdr_reserve_space(xdr, XDR_UNIT); if (!attrlen_p) goto out_resource; - for_each_set_bit(bit, (const unsigned long *)&u.mask, + bitmap_from_arr32(attr_bitmap, attrmask, + ARRAY_SIZE(nfsd4_enc_fattr4_encode_ops)); + for_each_set_bit(bit, attr_bitmap, ARRAY_SIZE(nfsd4_enc_fattr4_encode_ops)) { status = nfsd4_enc_fattr4_encode_ops[bit](xdr, &args); if (status != nfs_ok) -- cgit v1.2.3 From 156539fd65019e8ed6b9fbac0583cf519cdbb227 Mon Sep 17 00:00:00 2001 From: Michael Ellerman Date: Fri, 22 Mar 2024 21:38:40 +1100 Subject: Documentation: embargoed-hardware-issues.rst: Add myself for Power Unfortunately Anton has left IBM. Add myself as the contact for Power, until someone else volunteers. Signed-off-by: Michael Ellerman Link: https://lore.kernel.org/r/20240322103840.668746-1-mpe@ellerman.id.au Signed-off-by: Greg Kroah-Hartman --- Documentation/process/embargoed-hardware-issues.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Documentation/process/embargoed-hardware-issues.rst b/Documentation/process/embargoed-hardware-issues.rst index bb2100228cc7..6e9a4597bf2c 100644 --- a/Documentation/process/embargoed-hardware-issues.rst +++ b/Documentation/process/embargoed-hardware-issues.rst @@ -252,7 +252,7 @@ an involved disclosed party. The current ambassadors list: AMD Tom Lendacky Ampere Darren Hart ARM Catalin Marinas - IBM Power Anton Blanchard + IBM Power Michael Ellerman IBM Z Christian Borntraeger Intel Tony Luck Qualcomm Trilok Soni -- cgit v1.2.3 From 50a9b7fc151e67b9e642232d32e8c5a5ac13e64a Mon Sep 17 00:00:00 2001 From: Lucas De Marchi Date: Fri, 5 Apr 2024 13:07:11 -0700 Subject: drm/xe/display: Fix double mutex initialization MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit All of these mutexes are already initialized by the display side since commit 3fef3e6ff86a ("drm/i915: move display mutex inits to display code"), so the xe shouldn´t initialize them. Fixes: 44e694958b95 ("drm/xe/display: Implement display support") Cc: Jani Nikula Cc: Arun R Murthy Reviewed-by: Jani Nikula Link: https://patchwork.freedesktop.org/patch/msgid/20240405200711.2041428-1-lucas.demarchi@intel.com Signed-off-by: Lucas De Marchi (cherry picked from commit 117de185edf2c5767f03575219bf7a43b161ff0d) Signed-off-by: Lucas De Marchi --- drivers/gpu/drm/xe/display/xe_display.c | 5 ----- 1 file changed, 5 deletions(-) diff --git a/drivers/gpu/drm/xe/display/xe_display.c b/drivers/gpu/drm/xe/display/xe_display.c index e4db069f0db3..6ec375c1c4b6 100644 --- a/drivers/gpu/drm/xe/display/xe_display.c +++ b/drivers/gpu/drm/xe/display/xe_display.c @@ -108,11 +108,6 @@ int xe_display_create(struct xe_device *xe) xe->display.hotplug.dp_wq = alloc_ordered_workqueue("xe-dp", 0); drmm_mutex_init(&xe->drm, &xe->sb_lock); - drmm_mutex_init(&xe->drm, &xe->display.backlight.lock); - drmm_mutex_init(&xe->drm, &xe->display.audio.mutex); - drmm_mutex_init(&xe->drm, &xe->display.wm.wm_mutex); - drmm_mutex_init(&xe->drm, &xe->display.pps.mutex); - drmm_mutex_init(&xe->drm, &xe->display.hdcp.hdcp_mutex); xe->enabled_irq_mask = ~0; err = drmm_add_action_or_reset(&xe->drm, display_destroy, NULL); -- cgit v1.2.3 From a8ad8715472bb8f6a2ea8b4072a28151eb9f4f24 Mon Sep 17 00:00:00 2001 From: Karthik Poosa Date: Fri, 5 Apr 2024 18:31:27 +0530 Subject: drm/xe/hwmon: Cast result to output precision on left shift of operand Address potential overflow in result of left shift of a lower precision (u32) operand before assignment to higher precision (u64) variable. v2: - Update commit message. (Himal) Fixes: 4446fcf220ce ("drm/xe/hwmon: Expose power1_max_interval") Signed-off-by: Karthik Poosa Reviewed-by: Anshuman Gupta Cc: Badal Nilawar Link: https://patchwork.freedesktop.org/patch/msgid/20240405130127.1392426-5-karthik.poosa@intel.com Signed-off-by: Lucas De Marchi (cherry picked from commit 883232b47b81108b0252197c747f396ecd51455a) Signed-off-by: Lucas De Marchi --- drivers/gpu/drm/xe/xe_hwmon.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/xe/xe_hwmon.c b/drivers/gpu/drm/xe/xe_hwmon.c index b82233a41606..9ac7fbe201b3 100644 --- a/drivers/gpu/drm/xe/xe_hwmon.c +++ b/drivers/gpu/drm/xe/xe_hwmon.c @@ -290,7 +290,7 @@ xe_hwmon_power1_max_interval_show(struct device *dev, struct device_attribute *a * As y can be < 2, we compute tau4 = (4 | x) << y * and then add 2 when doing the final right shift to account for units */ - tau4 = ((1 << x_w) | x) << y; + tau4 = (u64)((1 << x_w) | x) << y; /* val in hwmon interface units (millisec) */ out = mul_u64_u32_shr(tau4, SF_TIME, hwmon->scl_shift_time + x_w); @@ -330,7 +330,7 @@ xe_hwmon_power1_max_interval_store(struct device *dev, struct device_attribute * r = FIELD_PREP(PKG_MAX_WIN, PKG_MAX_WIN_DEFAULT); x = REG_FIELD_GET(PKG_MAX_WIN_X, r); y = REG_FIELD_GET(PKG_MAX_WIN_Y, r); - tau4 = ((1 << x_w) | x) << y; + tau4 = (u64)((1 << x_w) | x) << y; max_win = mul_u64_u32_shr(tau4, SF_TIME, hwmon->scl_shift_time + x_w); if (val > max_win) -- cgit v1.2.3 From 9cb46b31f3d08ed3fce86349e8c12f96d7c88717 Mon Sep 17 00:00:00 2001 From: Himal Prasad Ghimiray Date: Mon, 1 Apr 2024 23:23:00 +0530 Subject: drm/xe/xe_migrate: Cast to output precision before multiplying operands Addressing potential overflow in result of multiplication of two lower precision (u32) operands before widening it to higher precision (u64). -v2 Fix commit message and description. (Rodrigo) Cc: Rodrigo Vivi Signed-off-by: Himal Prasad Ghimiray Reviewed-by: Rodrigo Vivi Link: https://patchwork.freedesktop.org/patch/msgid/20240401175300.3823653-1-himal.prasad.ghimiray@intel.com Signed-off-by: Rodrigo Vivi (cherry picked from commit 34820967ae7b45411f8f4f737c2d63b0c608e0d7) Signed-off-by: Lucas De Marchi --- drivers/gpu/drm/xe/xe_migrate.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/xe/xe_migrate.c b/drivers/gpu/drm/xe/xe_migrate.c index ee1bb938c493..2ba4fb9511f6 100644 --- a/drivers/gpu/drm/xe/xe_migrate.c +++ b/drivers/gpu/drm/xe/xe_migrate.c @@ -227,7 +227,7 @@ static int xe_migrate_prepare_vm(struct xe_tile *tile, struct xe_migrate *m, if (vm->flags & XE_VM_FLAG_64K && level == 1) flags = XE_PDE_64K; - entry = vm->pt_ops->pde_encode_bo(bo, map_ofs + (level - 1) * + entry = vm->pt_ops->pde_encode_bo(bo, map_ofs + (u64)(level - 1) * XE_PAGE_SIZE, pat_index); xe_map_wr(xe, &bo->vmap, map_ofs + XE_PAGE_SIZE * level, u64, entry | flags); @@ -235,7 +235,7 @@ static int xe_migrate_prepare_vm(struct xe_tile *tile, struct xe_migrate *m, /* Write PDE's that point to our BO. */ for (i = 0; i < num_entries - num_level; i++) { - entry = vm->pt_ops->pde_encode_bo(bo, i * XE_PAGE_SIZE, + entry = vm->pt_ops->pde_encode_bo(bo, (u64)i * XE_PAGE_SIZE, pat_index); xe_map_wr(xe, &bo->vmap, map_ofs + XE_PAGE_SIZE + @@ -291,7 +291,7 @@ static int xe_migrate_prepare_vm(struct xe_tile *tile, struct xe_migrate *m, #define VM_SA_UPDATE_UNIT_SIZE (XE_PAGE_SIZE / NUM_VMUSA_UNIT_PER_PAGE) #define NUM_VMUSA_WRITES_PER_UNIT (VM_SA_UPDATE_UNIT_SIZE / sizeof(u64)) drm_suballoc_manager_init(&m->vm_update_sa, - (map_ofs / XE_PAGE_SIZE - NUM_KERNEL_PDE) * + (size_t)(map_ofs / XE_PAGE_SIZE - NUM_KERNEL_PDE) * NUM_VMUSA_UNIT_PER_PAGE, 0); m->pt_bo = bo; @@ -490,7 +490,7 @@ static void emit_pte(struct xe_migrate *m, struct xe_vm *vm = m->q->vm; u16 pat_index; u32 ptes; - u64 ofs = at_pt * XE_PAGE_SIZE; + u64 ofs = (u64)at_pt * XE_PAGE_SIZE; u64 cur_ofs; /* Indirect access needs compression enabled uncached PAT index */ -- cgit v1.2.3 From f76646c83f028c62853c23dac49204232e903597 Mon Sep 17 00:00:00 2001 From: Ashutosh Dixit Date: Thu, 4 Apr 2024 09:12:56 -0700 Subject: drm/xe: Label RING_CONTEXT_CONTROL as masked RING_CONTEXT_CONTROL is a masked register. v2: Also clean up setting register value (Lucas) Reviewed-by: Matt Roper Reviewed-by: Lucas De Marchi Signed-off-by: Ashutosh Dixit Link: https://patchwork.freedesktop.org/patch/msgid/20240404161256.3852502-1-ashutosh.dixit@intel.com (cherry picked from commit dc30c6e7149baaae4288c742de95212b31f07438) Signed-off-by: Lucas De Marchi --- drivers/gpu/drm/xe/regs/xe_engine_regs.h | 2 +- drivers/gpu/drm/xe/xe_lrc.c | 5 ++--- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/xe/regs/xe_engine_regs.h b/drivers/gpu/drm/xe/regs/xe_engine_regs.h index 0b1266c88a6a..deddc8be48c0 100644 --- a/drivers/gpu/drm/xe/regs/xe_engine_regs.h +++ b/drivers/gpu/drm/xe/regs/xe_engine_regs.h @@ -125,7 +125,7 @@ #define RING_EXECLIST_STATUS_LO(base) XE_REG((base) + 0x234) #define RING_EXECLIST_STATUS_HI(base) XE_REG((base) + 0x234 + 4) -#define RING_CONTEXT_CONTROL(base) XE_REG((base) + 0x244) +#define RING_CONTEXT_CONTROL(base) XE_REG((base) + 0x244, XE_REG_OPTION_MASKED) #define CTX_CTRL_INHIBIT_SYN_CTX_SWITCH REG_BIT(3) #define CTX_CTRL_ENGINE_CTX_RESTORE_INHIBIT REG_BIT(0) diff --git a/drivers/gpu/drm/xe/xe_lrc.c b/drivers/gpu/drm/xe/xe_lrc.c index 1426febe86eb..57066faf575e 100644 --- a/drivers/gpu/drm/xe/xe_lrc.c +++ b/drivers/gpu/drm/xe/xe_lrc.c @@ -525,9 +525,8 @@ static const u8 *reg_offsets(struct xe_device *xe, enum xe_engine_class class) static void set_context_control(u32 *regs, struct xe_hw_engine *hwe) { - regs[CTX_CONTEXT_CONTROL] = _MASKED_BIT_ENABLE(CTX_CTRL_INHIBIT_SYN_CTX_SWITCH) | - _MASKED_BIT_DISABLE(CTX_CTRL_ENGINE_CTX_RESTORE_INHIBIT) | - CTX_CTRL_ENGINE_CTX_RESTORE_INHIBIT; + regs[CTX_CONTEXT_CONTROL] = _MASKED_BIT_ENABLE(CTX_CTRL_INHIBIT_SYN_CTX_SWITCH | + CTX_CTRL_ENGINE_CTX_RESTORE_INHIBIT); /* TODO: Timestamp */ } -- cgit v1.2.3 From ebaed6d4def877d2035786ff318379eb750044c8 Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Fri, 29 Mar 2024 11:29:10 -0700 Subject: peci: linux/peci.h: fix Excess kernel-doc description warning Remove the @controller: line to prevent the kernel-doc warning: include/linux/peci.h:84: warning: Excess struct member 'controller' description in 'peci_device' Signed-off-by: Randy Dunlap Cc: Iwona Winiarska Cc: openbmc@lists.ozlabs.org Reviewed-by: Iwona Winiarska Fixes: 6523d3b2ffa2 ("peci: Add core infrastructure") Cc: Greg Kroah-Hartman Link: https://lore.kernel.org/r/20240329182910.29495-1-rdunlap@infradead.org Signed-off-by: Greg Kroah-Hartman --- include/linux/peci.h | 1 - 1 file changed, 1 deletion(-) diff --git a/include/linux/peci.h b/include/linux/peci.h index 9b3d36aff431..90e241458ef6 100644 --- a/include/linux/peci.h +++ b/include/linux/peci.h @@ -58,7 +58,6 @@ static inline struct peci_controller *to_peci_controller(void *d) /** * struct peci_device - PECI device * @dev: device object to register PECI device to the device model - * @controller: manages the bus segment hosting this PECI device * @info: PECI device characteristics * @info.family: device family * @info.model: device model -- cgit v1.2.3 From fd706c9b1674e2858766bfbf7430534c2b26fbef Mon Sep 17 00:00:00 2001 From: Sean Christopherson Date: Fri, 5 Apr 2024 16:55:54 -0700 Subject: KVM: x86: Snapshot if a vCPU's vendor model is AMD vs. Intel compatible Add kvm_vcpu_arch.is_amd_compatible to cache if a vCPU's vendor model is compatible with AMD, i.e. if the vCPU vendor is AMD or Hygon, along with helpers to check if a vCPU is compatible AMD vs. Intel. To handle Intel vs. AMD behavior related to masking the LVTPC entry, KVM will need to check for vendor compatibility on every PMI injection, i.e. querying for AMD will soon be a moderately hot path. Note! This subtly (or maybe not-so-subtly) makes "Intel compatible" KVM's default behavior, both if userspace omits (or never sets) CPUID 0x0 and if userspace sets a completely unknown vendor. One could argue that KVM should treat such vCPUs as not being compatible with Intel *or* AMD, but that would add useless complexity to KVM. KVM needs to do *something* in the face of vendor specific behavior, and so unless KVM conjured up a magic third option, choosing to treat unknown vendors as neither Intel nor AMD means that checks on AMD compatibility would yield Intel behavior, and checks for Intel compatibility would yield AMD behavior. And that's far worse as it would effectively yield random behavior depending on whether KVM checked for AMD vs. Intel vs. !AMD vs. !Intel. And practically speaking, all x86 CPUs follow either Intel or AMD architecture, i.e. "supporting" an unknown third architecture adds no value. Deliberately don't convert any of the existing guest_cpuid_is_intel() checks, as the Intel side of things is messier due to some flows explicitly checking for exactly vendor==Intel, versus some flows assuming anything that isn't "AMD compatible" gets Intel behavior. The Intel code will be cleaned up in the future. Cc: stable@vger.kernel.org Signed-off-by: Sean Christopherson Message-ID: <20240405235603.1173076-2-seanjc@google.com> Signed-off-by: Paolo Bonzini --- arch/x86/include/asm/kvm_host.h | 1 + arch/x86/kvm/cpuid.c | 1 + arch/x86/kvm/cpuid.h | 10 ++++++++++ arch/x86/kvm/mmu/mmu.c | 2 +- arch/x86/kvm/x86.c | 2 +- 5 files changed, 14 insertions(+), 2 deletions(-) diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h index 16e07a2eee19..6efd1497b026 100644 --- a/arch/x86/include/asm/kvm_host.h +++ b/arch/x86/include/asm/kvm_host.h @@ -855,6 +855,7 @@ struct kvm_vcpu_arch { int cpuid_nent; struct kvm_cpuid_entry2 *cpuid_entries; struct kvm_hypervisor_cpuid kvm_cpuid; + bool is_amd_compatible; /* * FIXME: Drop this macro and use KVM_NR_GOVERNED_FEATURES directly diff --git a/arch/x86/kvm/cpuid.c b/arch/x86/kvm/cpuid.c index bfc0bfcb2bc6..77352a4abd87 100644 --- a/arch/x86/kvm/cpuid.c +++ b/arch/x86/kvm/cpuid.c @@ -376,6 +376,7 @@ static void kvm_vcpu_after_set_cpuid(struct kvm_vcpu *vcpu) kvm_update_pv_runtime(vcpu); + vcpu->arch.is_amd_compatible = guest_cpuid_is_amd_or_hygon(vcpu); vcpu->arch.maxphyaddr = cpuid_query_maxphyaddr(vcpu); vcpu->arch.reserved_gpa_bits = kvm_vcpu_reserved_gpa_bits_raw(vcpu); diff --git a/arch/x86/kvm/cpuid.h b/arch/x86/kvm/cpuid.h index 856e3037e74f..23dbb9eb277c 100644 --- a/arch/x86/kvm/cpuid.h +++ b/arch/x86/kvm/cpuid.h @@ -120,6 +120,16 @@ static inline bool guest_cpuid_is_intel(struct kvm_vcpu *vcpu) return best && is_guest_vendor_intel(best->ebx, best->ecx, best->edx); } +static inline bool guest_cpuid_is_amd_compatible(struct kvm_vcpu *vcpu) +{ + return vcpu->arch.is_amd_compatible; +} + +static inline bool guest_cpuid_is_intel_compatible(struct kvm_vcpu *vcpu) +{ + return !guest_cpuid_is_amd_compatible(vcpu); +} + static inline int guest_cpuid_family(struct kvm_vcpu *vcpu) { struct kvm_cpuid_entry2 *best; diff --git a/arch/x86/kvm/mmu/mmu.c b/arch/x86/kvm/mmu/mmu.c index 992e651540e8..bf4de6d7e39c 100644 --- a/arch/x86/kvm/mmu/mmu.c +++ b/arch/x86/kvm/mmu/mmu.c @@ -4935,7 +4935,7 @@ static void reset_guest_rsvds_bits_mask(struct kvm_vcpu *vcpu, context->cpu_role.base.level, is_efer_nx(context), guest_can_use(vcpu, X86_FEATURE_GBPAGES), is_cr4_pse(context), - guest_cpuid_is_amd_or_hygon(vcpu)); + guest_cpuid_is_amd_compatible(vcpu)); } static void __reset_rsvds_bits_mask_ept(struct rsvd_bits_validate *rsvd_check, diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c index 47d9f03b7778..ebcc12d1e1de 100644 --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c @@ -3470,7 +3470,7 @@ static bool is_mci_status_msr(u32 msr) static bool can_set_mci_status(struct kvm_vcpu *vcpu) { /* McStatusWrEn enabled? */ - if (guest_cpuid_is_amd_or_hygon(vcpu)) + if (guest_cpuid_is_amd_compatible(vcpu)) return !!(vcpu->arch.msr_hwcr & BIT_ULL(18)); return false; -- cgit v1.2.3 From 49ff3b4aec51e3abfc9369997cc603319b02af9a Mon Sep 17 00:00:00 2001 From: Sandipan Das Date: Fri, 5 Apr 2024 16:55:55 -0700 Subject: KVM: x86/pmu: Do not mask LVTPC when handling a PMI on AMD platforms On AMD and Hygon platforms, the local APIC does not automatically set the mask bit of the LVTPC register when handling a PMI and there is no need to clear it in the kernel's PMI handler. For guests, the mask bit is currently set by kvm_apic_local_deliver() and unless it is cleared by the guest kernel's PMI handler, PMIs stop arriving and break use-cases like sampling with perf record. This does not affect non-PerfMonV2 guests because PMIs are handled in the guest kernel by x86_pmu_handle_irq() which always clears the LVTPC mask bit irrespective of the vendor. Before: $ perf record -e cycles:u true [ perf record: Woken up 1 times to write data ] [ perf record: Captured and wrote 0.001 MB perf.data (1 samples) ] After: $ perf record -e cycles:u true [ perf record: Woken up 1 times to write data ] [ perf record: Captured and wrote 0.002 MB perf.data (19 samples) ] Fixes: a16eb25b09c0 ("KVM: x86: Mask LVTPC when handling a PMI") Cc: stable@vger.kernel.org Signed-off-by: Sandipan Das Reviewed-by: Jim Mattson [sean: use is_intel_compatible instead of !is_amd_or_hygon()] Signed-off-by: Sean Christopherson Message-ID: <20240405235603.1173076-3-seanjc@google.com> Signed-off-by: Paolo Bonzini --- arch/x86/kvm/lapic.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/arch/x86/kvm/lapic.c b/arch/x86/kvm/lapic.c index cf37586f0466..ebf41023be38 100644 --- a/arch/x86/kvm/lapic.c +++ b/arch/x86/kvm/lapic.c @@ -2776,7 +2776,8 @@ int kvm_apic_local_deliver(struct kvm_lapic *apic, int lvt_type) trig_mode = reg & APIC_LVT_LEVEL_TRIGGER; r = __apic_accept_irq(apic, mode, vector, 1, trig_mode, NULL); - if (r && lvt_type == APIC_LVTPC) + if (r && lvt_type == APIC_LVTPC && + guest_cpuid_is_intel_compatible(apic->vcpu)) kvm_lapic_set_reg(apic, APIC_LVTPC, reg | APIC_LVT_MASKED); return r; } -- cgit v1.2.3 From 2b8dbf69ec60faf6c7db49e57d7f316409ccec92 Mon Sep 17 00:00:00 2001 From: Namhyung Kim Date: Fri, 5 Apr 2024 14:17:57 -0700 Subject: perf annotate: Make sure to call symbol__annotate2() in TUI The symbol__annotate2() initializes some data structures needed by TUI. It has a logic to prevent calling it multiple times by checking if it has the annotated source. But data type profiling uses a different code (symbol__annotate) to allocate the annotated lines in advance. So TUI missed to call symbol__annotate2() when it shows the annotation browser. Make symbol__annotate() reentrant and handle that situation properly. This fixes a crash in the annotation browser started by perf report in TUI like below. $ perf report -s type,sym --tui # and press 'a' key and then move down Fixes: 81e57deec325 ("perf report: Support data type profiling") Reviewed-by: Ian Rogers Signed-off-by: Namhyung Kim Link: https://lore.kernel.org/r/20240405211800.1412920-2-namhyung@kernel.org --- tools/perf/ui/browsers/annotate.c | 2 +- tools/perf/util/annotate.c | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/tools/perf/ui/browsers/annotate.c b/tools/perf/ui/browsers/annotate.c index ec5e21932876..4790c735599b 100644 --- a/tools/perf/ui/browsers/annotate.c +++ b/tools/perf/ui/browsers/annotate.c @@ -970,7 +970,7 @@ int symbol__tui_annotate(struct map_symbol *ms, struct evsel *evsel, if (dso->annotate_warned) return -1; - if (not_annotated) { + if (not_annotated || !sym->annotate2) { err = symbol__annotate2(ms, evsel, &browser.arch); if (err) { char msg[BUFSIZ]; diff --git a/tools/perf/util/annotate.c b/tools/perf/util/annotate.c index ac002d907d81..50ca92255ff6 100644 --- a/tools/perf/util/annotate.c +++ b/tools/perf/util/annotate.c @@ -2461,6 +2461,9 @@ int symbol__annotate(struct map_symbol *ms, struct evsel *evsel, if (parch) *parch = arch; + if (!list_empty(¬es->src->source)) + return 0; + args.arch = arch; args.ms = *ms; if (annotate_opts.full_addr) -- cgit v1.2.3 From b372e96bd0a32729d55d27f613c8bc80708a82e1 Mon Sep 17 00:00:00 2001 From: NeilBrown Date: Mon, 25 Mar 2024 09:21:20 +1100 Subject: ceph: redirty page before returning AOP_WRITEPAGE_ACTIVATE The page has been marked clean before writepage is called. If we don't redirty it before postponing the write, it might never get written. Cc: stable@vger.kernel.org Fixes: 503d4fa6ee28 ("ceph: remove reliance on bdi congestion") Signed-off-by: NeilBrown Reviewed-by: Jeff Layton Reviewed-by: Xiubo Li Signed-off-by: Ilya Dryomov --- fs/ceph/addr.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/fs/ceph/addr.c b/fs/ceph/addr.c index 1340d77124ae..ee9caf7916fb 100644 --- a/fs/ceph/addr.c +++ b/fs/ceph/addr.c @@ -795,8 +795,10 @@ static int ceph_writepage(struct page *page, struct writeback_control *wbc) ihold(inode); if (wbc->sync_mode == WB_SYNC_NONE && - ceph_inode_to_fs_client(inode)->write_congested) + ceph_inode_to_fs_client(inode)->write_congested) { + redirty_page_for_writepage(wbc, page); return AOP_WRITEPAGE_ACTIVATE; + } wait_on_page_fscache(page); -- cgit v1.2.3 From f3408580bac8ce5cd76e7391e529c0a22e7c7eb2 Mon Sep 17 00:00:00 2001 From: Namhyung Kim Date: Tue, 9 Apr 2024 15:55:42 -0700 Subject: perf lock contention: Add a missing NULL check I got a report for a failure in BPF verifier on a recent kernel with perf lock contention command. It checks task->sighand->siglock without checking if sighand is NULL or not. Let's add one. ; if (&curr->sighand->siglock == (void *)lock) 265: (79) r1 = *(u64 *)(r0 +2624) ; frame1: R0_w=trusted_ptr_task_struct(off=0,imm=0) ; R1_w=rcu_ptr_or_null_sighand_struct(off=0,imm=0) 266: (b7) r2 = 0 ; frame1: R2_w=0 267: (0f) r1 += r2 R1 pointer arithmetic on rcu_ptr_or_null_ prohibited, null-check it first processed 164 insns (limit 1000000) max_states_per_insn 1 total_states 15 peak_states 15 mark_read 5 -- END PROG LOAD LOG -- libbpf: prog 'contention_end': failed to load: -13 libbpf: failed to load object 'lock_contention_bpf' libbpf: failed to load BPF skeleton 'lock_contention_bpf': -13 Failed to load lock-contention BPF skeleton lock contention BPF setup failed lock contention did not detect any lock contention Fixes: 1811e82767dcc ("perf lock contention: Track and show siglock with address") Reviewed-by: Ian Rogers Acked-by: Arnaldo Carvalho de Melo Cc: Song Liu Cc: bpf@vger.kernel.org Signed-off-by: Namhyung Kim Link: https://lore.kernel.org/r/20240409225542.1870999-1-namhyung@kernel.org --- tools/perf/util/bpf_skel/lock_contention.bpf.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/tools/perf/util/bpf_skel/lock_contention.bpf.c b/tools/perf/util/bpf_skel/lock_contention.bpf.c index fb54bd38e7d0..d931a898c434 100644 --- a/tools/perf/util/bpf_skel/lock_contention.bpf.c +++ b/tools/perf/util/bpf_skel/lock_contention.bpf.c @@ -284,6 +284,7 @@ static inline __u32 check_lock_type(__u64 lock, __u32 flags) struct task_struct *curr; struct mm_struct___old *mm_old; struct mm_struct___new *mm_new; + struct sighand_struct *sighand; switch (flags) { case LCB_F_READ: /* rwsem */ @@ -305,7 +306,9 @@ static inline __u32 check_lock_type(__u64 lock, __u32 flags) break; case LCB_F_SPIN: /* spinlock */ curr = bpf_get_current_task_btf(); - if (&curr->sighand->siglock == (void *)lock) + sighand = curr->sighand; + + if (sighand && &sighand->siglock == (void *)lock) return LCD_F_SIGHAND_LOCK; break; default: -- cgit v1.2.3 From 3ef842a77e7cdf757fe3f1d2999aa2cc88eb53ba Mon Sep 17 00:00:00 2001 From: Namhyung Kim Date: Mon, 8 Apr 2024 11:55:12 -0700 Subject: tools/include: Sync uapi/drm/i915_drm.h with the kernel sources To pick up changes from: b112364867499 ("drm/i915: Add GuC submission interface version query") 5cf0fbf763741 ("drm/i915: Add some boring kerneldoc") This should be used to beautify DRM syscall arguments and it addresses these tools/perf build warnings: Warning: Kernel ABI header differences: diff -u tools/include/uapi/drm/i915_drm.h include/uapi/drm/i915_drm.h Cc: Maarten Lankhorst Cc: Maxime Ripard Cc: Thomas Zimmermann Cc: David Airlie Cc: Daniel Vetter Cc: dri-devel@lists.freedesktop.org Signed-off-by: Namhyung Kim Link: https://lore.kernel.org/r/20240408185520.1550865-2-namhyung@kernel.org --- tools/include/uapi/drm/i915_drm.h | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/tools/include/uapi/drm/i915_drm.h b/tools/include/uapi/drm/i915_drm.h index fd4f9574d177..2ee338860b7e 100644 --- a/tools/include/uapi/drm/i915_drm.h +++ b/tools/include/uapi/drm/i915_drm.h @@ -3013,6 +3013,7 @@ struct drm_i915_query_item { * - %DRM_I915_QUERY_MEMORY_REGIONS (see struct drm_i915_query_memory_regions) * - %DRM_I915_QUERY_HWCONFIG_BLOB (see `GuC HWCONFIG blob uAPI`) * - %DRM_I915_QUERY_GEOMETRY_SUBSLICES (see struct drm_i915_query_topology_info) + * - %DRM_I915_QUERY_GUC_SUBMISSION_VERSION (see struct drm_i915_query_guc_submission_version) */ __u64 query_id; #define DRM_I915_QUERY_TOPOLOGY_INFO 1 @@ -3021,6 +3022,7 @@ struct drm_i915_query_item { #define DRM_I915_QUERY_MEMORY_REGIONS 4 #define DRM_I915_QUERY_HWCONFIG_BLOB 5 #define DRM_I915_QUERY_GEOMETRY_SUBSLICES 6 +#define DRM_I915_QUERY_GUC_SUBMISSION_VERSION 7 /* Must be kept compact -- no holes and well documented */ /** @@ -3566,6 +3568,20 @@ struct drm_i915_query_memory_regions { struct drm_i915_memory_region_info regions[]; }; +/** + * struct drm_i915_query_guc_submission_version - query GuC submission interface version + */ +struct drm_i915_query_guc_submission_version { + /** @branch: Firmware branch version. */ + __u32 branch; + /** @major: Firmware major version. */ + __u32 major; + /** @minor: Firmware minor version. */ + __u32 minor; + /** @patch: Firmware patch version. */ + __u32 patch; +}; + /** * DOC: GuC HWCONFIG blob uAPI * -- cgit v1.2.3 From 4cfa8a873d3e3a87894f8de056ee69a857b5adcd Mon Sep 17 00:00:00 2001 From: Namhyung Kim Date: Mon, 8 Apr 2024 11:55:13 -0700 Subject: tools/include: Sync uapi/linux/fs.h with the kernel sources To pick up the changes from: 41bcbe59c3b3f ("fs: FS_IOC_GETUUID") ae8c511757304 ("fs: add FS_IOC_GETFSSYSFSPATH") 73fa7547c70b3 ("vfs: add RWF_NOAPPEND flag for pwritev2") This should be used to beautify fs syscall arguments and it addresses these tools/perf build warnings: Warning: Kernel ABI header differences: diff -u tools/include/uapi/linux/fs.h include/uapi/linux/fs.h Reviewed-by: Jan Kara Reviewed-by: Christian Brauner Cc: Alexander Viro Cc: linux-fsdevel@vger.kernel.org Signed-off-by: Namhyung Kim Link: https://lore.kernel.org/r/20240408185520.1550865-3-namhyung@kernel.org --- tools/include/uapi/linux/fs.h | 30 +++++++++++++++++++++++++++++- 1 file changed, 29 insertions(+), 1 deletion(-) diff --git a/tools/include/uapi/linux/fs.h b/tools/include/uapi/linux/fs.h index 48ad69f7722e..45e4e64fd664 100644 --- a/tools/include/uapi/linux/fs.h +++ b/tools/include/uapi/linux/fs.h @@ -64,6 +64,24 @@ struct fstrim_range { __u64 minlen; }; +/* + * We include a length field because some filesystems (vfat) have an identifier + * that we do want to expose as a UUID, but doesn't have the standard length. + * + * We use a fixed size buffer beacuse this interface will, by fiat, never + * support "UUIDs" longer than 16 bytes; we don't want to force all downstream + * users to have to deal with that. + */ +struct fsuuid2 { + __u8 len; + __u8 uuid[16]; +}; + +struct fs_sysfs_path { + __u8 len; + __u8 name[128]; +}; + /* extent-same (dedupe) ioctls; these MUST match the btrfs ioctl definitions */ #define FILE_DEDUPE_RANGE_SAME 0 #define FILE_DEDUPE_RANGE_DIFFERS 1 @@ -215,6 +233,13 @@ struct fsxattr { #define FS_IOC_FSSETXATTR _IOW('X', 32, struct fsxattr) #define FS_IOC_GETFSLABEL _IOR(0x94, 49, char[FSLABEL_MAX]) #define FS_IOC_SETFSLABEL _IOW(0x94, 50, char[FSLABEL_MAX]) +/* Returns the external filesystem UUID, the same one blkid returns */ +#define FS_IOC_GETFSUUID _IOR(0x15, 0, struct fsuuid2) +/* + * Returns the path component under /sys/fs/ that refers to this filesystem; + * also /sys/kernel/debug/ for filesystems with debugfs exports + */ +#define FS_IOC_GETFSSYSFSPATH _IOR(0x15, 1, struct fs_sysfs_path) /* * Inode flags (FS_IOC_GETFLAGS / FS_IOC_SETFLAGS) @@ -301,9 +326,12 @@ typedef int __bitwise __kernel_rwf_t; /* per-IO O_APPEND */ #define RWF_APPEND ((__force __kernel_rwf_t)0x00000010) +/* per-IO negation of O_APPEND */ +#define RWF_NOAPPEND ((__force __kernel_rwf_t)0x00000020) + /* mask of flags supported by the kernel */ #define RWF_SUPPORTED (RWF_HIPRI | RWF_DSYNC | RWF_SYNC | RWF_NOWAIT |\ - RWF_APPEND) + RWF_APPEND | RWF_NOAPPEND) /* Pagemap ioctl */ #define PAGEMAP_SCAN _IOWR('f', 16, struct pm_scan_arg) -- cgit v1.2.3 From bee3b820c66a6aae0e16d0ac47f9744446f33bff Mon Sep 17 00:00:00 2001 From: Namhyung Kim Date: Mon, 8 Apr 2024 11:55:14 -0700 Subject: tools/include: Sync uapi/linux/kvm.h and asm/kvm.h with the kernel sources To pick up the changes from: 6bda055d6258 ("KVM: define __KVM_HAVE_GUEST_DEBUG unconditionally") 5d9cb71642db ("KVM: arm64: move ARM-specific defines to uapi/asm/kvm.h") 71cd774ad2f9 ("KVM: s390: move s390-specific structs to uapi/asm/kvm.h") d750951c9ed7 ("KVM: powerpc: move powerpc-specific structs to uapi/asm/kvm.h") bcac0477277e ("KVM: x86: move x86-specific structs to uapi/asm/kvm.h") c0a411904e15 ("KVM: remove more traces of device assignment UAPI") f3c80061c0d3 ("KVM: SEV: fix compat ABI for KVM_MEMORY_ENCRYPT_OP") That should be used to beautify the KVM arguments and it addresses these tools/perf build warnings: Warning: Kernel ABI header differences: diff -u tools/include/uapi/linux/kvm.h include/uapi/linux/kvm.h diff -u tools/arch/x86/include/uapi/asm/kvm.h arch/x86/include/uapi/asm/kvm.h diff -u tools/arch/powerpc/include/uapi/asm/kvm.h arch/powerpc/include/uapi/asm/kvm.h diff -u tools/arch/s390/include/uapi/asm/kvm.h arch/s390/include/uapi/asm/kvm.h diff -u tools/arch/arm64/include/uapi/asm/kvm.h arch/arm64/include/uapi/asm/kvm.h Cc: Paolo Bonzini Cc: kvm@vger.kernel.org Signed-off-by: Namhyung Kim Link: https://lore.kernel.org/r/20240408185520.1550865-4-namhyung@kernel.org --- tools/arch/arm64/include/uapi/asm/kvm.h | 15 +- tools/arch/powerpc/include/uapi/asm/kvm.h | 45 +- tools/arch/s390/include/uapi/asm/kvm.h | 315 +++++++++++++- tools/arch/x86/include/uapi/asm/kvm.h | 308 ++++++++++++- tools/include/uapi/linux/kvm.h | 689 +----------------------------- 5 files changed, 672 insertions(+), 700 deletions(-) diff --git a/tools/arch/arm64/include/uapi/asm/kvm.h b/tools/arch/arm64/include/uapi/asm/kvm.h index 89d2fc872d9f..964df31da975 100644 --- a/tools/arch/arm64/include/uapi/asm/kvm.h +++ b/tools/arch/arm64/include/uapi/asm/kvm.h @@ -37,9 +37,7 @@ #include #include -#define __KVM_HAVE_GUEST_DEBUG #define __KVM_HAVE_IRQ_LINE -#define __KVM_HAVE_READONLY_MEM #define __KVM_HAVE_VCPU_EVENTS #define KVM_COALESCED_MMIO_PAGE_OFFSET 1 @@ -76,11 +74,11 @@ struct kvm_regs { /* KVM_ARM_SET_DEVICE_ADDR ioctl id encoding */ #define KVM_ARM_DEVICE_TYPE_SHIFT 0 -#define KVM_ARM_DEVICE_TYPE_MASK GENMASK(KVM_ARM_DEVICE_TYPE_SHIFT + 15, \ - KVM_ARM_DEVICE_TYPE_SHIFT) +#define KVM_ARM_DEVICE_TYPE_MASK __GENMASK(KVM_ARM_DEVICE_TYPE_SHIFT + 15, \ + KVM_ARM_DEVICE_TYPE_SHIFT) #define KVM_ARM_DEVICE_ID_SHIFT 16 -#define KVM_ARM_DEVICE_ID_MASK GENMASK(KVM_ARM_DEVICE_ID_SHIFT + 15, \ - KVM_ARM_DEVICE_ID_SHIFT) +#define KVM_ARM_DEVICE_ID_MASK __GENMASK(KVM_ARM_DEVICE_ID_SHIFT + 15, \ + KVM_ARM_DEVICE_ID_SHIFT) /* Supported device IDs */ #define KVM_ARM_DEVICE_VGIC_V2 0 @@ -162,6 +160,11 @@ struct kvm_sync_regs { __u64 device_irq_level; }; +/* Bits for run->s.regs.device_irq_level */ +#define KVM_ARM_DEV_EL1_VTIMER (1 << 0) +#define KVM_ARM_DEV_EL1_PTIMER (1 << 1) +#define KVM_ARM_DEV_PMU (1 << 2) + /* * PMU filter structure. Describe a range of events with a particular * action. To be used with KVM_ARM_VCPU_PMU_V3_FILTER. diff --git a/tools/arch/powerpc/include/uapi/asm/kvm.h b/tools/arch/powerpc/include/uapi/asm/kvm.h index 9f18fa090f1f..1691297a766a 100644 --- a/tools/arch/powerpc/include/uapi/asm/kvm.h +++ b/tools/arch/powerpc/include/uapi/asm/kvm.h @@ -28,7 +28,6 @@ #define __KVM_HAVE_PPC_SMT #define __KVM_HAVE_IRQCHIP #define __KVM_HAVE_IRQ_LINE -#define __KVM_HAVE_GUEST_DEBUG /* Not always available, but if it is, this is the correct offset. */ #define KVM_COALESCED_MMIO_PAGE_OFFSET 1 @@ -733,4 +732,48 @@ struct kvm_ppc_xive_eq { #define KVM_XIVE_TIMA_PAGE_OFFSET 0 #define KVM_XIVE_ESB_PAGE_OFFSET 4 +/* for KVM_PPC_GET_PVINFO */ + +#define KVM_PPC_PVINFO_FLAGS_EV_IDLE (1<<0) + +struct kvm_ppc_pvinfo { + /* out */ + __u32 flags; + __u32 hcall[4]; + __u8 pad[108]; +}; + +/* for KVM_PPC_GET_SMMU_INFO */ +#define KVM_PPC_PAGE_SIZES_MAX_SZ 8 + +struct kvm_ppc_one_page_size { + __u32 page_shift; /* Page shift (or 0) */ + __u32 pte_enc; /* Encoding in the HPTE (>>12) */ +}; + +struct kvm_ppc_one_seg_page_size { + __u32 page_shift; /* Base page shift of segment (or 0) */ + __u32 slb_enc; /* SLB encoding for BookS */ + struct kvm_ppc_one_page_size enc[KVM_PPC_PAGE_SIZES_MAX_SZ]; +}; + +#define KVM_PPC_PAGE_SIZES_REAL 0x00000001 +#define KVM_PPC_1T_SEGMENTS 0x00000002 +#define KVM_PPC_NO_HASH 0x00000004 + +struct kvm_ppc_smmu_info { + __u64 flags; + __u32 slb_size; + __u16 data_keys; /* # storage keys supported for data */ + __u16 instr_keys; /* # storage keys supported for instructions */ + struct kvm_ppc_one_seg_page_size sps[KVM_PPC_PAGE_SIZES_MAX_SZ]; +}; + +/* for KVM_PPC_RESIZE_HPT_{PREPARE,COMMIT} */ +struct kvm_ppc_resize_hpt { + __u64 flags; + __u32 shift; + __u32 pad; +}; + #endif /* __LINUX_KVM_POWERPC_H */ diff --git a/tools/arch/s390/include/uapi/asm/kvm.h b/tools/arch/s390/include/uapi/asm/kvm.h index abe926d43cbe..05eaf6db3ad4 100644 --- a/tools/arch/s390/include/uapi/asm/kvm.h +++ b/tools/arch/s390/include/uapi/asm/kvm.h @@ -12,7 +12,320 @@ #include #define __KVM_S390 -#define __KVM_HAVE_GUEST_DEBUG + +struct kvm_s390_skeys { + __u64 start_gfn; + __u64 count; + __u64 skeydata_addr; + __u32 flags; + __u32 reserved[9]; +}; + +#define KVM_S390_CMMA_PEEK (1 << 0) + +/** + * kvm_s390_cmma_log - Used for CMMA migration. + * + * Used both for input and output. + * + * @start_gfn: Guest page number to start from. + * @count: Size of the result buffer. + * @flags: Control operation mode via KVM_S390_CMMA_* flags + * @remaining: Used with KVM_S390_GET_CMMA_BITS. Indicates how many dirty + * pages are still remaining. + * @mask: Used with KVM_S390_SET_CMMA_BITS. Bitmap of bits to actually set + * in the PGSTE. + * @values: Pointer to the values buffer. + * + * Used in KVM_S390_{G,S}ET_CMMA_BITS ioctls. + */ +struct kvm_s390_cmma_log { + __u64 start_gfn; + __u32 count; + __u32 flags; + union { + __u64 remaining; + __u64 mask; + }; + __u64 values; +}; + +#define KVM_S390_RESET_POR 1 +#define KVM_S390_RESET_CLEAR 2 +#define KVM_S390_RESET_SUBSYSTEM 4 +#define KVM_S390_RESET_CPU_INIT 8 +#define KVM_S390_RESET_IPL 16 + +/* for KVM_S390_MEM_OP */ +struct kvm_s390_mem_op { + /* in */ + __u64 gaddr; /* the guest address */ + __u64 flags; /* flags */ + __u32 size; /* amount of bytes */ + __u32 op; /* type of operation */ + __u64 buf; /* buffer in userspace */ + union { + struct { + __u8 ar; /* the access register number */ + __u8 key; /* access key, ignored if flag unset */ + __u8 pad1[6]; /* ignored */ + __u64 old_addr; /* ignored if cmpxchg flag unset */ + }; + __u32 sida_offset; /* offset into the sida */ + __u8 reserved[32]; /* ignored */ + }; +}; +/* types for kvm_s390_mem_op->op */ +#define KVM_S390_MEMOP_LOGICAL_READ 0 +#define KVM_S390_MEMOP_LOGICAL_WRITE 1 +#define KVM_S390_MEMOP_SIDA_READ 2 +#define KVM_S390_MEMOP_SIDA_WRITE 3 +#define KVM_S390_MEMOP_ABSOLUTE_READ 4 +#define KVM_S390_MEMOP_ABSOLUTE_WRITE 5 +#define KVM_S390_MEMOP_ABSOLUTE_CMPXCHG 6 + +/* flags for kvm_s390_mem_op->flags */ +#define KVM_S390_MEMOP_F_CHECK_ONLY (1ULL << 0) +#define KVM_S390_MEMOP_F_INJECT_EXCEPTION (1ULL << 1) +#define KVM_S390_MEMOP_F_SKEY_PROTECTION (1ULL << 2) + +/* flags specifying extension support via KVM_CAP_S390_MEM_OP_EXTENSION */ +#define KVM_S390_MEMOP_EXTENSION_CAP_BASE (1 << 0) +#define KVM_S390_MEMOP_EXTENSION_CAP_CMPXCHG (1 << 1) + +struct kvm_s390_psw { + __u64 mask; + __u64 addr; +}; + +/* valid values for type in kvm_s390_interrupt */ +#define KVM_S390_SIGP_STOP 0xfffe0000u +#define KVM_S390_PROGRAM_INT 0xfffe0001u +#define KVM_S390_SIGP_SET_PREFIX 0xfffe0002u +#define KVM_S390_RESTART 0xfffe0003u +#define KVM_S390_INT_PFAULT_INIT 0xfffe0004u +#define KVM_S390_INT_PFAULT_DONE 0xfffe0005u +#define KVM_S390_MCHK 0xfffe1000u +#define KVM_S390_INT_CLOCK_COMP 0xffff1004u +#define KVM_S390_INT_CPU_TIMER 0xffff1005u +#define KVM_S390_INT_VIRTIO 0xffff2603u +#define KVM_S390_INT_SERVICE 0xffff2401u +#define KVM_S390_INT_EMERGENCY 0xffff1201u +#define KVM_S390_INT_EXTERNAL_CALL 0xffff1202u +/* Anything below 0xfffe0000u is taken by INT_IO */ +#define KVM_S390_INT_IO(ai,cssid,ssid,schid) \ + (((schid)) | \ + ((ssid) << 16) | \ + ((cssid) << 18) | \ + ((ai) << 26)) +#define KVM_S390_INT_IO_MIN 0x00000000u +#define KVM_S390_INT_IO_MAX 0xfffdffffu +#define KVM_S390_INT_IO_AI_MASK 0x04000000u + + +struct kvm_s390_interrupt { + __u32 type; + __u32 parm; + __u64 parm64; +}; + +struct kvm_s390_io_info { + __u16 subchannel_id; + __u16 subchannel_nr; + __u32 io_int_parm; + __u32 io_int_word; +}; + +struct kvm_s390_ext_info { + __u32 ext_params; + __u32 pad; + __u64 ext_params2; +}; + +struct kvm_s390_pgm_info { + __u64 trans_exc_code; + __u64 mon_code; + __u64 per_address; + __u32 data_exc_code; + __u16 code; + __u16 mon_class_nr; + __u8 per_code; + __u8 per_atmid; + __u8 exc_access_id; + __u8 per_access_id; + __u8 op_access_id; +#define KVM_S390_PGM_FLAGS_ILC_VALID 0x01 +#define KVM_S390_PGM_FLAGS_ILC_0 0x02 +#define KVM_S390_PGM_FLAGS_ILC_1 0x04 +#define KVM_S390_PGM_FLAGS_ILC_MASK 0x06 +#define KVM_S390_PGM_FLAGS_NO_REWIND 0x08 + __u8 flags; + __u8 pad[2]; +}; + +struct kvm_s390_prefix_info { + __u32 address; +}; + +struct kvm_s390_extcall_info { + __u16 code; +}; + +struct kvm_s390_emerg_info { + __u16 code; +}; + +#define KVM_S390_STOP_FLAG_STORE_STATUS 0x01 +struct kvm_s390_stop_info { + __u32 flags; +}; + +struct kvm_s390_mchk_info { + __u64 cr14; + __u64 mcic; + __u64 failing_storage_address; + __u32 ext_damage_code; + __u32 pad; + __u8 fixed_logout[16]; +}; + +struct kvm_s390_irq { + __u64 type; + union { + struct kvm_s390_io_info io; + struct kvm_s390_ext_info ext; + struct kvm_s390_pgm_info pgm; + struct kvm_s390_emerg_info emerg; + struct kvm_s390_extcall_info extcall; + struct kvm_s390_prefix_info prefix; + struct kvm_s390_stop_info stop; + struct kvm_s390_mchk_info mchk; + char reserved[64]; + } u; +}; + +struct kvm_s390_irq_state { + __u64 buf; + __u32 flags; /* will stay unused for compatibility reasons */ + __u32 len; + __u32 reserved[4]; /* will stay unused for compatibility reasons */ +}; + +struct kvm_s390_ucas_mapping { + __u64 user_addr; + __u64 vcpu_addr; + __u64 length; +}; + +struct kvm_s390_pv_sec_parm { + __u64 origin; + __u64 length; +}; + +struct kvm_s390_pv_unp { + __u64 addr; + __u64 size; + __u64 tweak; +}; + +enum pv_cmd_dmp_id { + KVM_PV_DUMP_INIT, + KVM_PV_DUMP_CONFIG_STOR_STATE, + KVM_PV_DUMP_COMPLETE, + KVM_PV_DUMP_CPU, +}; + +struct kvm_s390_pv_dmp { + __u64 subcmd; + __u64 buff_addr; + __u64 buff_len; + __u64 gaddr; /* For dump storage state */ + __u64 reserved[4]; +}; + +enum pv_cmd_info_id { + KVM_PV_INFO_VM, + KVM_PV_INFO_DUMP, +}; + +struct kvm_s390_pv_info_dump { + __u64 dump_cpu_buffer_len; + __u64 dump_config_mem_buffer_per_1m; + __u64 dump_config_finalize_len; +}; + +struct kvm_s390_pv_info_vm { + __u64 inst_calls_list[4]; + __u64 max_cpus; + __u64 max_guests; + __u64 max_guest_addr; + __u64 feature_indication; +}; + +struct kvm_s390_pv_info_header { + __u32 id; + __u32 len_max; + __u32 len_written; + __u32 reserved; +}; + +struct kvm_s390_pv_info { + struct kvm_s390_pv_info_header header; + union { + struct kvm_s390_pv_info_dump dump; + struct kvm_s390_pv_info_vm vm; + }; +}; + +enum pv_cmd_id { + KVM_PV_ENABLE, + KVM_PV_DISABLE, + KVM_PV_SET_SEC_PARMS, + KVM_PV_UNPACK, + KVM_PV_VERIFY, + KVM_PV_PREP_RESET, + KVM_PV_UNSHARE_ALL, + KVM_PV_INFO, + KVM_PV_DUMP, + KVM_PV_ASYNC_CLEANUP_PREPARE, + KVM_PV_ASYNC_CLEANUP_PERFORM, +}; + +struct kvm_pv_cmd { + __u32 cmd; /* Command to be executed */ + __u16 rc; /* Ultravisor return code */ + __u16 rrc; /* Ultravisor return reason code */ + __u64 data; /* Data or address */ + __u32 flags; /* flags for future extensions. Must be 0 for now */ + __u32 reserved[3]; +}; + +struct kvm_s390_zpci_op { + /* in */ + __u32 fh; /* target device */ + __u8 op; /* operation to perform */ + __u8 pad[3]; + union { + /* for KVM_S390_ZPCIOP_REG_AEN */ + struct { + __u64 ibv; /* Guest addr of interrupt bit vector */ + __u64 sb; /* Guest addr of summary bit */ + __u32 flags; + __u32 noi; /* Number of interrupts */ + __u8 isc; /* Guest interrupt subclass */ + __u8 sbo; /* Offset of guest summary bit vector */ + __u16 pad; + } reg_aen; + __u64 reserved[8]; + } u; +}; + +/* types for kvm_s390_zpci_op->op */ +#define KVM_S390_ZPCIOP_REG_AEN 0 +#define KVM_S390_ZPCIOP_DEREG_AEN 1 + +/* flags for kvm_s390_zpci_op->u.reg_aen.flags */ +#define KVM_S390_ZPCIOP_REGAEN_HOST (1 << 0) /* Device control API: s390-specific devices */ #define KVM_DEV_FLIC_GET_ALL_IRQS 1 diff --git a/tools/arch/x86/include/uapi/asm/kvm.h b/tools/arch/x86/include/uapi/asm/kvm.h index a448d0964fc0..ef11aa4cab42 100644 --- a/tools/arch/x86/include/uapi/asm/kvm.h +++ b/tools/arch/x86/include/uapi/asm/kvm.h @@ -7,6 +7,8 @@ * */ +#include +#include #include #include #include @@ -40,7 +42,6 @@ #define __KVM_HAVE_IRQ_LINE #define __KVM_HAVE_MSI #define __KVM_HAVE_USER_NMI -#define __KVM_HAVE_GUEST_DEBUG #define __KVM_HAVE_MSIX #define __KVM_HAVE_MCE #define __KVM_HAVE_PIT_STATE2 @@ -49,7 +50,6 @@ #define __KVM_HAVE_DEBUGREGS #define __KVM_HAVE_XSAVE #define __KVM_HAVE_XCRS -#define __KVM_HAVE_READONLY_MEM /* Architectural interrupt line count. */ #define KVM_NR_INTERRUPTS 256 @@ -526,9 +526,301 @@ struct kvm_pmu_event_filter { #define KVM_PMU_EVENT_ALLOW 0 #define KVM_PMU_EVENT_DENY 1 -#define KVM_PMU_EVENT_FLAG_MASKED_EVENTS BIT(0) +#define KVM_PMU_EVENT_FLAG_MASKED_EVENTS _BITUL(0) #define KVM_PMU_EVENT_FLAGS_VALID_MASK (KVM_PMU_EVENT_FLAG_MASKED_EVENTS) +/* for KVM_CAP_MCE */ +struct kvm_x86_mce { + __u64 status; + __u64 addr; + __u64 misc; + __u64 mcg_status; + __u8 bank; + __u8 pad1[7]; + __u64 pad2[3]; +}; + +/* for KVM_CAP_XEN_HVM */ +#define KVM_XEN_HVM_CONFIG_HYPERCALL_MSR (1 << 0) +#define KVM_XEN_HVM_CONFIG_INTERCEPT_HCALL (1 << 1) +#define KVM_XEN_HVM_CONFIG_SHARED_INFO (1 << 2) +#define KVM_XEN_HVM_CONFIG_RUNSTATE (1 << 3) +#define KVM_XEN_HVM_CONFIG_EVTCHN_2LEVEL (1 << 4) +#define KVM_XEN_HVM_CONFIG_EVTCHN_SEND (1 << 5) +#define KVM_XEN_HVM_CONFIG_RUNSTATE_UPDATE_FLAG (1 << 6) +#define KVM_XEN_HVM_CONFIG_PVCLOCK_TSC_UNSTABLE (1 << 7) +#define KVM_XEN_HVM_CONFIG_SHARED_INFO_HVA (1 << 8) + +struct kvm_xen_hvm_config { + __u32 flags; + __u32 msr; + __u64 blob_addr_32; + __u64 blob_addr_64; + __u8 blob_size_32; + __u8 blob_size_64; + __u8 pad2[30]; +}; + +struct kvm_xen_hvm_attr { + __u16 type; + __u16 pad[3]; + union { + __u8 long_mode; + __u8 vector; + __u8 runstate_update_flag; + union { + __u64 gfn; +#define KVM_XEN_INVALID_GFN ((__u64)-1) + __u64 hva; + } shared_info; + struct { + __u32 send_port; + __u32 type; /* EVTCHNSTAT_ipi / EVTCHNSTAT_interdomain */ + __u32 flags; +#define KVM_XEN_EVTCHN_DEASSIGN (1 << 0) +#define KVM_XEN_EVTCHN_UPDATE (1 << 1) +#define KVM_XEN_EVTCHN_RESET (1 << 2) + /* + * Events sent by the guest are either looped back to + * the guest itself (potentially on a different port#) + * or signalled via an eventfd. + */ + union { + struct { + __u32 port; + __u32 vcpu; + __u32 priority; + } port; + struct { + __u32 port; /* Zero for eventfd */ + __s32 fd; + } eventfd; + __u32 padding[4]; + } deliver; + } evtchn; + __u32 xen_version; + __u64 pad[8]; + } u; +}; + + +/* Available with KVM_CAP_XEN_HVM / KVM_XEN_HVM_CONFIG_SHARED_INFO */ +#define KVM_XEN_ATTR_TYPE_LONG_MODE 0x0 +#define KVM_XEN_ATTR_TYPE_SHARED_INFO 0x1 +#define KVM_XEN_ATTR_TYPE_UPCALL_VECTOR 0x2 +/* Available with KVM_CAP_XEN_HVM / KVM_XEN_HVM_CONFIG_EVTCHN_SEND */ +#define KVM_XEN_ATTR_TYPE_EVTCHN 0x3 +#define KVM_XEN_ATTR_TYPE_XEN_VERSION 0x4 +/* Available with KVM_CAP_XEN_HVM / KVM_XEN_HVM_CONFIG_RUNSTATE_UPDATE_FLAG */ +#define KVM_XEN_ATTR_TYPE_RUNSTATE_UPDATE_FLAG 0x5 +/* Available with KVM_CAP_XEN_HVM / KVM_XEN_HVM_CONFIG_SHARED_INFO_HVA */ +#define KVM_XEN_ATTR_TYPE_SHARED_INFO_HVA 0x6 + +struct kvm_xen_vcpu_attr { + __u16 type; + __u16 pad[3]; + union { + __u64 gpa; +#define KVM_XEN_INVALID_GPA ((__u64)-1) + __u64 hva; + __u64 pad[8]; + struct { + __u64 state; + __u64 state_entry_time; + __u64 time_running; + __u64 time_runnable; + __u64 time_blocked; + __u64 time_offline; + } runstate; + __u32 vcpu_id; + struct { + __u32 port; + __u32 priority; + __u64 expires_ns; + } timer; + __u8 vector; + } u; +}; + +/* Available with KVM_CAP_XEN_HVM / KVM_XEN_HVM_CONFIG_SHARED_INFO */ +#define KVM_XEN_VCPU_ATTR_TYPE_VCPU_INFO 0x0 +#define KVM_XEN_VCPU_ATTR_TYPE_VCPU_TIME_INFO 0x1 +#define KVM_XEN_VCPU_ATTR_TYPE_RUNSTATE_ADDR 0x2 +#define KVM_XEN_VCPU_ATTR_TYPE_RUNSTATE_CURRENT 0x3 +#define KVM_XEN_VCPU_ATTR_TYPE_RUNSTATE_DATA 0x4 +#define KVM_XEN_VCPU_ATTR_TYPE_RUNSTATE_ADJUST 0x5 +/* Available with KVM_CAP_XEN_HVM / KVM_XEN_HVM_CONFIG_EVTCHN_SEND */ +#define KVM_XEN_VCPU_ATTR_TYPE_VCPU_ID 0x6 +#define KVM_XEN_VCPU_ATTR_TYPE_TIMER 0x7 +#define KVM_XEN_VCPU_ATTR_TYPE_UPCALL_VECTOR 0x8 +/* Available with KVM_CAP_XEN_HVM / KVM_XEN_HVM_CONFIG_SHARED_INFO_HVA */ +#define KVM_XEN_VCPU_ATTR_TYPE_VCPU_INFO_HVA 0x9 + +/* Secure Encrypted Virtualization command */ +enum sev_cmd_id { + /* Guest initialization commands */ + KVM_SEV_INIT = 0, + KVM_SEV_ES_INIT, + /* Guest launch commands */ + KVM_SEV_LAUNCH_START, + KVM_SEV_LAUNCH_UPDATE_DATA, + KVM_SEV_LAUNCH_UPDATE_VMSA, + KVM_SEV_LAUNCH_SECRET, + KVM_SEV_LAUNCH_MEASURE, + KVM_SEV_LAUNCH_FINISH, + /* Guest migration commands (outgoing) */ + KVM_SEV_SEND_START, + KVM_SEV_SEND_UPDATE_DATA, + KVM_SEV_SEND_UPDATE_VMSA, + KVM_SEV_SEND_FINISH, + /* Guest migration commands (incoming) */ + KVM_SEV_RECEIVE_START, + KVM_SEV_RECEIVE_UPDATE_DATA, + KVM_SEV_RECEIVE_UPDATE_VMSA, + KVM_SEV_RECEIVE_FINISH, + /* Guest status and debug commands */ + KVM_SEV_GUEST_STATUS, + KVM_SEV_DBG_DECRYPT, + KVM_SEV_DBG_ENCRYPT, + /* Guest certificates commands */ + KVM_SEV_CERT_EXPORT, + /* Attestation report */ + KVM_SEV_GET_ATTESTATION_REPORT, + /* Guest Migration Extension */ + KVM_SEV_SEND_CANCEL, + + KVM_SEV_NR_MAX, +}; + +struct kvm_sev_cmd { + __u32 id; + __u32 pad0; + __u64 data; + __u32 error; + __u32 sev_fd; +}; + +struct kvm_sev_launch_start { + __u32 handle; + __u32 policy; + __u64 dh_uaddr; + __u32 dh_len; + __u32 pad0; + __u64 session_uaddr; + __u32 session_len; + __u32 pad1; +}; + +struct kvm_sev_launch_update_data { + __u64 uaddr; + __u32 len; + __u32 pad0; +}; + + +struct kvm_sev_launch_secret { + __u64 hdr_uaddr; + __u32 hdr_len; + __u32 pad0; + __u64 guest_uaddr; + __u32 guest_len; + __u32 pad1; + __u64 trans_uaddr; + __u32 trans_len; + __u32 pad2; +}; + +struct kvm_sev_launch_measure { + __u64 uaddr; + __u32 len; + __u32 pad0; +}; + +struct kvm_sev_guest_status { + __u32 handle; + __u32 policy; + __u32 state; +}; + +struct kvm_sev_dbg { + __u64 src_uaddr; + __u64 dst_uaddr; + __u32 len; + __u32 pad0; +}; + +struct kvm_sev_attestation_report { + __u8 mnonce[16]; + __u64 uaddr; + __u32 len; + __u32 pad0; +}; + +struct kvm_sev_send_start { + __u32 policy; + __u32 pad0; + __u64 pdh_cert_uaddr; + __u32 pdh_cert_len; + __u32 pad1; + __u64 plat_certs_uaddr; + __u32 plat_certs_len; + __u32 pad2; + __u64 amd_certs_uaddr; + __u32 amd_certs_len; + __u32 pad3; + __u64 session_uaddr; + __u32 session_len; + __u32 pad4; +}; + +struct kvm_sev_send_update_data { + __u64 hdr_uaddr; + __u32 hdr_len; + __u32 pad0; + __u64 guest_uaddr; + __u32 guest_len; + __u32 pad1; + __u64 trans_uaddr; + __u32 trans_len; + __u32 pad2; +}; + +struct kvm_sev_receive_start { + __u32 handle; + __u32 policy; + __u64 pdh_uaddr; + __u32 pdh_len; + __u32 pad0; + __u64 session_uaddr; + __u32 session_len; + __u32 pad1; +}; + +struct kvm_sev_receive_update_data { + __u64 hdr_uaddr; + __u32 hdr_len; + __u32 pad0; + __u64 guest_uaddr; + __u32 guest_len; + __u32 pad1; + __u64 trans_uaddr; + __u32 trans_len; + __u32 pad2; +}; + +#define KVM_X2APIC_API_USE_32BIT_IDS (1ULL << 0) +#define KVM_X2APIC_API_DISABLE_BROADCAST_QUIRK (1ULL << 1) + +struct kvm_hyperv_eventfd { + __u32 conn_id; + __s32 fd; + __u32 flags; + __u32 padding[3]; +}; + +#define KVM_HYPERV_CONN_ID_MASK 0x00ffffff +#define KVM_HYPERV_EVENTFD_DEASSIGN (1 << 0) + /* * Masked event layout. * Bits Description @@ -549,10 +841,10 @@ struct kvm_pmu_event_filter { ((__u64)(!!(exclude)) << 55)) #define KVM_PMU_MASKED_ENTRY_EVENT_SELECT \ - (GENMASK_ULL(7, 0) | GENMASK_ULL(35, 32)) -#define KVM_PMU_MASKED_ENTRY_UMASK_MASK (GENMASK_ULL(63, 56)) -#define KVM_PMU_MASKED_ENTRY_UMASK_MATCH (GENMASK_ULL(15, 8)) -#define KVM_PMU_MASKED_ENTRY_EXCLUDE (BIT_ULL(55)) + (__GENMASK_ULL(7, 0) | __GENMASK_ULL(35, 32)) +#define KVM_PMU_MASKED_ENTRY_UMASK_MASK (__GENMASK_ULL(63, 56)) +#define KVM_PMU_MASKED_ENTRY_UMASK_MATCH (__GENMASK_ULL(15, 8)) +#define KVM_PMU_MASKED_ENTRY_EXCLUDE (_BITULL(55)) #define KVM_PMU_MASKED_ENTRY_UMASK_MASK_SHIFT (56) /* for KVM_{GET,SET,HAS}_DEVICE_ATTR */ @@ -560,7 +852,7 @@ struct kvm_pmu_event_filter { #define KVM_VCPU_TSC_OFFSET 0 /* attribute for the TSC offset */ /* x86-specific KVM_EXIT_HYPERCALL flags. */ -#define KVM_EXIT_HYPERCALL_LONG_MODE BIT(0) +#define KVM_EXIT_HYPERCALL_LONG_MODE _BITULL(0) #define KVM_X86_DEFAULT_VM 0 #define KVM_X86_SW_PROTECTED_VM 1 diff --git a/tools/include/uapi/linux/kvm.h b/tools/include/uapi/linux/kvm.h index c3308536482b..2190adbe3002 100644 --- a/tools/include/uapi/linux/kvm.h +++ b/tools/include/uapi/linux/kvm.h @@ -16,6 +16,11 @@ #define KVM_API_VERSION 12 +/* + * Backwards-compatible definitions. + */ +#define __KVM_HAVE_GUEST_DEBUG + /* for KVM_SET_USER_MEMORY_REGION */ struct kvm_userspace_memory_region { __u32 slot; @@ -85,43 +90,6 @@ struct kvm_pit_config { #define KVM_PIT_SPEAKER_DUMMY 1 -struct kvm_s390_skeys { - __u64 start_gfn; - __u64 count; - __u64 skeydata_addr; - __u32 flags; - __u32 reserved[9]; -}; - -#define KVM_S390_CMMA_PEEK (1 << 0) - -/** - * kvm_s390_cmma_log - Used for CMMA migration. - * - * Used both for input and output. - * - * @start_gfn: Guest page number to start from. - * @count: Size of the result buffer. - * @flags: Control operation mode via KVM_S390_CMMA_* flags - * @remaining: Used with KVM_S390_GET_CMMA_BITS. Indicates how many dirty - * pages are still remaining. - * @mask: Used with KVM_S390_SET_CMMA_BITS. Bitmap of bits to actually set - * in the PGSTE. - * @values: Pointer to the values buffer. - * - * Used in KVM_S390_{G,S}ET_CMMA_BITS ioctls. - */ -struct kvm_s390_cmma_log { - __u64 start_gfn; - __u32 count; - __u32 flags; - union { - __u64 remaining; - __u64 mask; - }; - __u64 values; -}; - struct kvm_hyperv_exit { #define KVM_EXIT_HYPERV_SYNIC 1 #define KVM_EXIT_HYPERV_HCALL 2 @@ -315,11 +283,6 @@ struct kvm_run { __u32 ipb; } s390_sieic; /* KVM_EXIT_S390_RESET */ -#define KVM_S390_RESET_POR 1 -#define KVM_S390_RESET_CLEAR 2 -#define KVM_S390_RESET_SUBSYSTEM 4 -#define KVM_S390_RESET_CPU_INIT 8 -#define KVM_S390_RESET_IPL 16 __u64 s390_reset_flags; /* KVM_EXIT_S390_UCONTROL */ struct { @@ -536,43 +499,6 @@ struct kvm_translation { __u8 pad[5]; }; -/* for KVM_S390_MEM_OP */ -struct kvm_s390_mem_op { - /* in */ - __u64 gaddr; /* the guest address */ - __u64 flags; /* flags */ - __u32 size; /* amount of bytes */ - __u32 op; /* type of operation */ - __u64 buf; /* buffer in userspace */ - union { - struct { - __u8 ar; /* the access register number */ - __u8 key; /* access key, ignored if flag unset */ - __u8 pad1[6]; /* ignored */ - __u64 old_addr; /* ignored if cmpxchg flag unset */ - }; - __u32 sida_offset; /* offset into the sida */ - __u8 reserved[32]; /* ignored */ - }; -}; -/* types for kvm_s390_mem_op->op */ -#define KVM_S390_MEMOP_LOGICAL_READ 0 -#define KVM_S390_MEMOP_LOGICAL_WRITE 1 -#define KVM_S390_MEMOP_SIDA_READ 2 -#define KVM_S390_MEMOP_SIDA_WRITE 3 -#define KVM_S390_MEMOP_ABSOLUTE_READ 4 -#define KVM_S390_MEMOP_ABSOLUTE_WRITE 5 -#define KVM_S390_MEMOP_ABSOLUTE_CMPXCHG 6 - -/* flags for kvm_s390_mem_op->flags */ -#define KVM_S390_MEMOP_F_CHECK_ONLY (1ULL << 0) -#define KVM_S390_MEMOP_F_INJECT_EXCEPTION (1ULL << 1) -#define KVM_S390_MEMOP_F_SKEY_PROTECTION (1ULL << 2) - -/* flags specifying extension support via KVM_CAP_S390_MEM_OP_EXTENSION */ -#define KVM_S390_MEMOP_EXTENSION_CAP_BASE (1 << 0) -#define KVM_S390_MEMOP_EXTENSION_CAP_CMPXCHG (1 << 1) - /* for KVM_INTERRUPT */ struct kvm_interrupt { /* in */ @@ -637,124 +563,6 @@ struct kvm_mp_state { __u32 mp_state; }; -struct kvm_s390_psw { - __u64 mask; - __u64 addr; -}; - -/* valid values for type in kvm_s390_interrupt */ -#define KVM_S390_SIGP_STOP 0xfffe0000u -#define KVM_S390_PROGRAM_INT 0xfffe0001u -#define KVM_S390_SIGP_SET_PREFIX 0xfffe0002u -#define KVM_S390_RESTART 0xfffe0003u -#define KVM_S390_INT_PFAULT_INIT 0xfffe0004u -#define KVM_S390_INT_PFAULT_DONE 0xfffe0005u -#define KVM_S390_MCHK 0xfffe1000u -#define KVM_S390_INT_CLOCK_COMP 0xffff1004u -#define KVM_S390_INT_CPU_TIMER 0xffff1005u -#define KVM_S390_INT_VIRTIO 0xffff2603u -#define KVM_S390_INT_SERVICE 0xffff2401u -#define KVM_S390_INT_EMERGENCY 0xffff1201u -#define KVM_S390_INT_EXTERNAL_CALL 0xffff1202u -/* Anything below 0xfffe0000u is taken by INT_IO */ -#define KVM_S390_INT_IO(ai,cssid,ssid,schid) \ - (((schid)) | \ - ((ssid) << 16) | \ - ((cssid) << 18) | \ - ((ai) << 26)) -#define KVM_S390_INT_IO_MIN 0x00000000u -#define KVM_S390_INT_IO_MAX 0xfffdffffu -#define KVM_S390_INT_IO_AI_MASK 0x04000000u - - -struct kvm_s390_interrupt { - __u32 type; - __u32 parm; - __u64 parm64; -}; - -struct kvm_s390_io_info { - __u16 subchannel_id; - __u16 subchannel_nr; - __u32 io_int_parm; - __u32 io_int_word; -}; - -struct kvm_s390_ext_info { - __u32 ext_params; - __u32 pad; - __u64 ext_params2; -}; - -struct kvm_s390_pgm_info { - __u64 trans_exc_code; - __u64 mon_code; - __u64 per_address; - __u32 data_exc_code; - __u16 code; - __u16 mon_class_nr; - __u8 per_code; - __u8 per_atmid; - __u8 exc_access_id; - __u8 per_access_id; - __u8 op_access_id; -#define KVM_S390_PGM_FLAGS_ILC_VALID 0x01 -#define KVM_S390_PGM_FLAGS_ILC_0 0x02 -#define KVM_S390_PGM_FLAGS_ILC_1 0x04 -#define KVM_S390_PGM_FLAGS_ILC_MASK 0x06 -#define KVM_S390_PGM_FLAGS_NO_REWIND 0x08 - __u8 flags; - __u8 pad[2]; -}; - -struct kvm_s390_prefix_info { - __u32 address; -}; - -struct kvm_s390_extcall_info { - __u16 code; -}; - -struct kvm_s390_emerg_info { - __u16 code; -}; - -#define KVM_S390_STOP_FLAG_STORE_STATUS 0x01 -struct kvm_s390_stop_info { - __u32 flags; -}; - -struct kvm_s390_mchk_info { - __u64 cr14; - __u64 mcic; - __u64 failing_storage_address; - __u32 ext_damage_code; - __u32 pad; - __u8 fixed_logout[16]; -}; - -struct kvm_s390_irq { - __u64 type; - union { - struct kvm_s390_io_info io; - struct kvm_s390_ext_info ext; - struct kvm_s390_pgm_info pgm; - struct kvm_s390_emerg_info emerg; - struct kvm_s390_extcall_info extcall; - struct kvm_s390_prefix_info prefix; - struct kvm_s390_stop_info stop; - struct kvm_s390_mchk_info mchk; - char reserved[64]; - } u; -}; - -struct kvm_s390_irq_state { - __u64 buf; - __u32 flags; /* will stay unused for compatibility reasons */ - __u32 len; - __u32 reserved[4]; /* will stay unused for compatibility reasons */ -}; - /* for KVM_SET_GUEST_DEBUG */ #define KVM_GUESTDBG_ENABLE 0x00000001 @@ -810,50 +618,6 @@ struct kvm_enable_cap { __u8 pad[64]; }; -/* for KVM_PPC_GET_PVINFO */ - -#define KVM_PPC_PVINFO_FLAGS_EV_IDLE (1<<0) - -struct kvm_ppc_pvinfo { - /* out */ - __u32 flags; - __u32 hcall[4]; - __u8 pad[108]; -}; - -/* for KVM_PPC_GET_SMMU_INFO */ -#define KVM_PPC_PAGE_SIZES_MAX_SZ 8 - -struct kvm_ppc_one_page_size { - __u32 page_shift; /* Page shift (or 0) */ - __u32 pte_enc; /* Encoding in the HPTE (>>12) */ -}; - -struct kvm_ppc_one_seg_page_size { - __u32 page_shift; /* Base page shift of segment (or 0) */ - __u32 slb_enc; /* SLB encoding for BookS */ - struct kvm_ppc_one_page_size enc[KVM_PPC_PAGE_SIZES_MAX_SZ]; -}; - -#define KVM_PPC_PAGE_SIZES_REAL 0x00000001 -#define KVM_PPC_1T_SEGMENTS 0x00000002 -#define KVM_PPC_NO_HASH 0x00000004 - -struct kvm_ppc_smmu_info { - __u64 flags; - __u32 slb_size; - __u16 data_keys; /* # storage keys supported for data */ - __u16 instr_keys; /* # storage keys supported for instructions */ - struct kvm_ppc_one_seg_page_size sps[KVM_PPC_PAGE_SIZES_MAX_SZ]; -}; - -/* for KVM_PPC_RESIZE_HPT_{PREPARE,COMMIT} */ -struct kvm_ppc_resize_hpt { - __u64 flags; - __u32 shift; - __u32 pad; -}; - #define KVMIO 0xAE /* machine type bits, to be used as argument to KVM_CREATE_VM */ @@ -923,9 +687,7 @@ struct kvm_ppc_resize_hpt { /* Bug in KVM_SET_USER_MEMORY_REGION fixed: */ #define KVM_CAP_DESTROY_MEMORY_REGION_WORKS 21 #define KVM_CAP_USER_NMI 22 -#ifdef __KVM_HAVE_GUEST_DEBUG #define KVM_CAP_SET_GUEST_DEBUG 23 -#endif #ifdef __KVM_HAVE_PIT #define KVM_CAP_REINJECT_CONTROL 24 #endif @@ -1156,8 +918,6 @@ struct kvm_ppc_resize_hpt { #define KVM_CAP_GUEST_MEMFD 234 #define KVM_CAP_VM_TYPES 235 -#ifdef KVM_CAP_IRQ_ROUTING - struct kvm_irq_routing_irqchip { __u32 irqchip; __u32 pin; @@ -1222,42 +982,6 @@ struct kvm_irq_routing { struct kvm_irq_routing_entry entries[]; }; -#endif - -#ifdef KVM_CAP_MCE -/* x86 MCE */ -struct kvm_x86_mce { - __u64 status; - __u64 addr; - __u64 misc; - __u64 mcg_status; - __u8 bank; - __u8 pad1[7]; - __u64 pad2[3]; -}; -#endif - -#ifdef KVM_CAP_XEN_HVM -#define KVM_XEN_HVM_CONFIG_HYPERCALL_MSR (1 << 0) -#define KVM_XEN_HVM_CONFIG_INTERCEPT_HCALL (1 << 1) -#define KVM_XEN_HVM_CONFIG_SHARED_INFO (1 << 2) -#define KVM_XEN_HVM_CONFIG_RUNSTATE (1 << 3) -#define KVM_XEN_HVM_CONFIG_EVTCHN_2LEVEL (1 << 4) -#define KVM_XEN_HVM_CONFIG_EVTCHN_SEND (1 << 5) -#define KVM_XEN_HVM_CONFIG_RUNSTATE_UPDATE_FLAG (1 << 6) -#define KVM_XEN_HVM_CONFIG_PVCLOCK_TSC_UNSTABLE (1 << 7) - -struct kvm_xen_hvm_config { - __u32 flags; - __u32 msr; - __u64 blob_addr_32; - __u64 blob_addr_64; - __u8 blob_size_32; - __u8 blob_size_64; - __u8 pad2[30]; -}; -#endif - #define KVM_IRQFD_FLAG_DEASSIGN (1 << 0) /* * Available with KVM_CAP_IRQFD_RESAMPLE @@ -1442,11 +1166,6 @@ struct kvm_vfio_spapr_tce { struct kvm_userspace_memory_region2) /* enable ucontrol for s390 */ -struct kvm_s390_ucas_mapping { - __u64 user_addr; - __u64 vcpu_addr; - __u64 length; -}; #define KVM_S390_UCAS_MAP _IOW(KVMIO, 0x50, struct kvm_s390_ucas_mapping) #define KVM_S390_UCAS_UNMAP _IOW(KVMIO, 0x51, struct kvm_s390_ucas_mapping) #define KVM_S390_VCPU_FAULT _IOW(KVMIO, 0x52, unsigned long) @@ -1641,89 +1360,6 @@ struct kvm_enc_region { #define KVM_S390_NORMAL_RESET _IO(KVMIO, 0xc3) #define KVM_S390_CLEAR_RESET _IO(KVMIO, 0xc4) -struct kvm_s390_pv_sec_parm { - __u64 origin; - __u64 length; -}; - -struct kvm_s390_pv_unp { - __u64 addr; - __u64 size; - __u64 tweak; -}; - -enum pv_cmd_dmp_id { - KVM_PV_DUMP_INIT, - KVM_PV_DUMP_CONFIG_STOR_STATE, - KVM_PV_DUMP_COMPLETE, - KVM_PV_DUMP_CPU, -}; - -struct kvm_s390_pv_dmp { - __u64 subcmd; - __u64 buff_addr; - __u64 buff_len; - __u64 gaddr; /* For dump storage state */ - __u64 reserved[4]; -}; - -enum pv_cmd_info_id { - KVM_PV_INFO_VM, - KVM_PV_INFO_DUMP, -}; - -struct kvm_s390_pv_info_dump { - __u64 dump_cpu_buffer_len; - __u64 dump_config_mem_buffer_per_1m; - __u64 dump_config_finalize_len; -}; - -struct kvm_s390_pv_info_vm { - __u64 inst_calls_list[4]; - __u64 max_cpus; - __u64 max_guests; - __u64 max_guest_addr; - __u64 feature_indication; -}; - -struct kvm_s390_pv_info_header { - __u32 id; - __u32 len_max; - __u32 len_written; - __u32 reserved; -}; - -struct kvm_s390_pv_info { - struct kvm_s390_pv_info_header header; - union { - struct kvm_s390_pv_info_dump dump; - struct kvm_s390_pv_info_vm vm; - }; -}; - -enum pv_cmd_id { - KVM_PV_ENABLE, - KVM_PV_DISABLE, - KVM_PV_SET_SEC_PARMS, - KVM_PV_UNPACK, - KVM_PV_VERIFY, - KVM_PV_PREP_RESET, - KVM_PV_UNSHARE_ALL, - KVM_PV_INFO, - KVM_PV_DUMP, - KVM_PV_ASYNC_CLEANUP_PREPARE, - KVM_PV_ASYNC_CLEANUP_PERFORM, -}; - -struct kvm_pv_cmd { - __u32 cmd; /* Command to be executed */ - __u16 rc; /* Ultravisor return code */ - __u16 rrc; /* Ultravisor return reason code */ - __u64 data; /* Data or address */ - __u32 flags; /* flags for future extensions. Must be 0 for now */ - __u32 reserved[3]; -}; - /* Available with KVM_CAP_S390_PROTECTED */ #define KVM_S390_PV_COMMAND _IOWR(KVMIO, 0xc5, struct kvm_pv_cmd) @@ -1737,58 +1373,6 @@ struct kvm_pv_cmd { #define KVM_XEN_HVM_GET_ATTR _IOWR(KVMIO, 0xc8, struct kvm_xen_hvm_attr) #define KVM_XEN_HVM_SET_ATTR _IOW(KVMIO, 0xc9, struct kvm_xen_hvm_attr) -struct kvm_xen_hvm_attr { - __u16 type; - __u16 pad[3]; - union { - __u8 long_mode; - __u8 vector; - __u8 runstate_update_flag; - struct { - __u64 gfn; -#define KVM_XEN_INVALID_GFN ((__u64)-1) - } shared_info; - struct { - __u32 send_port; - __u32 type; /* EVTCHNSTAT_ipi / EVTCHNSTAT_interdomain */ - __u32 flags; -#define KVM_XEN_EVTCHN_DEASSIGN (1 << 0) -#define KVM_XEN_EVTCHN_UPDATE (1 << 1) -#define KVM_XEN_EVTCHN_RESET (1 << 2) - /* - * Events sent by the guest are either looped back to - * the guest itself (potentially on a different port#) - * or signalled via an eventfd. - */ - union { - struct { - __u32 port; - __u32 vcpu; - __u32 priority; - } port; - struct { - __u32 port; /* Zero for eventfd */ - __s32 fd; - } eventfd; - __u32 padding[4]; - } deliver; - } evtchn; - __u32 xen_version; - __u64 pad[8]; - } u; -}; - - -/* Available with KVM_CAP_XEN_HVM / KVM_XEN_HVM_CONFIG_SHARED_INFO */ -#define KVM_XEN_ATTR_TYPE_LONG_MODE 0x0 -#define KVM_XEN_ATTR_TYPE_SHARED_INFO 0x1 -#define KVM_XEN_ATTR_TYPE_UPCALL_VECTOR 0x2 -/* Available with KVM_CAP_XEN_HVM / KVM_XEN_HVM_CONFIG_EVTCHN_SEND */ -#define KVM_XEN_ATTR_TYPE_EVTCHN 0x3 -#define KVM_XEN_ATTR_TYPE_XEN_VERSION 0x4 -/* Available with KVM_CAP_XEN_HVM / KVM_XEN_HVM_CONFIG_RUNSTATE_UPDATE_FLAG */ -#define KVM_XEN_ATTR_TYPE_RUNSTATE_UPDATE_FLAG 0x5 - /* Per-vCPU Xen attributes */ #define KVM_XEN_VCPU_GET_ATTR _IOWR(KVMIO, 0xca, struct kvm_xen_vcpu_attr) #define KVM_XEN_VCPU_SET_ATTR _IOW(KVMIO, 0xcb, struct kvm_xen_vcpu_attr) @@ -1799,242 +1383,6 @@ struct kvm_xen_hvm_attr { #define KVM_GET_SREGS2 _IOR(KVMIO, 0xcc, struct kvm_sregs2) #define KVM_SET_SREGS2 _IOW(KVMIO, 0xcd, struct kvm_sregs2) -struct kvm_xen_vcpu_attr { - __u16 type; - __u16 pad[3]; - union { - __u64 gpa; -#define KVM_XEN_INVALID_GPA ((__u64)-1) - __u64 pad[8]; - struct { - __u64 state; - __u64 state_entry_time; - __u64 time_running; - __u64 time_runnable; - __u64 time_blocked; - __u64 time_offline; - } runstate; - __u32 vcpu_id; - struct { - __u32 port; - __u32 priority; - __u64 expires_ns; - } timer; - __u8 vector; - } u; -}; - -/* Available with KVM_CAP_XEN_HVM / KVM_XEN_HVM_CONFIG_SHARED_INFO */ -#define KVM_XEN_VCPU_ATTR_TYPE_VCPU_INFO 0x0 -#define KVM_XEN_VCPU_ATTR_TYPE_VCPU_TIME_INFO 0x1 -#define KVM_XEN_VCPU_ATTR_TYPE_RUNSTATE_ADDR 0x2 -#define KVM_XEN_VCPU_ATTR_TYPE_RUNSTATE_CURRENT 0x3 -#define KVM_XEN_VCPU_ATTR_TYPE_RUNSTATE_DATA 0x4 -#define KVM_XEN_VCPU_ATTR_TYPE_RUNSTATE_ADJUST 0x5 -/* Available with KVM_CAP_XEN_HVM / KVM_XEN_HVM_CONFIG_EVTCHN_SEND */ -#define KVM_XEN_VCPU_ATTR_TYPE_VCPU_ID 0x6 -#define KVM_XEN_VCPU_ATTR_TYPE_TIMER 0x7 -#define KVM_XEN_VCPU_ATTR_TYPE_UPCALL_VECTOR 0x8 - -/* Secure Encrypted Virtualization command */ -enum sev_cmd_id { - /* Guest initialization commands */ - KVM_SEV_INIT = 0, - KVM_SEV_ES_INIT, - /* Guest launch commands */ - KVM_SEV_LAUNCH_START, - KVM_SEV_LAUNCH_UPDATE_DATA, - KVM_SEV_LAUNCH_UPDATE_VMSA, - KVM_SEV_LAUNCH_SECRET, - KVM_SEV_LAUNCH_MEASURE, - KVM_SEV_LAUNCH_FINISH, - /* Guest migration commands (outgoing) */ - KVM_SEV_SEND_START, - KVM_SEV_SEND_UPDATE_DATA, - KVM_SEV_SEND_UPDATE_VMSA, - KVM_SEV_SEND_FINISH, - /* Guest migration commands (incoming) */ - KVM_SEV_RECEIVE_START, - KVM_SEV_RECEIVE_UPDATE_DATA, - KVM_SEV_RECEIVE_UPDATE_VMSA, - KVM_SEV_RECEIVE_FINISH, - /* Guest status and debug commands */ - KVM_SEV_GUEST_STATUS, - KVM_SEV_DBG_DECRYPT, - KVM_SEV_DBG_ENCRYPT, - /* Guest certificates commands */ - KVM_SEV_CERT_EXPORT, - /* Attestation report */ - KVM_SEV_GET_ATTESTATION_REPORT, - /* Guest Migration Extension */ - KVM_SEV_SEND_CANCEL, - - KVM_SEV_NR_MAX, -}; - -struct kvm_sev_cmd { - __u32 id; - __u64 data; - __u32 error; - __u32 sev_fd; -}; - -struct kvm_sev_launch_start { - __u32 handle; - __u32 policy; - __u64 dh_uaddr; - __u32 dh_len; - __u64 session_uaddr; - __u32 session_len; -}; - -struct kvm_sev_launch_update_data { - __u64 uaddr; - __u32 len; -}; - - -struct kvm_sev_launch_secret { - __u64 hdr_uaddr; - __u32 hdr_len; - __u64 guest_uaddr; - __u32 guest_len; - __u64 trans_uaddr; - __u32 trans_len; -}; - -struct kvm_sev_launch_measure { - __u64 uaddr; - __u32 len; -}; - -struct kvm_sev_guest_status { - __u32 handle; - __u32 policy; - __u32 state; -}; - -struct kvm_sev_dbg { - __u64 src_uaddr; - __u64 dst_uaddr; - __u32 len; -}; - -struct kvm_sev_attestation_report { - __u8 mnonce[16]; - __u64 uaddr; - __u32 len; -}; - -struct kvm_sev_send_start { - __u32 policy; - __u64 pdh_cert_uaddr; - __u32 pdh_cert_len; - __u64 plat_certs_uaddr; - __u32 plat_certs_len; - __u64 amd_certs_uaddr; - __u32 amd_certs_len; - __u64 session_uaddr; - __u32 session_len; -}; - -struct kvm_sev_send_update_data { - __u64 hdr_uaddr; - __u32 hdr_len; - __u64 guest_uaddr; - __u32 guest_len; - __u64 trans_uaddr; - __u32 trans_len; -}; - -struct kvm_sev_receive_start { - __u32 handle; - __u32 policy; - __u64 pdh_uaddr; - __u32 pdh_len; - __u64 session_uaddr; - __u32 session_len; -}; - -struct kvm_sev_receive_update_data { - __u64 hdr_uaddr; - __u32 hdr_len; - __u64 guest_uaddr; - __u32 guest_len; - __u64 trans_uaddr; - __u32 trans_len; -}; - -#define KVM_DEV_ASSIGN_ENABLE_IOMMU (1 << 0) -#define KVM_DEV_ASSIGN_PCI_2_3 (1 << 1) -#define KVM_DEV_ASSIGN_MASK_INTX (1 << 2) - -struct kvm_assigned_pci_dev { - __u32 assigned_dev_id; - __u32 busnr; - __u32 devfn; - __u32 flags; - __u32 segnr; - union { - __u32 reserved[11]; - }; -}; - -#define KVM_DEV_IRQ_HOST_INTX (1 << 0) -#define KVM_DEV_IRQ_HOST_MSI (1 << 1) -#define KVM_DEV_IRQ_HOST_MSIX (1 << 2) - -#define KVM_DEV_IRQ_GUEST_INTX (1 << 8) -#define KVM_DEV_IRQ_GUEST_MSI (1 << 9) -#define KVM_DEV_IRQ_GUEST_MSIX (1 << 10) - -#define KVM_DEV_IRQ_HOST_MASK 0x00ff -#define KVM_DEV_IRQ_GUEST_MASK 0xff00 - -struct kvm_assigned_irq { - __u32 assigned_dev_id; - __u32 host_irq; /* ignored (legacy field) */ - __u32 guest_irq; - __u32 flags; - union { - __u32 reserved[12]; - }; -}; - -struct kvm_assigned_msix_nr { - __u32 assigned_dev_id; - __u16 entry_nr; - __u16 padding; -}; - -#define KVM_MAX_MSIX_PER_DEV 256 -struct kvm_assigned_msix_entry { - __u32 assigned_dev_id; - __u32 gsi; - __u16 entry; /* The index of entry in the MSI-X table */ - __u16 padding[3]; -}; - -#define KVM_X2APIC_API_USE_32BIT_IDS (1ULL << 0) -#define KVM_X2APIC_API_DISABLE_BROADCAST_QUIRK (1ULL << 1) - -/* Available with KVM_CAP_ARM_USER_IRQ */ - -/* Bits for run->s.regs.device_irq_level */ -#define KVM_ARM_DEV_EL1_VTIMER (1 << 0) -#define KVM_ARM_DEV_EL1_PTIMER (1 << 1) -#define KVM_ARM_DEV_PMU (1 << 2) - -struct kvm_hyperv_eventfd { - __u32 conn_id; - __s32 fd; - __u32 flags; - __u32 padding[3]; -}; - -#define KVM_HYPERV_CONN_ID_MASK 0x00ffffff -#define KVM_HYPERV_EVENTFD_DEASSIGN (1 << 0) - #define KVM_DIRTY_LOG_MANUAL_PROTECT_ENABLE (1 << 0) #define KVM_DIRTY_LOG_INITIALLY_SET (1 << 1) @@ -2180,33 +1528,6 @@ struct kvm_stats_desc { /* Available with KVM_CAP_S390_ZPCI_OP */ #define KVM_S390_ZPCI_OP _IOW(KVMIO, 0xd1, struct kvm_s390_zpci_op) -struct kvm_s390_zpci_op { - /* in */ - __u32 fh; /* target device */ - __u8 op; /* operation to perform */ - __u8 pad[3]; - union { - /* for KVM_S390_ZPCIOP_REG_AEN */ - struct { - __u64 ibv; /* Guest addr of interrupt bit vector */ - __u64 sb; /* Guest addr of summary bit */ - __u32 flags; - __u32 noi; /* Number of interrupts */ - __u8 isc; /* Guest interrupt subclass */ - __u8 sbo; /* Offset of guest summary bit vector */ - __u16 pad; - } reg_aen; - __u64 reserved[8]; - } u; -}; - -/* types for kvm_s390_zpci_op->op */ -#define KVM_S390_ZPCIOP_REG_AEN 0 -#define KVM_S390_ZPCIOP_DEREG_AEN 1 - -/* flags for kvm_s390_zpci_op->u.reg_aen.flags */ -#define KVM_S390_ZPCIOP_REGAEN_HOST (1 << 0) - /* Available with KVM_CAP_MEMORY_ATTRIBUTES */ #define KVM_SET_MEMORY_ATTRIBUTES _IOW(KVMIO, 0xd2, struct kvm_memory_attributes) -- cgit v1.2.3 From b7ce17f257da17a4163da82e0fb7726c2de85da7 Mon Sep 17 00:00:00 2001 From: Namhyung Kim Date: Mon, 8 Apr 2024 11:55:15 -0700 Subject: tools/include: Sync uapi/sound/asound.h with the kernel sources To pick up the changes from: 85df6b5a6658 ("ALSA: pcm: clarify and fix default msbits value for all formats") This should be used to beautify sound syscall arguments and it addresses these tools/perf build warnings: Warning: Kernel ABI header differences: diff -u tools/include/uapi/sound/asound.h include/uapi/sound/asound.h Cc: Jaroslav Kysela Cc: Takashi Iwai Cc: linux-sound@vger.kernel.org Signed-off-by: Namhyung Kim Link: https://lore.kernel.org/r/20240408185520.1550865-5-namhyung@kernel.org --- tools/include/uapi/sound/asound.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/include/uapi/sound/asound.h b/tools/include/uapi/sound/asound.h index d5b9cfbd9cea..628d46a0da92 100644 --- a/tools/include/uapi/sound/asound.h +++ b/tools/include/uapi/sound/asound.h @@ -142,7 +142,7 @@ struct snd_hwdep_dsp_image { * * *****************************************************************************/ -#define SNDRV_PCM_VERSION SNDRV_PROTOCOL_VERSION(2, 0, 16) +#define SNDRV_PCM_VERSION SNDRV_PROTOCOL_VERSION(2, 0, 17) typedef unsigned long snd_pcm_uframes_t; typedef signed long snd_pcm_sframes_t; @@ -416,7 +416,7 @@ struct snd_pcm_hw_params { unsigned int rmask; /* W: requested masks */ unsigned int cmask; /* R: changed masks */ unsigned int info; /* R: Info flags for returned setup */ - unsigned int msbits; /* R: used most significant bits */ + unsigned int msbits; /* R: used most significant bits (in sample bit-width) */ unsigned int rate_num; /* R: rate numerator */ unsigned int rate_den; /* R: rate denominator */ snd_pcm_uframes_t fifo_size; /* R: chip FIFO size in frames */ -- cgit v1.2.3 From 58e1b92df491c35abad7ddd2e393b89244e16bd5 Mon Sep 17 00:00:00 2001 From: Namhyung Kim Date: Mon, 8 Apr 2024 11:55:16 -0700 Subject: tools/include: Sync x86 CPU feature headers with the kernel sources To pick up the changes from: 598c2fafc06f ("perf/x86/amd/lbr: Use freeze based on availability") 7f274e609f3d ("x86/cpufeatures: Add new word for scattered features") This should address these tools/perf build warnings: Warning: Kernel ABI header differences: diff -u tools/arch/x86/include/asm/disabled-features.h arch/x86/include/asm/disabled-features.h diff -u tools/arch/x86/include/asm/required-features.h arch/x86/include/asm/required-features.h diff -u tools/arch/x86/include/asm/cpufeatures.h arch/x86/include/asm/cpufeatures.h Cc: Thomas Gleixner Cc: Ingo Molnar Cc: Borislav Petkov Cc: Dave Hansen Cc: "H. Peter Anvin" Cc: x86@kernel.org Signed-off-by: Namhyung Kim Link: https://lore.kernel.org/r/20240408185520.1550865-6-namhyung@kernel.org --- tools/arch/x86/include/asm/cpufeatures.h | 17 ++++++++++++----- tools/arch/x86/include/asm/disabled-features.h | 11 +++++++++-- tools/arch/x86/include/asm/required-features.h | 3 ++- 3 files changed, 23 insertions(+), 8 deletions(-) diff --git a/tools/arch/x86/include/asm/cpufeatures.h b/tools/arch/x86/include/asm/cpufeatures.h index 25160d26764b..a38f8f9ba657 100644 --- a/tools/arch/x86/include/asm/cpufeatures.h +++ b/tools/arch/x86/include/asm/cpufeatures.h @@ -13,7 +13,7 @@ /* * Defines x86 CPU feature bits */ -#define NCAPINTS 21 /* N 32-bit words worth of info */ +#define NCAPINTS 22 /* N 32-bit words worth of info */ #define NBUGINTS 2 /* N 32-bit bug flags */ /* @@ -81,10 +81,8 @@ #define X86_FEATURE_K6_MTRR ( 3*32+ 1) /* AMD K6 nonstandard MTRRs */ #define X86_FEATURE_CYRIX_ARR ( 3*32+ 2) /* Cyrix ARRs (= MTRRs) */ #define X86_FEATURE_CENTAUR_MCR ( 3*32+ 3) /* Centaur MCRs (= MTRRs) */ - -/* CPU types for specific tunings: */ #define X86_FEATURE_K8 ( 3*32+ 4) /* "" Opteron, Athlon64 */ -/* FREE, was #define X86_FEATURE_K7 ( 3*32+ 5) "" Athlon */ +#define X86_FEATURE_ZEN5 ( 3*32+ 5) /* "" CPU based on Zen5 microarchitecture */ #define X86_FEATURE_P3 ( 3*32+ 6) /* "" P3 */ #define X86_FEATURE_P4 ( 3*32+ 7) /* "" P4 */ #define X86_FEATURE_CONSTANT_TSC ( 3*32+ 8) /* TSC ticks at a constant rate */ @@ -97,7 +95,7 @@ #define X86_FEATURE_SYSENTER32 ( 3*32+15) /* "" sysenter in IA32 userspace */ #define X86_FEATURE_REP_GOOD ( 3*32+16) /* REP microcode works well */ #define X86_FEATURE_AMD_LBR_V2 ( 3*32+17) /* AMD Last Branch Record Extension Version 2 */ -/* FREE, was #define X86_FEATURE_LFENCE_RDTSC ( 3*32+18) "" LFENCE synchronizes RDTSC */ +#define X86_FEATURE_CLEAR_CPU_BUF ( 3*32+18) /* "" Clear CPU buffers using VERW */ #define X86_FEATURE_ACC_POWER ( 3*32+19) /* AMD Accumulated Power Mechanism */ #define X86_FEATURE_NOPL ( 3*32+20) /* The NOPL (0F 1F) instructions */ #define X86_FEATURE_ALWAYS ( 3*32+21) /* "" Always-present feature */ @@ -461,6 +459,14 @@ #define X86_FEATURE_IBPB_BRTYPE (20*32+28) /* "" MSR_PRED_CMD[IBPB] flushes all branch type predictions */ #define X86_FEATURE_SRSO_NO (20*32+29) /* "" CPU is not affected by SRSO */ +/* + * Extended auxiliary flags: Linux defined - for features scattered in various + * CPUID levels like 0x80000022, etc. + * + * Reuse free bits when adding new feature flags! + */ +#define X86_FEATURE_AMD_LBR_PMC_FREEZE (21*32+ 0) /* AMD LBR and PMC Freeze */ + /* * BUG word(s) */ @@ -508,4 +514,5 @@ /* BUG word 2 */ #define X86_BUG_SRSO X86_BUG(1*32 + 0) /* AMD SRSO bug */ #define X86_BUG_DIV0 X86_BUG(1*32 + 1) /* AMD DIV0 speculation bug */ +#define X86_BUG_RFDS X86_BUG(1*32 + 2) /* CPU is vulnerable to Register File Data Sampling */ #endif /* _ASM_X86_CPUFEATURES_H */ diff --git a/tools/arch/x86/include/asm/disabled-features.h b/tools/arch/x86/include/asm/disabled-features.h index 1f23960d2b06..c492bdc97b05 100644 --- a/tools/arch/x86/include/asm/disabled-features.h +++ b/tools/arch/x86/include/asm/disabled-features.h @@ -123,6 +123,12 @@ # define DISABLE_FRED (1 << (X86_FEATURE_FRED & 31)) #endif +#ifdef CONFIG_KVM_AMD_SEV +#define DISABLE_SEV_SNP 0 +#else +#define DISABLE_SEV_SNP (1 << (X86_FEATURE_SEV_SNP & 31)) +#endif + /* * Make sure to add features to the correct mask */ @@ -147,8 +153,9 @@ DISABLE_ENQCMD) #define DISABLED_MASK17 0 #define DISABLED_MASK18 (DISABLE_IBT) -#define DISABLED_MASK19 0 +#define DISABLED_MASK19 (DISABLE_SEV_SNP) #define DISABLED_MASK20 0 -#define DISABLED_MASK_CHECK BUILD_BUG_ON_ZERO(NCAPINTS != 21) +#define DISABLED_MASK21 0 +#define DISABLED_MASK_CHECK BUILD_BUG_ON_ZERO(NCAPINTS != 22) #endif /* _ASM_X86_DISABLED_FEATURES_H */ diff --git a/tools/arch/x86/include/asm/required-features.h b/tools/arch/x86/include/asm/required-features.h index 7ba1726b71c7..e9187ddd3d1f 100644 --- a/tools/arch/x86/include/asm/required-features.h +++ b/tools/arch/x86/include/asm/required-features.h @@ -99,6 +99,7 @@ #define REQUIRED_MASK18 0 #define REQUIRED_MASK19 0 #define REQUIRED_MASK20 0 -#define REQUIRED_MASK_CHECK BUILD_BUG_ON_ZERO(NCAPINTS != 21) +#define REQUIRED_MASK21 0 +#define REQUIRED_MASK_CHECK BUILD_BUG_ON_ZERO(NCAPINTS != 22) #endif /* _ASM_X86_REQUIRED_FEATURES_H */ -- cgit v1.2.3 From 978f2a60dd5ca6c25dfd5e24e7191b16af0ec429 Mon Sep 17 00:00:00 2001 From: Namhyung Kim Date: Mon, 8 Apr 2024 11:55:17 -0700 Subject: tools/include: Sync x86 asm/irq_vectors.h with the kernel sources To pick up the changes from: 0cbca1bf44a0 ("x86: irq: unconditionally define KVM interrupt vectors") This should address these tools/perf build warnings: Warning: Kernel ABI header differences: diff -u tools/arch/x86/include/asm/irq_vectors.h arch/x86/include/asm/irq_vectors.h Cc: Thomas Gleixner Cc: Ingo Molnar Cc: Borislav Petkov Cc: Dave Hansen Cc: "H. Peter Anvin" Cc: x86@kernel.org Signed-off-by: Namhyung Kim Link: https://lore.kernel.org/r/20240408185520.1550865-7-namhyung@kernel.org --- tools/arch/x86/include/asm/irq_vectors.h | 2 -- 1 file changed, 2 deletions(-) diff --git a/tools/arch/x86/include/asm/irq_vectors.h b/tools/arch/x86/include/asm/irq_vectors.h index 3f73ac3ed3a0..d18bfb238f66 100644 --- a/tools/arch/x86/include/asm/irq_vectors.h +++ b/tools/arch/x86/include/asm/irq_vectors.h @@ -84,11 +84,9 @@ #define HYPERVISOR_CALLBACK_VECTOR 0xf3 /* Vector for KVM to deliver posted interrupt IPI */ -#if IS_ENABLED(CONFIG_KVM) #define POSTED_INTR_VECTOR 0xf2 #define POSTED_INTR_WAKEUP_VECTOR 0xf1 #define POSTED_INTR_NESTED_VECTOR 0xf0 -#endif #define MANAGED_IRQ_SHUTDOWN_VECTOR 0xef -- cgit v1.2.3 From c781a72f9ddd09baddde9df1f59955c0d6ea4944 Mon Sep 17 00:00:00 2001 From: Namhyung Kim Date: Mon, 8 Apr 2024 11:55:18 -0700 Subject: tools/include: Sync x86 asm/msr-index.h with the kernel sources To pick up the changes from: 8076fcde016c ("x86/rfds: Mitigate Register File Data Sampling (RFDS)") d7b69b590bc9 ("x86/sev: Dump SEV_STATUS") cd6df3f378f6 ("x86/cpu: Add MSR numbers for FRED configuration") 216d106c7ff7 ("x86/sev: Add SEV-SNP host initialization support") This should address these tools/perf build warnings: Warning: Kernel ABI header differences: diff -u tools/arch/x86/include/asm/msr-index.h arch/x86/include/asm/msr-index.h Cc: Thomas Gleixner Cc: Ingo Molnar Cc: Borislav Petkov Cc: Dave Hansen Cc: "H. Peter Anvin" Cc: x86@kernel.org Signed-off-by: Namhyung Kim Link: https://lore.kernel.org/r/20240408185520.1550865-8-namhyung@kernel.org --- tools/arch/x86/include/asm/msr-index.h | 74 +++++++++++++++++++++++----------- 1 file changed, 51 insertions(+), 23 deletions(-) diff --git a/tools/arch/x86/include/asm/msr-index.h b/tools/arch/x86/include/asm/msr-index.h index 1f9dc9bd13eb..05956bd8bacf 100644 --- a/tools/arch/x86/include/asm/msr-index.h +++ b/tools/arch/x86/include/asm/msr-index.h @@ -176,6 +176,14 @@ * CPU is not vulnerable to Gather * Data Sampling (GDS). */ +#define ARCH_CAP_RFDS_NO BIT(27) /* + * Not susceptible to Register + * File Data Sampling. + */ +#define ARCH_CAP_RFDS_CLEAR BIT(28) /* + * VERW clears CPU Register + * File. + */ #define ARCH_CAP_XAPIC_DISABLE BIT(21) /* * IA32_XAPIC_DISABLE_STATUS MSR @@ -605,34 +613,47 @@ #define MSR_AMD64_SEV_ES_GHCB 0xc0010130 #define MSR_AMD64_SEV 0xc0010131 #define MSR_AMD64_SEV_ENABLED_BIT 0 -#define MSR_AMD64_SEV_ES_ENABLED_BIT 1 -#define MSR_AMD64_SEV_SNP_ENABLED_BIT 2 #define MSR_AMD64_SEV_ENABLED BIT_ULL(MSR_AMD64_SEV_ENABLED_BIT) +#define MSR_AMD64_SEV_ES_ENABLED_BIT 1 #define MSR_AMD64_SEV_ES_ENABLED BIT_ULL(MSR_AMD64_SEV_ES_ENABLED_BIT) +#define MSR_AMD64_SEV_SNP_ENABLED_BIT 2 #define MSR_AMD64_SEV_SNP_ENABLED BIT_ULL(MSR_AMD64_SEV_SNP_ENABLED_BIT) - -/* SNP feature bits enabled by the hypervisor */ -#define MSR_AMD64_SNP_VTOM BIT_ULL(3) -#define MSR_AMD64_SNP_REFLECT_VC BIT_ULL(4) -#define MSR_AMD64_SNP_RESTRICTED_INJ BIT_ULL(5) -#define MSR_AMD64_SNP_ALT_INJ BIT_ULL(6) -#define MSR_AMD64_SNP_DEBUG_SWAP BIT_ULL(7) -#define MSR_AMD64_SNP_PREVENT_HOST_IBS BIT_ULL(8) -#define MSR_AMD64_SNP_BTB_ISOLATION BIT_ULL(9) -#define MSR_AMD64_SNP_VMPL_SSS BIT_ULL(10) -#define MSR_AMD64_SNP_SECURE_TSC BIT_ULL(11) -#define MSR_AMD64_SNP_VMGEXIT_PARAM BIT_ULL(12) -#define MSR_AMD64_SNP_IBS_VIRT BIT_ULL(14) -#define MSR_AMD64_SNP_VMSA_REG_PROTECTION BIT_ULL(16) -#define MSR_AMD64_SNP_SMT_PROTECTION BIT_ULL(17) - -/* SNP feature bits reserved for future use. */ -#define MSR_AMD64_SNP_RESERVED_BIT13 BIT_ULL(13) -#define MSR_AMD64_SNP_RESERVED_BIT15 BIT_ULL(15) -#define MSR_AMD64_SNP_RESERVED_MASK GENMASK_ULL(63, 18) +#define MSR_AMD64_SNP_VTOM_BIT 3 +#define MSR_AMD64_SNP_VTOM BIT_ULL(MSR_AMD64_SNP_VTOM_BIT) +#define MSR_AMD64_SNP_REFLECT_VC_BIT 4 +#define MSR_AMD64_SNP_REFLECT_VC BIT_ULL(MSR_AMD64_SNP_REFLECT_VC_BIT) +#define MSR_AMD64_SNP_RESTRICTED_INJ_BIT 5 +#define MSR_AMD64_SNP_RESTRICTED_INJ BIT_ULL(MSR_AMD64_SNP_RESTRICTED_INJ_BIT) +#define MSR_AMD64_SNP_ALT_INJ_BIT 6 +#define MSR_AMD64_SNP_ALT_INJ BIT_ULL(MSR_AMD64_SNP_ALT_INJ_BIT) +#define MSR_AMD64_SNP_DEBUG_SWAP_BIT 7 +#define MSR_AMD64_SNP_DEBUG_SWAP BIT_ULL(MSR_AMD64_SNP_DEBUG_SWAP_BIT) +#define MSR_AMD64_SNP_PREVENT_HOST_IBS_BIT 8 +#define MSR_AMD64_SNP_PREVENT_HOST_IBS BIT_ULL(MSR_AMD64_SNP_PREVENT_HOST_IBS_BIT) +#define MSR_AMD64_SNP_BTB_ISOLATION_BIT 9 +#define MSR_AMD64_SNP_BTB_ISOLATION BIT_ULL(MSR_AMD64_SNP_BTB_ISOLATION_BIT) +#define MSR_AMD64_SNP_VMPL_SSS_BIT 10 +#define MSR_AMD64_SNP_VMPL_SSS BIT_ULL(MSR_AMD64_SNP_VMPL_SSS_BIT) +#define MSR_AMD64_SNP_SECURE_TSC_BIT 11 +#define MSR_AMD64_SNP_SECURE_TSC BIT_ULL(MSR_AMD64_SNP_SECURE_TSC_BIT) +#define MSR_AMD64_SNP_VMGEXIT_PARAM_BIT 12 +#define MSR_AMD64_SNP_VMGEXIT_PARAM BIT_ULL(MSR_AMD64_SNP_VMGEXIT_PARAM_BIT) +#define MSR_AMD64_SNP_RESERVED_BIT13 BIT_ULL(13) +#define MSR_AMD64_SNP_IBS_VIRT_BIT 14 +#define MSR_AMD64_SNP_IBS_VIRT BIT_ULL(MSR_AMD64_SNP_IBS_VIRT_BIT) +#define MSR_AMD64_SNP_RESERVED_BIT15 BIT_ULL(15) +#define MSR_AMD64_SNP_VMSA_REG_PROT_BIT 16 +#define MSR_AMD64_SNP_VMSA_REG_PROT BIT_ULL(MSR_AMD64_SNP_VMSA_REG_PROT_BIT) +#define MSR_AMD64_SNP_SMT_PROT_BIT 17 +#define MSR_AMD64_SNP_SMT_PROT BIT_ULL(MSR_AMD64_SNP_SMT_PROT_BIT) +#define MSR_AMD64_SNP_RESV_BIT 18 +#define MSR_AMD64_SNP_RESERVED_MASK GENMASK_ULL(63, MSR_AMD64_SNP_RESV_BIT) #define MSR_AMD64_VIRT_SPEC_CTRL 0xc001011f +#define MSR_AMD64_RMP_BASE 0xc0010132 +#define MSR_AMD64_RMP_END 0xc0010133 + /* AMD Collaborative Processor Performance Control MSRs */ #define MSR_AMD_CPPC_CAP1 0xc00102b0 #define MSR_AMD_CPPC_ENABLE 0xc00102b1 @@ -719,8 +740,15 @@ #define MSR_K8_TOP_MEM1 0xc001001a #define MSR_K8_TOP_MEM2 0xc001001d #define MSR_AMD64_SYSCFG 0xc0010010 -#define MSR_AMD64_SYSCFG_MEM_ENCRYPT_BIT 23 +#define MSR_AMD64_SYSCFG_MEM_ENCRYPT_BIT 23 #define MSR_AMD64_SYSCFG_MEM_ENCRYPT BIT_ULL(MSR_AMD64_SYSCFG_MEM_ENCRYPT_BIT) +#define MSR_AMD64_SYSCFG_SNP_EN_BIT 24 +#define MSR_AMD64_SYSCFG_SNP_EN BIT_ULL(MSR_AMD64_SYSCFG_SNP_EN_BIT) +#define MSR_AMD64_SYSCFG_SNP_VMPL_EN_BIT 25 +#define MSR_AMD64_SYSCFG_SNP_VMPL_EN BIT_ULL(MSR_AMD64_SYSCFG_SNP_VMPL_EN_BIT) +#define MSR_AMD64_SYSCFG_MFDM_BIT 19 +#define MSR_AMD64_SYSCFG_MFDM BIT_ULL(MSR_AMD64_SYSCFG_MFDM_BIT) + #define MSR_K8_INT_PENDING_MSG 0xc0010055 /* C1E active bits in int pending message */ #define K8_INTP_C1E_ACTIVE_MASK 0x18000000 -- cgit v1.2.3 From 99e4e1174acd7f5a942d37e1ac6c115f870d5975 Mon Sep 17 00:00:00 2001 From: Namhyung Kim Date: Mon, 8 Apr 2024 11:55:19 -0700 Subject: tools/include: Sync asm-generic/bitops/fls.h with the kernel sources To pick up the changes from: cb4ede926134 ("riscv: Avoid code duplication with generic bitops implementation") This should address these tools/perf build warnings: Warning: Kernel ABI header differences: diff -u tools/include/asm-generic/bitops/__fls.h include/asm-generic/bitops/__fls.h diff -u tools/include/asm-generic/bitops/fls.h include/asm-generic/bitops/fls.h Cc: Arnd Bergmann Cc: Geert Uytterhoeven Cc: Palmer Dabbelt Cc: linux-arch@vger.kernel.org Signed-off-by: Namhyung Kim Link: https://lore.kernel.org/r/20240408185520.1550865-9-namhyung@kernel.org --- tools/include/asm-generic/bitops/__fls.h | 8 ++++++-- tools/include/asm-generic/bitops/fls.h | 8 ++++++-- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/tools/include/asm-generic/bitops/__fls.h b/tools/include/asm-generic/bitops/__fls.h index 03f721a8a2b1..54ccccf96e21 100644 --- a/tools/include/asm-generic/bitops/__fls.h +++ b/tools/include/asm-generic/bitops/__fls.h @@ -5,12 +5,12 @@ #include /** - * __fls - find last (most-significant) set bit in a long word + * generic___fls - find last (most-significant) set bit in a long word * @word: the word to search * * Undefined if no set bit exists, so code should check against 0 first. */ -static __always_inline unsigned long __fls(unsigned long word) +static __always_inline unsigned long generic___fls(unsigned long word) { int num = BITS_PER_LONG - 1; @@ -41,4 +41,8 @@ static __always_inline unsigned long __fls(unsigned long word) return num; } +#ifndef __HAVE_ARCH___FLS +#define __fls(word) generic___fls(word) +#endif + #endif /* _ASM_GENERIC_BITOPS___FLS_H_ */ diff --git a/tools/include/asm-generic/bitops/fls.h b/tools/include/asm-generic/bitops/fls.h index b168bb10e1be..26f3ce1dd6e4 100644 --- a/tools/include/asm-generic/bitops/fls.h +++ b/tools/include/asm-generic/bitops/fls.h @@ -3,14 +3,14 @@ #define _ASM_GENERIC_BITOPS_FLS_H_ /** - * fls - find last (most-significant) bit set + * generic_fls - find last (most-significant) bit set * @x: the word to search * * This is defined the same way as ffs. * Note fls(0) = 0, fls(1) = 1, fls(0x80000000) = 32. */ -static __always_inline int fls(unsigned int x) +static __always_inline int generic_fls(unsigned int x) { int r = 32; @@ -39,4 +39,8 @@ static __always_inline int fls(unsigned int x) return r; } +#ifndef __HAVE_ARCH_FLS +#define fls(x) generic_fls(x) +#endif + #endif /* _ASM_GENERIC_BITOPS_FLS_H_ */ -- cgit v1.2.3 From 1cebd7f74976455ccd89c1dfbcf00bca52d0a512 Mon Sep 17 00:00:00 2001 From: Namhyung Kim Date: Mon, 8 Apr 2024 11:55:20 -0700 Subject: tools/include: Sync arm64 asm/cputype.h with the kernel sources To pick up the changes from: fb091ff39479 ("arm64: Subscribe Microsoft Azure Cobalt 100 to ARM Neoverse N2 errata") This should address these tools/perf build warnings: Warning: Kernel ABI header differences: diff -u tools/arch/arm64/include/asm/cputype.h arch/arm64/include/asm/cputype.h Cc: Catalin Marinas Cc: Will Deacon Cc: linux-arm-kernel@lists.infradead.org Signed-off-by: Namhyung Kim Link: https://lore.kernel.org/r/20240408185520.1550865-10-namhyung@kernel.org --- tools/arch/arm64/include/asm/cputype.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/tools/arch/arm64/include/asm/cputype.h b/tools/arch/arm64/include/asm/cputype.h index 7c7493cb571f..52f076afeb96 100644 --- a/tools/arch/arm64/include/asm/cputype.h +++ b/tools/arch/arm64/include/asm/cputype.h @@ -61,6 +61,7 @@ #define ARM_CPU_IMP_HISI 0x48 #define ARM_CPU_IMP_APPLE 0x61 #define ARM_CPU_IMP_AMPERE 0xC0 +#define ARM_CPU_IMP_MICROSOFT 0x6D #define ARM_CPU_PART_AEM_V8 0xD0F #define ARM_CPU_PART_FOUNDATION 0xD00 @@ -135,6 +136,8 @@ #define AMPERE_CPU_PART_AMPERE1 0xAC3 +#define MICROSOFT_CPU_PART_AZURE_COBALT_100 0xD49 /* Based on r0p0 of ARM Neoverse N2 */ + #define MIDR_CORTEX_A53 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_A53) #define MIDR_CORTEX_A57 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_A57) #define MIDR_CORTEX_A72 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_A72) @@ -193,6 +196,7 @@ #define MIDR_APPLE_M2_BLIZZARD_MAX MIDR_CPU_MODEL(ARM_CPU_IMP_APPLE, APPLE_CPU_PART_M2_BLIZZARD_MAX) #define MIDR_APPLE_M2_AVALANCHE_MAX MIDR_CPU_MODEL(ARM_CPU_IMP_APPLE, APPLE_CPU_PART_M2_AVALANCHE_MAX) #define MIDR_AMPERE1 MIDR_CPU_MODEL(ARM_CPU_IMP_AMPERE, AMPERE_CPU_PART_AMPERE1) +#define MIDR_MICROSOFT_AZURE_COBALT_100 MIDR_CPU_MODEL(ARM_CPU_IMP_MICROSOFT, MICROSOFT_CPU_PART_AZURE_COBALT_100) /* Fujitsu Erratum 010001 affects A64FX 1.0 and 1.1, (v0r0 and v1r0) */ #define MIDR_FUJITSU_ERRATUM_010001 MIDR_FUJITSU_A64FX -- cgit v1.2.3 From 447112d7edd77fa468938377418434233bcb3709 Mon Sep 17 00:00:00 2001 From: Sean Christopherson Date: Wed, 6 Mar 2024 17:13:42 -0800 Subject: KVM: VMX: Snapshot LBR capabilities during module initialization Snapshot VMX's LBR capabilities once during module initialization instead of calling into perf every time a vCPU reconfigures its vPMU. This will allow massaging the LBR capabilities, e.g. if the CPU doesn't support callstacks, without having to remember to update multiple locations. Opportunistically tag vmx_get_perf_capabilities() with __init, as it's only called from vmx_set_cpu_caps(). Reviewed-by: Mingwei Zhang Link: https://lore.kernel.org/r/20240307011344.835640-2-seanjc@google.com Signed-off-by: Sean Christopherson --- arch/x86/kvm/vmx/pmu_intel.c | 2 +- arch/x86/kvm/vmx/vmx.c | 9 +++++---- arch/x86/kvm/vmx/vmx.h | 2 ++ 3 files changed, 8 insertions(+), 5 deletions(-) diff --git a/arch/x86/kvm/vmx/pmu_intel.c b/arch/x86/kvm/vmx/pmu_intel.c index 12ade343a17e..be40474de6e4 100644 --- a/arch/x86/kvm/vmx/pmu_intel.c +++ b/arch/x86/kvm/vmx/pmu_intel.c @@ -535,7 +535,7 @@ static void intel_pmu_refresh(struct kvm_vcpu *vcpu) perf_capabilities = vcpu_get_perf_capabilities(vcpu); if (cpuid_model_is_consistent(vcpu) && (perf_capabilities & PMU_CAP_LBR_FMT)) - x86_perf_get_lbr(&lbr_desc->records); + memcpy(&lbr_desc->records, &vmx_lbr_caps, sizeof(vmx_lbr_caps)); else lbr_desc->records.nr = 0; diff --git a/arch/x86/kvm/vmx/vmx.c b/arch/x86/kvm/vmx/vmx.c index e3315bda6237..aca41d3419f9 100644 --- a/arch/x86/kvm/vmx/vmx.c +++ b/arch/x86/kvm/vmx/vmx.c @@ -218,6 +218,8 @@ module_param(ple_window_max, uint, 0444); int __read_mostly pt_mode = PT_MODE_SYSTEM; module_param(pt_mode, int, S_IRUGO); +struct x86_pmu_lbr __ro_after_init vmx_lbr_caps; + static DEFINE_STATIC_KEY_FALSE(vmx_l1d_should_flush); static DEFINE_STATIC_KEY_FALSE(vmx_l1d_flush_cond); static DEFINE_MUTEX(vmx_l1d_flush_mutex); @@ -7862,10 +7864,9 @@ static void vmx_vcpu_after_set_cpuid(struct kvm_vcpu *vcpu) vmx_update_exception_bitmap(vcpu); } -static u64 vmx_get_perf_capabilities(void) +static __init u64 vmx_get_perf_capabilities(void) { u64 perf_cap = PMU_CAP_FW_WRITES; - struct x86_pmu_lbr lbr; u64 host_perf_cap = 0; if (!enable_pmu) @@ -7875,8 +7876,8 @@ static u64 vmx_get_perf_capabilities(void) rdmsrl(MSR_IA32_PERF_CAPABILITIES, host_perf_cap); if (!cpu_feature_enabled(X86_FEATURE_ARCH_LBR)) { - x86_perf_get_lbr(&lbr); - if (lbr.nr) + x86_perf_get_lbr(&vmx_lbr_caps); + if (vmx_lbr_caps.nr) perf_cap |= host_perf_cap & PMU_CAP_LBR_FMT; } diff --git a/arch/x86/kvm/vmx/vmx.h b/arch/x86/kvm/vmx/vmx.h index 1742c88ba9c8..90f9e4434646 100644 --- a/arch/x86/kvm/vmx/vmx.h +++ b/arch/x86/kvm/vmx/vmx.h @@ -110,6 +110,8 @@ struct lbr_desc { bool msr_passthrough; }; +extern struct x86_pmu_lbr vmx_lbr_caps; + /* * The nested_vmx structure is part of vcpu_vmx, and holds information we need * for correct emulation of VMX (i.e., nested VMX) on this vcpu. -- cgit v1.2.3 From 0d0b60865071115f6da76090f0dbc1f0e8b9c647 Mon Sep 17 00:00:00 2001 From: Sean Christopherson Date: Wed, 6 Mar 2024 17:13:43 -0800 Subject: perf/x86/intel: Expose existence of callback support to KVM Add a "has_callstack" field to the x86_pmu_lbr structure used to pass information to KVM, and set it accordingly in x86_perf_get_lbr(). KVM will use has_callstack to avoid trying to create perf LBR events with PERF_SAMPLE_BRANCH_CALL_STACK on CPUs that don't support callstacks. Reviewed-by: Mingwei Zhang Link: https://lore.kernel.org/r/20240307011344.835640-3-seanjc@google.com Signed-off-by: Sean Christopherson --- arch/x86/events/intel/lbr.c | 1 + arch/x86/include/asm/perf_event.h | 1 + 2 files changed, 2 insertions(+) diff --git a/arch/x86/events/intel/lbr.c b/arch/x86/events/intel/lbr.c index 78cd5084104e..4367aa77cb8d 100644 --- a/arch/x86/events/intel/lbr.c +++ b/arch/x86/events/intel/lbr.c @@ -1693,6 +1693,7 @@ void x86_perf_get_lbr(struct x86_pmu_lbr *lbr) lbr->from = x86_pmu.lbr_from; lbr->to = x86_pmu.lbr_to; lbr->info = x86_pmu.lbr_info; + lbr->has_callstack = x86_pmu_has_lbr_callstack(); } EXPORT_SYMBOL_GPL(x86_perf_get_lbr); diff --git a/arch/x86/include/asm/perf_event.h b/arch/x86/include/asm/perf_event.h index 3736b8a46c04..7f1e17250546 100644 --- a/arch/x86/include/asm/perf_event.h +++ b/arch/x86/include/asm/perf_event.h @@ -555,6 +555,7 @@ struct x86_pmu_lbr { unsigned int from; unsigned int to; unsigned int info; + bool has_callstack; }; extern void perf_get_x86_pmu_capability(struct x86_pmu_capability *cap); -- cgit v1.2.3 From bb9dc859086df369f1fd34578dd5ca82d6321d21 Mon Sep 17 00:00:00 2001 From: Sean Christopherson Date: Wed, 6 Mar 2024 17:13:44 -0800 Subject: KVM: VMX: Disable LBR virtualization if the CPU doesn't support LBR callstacks Disable LBR virtualization if the CPU doesn't support callstacks, which were introduced in HSW (see commit e9d7f7cd97c4 ("perf/x86/intel: Add basic Haswell LBR call stack support"), as KVM unconditionally configures the perf LBR event with PERF_SAMPLE_BRANCH_CALL_STACK, i.e. LBR virtualization always fails on pre-HSW CPUs. Simply disable LBR support on such CPUs, as it has never worked, i.e. there is no risk of breaking an existing setup, and figuring out a way to performantly context switch LBRs on old CPUs is not worth the effort. Fixes: be635e34c284 ("KVM: vmx/pmu: Expose LBR_FMT in the MSR_IA32_PERF_CAPABILITIES") Cc: Mingwei Zhang Cc: Jim Mattson Tested-by: Mingwei Zhang Link: https://lore.kernel.org/r/20240307011344.835640-4-seanjc@google.com Signed-off-by: Sean Christopherson --- arch/x86/kvm/vmx/vmx.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/arch/x86/kvm/vmx/vmx.c b/arch/x86/kvm/vmx/vmx.c index aca41d3419f9..22411f4aff53 100644 --- a/arch/x86/kvm/vmx/vmx.c +++ b/arch/x86/kvm/vmx/vmx.c @@ -7877,7 +7877,15 @@ static __init u64 vmx_get_perf_capabilities(void) if (!cpu_feature_enabled(X86_FEATURE_ARCH_LBR)) { x86_perf_get_lbr(&vmx_lbr_caps); - if (vmx_lbr_caps.nr) + + /* + * KVM requires LBR callstack support, as the overhead due to + * context switching LBRs without said support is too high. + * See intel_pmu_create_guest_lbr_event() for more info. + */ + if (!vmx_lbr_caps.has_callstack) + memset(&vmx_lbr_caps, 0, sizeof(vmx_lbr_caps)); + else if (vmx_lbr_caps.nr) perf_cap |= host_perf_cap & PMU_CAP_LBR_FMT; } -- cgit v1.2.3 From 1bc26cb9090246190e8c540f5aa201cea2f895a1 Mon Sep 17 00:00:00 2001 From: Sean Christopherson Date: Mon, 8 Apr 2024 16:11:15 -0700 Subject: KVM: x86/mmu: Precisely invalidate MMU root_role during CPUID update Set kvm_mmu_page_role.invalid to mark the various MMU root_roles invalid during CPUID update in order to force a refresh, instead of zeroing out the entire role. This fixes a bug where kvm_mmu_free_roots() incorrectly thinks a root is indirect, i.e. not a TDP MMU, due to "direct" being zeroed, which in turn causes KVM to take mmu_lock for write instead of read. Note, paving over the entire role was largely unintentional, commit 7a458f0e1ba1 ("KVM: x86/mmu: remove extended bits from mmu_role, rename field") simply missed that "invalid" could be set. Fixes: 576a15de8d29 ("KVM: x86/mmu: Free TDP MMU roots while holding mmy_lock for read") Reported-by: syzbot+dc308fcfcd53f987de73@syzkaller.appspotmail.com Closes: https://lore.kernel.org/all/0000000000009b38080614c49bdb@google.com Cc: Phi Nguyen Link: https://lore.kernel.org/r/20240408231115.1387279-1-seanjc@google.com Signed-off-by: Sean Christopherson --- arch/x86/kvm/mmu/mmu.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/arch/x86/kvm/mmu/mmu.c b/arch/x86/kvm/mmu/mmu.c index 18a404b5923f..59c051845992 100644 --- a/arch/x86/kvm/mmu/mmu.c +++ b/arch/x86/kvm/mmu/mmu.c @@ -5576,9 +5576,9 @@ void kvm_mmu_after_set_cpuid(struct kvm_vcpu *vcpu) * that problem is swept under the rug; KVM's CPUID API is horrific and * it's all but impossible to solve it without introducing a new API. */ - vcpu->arch.root_mmu.root_role.word = 0; - vcpu->arch.guest_mmu.root_role.word = 0; - vcpu->arch.nested_mmu.root_role.word = 0; + vcpu->arch.root_mmu.root_role.invalid = 1; + vcpu->arch.guest_mmu.root_role.invalid = 1; + vcpu->arch.nested_mmu.root_role.invalid = 1; vcpu->arch.root_mmu.cpu_role.ext.valid = 0; vcpu->arch.guest_mmu.cpu_role.ext.valid = 0; vcpu->arch.nested_mmu.cpu_role.ext.valid = 0; -- cgit v1.2.3 From 2673dfb591a359c75080dd5af3da484b89320d22 Mon Sep 17 00:00:00 2001 From: David Matlack Date: Fri, 15 Mar 2024 16:05:38 -0700 Subject: KVM: x86/mmu: Write-protect L2 SPTEs in TDP MMU when clearing dirty status Check kvm_mmu_page_ad_need_write_protect() when deciding whether to write-protect or clear D-bits on TDP MMU SPTEs, so that the TDP MMU accounts for any role-specific reasons for disabling D-bit dirty logging. Specifically, TDP MMU SPTEs must be write-protected when the TDP MMU is being used to run an L2 (i.e. L1 has disabled EPT) and PML is enabled. KVM always disables PML when running L2, even when L1 and L2 GPAs are in the some domain, so failing to write-protect TDP MMU SPTEs will cause writes made by L2 to not be reflected in the dirty log. Reported-by: syzbot+900d58a45dcaab9e4821@syzkaller.appspotmail.com Closes: https://syzkaller.appspot.com/bug?extid=900d58a45dcaab9e4821 Fixes: 5982a5392663 ("KVM: x86/mmu: Use kvm_ad_enabled() to determine if TDP MMU SPTEs need wrprot") Cc: stable@vger.kernel.org Cc: Vipin Sharma Cc: Sean Christopherson Signed-off-by: David Matlack Link: https://lore.kernel.org/r/20240315230541.1635322-2-dmatlack@google.com [sean: massage shortlog and changelog, tweak ternary op formatting] Signed-off-by: Sean Christopherson --- arch/x86/kvm/mmu/tdp_mmu.c | 21 ++++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/arch/x86/kvm/mmu/tdp_mmu.c b/arch/x86/kvm/mmu/tdp_mmu.c index d078157e62aa..cf7d607a0125 100644 --- a/arch/x86/kvm/mmu/tdp_mmu.c +++ b/arch/x86/kvm/mmu/tdp_mmu.c @@ -1548,6 +1548,16 @@ void kvm_tdp_mmu_try_split_huge_pages(struct kvm *kvm, } } +static bool tdp_mmu_need_write_protect(struct kvm_mmu_page *sp) +{ + /* + * All TDP MMU shadow pages share the same role as their root, aside + * from level, so it is valid to key off any shadow page to determine if + * write protection is needed for an entire tree. + */ + return kvm_mmu_page_ad_need_write_protect(sp) || !kvm_ad_enabled(); +} + /* * Clear the dirty status of all the SPTEs mapping GFNs in the memslot. If * AD bits are enabled, this will involve clearing the dirty bit on each SPTE. @@ -1558,7 +1568,8 @@ void kvm_tdp_mmu_try_split_huge_pages(struct kvm *kvm, static bool clear_dirty_gfn_range(struct kvm *kvm, struct kvm_mmu_page *root, gfn_t start, gfn_t end) { - u64 dbit = kvm_ad_enabled() ? shadow_dirty_mask : PT_WRITABLE_MASK; + const u64 dbit = tdp_mmu_need_write_protect(root) ? PT_WRITABLE_MASK : + shadow_dirty_mask; struct tdp_iter iter; bool spte_set = false; @@ -1573,7 +1584,7 @@ retry: if (tdp_mmu_iter_cond_resched(kvm, &iter, false, true)) continue; - KVM_MMU_WARN_ON(kvm_ad_enabled() && + KVM_MMU_WARN_ON(dbit == shadow_dirty_mask && spte_ad_need_write_protect(iter.old_spte)); if (!(iter.old_spte & dbit)) @@ -1620,8 +1631,8 @@ bool kvm_tdp_mmu_clear_dirty_slot(struct kvm *kvm, static void clear_dirty_pt_masked(struct kvm *kvm, struct kvm_mmu_page *root, gfn_t gfn, unsigned long mask, bool wrprot) { - u64 dbit = (wrprot || !kvm_ad_enabled()) ? PT_WRITABLE_MASK : - shadow_dirty_mask; + const u64 dbit = (wrprot || tdp_mmu_need_write_protect(root)) ? PT_WRITABLE_MASK : + shadow_dirty_mask; struct tdp_iter iter; lockdep_assert_held_write(&kvm->mmu_lock); @@ -1633,7 +1644,7 @@ static void clear_dirty_pt_masked(struct kvm *kvm, struct kvm_mmu_page *root, if (!mask) break; - KVM_MMU_WARN_ON(kvm_ad_enabled() && + KVM_MMU_WARN_ON(dbit == shadow_dirty_mask && spte_ad_need_write_protect(iter.old_spte)); if (iter.level > PG_LEVEL_4K || -- cgit v1.2.3 From feac19aa4c26dc028d358bf23fa8f228ab46699e Mon Sep 17 00:00:00 2001 From: David Matlack Date: Fri, 15 Mar 2024 16:05:39 -0700 Subject: KVM: x86/mmu: Remove function comments above clear_dirty_{gfn_range,pt_masked}() Drop the comments above clear_dirty_gfn_range() and clear_dirty_pt_masked(), since each is word-for-word identical to the comment above their parent function. Leave the comment on the parent functions since they are APIs called by the KVM/x86 MMU. No functional change intended. Signed-off-by: David Matlack Link: https://lore.kernel.org/r/20240315230541.1635322-3-dmatlack@google.com Signed-off-by: Sean Christopherson --- arch/x86/kvm/mmu/tdp_mmu.c | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/arch/x86/kvm/mmu/tdp_mmu.c b/arch/x86/kvm/mmu/tdp_mmu.c index cf7d607a0125..23759b2bca5e 100644 --- a/arch/x86/kvm/mmu/tdp_mmu.c +++ b/arch/x86/kvm/mmu/tdp_mmu.c @@ -1558,13 +1558,6 @@ static bool tdp_mmu_need_write_protect(struct kvm_mmu_page *sp) return kvm_mmu_page_ad_need_write_protect(sp) || !kvm_ad_enabled(); } -/* - * Clear the dirty status of all the SPTEs mapping GFNs in the memslot. If - * AD bits are enabled, this will involve clearing the dirty bit on each SPTE. - * If AD bits are not enabled, this will require clearing the writable bit on - * each SPTE. Returns true if an SPTE has been changed and the TLBs need to - * be flushed. - */ static bool clear_dirty_gfn_range(struct kvm *kvm, struct kvm_mmu_page *root, gfn_t start, gfn_t end) { @@ -1621,13 +1614,6 @@ bool kvm_tdp_mmu_clear_dirty_slot(struct kvm *kvm, return spte_set; } -/* - * Clears the dirty status of all the 4k SPTEs mapping GFNs for which a bit is - * set in mask, starting at gfn. The given memslot is expected to contain all - * the GFNs represented by set bits in the mask. If AD bits are enabled, - * clearing the dirty status will involve clearing the dirty bit on each SPTE - * or, if AD bits are not enabled, clearing the writable bit on each SPTE. - */ static void clear_dirty_pt_masked(struct kvm *kvm, struct kvm_mmu_page *root, gfn_t gfn, unsigned long mask, bool wrprot) { -- cgit v1.2.3 From b1a8d2b02b69c7d7685f2e19f32034065310dbae Mon Sep 17 00:00:00 2001 From: David Matlack Date: Fri, 15 Mar 2024 16:05:40 -0700 Subject: KVM: x86/mmu: Fix and clarify comments about clearing D-bit vs. write-protecting Drop the "If AD bits are enabled/disabled" verbiage from the comments above kvm_tdp_mmu_clear_dirty_{slot,pt_masked}() since TDP MMU SPTEs may need to be write-protected even when A/D bits are enabled. i.e. These comments aren't technically correct. No functional change intended. Signed-off-by: David Matlack Link: https://lore.kernel.org/r/20240315230541.1635322-4-dmatlack@google.com Signed-off-by: Sean Christopherson --- arch/x86/kvm/mmu/tdp_mmu.c | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) diff --git a/arch/x86/kvm/mmu/tdp_mmu.c b/arch/x86/kvm/mmu/tdp_mmu.c index 23759b2bca5e..04c1f0957fea 100644 --- a/arch/x86/kvm/mmu/tdp_mmu.c +++ b/arch/x86/kvm/mmu/tdp_mmu.c @@ -1594,11 +1594,9 @@ retry: } /* - * Clear the dirty status of all the SPTEs mapping GFNs in the memslot. If - * AD bits are enabled, this will involve clearing the dirty bit on each SPTE. - * If AD bits are not enabled, this will require clearing the writable bit on - * each SPTE. Returns true if an SPTE has been changed and the TLBs need to - * be flushed. + * Clear the dirty status (D-bit or W-bit) of all the SPTEs mapping GFNs in the + * memslot. Returns true if an SPTE has been changed and the TLBs need to be + * flushed. */ bool kvm_tdp_mmu_clear_dirty_slot(struct kvm *kvm, const struct kvm_memory_slot *slot) @@ -1656,11 +1654,9 @@ static void clear_dirty_pt_masked(struct kvm *kvm, struct kvm_mmu_page *root, } /* - * Clears the dirty status of all the 4k SPTEs mapping GFNs for which a bit is - * set in mask, starting at gfn. The given memslot is expected to contain all - * the GFNs represented by set bits in the mask. If AD bits are enabled, - * clearing the dirty status will involve clearing the dirty bit on each SPTE - * or, if AD bits are not enabled, clearing the writable bit on each SPTE. + * Clear the dirty status (D-bit or W-bit) of all the 4k SPTEs mapping GFNs for + * which a bit is set in mask, starting at gfn. The given memslot is expected to + * contain all the GFNs represented by set bits in the mask. */ void kvm_tdp_mmu_clear_dirty_pt_masked(struct kvm *kvm, struct kvm_memory_slot *slot, -- cgit v1.2.3 From 40e0ee6338f0c042c0dabe1f17eb76eac37b5425 Mon Sep 17 00:00:00 2001 From: David Matlack Date: Fri, 15 Mar 2024 16:05:41 -0700 Subject: KVM: selftests: Add coverage of EPT-disabled to vmx_dirty_log_test Extend vmx_dirty_log_test to include accesses made by L2 when EPT is disabled. This commit adds explicit coverage of a bug caught by syzkaller, where the TDP MMU would clear D-bits instead of write-protecting SPTEs being used to map an L2, which only happens when L1 does not enable EPT, causing writes made by L2 to not be reflected in the dirty log when PML is enabled: $ ./vmx_dirty_log_test Nested EPT: disabled ==== Test Assertion Failure ==== x86_64/vmx_dirty_log_test.c:151: test_bit(0, bmap) pid=72052 tid=72052 errno=4 - Interrupted system call (stack trace empty) Page 0 incorrectly reported clean Opportunistically replace the volatile casts with {READ,WRITE}_ONCE(). Link: https://lore.kernel.org/kvm/000000000000c6526f06137f18cc@google.com/ Signed-off-by: David Matlack Link: https://lore.kernel.org/r/20240315230541.1635322-5-dmatlack@google.com Signed-off-by: Sean Christopherson --- .../selftests/kvm/x86_64/vmx_dirty_log_test.c | 60 +++++++++++++++++----- 1 file changed, 46 insertions(+), 14 deletions(-) diff --git a/tools/testing/selftests/kvm/x86_64/vmx_dirty_log_test.c b/tools/testing/selftests/kvm/x86_64/vmx_dirty_log_test.c index 7f6f5f23fb9b..977948fd52e6 100644 --- a/tools/testing/selftests/kvm/x86_64/vmx_dirty_log_test.c +++ b/tools/testing/selftests/kvm/x86_64/vmx_dirty_log_test.c @@ -28,16 +28,16 @@ #define NESTED_TEST_MEM1 0xc0001000 #define NESTED_TEST_MEM2 0xc0002000 -static void l2_guest_code(void) +static void l2_guest_code(u64 *a, u64 *b) { - *(volatile uint64_t *)NESTED_TEST_MEM1; - *(volatile uint64_t *)NESTED_TEST_MEM1 = 1; + READ_ONCE(*a); + WRITE_ONCE(*a, 1); GUEST_SYNC(true); GUEST_SYNC(false); - *(volatile uint64_t *)NESTED_TEST_MEM2 = 1; + WRITE_ONCE(*b, 1); GUEST_SYNC(true); - *(volatile uint64_t *)NESTED_TEST_MEM2 = 1; + WRITE_ONCE(*b, 1); GUEST_SYNC(true); GUEST_SYNC(false); @@ -45,17 +45,33 @@ static void l2_guest_code(void) vmcall(); } +static void l2_guest_code_ept_enabled(void) +{ + l2_guest_code((u64 *)NESTED_TEST_MEM1, (u64 *)NESTED_TEST_MEM2); +} + +static void l2_guest_code_ept_disabled(void) +{ + /* Access the same L1 GPAs as l2_guest_code_ept_enabled() */ + l2_guest_code((u64 *)GUEST_TEST_MEM, (u64 *)GUEST_TEST_MEM); +} + void l1_guest_code(struct vmx_pages *vmx) { #define L2_GUEST_STACK_SIZE 64 unsigned long l2_guest_stack[L2_GUEST_STACK_SIZE]; + void *l2_rip; GUEST_ASSERT(vmx->vmcs_gpa); GUEST_ASSERT(prepare_for_vmx_operation(vmx)); GUEST_ASSERT(load_vmcs(vmx)); - prepare_vmcs(vmx, l2_guest_code, - &l2_guest_stack[L2_GUEST_STACK_SIZE]); + if (vmx->eptp_gpa) + l2_rip = l2_guest_code_ept_enabled; + else + l2_rip = l2_guest_code_ept_disabled; + + prepare_vmcs(vmx, l2_rip, &l2_guest_stack[L2_GUEST_STACK_SIZE]); GUEST_SYNC(false); GUEST_ASSERT(!vmlaunch()); @@ -64,7 +80,7 @@ void l1_guest_code(struct vmx_pages *vmx) GUEST_DONE(); } -int main(int argc, char *argv[]) +static void test_vmx_dirty_log(bool enable_ept) { vm_vaddr_t vmx_pages_gva = 0; struct vmx_pages *vmx; @@ -76,8 +92,7 @@ int main(int argc, char *argv[]) struct ucall uc; bool done = false; - TEST_REQUIRE(kvm_cpu_has(X86_FEATURE_VMX)); - TEST_REQUIRE(kvm_cpu_has_ept()); + pr_info("Nested EPT: %s\n", enable_ept ? "enabled" : "disabled"); /* Create VM */ vm = vm_create_with_one_vcpu(&vcpu, l1_guest_code); @@ -103,11 +118,16 @@ int main(int argc, char *argv[]) * * Note that prepare_eptp should be called only L1's GPA map is done, * meaning after the last call to virt_map. + * + * When EPT is disabled, the L2 guest code will still access the same L1 + * GPAs as the EPT enabled case. */ - prepare_eptp(vmx, vm, 0); - nested_map_memslot(vmx, vm, 0); - nested_map(vmx, vm, NESTED_TEST_MEM1, GUEST_TEST_MEM, 4096); - nested_map(vmx, vm, NESTED_TEST_MEM2, GUEST_TEST_MEM, 4096); + if (enable_ept) { + prepare_eptp(vmx, vm, 0); + nested_map_memslot(vmx, vm, 0); + nested_map(vmx, vm, NESTED_TEST_MEM1, GUEST_TEST_MEM, 4096); + nested_map(vmx, vm, NESTED_TEST_MEM2, GUEST_TEST_MEM, 4096); + } bmap = bitmap_zalloc(TEST_MEM_PAGES); host_test_mem = addr_gpa2hva(vm, GUEST_TEST_MEM); @@ -148,3 +168,15 @@ int main(int argc, char *argv[]) } } } + +int main(int argc, char *argv[]) +{ + TEST_REQUIRE(kvm_cpu_has(X86_FEATURE_VMX)); + + test_vmx_dirty_log(/*enable_ept=*/false); + + if (kvm_cpu_has_ept()) + test_vmx_dirty_log(/*enable_ept=*/true); + + return 0; +} -- cgit v1.2.3 From eefb85b3f0310c2f4149c50cb9b13094ed1dde25 Mon Sep 17 00:00:00 2001 From: Sean Christopherson Date: Mon, 4 Mar 2024 16:37:42 -0800 Subject: KVM: Drop unused @may_block param from gfn_to_pfn_cache_invalidate_start() Remove gfn_to_pfn_cache_invalidate_start()'s unused @may_block parameter, which was leftover from KVM's abandoned (for now) attempt to support guest usage of gfn_to_pfn caches. Fixes: a4bff3df5147 ("KVM: pfncache: remove KVM_GUEST_USES_PFN usage") Reported-by: Like Xu Cc: Paul Durrant Cc: David Woodhouse Reviewed-by: Paul Durrant Reviewed-by: David Woodhouse Link: https://lore.kernel.org/r/20240305003742.245767-1-seanjc@google.com Signed-off-by: Sean Christopherson --- virt/kvm/kvm_main.c | 3 +-- virt/kvm/kvm_mm.h | 6 ++---- virt/kvm/pfncache.c | 2 +- 3 files changed, 4 insertions(+), 7 deletions(-) diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c index fb49c2a60200..ff0a20565f90 100644 --- a/virt/kvm/kvm_main.c +++ b/virt/kvm/kvm_main.c @@ -832,8 +832,7 @@ static int kvm_mmu_notifier_invalidate_range_start(struct mmu_notifier *mn, * mn_active_invalidate_count (see above) instead of * mmu_invalidate_in_progress. */ - gfn_to_pfn_cache_invalidate_start(kvm, range->start, range->end, - hva_range.may_block); + gfn_to_pfn_cache_invalidate_start(kvm, range->start, range->end); /* * If one or more memslots were found and thus zapped, notify arch code diff --git a/virt/kvm/kvm_mm.h b/virt/kvm/kvm_mm.h index ecefc7ec51af..715f19669d01 100644 --- a/virt/kvm/kvm_mm.h +++ b/virt/kvm/kvm_mm.h @@ -26,13 +26,11 @@ kvm_pfn_t hva_to_pfn(unsigned long addr, bool atomic, bool interruptible, #ifdef CONFIG_HAVE_KVM_PFNCACHE void gfn_to_pfn_cache_invalidate_start(struct kvm *kvm, unsigned long start, - unsigned long end, - bool may_block); + unsigned long end); #else static inline void gfn_to_pfn_cache_invalidate_start(struct kvm *kvm, unsigned long start, - unsigned long end, - bool may_block) + unsigned long end) { } #endif /* HAVE_KVM_PFNCACHE */ diff --git a/virt/kvm/pfncache.c b/virt/kvm/pfncache.c index f618719644e0..e3453e869e92 100644 --- a/virt/kvm/pfncache.c +++ b/virt/kvm/pfncache.c @@ -23,7 +23,7 @@ * MMU notifier 'invalidate_range_start' hook. */ void gfn_to_pfn_cache_invalidate_start(struct kvm *kvm, unsigned long start, - unsigned long end, bool may_block) + unsigned long end) { struct gfn_to_pfn_cache *gpc; -- cgit v1.2.3 From 17f8dc2db52185460f212052f3a692c1fdc167ba Mon Sep 17 00:00:00 2001 From: Xiubo Li Date: Tue, 9 Apr 2024 08:56:03 +0800 Subject: ceph: switch to use cap_delay_lock for the unlink delay list The same list item will be used in both cap_delay_list and cap_unlink_delay_list, so it's buggy to use two different locks to protect them. Cc: stable@vger.kernel.org Fixes: dbc347ef7f0c ("ceph: add ceph_cap_unlink_work to fire check_caps() immediately") Link: https://lists.ceph.io/hyperkitty/list/ceph-users@ceph.io/thread/AODC76VXRAMXKLFDCTK4TKFDDPWUSCN5 Reported-by: Marc Ruhmann Signed-off-by: Xiubo Li Reviewed-by: Ilya Dryomov Tested-by: Marc Ruhmann Signed-off-by: Ilya Dryomov --- fs/ceph/caps.c | 4 ++-- fs/ceph/mds_client.c | 9 ++++----- fs/ceph/mds_client.h | 3 +-- 3 files changed, 7 insertions(+), 9 deletions(-) diff --git a/fs/ceph/caps.c b/fs/ceph/caps.c index 55051ad09c19..c4941ba245ac 100644 --- a/fs/ceph/caps.c +++ b/fs/ceph/caps.c @@ -4783,13 +4783,13 @@ int ceph_drop_caps_for_unlink(struct inode *inode) doutc(mdsc->fsc->client, "%p %llx.%llx\n", inode, ceph_vinop(inode)); - spin_lock(&mdsc->cap_unlink_delay_lock); + spin_lock(&mdsc->cap_delay_lock); ci->i_ceph_flags |= CEPH_I_FLUSH; if (!list_empty(&ci->i_cap_delay_list)) list_del_init(&ci->i_cap_delay_list); list_add_tail(&ci->i_cap_delay_list, &mdsc->cap_unlink_delay_list); - spin_unlock(&mdsc->cap_unlink_delay_lock); + spin_unlock(&mdsc->cap_delay_lock); /* * Fire the work immediately, because the MDS maybe diff --git a/fs/ceph/mds_client.c b/fs/ceph/mds_client.c index 3ab9c268a8bb..360b686c3c67 100644 --- a/fs/ceph/mds_client.c +++ b/fs/ceph/mds_client.c @@ -2504,7 +2504,7 @@ static void ceph_cap_unlink_work(struct work_struct *work) struct ceph_client *cl = mdsc->fsc->client; doutc(cl, "begin\n"); - spin_lock(&mdsc->cap_unlink_delay_lock); + spin_lock(&mdsc->cap_delay_lock); while (!list_empty(&mdsc->cap_unlink_delay_list)) { struct ceph_inode_info *ci; struct inode *inode; @@ -2516,15 +2516,15 @@ static void ceph_cap_unlink_work(struct work_struct *work) inode = igrab(&ci->netfs.inode); if (inode) { - spin_unlock(&mdsc->cap_unlink_delay_lock); + spin_unlock(&mdsc->cap_delay_lock); doutc(cl, "on %p %llx.%llx\n", inode, ceph_vinop(inode)); ceph_check_caps(ci, CHECK_CAPS_FLUSH); iput(inode); - spin_lock(&mdsc->cap_unlink_delay_lock); + spin_lock(&mdsc->cap_delay_lock); } } - spin_unlock(&mdsc->cap_unlink_delay_lock); + spin_unlock(&mdsc->cap_delay_lock); doutc(cl, "done\n"); } @@ -5404,7 +5404,6 @@ int ceph_mdsc_init(struct ceph_fs_client *fsc) INIT_LIST_HEAD(&mdsc->cap_wait_list); spin_lock_init(&mdsc->cap_delay_lock); INIT_LIST_HEAD(&mdsc->cap_unlink_delay_list); - spin_lock_init(&mdsc->cap_unlink_delay_lock); INIT_LIST_HEAD(&mdsc->snap_flush_list); spin_lock_init(&mdsc->snap_flush_lock); mdsc->last_cap_flush_tid = 1; diff --git a/fs/ceph/mds_client.h b/fs/ceph/mds_client.h index 03f8ff00874f..b88e80415224 100644 --- a/fs/ceph/mds_client.h +++ b/fs/ceph/mds_client.h @@ -461,9 +461,8 @@ struct ceph_mds_client { struct delayed_work delayed_work; /* delayed work */ unsigned long last_renew_caps; /* last time we renewed our caps */ struct list_head cap_delay_list; /* caps with delayed release */ - spinlock_t cap_delay_lock; /* protects cap_delay_list */ struct list_head cap_unlink_delay_list; /* caps with delayed release for unlink */ - spinlock_t cap_unlink_delay_lock; /* protects cap_unlink_delay_list */ + spinlock_t cap_delay_lock; /* protects cap_delay_list and cap_unlink_delay_list */ struct list_head snap_flush_list; /* cap_snaps ready to flush */ spinlock_t snap_flush_lock; -- cgit v1.2.3 From d3e0469306793972fd2b1ea016fa7ab0658c9849 Mon Sep 17 00:00:00 2001 From: Jeff Layton Date: Tue, 9 Apr 2024 07:01:57 -0400 Subject: MAINTAINERS: remove myself as a Reviewer for Ceph It has been a couple of years since I stepped down as CephFS maintainer. I'm not involved in any meaningful way with the project these days, so while I'm happy to help review the occasional patch, I don't need to be cc'ed on all of them. Signed-off-by: Jeff Layton Signed-off-by: Ilya Dryomov --- MAINTAINERS | 2 -- 1 file changed, 2 deletions(-) diff --git a/MAINTAINERS b/MAINTAINERS index aea47e04c3a5..c45e2c3f6ff9 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -4869,7 +4869,6 @@ F: drivers/power/supply/cw2015_battery.c CEPH COMMON CODE (LIBCEPH) M: Ilya Dryomov M: Xiubo Li -R: Jeff Layton L: ceph-devel@vger.kernel.org S: Supported W: http://ceph.com/ @@ -4881,7 +4880,6 @@ F: net/ceph/ CEPH DISTRIBUTED FILE SYSTEM CLIENT (CEPH) M: Xiubo Li M: Ilya Dryomov -R: Jeff Layton L: ceph-devel@vger.kernel.org S: Supported W: http://ceph.com/ -- cgit v1.2.3 From 28e0947651ce6a2200b9a7eceb93282e97d7e51a Mon Sep 17 00:00:00 2001 From: Steve French Date: Sat, 6 Apr 2024 23:16:08 -0500 Subject: smb3: fix Open files on server counter going negative We were decrementing the count of open files on server twice for the case where we were closing cached directories. Fixes: 8e843bf38f7b ("cifs: return a single-use cfid if we did not get a lease") Cc: stable@vger.kernel.org Acked-by: Bharath SM Signed-off-by: Steve French --- fs/smb/client/cached_dir.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/fs/smb/client/cached_dir.c b/fs/smb/client/cached_dir.c index 13a9d7acf8f8..0ff2491c311d 100644 --- a/fs/smb/client/cached_dir.c +++ b/fs/smb/client/cached_dir.c @@ -433,8 +433,8 @@ smb2_close_cached_fid(struct kref *ref) if (cfid->is_open) { rc = SMB2_close(0, cfid->tcon, cfid->fid.persistent_fid, cfid->fid.volatile_fid); - if (rc != -EBUSY && rc != -EAGAIN) - atomic_dec(&cfid->tcon->num_remote_opens); + if (rc) /* should we retry on -EBUSY or -EAGAIN? */ + cifs_dbg(VFS, "close cached dir rc %d\n", rc); } free_cached_dir(cfid); -- cgit v1.2.3 From c6ff459037b2e35450af2351037eac4c8aca1d6b Mon Sep 17 00:00:00 2001 From: Paulo Alcantara Date: Tue, 9 Apr 2024 11:28:59 -0300 Subject: smb: client: instantiate when creating SFU files In cifs_sfu_make_node(), on success, instantiate rather than leave it with dentry unhashed negative to support callers that expect mknod(2) to always instantiate. This fixes the following test case: mount.cifs //srv/share /mnt -o ...,sfu mkfifo /mnt/fifo ./xfstests/ltp/growfiles -b -W test -e 1 -u -i 0 -L 30 /mnt/fifo ... BUG: unable to handle page fault for address: 000000034cec4e58 #PF: supervisor read access in kernel mode #PF: error_code(0x0000) - not-present page PGD 0 P4D 0 Oops: 0000 1 PREEMPT SMP PTI CPU: 0 PID: 138098 Comm: growfiles Kdump: loaded Not tainted 5.14.0-436.3987_1240945149.el9.x86_64 #1 Hardware name: Red Hat KVM, BIOS 0.5.1 01/01/2011 RIP: 0010:_raw_callee_save__kvm_vcpu_is_preempted+0x0/0x20 Code: e8 15 d9 61 00 e9 63 ff ff ff 41 bd ea ff ff ff e9 58 ff ff ff e8 d0 71 c0 00 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 <48> 8b 04 fd 60 2b c1 99 80 b8 90 50 03 00 00 0f 95 c0 c3 cc cc cc RSP: 0018:ffffb6a143cf7cf8 EFLAGS: 00010206 RAX: ffff8a9bc30fb038 RBX: ffff8a9bc666a200 RCX: ffff8a9cc0260000 RDX: 00000000736f622e RSI: ffff8a9bc30fb038 RDI: 000000007665645f RBP: ffffb6a143cf7d70 R08: 0000000000001000 R09: 0000000000000001 R10: 0000000000000001 R11: 0000000000000000 R12: ffff8a9bc666a200 R13: 0000559a302a12b0 R14: 0000000000001000 R15: 0000000000000000 FS: 00007fbed1dbb740(0000) GS:ffff8a9cf0000000(0000) knlGS:0000000000000000 CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 CR2: 000000034cec4e58 CR3: 0000000128ec6006 CR4: 0000000000770ef0 DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400 PKRU: 55555554 Call Trace: ? show_trace_log_lvl+0x1c4/0x2df ? show_trace_log_lvl+0x1c4/0x2df ? __mutex_lock.constprop.0+0x5f7/0x6a0 ? __die_body.cold+0x8/0xd ? page_fault_oops+0x134/0x170 ? exc_page_fault+0x62/0x150 ? asm_exc_page_fault+0x22/0x30 ? _pfx_raw_callee_save__kvm_vcpu_is_preempted+0x10/0x10 __mutex_lock.constprop.0+0x5f7/0x6a0 ? __mod_memcg_lruvec_state+0x84/0xd0 pipe_write+0x47/0x650 ? do_anonymous_page+0x258/0x410 ? inode_security+0x22/0x60 ? selinux_file_permission+0x108/0x150 vfs_write+0x2cb/0x410 ksys_write+0x5f/0xe0 do_syscall_64+0x5c/0xf0 ? syscall_exit_to_user_mode+0x22/0x40 ? do_syscall_64+0x6b/0xf0 ? sched_clock_cpu+0x9/0xc0 ? exc_page_fault+0x62/0x150 entry_SYSCALL_64_after_hwframe+0x6e/0x76 Cc: stable@vger.kernel.org Fixes: 72bc63f5e23a ("smb3: fix creating FIFOs when mounting with "sfu" mount option") Suggested-by: Al Viro Signed-off-by: Paulo Alcantara (Red Hat) Signed-off-by: Steve French --- fs/smb/client/smb2ops.c | 94 +++++++++++++++++++++++++++++-------------------- 1 file changed, 55 insertions(+), 39 deletions(-) diff --git a/fs/smb/client/smb2ops.c b/fs/smb/client/smb2ops.c index b156eefa75d7..78c94d0350fe 100644 --- a/fs/smb/client/smb2ops.c +++ b/fs/smb/client/smb2ops.c @@ -4964,68 +4964,84 @@ static int smb2_next_header(struct TCP_Server_Info *server, char *buf, return 0; } -int cifs_sfu_make_node(unsigned int xid, struct inode *inode, - struct dentry *dentry, struct cifs_tcon *tcon, - const char *full_path, umode_t mode, dev_t dev) +static int __cifs_sfu_make_node(unsigned int xid, struct inode *inode, + struct dentry *dentry, struct cifs_tcon *tcon, + const char *full_path, umode_t mode, dev_t dev) { - struct cifs_open_info_data buf = {}; struct TCP_Server_Info *server = tcon->ses->server; struct cifs_open_parms oparms; struct cifs_io_parms io_parms = {}; struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb); struct cifs_fid fid; unsigned int bytes_written; - struct win_dev *pdev; + struct win_dev pdev = {}; struct kvec iov[2]; __u32 oplock = server->oplocks ? REQ_OPLOCK : 0; int rc; - if (!S_ISCHR(mode) && !S_ISBLK(mode) && !S_ISFIFO(mode)) + switch (mode & S_IFMT) { + case S_IFCHR: + strscpy(pdev.type, "IntxCHR"); + pdev.major = cpu_to_le64(MAJOR(dev)); + pdev.minor = cpu_to_le64(MINOR(dev)); + break; + case S_IFBLK: + strscpy(pdev.type, "IntxBLK"); + pdev.major = cpu_to_le64(MAJOR(dev)); + pdev.minor = cpu_to_le64(MINOR(dev)); + break; + case S_IFIFO: + strscpy(pdev.type, "LnxFIFO"); + break; + default: return -EPERM; + } - oparms = (struct cifs_open_parms) { - .tcon = tcon, - .cifs_sb = cifs_sb, - .desired_access = GENERIC_WRITE, - .create_options = cifs_create_options(cifs_sb, CREATE_NOT_DIR | - CREATE_OPTION_SPECIAL), - .disposition = FILE_CREATE, - .path = full_path, - .fid = &fid, - }; + oparms = CIFS_OPARMS(cifs_sb, tcon, full_path, GENERIC_WRITE, + FILE_CREATE, CREATE_NOT_DIR | + CREATE_OPTION_SPECIAL, ACL_NO_MODE); + oparms.fid = &fid; - rc = server->ops->open(xid, &oparms, &oplock, &buf); + rc = server->ops->open(xid, &oparms, &oplock, NULL); if (rc) return rc; - /* - * BB Do not bother to decode buf since no local inode yet to put - * timestamps in, but we can reuse it safely. - */ - pdev = (struct win_dev *)&buf.fi; io_parms.pid = current->tgid; io_parms.tcon = tcon; - io_parms.length = sizeof(*pdev); - iov[1].iov_base = pdev; - iov[1].iov_len = sizeof(*pdev); - if (S_ISCHR(mode)) { - memcpy(pdev->type, "IntxCHR", 8); - pdev->major = cpu_to_le64(MAJOR(dev)); - pdev->minor = cpu_to_le64(MINOR(dev)); - } else if (S_ISBLK(mode)) { - memcpy(pdev->type, "IntxBLK", 8); - pdev->major = cpu_to_le64(MAJOR(dev)); - pdev->minor = cpu_to_le64(MINOR(dev)); - } else if (S_ISFIFO(mode)) { - memcpy(pdev->type, "LnxFIFO", 8); - } + io_parms.length = sizeof(pdev); + iov[1].iov_base = &pdev; + iov[1].iov_len = sizeof(pdev); rc = server->ops->sync_write(xid, &fid, &io_parms, &bytes_written, iov, 1); server->ops->close(xid, tcon, &fid); - d_drop(dentry); - /* FIXME: add code here to set EAs */ - cifs_free_open_info(&buf); + return rc; +} + +int cifs_sfu_make_node(unsigned int xid, struct inode *inode, + struct dentry *dentry, struct cifs_tcon *tcon, + const char *full_path, umode_t mode, dev_t dev) +{ + struct inode *new = NULL; + int rc; + + rc = __cifs_sfu_make_node(xid, inode, dentry, tcon, + full_path, mode, dev); + if (rc) + return rc; + + if (tcon->posix_extensions) { + rc = smb311_posix_get_inode_info(&new, full_path, NULL, + inode->i_sb, xid); + } else if (tcon->unix_ext) { + rc = cifs_get_inode_info_unix(&new, full_path, + inode->i_sb, xid); + } else { + rc = cifs_get_inode_info(&new, full_path, NULL, + inode->i_sb, xid, NULL); + } + if (!rc) + d_instantiate(dentry, new); return rc; } -- cgit v1.2.3 From 35f834265e0dc78b003aa0d1af65cafb89666b76 Mon Sep 17 00:00:00 2001 From: Steve French Date: Thu, 4 Apr 2024 18:06:56 -0500 Subject: smb3: fix broken reconnect when password changing on the server by allowing password rotation There are various use cases that are becoming more common in which password changes are scheduled on a server(s) periodically but the clients connected to this server need to stay connected (even in the face of brief network reconnects) due to mounts which can not be easily unmounted and mounted at will, and servers that do password rotation do not always have the ability to tell the clients exactly when to the new password will be effective, so add support for an alt password ("password2=") on mount (and also remount) so that we can anticipate the upcoming change to the server without risking breaking existing mounts. An alternative would have been to use the kernel keyring for this but the processes doing the reconnect do not have access to the keyring but do have access to the ses structure. Reviewed-by: Bharath SM Signed-off-by: Steve French --- fs/smb/client/cifsglob.h | 1 + fs/smb/client/connect.c | 8 ++++++++ fs/smb/client/fs_context.c | 21 +++++++++++++++++++++ fs/smb/client/fs_context.h | 2 ++ fs/smb/client/misc.c | 1 + fs/smb/client/smb2pdu.c | 11 +++++++++++ 6 files changed, 44 insertions(+) diff --git a/fs/smb/client/cifsglob.h b/fs/smb/client/cifsglob.h index f6a302205f89..d6669ce4ae87 100644 --- a/fs/smb/client/cifsglob.h +++ b/fs/smb/client/cifsglob.h @@ -1077,6 +1077,7 @@ struct cifs_ses { and after mount option parsing we fill it */ char *domainName; char *password; + char *password2; /* When key rotation used, new password may be set before it expires */ char workstation_name[CIFS_MAX_WORKSTATION_LEN]; struct session_key auth_key; struct ntlmssp_auth *ntlmssp; /* ciphertext, flags, server challenge */ diff --git a/fs/smb/client/connect.c b/fs/smb/client/connect.c index 85679ae106fd..4e35970681bf 100644 --- a/fs/smb/client/connect.c +++ b/fs/smb/client/connect.c @@ -2183,6 +2183,7 @@ cifs_set_cifscreds(struct smb3_fs_context *ctx, struct cifs_ses *ses) } ++delim; + /* BB consider adding support for password2 (Key Rotation) for multiuser in future */ ctx->password = kstrndup(delim, len, GFP_KERNEL); if (!ctx->password) { cifs_dbg(FYI, "Unable to allocate %zd bytes for password\n", @@ -2206,6 +2207,7 @@ cifs_set_cifscreds(struct smb3_fs_context *ctx, struct cifs_ses *ses) kfree(ctx->username); ctx->username = NULL; kfree_sensitive(ctx->password); + /* no need to free ctx->password2 since not allocated in this path */ ctx->password = NULL; goto out_key_put; } @@ -2317,6 +2319,12 @@ cifs_get_smb_ses(struct TCP_Server_Info *server, struct smb3_fs_context *ctx) if (!ses->password) goto get_ses_fail; } + /* ctx->password freed at unmount */ + if (ctx->password2) { + ses->password2 = kstrdup(ctx->password2, GFP_KERNEL); + if (!ses->password2) + goto get_ses_fail; + } if (ctx->domainname) { ses->domainName = kstrdup(ctx->domainname, GFP_KERNEL); if (!ses->domainName) diff --git a/fs/smb/client/fs_context.c b/fs/smb/client/fs_context.c index b7bfe705b2c4..6c727d8c31e8 100644 --- a/fs/smb/client/fs_context.c +++ b/fs/smb/client/fs_context.c @@ -162,6 +162,7 @@ const struct fs_parameter_spec smb3_fs_parameters[] = { fsparam_string("username", Opt_user), fsparam_string("pass", Opt_pass), fsparam_string("password", Opt_pass), + fsparam_string("password2", Opt_pass2), fsparam_string("ip", Opt_ip), fsparam_string("addr", Opt_ip), fsparam_string("domain", Opt_domain), @@ -345,6 +346,7 @@ smb3_fs_context_dup(struct smb3_fs_context *new_ctx, struct smb3_fs_context *ctx new_ctx->nodename = NULL; new_ctx->username = NULL; new_ctx->password = NULL; + new_ctx->password2 = NULL; new_ctx->server_hostname = NULL; new_ctx->domainname = NULL; new_ctx->UNC = NULL; @@ -357,6 +359,7 @@ smb3_fs_context_dup(struct smb3_fs_context *new_ctx, struct smb3_fs_context *ctx DUP_CTX_STR(prepath); DUP_CTX_STR(username); DUP_CTX_STR(password); + DUP_CTX_STR(password2); DUP_CTX_STR(server_hostname); DUP_CTX_STR(UNC); DUP_CTX_STR(source); @@ -905,6 +908,8 @@ static int smb3_reconfigure(struct fs_context *fc) else { kfree_sensitive(ses->password); ses->password = kstrdup(ctx->password, GFP_KERNEL); + kfree_sensitive(ses->password2); + ses->password2 = kstrdup(ctx->password2, GFP_KERNEL); } STEAL_STRING(cifs_sb, ctx, domainname); STEAL_STRING(cifs_sb, ctx, nodename); @@ -1305,6 +1310,18 @@ static int smb3_fs_context_parse_param(struct fs_context *fc, goto cifs_parse_mount_err; } break; + case Opt_pass2: + kfree_sensitive(ctx->password2); + ctx->password2 = NULL; + if (strlen(param->string) == 0) + break; + + ctx->password2 = kstrdup(param->string, GFP_KERNEL); + if (ctx->password2 == NULL) { + cifs_errorf(fc, "OOM when copying password2 string\n"); + goto cifs_parse_mount_err; + } + break; case Opt_ip: if (strlen(param->string) == 0) { ctx->got_ip = false; @@ -1608,6 +1625,8 @@ static int smb3_fs_context_parse_param(struct fs_context *fc, cifs_parse_mount_err: kfree_sensitive(ctx->password); ctx->password = NULL; + kfree_sensitive(ctx->password2); + ctx->password2 = NULL; return -EINVAL; } @@ -1713,6 +1732,8 @@ smb3_cleanup_fs_context_contents(struct smb3_fs_context *ctx) ctx->username = NULL; kfree_sensitive(ctx->password); ctx->password = NULL; + kfree_sensitive(ctx->password2); + ctx->password2 = NULL; kfree(ctx->server_hostname); ctx->server_hostname = NULL; kfree(ctx->UNC); diff --git a/fs/smb/client/fs_context.h b/fs/smb/client/fs_context.h index 8a35645e0b65..a947bddeba27 100644 --- a/fs/smb/client/fs_context.h +++ b/fs/smb/client/fs_context.h @@ -145,6 +145,7 @@ enum cifs_param { Opt_source, Opt_user, Opt_pass, + Opt_pass2, Opt_ip, Opt_domain, Opt_srcaddr, @@ -177,6 +178,7 @@ struct smb3_fs_context { char *username; char *password; + char *password2; char *domainname; char *source; char *server_hostname; diff --git a/fs/smb/client/misc.c b/fs/smb/client/misc.c index 33ac4f8f5050..7d15a1969b81 100644 --- a/fs/smb/client/misc.c +++ b/fs/smb/client/misc.c @@ -98,6 +98,7 @@ sesInfoFree(struct cifs_ses *buf_to_free) kfree(buf_to_free->serverDomain); kfree(buf_to_free->serverNOS); kfree_sensitive(buf_to_free->password); + kfree_sensitive(buf_to_free->password2); kfree(buf_to_free->user_name); kfree(buf_to_free->domainName); kfree_sensitive(buf_to_free->auth_key.response); diff --git a/fs/smb/client/smb2pdu.c b/fs/smb/client/smb2pdu.c index c0c4933af5fc..86c647a947cc 100644 --- a/fs/smb/client/smb2pdu.c +++ b/fs/smb/client/smb2pdu.c @@ -367,6 +367,17 @@ again: } rc = cifs_setup_session(0, ses, server, nls_codepage); + if ((rc == -EACCES) || (rc == -EKEYEXPIRED) || (rc == -EKEYREVOKED)) { + /* + * Try alternate password for next reconnect (key rotation + * could be enabled on the server e.g.) if an alternate + * password is available and the current password is expired, + * but do not swap on non pwd related errors like host down + */ + if (ses->password2) + swap(ses->password2, ses->password); + } + if ((rc == -EACCES) && !tcon->retry) { mutex_unlock(&ses->session_mutex); rc = -EHOSTDOWN; -- cgit v1.2.3 From a8fa658eebe8b17fc852482da52f8841be8931d6 Mon Sep 17 00:00:00 2001 From: Yang Li Date: Fri, 22 Mar 2024 14:26:04 +0800 Subject: eventfs: Fix kernel-doc comments to functions This commit fix kernel-doc style comments with complete parameter descriptions for the lookup_file(),lookup_dir_entry() and lookup_file_dentry(). Link: https://lore.kernel.org/linux-trace-kernel/20240322062604.28862-1-yang.lee@linux.alibaba.com Signed-off-by: Yang Li Signed-off-by: Steven Rostedt (Google) --- fs/tracefs/event_inode.c | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/fs/tracefs/event_inode.c b/fs/tracefs/event_inode.c index dc067eeb6387..894c6ca1e500 100644 --- a/fs/tracefs/event_inode.c +++ b/fs/tracefs/event_inode.c @@ -336,6 +336,7 @@ static void update_inode_attr(struct dentry *dentry, struct inode *inode, /** * lookup_file - look up a file in the tracefs filesystem + * @parent_ei: Pointer to the eventfs_inode that represents parent of the file * @dentry: the dentry to look up * @mode: the permission that the file should have. * @attr: saved attributes changed by user @@ -389,6 +390,7 @@ static struct dentry *lookup_file(struct eventfs_inode *parent_ei, /** * lookup_dir_entry - look up a dir in the tracefs filesystem * @dentry: the directory to look up + * @pei: Pointer to the parent eventfs_inode if available * @ei: the eventfs_inode that represents the directory to create * * This function will look up a dentry for a directory represented by @@ -478,16 +480,20 @@ void eventfs_d_release(struct dentry *dentry) /** * lookup_file_dentry - create a dentry for a file of an eventfs_inode + * @dentry: The parent dentry under which the new file's dentry will be created * @ei: the eventfs_inode that the file will be created under * @idx: the index into the entry_attrs[] of the @ei - * @parent: The parent dentry of the created file. - * @name: The name of the file to create * @mode: The mode of the file. * @data: The data to use to set the inode of the file with on open() * @fops: The fops of the file to be created. * - * Create a dentry for a file of an eventfs_inode @ei and place it into the - * address located at @e_dentry. + * This function creates a dentry for a file associated with an + * eventfs_inode @ei. It uses the entry attributes specified by @idx, + * if available. The file will have the specified @mode and its inode will be + * set up with @data upon open. The file operations will be set to @fops. + * + * Return: Returns a pointer to the newly created file's dentry or an error + * pointer. */ static struct dentry * lookup_file_dentry(struct dentry *dentry, -- cgit v1.2.3 From d96c36004e31e2baaf8ea1b449b7d0b2c2bfb41a Mon Sep 17 00:00:00 2001 From: Prasad Pandit Date: Fri, 22 Mar 2024 17:48:01 +0530 Subject: tracing: Fix FTRACE_RECORD_RECURSION_SIZE Kconfig entry Fix FTRACE_RECORD_RECURSION_SIZE entry, replace tab with a space character. It helps Kconfig parsers to read file without error. Link: https://lore.kernel.org/linux-trace-kernel/20240322121801.1803948-1-ppandit@redhat.com Cc: Masami Hiramatsu Cc: Mathieu Desnoyers Fixes: 773c16705058 ("ftrace: Add recording of functions that caused recursion") Signed-off-by: Prasad Pandit Reviewed-by: Randy Dunlap Signed-off-by: Steven Rostedt (Google) --- kernel/trace/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kernel/trace/Kconfig b/kernel/trace/Kconfig index 61c541c36596..47345bf1d4a9 100644 --- a/kernel/trace/Kconfig +++ b/kernel/trace/Kconfig @@ -965,7 +965,7 @@ config FTRACE_RECORD_RECURSION config FTRACE_RECORD_RECURSION_SIZE int "Max number of recursed functions to record" - default 128 + default 128 depends on FTRACE_RECORD_RECURSION help This defines the limit of number of functions that can be -- cgit v1.2.3 From 5281ec83454d70d98b71f1836fb16512566c01cd Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Wed, 3 Apr 2024 10:06:24 +0200 Subject: tracing: hide unused ftrace_event_id_fops MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When CONFIG_PERF_EVENTS, a 'make W=1' build produces a warning about the unused ftrace_event_id_fops variable: kernel/trace/trace_events.c:2155:37: error: 'ftrace_event_id_fops' defined but not used [-Werror=unused-const-variable=] 2155 | static const struct file_operations ftrace_event_id_fops = { Hide this in the same #ifdef as the reference to it. Link: https://lore.kernel.org/linux-trace-kernel/20240403080702.3509288-7-arnd@kernel.org Cc: Masami Hiramatsu Cc: Oleg Nesterov Cc: Mathieu Desnoyers Cc: Zheng Yejian Cc: Kees Cook Cc: Ajay Kaher Cc: Jinjie Ruan Cc: Clément Léger Cc: Dan Carpenter Cc: "Tzvetomir Stoyanov (VMware)" Fixes: 620a30e97feb ("tracing: Don't pass file_operations array to event_create_dir()") Signed-off-by: Arnd Bergmann Signed-off-by: Steven Rostedt (Google) --- kernel/trace/trace_events.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/kernel/trace/trace_events.c b/kernel/trace/trace_events.c index 7c364b87352e..52f75c36bbca 100644 --- a/kernel/trace/trace_events.c +++ b/kernel/trace/trace_events.c @@ -1670,6 +1670,7 @@ static int trace_format_open(struct inode *inode, struct file *file) return 0; } +#ifdef CONFIG_PERF_EVENTS static ssize_t event_id_read(struct file *filp, char __user *ubuf, size_t cnt, loff_t *ppos) { @@ -1684,6 +1685,7 @@ event_id_read(struct file *filp, char __user *ubuf, size_t cnt, loff_t *ppos) return simple_read_from_buffer(ubuf, cnt, ppos, buf, len); } +#endif static ssize_t event_filter_read(struct file *filp, char __user *ubuf, size_t cnt, @@ -2152,10 +2154,12 @@ static const struct file_operations ftrace_event_format_fops = { .release = seq_release, }; +#ifdef CONFIG_PERF_EVENTS static const struct file_operations ftrace_event_id_fops = { .read = event_id_read, .llseek = default_llseek, }; +#endif static const struct file_operations ftrace_event_filter_fops = { .open = tracing_open_file_tr, -- cgit v1.2.3 From ffe3986fece696cf65e0ef99e74c75f848be8e30 Mon Sep 17 00:00:00 2001 From: "Steven Rostedt (Google)" Date: Tue, 9 Apr 2024 15:13:09 -0400 Subject: ring-buffer: Only update pages_touched when a new page is touched The "buffer_percent" logic that is used by the ring buffer splice code to only wake up the tasks when there's no data after the buffer is filled to the percentage of the "buffer_percent" file is dependent on three variables that determine the amount of data that is in the ring buffer: 1) pages_read - incremented whenever a new sub-buffer is consumed 2) pages_lost - incremented every time a writer overwrites a sub-buffer 3) pages_touched - incremented when a write goes to a new sub-buffer The percentage is the calculation of: (pages_touched - (pages_lost + pages_read)) / nr_pages Basically, the amount of data is the total number of sub-bufs that have been touched, minus the number of sub-bufs lost and sub-bufs consumed. This is divided by the total count to give the buffer percentage. When the percentage is greater than the value in the "buffer_percent" file, it wakes up splice readers waiting for that amount. It was observed that over time, the amount read from the splice was constantly decreasing the longer the trace was running. That is, if one asked for 60%, it would read over 60% when it first starts tracing, but then it would be woken up at under 60% and would slowly decrease the amount of data read after being woken up, where the amount becomes much less than the buffer percent. This was due to an accounting of the pages_touched incrementation. This value is incremented whenever a writer transfers to a new sub-buffer. But the place where it was incremented was incorrect. If a writer overflowed the current sub-buffer it would go to the next one. If it gets preempted by an interrupt at that time, and the interrupt performs a trace, it too will end up going to the next sub-buffer. But only one should increment the counter. Unfortunately, that was not the case. Change the cmpxchg() that does the real switch of the tail-page into a try_cmpxchg(), and on success, perform the increment of pages_touched. This will only increment the counter once for when the writer moves to a new sub-buffer, and not when there's a race and is incremented for when a writer and its preempting writer both move to the same new sub-buffer. Link: https://lore.kernel.org/linux-trace-kernel/20240409151309.0d0e5056@gandalf.local.home Cc: stable@vger.kernel.org Cc: Mathieu Desnoyers Fixes: 2c2b0a78b3739 ("ring-buffer: Add percentage of ring buffer full to wake up reader") Acked-by: Masami Hiramatsu (Google) Signed-off-by: Steven Rostedt (Google) --- kernel/trace/ring_buffer.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/kernel/trace/ring_buffer.c b/kernel/trace/ring_buffer.c index 25476ead681b..6511dc3a00da 100644 --- a/kernel/trace/ring_buffer.c +++ b/kernel/trace/ring_buffer.c @@ -1393,7 +1393,6 @@ static void rb_tail_page_update(struct ring_buffer_per_cpu *cpu_buffer, old_write = local_add_return(RB_WRITE_INTCNT, &next_page->write); old_entries = local_add_return(RB_WRITE_INTCNT, &next_page->entries); - local_inc(&cpu_buffer->pages_touched); /* * Just make sure we have seen our old_write and synchronize * with any interrupts that come in. @@ -1430,8 +1429,9 @@ static void rb_tail_page_update(struct ring_buffer_per_cpu *cpu_buffer, */ local_set(&next_page->page->commit, 0); - /* Again, either we update tail_page or an interrupt does */ - (void)cmpxchg(&cpu_buffer->tail_page, tail_page, next_page); + /* Either we update tail_page or an interrupt does */ + if (try_cmpxchg(&cpu_buffer->tail_page, &tail_page, next_page)) + local_inc(&cpu_buffer->pages_touched); } } -- cgit v1.2.3 From 62bef5df35a87d0f8464b1a8837540988cfaf5db Mon Sep 17 00:00:00 2001 From: Shengjiu Wang Date: Thu, 11 Apr 2024 18:11:44 +0800 Subject: ASoC: dt-bindings: imx-audio-spdif: convert to YAML Convert the imx-audio-spdif binding to YAML. When testing dtbs_check, found below compatible strings are not listed in document: fsl,imx-sabreauto-spdif fsl,imx6sx-sdb-spdif So add them in yaml file to pass the test. Signed-off-by: Shengjiu Wang Reviewed-by: Krzysztof Kozlowski Link: https://msgid.link/r/1712830305-31350-2-git-send-email-shengjiu.wang@nxp.com Signed-off-by: Mark Brown --- .../bindings/sound/fsl,imx-audio-spdif.yaml | 66 ++++++++++++++++++++++ .../devicetree/bindings/sound/imx-audio-spdif.txt | 36 ------------ 2 files changed, 66 insertions(+), 36 deletions(-) create mode 100644 Documentation/devicetree/bindings/sound/fsl,imx-audio-spdif.yaml delete mode 100644 Documentation/devicetree/bindings/sound/imx-audio-spdif.txt diff --git a/Documentation/devicetree/bindings/sound/fsl,imx-audio-spdif.yaml b/Documentation/devicetree/bindings/sound/fsl,imx-audio-spdif.yaml new file mode 100644 index 000000000000..5fc543d02ecb --- /dev/null +++ b/Documentation/devicetree/bindings/sound/fsl,imx-audio-spdif.yaml @@ -0,0 +1,66 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/sound/fsl,imx-audio-spdif.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Freescale i.MX audio complex with S/PDIF transceiver + +maintainers: + - Shengjiu Wang + +properties: + compatible: + oneOf: + - items: + - enum: + - fsl,imx-sabreauto-spdif + - fsl,imx6sx-sdb-spdif + - const: fsl,imx-audio-spdif + - enum: + - fsl,imx-audio-spdif + + model: + $ref: /schemas/types.yaml#/definitions/string + description: User specified audio sound card name + + spdif-controller: + $ref: /schemas/types.yaml#/definitions/phandle + description: The phandle of the i.MX S/PDIF controller + + spdif-out: + type: boolean + description: + If present, the transmitting function of S/PDIF will be enabled, + indicating there's a physical S/PDIF out connector or jack on the + board or it's connecting to some other IP block, such as an HDMI + encoder or display-controller. + + spdif-in: + type: boolean + description: + If present, the receiving function of S/PDIF will be enabled, + indicating there is a physical S/PDIF in connector/jack on the board. + +required: + - compatible + - model + - spdif-controller + +anyOf: + - required: + - spdif-in + - required: + - spdif-out + +additionalProperties: false + +examples: + - | + sound-spdif { + compatible = "fsl,imx-audio-spdif"; + model = "imx-spdif"; + spdif-controller = <&spdif>; + spdif-out; + spdif-in; + }; diff --git a/Documentation/devicetree/bindings/sound/imx-audio-spdif.txt b/Documentation/devicetree/bindings/sound/imx-audio-spdif.txt deleted file mode 100644 index da84a442ccea..000000000000 --- a/Documentation/devicetree/bindings/sound/imx-audio-spdif.txt +++ /dev/null @@ -1,36 +0,0 @@ -Freescale i.MX audio complex with S/PDIF transceiver - -Required properties: - - - compatible : "fsl,imx-audio-spdif" - - - model : The user-visible name of this sound complex - - - spdif-controller : The phandle of the i.MX S/PDIF controller - - -Optional properties: - - - spdif-out : This is a boolean property. If present, the - transmitting function of S/PDIF will be enabled, - indicating there's a physical S/PDIF out connector - or jack on the board or it's connecting to some - other IP block, such as an HDMI encoder or - display-controller. - - - spdif-in : This is a boolean property. If present, the receiving - function of S/PDIF will be enabled, indicating there - is a physical S/PDIF in connector/jack on the board. - -* Note: At least one of these two properties should be set in the DT binding. - - -Example: - -sound-spdif { - compatible = "fsl,imx-audio-spdif"; - model = "imx-spdif"; - spdif-controller = <&spdif>; - spdif-out; - spdif-in; -}; -- cgit v1.2.3 From 824f06ff81464f823cd6259ff2ec8fbeceb2afa5 Mon Sep 17 00:00:00 2001 From: Eric Van Hensbergen Date: Thu, 11 Apr 2024 23:36:33 +0000 Subject: fs/9p: Revert "fs/9p: fix dups even in uncached mode" This reverts commit be57855f505003c5cafff40338d5d0f23b00ba4d. It caused a regression involving duplicate inode numbers in some tester trees. The bad behavior seems to be dependent on inode reuse policy in underlying file system, so it did not trigger in my test setup. Signed-off-by: Eric Van Hensbergen --- fs/9p/vfs_super.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/fs/9p/vfs_super.c b/fs/9p/vfs_super.c index 4236058c7bbd..eeac06c2a84c 100644 --- a/fs/9p/vfs_super.c +++ b/fs/9p/vfs_super.c @@ -244,6 +244,21 @@ done: return res; } +static int v9fs_drop_inode(struct inode *inode) +{ + struct v9fs_session_info *v9ses; + + v9ses = v9fs_inode2v9ses(inode); + if (v9ses->cache & (CACHE_META|CACHE_LOOSE)) + return generic_drop_inode(inode); + /* + * in case of non cached mode always drop the + * inode because we want the inode attribute + * to always match that on the server. + */ + return 1; +} + static int v9fs_write_inode(struct inode *inode, struct writeback_control *wbc) { @@ -278,6 +293,7 @@ static const struct super_operations v9fs_super_ops_dotl = { .alloc_inode = v9fs_alloc_inode, .free_inode = v9fs_free_inode, .statfs = v9fs_statfs, + .drop_inode = v9fs_drop_inode, .evict_inode = v9fs_evict_inode, .show_options = v9fs_show_options, .umount_begin = v9fs_umount_begin, -- cgit v1.2.3 From 7fd524b9bd1be210fe79035800f4bd78a41b349f Mon Sep 17 00:00:00 2001 From: Joakim Sindholt Date: Mon, 18 Mar 2024 12:22:32 +0100 Subject: fs/9p: drop inodes immediately on non-.L too Signed-off-by: Joakim Sindholt Signed-off-by: Eric Van Hensbergen --- fs/9p/vfs_super.c | 1 + 1 file changed, 1 insertion(+) diff --git a/fs/9p/vfs_super.c b/fs/9p/vfs_super.c index eeac06c2a84c..55e67e36ae68 100644 --- a/fs/9p/vfs_super.c +++ b/fs/9p/vfs_super.c @@ -283,6 +283,7 @@ static const struct super_operations v9fs_super_ops = { .alloc_inode = v9fs_alloc_inode, .free_inode = v9fs_free_inode, .statfs = simple_statfs, + .drop_inode = v9fs_drop_inode, .evict_inode = v9fs_evict_inode, .show_options = v9fs_show_options, .umount_begin = v9fs_umount_begin, -- cgit v1.2.3 From 3b0daecfeac0103aba8b293df07a0cbaf8b43f29 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Fri, 12 Apr 2024 06:11:25 +1000 Subject: amdkfd: use calloc instead of kzalloc to avoid integer overflow This uses calloc instead of doing the multiplication which might overflow. Cc: stable@vger.kernel.org Signed-off-by: Dave Airlie --- drivers/gpu/drm/amd/amdkfd/kfd_chardev.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c b/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c index f9631f4b1a02..55aa74cbc532 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c @@ -779,8 +779,8 @@ static int kfd_ioctl_get_process_apertures_new(struct file *filp, * nodes, but not more than args->num_of_nodes as that is * the amount of memory allocated by user */ - pa = kzalloc((sizeof(struct kfd_process_device_apertures) * - args->num_of_nodes), GFP_KERNEL); + pa = kcalloc(args->num_of_nodes, sizeof(struct kfd_process_device_apertures), + GFP_KERNEL); if (!pa) return -ENOMEM; -- cgit v1.2.3 From 2b3e79fea66e166622a454715ce981432ac8c6e3 Mon Sep 17 00:00:00 2001 From: Kent Overstreet Date: Thu, 11 Apr 2024 01:01:11 -0400 Subject: bcachefs: Don't use bch2_btree_node_lock_write_nofail() in btree split path It turns out - btree splits happen with the rest of the transaction still locked, to avoid unnecessary restarts, which means using nofail doesn't work here - we can deadlock. Fortunately, we now have the ability to return errors here. Signed-off-by: Kent Overstreet --- fs/bcachefs/btree_update_interior.c | 41 +++++++++++++++++++++++-------------- 1 file changed, 26 insertions(+), 15 deletions(-) diff --git a/fs/bcachefs/btree_update_interior.c b/fs/bcachefs/btree_update_interior.c index c4a5e83a56a4..29a5bc7d8789 100644 --- a/fs/bcachefs/btree_update_interior.c +++ b/fs/bcachefs/btree_update_interior.c @@ -1280,23 +1280,29 @@ static void bch2_btree_set_root_inmem(struct bch_fs *c, struct btree *b) bch2_recalc_btree_reserve(c); } -static void bch2_btree_set_root(struct btree_update *as, - struct btree_trans *trans, - struct btree_path *path, - struct btree *b) +static int bch2_btree_set_root(struct btree_update *as, + struct btree_trans *trans, + struct btree_path *path, + struct btree *b, + bool nofail) { struct bch_fs *c = as->c; - struct btree *old; trace_and_count(c, btree_node_set_root, trans, b); - old = btree_node_root(c, b); + struct btree *old = btree_node_root(c, b); /* * Ensure no one is using the old root while we switch to the * new root: */ - bch2_btree_node_lock_write_nofail(trans, path, &old->c); + if (nofail) { + bch2_btree_node_lock_write_nofail(trans, path, &old->c); + } else { + int ret = bch2_btree_node_lock_write(trans, path, &old->c); + if (ret) + return ret; + } bch2_btree_set_root_inmem(c, b); @@ -1310,6 +1316,7 @@ static void bch2_btree_set_root(struct btree_update *as, * depend on the new root would have to update the new root. */ bch2_btree_node_unlock_write(trans, path, old); + return 0; } /* Interior node updates: */ @@ -1652,15 +1659,16 @@ static int btree_split(struct btree_update *as, struct btree_trans *trans, if (parent) { /* Split a non root node */ ret = bch2_btree_insert_node(as, trans, path, parent, &as->parent_keys); - if (ret) - goto err; } else if (n3) { - bch2_btree_set_root(as, trans, trans->paths + path, n3); + ret = bch2_btree_set_root(as, trans, trans->paths + path, n3, false); } else { /* Root filled up but didn't need to be split */ - bch2_btree_set_root(as, trans, trans->paths + path, n1); + ret = bch2_btree_set_root(as, trans, trans->paths + path, n1, false); } + if (ret) + goto err; + if (n3) { bch2_btree_update_get_open_buckets(as, n3); bch2_btree_node_write(c, n3, SIX_LOCK_intent, 0); @@ -1863,7 +1871,9 @@ static void __btree_increase_depth(struct btree_update *as, struct btree_trans * bch2_keylist_add(&as->parent_keys, &b->key); btree_split_insert_keys(as, trans, path_idx, n, &as->parent_keys); - bch2_btree_set_root(as, trans, path, n); + int ret = bch2_btree_set_root(as, trans, path, n, true); + BUG_ON(ret); + bch2_btree_update_get_open_buckets(as, n); bch2_btree_node_write(c, n, SIX_LOCK_intent, 0); bch2_trans_node_add(trans, path, n); @@ -2106,12 +2116,13 @@ int bch2_btree_node_rewrite(struct btree_trans *trans, if (parent) { bch2_keylist_add(&as->parent_keys, &n->key); ret = bch2_btree_insert_node(as, trans, iter->path, parent, &as->parent_keys); - if (ret) - goto err; } else { - bch2_btree_set_root(as, trans, btree_iter_path(trans, iter), n); + ret = bch2_btree_set_root(as, trans, btree_iter_path(trans, iter), n, false); } + if (ret) + goto err; + bch2_btree_update_get_open_buckets(as, n); bch2_btree_node_write(c, n, SIX_LOCK_intent, 0); -- cgit v1.2.3 From 210cfef579260ed6c3b700e7baeae51a5e183f43 Mon Sep 17 00:00:00 2001 From: Nathan Lynch Date: Thu, 4 Apr 2024 17:02:09 -0500 Subject: selftests/powerpc/papr-vpd: Fix missing variable initialization The "close handle without consuming VPD" testcase has inconsistent results because it fails to initialize the location code object it passes to ioctl() to create a VPD handle. Initialize the location code to the empty string as intended. Signed-off-by: Nathan Lynch Fixes: 9118c5d32bdd ("powerpc/selftests: Add test for papr-vpd") Reported-by: Geetika Moolchandani Signed-off-by: Michael Ellerman Link: https://msgid.link/20240404-papr-vpd-test-uninit-lc-v2-1-37bff46c65a5@linux.ibm.com --- tools/testing/selftests/powerpc/papr_vpd/papr_vpd.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/testing/selftests/powerpc/papr_vpd/papr_vpd.c b/tools/testing/selftests/powerpc/papr_vpd/papr_vpd.c index 505294da1b9f..d6f99eb9be65 100644 --- a/tools/testing/selftests/powerpc/papr_vpd/papr_vpd.c +++ b/tools/testing/selftests/powerpc/papr_vpd/papr_vpd.c @@ -154,7 +154,7 @@ static int dev_papr_vpd_null_handle(void) static int papr_vpd_close_handle_without_reading(void) { const int devfd = open(DEVPATH, O_RDONLY); - struct papr_location_code lc; + struct papr_location_code lc = { .str = "", }; int fd; SKIP_IF_MSG(devfd < 0 && errno == ENOENT, -- cgit v1.2.3 From 84b1cec4fac5889b6d138d4b5ff6f2d5ef126c5e Mon Sep 17 00:00:00 2001 From: Vasant Hegde Date: Thu, 4 Apr 2024 10:27:17 +0000 Subject: iommu/amd: Fix possible irq lock inversion dependency issue LOCKDEP detector reported below warning: ---------------------------------------- [ 23.796949] ======================================================== [ 23.796950] WARNING: possible irq lock inversion dependency detected [ 23.796952] 6.8.0fix+ #811 Not tainted [ 23.796954] -------------------------------------------------------- [ 23.796954] kworker/0:1/8 just changed the state of lock: [ 23.796956] ff365325e084a9b8 (&domain->lock){..-.}-{3:3}, at: amd_iommu_flush_iotlb_all+0x1f/0x50 [ 23.796969] but this lock took another, SOFTIRQ-unsafe lock in the past: [ 23.796970] (pd_bitmap_lock){+.+.}-{3:3} [ 23.796972] and interrupts could create inverse lock ordering between them. [ 23.796973] other info that might help us debug this: [ 23.796974] Chain exists of: &domain->lock --> &dev_data->lock --> pd_bitmap_lock [ 23.796980] Possible interrupt unsafe locking scenario: [ 23.796981] CPU0 CPU1 [ 23.796982] ---- ---- [ 23.796983] lock(pd_bitmap_lock); [ 23.796985] local_irq_disable(); [ 23.796985] lock(&domain->lock); [ 23.796988] lock(&dev_data->lock); [ 23.796990] [ 23.796991] lock(&domain->lock); Fix this issue by disabling interrupt when acquiring pd_bitmap_lock. Note that this is temporary fix. We have a plan to replace custom bitmap allocator with IDA allocator. Fixes: 87a6f1f22c97 ("iommu/amd: Introduce per-device domain ID to fix potential TLB aliasing issue") Reviewed-by: Suravee Suthikulpanit Signed-off-by: Vasant Hegde Link: https://lore.kernel.org/r/20240404102717.6705-1-vasant.hegde@amd.com Signed-off-by: Joerg Roedel --- drivers/iommu/amd/iommu.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/drivers/iommu/amd/iommu.c b/drivers/iommu/amd/iommu.c index d35c1b8c8e65..e692217fcb28 100644 --- a/drivers/iommu/amd/iommu.c +++ b/drivers/iommu/amd/iommu.c @@ -1692,26 +1692,29 @@ int amd_iommu_complete_ppr(struct pci_dev *pdev, u32 pasid, static u16 domain_id_alloc(void) { + unsigned long flags; int id; - spin_lock(&pd_bitmap_lock); + spin_lock_irqsave(&pd_bitmap_lock, flags); id = find_first_zero_bit(amd_iommu_pd_alloc_bitmap, MAX_DOMAIN_ID); BUG_ON(id == 0); if (id > 0 && id < MAX_DOMAIN_ID) __set_bit(id, amd_iommu_pd_alloc_bitmap); else id = 0; - spin_unlock(&pd_bitmap_lock); + spin_unlock_irqrestore(&pd_bitmap_lock, flags); return id; } static void domain_id_free(int id) { - spin_lock(&pd_bitmap_lock); + unsigned long flags; + + spin_lock_irqsave(&pd_bitmap_lock, flags); if (id > 0 && id < MAX_DOMAIN_ID) __clear_bit(id, amd_iommu_pd_alloc_bitmap); - spin_unlock(&pd_bitmap_lock); + spin_unlock_irqrestore(&pd_bitmap_lock, flags); } static void free_gcr3_tbl_level1(u64 *tbl) -- cgit v1.2.3 From b650b38b006053ef96e90b8e3f7e6edc7845cd57 Mon Sep 17 00:00:00 2001 From: Vasant Hegde Date: Wed, 10 Apr 2024 08:57:02 +0000 Subject: iommu/amd: Do not enable SNP when V2 page table is enabled DTE[Mode]=0 is not supported when SNP is enabled in the host. That means to support SNP, IOMMU must be configured with V1 page table (See IOMMU spec [1] for the details). If user passes kernel command line to configure IOMMU domains with v2 page table (amd_iommu=pgtbl_v2) then disable SNP as the user asked by not forcing the page table to v1. [1] https://www.amd.com/content/dam/amd/en/documents/processor-tech-docs/specifications/48882_IOMMU.pdf Cc: Ashish Kalra Cc: Michael Roth Cc: Tom Lendacky Signed-off-by: Vasant Hegde Reviewed-by: Tom Lendacky Link: https://lore.kernel.org/r/20240410085702.31869-1-vasant.hegde@amd.com Signed-off-by: Joerg Roedel --- drivers/iommu/amd/init.c | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/drivers/iommu/amd/init.c b/drivers/iommu/amd/init.c index 33228c1c8980..a714eb08c08b 100644 --- a/drivers/iommu/amd/init.c +++ b/drivers/iommu/amd/init.c @@ -3232,28 +3232,29 @@ static void iommu_snp_enable(void) return; /* * The SNP support requires that IOMMU must be enabled, and is - * not configured in the passthrough mode. + * configured with V1 page table (DTE[Mode] = 0 is not supported). */ if (no_iommu || iommu_default_passthrough()) { pr_err("SNP: IOMMU disabled or configured in passthrough mode, SNP cannot be supported.\n"); - cc_platform_clear(CC_ATTR_HOST_SEV_SNP); - return; + goto disable_snp; + } + + if (amd_iommu_pgtable != AMD_IOMMU_V1) { + pr_warn("SNP: IOMMU is configured with V2 page table mode, SNP cannot be supported.\n"); + goto disable_snp; } amd_iommu_snp_en = check_feature(FEATURE_SNP); if (!amd_iommu_snp_en) { pr_err("SNP: IOMMU SNP feature not enabled, SNP cannot be supported.\n"); - cc_platform_clear(CC_ATTR_HOST_SEV_SNP); - return; + goto disable_snp; } pr_info("IOMMU SNP support enabled.\n"); + return; - /* Enforce IOMMU v1 pagetable when SNP is enabled. */ - if (amd_iommu_pgtable != AMD_IOMMU_V1) { - pr_warn("Forcing use of AMD IOMMU v1 page table due to SNP.\n"); - amd_iommu_pgtable = AMD_IOMMU_V1; - } +disable_snp: + cc_platform_clear(CC_ATTR_HOST_SEV_SNP); #endif } -- cgit v1.2.3 From 7537e31df80cb58c27f3b6fef702534ea87a5957 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Wed, 10 Apr 2024 18:41:09 +0200 Subject: iommu: mtk: fix module autoloading Add MODULE_DEVICE_TABLE(), so modules could be properly autoloaded based on the alias from of_device_id table. Signed-off-by: Krzysztof Kozlowski Link: https://lore.kernel.org/r/20240410164109.233308-1-krzk@kernel.org Signed-off-by: Joerg Roedel --- drivers/iommu/mtk_iommu.c | 1 + drivers/iommu/mtk_iommu_v1.c | 1 + 2 files changed, 2 insertions(+) diff --git a/drivers/iommu/mtk_iommu.c b/drivers/iommu/mtk_iommu.c index b8c47f18bc26..6a2707fe7a78 100644 --- a/drivers/iommu/mtk_iommu.c +++ b/drivers/iommu/mtk_iommu.c @@ -1790,6 +1790,7 @@ static const struct of_device_id mtk_iommu_of_ids[] = { { .compatible = "mediatek,mt8365-m4u", .data = &mt8365_data}, {} }; +MODULE_DEVICE_TABLE(of, mtk_iommu_of_ids); static struct platform_driver mtk_iommu_driver = { .probe = mtk_iommu_probe, diff --git a/drivers/iommu/mtk_iommu_v1.c b/drivers/iommu/mtk_iommu_v1.c index a9fa2a54dc9b..d6e4002200bd 100644 --- a/drivers/iommu/mtk_iommu_v1.c +++ b/drivers/iommu/mtk_iommu_v1.c @@ -600,6 +600,7 @@ static const struct of_device_id mtk_iommu_v1_of_ids[] = { { .compatible = "mediatek,mt2701-m4u", }, {} }; +MODULE_DEVICE_TABLE(of, mtk_iommu_v1_of_ids); static const struct component_master_ops mtk_iommu_v1_com_ops = { .bind = mtk_iommu_v1_bind, -- cgit v1.2.3 From 36d4fe147c870f6d3f6602befd7ef44393a1c87a Mon Sep 17 00:00:00 2001 From: Josh Poimboeuf Date: Wed, 10 Apr 2024 22:40:50 -0700 Subject: x86/bugs: Remove CONFIG_BHI_MITIGATION_AUTO and spectre_bhi=auto Unlike most other mitigations' "auto" options, spectre_bhi=auto only mitigates newer systems, which is confusing and not particularly useful. Remove it. Signed-off-by: Josh Poimboeuf Signed-off-by: Ingo Molnar Reviewed-by: Nikolay Borisov Cc: Sean Christopherson Cc: Linus Torvalds Link: https://lore.kernel.org/r/412e9dc87971b622bbbaf64740ebc1f140bff343.1712813475.git.jpoimboe@kernel.org --- Documentation/admin-guide/hw-vuln/spectre.rst | 4 ---- Documentation/admin-guide/kernel-parameters.txt | 3 --- arch/x86/Kconfig | 5 ----- arch/x86/kernel/cpu/bugs.c | 10 +--------- 4 files changed, 1 insertion(+), 21 deletions(-) diff --git a/Documentation/admin-guide/hw-vuln/spectre.rst b/Documentation/admin-guide/hw-vuln/spectre.rst index 5a39acf82483..25a04cda4c2c 100644 --- a/Documentation/admin-guide/hw-vuln/spectre.rst +++ b/Documentation/admin-guide/hw-vuln/spectre.rst @@ -669,10 +669,6 @@ kernel command line. needed. off Disable the mitigation. - auto - Enable the HW mitigation if needed, but - *don't* enable the SW mitigation except for KVM. - The system may be vulnerable. For spectre_v2_user see Documentation/admin-guide/kernel-parameters.txt diff --git a/Documentation/admin-guide/kernel-parameters.txt b/Documentation/admin-guide/kernel-parameters.txt index a3874cc97892..902ecd92a29f 100644 --- a/Documentation/admin-guide/kernel-parameters.txt +++ b/Documentation/admin-guide/kernel-parameters.txt @@ -6072,9 +6072,6 @@ on - (default) Enable the HW or SW mitigation as needed. off - Disable the mitigation. - auto - Enable the HW mitigation if needed, but - *don't* enable the SW mitigation except - for KVM. The system may be vulnerable. spectre_v2= [X86,EARLY] Control mitigation of Spectre variant 2 (indirect branch speculation) vulnerability. diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index 10a6251f58f3..b63b6767a63d 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig @@ -2651,11 +2651,6 @@ config SPECTRE_BHI_OFF bool "off" help Equivalent to setting spectre_bhi=off command line parameter. -config SPECTRE_BHI_AUTO - bool "auto" - depends on BROKEN - help - Equivalent to setting spectre_bhi=auto command line parameter. endchoice diff --git a/arch/x86/kernel/cpu/bugs.c b/arch/x86/kernel/cpu/bugs.c index 9eeb60f5fbb3..6af4780a18ed 100644 --- a/arch/x86/kernel/cpu/bugs.c +++ b/arch/x86/kernel/cpu/bugs.c @@ -1625,13 +1625,10 @@ static bool __init spec_ctrl_bhi_dis(void) enum bhi_mitigations { BHI_MITIGATION_OFF, BHI_MITIGATION_ON, - BHI_MITIGATION_AUTO, }; static enum bhi_mitigations bhi_mitigation __ro_after_init = - IS_ENABLED(CONFIG_SPECTRE_BHI_ON) ? BHI_MITIGATION_ON : - IS_ENABLED(CONFIG_SPECTRE_BHI_OFF) ? BHI_MITIGATION_OFF : - BHI_MITIGATION_AUTO; + IS_ENABLED(CONFIG_SPECTRE_BHI_ON) ? BHI_MITIGATION_ON : BHI_MITIGATION_OFF; static int __init spectre_bhi_parse_cmdline(char *str) { @@ -1642,8 +1639,6 @@ static int __init spectre_bhi_parse_cmdline(char *str) bhi_mitigation = BHI_MITIGATION_OFF; else if (!strcmp(str, "on")) bhi_mitigation = BHI_MITIGATION_ON; - else if (!strcmp(str, "auto")) - bhi_mitigation = BHI_MITIGATION_AUTO; else pr_err("Ignoring unknown spectre_bhi option (%s)", str); @@ -1673,9 +1668,6 @@ static void __init bhi_select_mitigation(void) setup_force_cpu_cap(X86_FEATURE_CLEAR_BHB_LOOP_ON_VMEXIT); pr_info("Spectre BHI mitigation: SW BHB clearing on vm exit\n"); - if (bhi_mitigation == BHI_MITIGATION_AUTO) - return; - /* Mitigate syscalls when the mitigation is forced =on */ setup_force_cpu_cap(X86_FEATURE_CLEAR_BHB_LOOP); pr_info("Spectre BHI mitigation: SW BHB clearing on syscall\n"); -- cgit v1.2.3 From 4f511739c54b549061993b53fc0380f48dfca23b Mon Sep 17 00:00:00 2001 From: Josh Poimboeuf Date: Wed, 10 Apr 2024 22:40:51 -0700 Subject: x86/bugs: Replace CONFIG_SPECTRE_BHI_{ON,OFF} with CONFIG_MITIGATION_SPECTRE_BHI For consistency with the other CONFIG_MITIGATION_* options, replace the CONFIG_SPECTRE_BHI_{ON,OFF} options with a single CONFIG_MITIGATION_SPECTRE_BHI option. [ mingo: Fix ] Signed-off-by: Josh Poimboeuf Signed-off-by: Ingo Molnar Cc: Sean Christopherson Cc: Linus Torvalds Cc: Nikolay Borisov Link: https://lore.kernel.org/r/3833812ea63e7fdbe36bf8b932e63f70d18e2a2a.1712813475.git.jpoimboe@kernel.org --- arch/x86/Kconfig | 17 +++-------------- arch/x86/kernel/cpu/bugs.c | 2 +- 2 files changed, 4 insertions(+), 15 deletions(-) diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index b63b6767a63d..4474bf32d0a4 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig @@ -2633,27 +2633,16 @@ config MITIGATION_RFDS stored in floating point, vector and integer registers. See also -choice - prompt "Clear branch history" +config MITIGATION_SPECTRE_BHI + bool "Mitigate Spectre-BHB (Branch History Injection)" depends on CPU_SUP_INTEL - default SPECTRE_BHI_ON + default y help Enable BHI mitigations. BHI attacks are a form of Spectre V2 attacks where the branch history buffer is poisoned to speculatively steer indirect branches. See -config SPECTRE_BHI_ON - bool "on" - help - Equivalent to setting spectre_bhi=on command line parameter. -config SPECTRE_BHI_OFF - bool "off" - help - Equivalent to setting spectre_bhi=off command line parameter. - -endchoice - endif config ARCH_HAS_ADD_PAGES diff --git a/arch/x86/kernel/cpu/bugs.c b/arch/x86/kernel/cpu/bugs.c index 6af4780a18ed..ca295b0c1eee 100644 --- a/arch/x86/kernel/cpu/bugs.c +++ b/arch/x86/kernel/cpu/bugs.c @@ -1628,7 +1628,7 @@ enum bhi_mitigations { }; static enum bhi_mitigations bhi_mitigation __ro_after_init = - IS_ENABLED(CONFIG_SPECTRE_BHI_ON) ? BHI_MITIGATION_ON : BHI_MITIGATION_OFF; + IS_ENABLED(CONFIG_MITIGATION_SPECTRE_BHI) ? BHI_MITIGATION_ON : BHI_MITIGATION_OFF; static int __init spectre_bhi_parse_cmdline(char *str) { -- cgit v1.2.3 From 1b3108f6898ef2e03973d65255182792e94e2240 Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Wed, 10 Apr 2024 21:45:27 +0200 Subject: x86/cpu/amd: Make the CPUID 0x80000008 parser correct CPUID 0x80000008 ECX.cpu_nthreads describes the number of threads in the package. The parser uses this value to initialize the SMT domain level. That's wrong because cpu_nthreads does not describe the number of threads per physical core. So this needs to set the CORE domain level and let the later parsers set the SMT shift if available. Preset the SMT domain level with the assumption of one thread per core, which is correct ifrt here are no other CPUID leafs to parse, and propagate cpu_nthreads and the core level APIC bitwidth into the CORE domain. Fixes: f7fb3b2dd92c ("x86/cpu: Provide an AMD/HYGON specific topology parser") Reported-by: "kernelci.org bot" Reported-by: Laura Nao Signed-off-by: Thomas Gleixner Tested-by: Laura Nao Link: https://lore.kernel.org/r/20240410194311.535206450@linutronix.de --- arch/x86/kernel/cpu/topology_amd.c | 24 ++++++++++++++++++------ 1 file changed, 18 insertions(+), 6 deletions(-) diff --git a/arch/x86/kernel/cpu/topology_amd.c b/arch/x86/kernel/cpu/topology_amd.c index 1a8b3ad493af..79a85a4814ca 100644 --- a/arch/x86/kernel/cpu/topology_amd.c +++ b/arch/x86/kernel/cpu/topology_amd.c @@ -29,11 +29,21 @@ static bool parse_8000_0008(struct topo_scan *tscan) if (!sft) sft = get_count_order(ecx.cpu_nthreads + 1); - topology_set_dom(tscan, TOPO_SMT_DOMAIN, sft, ecx.cpu_nthreads + 1); + /* + * cpu_nthreads describes the number of threads in the package + * sft is the number of APIC ID bits per package + * + * As the number of actual threads per core is not described in + * this leaf, just set the CORE domain shift and let the later + * parsers set SMT shift. Assume one thread per core by default + * which is correct if there are no other CPUID leafs to parse. + */ + topology_update_dom(tscan, TOPO_SMT_DOMAIN, 0, 1); + topology_set_dom(tscan, TOPO_CORE_DOMAIN, sft, ecx.cpu_nthreads + 1); return true; } -static void store_node(struct topo_scan *tscan, unsigned int nr_nodes, u16 node_id) +static void store_node(struct topo_scan *tscan, u16 nr_nodes, u16 node_id) { /* * Starting with Fam 17h the DIE domain could probably be used to @@ -73,12 +83,14 @@ static bool parse_8000_001e(struct topo_scan *tscan, bool has_0xb) tscan->c->topo.initial_apicid = leaf.ext_apic_id; /* - * If leaf 0xb is available, then SMT shift is set already. If not - * take it from ecx.threads_per_core and use topo_update_dom() - - * topology_set_dom() would propagate and overwrite the already - * propagated CORE level. + * If leaf 0xb is available, then the domain shifts are set + * already and nothing to do here. */ if (!has_0xb) { + /* + * Leaf 0x80000008 set the CORE domain shift already. + * Update the SMT domain, but do not propagate it. + */ unsigned int nthreads = leaf.core_nthreads + 1; topology_update_dom(tscan, TOPO_SMT_DOMAIN, get_count_order(nthreads), nthreads); -- cgit v1.2.3 From c064b536a8f9ab7c8e204da8f5a22f7420d0b56c Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Wed, 10 Apr 2024 21:45:28 +0200 Subject: x86/cpu/amd: Make the NODEID_MSR union actually work A system with NODEID_MSR was reported to crash during early boot without any output. The reason is that the union which is used for accessing the bitfields in the MSR is written wrongly and the resulting executable code accesses the wrong part of the MSR data. As a consequence a later division by that value results in 0 and that result is used for another division as divisor, which obviously does not work well. The magic world of C, unions and bitfields: union { u64 bita : 3, bitb : 3; u64 all; } x; x.all = foo(); a = x.bita; b = x.bitb; results in the effective executable code of: a = b = x.bita; because bita and bitb are treated as union members and therefore both end up at bit offset 0. Wrapping the bitfield into an anonymous struct: union { struct { u64 bita : 3, bitb : 3; }; u64 all; } x; works like expected. Rework the NODEID_MSR union in exactly that way to cure the problem. Fixes: f7fb3b2dd92c ("x86/cpu: Provide an AMD/HYGON specific topology parser") Reported-by: "kernelci.org bot" Reported-by: Laura Nao Signed-off-by: Thomas Gleixner Tested-by: Laura Nao Link: https://lore.kernel.org/r/20240410194311.596282919@linutronix.de Closes: https://lore.kernel.org/all/20240322175210.124416-1-laura.nao@collabora.com/ --- arch/x86/kernel/cpu/topology_amd.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/arch/x86/kernel/cpu/topology_amd.c b/arch/x86/kernel/cpu/topology_amd.c index 79a85a4814ca..7f999aef1965 100644 --- a/arch/x86/kernel/cpu/topology_amd.c +++ b/arch/x86/kernel/cpu/topology_amd.c @@ -121,13 +121,13 @@ static bool parse_8000_001e(struct topo_scan *tscan, bool has_0xb) static bool parse_fam10h_node_id(struct topo_scan *tscan) { - struct { - union { + union { + struct { u64 node_id : 3, nodes_per_pkg : 3, unused : 58; - u64 msr; }; + u64 msr; } nid; if (!boot_cpu_has(X86_FEATURE_NODEID_MSR)) -- cgit v1.2.3 From 7211274fe0ee352332255e41ab5e628b86e83994 Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Thu, 11 Apr 2024 18:55:38 +0200 Subject: x86/cpu/amd: Move TOPOEXT enablement into the topology parser The topology rework missed that early_init_amd() tries to re-enable the Topology Extensions when the BIOS disabled them. The new parser is invoked before early_init_amd() so the re-enable attempt happens too late. Move it into the AMD specific topology parser code where it belongs. Fixes: f7fb3b2dd92c ("x86/cpu: Provide an AMD/HYGON specific topology parser") Signed-off-by: Thomas Gleixner Signed-off-by: Ingo Molnar Link: https://lore.kernel.org/r/878r1j260l.ffs@tglx --- arch/x86/kernel/cpu/amd.c | 15 --------------- arch/x86/kernel/cpu/topology_amd.c | 21 +++++++++++++++++++++ 2 files changed, 21 insertions(+), 15 deletions(-) diff --git a/arch/x86/kernel/cpu/amd.c b/arch/x86/kernel/cpu/amd.c index 9bf17c9c29da..cb9eece55904 100644 --- a/arch/x86/kernel/cpu/amd.c +++ b/arch/x86/kernel/cpu/amd.c @@ -535,7 +535,6 @@ clear_sev: static void early_init_amd(struct cpuinfo_x86 *c) { - u64 value; u32 dummy; if (c->x86 >= 0xf) @@ -603,20 +602,6 @@ static void early_init_amd(struct cpuinfo_x86 *c) early_detect_mem_encrypt(c); - /* Re-enable TopologyExtensions if switched off by BIOS */ - if (c->x86 == 0x15 && - (c->x86_model >= 0x10 && c->x86_model <= 0x6f) && - !cpu_has(c, X86_FEATURE_TOPOEXT)) { - - if (msr_set_bit(0xc0011005, 54) > 0) { - rdmsrl(0xc0011005, value); - if (value & BIT_64(54)) { - set_cpu_cap(c, X86_FEATURE_TOPOEXT); - pr_info_once(FW_INFO "CPU: Re-enabling disabled Topology Extensions Support.\n"); - } - } - } - if (!cpu_has(c, X86_FEATURE_HYPERVISOR) && !cpu_has(c, X86_FEATURE_IBPB_BRTYPE)) { if (c->x86 == 0x17 && boot_cpu_has(X86_FEATURE_AMD_IBPB)) setup_force_cpu_cap(X86_FEATURE_IBPB_BRTYPE); diff --git a/arch/x86/kernel/cpu/topology_amd.c b/arch/x86/kernel/cpu/topology_amd.c index 7f999aef1965..a7aa6eff4ae5 100644 --- a/arch/x86/kernel/cpu/topology_amd.c +++ b/arch/x86/kernel/cpu/topology_amd.c @@ -147,6 +147,26 @@ static void legacy_set_llc(struct topo_scan *tscan) tscan->c->topo.llc_id = apicid >> tscan->dom_shifts[TOPO_CORE_DOMAIN]; } +static void topoext_fixup(struct topo_scan *tscan) +{ + struct cpuinfo_x86 *c = tscan->c; + u64 msrval; + + /* Try to re-enable TopologyExtensions if switched off by BIOS */ + if (cpu_has(c, X86_FEATURE_TOPOEXT) || c->x86_vendor != X86_VENDOR_AMD || + c->x86 != 0x15 || c->x86_model < 0x10 || c->x86_model > 0x6f) + return; + + if (msr_set_bit(0xc0011005, 54) <= 0) + return; + + rdmsrl(0xc0011005, msrval); + if (msrval & BIT_64(54)) { + set_cpu_cap(c, X86_FEATURE_TOPOEXT); + pr_info_once(FW_INFO "CPU: Re-enabling disabled Topology Extensions Support.\n"); + } +} + static void parse_topology_amd(struct topo_scan *tscan) { bool has_0xb = false; @@ -176,6 +196,7 @@ static void parse_topology_amd(struct topo_scan *tscan) void cpu_parse_topology_amd(struct topo_scan *tscan) { tscan->amd_nodes_per_pkg = 1; + topoext_fixup(tscan); parse_topology_amd(tscan); if (tscan->amd_nodes_per_pkg > 1) -- cgit v1.2.3 From 5b3625a4f6422e8982f90f0c11b5546149c962b8 Mon Sep 17 00:00:00 2001 From: Xuchun Shang Date: Thu, 11 Apr 2024 11:07:42 +0800 Subject: iommu/vt-d: Fix wrong use of pasid config The commit "iommu/vt-d: Add IOMMU perfmon support" introduce IOMMU PMU feature, but use the wrong config when set pasid filter. Fixes: 7232ab8b89e9 ("iommu/vt-d: Add IOMMU perfmon support") Signed-off-by: Xuchun Shang Reviewed-by: Kan Liang Link: https://lore.kernel.org/r/20240401060753.3321318-1-xuchun.shang@linux.alibaba.com Signed-off-by: Lu Baolu Signed-off-by: Joerg Roedel --- drivers/iommu/intel/perfmon.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/iommu/intel/perfmon.c b/drivers/iommu/intel/perfmon.c index cf43e798eca4..44083d01852d 100644 --- a/drivers/iommu/intel/perfmon.c +++ b/drivers/iommu/intel/perfmon.c @@ -438,7 +438,7 @@ static int iommu_pmu_assign_event(struct iommu_pmu *iommu_pmu, iommu_pmu_set_filter(domain, event->attr.config1, IOMMU_PMU_FILTER_DOMAIN, idx, event->attr.config1); - iommu_pmu_set_filter(pasid, event->attr.config1, + iommu_pmu_set_filter(pasid, event->attr.config2, IOMMU_PMU_FILTER_PASID, idx, event->attr.config1); iommu_pmu_set_filter(ats, event->attr.config2, -- cgit v1.2.3 From a34f3e20ddff02c4f12df2c0635367394e64c63d Mon Sep 17 00:00:00 2001 From: Jacob Pan Date: Thu, 11 Apr 2024 11:07:43 +0800 Subject: iommu/vt-d: Allocate local memory for page request queue The page request queue is per IOMMU, its allocation should be made NUMA-aware for performance reasons. Fixes: a222a7f0bb6c ("iommu/vt-d: Implement page request handling") Signed-off-by: Jacob Pan Reviewed-by: Kevin Tian Link: https://lore.kernel.org/r/20240403214007.985600-1-jacob.jun.pan@linux.intel.com Signed-off-by: Lu Baolu Signed-off-by: Joerg Roedel --- drivers/iommu/intel/svm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/iommu/intel/svm.c b/drivers/iommu/intel/svm.c index c1bed89b1026..ee3b469e2da1 100644 --- a/drivers/iommu/intel/svm.c +++ b/drivers/iommu/intel/svm.c @@ -66,7 +66,7 @@ int intel_svm_enable_prq(struct intel_iommu *iommu) struct page *pages; int irq, ret; - pages = alloc_pages(GFP_KERNEL | __GFP_ZERO, PRQ_ORDER); + pages = alloc_pages_node(iommu->node, GFP_KERNEL | __GFP_ZERO, PRQ_ORDER); if (!pages) { pr_warn("IOMMU: %s: Failed to allocate page request queue\n", iommu->name); -- cgit v1.2.3 From 89436f4f54125b1297aec1f466efd8acb4ec613d Mon Sep 17 00:00:00 2001 From: Lu Baolu Date: Thu, 11 Apr 2024 11:07:44 +0800 Subject: iommu/vt-d: Fix WARN_ON in iommu probe path Commit 1a75cc710b95 ("iommu/vt-d: Use rbtree to track iommu probed devices") adds all devices probed by the iommu driver in a rbtree indexed by the source ID of each device. It assumes that each device has a unique source ID. This assumption is incorrect and the VT-d spec doesn't state this requirement either. The reason for using a rbtree to track devices is to look up the device with PCI bus and devfunc in the paths of handling ATS invalidation time out error and the PRI I/O page faults. Both are PCI ATS feature related. Only track the devices that have PCI ATS capabilities in the rbtree to avoid unnecessary WARN_ON in the iommu probe path. Otherwise, on some platforms below kernel splat will be displayed and the iommu probe results in failure. WARNING: CPU: 3 PID: 166 at drivers/iommu/intel/iommu.c:158 intel_iommu_probe_device+0x319/0xd90 Call Trace: ? __warn+0x7e/0x180 ? intel_iommu_probe_device+0x319/0xd90 ? report_bug+0x1f8/0x200 ? handle_bug+0x3c/0x70 ? exc_invalid_op+0x18/0x70 ? asm_exc_invalid_op+0x1a/0x20 ? intel_iommu_probe_device+0x319/0xd90 ? debug_mutex_init+0x37/0x50 __iommu_probe_device+0xf2/0x4f0 iommu_probe_device+0x22/0x70 iommu_bus_notifier+0x1e/0x40 notifier_call_chain+0x46/0x150 blocking_notifier_call_chain+0x42/0x60 bus_notify+0x2f/0x50 device_add+0x5ed/0x7e0 platform_device_add+0xf5/0x240 mfd_add_devices+0x3f9/0x500 ? preempt_count_add+0x4c/0xa0 ? up_write+0xa2/0x1b0 ? __debugfs_create_file+0xe3/0x150 intel_lpss_probe+0x49f/0x5b0 ? pci_conf1_write+0xa3/0xf0 intel_lpss_pci_probe+0xcf/0x110 [intel_lpss_pci] pci_device_probe+0x95/0x120 really_probe+0xd9/0x370 ? __pfx___driver_attach+0x10/0x10 __driver_probe_device+0x73/0x150 driver_probe_device+0x19/0xa0 __driver_attach+0xb6/0x180 ? __pfx___driver_attach+0x10/0x10 bus_for_each_dev+0x77/0xd0 bus_add_driver+0x114/0x210 driver_register+0x5b/0x110 ? __pfx_intel_lpss_pci_driver_init+0x10/0x10 [intel_lpss_pci] do_one_initcall+0x57/0x2b0 ? kmalloc_trace+0x21e/0x280 ? do_init_module+0x1e/0x210 do_init_module+0x5f/0x210 load_module+0x1d37/0x1fc0 ? init_module_from_file+0x86/0xd0 init_module_from_file+0x86/0xd0 idempotent_init_module+0x17c/0x230 __x64_sys_finit_module+0x56/0xb0 do_syscall_64+0x6e/0x140 entry_SYSCALL_64_after_hwframe+0x71/0x79 Fixes: 1a75cc710b95 ("iommu/vt-d: Use rbtree to track iommu probed devices") Closes: https://gitlab.freedesktop.org/drm/intel/-/issues/10689 Signed-off-by: Lu Baolu Link: https://lore.kernel.org/r/20240407011429.136282-1-baolu.lu@linux.intel.com Reviewed-by: Kevin Tian Signed-off-by: Joerg Roedel --- drivers/iommu/intel/iommu.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/drivers/iommu/intel/iommu.c b/drivers/iommu/intel/iommu.c index 50eb9aed47cc..a7ecd90303dc 100644 --- a/drivers/iommu/intel/iommu.c +++ b/drivers/iommu/intel/iommu.c @@ -4299,9 +4299,11 @@ static struct iommu_device *intel_iommu_probe_device(struct device *dev) } dev_iommu_priv_set(dev, info); - ret = device_rbtree_insert(iommu, info); - if (ret) - goto free; + if (pdev && pci_ats_supported(pdev)) { + ret = device_rbtree_insert(iommu, info); + if (ret) + goto free; + } if (sm_supported(iommu) && !dev_is_real_dma_subdevice(dev)) { ret = intel_pasid_alloc_table(dev); @@ -4336,7 +4338,8 @@ static void intel_iommu_release_device(struct device *dev) struct intel_iommu *iommu = info->iommu; mutex_lock(&iommu->iopf_lock); - device_rbtree_remove(info); + if (dev_is_pci(dev) && pci_ats_supported(to_pci_dev(dev))) + device_rbtree_remove(info); mutex_unlock(&iommu->iopf_lock); if (sm_supported(iommu) && !dev_is_real_dma_subdevice(dev) && -- cgit v1.2.3 From b8246a2ad80a810cafbeddb30525278f9d64bca3 Mon Sep 17 00:00:00 2001 From: Vasant Hegde Date: Wed, 10 Apr 2024 10:16:43 +0000 Subject: iommu/amd: Change log message severity Use consistent log severity (pr_warn) to log all messages in SNP enable path. Suggested-by: Tom Lendacky Signed-off-by: Vasant Hegde Link: https://lore.kernel.org/r/20240410101643.32309-1-vasant.hegde@amd.com Signed-off-by: Joerg Roedel --- drivers/iommu/amd/init.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/iommu/amd/init.c b/drivers/iommu/amd/init.c index a714eb08c08b..ac6754a85f35 100644 --- a/drivers/iommu/amd/init.c +++ b/drivers/iommu/amd/init.c @@ -3235,7 +3235,7 @@ static void iommu_snp_enable(void) * configured with V1 page table (DTE[Mode] = 0 is not supported). */ if (no_iommu || iommu_default_passthrough()) { - pr_err("SNP: IOMMU disabled or configured in passthrough mode, SNP cannot be supported.\n"); + pr_warn("SNP: IOMMU disabled or configured in passthrough mode, SNP cannot be supported.\n"); goto disable_snp; } @@ -3246,7 +3246,7 @@ static void iommu_snp_enable(void) amd_iommu_snp_en = check_feature(FEATURE_SNP); if (!amd_iommu_snp_en) { - pr_err("SNP: IOMMU SNP feature not enabled, SNP cannot be supported.\n"); + pr_warn("SNP: IOMMU SNP feature not enabled, SNP cannot be supported.\n"); goto disable_snp; } -- cgit v1.2.3 From e4a6bceac98eba3c00e874892736b34ea5fdaca3 Mon Sep 17 00:00:00 2001 From: John Stultz Date: Wed, 10 Apr 2024 16:26:28 -0700 Subject: selftests: timers: Fix posix_timers ksft_print_msg() warning After commit 6d029c25b71f ("selftests/timers/posix_timers: Reimplement check_timer_distribution()") the following warning occurs when building with an older gcc: posix_timers.c:250:2: warning: format not a string literal and no format arguments [-Wformat-security] 250 | ksft_print_msg(errmsg); | ^~~~~~~~~~~~~~ Fix this up by changing it to ksft_print_msg("%s", errmsg) Fixes: 6d029c25b71f ("selftests/timers/posix_timers: Reimplement check_timer_distribution()") Signed-off-by: John Stultz Signed-off-by: Thomas Gleixner Acked-by: Justin Stitt Acked-by: Shuah Khan Cc: stable@vger.kernel.org Link: https://lore.kernel.org/r/20240410232637.4135564-1-jstultz@google.com --- tools/testing/selftests/timers/posix_timers.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/testing/selftests/timers/posix_timers.c b/tools/testing/selftests/timers/posix_timers.c index d86a0e00711e..348f47176e0a 100644 --- a/tools/testing/selftests/timers/posix_timers.c +++ b/tools/testing/selftests/timers/posix_timers.c @@ -247,7 +247,7 @@ static int check_timer_distribution(void) ksft_test_result_skip("check signal distribution (old kernel)\n"); return 0; err: - ksft_print_msg(errmsg); + ksft_print_msg("%s", errmsg); return -1; } -- cgit v1.2.3 From f7d5bcd35d427daac7e206b1073ca14f5db85c27 Mon Sep 17 00:00:00 2001 From: Nathan Chancellor Date: Thu, 11 Apr 2024 11:45:40 -0700 Subject: selftests: kselftest: Mark functions that unconditionally call exit() as __noreturn After commit 6d029c25b71f ("selftests/timers/posix_timers: Reimplement check_timer_distribution()"), clang warns: tools/testing/selftests/timers/../kselftest.h:398:6: warning: variable 'major' is used uninitialized whenever '||' condition is true [-Wsometimes-uninitialized] 398 | if (uname(&info) || sscanf(info.release, "%u.%u.", &major, &minor) != 2) | ^~~~~~~~~~~~ tools/testing/selftests/timers/../kselftest.h:401:9: note: uninitialized use occurs here 401 | return major > min_major || (major == min_major && minor >= min_minor); | ^~~~~ tools/testing/selftests/timers/../kselftest.h:398:6: note: remove the '||' if its condition is always false 398 | if (uname(&info) || sscanf(info.release, "%u.%u.", &major, &minor) != 2) | ^~~~~~~~~~~~~~~ tools/testing/selftests/timers/../kselftest.h:395:20: note: initialize the variable 'major' to silence this warning 395 | unsigned int major, minor; | ^ | = 0 This is a false positive because if uname() fails, ksft_exit_fail_msg() will be called, which unconditionally calls exit(), a noreturn function. However, clang does not know that ksft_exit_fail_msg() will call exit() at the point in the pipeline that the warning is emitted because inlining has not occurred, so it assumes control flow will resume normally after ksft_exit_fail_msg() is called. Make it clear to clang that all of the functions that call exit() unconditionally in kselftest.h are noreturn transitively by marking them explicitly with '__attribute__((__noreturn__))', which clears up the warning above and any future warnings that may appear for the same reason. Fixes: 6d029c25b71f ("selftests/timers/posix_timers: Reimplement check_timer_distribution()") Reported-by: John Stultz Signed-off-by: Nathan Chancellor Signed-off-by: Thomas Gleixner Acked-by: Shuah Khan Cc: stable@vger.kernel.org Link: https://lore.kernel.org/r/20240411-mark-kselftest-exit-funcs-noreturn-v1-1-b027c948f586@kernel.org Closes: https://lore.kernel.org/all/20240410232637.4135564-2-jstultz@google.com/ --- tools/testing/selftests/kselftest.h | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/tools/testing/selftests/kselftest.h b/tools/testing/selftests/kselftest.h index 973b18e156b2..0591974b57e0 100644 --- a/tools/testing/selftests/kselftest.h +++ b/tools/testing/selftests/kselftest.h @@ -80,6 +80,9 @@ #define KSFT_XPASS 3 #define KSFT_SKIP 4 +#ifndef __noreturn +#define __noreturn __attribute__((__noreturn__)) +#endif #define __printf(a, b) __attribute__((format(printf, a, b))) /* counters */ @@ -300,13 +303,13 @@ void ksft_test_result_code(int exit_code, const char *test_name, va_end(args); } -static inline int ksft_exit_pass(void) +static inline __noreturn int ksft_exit_pass(void) { ksft_print_cnts(); exit(KSFT_PASS); } -static inline int ksft_exit_fail(void) +static inline __noreturn int ksft_exit_fail(void) { ksft_print_cnts(); exit(KSFT_FAIL); @@ -333,7 +336,7 @@ static inline int ksft_exit_fail(void) ksft_cnt.ksft_xfail + \ ksft_cnt.ksft_xskip) -static inline __printf(1, 2) int ksft_exit_fail_msg(const char *msg, ...) +static inline __noreturn __printf(1, 2) int ksft_exit_fail_msg(const char *msg, ...) { int saved_errno = errno; va_list args; @@ -348,19 +351,19 @@ static inline __printf(1, 2) int ksft_exit_fail_msg(const char *msg, ...) exit(KSFT_FAIL); } -static inline int ksft_exit_xfail(void) +static inline __noreturn int ksft_exit_xfail(void) { ksft_print_cnts(); exit(KSFT_XFAIL); } -static inline int ksft_exit_xpass(void) +static inline __noreturn int ksft_exit_xpass(void) { ksft_print_cnts(); exit(KSFT_XPASS); } -static inline __printf(1, 2) int ksft_exit_skip(const char *msg, ...) +static inline __noreturn __printf(1, 2) int ksft_exit_skip(const char *msg, ...) { int saved_errno = errno; va_list args; -- cgit v1.2.3 From ed366de8ec89d4f960d66c85fc37d9de22f7bf6d Mon Sep 17 00:00:00 2001 From: John Stultz Date: Wed, 10 Apr 2024 16:26:30 -0700 Subject: selftests: timers: Fix abs() warning in posix_timers test Building with clang results in the following warning: posix_timers.c:69:6: warning: absolute value function 'abs' given an argument of type 'long long' but has parameter of type 'int' which may cause truncation of value [-Wabsolute-value] if (abs(diff - DELAY * USECS_PER_SEC) > USECS_PER_SEC / 2) { ^ So switch to using llabs() instead. Fixes: 0bc4b0cf1570 ("selftests: add basic posix timers selftests") Signed-off-by: John Stultz Signed-off-by: Thomas Gleixner Cc: stable@vger.kernel.org Link: https://lore.kernel.org/r/20240410232637.4135564-3-jstultz@google.com --- tools/testing/selftests/timers/posix_timers.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/testing/selftests/timers/posix_timers.c b/tools/testing/selftests/timers/posix_timers.c index 348f47176e0a..c001dd79179d 100644 --- a/tools/testing/selftests/timers/posix_timers.c +++ b/tools/testing/selftests/timers/posix_timers.c @@ -66,7 +66,7 @@ static int check_diff(struct timeval start, struct timeval end) diff = end.tv_usec - start.tv_usec; diff += (end.tv_sec - start.tv_sec) * USECS_PER_SEC; - if (abs(diff - DELAY * USECS_PER_SEC) > USECS_PER_SEC / 2) { + if (llabs(diff - DELAY * USECS_PER_SEC) > USECS_PER_SEC / 2) { printf("Diff too high: %lld..", diff); return -1; } -- cgit v1.2.3 From 607638faf2ff1cede37458111496e7cc6c977f6f Mon Sep 17 00:00:00 2001 From: Peter Oberparleiter Date: Wed, 10 Apr 2024 11:46:18 +0200 Subject: s390/qdio: handle deferred cc1 A deferred condition code 1 response indicates that I/O was not started and should be retried. The current QDIO implementation handles a cc1 response as I/O error, resulting in a failed QDIO setup. This can happen for example when a path verification request arrives at the same time as QDIO setup I/O is started. Fix this by retrying the QDIO setup I/O when a cc1 response is received. Note that since commit 2297791c92d0 ("s390/cio: dont unregister subchannel from child-drivers") commit 5ef1dc40ffa6 ("s390/cio: fix invalid -EBUSY on ccw_device_start") deferred cc1 responses are much more likely to occur. See the commit message of the latter for more background information. Fixes: 2297791c92d0 ("s390/cio: dont unregister subchannel from child-drivers") Reviewed-by: Alexandra Winter Signed-off-by: Peter Oberparleiter Signed-off-by: Alexander Gordeev --- drivers/s390/cio/qdio_main.c | 28 +++++++++++++++++++++++----- 1 file changed, 23 insertions(+), 5 deletions(-) diff --git a/drivers/s390/cio/qdio_main.c b/drivers/s390/cio/qdio_main.c index 3d9f0834c78b..a1cb39f4b7a2 100644 --- a/drivers/s390/cio/qdio_main.c +++ b/drivers/s390/cio/qdio_main.c @@ -722,8 +722,8 @@ static void qdio_handle_activate_check(struct qdio_irq *irq_ptr, lgr_info_log(); } -static void qdio_establish_handle_irq(struct qdio_irq *irq_ptr, int cstat, - int dstat) +static int qdio_establish_handle_irq(struct qdio_irq *irq_ptr, int cstat, + int dstat, int dcc) { DBF_DEV_EVENT(DBF_INFO, irq_ptr, "qest irq"); @@ -731,15 +731,18 @@ static void qdio_establish_handle_irq(struct qdio_irq *irq_ptr, int cstat, goto error; if (dstat & ~(DEV_STAT_DEV_END | DEV_STAT_CHN_END)) goto error; + if (dcc == 1) + return -EAGAIN; if (!(dstat & DEV_STAT_DEV_END)) goto error; qdio_set_state(irq_ptr, QDIO_IRQ_STATE_ESTABLISHED); - return; + return 0; error: DBF_ERROR("%4x EQ:error", irq_ptr->schid.sch_no); DBF_ERROR("ds: %2x cs:%2x", dstat, cstat); qdio_set_state(irq_ptr, QDIO_IRQ_STATE_ERR); + return -EIO; } /* qdio interrupt handler */ @@ -748,7 +751,7 @@ void qdio_int_handler(struct ccw_device *cdev, unsigned long intparm, { struct qdio_irq *irq_ptr = cdev->private->qdio_data; struct subchannel_id schid; - int cstat, dstat; + int cstat, dstat, rc, dcc; if (!intparm || !irq_ptr) { ccw_device_get_schid(cdev, &schid); @@ -768,10 +771,12 @@ void qdio_int_handler(struct ccw_device *cdev, unsigned long intparm, qdio_irq_check_sense(irq_ptr, irb); cstat = irb->scsw.cmd.cstat; dstat = irb->scsw.cmd.dstat; + dcc = scsw_cmd_is_valid_cc(&irb->scsw) ? irb->scsw.cmd.cc : 0; + rc = 0; switch (irq_ptr->state) { case QDIO_IRQ_STATE_INACTIVE: - qdio_establish_handle_irq(irq_ptr, cstat, dstat); + rc = qdio_establish_handle_irq(irq_ptr, cstat, dstat, dcc); break; case QDIO_IRQ_STATE_CLEANUP: qdio_set_state(irq_ptr, QDIO_IRQ_STATE_INACTIVE); @@ -785,12 +790,25 @@ void qdio_int_handler(struct ccw_device *cdev, unsigned long intparm, if (cstat || dstat) qdio_handle_activate_check(irq_ptr, intparm, cstat, dstat); + else if (dcc == 1) + rc = -EAGAIN; break; case QDIO_IRQ_STATE_STOPPED: break; default: WARN_ON_ONCE(1); } + + if (rc == -EAGAIN) { + DBF_DEV_EVENT(DBF_INFO, irq_ptr, "qint retry"); + rc = ccw_device_start(cdev, irq_ptr->ccw, intparm, 0, 0); + if (!rc) + return; + DBF_ERROR("%4x RETRY ERR", irq_ptr->schid.sch_no); + DBF_ERROR("rc:%4x", rc); + qdio_set_state(irq_ptr, QDIO_IRQ_STATE_ERR); + } + wake_up(&cdev->private->wait_q); } -- cgit v1.2.3 From 2d8527f2f911fab84aec04df4788c0c23af3df48 Mon Sep 17 00:00:00 2001 From: Peter Oberparleiter Date: Wed, 10 Apr 2024 11:46:19 +0200 Subject: s390/cio: fix race condition during online processing A race condition exists in ccw_device_set_online() that can cause the online process to fail, leaving the affected device in an inconsistent state. As a result, subsequent attempts to set that device online fail with return code ENODEV. The problem occurs when a path verification request arrives after a wait for final device state completed, but before the result state is evaluated. Fix this by ensuring that the CCW-device lock is held between determining final state and checking result state. Note that since: commit 2297791c92d0 ("s390/cio: dont unregister subchannel from child-drivers") path verification requests are much more likely to occur during boot, resulting in an increased chance of this race condition occurring. Fixes: 2297791c92d0 ("s390/cio: dont unregister subchannel from child-drivers") Reviewed-by: Alexandra Winter Reviewed-by: Vineeth Vijayan Signed-off-by: Peter Oberparleiter Signed-off-by: Alexander Gordeev --- drivers/s390/cio/device.c | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/drivers/s390/cio/device.c b/drivers/s390/cio/device.c index f95d12345d98..920f550bc313 100644 --- a/drivers/s390/cio/device.c +++ b/drivers/s390/cio/device.c @@ -363,10 +363,8 @@ int ccw_device_set_online(struct ccw_device *cdev) spin_lock_irq(cdev->ccwlock); ret = ccw_device_online(cdev); - spin_unlock_irq(cdev->ccwlock); - if (ret == 0) - wait_event(cdev->private->wait_q, dev_fsm_final_state(cdev)); - else { + if (ret) { + spin_unlock_irq(cdev->ccwlock); CIO_MSG_EVENT(0, "ccw_device_online returned %d, " "device 0.%x.%04x\n", ret, cdev->private->dev_id.ssid, @@ -375,7 +373,12 @@ int ccw_device_set_online(struct ccw_device *cdev) put_device(&cdev->dev); return ret; } - spin_lock_irq(cdev->ccwlock); + /* Wait until a final state is reached */ + while (!dev_fsm_final_state(cdev)) { + spin_unlock_irq(cdev->ccwlock); + wait_event(cdev->private->wait_q, dev_fsm_final_state(cdev)); + spin_lock_irq(cdev->ccwlock); + } /* Check if online processing was successful */ if ((cdev->private->state != DEV_STATE_ONLINE) && (cdev->private->state != DEV_STATE_W4SENSE)) { -- cgit v1.2.3 From 6f76592ef63a1ffd8949f0828d24da7913ddb6d8 Mon Sep 17 00:00:00 2001 From: Peter Oberparleiter Date: Wed, 10 Apr 2024 11:46:20 +0200 Subject: s390/cio: log fake IRB events Add traces when queueing and delivering fake IRBs. These are significant events that might have an impact on device driver processing and are therefore relevant for problem analysis. Reviewed-by: Vineeth Vijayan Signed-off-by: Peter Oberparleiter Signed-off-by: Alexander Gordeev --- drivers/s390/cio/device_fsm.c | 5 +++++ drivers/s390/cio/device_ops.c | 8 ++++++++ 2 files changed, 13 insertions(+) diff --git a/drivers/s390/cio/device_fsm.c b/drivers/s390/cio/device_fsm.c index 65d8b2cfd626..42791fa0b80e 100644 --- a/drivers/s390/cio/device_fsm.c +++ b/drivers/s390/cio/device_fsm.c @@ -504,6 +504,11 @@ callback: ccw_device_done(cdev, DEV_STATE_ONLINE); /* Deliver fake irb to device driver, if needed. */ if (cdev->private->flags.fake_irb) { + CIO_MSG_EVENT(2, "fakeirb: deliver device 0.%x.%04x intparm %lx type=%d\n", + cdev->private->dev_id.ssid, + cdev->private->dev_id.devno, + cdev->private->intparm, + cdev->private->flags.fake_irb); create_fake_irb(&cdev->private->dma_area->irb, cdev->private->flags.fake_irb); cdev->private->flags.fake_irb = 0; diff --git a/drivers/s390/cio/device_ops.c b/drivers/s390/cio/device_ops.c index 40c97f873075..acd6790dba4d 100644 --- a/drivers/s390/cio/device_ops.c +++ b/drivers/s390/cio/device_ops.c @@ -208,6 +208,10 @@ int ccw_device_start_timeout_key(struct ccw_device *cdev, struct ccw1 *cpa, if (!cdev->private->flags.fake_irb) { cdev->private->flags.fake_irb = FAKE_CMD_IRB; cdev->private->intparm = intparm; + CIO_MSG_EVENT(2, "fakeirb: queue device 0.%x.%04x intparm %lx type=%d\n", + cdev->private->dev_id.ssid, + cdev->private->dev_id.devno, intparm, + cdev->private->flags.fake_irb); return 0; } else /* There's already a fake I/O around. */ @@ -551,6 +555,10 @@ int ccw_device_tm_start_timeout_key(struct ccw_device *cdev, struct tcw *tcw, if (!cdev->private->flags.fake_irb) { cdev->private->flags.fake_irb = FAKE_TM_IRB; cdev->private->intparm = intparm; + CIO_MSG_EVENT(2, "fakeirb: queue device 0.%x.%04x intparm %lx type=%d\n", + cdev->private->dev_id.ssid, + cdev->private->dev_id.devno, intparm, + cdev->private->flags.fake_irb); return 0; } else /* There's already a fake I/O around. */ -- cgit v1.2.3 From 3ec4848913d695245716ea45ca4872d9dff097a5 Mon Sep 17 00:00:00 2001 From: Yu Kuai Date: Thu, 11 Apr 2024 11:23:48 +0800 Subject: block: fix that blk_time_get_ns() doesn't update time after schedule While monitoring the throttle time of IO from iocost, it's found that such time is always zero after the io_schedule() from ioc_rqos_throttle, for example, with the following debug patch: + printk("%s-%d: %s enter %llu\n", current->comm, current->pid, __func__, blk_time_get_ns()); while (true) { set_current_state(TASK_UNINTERRUPTIBLE); if (wait.committed) break; io_schedule(); } + printk("%s-%d: %s exit %llu\n", current->comm, current->pid, __func__, blk_time_get_ns()); It can be observerd that blk_time_get_ns() always return the same time: [ 1068.096579] fio-1268: ioc_rqos_throttle enter 1067901962288 [ 1068.272587] fio-1268: ioc_rqos_throttle exit 1067901962288 [ 1068.274389] fio-1268: ioc_rqos_throttle enter 1067901962288 [ 1068.472690] fio-1268: ioc_rqos_throttle exit 1067901962288 [ 1068.474485] fio-1268: ioc_rqos_throttle enter 1067901962288 [ 1068.672656] fio-1268: ioc_rqos_throttle exit 1067901962288 [ 1068.674451] fio-1268: ioc_rqos_throttle enter 1067901962288 [ 1068.872655] fio-1268: ioc_rqos_throttle exit 1067901962288 And I think the root cause is that 'PF_BLOCK_TS' is always cleared by blk_flush_plug() before scheduel(), hence blk_plug_invalidate_ts() will never be called: blk_time_get_ns plug->cur_ktime = ktime_get_ns(); current->flags |= PF_BLOCK_TS; io_schedule: io_schedule_prepare blk_flush_plug __blk_flush_plug /* the flag is cleared, while time is not */ current->flags &= ~PF_BLOCK_TS; schedule sched_update_worker /* the flag is not set, hence plug->cur_ktime is not cleared */ if (tsk->flags & PF_BLOCK_TS) blk_plug_invalidate_ts() blk_time_get_ns /* got the time stashed before schedule */ return plug->cur_ktime; Fix the problem by clearing cached time in __blk_flush_plug(). Fixes: 06b23f92af87 ("block: update cached timestamp post schedule/preemption") Signed-off-by: Yu Kuai Link: https://lore.kernel.org/r/20240411032349.3051233-2-yukuai1@huaweicloud.com Signed-off-by: Jens Axboe --- block/blk-core.c | 1 + 1 file changed, 1 insertion(+) diff --git a/block/blk-core.c b/block/blk-core.c index 3a6f5603fb44..b795ac177281 100644 --- a/block/blk-core.c +++ b/block/blk-core.c @@ -1197,6 +1197,7 @@ void __blk_flush_plug(struct blk_plug *plug, bool from_schedule) if (unlikely(!rq_list_empty(plug->cached_rq))) blk_mq_free_plug_rqs(plug); + plug->cur_ktime = 0; current->flags &= ~PF_BLOCK_TS; } -- cgit v1.2.3 From 16767502aa990cca2cb7d1372b31d328c4c85b40 Mon Sep 17 00:00:00 2001 From: Oleg Nesterov Date: Fri, 12 Apr 2024 14:35:36 +0200 Subject: selftests: kselftest: Fix build failure with NOLIBC As Mark explains ksft_min_kernel_version() can't be compiled with nolibc, it doesn't implement uname(). Fixes: 6d029c25b71f ("selftests/timers/posix_timers: Reimplement check_timer_distribution()") Reported-by: Mark Brown Signed-off-by: Oleg Nesterov Signed-off-by: Thomas Gleixner Link: https://lore.kernel.org/r/20240412123536.GA32444@redhat.com Closes: https://lore.kernel.org/all/f0523b3a-ea08-4615-b0fb-5b504a2d39df@sirena.org.uk/ --- tools/testing/selftests/kselftest.h | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/tools/testing/selftests/kselftest.h b/tools/testing/selftests/kselftest.h index 0591974b57e0..7b89362da4bf 100644 --- a/tools/testing/selftests/kselftest.h +++ b/tools/testing/selftests/kselftest.h @@ -395,6 +395,10 @@ static inline __noreturn __printf(1, 2) int ksft_exit_skip(const char *msg, ...) static inline int ksft_min_kernel_version(unsigned int min_major, unsigned int min_minor) { +#ifdef NOLIBC + ksft_print_msg("NOLIBC: Can't check kernel version: Function not implemented\n"); + return 0; +#else unsigned int major, minor; struct utsname info; @@ -402,6 +406,7 @@ static inline int ksft_min_kernel_version(unsigned int min_major, ksft_exit_fail_msg("Can't parse kernel version\n"); return major > min_major || (major == min_major && minor >= min_minor); +#endif } #endif /* __KSELFTEST_H */ -- cgit v1.2.3 From 3cba9cfcc1520a2307a29f6fab887bcfc121c417 Mon Sep 17 00:00:00 2001 From: Abdelrahman Morsy Date: Tue, 2 Apr 2024 14:14:06 +0200 Subject: HID: mcp-2221: cancel delayed_work only when CONFIG_IIO is enabled If the device is unplugged and CONFIG_IIO is not supported, this will result in a warning message at kernel/workqueue. Only cancel delayed work in mcp2221_remove(), when CONFIG_IIO is enabled. Signed-off-by: Abdelrahman Morsy Signed-off-by: Jiri Kosina --- drivers/hid/hid-mcp2221.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/hid/hid-mcp2221.c b/drivers/hid/hid-mcp2221.c index f9cceaeffd08..da5ea5a23b08 100644 --- a/drivers/hid/hid-mcp2221.c +++ b/drivers/hid/hid-mcp2221.c @@ -944,9 +944,11 @@ static void mcp2221_hid_unregister(void *ptr) /* This is needed to be sure hid_hw_stop() isn't called twice by the subsystem */ static void mcp2221_remove(struct hid_device *hdev) { +#if IS_REACHABLE(CONFIG_IIO) struct mcp2221 *mcp = hid_get_drvdata(hdev); cancel_delayed_work_sync(&mcp->init_work); +#endif } #if IS_REACHABLE(CONFIG_IIO) -- cgit v1.2.3 From 46dad3c1e57897ab9228332f03e1c14798d2d3b9 Mon Sep 17 00:00:00 2001 From: Yuntao Wang Date: Fri, 12 Apr 2024 16:17:32 +0800 Subject: init/main.c: Fix potential static_command_line memory overflow We allocate memory of size 'xlen + strlen(boot_command_line) + 1' for static_command_line, but the strings copied into static_command_line are extra_command_line and command_line, rather than extra_command_line and boot_command_line. When strlen(command_line) > strlen(boot_command_line), static_command_line will overflow. This patch just recovers strlen(command_line) which was miss-consolidated with strlen(boot_command_line) in the commit f5c7310ac73e ("init/main: add checks for the return value of memblock_alloc*()") Link: https://lore.kernel.org/all/20240412081733.35925-2-ytcoode@gmail.com/ Fixes: f5c7310ac73e ("init/main: add checks for the return value of memblock_alloc*()") Cc: stable@vger.kernel.org Signed-off-by: Yuntao Wang Signed-off-by: Masami Hiramatsu (Google) --- init/main.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/init/main.c b/init/main.c index 881f6230ee59..5dcf5274c09c 100644 --- a/init/main.c +++ b/init/main.c @@ -636,6 +636,8 @@ static void __init setup_command_line(char *command_line) if (!saved_command_line) panic("%s: Failed to allocate %zu bytes\n", __func__, len + ilen); + len = xlen + strlen(command_line) + 1; + static_command_line = memblock_alloc(len, SMP_CACHE_BYTES); if (!static_command_line) panic("%s: Failed to allocate %zu bytes\n", __func__, len); -- cgit v1.2.3 From d5cf50dafc9dd5faa1e61e7021e3496ddf7fd61e Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Fri, 12 Apr 2024 10:05:10 -0700 Subject: Kconfig: add some hidden tabs on purpose Commit d96c36004e31 ("tracing: Fix FTRACE_RECORD_RECURSION_SIZE Kconfig entry") removed a hidden tab because it apparently showed breakage in some third-party kernel config parsing tool. It wasn't clear what tool it was, but let's make sure it gets fixed. Because if you can't parse tabs as whitespace, you should not be parsing the kernel Kconfig files. In fact, let's make such breakage more obvious than some esoteric ftrace record size option. If you can't parse tabs, you can't have page sizes. Yes, tab-vs-space confusion is sadly a traditional Unix thing, and 'make' is famous for being broken in this regard. But no, that does not mean that it's ok. I'd add more random tabs to our Kconfig files, but I don't want to make things uglier than necessary. But it *might* bbe necessary if it turns out we see more of this kind of silly tooling. Fixes: d96c36004e31 ("tracing: Fix FTRACE_RECORD_RECURSION_SIZE Kconfig entry") Link: https://lore.kernel.org/lkml/CAHk-=wj-hLLN_t_m5OL4dXLaxvXKy_axuoJYXif7iczbfgAevQ@mail.gmail.com/ Signed-off-by: Linus Torvalds --- arch/Kconfig | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/arch/Kconfig b/arch/Kconfig index 9f066785bb71..65afb1de48b3 100644 --- a/arch/Kconfig +++ b/arch/Kconfig @@ -1172,12 +1172,12 @@ config PAGE_SIZE_LESS_THAN_256KB config PAGE_SHIFT int - default 12 if PAGE_SIZE_4KB - default 13 if PAGE_SIZE_8KB - default 14 if PAGE_SIZE_16KB - default 15 if PAGE_SIZE_32KB - default 16 if PAGE_SIZE_64KB - default 18 if PAGE_SIZE_256KB + default 12 if PAGE_SIZE_4KB + default 13 if PAGE_SIZE_8KB + default 14 if PAGE_SIZE_16KB + default 15 if PAGE_SIZE_32KB + default 16 if PAGE_SIZE_64KB + default 18 if PAGE_SIZE_256KB # This allows to use a set of generic functions to determine mmap base # address by giving priority to top-down scheme only if the process -- cgit v1.2.3 From 11baa36d317321f5d54059f07d243c5a1dbbfbb2 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Wed, 10 Apr 2024 19:03:05 +0200 Subject: gpio: lpc32xx: fix module autoloading Add MODULE_DEVICE_TABLE(), so the module could be properly autoloaded based on the alias from of_device_id table. Signed-off-by: Krzysztof Kozlowski Signed-off-by: Bartosz Golaszewski --- drivers/gpio/gpio-lpc32xx.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/gpio/gpio-lpc32xx.c b/drivers/gpio/gpio-lpc32xx.c index 5ef8af824980..c097e310c9e8 100644 --- a/drivers/gpio/gpio-lpc32xx.c +++ b/drivers/gpio/gpio-lpc32xx.c @@ -529,6 +529,7 @@ static const struct of_device_id lpc32xx_gpio_of_match[] = { { .compatible = "nxp,lpc3220-gpio", }, { }, }; +MODULE_DEVICE_TABLE(of, lpc32xx_gpio_of_match); static struct platform_driver lpc32xx_gpio_driver = { .driver = { -- cgit v1.2.3 From 79336504781e7fee5ddaf046dcc186c8dfdf60b1 Mon Sep 17 00:00:00 2001 From: Damien Le Moal Date: Fri, 12 Apr 2024 08:41:15 +0900 Subject: ata: libata-scsi: Fix ata_scsi_dev_rescan() error path Commit 0c76106cb975 ("scsi: sd: Fix TCG OPAL unlock on system resume") incorrectly handles failures of scsi_resume_device() in ata_scsi_dev_rescan(), leading to a double call to spin_unlock_irqrestore() to unlock a device port. Fix this by redefining the goto labels used in case of errors and only unlock the port scsi_scan_mutex when scsi_resume_device() fails. Bug found with the Smatch static checker warning: drivers/ata/libata-scsi.c:4774 ata_scsi_dev_rescan() error: double unlocked 'ap->lock' (orig line 4757) Reported-by: Dan Carpenter Fixes: 0c76106cb975 ("scsi: sd: Fix TCG OPAL unlock on system resume") Cc: stable@vger.kernel.org Signed-off-by: Damien Le Moal Reviewed-by: Niklas Cassel --- drivers/ata/libata-scsi.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c index 2f4c58837641..e954976891a9 100644 --- a/drivers/ata/libata-scsi.c +++ b/drivers/ata/libata-scsi.c @@ -4745,7 +4745,7 @@ void ata_scsi_dev_rescan(struct work_struct *work) * bail out. */ if (ap->pflags & ATA_PFLAG_SUSPENDED) - goto unlock; + goto unlock_ap; if (!sdev) continue; @@ -4758,7 +4758,7 @@ void ata_scsi_dev_rescan(struct work_struct *work) if (do_resume) { ret = scsi_resume_device(sdev); if (ret == -EWOULDBLOCK) - goto unlock; + goto unlock_scan; dev->flags &= ~ATA_DFLAG_RESUMING; } ret = scsi_rescan_device(sdev); @@ -4766,12 +4766,13 @@ void ata_scsi_dev_rescan(struct work_struct *work) spin_lock_irqsave(ap->lock, flags); if (ret) - goto unlock; + goto unlock_ap; } } -unlock: +unlock_ap: spin_unlock_irqrestore(ap->lock, flags); +unlock_scan: mutex_unlock(&ap->scsi_scan_mutex); /* Reschedule with a delay if scsi_rescan_device() returned an error */ -- cgit v1.2.3 From c0297e7dd50795d559f3534887a6de1756b35d0f Mon Sep 17 00:00:00 2001 From: Igor Pylypiv Date: Thu, 11 Apr 2024 20:12:24 +0000 Subject: ata: libata-core: Allow command duration limits detection for ACS-4 drives Even though the command duration limits (CDL) feature was first added in ACS-5 (major version 12), there are some ACS-4 (major version 11) drives that implement CDL as well. IDENTIFY_DEVICE, SUPPORTED_CAPABILITIES, and CURRENT_SETTINGS log pages are mandatory in the ACS-4 standard so it should be safe to read these log pages on older drives implementing the ACS-4 standard. Fixes: 62e4a60e0cdb ("scsi: ata: libata: Detect support for command duration limits") Cc: stable@vger.kernel.org Signed-off-by: Igor Pylypiv Signed-off-by: Damien Le Moal --- drivers/ata/libata-core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c index be3412cdb22e..c449d60d9bb9 100644 --- a/drivers/ata/libata-core.c +++ b/drivers/ata/libata-core.c @@ -2539,7 +2539,7 @@ static void ata_dev_config_cdl(struct ata_device *dev) bool cdl_enabled; u64 val; - if (ata_id_major_version(dev->id) < 12) + if (ata_id_major_version(dev->id) < 11) goto not_supported; if (!ata_log_supported(dev, ATA_LOG_IDENTIFY_DEVICE) || -- cgit v1.2.3 From 283454c8a123072e5c386a5a2b5fc576aa455b6f Mon Sep 17 00:00:00 2001 From: Kuniyuki Iwashima Date: Wed, 10 Apr 2024 10:10:15 -0700 Subject: af_unix: Call manage_oob() for every skb in unix_stream_read_generic(). When we call recv() for AF_UNIX socket, we first peek one skb and calls manage_oob() to check if the skb is sent with MSG_OOB. However, when we fetch the next (and the following) skb, manage_oob() is not called now, leading a wrong behaviour. Let's say a socket send()s "hello" with MSG_OOB and the peer tries to recv() 5 bytes with MSG_PEEK. Here, we should get only "hell" without 'o', but actually not: >>> from socket import * >>> c1, c2 = socketpair(AF_UNIX, SOCK_STREAM) >>> c1.send(b'hello', MSG_OOB) 5 >>> c2.recv(5, MSG_PEEK) b'hello' The first skb fills 4 bytes, and the next skb is peeked but not properly checked by manage_oob(). Let's move up the again label to call manage_oob() for evry skb. With this patch: >>> from socket import * >>> c1, c2 = socketpair(AF_UNIX, SOCK_STREAM) >>> c1.send(b'hello', MSG_OOB) 5 >>> c2.recv(5, MSG_PEEK) b'hell' Fixes: 314001f0bf92 ("af_unix: Add OOB support") Signed-off-by: Kuniyuki Iwashima Link: https://lore.kernel.org/r/20240410171016.7621-2-kuniyu@amazon.com Signed-off-by: Jakub Kicinski --- net/unix/af_unix.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c index d032eb5fa6df..f297320438bf 100644 --- a/net/unix/af_unix.c +++ b/net/unix/af_unix.c @@ -2741,6 +2741,7 @@ redo: last = skb = skb_peek(&sk->sk_receive_queue); last_len = last ? last->len : 0; +again: #if IS_ENABLED(CONFIG_AF_UNIX_OOB) if (skb) { skb = manage_oob(skb, sk, flags, copied); @@ -2752,7 +2753,6 @@ redo: } } #endif -again: if (skb == NULL) { if (copied >= target) goto unlock; -- cgit v1.2.3 From 22dd70eb2c3d754862964377a75abafd3167346b Mon Sep 17 00:00:00 2001 From: Kuniyuki Iwashima Date: Wed, 10 Apr 2024 10:10:16 -0700 Subject: af_unix: Don't peek OOB data without MSG_OOB. Currently, we can read OOB data without MSG_OOB by using MSG_PEEK when OOB data is sitting on the front row, which is apparently wrong. >>> from socket import * >>> c1, c2 = socketpair(AF_UNIX, SOCK_STREAM) >>> c1.send(b'a', MSG_OOB) 1 >>> c2.recv(1, MSG_PEEK | MSG_DONTWAIT) b'a' If manage_oob() is called when no data has been copied, we only check if the socket enables SO_OOBINLINE or MSG_PEEK is not used. Otherwise, the skb is returned as is. However, here we should return NULL if MSG_PEEK is set and no data has been copied. Also, in such a case, we should not jump to the redo label because we will be caught in the loop and hog the CPU until normal data comes in. Then, we need to handle skb == NULL case with the if-clause below the manage_oob() block. With this patch: >>> from socket import * >>> c1, c2 = socketpair(AF_UNIX, SOCK_STREAM) >>> c1.send(b'a', MSG_OOB) 1 >>> c2.recv(1, MSG_PEEK | MSG_DONTWAIT) Traceback (most recent call last): File "", line 1, in BlockingIOError: [Errno 11] Resource temporarily unavailable Fixes: 314001f0bf92 ("af_unix: Add OOB support") Signed-off-by: Kuniyuki Iwashima Link: https://lore.kernel.org/r/20240410171016.7621-3-kuniyu@amazon.com Signed-off-by: Jakub Kicinski --- net/unix/af_unix.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c index f297320438bf..9a6ad5974dff 100644 --- a/net/unix/af_unix.c +++ b/net/unix/af_unix.c @@ -2663,7 +2663,9 @@ static struct sk_buff *manage_oob(struct sk_buff *skb, struct sock *sk, WRITE_ONCE(u->oob_skb, NULL); consume_skb(skb); } - } else if (!(flags & MSG_PEEK)) { + } else if (flags & MSG_PEEK) { + skb = NULL; + } else { skb_unlink(skb, &sk->sk_receive_queue); WRITE_ONCE(u->oob_skb, NULL); if (!WARN_ON_ONCE(skb_unref(skb))) @@ -2745,11 +2747,9 @@ again: #if IS_ENABLED(CONFIG_AF_UNIX_OOB) if (skb) { skb = manage_oob(skb, sk, flags, copied); - if (!skb) { + if (!skb && copied) { unix_state_unlock(sk); - if (copied) - break; - goto redo; + break; } } #endif -- cgit v1.2.3 From 68aba00483c7c4102429bcdfdece7289a8ab5c8e Mon Sep 17 00:00:00 2001 From: Asbjørn Sloth Tønnesen Date: Thu, 11 Apr 2024 11:13:18 +0000 Subject: net: sparx5: flower: fix fragment flags handling MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit I noticed that only 3 out of the 4 input bits were used, mt.key->flags & FLOW_DIS_IS_FRAGMENT was never checked. In order to avoid a complicated maze, I converted it to use a 16 byte mapping table. As shown in the table below the old heuristics doesn't always do the right thing, ie. when FLOW_DIS_IS_FRAGMENT=1/1 then it used to only match follow-up fragment packets. Here are all the combinations, and their resulting new/old VCAP key/mask filter: /- FLOW_DIS_IS_FRAGMENT (key/mask) | /- FLOW_DIS_FIRST_FRAG (key/mask) | | /-- new VCAP fragment (key/mask) v v v v- old VCAP fragment (key/mask) 0/0 0/0 -/- -/- impossible (due to entry cond. on mask) 0/0 0/1 -/- 0/3 !! invalid (can't match non-fragment + follow-up frag) 0/0 1/0 -/- -/- impossible (key > mask) 0/0 1/1 1/3 1/3 first fragment 0/1 0/0 0/3 3/3 !! not fragmented 0/1 0/1 0/3 3/3 !! not fragmented (+ not first fragment) 0/1 1/0 -/- -/- impossible (key > mask) 0/1 1/1 -/- 1/3 !! invalid (non-fragment and first frag) 1/0 0/0 -/- -/- impossible (key > mask) 1/0 0/1 -/- -/- impossible (key > mask) 1/0 1/0 -/- -/- impossible (key > mask) 1/0 1/1 -/- -/- impossible (key > mask) 1/1 0/0 1/1 3/3 !! some fragment 1/1 0/1 3/3 3/3 follow-up fragment 1/1 1/0 -/- -/- impossible (key > mask) 1/1 1/1 1/3 1/3 first fragment In the datasheet the VCAP fragment values are documented as: 0 = no fragment 1 = initial fragment 2 = suspicious fragment 3 = valid follow-up fragment Result: 3 combinations match the old behavior, 3 combinations have been corrected, 2 combinations are now invalid, and fail, 8 combinations are impossible. It should now be aligned with how FLOW_DIS_IS_FRAGMENT and FLOW_DIS_FIRST_FRAG is set in __skb_flow_dissect() in net/core/flow_dissector.c Since the VCAP fragment values are not a bitfield, we have to ignore the suspicious fragment value, eg. when matching on any kind of fragment with FLOW_DIS_IS_FRAGMENT=1/1. Only compile tested, and logic tested in userspace, as I unfortunately don't have access to this switch chip (yet). Fixes: d6c2964db3fe ("net: microchip: sparx5: Adding more tc flower keys for the IS2 VCAP") Signed-off-by: Asbjørn Sloth Tønnesen Reviewed-by: Steen Hegelund Tested-by: Daniel Machon Reviewed-by: Jacob Keller Link: https://lore.kernel.org/r/20240411111321.114095-1-ast@fiberby.net Signed-off-by: Jakub Kicinski --- .../ethernet/microchip/sparx5/sparx5_tc_flower.c | 61 ++++++++++++++-------- 1 file changed, 40 insertions(+), 21 deletions(-) diff --git a/drivers/net/ethernet/microchip/sparx5/sparx5_tc_flower.c b/drivers/net/ethernet/microchip/sparx5/sparx5_tc_flower.c index 523e0c470894..55f255a3c9db 100644 --- a/drivers/net/ethernet/microchip/sparx5/sparx5_tc_flower.c +++ b/drivers/net/ethernet/microchip/sparx5/sparx5_tc_flower.c @@ -36,6 +36,27 @@ struct sparx5_tc_flower_template { u16 l3_proto; /* protocol specified in the template */ }; +/* SparX-5 VCAP fragment types: + * 0 = no fragment, 1 = initial fragment, + * 2 = suspicious fragment, 3 = valid follow-up fragment + */ +enum { /* key / mask */ + FRAG_NOT = 0x03, /* 0 / 3 */ + FRAG_SOME = 0x11, /* 1 / 1 */ + FRAG_FIRST = 0x13, /* 1 / 3 */ + FRAG_LATER = 0x33, /* 3 / 3 */ + FRAG_INVAL = 0xff, /* invalid */ +}; + +/* Flower fragment flag to VCAP fragment type mapping */ +static const u8 sparx5_vcap_frag_map[4][4] = { /* is_frag */ + { FRAG_INVAL, FRAG_INVAL, FRAG_INVAL, FRAG_FIRST }, /* 0/0 */ + { FRAG_NOT, FRAG_NOT, FRAG_INVAL, FRAG_INVAL }, /* 0/1 */ + { FRAG_INVAL, FRAG_INVAL, FRAG_INVAL, FRAG_INVAL }, /* 1/0 */ + { FRAG_SOME, FRAG_LATER, FRAG_INVAL, FRAG_FIRST } /* 1/1 */ + /* 0/0 0/1 1/0 1/1 <-- first_frag */ +}; + static int sparx5_tc_flower_es0_tpid(struct vcap_tc_flower_parse_usage *st) { @@ -145,29 +166,27 @@ sparx5_tc_flower_handler_control_usage(struct vcap_tc_flower_parse_usage *st) flow_rule_match_control(st->frule, &mt); if (mt.mask->flags) { - if (mt.mask->flags & FLOW_DIS_FIRST_FRAG) { - if (mt.key->flags & FLOW_DIS_FIRST_FRAG) { - value = 1; /* initial fragment */ - mask = 0x3; - } else { - if (mt.mask->flags & FLOW_DIS_IS_FRAGMENT) { - value = 3; /* follow up fragment */ - mask = 0x3; - } else { - value = 0; /* no fragment */ - mask = 0x3; - } - } - } else { - if (mt.mask->flags & FLOW_DIS_IS_FRAGMENT) { - value = 3; /* follow up fragment */ - mask = 0x3; - } else { - value = 0; /* no fragment */ - mask = 0x3; - } + u8 is_frag_key = !!(mt.key->flags & FLOW_DIS_IS_FRAGMENT); + u8 is_frag_mask = !!(mt.mask->flags & FLOW_DIS_IS_FRAGMENT); + u8 is_frag_idx = (is_frag_key << 1) | is_frag_mask; + + u8 first_frag_key = !!(mt.key->flags & FLOW_DIS_FIRST_FRAG); + u8 first_frag_mask = !!(mt.mask->flags & FLOW_DIS_FIRST_FRAG); + u8 first_frag_idx = (first_frag_key << 1) | first_frag_mask; + + /* Lookup verdict based on the 2 + 2 input bits */ + u8 vdt = sparx5_vcap_frag_map[is_frag_idx][first_frag_idx]; + + if (vdt == FRAG_INVAL) { + NL_SET_ERR_MSG_MOD(st->fco->common.extack, + "Match on invalid fragment flag combination"); + return -EINVAL; } + /* Extract VCAP fragment key and mask from verdict */ + value = (vdt >> 4) & 0x3; + mask = vdt & 0x3; + err = vcap_rule_add_key_u32(st->vrule, VCAP_KF_L3_FRAGMENT_TYPE, value, mask); -- cgit v1.2.3 From 37cc10da3a50e6d0cb9808a90b7da9b4868794dd Mon Sep 17 00:00:00 2001 From: Shay Drory Date: Thu, 11 Apr 2024 14:54:39 +0300 Subject: net/mlx5: Lag, restore buckets number to default after hash LAG deactivation The cited patch introduces the concept of buckets in LAG in hash mode. However, the patch doesn't clear the number of buckets in the LAG deactivation. This results in using the wrong number of buckets in case user create a hash mode LAG and afterwards create a non-hash mode LAG. Hence, restore buckets number to default after hash mode LAG deactivation. Fixes: 352899f384d4 ("net/mlx5: Lag, use buckets in hash mode") Signed-off-by: Shay Drory Reviewed-by: Maor Gottlieb Signed-off-by: Tariq Toukan Link: https://lore.kernel.org/r/20240411115444.374475-2-tariqt@nvidia.com Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/mellanox/mlx5/core/lag/lag.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/net/ethernet/mellanox/mlx5/core/lag/lag.c b/drivers/net/ethernet/mellanox/mlx5/core/lag/lag.c index d14459e5c04f..69d482f7c5a2 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/lag/lag.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/lag/lag.c @@ -703,8 +703,10 @@ int mlx5_deactivate_lag(struct mlx5_lag *ldev) return err; } - if (test_bit(MLX5_LAG_MODE_FLAG_HASH_BASED, &flags)) + if (test_bit(MLX5_LAG_MODE_FLAG_HASH_BASED, &flags)) { mlx5_lag_port_sel_destroy(ldev); + ldev->buckets = 1; + } if (mlx5_lag_has_drop_rule(ldev)) mlx5_lag_drop_rule_cleanup(ldev); -- cgit v1.2.3 From aa4ac90d04f4371466000825adb44935ecb5c974 Mon Sep 17 00:00:00 2001 From: Tariq Toukan Date: Thu, 11 Apr 2024 14:54:40 +0300 Subject: net/mlx5: SD, Handle possible devcom ERR_PTR Check if devcom holds an error pointer and return immediately. This fixes Smatch static checker warning: drivers/net/ethernet/mellanox/mlx5/core/lib/sd.c:221 sd_register() error: 'devcom' dereferencing possible ERR_PTR() Enhance mlx5_devcom_register_component() so it stops returning NULL, making it easier for its callers. Fixes: d3d057666090 ("net/mlx5: SD, Implement devcom communication and primary election") Reported-by: Dan Carpenter Link: https://lore.kernel.org/all/f09666c8-e604-41f6-958b-4cc55c73faf9@gmail.com/T/ Signed-off-by: Tariq Toukan Reviewed-by: Gal Pressman Link: https://lore.kernel.org/r/20240411115444.374475-3-tariqt@nvidia.com Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/mellanox/mlx5/core/en_main.c | 4 ++-- drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c | 2 +- drivers/net/ethernet/mellanox/mlx5/core/lib/devcom.c | 2 +- drivers/net/ethernet/mellanox/mlx5/core/lib/sd.c | 4 ++-- drivers/net/ethernet/mellanox/mlx5/core/main.c | 2 +- 5 files changed, 7 insertions(+), 7 deletions(-) diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c index b375ef268671..319930c04093 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c @@ -209,8 +209,8 @@ static int mlx5e_devcom_init_mpv(struct mlx5e_priv *priv, u64 *data) *data, mlx5e_devcom_event_mpv, priv); - if (IS_ERR_OR_NULL(priv->devcom)) - return -EOPNOTSUPP; + if (IS_ERR(priv->devcom)) + return PTR_ERR(priv->devcom); if (mlx5_core_is_mp_master(priv->mdev)) { mlx5_devcom_send_event(priv->devcom, MPV_DEVCOM_MASTER_UP, diff --git a/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c b/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c index 1f60954c12f7..844d3e3a65dd 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c @@ -3060,7 +3060,7 @@ void mlx5_esw_offloads_devcom_init(struct mlx5_eswitch *esw, u64 key) key, mlx5_esw_offloads_devcom_event, esw); - if (IS_ERR_OR_NULL(esw->devcom)) + if (IS_ERR(esw->devcom)) return; mlx5_devcom_send_event(esw->devcom, diff --git a/drivers/net/ethernet/mellanox/mlx5/core/lib/devcom.c b/drivers/net/ethernet/mellanox/mlx5/core/lib/devcom.c index e7d59cfa8708..7b0766c89f4c 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/lib/devcom.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/lib/devcom.c @@ -220,7 +220,7 @@ mlx5_devcom_register_component(struct mlx5_devcom_dev *devc, struct mlx5_devcom_comp *comp; if (IS_ERR_OR_NULL(devc)) - return NULL; + return ERR_PTR(-EINVAL); mutex_lock(&comp_list_lock); comp = devcom_component_get(devc, id, key, handler); diff --git a/drivers/net/ethernet/mellanox/mlx5/core/lib/sd.c b/drivers/net/ethernet/mellanox/mlx5/core/lib/sd.c index 5b28084e8a03..dd5d186dc614 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/lib/sd.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/lib/sd.c @@ -213,8 +213,8 @@ static int sd_register(struct mlx5_core_dev *dev) sd = mlx5_get_sd(dev); devcom = mlx5_devcom_register_component(dev->priv.devc, MLX5_DEVCOM_SD_GROUP, sd->group_id, NULL, dev); - if (!devcom) - return -ENOMEM; + if (IS_ERR(devcom)) + return PTR_ERR(devcom); sd->devcom = devcom; diff --git a/drivers/net/ethernet/mellanox/mlx5/core/main.c b/drivers/net/ethernet/mellanox/mlx5/core/main.c index 59806553889e..a39c4b25ba28 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/main.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/main.c @@ -956,7 +956,7 @@ static void mlx5_register_hca_devcom_comp(struct mlx5_core_dev *dev) mlx5_devcom_register_component(dev->priv.devc, MLX5_DEVCOM_HCA_PORTS, mlx5_query_nic_system_image_guid(dev), NULL, dev); - if (IS_ERR_OR_NULL(dev->priv.hca_devcom_comp)) + if (IS_ERR(dev->priv.hca_devcom_comp)) mlx5_core_err(dev, "Failed to register devcom HCA component\n"); } -- cgit v1.2.3 From bf729988303a27833a86acb561f42b9a3cc12728 Mon Sep 17 00:00:00 2001 From: Shay Drory Date: Thu, 11 Apr 2024 14:54:41 +0300 Subject: net/mlx5: Restore mistakenly dropped parts in register devlink flow Code parts from cited commit were mistakenly dropped while rebasing before submission. Add them here. Fixes: c6e77aa9dd82 ("net/mlx5: Register devlink first under devlink lock") Signed-off-by: Shay Drory Signed-off-by: Tariq Toukan Link: https://lore.kernel.org/r/20240411115444.374475-4-tariqt@nvidia.com Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/mellanox/mlx5/core/main.c | 5 ++++- drivers/net/ethernet/mellanox/mlx5/core/sf/dev/driver.c | 1 - 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/net/ethernet/mellanox/mlx5/core/main.c b/drivers/net/ethernet/mellanox/mlx5/core/main.c index a39c4b25ba28..331ce47f51a1 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/main.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/main.c @@ -1699,12 +1699,15 @@ int mlx5_init_one_light(struct mlx5_core_dev *dev) err = mlx5_devlink_params_register(priv_to_devlink(dev)); if (err) { mlx5_core_warn(dev, "mlx5_devlink_param_reg err = %d\n", err); - goto query_hca_caps_err; + goto params_reg_err; } devl_unlock(devlink); return 0; +params_reg_err: + devl_unregister(devlink); + devl_unlock(devlink); query_hca_caps_err: devl_unregister(devlink); devl_unlock(devlink); diff --git a/drivers/net/ethernet/mellanox/mlx5/core/sf/dev/driver.c b/drivers/net/ethernet/mellanox/mlx5/core/sf/dev/driver.c index e3bf8c7e4baa..7ebe71280827 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/sf/dev/driver.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/sf/dev/driver.c @@ -75,7 +75,6 @@ static int mlx5_sf_dev_probe(struct auxiliary_device *adev, const struct auxilia goto peer_devlink_set_err; } - devlink_register(devlink); return 0; peer_devlink_set_err: -- cgit v1.2.3 From 6c685bdb9e1af966ec0278dbd4068ec39ae88c2d Mon Sep 17 00:00:00 2001 From: Rahul Rameshbabu Date: Thu, 11 Apr 2024 14:54:42 +0300 Subject: net/mlx5e: Use channel mdev reference instead of global mdev instance for coalescing Channels can potentially have independent mdev instances. Do not refer to the global mdev instance in the mlx5e_priv instance for channel FW operations related to coalescing. CQ numbers that would be valid on the channel's mdev instance may not be correctly referenced if using the mlx5e_priv instance. Fixes: 67936e138586 ("net/mlx5e: Let channels be SD-aware") Signed-off-by: Rahul Rameshbabu Signed-off-by: Tariq Toukan Link: https://lore.kernel.org/r/20240411115444.374475-5-tariqt@nvidia.com Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c b/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c index 8f101181648c..67a29826bb57 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c @@ -589,12 +589,12 @@ static int mlx5e_get_coalesce(struct net_device *netdev, static void mlx5e_set_priv_channels_tx_coalesce(struct mlx5e_priv *priv, struct ethtool_coalesce *coal) { - struct mlx5_core_dev *mdev = priv->mdev; int tc; int i; for (i = 0; i < priv->channels.num; ++i) { struct mlx5e_channel *c = priv->channels.c[i]; + struct mlx5_core_dev *mdev = c->mdev; for (tc = 0; tc < c->num_tc; tc++) { mlx5_core_modify_cq_moderation(mdev, @@ -608,11 +608,11 @@ mlx5e_set_priv_channels_tx_coalesce(struct mlx5e_priv *priv, struct ethtool_coal static void mlx5e_set_priv_channels_rx_coalesce(struct mlx5e_priv *priv, struct ethtool_coalesce *coal) { - struct mlx5_core_dev *mdev = priv->mdev; int i; for (i = 0; i < priv->channels.num; ++i) { struct mlx5e_channel *c = priv->channels.c[i]; + struct mlx5_core_dev *mdev = c->mdev; mlx5_core_modify_cq_moderation(mdev, &c->rq.cq.mcq, coal->rx_coalesce_usecs, -- cgit v1.2.3 From fdce06bda7e56b2a34c53ea58bad7af2fae96da1 Mon Sep 17 00:00:00 2001 From: Carolina Jubran Date: Thu, 11 Apr 2024 14:54:43 +0300 Subject: net/mlx5e: Acquire RTNL lock before RQs/SQs activation/deactivation netif_queue_set_napi asserts whether RTNL lock is held if the netdev is initialized. Acquire the RTNL lock before activating or deactivating RQs/SQs if the lock has not been held before in the flow. Fixes: f25e7b82635f ("net/mlx5e: link NAPI instances to queues and IRQs") Cc: Joe Damato Signed-off-by: Carolina Jubran Reviewed-by: Rahul Rameshbabu Signed-off-by: Tariq Toukan Link: https://lore.kernel.org/r/20240411115444.374475-6-tariqt@nvidia.com Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/mellanox/mlx5/core/en/reporter_tx.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/reporter_tx.c b/drivers/net/ethernet/mellanox/mlx5/core/en/reporter_tx.c index 0ab9db319530..22918b2ef7f1 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en/reporter_tx.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en/reporter_tx.c @@ -108,7 +108,10 @@ static int mlx5e_tx_reporter_err_cqe_recover(void *ctx) mlx5e_reset_txqsq_cc_pc(sq); sq->stats->recover++; clear_bit(MLX5E_SQ_STATE_RECOVERING, &sq->state); + rtnl_lock(); mlx5e_activate_txqsq(sq); + rtnl_unlock(); + if (sq->channel) mlx5e_trigger_napi_icosq(sq->channel); else @@ -179,12 +182,16 @@ static int mlx5e_tx_reporter_ptpsq_unhealthy_recover(void *ctx) carrier_ok = netif_carrier_ok(netdev); netif_carrier_off(netdev); + rtnl_lock(); mlx5e_deactivate_priv_channels(priv); + rtnl_unlock(); mlx5e_ptp_close(chs->ptp); err = mlx5e_ptp_open(priv, &chs->params, chs->c[0]->lag_port, &chs->ptp); + rtnl_lock(); mlx5e_activate_priv_channels(priv); + rtnl_unlock(); /* return carrier back if needed */ if (carrier_ok) -- cgit v1.2.3 From fef965764cf562f28afb997b626fc7c3cec99693 Mon Sep 17 00:00:00 2001 From: Carolina Jubran Date: Thu, 11 Apr 2024 14:54:44 +0300 Subject: net/mlx5e: Prevent deadlock while disabling aRFS When disabling aRFS under the `priv->state_lock`, any scheduled aRFS works are canceled using the `cancel_work_sync` function, which waits for the work to end if it has already started. However, while waiting for the work handler, the handler will try to acquire the `state_lock` which is already acquired. The worker acquires the lock to delete the rules if the state is down, which is not the worker's responsibility since disabling aRFS deletes the rules. Add an aRFS state variable, which indicates whether the aRFS is enabled and prevent adding rules when the aRFS is disabled. Kernel log: ====================================================== WARNING: possible circular locking dependency detected 6.7.0-rc4_net_next_mlx5_5483eb2 #1 Tainted: G I ------------------------------------------------------ ethtool/386089 is trying to acquire lock: ffff88810f21ce68 ((work_completion)(&rule->arfs_work)){+.+.}-{0:0}, at: __flush_work+0x74/0x4e0 but task is already holding lock: ffff8884a1808cc0 (&priv->state_lock){+.+.}-{3:3}, at: mlx5e_ethtool_set_channels+0x53/0x200 [mlx5_core] which lock already depends on the new lock. the existing dependency chain (in reverse order) is: -> #1 (&priv->state_lock){+.+.}-{3:3}: __mutex_lock+0x80/0xc90 arfs_handle_work+0x4b/0x3b0 [mlx5_core] process_one_work+0x1dc/0x4a0 worker_thread+0x1bf/0x3c0 kthread+0xd7/0x100 ret_from_fork+0x2d/0x50 ret_from_fork_asm+0x11/0x20 -> #0 ((work_completion)(&rule->arfs_work)){+.+.}-{0:0}: __lock_acquire+0x17b4/0x2c80 lock_acquire+0xd0/0x2b0 __flush_work+0x7a/0x4e0 __cancel_work_timer+0x131/0x1c0 arfs_del_rules+0x143/0x1e0 [mlx5_core] mlx5e_arfs_disable+0x1b/0x30 [mlx5_core] mlx5e_ethtool_set_channels+0xcb/0x200 [mlx5_core] ethnl_set_channels+0x28f/0x3b0 ethnl_default_set_doit+0xec/0x240 genl_family_rcv_msg_doit+0xd0/0x120 genl_rcv_msg+0x188/0x2c0 netlink_rcv_skb+0x54/0x100 genl_rcv+0x24/0x40 netlink_unicast+0x1a1/0x270 netlink_sendmsg+0x214/0x460 __sock_sendmsg+0x38/0x60 __sys_sendto+0x113/0x170 __x64_sys_sendto+0x20/0x30 do_syscall_64+0x40/0xe0 entry_SYSCALL_64_after_hwframe+0x46/0x4e other info that might help us debug this: Possible unsafe locking scenario: CPU0 CPU1 ---- ---- lock(&priv->state_lock); lock((work_completion)(&rule->arfs_work)); lock(&priv->state_lock); lock((work_completion)(&rule->arfs_work)); *** DEADLOCK *** 3 locks held by ethtool/386089: #0: ffffffff82ea7210 (cb_lock){++++}-{3:3}, at: genl_rcv+0x15/0x40 #1: ffffffff82e94c88 (rtnl_mutex){+.+.}-{3:3}, at: ethnl_default_set_doit+0xd3/0x240 #2: ffff8884a1808cc0 (&priv->state_lock){+.+.}-{3:3}, at: mlx5e_ethtool_set_channels+0x53/0x200 [mlx5_core] stack backtrace: CPU: 15 PID: 386089 Comm: ethtool Tainted: G I 6.7.0-rc4_net_next_mlx5_5483eb2 #1 Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS rel-1.13.0-0-gf21b5a4aeb02-prebuilt.qemu.org 04/01/2014 Call Trace: dump_stack_lvl+0x60/0xa0 check_noncircular+0x144/0x160 __lock_acquire+0x17b4/0x2c80 lock_acquire+0xd0/0x2b0 ? __flush_work+0x74/0x4e0 ? save_trace+0x3e/0x360 ? __flush_work+0x74/0x4e0 __flush_work+0x7a/0x4e0 ? __flush_work+0x74/0x4e0 ? __lock_acquire+0xa78/0x2c80 ? lock_acquire+0xd0/0x2b0 ? mark_held_locks+0x49/0x70 __cancel_work_timer+0x131/0x1c0 ? mark_held_locks+0x49/0x70 arfs_del_rules+0x143/0x1e0 [mlx5_core] mlx5e_arfs_disable+0x1b/0x30 [mlx5_core] mlx5e_ethtool_set_channels+0xcb/0x200 [mlx5_core] ethnl_set_channels+0x28f/0x3b0 ethnl_default_set_doit+0xec/0x240 genl_family_rcv_msg_doit+0xd0/0x120 genl_rcv_msg+0x188/0x2c0 ? ethnl_ops_begin+0xb0/0xb0 ? genl_family_rcv_msg_dumpit+0xf0/0xf0 netlink_rcv_skb+0x54/0x100 genl_rcv+0x24/0x40 netlink_unicast+0x1a1/0x270 netlink_sendmsg+0x214/0x460 __sock_sendmsg+0x38/0x60 __sys_sendto+0x113/0x170 ? do_user_addr_fault+0x53f/0x8f0 __x64_sys_sendto+0x20/0x30 do_syscall_64+0x40/0xe0 entry_SYSCALL_64_after_hwframe+0x46/0x4e Fixes: 45bf454ae884 ("net/mlx5e: Enabling aRFS mechanism") Signed-off-by: Carolina Jubran Signed-off-by: Tariq Toukan Link: https://lore.kernel.org/r/20240411115444.374475-7-tariqt@nvidia.com Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/mellanox/mlx5/core/en_arfs.c | 27 ++++++++++++++--------- 1 file changed, 16 insertions(+), 11 deletions(-) diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_arfs.c b/drivers/net/ethernet/mellanox/mlx5/core/en_arfs.c index c7f542d0b8f0..93cf23278d93 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_arfs.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_arfs.c @@ -46,6 +46,10 @@ struct arfs_table { struct hlist_head rules_hash[ARFS_HASH_SIZE]; }; +enum { + MLX5E_ARFS_STATE_ENABLED, +}; + enum arfs_type { ARFS_IPV4_TCP, ARFS_IPV6_TCP, @@ -60,6 +64,7 @@ struct mlx5e_arfs_tables { spinlock_t arfs_lock; int last_filter_id; struct workqueue_struct *wq; + unsigned long state; }; struct arfs_tuple { @@ -170,6 +175,8 @@ int mlx5e_arfs_enable(struct mlx5e_flow_steering *fs) return err; } } + set_bit(MLX5E_ARFS_STATE_ENABLED, &arfs->state); + return 0; } @@ -455,6 +462,8 @@ static void arfs_del_rules(struct mlx5e_flow_steering *fs) int i; int j; + clear_bit(MLX5E_ARFS_STATE_ENABLED, &arfs->state); + spin_lock_bh(&arfs->arfs_lock); mlx5e_for_each_arfs_rule(rule, htmp, arfs->arfs_tables, i, j) { hlist_del_init(&rule->hlist); @@ -627,17 +636,8 @@ static void arfs_handle_work(struct work_struct *work) struct mlx5_flow_handle *rule; arfs = mlx5e_fs_get_arfs(priv->fs); - mutex_lock(&priv->state_lock); - if (!test_bit(MLX5E_STATE_OPENED, &priv->state)) { - spin_lock_bh(&arfs->arfs_lock); - hlist_del(&arfs_rule->hlist); - spin_unlock_bh(&arfs->arfs_lock); - - mutex_unlock(&priv->state_lock); - kfree(arfs_rule); - goto out; - } - mutex_unlock(&priv->state_lock); + if (!test_bit(MLX5E_ARFS_STATE_ENABLED, &arfs->state)) + return; if (!arfs_rule->rule) { rule = arfs_add_rule(priv, arfs_rule); @@ -753,6 +753,11 @@ int mlx5e_rx_flow_steer(struct net_device *dev, const struct sk_buff *skb, return -EPROTONOSUPPORT; spin_lock_bh(&arfs->arfs_lock); + if (!test_bit(MLX5E_ARFS_STATE_ENABLED, &arfs->state)) { + spin_unlock_bh(&arfs->arfs_lock); + return -EPERM; + } + arfs_rule = arfs_find_rule(arfs_t, &fk); if (arfs_rule) { if (arfs_rule->rxq == rxq_index || work_busy(&arfs_rule->arfs_work)) { -- cgit v1.2.3 From 58caa786f1c02fd84919fb6db9eaecb22e8f7983 Mon Sep 17 00:00:00 2001 From: Kent Overstreet Date: Thu, 11 Apr 2024 17:47:42 -0400 Subject: bcachefs: Fix UAFs of btree_insert_entry array The btree paths array is now dynamically resizable - and as well the btree_insert_entries array, as it needs to be the same size. The merge path (and interior update path) allocates new btree paths, thus can trigger a resize; thus we need to not retain direct pointers after invoking merge; similarly when running btree node triggers. Signed-off-by: Kent Overstreet --- fs/bcachefs/btree_trans_commit.c | 27 ++++++++++++++------------- 1 file changed, 14 insertions(+), 13 deletions(-) diff --git a/fs/bcachefs/btree_trans_commit.c b/fs/bcachefs/btree_trans_commit.c index aa9da4970740..9609ad370d71 100644 --- a/fs/bcachefs/btree_trans_commit.c +++ b/fs/bcachefs/btree_trans_commit.c @@ -499,9 +499,8 @@ static int run_one_trans_trigger(struct btree_trans *trans, struct btree_insert_ } static int run_btree_triggers(struct btree_trans *trans, enum btree_id btree_id, - struct btree_insert_entry *btree_id_start) + unsigned btree_id_start) { - struct btree_insert_entry *i; bool trans_trigger_run; int ret, overwrite; @@ -514,13 +513,13 @@ static int run_btree_triggers(struct btree_trans *trans, enum btree_id btree_id, do { trans_trigger_run = false; - for (i = btree_id_start; - i < trans->updates + trans->nr_updates && i->btree_id <= btree_id; + for (unsigned i = btree_id_start; + i < trans->nr_updates && trans->updates[i].btree_id <= btree_id; i++) { - if (i->btree_id != btree_id) + if (trans->updates[i].btree_id != btree_id) continue; - ret = run_one_trans_trigger(trans, i, overwrite); + ret = run_one_trans_trigger(trans, trans->updates + i, overwrite); if (ret < 0) return ret; if (ret) @@ -534,8 +533,7 @@ static int run_btree_triggers(struct btree_trans *trans, enum btree_id btree_id, static int bch2_trans_commit_run_triggers(struct btree_trans *trans) { - struct btree_insert_entry *btree_id_start = trans->updates; - unsigned btree_id = 0; + unsigned btree_id = 0, btree_id_start = 0; int ret = 0; /* @@ -549,8 +547,8 @@ static int bch2_trans_commit_run_triggers(struct btree_trans *trans) if (btree_id == BTREE_ID_alloc) continue; - while (btree_id_start < trans->updates + trans->nr_updates && - btree_id_start->btree_id < btree_id) + while (btree_id_start < trans->nr_updates && + trans->updates[btree_id_start].btree_id < btree_id) btree_id_start++; ret = run_btree_triggers(trans, btree_id, btree_id_start); @@ -558,11 +556,13 @@ static int bch2_trans_commit_run_triggers(struct btree_trans *trans) return ret; } - trans_for_each_update(trans, i) { + for (unsigned idx = 0; idx < trans->nr_updates; idx++) { + struct btree_insert_entry *i = trans->updates + idx; + if (i->btree_id > BTREE_ID_alloc) break; if (i->btree_id == BTREE_ID_alloc) { - ret = run_btree_triggers(trans, BTREE_ID_alloc, i); + ret = run_btree_triggers(trans, BTREE_ID_alloc, idx); if (ret) return ret; break; @@ -826,7 +826,8 @@ static inline int do_bch2_trans_commit(struct btree_trans *trans, unsigned flags struct bch_fs *c = trans->c; int ret = 0, u64s_delta = 0; - trans_for_each_update(trans, i) { + for (unsigned idx = 0; idx < trans->nr_updates; idx++) { + struct btree_insert_entry *i = trans->updates + idx; if (i->cached) continue; -- cgit v1.2.3 From 031ad9e7dbd18c63e671fc4d98be3082189b8a63 Mon Sep 17 00:00:00 2001 From: Kent Overstreet Date: Thu, 11 Apr 2024 21:30:43 -0400 Subject: bcachefs: Check for packed bkeys that are too big add missing validation; fixes assertion pop in bkey unpack Signed-off-by: Kent Overstreet --- fs/bcachefs/bkey.h | 6 ++++++ fs/bcachefs/btree_io.c | 15 ++++++++------- 2 files changed, 14 insertions(+), 7 deletions(-) diff --git a/fs/bcachefs/bkey.h b/fs/bcachefs/bkey.h index cf23ff47bed8..3a45d128f608 100644 --- a/fs/bcachefs/bkey.h +++ b/fs/bcachefs/bkey.h @@ -314,6 +314,12 @@ static inline unsigned bkeyp_key_u64s(const struct bkey_format *format, return bkey_packed(k) ? format->key_u64s : BKEY_U64s; } +static inline bool bkeyp_u64s_valid(const struct bkey_format *f, + const struct bkey_packed *k) +{ + return ((unsigned) k->u64s - bkeyp_key_u64s(f, k) <= U8_MAX - BKEY_U64s); +} + static inline unsigned bkeyp_key_bytes(const struct bkey_format *format, const struct bkey_packed *k) { diff --git a/fs/bcachefs/btree_io.c b/fs/bcachefs/btree_io.c index d7de82ac3893..b1aaf0550644 100644 --- a/fs/bcachefs/btree_io.c +++ b/fs/bcachefs/btree_io.c @@ -831,7 +831,7 @@ static int bset_key_invalid(struct bch_fs *c, struct btree *b, (rw == WRITE ? bch2_bkey_val_invalid(c, k, READ, err) : 0); } -static bool __bkey_valid(struct bch_fs *c, struct btree *b, +static bool bkey_packed_valid(struct bch_fs *c, struct btree *b, struct bset *i, struct bkey_packed *k) { if (bkey_p_next(k) > vstruct_last(i)) @@ -840,7 +840,7 @@ static bool __bkey_valid(struct bch_fs *c, struct btree *b, if (k->format > KEY_FORMAT_CURRENT) return false; - if (k->u64s < bkeyp_key_u64s(&b->format, k)) + if (!bkeyp_u64s_valid(&b->format, k)) return false; struct printbuf buf = PRINTBUF; @@ -884,11 +884,13 @@ static int validate_bset_keys(struct bch_fs *c, struct btree *b, "invalid bkey format %u", k->format)) goto drop_this_key; - if (btree_err_on(k->u64s < bkeyp_key_u64s(&b->format, k), + if (btree_err_on(!bkeyp_u64s_valid(&b->format, k), -BCH_ERR_btree_node_read_err_fixable, c, NULL, b, i, btree_node_bkey_bad_u64s, - "k->u64s too small (%u < %u)", k->u64s, bkeyp_key_u64s(&b->format, k))) + "bad k->u64s %u (min %u max %lu)", k->u64s, + bkeyp_key_u64s(&b->format, k), + U8_MAX - BKEY_U64s + bkeyp_key_u64s(&b->format, k))) goto drop_this_key; if (!write) @@ -947,13 +949,12 @@ drop_this_key: * do */ - if (!__bkey_valid(c, b, i, (void *) ((u64 *) k + next_good_key))) { + if (!bkey_packed_valid(c, b, i, (void *) ((u64 *) k + next_good_key))) { for (next_good_key = 1; next_good_key < (u64 *) vstruct_last(i) - (u64 *) k; next_good_key++) - if (__bkey_valid(c, b, i, (void *) ((u64 *) k + next_good_key))) + if (bkey_packed_valid(c, b, i, (void *) ((u64 *) k + next_good_key))) goto got_good_key; - } /* -- cgit v1.2.3 From 87cb0239c87f608fd48fb50f9f53f129dcfd73f4 Mon Sep 17 00:00:00 2001 From: Kent Overstreet Date: Thu, 11 Apr 2024 23:38:07 -0400 Subject: bcachefs: btree node scan: handle encrypted nodes Signed-off-by: Kent Overstreet --- fs/bcachefs/btree_node_scan.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/fs/bcachefs/btree_node_scan.c b/fs/bcachefs/btree_node_scan.c index 556f76f5c84e..20f2b37c4474 100644 --- a/fs/bcachefs/btree_node_scan.c +++ b/fs/bcachefs/btree_node_scan.c @@ -133,9 +133,19 @@ static void try_read_btree_node(struct find_btree_nodes *f, struct bch_dev *ca, if (le64_to_cpu(bn->magic) != bset_magic(c)) return; + if (bch2_csum_type_is_encryption(BSET_CSUM_TYPE(&bn->keys))) { + struct nonce nonce = btree_nonce(&bn->keys, 0); + unsigned bytes = (void *) &bn->keys - (void *) &bn->flags; + + bch2_encrypt(c, BSET_CSUM_TYPE(&bn->keys), nonce, &bn->flags, bytes); + } + if (btree_id_is_alloc(BTREE_NODE_ID(bn))) return; + if (BTREE_NODE_LEVEL(bn) >= BTREE_MAX_DEPTH) + return; + rcu_read_lock(); struct found_btree_node n = { .btree_id = BTREE_NODE_ID(bn), -- cgit v1.2.3 From dc32c118ec6b1032693c489a0aa9e011f0acdb1a Mon Sep 17 00:00:00 2001 From: Kent Overstreet Date: Thu, 11 Apr 2024 21:20:27 -0400 Subject: bcachefs: fix unsafety in bch2_extent_ptr_to_text() Need to check if we have a valid bucket before checking if ptr is stale Signed-off-by: Kent Overstreet --- fs/bcachefs/extents.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/fs/bcachefs/extents.c b/fs/bcachefs/extents.c index 0e3ca99fbd2d..36d12d2adb81 100644 --- a/fs/bcachefs/extents.c +++ b/fs/bcachefs/extents.c @@ -998,7 +998,9 @@ void bch2_extent_ptr_to_text(struct printbuf *out, struct bch_fs *c, const struc prt_str(out, " cached"); if (ptr->unwritten) prt_str(out, " unwritten"); - if (ca && ptr_stale(ca, ptr)) + if (b >= ca->mi.first_bucket && + b < ca->mi.nbuckets && + ptr_stale(ca, ptr)) prt_printf(out, " stale"); } } -- cgit v1.2.3 From 2aeed876d7c2c2fb4c6b92f59bdf7e73cfe5e098 Mon Sep 17 00:00:00 2001 From: Kent Overstreet Date: Thu, 11 Apr 2024 23:37:24 -0400 Subject: bcachefs: fix unsafety in bch2_stripe_to_text() .to_text() functions need to work on key values that didn't pass .valid Signed-off-by: Kent Overstreet --- fs/bcachefs/ec.c | 46 +++++++++++++++++++++++++--------------------- fs/bcachefs/ec.h | 2 ++ 2 files changed, 27 insertions(+), 21 deletions(-) diff --git a/fs/bcachefs/ec.c b/fs/bcachefs/ec.c index 082075244e16..c0b2b2f180e0 100644 --- a/fs/bcachefs/ec.c +++ b/fs/bcachefs/ec.c @@ -131,29 +131,33 @@ fsck_err: void bch2_stripe_to_text(struct printbuf *out, struct bch_fs *c, struct bkey_s_c k) { - const struct bch_stripe *s = bkey_s_c_to_stripe(k).v; - unsigned i, nr_data = s->nr_blocks - s->nr_redundant; + const struct bch_stripe *sp = bkey_s_c_to_stripe(k).v; + struct bch_stripe s = {}; + + memcpy(&s, sp, min(sizeof(s), bkey_val_bytes(k.k))); + + unsigned nr_data = s.nr_blocks - s.nr_redundant; prt_printf(out, "algo %u sectors %u blocks %u:%u csum %u gran %u", - s->algorithm, - le16_to_cpu(s->sectors), - nr_data, - s->nr_redundant, - s->csum_type, - 1U << s->csum_granularity_bits); - - for (i = 0; i < s->nr_blocks; i++) { - const struct bch_extent_ptr *ptr = s->ptrs + i; - struct bch_dev *ca = bch_dev_bkey_exists(c, ptr->dev); - u32 offset; - u64 b = sector_to_bucket_and_offset(ca, ptr->offset, &offset); - - prt_printf(out, " %u:%llu:%u", ptr->dev, b, offset); - if (i < nr_data) - prt_printf(out, "#%u", stripe_blockcount_get(s, i)); - prt_printf(out, " gen %u", ptr->gen); - if (ptr_stale(ca, ptr)) - prt_printf(out, " stale"); + s.algorithm, + le16_to_cpu(s.sectors), + nr_data, + s.nr_redundant, + s.csum_type, + 1U << s.csum_granularity_bits); + + for (unsigned i = 0; i < s.nr_blocks; i++) { + const struct bch_extent_ptr *ptr = sp->ptrs + i; + + if ((void *) ptr >= bkey_val_end(k)) + break; + + bch2_extent_ptr_to_text(out, c, ptr); + + if (s.csum_type < BCH_CSUM_NR && + i < nr_data && + stripe_blockcount_offset(&s, i) < bkey_val_bytes(k.k)) + prt_printf(out, "#%u", stripe_blockcount_get(sp, i)); } } diff --git a/fs/bcachefs/ec.h b/fs/bcachefs/ec.h index f4369b02e805..f042616888b0 100644 --- a/fs/bcachefs/ec.h +++ b/fs/bcachefs/ec.h @@ -32,6 +32,8 @@ static inline unsigned stripe_csums_per_device(const struct bch_stripe *s) static inline unsigned stripe_csum_offset(const struct bch_stripe *s, unsigned dev, unsigned csum_idx) { + EBUG_ON(s->csum_type >= BCH_CSUM_NR); + unsigned csum_bytes = bch_crc_bytes[s->csum_type]; return sizeof(struct bch_stripe) + -- cgit v1.2.3 From 7b4c4ccf848b359762c1525bab5a12f008f14a65 Mon Sep 17 00:00:00 2001 From: Kent Overstreet Date: Thu, 11 Apr 2024 23:58:36 -0400 Subject: bcachefs: fix race in bch2_btree_node_evict() Signed-off-by: Kent Overstreet --- fs/bcachefs/btree_cache.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/fs/bcachefs/btree_cache.c b/fs/bcachefs/btree_cache.c index 84474324dba9..c7f156320a35 100644 --- a/fs/bcachefs/btree_cache.c +++ b/fs/bcachefs/btree_cache.c @@ -1148,6 +1148,8 @@ wait_on_io: btree_node_lock_nopath_nofail(trans, &b->c, SIX_LOCK_intent); btree_node_lock_nopath_nofail(trans, &b->c, SIX_LOCK_write); + if (unlikely(b->hash_val != btree_ptr_hash_val(k))) + goto out; if (btree_node_dirty(b)) { __bch2_btree_node_write(c, b, BTREE_WRITE_cache_reclaim); @@ -1162,7 +1164,7 @@ wait_on_io: btree_node_data_free(c, b); bch2_btree_node_hash_remove(bc, b); mutex_unlock(&bc->lock); - +out: six_unlock_write(&b->c.lock); six_unlock_intent(&b->c.lock); } -- cgit v1.2.3 From ba8ed36e72033dd6b89d44145f323e6c4508bfc9 Mon Sep 17 00:00:00 2001 From: Kent Overstreet Date: Fri, 12 Apr 2024 00:09:08 -0400 Subject: bcachefs: don't queue btree nodes for rewrites during scan many nodes found during scan will be old nodes, overwritten by newer nodes Signed-off-by: Kent Overstreet --- fs/bcachefs/btree_io.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/fs/bcachefs/btree_io.c b/fs/bcachefs/btree_io.c index b1aaf0550644..9678b2375bed 100644 --- a/fs/bcachefs/btree_io.c +++ b/fs/bcachefs/btree_io.c @@ -1340,7 +1340,9 @@ start: rb->start_time); bio_put(&rb->bio); - if (saw_error && !btree_node_read_error(b)) { + if (saw_error && + !btree_node_read_error(b) && + c->curr_recovery_pass != BCH_RECOVERY_PASS_scan_for_btree_nodes) { printbuf_reset(&buf); bch2_bpos_to_text(&buf, b->key.k.p); bch_err_ratelimited(c, "%s: rewriting btree node at btree=%s level=%u %s due to error", -- cgit v1.2.3 From 9abb6dd7ce5a261f7aebf6f396b50a63db71133f Mon Sep 17 00:00:00 2001 From: Kent Overstreet Date: Fri, 12 Apr 2024 15:17:00 -0400 Subject: bcachefs: Standardize helpers for printing enum strs with bounds checks Signed-off-by: Kent Overstreet --- fs/bcachefs/bcachefs_format.h | 4 ++-- fs/bcachefs/buckets.h | 8 -------- fs/bcachefs/checksum.c | 23 ++++++++++++++--------- fs/bcachefs/checksum.h | 5 +++-- fs/bcachefs/compress.h | 8 -------- fs/bcachefs/ec.c | 14 ++++++-------- fs/bcachefs/extents.c | 7 ++++--- fs/bcachefs/journal_io.c | 17 +++++++++-------- fs/bcachefs/opts.c | 29 +++++++++++++++++++++++++---- fs/bcachefs/opts.h | 10 ++++++---- 10 files changed, 69 insertions(+), 56 deletions(-) diff --git a/fs/bcachefs/bcachefs_format.h b/fs/bcachefs/bcachefs_format.h index 364ae42022af..9480f1b44f07 100644 --- a/fs/bcachefs/bcachefs_format.h +++ b/fs/bcachefs/bcachefs_format.h @@ -1314,7 +1314,7 @@ static inline __u64 __bset_magic(struct bch_sb *sb) x(write_buffer_keys, 11) \ x(datetime, 12) -enum { +enum bch_jset_entry_type { #define x(f, nr) BCH_JSET_ENTRY_##f = nr, BCH_JSET_ENTRY_TYPES() #undef x @@ -1360,7 +1360,7 @@ struct jset_entry_blacklist_v2 { x(inodes, 1) \ x(key_version, 2) -enum { +enum bch_fs_usage_type { #define x(f, nr) BCH_FS_USAGE_##f = nr, BCH_FS_USAGE_TYPES() #undef x diff --git a/fs/bcachefs/buckets.h b/fs/bcachefs/buckets.h index 00aaf4bb5139..f9af5adabe83 100644 --- a/fs/bcachefs/buckets.h +++ b/fs/bcachefs/buckets.h @@ -395,14 +395,6 @@ static inline const char *bch2_data_type_str(enum bch_data_type type) : "(invalid data type)"; } -static inline void bch2_prt_data_type(struct printbuf *out, enum bch_data_type type) -{ - if (type < BCH_DATA_NR) - prt_str(out, __bch2_data_types[type]); - else - prt_printf(out, "(invalid data type %u)", type); -} - /* disk reservations: */ static inline void bch2_disk_reservation_put(struct bch_fs *c, diff --git a/fs/bcachefs/checksum.c b/fs/bcachefs/checksum.c index 4701457f6381..7ed779b411f6 100644 --- a/fs/bcachefs/checksum.c +++ b/fs/bcachefs/checksum.c @@ -429,15 +429,20 @@ int bch2_rechecksum_bio(struct bch_fs *c, struct bio *bio, extent_nonce(version, crc_old), bio); if (bch2_crc_cmp(merged, crc_old.csum) && !c->opts.no_data_io) { - bch_err(c, "checksum error in %s() (memory corruption or bug?)\n" - "expected %0llx:%0llx got %0llx:%0llx (old type %s new type %s)", - __func__, - crc_old.csum.hi, - crc_old.csum.lo, - merged.hi, - merged.lo, - bch2_csum_types[crc_old.csum_type], - bch2_csum_types[new_csum_type]); + struct printbuf buf = PRINTBUF; + prt_printf(&buf, "checksum error in %s() (memory corruption or bug?)\n" + "expected %0llx:%0llx got %0llx:%0llx (old type ", + __func__, + crc_old.csum.hi, + crc_old.csum.lo, + merged.hi, + merged.lo); + bch2_prt_csum_type(&buf, crc_old.csum_type); + prt_str(&buf, " new type "); + bch2_prt_csum_type(&buf, new_csum_type); + prt_str(&buf, ")"); + bch_err(c, "%s", buf.buf); + printbuf_exit(&buf); return -EIO; } diff --git a/fs/bcachefs/checksum.h b/fs/bcachefs/checksum.h index 1b8c2c1016dc..e40499fde9a4 100644 --- a/fs/bcachefs/checksum.h +++ b/fs/bcachefs/checksum.h @@ -61,11 +61,12 @@ static inline void bch2_csum_err_msg(struct printbuf *out, struct bch_csum expected, struct bch_csum got) { - prt_printf(out, "checksum error: got "); + prt_str(out, "checksum error, type "); + bch2_prt_csum_type(out, type); + prt_str(out, ": got "); bch2_csum_to_text(out, type, got); prt_str(out, " should be "); bch2_csum_to_text(out, type, expected); - prt_printf(out, " type %s", bch2_csum_types[type]); } int bch2_chacha_encrypt_key(struct bch_key *, struct nonce, void *, size_t); diff --git a/fs/bcachefs/compress.h b/fs/bcachefs/compress.h index 58c2eb45570f..607fd5e232c9 100644 --- a/fs/bcachefs/compress.h +++ b/fs/bcachefs/compress.h @@ -47,14 +47,6 @@ static inline enum bch_compression_type bch2_compression_opt_to_type(unsigned v) return __bch2_compression_opt_to_type[bch2_compression_decode(v).type]; } -static inline void bch2_prt_compression_type(struct printbuf *out, enum bch_compression_type type) -{ - if (type < BCH_COMPRESSION_TYPE_NR) - prt_str(out, __bch2_compression_types[type]); - else - prt_printf(out, "(invalid compression type %u)", type); -} - int bch2_bio_uncompress_inplace(struct bch_fs *, struct bio *, struct bch_extent_crc_unpacked *); int bch2_bio_uncompress(struct bch_fs *, struct bio *, struct bio *, diff --git a/fs/bcachefs/ec.c b/fs/bcachefs/ec.c index c0b2b2f180e0..556a217108d3 100644 --- a/fs/bcachefs/ec.c +++ b/fs/bcachefs/ec.c @@ -138,13 +138,13 @@ void bch2_stripe_to_text(struct printbuf *out, struct bch_fs *c, unsigned nr_data = s.nr_blocks - s.nr_redundant; - prt_printf(out, "algo %u sectors %u blocks %u:%u csum %u gran %u", + prt_printf(out, "algo %u sectors %u blocks %u:%u csum ", s.algorithm, le16_to_cpu(s.sectors), nr_data, - s.nr_redundant, - s.csum_type, - 1U << s.csum_granularity_bits); + s.nr_redundant); + bch2_prt_csum_type(out, s.csum_type); + prt_printf(out, " gran %u", 1U << s.csum_granularity_bits); for (unsigned i = 0; i < s.nr_blocks; i++) { const struct bch_extent_ptr *ptr = sp->ptrs + i; @@ -611,10 +611,8 @@ static void ec_validate_checksums(struct bch_fs *c, struct ec_stripe_buf *buf) struct printbuf err = PRINTBUF; struct bch_dev *ca = bch_dev_bkey_exists(c, v->ptrs[i].dev); - prt_printf(&err, "stripe checksum error: expected %0llx:%0llx got %0llx:%0llx (type %s)\n", - want.hi, want.lo, - got.hi, got.lo, - bch2_csum_types[v->csum_type]); + prt_str(&err, "stripe "); + bch2_csum_err_msg(&err, v->csum_type, want, got); prt_printf(&err, " for %ps at %u of\n ", (void *) _RET_IP_, i); bch2_bkey_val_to_text(&err, c, bkey_i_to_s_c(&buf->key)); bch_err_ratelimited(ca, "%s", err.buf); diff --git a/fs/bcachefs/extents.c b/fs/bcachefs/extents.c index 36d12d2adb81..1a331e539204 100644 --- a/fs/bcachefs/extents.c +++ b/fs/bcachefs/extents.c @@ -1030,11 +1030,12 @@ void bch2_bkey_ptrs_to_text(struct printbuf *out, struct bch_fs *c, struct bch_extent_crc_unpacked crc = bch2_extent_crc_unpack(k.k, entry_to_crc(entry)); - prt_printf(out, "crc: c_size %u size %u offset %u nonce %u csum %s compress ", + prt_printf(out, "crc: c_size %u size %u offset %u nonce %u csum ", crc.compressed_size, crc.uncompressed_size, - crc.offset, crc.nonce, - bch2_csum_types[crc.csum_type]); + crc.offset, crc.nonce); + bch2_prt_csum_type(out, crc.csum_type); + prt_str(out, " compress "); bch2_prt_compression_type(out, crc.compression_type); break; } diff --git a/fs/bcachefs/journal_io.c b/fs/bcachefs/journal_io.c index 725fcf46f631..9aa28b52ab92 100644 --- a/fs/bcachefs/journal_io.c +++ b/fs/bcachefs/journal_io.c @@ -247,7 +247,7 @@ static void journal_entry_err_msg(struct printbuf *out, if (entry) { prt_str(out, " type="); - prt_str(out, bch2_jset_entry_types[entry->type]); + bch2_prt_jset_entry_type(out, entry->type); } if (!jset) { @@ -403,7 +403,8 @@ static void journal_entry_btree_keys_to_text(struct printbuf *out, struct bch_fs jset_entry_for_each_key(entry, k) { if (!first) { prt_newline(out); - prt_printf(out, "%s: ", bch2_jset_entry_types[entry->type]); + bch2_prt_jset_entry_type(out, entry->type); + prt_str(out, ": "); } prt_printf(out, "btree=%s l=%u ", bch2_btree_id_str(entry->btree_id), entry->level); bch2_bkey_val_to_text(out, c, bkey_i_to_s_c(k)); @@ -563,9 +564,9 @@ static void journal_entry_usage_to_text(struct printbuf *out, struct bch_fs *c, struct jset_entry_usage *u = container_of(entry, struct jset_entry_usage, entry); - prt_printf(out, "type=%s v=%llu", - bch2_fs_usage_types[u->entry.btree_id], - le64_to_cpu(u->v)); + prt_str(out, "type="); + bch2_prt_fs_usage_type(out, u->entry.btree_id); + prt_printf(out, " v=%llu", le64_to_cpu(u->v)); } static int journal_entry_data_usage_validate(struct bch_fs *c, @@ -827,11 +828,11 @@ int bch2_journal_entry_validate(struct bch_fs *c, void bch2_journal_entry_to_text(struct printbuf *out, struct bch_fs *c, struct jset_entry *entry) { + bch2_prt_jset_entry_type(out, entry->type); + if (entry->type < BCH_JSET_ENTRY_NR) { - prt_printf(out, "%s: ", bch2_jset_entry_types[entry->type]); + prt_str(out, ": "); bch2_jset_entry_ops[entry->type].to_text(out, c, entry); - } else { - prt_printf(out, "(unknown type %u)", entry->type); } } diff --git a/fs/bcachefs/opts.c b/fs/bcachefs/opts.c index e1800c4119b5..bb068fd72465 100644 --- a/fs/bcachefs/opts.c +++ b/fs/bcachefs/opts.c @@ -43,7 +43,7 @@ const char * const __bch2_btree_ids[] = { NULL }; -const char * const bch2_csum_types[] = { +static const char * const __bch2_csum_types[] = { BCH_CSUM_TYPES() NULL }; @@ -53,7 +53,7 @@ const char * const bch2_csum_opts[] = { NULL }; -const char * const __bch2_compression_types[] = { +static const char * const __bch2_compression_types[] = { BCH_COMPRESSION_TYPES() NULL }; @@ -83,18 +83,39 @@ const char * const bch2_member_states[] = { NULL }; -const char * const bch2_jset_entry_types[] = { +static const char * const __bch2_jset_entry_types[] = { BCH_JSET_ENTRY_TYPES() NULL }; -const char * const bch2_fs_usage_types[] = { +static const char * const __bch2_fs_usage_types[] = { BCH_FS_USAGE_TYPES() NULL }; #undef x +static void prt_str_opt_boundscheck(struct printbuf *out, const char * const opts[], + unsigned nr, const char *type, unsigned idx) +{ + if (idx < nr) + prt_str(out, opts[idx]); + else + prt_printf(out, "(unknown %s %u)", type, idx); +} + +#define PRT_STR_OPT_BOUNDSCHECKED(name, type) \ +void bch2_prt_##name(struct printbuf *out, type t) \ +{ \ + prt_str_opt_boundscheck(out, __bch2_##name##s, ARRAY_SIZE(__bch2_##name##s) - 1, #name, t);\ +} + +PRT_STR_OPT_BOUNDSCHECKED(jset_entry_type, enum bch_jset_entry_type); +PRT_STR_OPT_BOUNDSCHECKED(fs_usage_type, enum bch_fs_usage_type); +PRT_STR_OPT_BOUNDSCHECKED(data_type, enum bch_data_type); +PRT_STR_OPT_BOUNDSCHECKED(csum_type, enum bch_csum_type); +PRT_STR_OPT_BOUNDSCHECKED(compression_type, enum bch_compression_type); + static int bch2_opt_fix_errors_parse(struct bch_fs *c, const char *val, u64 *res, struct printbuf *err) { diff --git a/fs/bcachefs/opts.h b/fs/bcachefs/opts.h index 1ac4135cca1c..84e452835a17 100644 --- a/fs/bcachefs/opts.h +++ b/fs/bcachefs/opts.h @@ -16,18 +16,20 @@ extern const char * const bch2_version_upgrade_opts[]; extern const char * const bch2_sb_features[]; extern const char * const bch2_sb_compat[]; extern const char * const __bch2_btree_ids[]; -extern const char * const bch2_csum_types[]; extern const char * const bch2_csum_opts[]; -extern const char * const __bch2_compression_types[]; extern const char * const bch2_compression_opts[]; extern const char * const bch2_str_hash_types[]; extern const char * const bch2_str_hash_opts[]; extern const char * const __bch2_data_types[]; extern const char * const bch2_member_states[]; -extern const char * const bch2_jset_entry_types[]; -extern const char * const bch2_fs_usage_types[]; extern const char * const bch2_d_types[]; +void bch2_prt_jset_entry_type(struct printbuf *, enum bch_jset_entry_type); +void bch2_prt_fs_usage_type(struct printbuf *, enum bch_fs_usage_type); +void bch2_prt_data_type(struct printbuf *, enum bch_data_type); +void bch2_prt_csum_type(struct printbuf *, enum bch_csum_type); +void bch2_prt_compression_type(struct printbuf *, enum bch_compression_type); + static inline const char *bch2_d_type_str(unsigned d_type) { return (d_type < BCH_DT_MAX ? bch2_d_types[d_type] : NULL) ?: "(bad d_type)"; -- cgit v1.2.3 From 4518e80adfdbfdec1cc79c98bc73677ff44d96bd Mon Sep 17 00:00:00 2001 From: Kent Overstreet Date: Fri, 12 Apr 2024 14:05:36 -0400 Subject: bcachefs: Go rw if running any explicit recovery passes This fixes a bug where we fail to start when upgrading/downgrading because we forgot we needed to go rw. Signed-off-by: Kent Overstreet --- fs/bcachefs/recovery_passes.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/bcachefs/recovery_passes.c b/fs/bcachefs/recovery_passes.c index cb501460d615..0cec0f7d9703 100644 --- a/fs/bcachefs/recovery_passes.c +++ b/fs/bcachefs/recovery_passes.c @@ -44,7 +44,7 @@ static int bch2_set_may_go_rw(struct bch_fs *c) set_bit(BCH_FS_may_go_rw, &c->flags); - if (keys->nr || c->opts.fsck || !c->sb.clean) + if (keys->nr || c->opts.fsck || !c->sb.clean || c->recovery_passes_explicit) return bch2_fs_read_write_early(c); return 0; } -- cgit v1.2.3 From 82cf18f23e1ae17053983e325e550194f947e1f1 Mon Sep 17 00:00:00 2001 From: Kent Overstreet Date: Fri, 12 Apr 2024 21:07:05 -0400 Subject: bcachefs: Fix deadlock in journal replay btree_key_can_insert_cached() should be checking the watermark - BCH_TRANS_COMMIT_journal_replay really means nonblocking mode when watermark < reclaim, it was being used incorrectly. Signed-off-by: Kent Overstreet --- fs/bcachefs/btree_trans_commit.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/fs/bcachefs/btree_trans_commit.c b/fs/bcachefs/btree_trans_commit.c index 9609ad370d71..bbec91e8e650 100644 --- a/fs/bcachefs/btree_trans_commit.c +++ b/fs/bcachefs/btree_trans_commit.c @@ -397,12 +397,13 @@ static int btree_key_can_insert_cached(struct btree_trans *trans, unsigned flags struct bkey_cached *ck = (void *) path->l[0].b; unsigned new_u64s; struct bkey_i *new_k; + unsigned watermark = flags & BCH_WATERMARK_MASK; EBUG_ON(path->level); - if (!test_bit(BKEY_CACHED_DIRTY, &ck->flags) && - bch2_btree_key_cache_must_wait(c) && - !(flags & BCH_TRANS_COMMIT_journal_reclaim)) + if (watermark < BCH_WATERMARK_reclaim && + !test_bit(BKEY_CACHED_DIRTY, &ck->flags) && + bch2_btree_key_cache_must_wait(c)) return -BCH_ERR_btree_insert_need_journal_reclaim; /* -- cgit v1.2.3 From 9e203c43dc1cbaefb3888ee0ba885b2d20d47526 Mon Sep 17 00:00:00 2001 From: Kent Overstreet Date: Sat, 13 Apr 2024 00:26:01 -0400 Subject: bcachefs: Fix missing write refs in fs fio paths bch2_journal_flush_seq requires us to have a write ref Signed-off-by: Kent Overstreet --- fs/bcachefs/bcachefs.h | 2 ++ fs/bcachefs/fs-io-direct.c | 19 +++++++++++++------ fs/bcachefs/fs-io.c | 16 ++++++++-------- 3 files changed, 23 insertions(+), 14 deletions(-) diff --git a/fs/bcachefs/bcachefs.h b/fs/bcachefs/bcachefs.h index a31a5f706929..91c3c1fef233 100644 --- a/fs/bcachefs/bcachefs.h +++ b/fs/bcachefs/bcachefs.h @@ -709,6 +709,8 @@ struct btree_trans_buf { x(stripe_delete) \ x(reflink) \ x(fallocate) \ + x(fsync) \ + x(dio_write) \ x(discard) \ x(discard_fast) \ x(invalidate) \ diff --git a/fs/bcachefs/fs-io-direct.c b/fs/bcachefs/fs-io-direct.c index f49e6c0f0f68..b889370a5088 100644 --- a/fs/bcachefs/fs-io-direct.c +++ b/fs/bcachefs/fs-io-direct.c @@ -387,6 +387,8 @@ static __always_inline long bch2_dio_write_done(struct dio_write *dio) ret = dio->op.error ?: ((long) dio->written << 9); bio_put(&dio->op.wbio.bio); + bch2_write_ref_put(dio->op.c, BCH_WRITE_REF_dio_write); + /* inode->i_dio_count is our ref on inode and thus bch_fs */ inode_dio_end(&inode->v); @@ -590,22 +592,25 @@ ssize_t bch2_direct_write(struct kiocb *req, struct iov_iter *iter) prefetch(&inode->ei_inode); prefetch((void *) &inode->ei_inode + 64); + if (!bch2_write_ref_tryget(c, BCH_WRITE_REF_dio_write)) + return -EROFS; + inode_lock(&inode->v); ret = generic_write_checks(req, iter); if (unlikely(ret <= 0)) - goto err; + goto err_put_write_ref; ret = file_remove_privs(file); if (unlikely(ret)) - goto err; + goto err_put_write_ref; ret = file_update_time(file); if (unlikely(ret)) - goto err; + goto err_put_write_ref; if (unlikely((req->ki_pos|iter->count) & (block_bytes(c) - 1))) - goto err; + goto err_put_write_ref; inode_dio_begin(&inode->v); bch2_pagecache_block_get(inode); @@ -645,7 +650,7 @@ ssize_t bch2_direct_write(struct kiocb *req, struct iov_iter *iter) } ret = bch2_dio_write_loop(dio); -err: +out: if (locked) inode_unlock(&inode->v); return ret; @@ -653,7 +658,9 @@ err_put_bio: bch2_pagecache_block_put(inode); bio_put(bio); inode_dio_end(&inode->v); - goto err; +err_put_write_ref: + bch2_write_ref_put(c, BCH_WRITE_REF_dio_write); + goto out; } void bch2_fs_fs_io_direct_exit(struct bch_fs *c) diff --git a/fs/bcachefs/fs-io.c b/fs/bcachefs/fs-io.c index 8c70123b6a0c..20b40477425f 100644 --- a/fs/bcachefs/fs-io.c +++ b/fs/bcachefs/fs-io.c @@ -174,18 +174,18 @@ void __bch2_i_sectors_acct(struct bch_fs *c, struct bch_inode_info *inode, static int bch2_flush_inode(struct bch_fs *c, struct bch_inode_info *inode) { - struct bch_inode_unpacked u; - int ret; - if (c->opts.journal_flush_disabled) return 0; - ret = bch2_inode_find_by_inum(c, inode_inum(inode), &u); - if (ret) - return ret; + if (!bch2_write_ref_tryget(c, BCH_WRITE_REF_fsync)) + return -EROFS; - return bch2_journal_flush_seq(&c->journal, u.bi_journal_seq) ?: - bch2_inode_flush_nocow_writes(c, inode); + struct bch_inode_unpacked u; + int ret = bch2_inode_find_by_inum(c, inode_inum(inode), &u) ?: + bch2_journal_flush_seq(&c->journal, u.bi_journal_seq) ?: + bch2_inode_flush_nocow_writes(c, inode); + bch2_write_ref_put(c, BCH_WRITE_REF_fsync); + return ret; } int bch2_fsync(struct file *file, loff_t start, loff_t end, int datasync) -- cgit v1.2.3 From 9054ef2ea944528b7935d0ce3f540d4dc0bc37ba Mon Sep 17 00:00:00 2001 From: Kent Overstreet Date: Sat, 13 Apr 2024 16:13:13 -0400 Subject: bcachefs: Run merges at BCH_WATERMARK_btree This fixes a deadlock where the interior update path during journal replay ends up doing a ton of merges on the backpointers btree, and deadlocking. Signed-off-by: Kent Overstreet --- fs/bcachefs/btree_update_interior.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/fs/bcachefs/btree_update_interior.c b/fs/bcachefs/btree_update_interior.c index 29a5bc7d8789..1a7537ee4329 100644 --- a/fs/bcachefs/btree_update_interior.c +++ b/fs/bcachefs/btree_update_interior.c @@ -1926,6 +1926,8 @@ int __bch2_foreground_maybe_merge(struct btree_trans *trans, BUG_ON(!trans->paths[path].should_be_locked); BUG_ON(!btree_node_locked(&trans->paths[path], level)); + flags &= ~BCH_WATERMARK_MASK; + b = trans->paths[path].l[level].b; if ((sib == btree_prev_sib && bpos_eq(b->data->min_key, POS_MIN)) || @@ -2071,6 +2073,10 @@ err: bch2_path_put(trans, new_path, true); bch2_path_put(trans, sib_path, true); bch2_trans_verify_locks(trans); + if (ret == -BCH_ERR_journal_reclaim_would_deadlock) + ret = 0; + if (!ret) + ret = bch2_trans_relock(trans); return ret; err_free_update: bch2_btree_node_free_never_used(as, trans, n); -- cgit v1.2.3 From 3f10048973c8366e27147d72bf3fd8d0e1d929f2 Mon Sep 17 00:00:00 2001 From: Kent Overstreet Date: Sat, 13 Apr 2024 18:39:03 -0400 Subject: bcachefs: Disable merges from interior update path There's been a bug in the btree write buffer where it wasn't triggering btree node merges - and leaving behind a bunch of nearly empty btree nodes. Then during journal replay, when updates to the backpointers btree aren't using the btree write buffer (because we require synchronization with journal replay), we end up doing those merges all at once. Then if it's the interior update path running them, we deadlock because those run with the highest watermark. There's no real need for the interior update path to be doing btree node merges; other code paths can handle that at lower watermarks. Signed-off-by: Kent Overstreet --- fs/bcachefs/btree_update_interior.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/fs/bcachefs/btree_update_interior.c b/fs/bcachefs/btree_update_interior.c index 1a7537ee4329..82ac00aa0f7b 100644 --- a/fs/bcachefs/btree_update_interior.c +++ b/fs/bcachefs/btree_update_interior.c @@ -1926,6 +1926,16 @@ int __bch2_foreground_maybe_merge(struct btree_trans *trans, BUG_ON(!trans->paths[path].should_be_locked); BUG_ON(!btree_node_locked(&trans->paths[path], level)); + /* + * Work around a deadlock caused by the btree write buffer not doing + * merges and leaving tons of merges for us to do - we really don't need + * to be doing merges at all from the interior update path, and if the + * interior update path is generating too many new interior updates we + * deadlock: + */ + if ((flags & BCH_WATERMARK_MASK) == BCH_WATERMARK_interior_updates) + return 0; + flags &= ~BCH_WATERMARK_MASK; b = trans->paths[path].l[level].b; -- cgit v1.2.3 From 86dbf8c566417afd62087ecd3bedcf84f91ee4e4 Mon Sep 17 00:00:00 2001 From: Kent Overstreet Date: Tue, 26 Dec 2023 22:42:34 -0500 Subject: bcachefs: Fix btree node merging on write buffer btrees The btree write buffer flush fastpath that avoids the main transaction commit path had the unfortunate side effect of not doing btree node merging. Signed-off-by: Kent Overstreet --- fs/bcachefs/btree_write_buffer.c | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/fs/bcachefs/btree_write_buffer.c b/fs/bcachefs/btree_write_buffer.c index baf63e2fddb6..36a6f42aba5e 100644 --- a/fs/bcachefs/btree_write_buffer.c +++ b/fs/bcachefs/btree_write_buffer.c @@ -316,6 +316,16 @@ static int bch2_btree_write_buffer_flush_locked(struct btree_trans *trans) bpos_gt(k->k.k.p, path->l[0].b->key.k.p)) { bch2_btree_node_unlock_write(trans, path, path->l[0].b); write_locked = false; + + ret = lockrestart_do(trans, + bch2_btree_iter_traverse(&iter) ?: + bch2_foreground_maybe_merge(trans, iter.path, 0, + BCH_WATERMARK_reclaim| + BCH_TRANS_COMMIT_journal_reclaim| + BCH_TRANS_COMMIT_no_check_rw| + BCH_TRANS_COMMIT_no_enospc)); + if (ret) + goto err; } } @@ -382,10 +392,10 @@ static int bch2_btree_write_buffer_flush_locked(struct btree_trans *trans) ret = commit_do(trans, NULL, NULL, BCH_WATERMARK_reclaim| + BCH_TRANS_COMMIT_journal_reclaim| BCH_TRANS_COMMIT_no_check_rw| BCH_TRANS_COMMIT_no_enospc| - BCH_TRANS_COMMIT_no_journal_res| - BCH_TRANS_COMMIT_journal_reclaim, + BCH_TRANS_COMMIT_no_journal_res , btree_write_buffered_insert(trans, i)); if (ret) goto err; -- cgit v1.2.3 From 7fda0efaa5fe6e93bb79a3a540a4b881ef788f66 Mon Sep 17 00:00:00 2001 From: Bard Liao Date: Thu, 11 Apr 2024 17:03:36 -0500 Subject: ASoC: Intel: sof_sdw: add missing sof_sdw_rt_amp_init for Realtek multi-function codecs We do need "info->amp_num++;" for the speaker dai. Signed-off-by: Bard Liao Signed-off-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20240411220347.131267-2-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/intel/boards/sof_sdw.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/sound/soc/intel/boards/sof_sdw.c b/sound/soc/intel/boards/sof_sdw.c index b94835448b1b..8a2cd19d8be6 100644 --- a/sound/soc/intel/boards/sof_sdw.c +++ b/sound/soc/intel/boards/sof_sdw.c @@ -737,6 +737,8 @@ static struct sof_sdw_codec_info codec_info_list[] = { .dai_name = "rt712-sdca-aif2", .dai_type = SOF_SDW_DAI_TYPE_AMP, .dailink = {SDW_AMP_OUT_DAI_ID, SDW_UNUSED_DAI_ID}, + .init = sof_sdw_rt_amp_init, + .exit = sof_sdw_rt_amp_exit, .rtd_init = rt712_spk_rtd_init, }, }, @@ -912,6 +914,8 @@ static struct sof_sdw_codec_info codec_info_list[] = { .dai_type = SOF_SDW_DAI_TYPE_AMP, /* No feedback capability is provided by rt722-sdca codec driver*/ .dailink = {SDW_AMP_OUT_DAI_ID, SDW_UNUSED_DAI_ID}, + .init = sof_sdw_rt_amp_init, + .exit = sof_sdw_rt_amp_exit, .rtd_init = rt722_spk_rtd_init, }, { -- cgit v1.2.3 From 0f8edb15fb6e436f0da7ab25ffcbcaab3def7e8c Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Thu, 11 Apr 2024 17:03:37 -0500 Subject: ASoC: Intel: soc-acpi: add support for HP Omen14 SoundWire configuration This platform has an RT711-sdca on link0 and RT1316 on link3 Closes: https://github.com/thesofproject/linux/issues/4880 Signed-off-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20240411220347.131267-3-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/intel/common/soc-acpi-intel-mtl-match.c | 29 +++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/sound/soc/intel/common/soc-acpi-intel-mtl-match.c b/sound/soc/intel/common/soc-acpi-intel-mtl-match.c index 75935b454e5d..264f5c19af56 100644 --- a/sound/soc/intel/common/soc-acpi-intel-mtl-match.c +++ b/sound/soc/intel/common/soc-acpi-intel-mtl-match.c @@ -296,6 +296,15 @@ static const struct snd_soc_acpi_adr_device rt1316_2_group2_adr[] = { } }; +static const struct snd_soc_acpi_adr_device rt1316_3_single_adr[] = { + { + .adr = 0x000330025D131601ull, + .num_endpoints = 1, + .endpoints = &single_endpoint, + .name_prefix = "rt1316-1" + } +}; + static const struct snd_soc_acpi_adr_device rt1318_1_group1_adr[] = { { .adr = 0x000130025D131801ull, @@ -562,6 +571,20 @@ static const struct snd_soc_acpi_link_adr mtl_rt713_l0_rt1316_l12[] = { {} }; +static const struct snd_soc_acpi_link_adr mtl_rt711_l0_rt1316_l3[] = { + { + .mask = BIT(0), + .num_adr = ARRAY_SIZE(rt711_sdca_0_adr), + .adr_d = rt711_sdca_0_adr, + }, + { + .mask = BIT(3), + .num_adr = ARRAY_SIZE(rt1316_3_single_adr), + .adr_d = rt1316_3_single_adr, + }, + {} +}; + static const struct snd_soc_acpi_adr_device mx8363_2_adr[] = { { .adr = 0x000230019F836300ull, @@ -703,6 +726,12 @@ struct snd_soc_acpi_mach snd_soc_acpi_intel_mtl_sdw_machines[] = { .drv_name = "sof_sdw", .sof_tplg_filename = "sof-mtl-rt711-l0-rt1316-l23-rt714-l1.tplg", }, + { + .link_mask = 0x9, /* 2 active links required */ + .links = mtl_rt711_l0_rt1316_l3, + .drv_name = "sof_sdw", + .sof_tplg_filename = "sof-mtl-rt711-l0-rt1316-l3.tplg", + }, { .link_mask = BIT(0), .links = mtl_rt722_only, -- cgit v1.2.3 From 4fee07fbf47d2a5f1065d985459e5ce7bf7969f0 Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Thu, 11 Apr 2024 17:03:38 -0500 Subject: ASoC: Intel: sof_sdw: add JD2 quirk for HP Omen 14 The default JD1 does not seem to work, use JD2 instead. Signed-off-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20240411220347.131267-4-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/intel/boards/sof_sdw.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/sound/soc/intel/boards/sof_sdw.c b/sound/soc/intel/boards/sof_sdw.c index 8a2cd19d8be6..f191dc72bc3d 100644 --- a/sound/soc/intel/boards/sof_sdw.c +++ b/sound/soc/intel/boards/sof_sdw.c @@ -498,6 +498,15 @@ static const struct dmi_system_id sof_sdw_quirk_table[] = { SOF_BT_OFFLOAD_SSP(1) | SOF_SSP_BT_OFFLOAD_PRESENT), }, + { + .callback = sof_sdw_quirk_cb, + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "HP"), + DMI_MATCH(DMI_PRODUCT_NAME, "OMEN Transcend Gaming Laptop"), + }, + .driver_data = (void *)(RT711_JD2), + }, + /* LunarLake devices */ { .callback = sof_sdw_quirk_cb, -- cgit v1.2.3 From b10cb955c6c0b8dbd9a768166d71cc12680b7fdf Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Thu, 11 Apr 2024 17:03:39 -0500 Subject: ASoC: Intel: sof_sdw: add quirk for Dell SKU 0C0F The JD1 jack detection doesn't seem to work, use JD2. Also use the 4 speaker configuration. Link: https://github.com/thesofproject/linux/issues/4900 Signed-off-by: Pierre-Louis Bossart Reviewed-by: Bard Liao Link: https://lore.kernel.org/r/20240411220347.131267-5-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/intel/boards/sof_sdw.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/sound/soc/intel/boards/sof_sdw.c b/sound/soc/intel/boards/sof_sdw.c index f191dc72bc3d..6253fc464198 100644 --- a/sound/soc/intel/boards/sof_sdw.c +++ b/sound/soc/intel/boards/sof_sdw.c @@ -432,6 +432,16 @@ static const struct dmi_system_id sof_sdw_quirk_table[] = { RT711_JD2 | SOF_SDW_FOUR_SPK), }, + { + .callback = sof_sdw_quirk_cb, + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"), + DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0C0F") + }, + .driver_data = (void *)(SOF_SDW_TGL_HDMI | + RT711_JD2 | + SOF_SDW_FOUR_SPK), + }, { .callback = sof_sdw_quirk_cb, .matches = { -- cgit v1.2.3 From 744866d28fe6b1a651e63d03a57e06d66e3d460a Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Thu, 11 Apr 2024 17:03:40 -0500 Subject: ASoC: Intel: sof_sdw: remove FOUR_SPEAKER quirks This patch removes a confusion between speakers and amplifiers. The existing code keeps track of the number of amplifiers and reports it in the 'cfg-amp' component string. The number of speakers is defined with quirks, but those quirks are not consistently added: in the MeteorLake case, none of the supported platforms used such a quirk, and UCM does not use the values reported anyways. The notion of 'FOUR_SPEAKERS' is also obsolete now with some platforms having more than four speakers. Let's just remove all this and only report the number of amplifiers. Signed-off-by: Pierre-Louis Bossart Reviewed-by: Bard Liao Link: https://lore.kernel.org/r/20240411220347.131267-6-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/intel/boards/sof_sdw.c | 68 +++++++++++---------------------- sound/soc/intel/boards/sof_sdw_common.h | 1 + 2 files changed, 23 insertions(+), 46 deletions(-) diff --git a/sound/soc/intel/boards/sof_sdw.c b/sound/soc/intel/boards/sof_sdw.c index 6253fc464198..d65c5da49000 100644 --- a/sound/soc/intel/boards/sof_sdw.c +++ b/sound/soc/intel/boards/sof_sdw.c @@ -27,7 +27,7 @@ static void log_quirks(struct device *dev) dev_dbg(dev, "quirk realtek,jack-detect-source %ld\n", SOF_JACK_JDSRC(sof_sdw_quirk)); if (sof_sdw_quirk & SOF_SDW_FOUR_SPK) - dev_dbg(dev, "quirk SOF_SDW_FOUR_SPK enabled\n"); + dev_err(dev, "quirk SOF_SDW_FOUR_SPK enabled but no longer supported\n"); if (sof_sdw_quirk & SOF_SDW_TGL_HDMI) dev_dbg(dev, "quirk SOF_SDW_TGL_HDMI enabled\n"); if (sof_sdw_quirk & SOF_SDW_PCH_DMIC) @@ -80,8 +80,7 @@ static const struct dmi_system_id sof_sdw_quirk_table[] = { DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"), DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "098F"), }, - .driver_data = (void *)(RT711_JD2 | - SOF_SDW_FOUR_SPK), + .driver_data = (void *)(RT711_JD2), }, { .callback = sof_sdw_quirk_cb, @@ -89,8 +88,7 @@ static const struct dmi_system_id sof_sdw_quirk_table[] = { DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"), DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0990"), }, - .driver_data = (void *)(RT711_JD2 | - SOF_SDW_FOUR_SPK), + .driver_data = (void *)(RT711_JD2), }, /* IceLake devices */ { @@ -141,8 +139,7 @@ static const struct dmi_system_id sof_sdw_quirk_table[] = { DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0A5D") }, .driver_data = (void *)(SOF_SDW_TGL_HDMI | - RT711_JD2 | - SOF_SDW_FOUR_SPK), + RT711_JD2), }, { .callback = sof_sdw_quirk_cb, @@ -151,8 +148,7 @@ static const struct dmi_system_id sof_sdw_quirk_table[] = { DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0A5E") }, .driver_data = (void *)(SOF_SDW_TGL_HDMI | - RT711_JD2 | - SOF_SDW_FOUR_SPK), + RT711_JD2), }, { .callback = sof_sdw_quirk_cb, @@ -162,7 +158,6 @@ static const struct dmi_system_id sof_sdw_quirk_table[] = { }, .driver_data = (void *)(SOF_SDW_TGL_HDMI | SOF_SDW_PCH_DMIC | - SOF_SDW_FOUR_SPK | SOF_BT_OFFLOAD_SSP(2) | SOF_SSP_BT_OFFLOAD_PRESENT), }, @@ -173,8 +168,7 @@ static const struct dmi_system_id sof_sdw_quirk_table[] = { DMI_MATCH(DMI_PRODUCT_NAME, "Ripto"), }, .driver_data = (void *)(SOF_SDW_TGL_HDMI | - SOF_SDW_PCH_DMIC | - SOF_SDW_FOUR_SPK), + SOF_SDW_PCH_DMIC), }, { /* @@ -258,8 +252,7 @@ static const struct dmi_system_id sof_sdw_quirk_table[] = { DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0A32") }, .driver_data = (void *)(SOF_SDW_TGL_HDMI | - RT711_JD2 | - SOF_SDW_FOUR_SPK), + RT711_JD2), }, { .callback = sof_sdw_quirk_cb, @@ -290,7 +283,6 @@ static const struct dmi_system_id sof_sdw_quirk_table[] = { }, .driver_data = (void *)(SOF_SDW_TGL_HDMI | SOF_SDW_PCH_DMIC | - SOF_SDW_FOUR_SPK | SOF_BT_OFFLOAD_SSP(2) | SOF_SSP_BT_OFFLOAD_PRESENT), }, @@ -301,8 +293,7 @@ static const struct dmi_system_id sof_sdw_quirk_table[] = { DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0AF0") }, .driver_data = (void *)(SOF_SDW_TGL_HDMI | - RT711_JD2 | - SOF_SDW_FOUR_SPK), + RT711_JD2), }, { .callback = sof_sdw_quirk_cb, @@ -311,8 +302,7 @@ static const struct dmi_system_id sof_sdw_quirk_table[] = { DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0AF3"), }, /* No Jack */ - .driver_data = (void *)(SOF_SDW_TGL_HDMI | - SOF_SDW_FOUR_SPK), + .driver_data = (void *)(SOF_SDW_TGL_HDMI), }, { .callback = sof_sdw_quirk_cb, @@ -321,8 +311,7 @@ static const struct dmi_system_id sof_sdw_quirk_table[] = { DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0AFE") }, .driver_data = (void *)(SOF_SDW_TGL_HDMI | - RT711_JD2 | - SOF_SDW_FOUR_SPK), + RT711_JD2), }, { .callback = sof_sdw_quirk_cb, @@ -331,8 +320,7 @@ static const struct dmi_system_id sof_sdw_quirk_table[] = { DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0AFF") }, .driver_data = (void *)(SOF_SDW_TGL_HDMI | - RT711_JD2 | - SOF_SDW_FOUR_SPK), + RT711_JD2), }, { .callback = sof_sdw_quirk_cb, @@ -341,8 +329,7 @@ static const struct dmi_system_id sof_sdw_quirk_table[] = { DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0B00") }, .driver_data = (void *)(SOF_SDW_TGL_HDMI | - RT711_JD2 | - SOF_SDW_FOUR_SPK), + RT711_JD2), }, { .callback = sof_sdw_quirk_cb, @@ -351,8 +338,7 @@ static const struct dmi_system_id sof_sdw_quirk_table[] = { DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0B01") }, .driver_data = (void *)(SOF_SDW_TGL_HDMI | - RT711_JD2 | - SOF_SDW_FOUR_SPK), + RT711_JD2), }, { .callback = sof_sdw_quirk_cb, @@ -361,8 +347,7 @@ static const struct dmi_system_id sof_sdw_quirk_table[] = { DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0B11") }, .driver_data = (void *)(SOF_SDW_TGL_HDMI | - RT711_JD2 | - SOF_SDW_FOUR_SPK), + RT711_JD2), }, { .callback = sof_sdw_quirk_cb, @@ -371,8 +356,7 @@ static const struct dmi_system_id sof_sdw_quirk_table[] = { DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0B12") }, .driver_data = (void *)(SOF_SDW_TGL_HDMI | - RT711_JD2 | - SOF_SDW_FOUR_SPK), + RT711_JD2), }, { .callback = sof_sdw_quirk_cb, @@ -400,8 +384,7 @@ static const struct dmi_system_id sof_sdw_quirk_table[] = { DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0B29"), }, .driver_data = (void *)(SOF_SDW_TGL_HDMI | - RT711_JD2 | - SOF_SDW_FOUR_SPK), + RT711_JD2), }, { .callback = sof_sdw_quirk_cb, @@ -429,8 +412,7 @@ static const struct dmi_system_id sof_sdw_quirk_table[] = { DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0BDA") }, .driver_data = (void *)(SOF_SDW_TGL_HDMI | - RT711_JD2 | - SOF_SDW_FOUR_SPK), + RT711_JD2), }, { .callback = sof_sdw_quirk_cb, @@ -449,8 +431,7 @@ static const struct dmi_system_id sof_sdw_quirk_table[] = { DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0C10"), }, /* No Jack */ - .driver_data = (void *)(SOF_SDW_TGL_HDMI | - SOF_SDW_FOUR_SPK), + .driver_data = (void *)(SOF_SDW_TGL_HDMI), }, { .callback = sof_sdw_quirk_cb, @@ -459,8 +440,7 @@ static const struct dmi_system_id sof_sdw_quirk_table[] = { DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0C11") }, .driver_data = (void *)(SOF_SDW_TGL_HDMI | - RT711_JD2 | - SOF_SDW_FOUR_SPK), + RT711_JD2), }, { .callback = sof_sdw_quirk_cb, @@ -469,8 +449,7 @@ static const struct dmi_system_id sof_sdw_quirk_table[] = { DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0C40") }, .driver_data = (void *)(SOF_SDW_TGL_HDMI | - RT711_JD2 | - SOF_SDW_FOUR_SPK), + RT711_JD2), }, { .callback = sof_sdw_quirk_cb, @@ -479,8 +458,7 @@ static const struct dmi_system_id sof_sdw_quirk_table[] = { DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0C4F") }, .driver_data = (void *)(SOF_SDW_TGL_HDMI | - RT711_JD2 | - SOF_SDW_FOUR_SPK), + RT711_JD2), }, /* MeteorLake devices */ { @@ -2010,9 +1988,7 @@ static int mc_probe(struct platform_device *pdev) amp_num += codec_info_list[i].amp_num; card->components = devm_kasprintf(card->dev, GFP_KERNEL, - "cfg-spk:%d cfg-amp:%d", - (sof_sdw_quirk & SOF_SDW_FOUR_SPK) - ? 4 : 2, amp_num); + "cfg-amp:%d", amp_num); if (!card->components) return -ENOMEM; diff --git a/sound/soc/intel/boards/sof_sdw_common.h b/sound/soc/intel/boards/sof_sdw_common.h index 8468487a6bd6..89253938ebaa 100644 --- a/sound/soc/intel/boards/sof_sdw_common.h +++ b/sound/soc/intel/boards/sof_sdw_common.h @@ -45,6 +45,7 @@ enum { }; #define SOF_JACK_JDSRC(quirk) ((quirk) & GENMASK(3, 0)) +/* Deprecated and no longer supported by the code */ #define SOF_SDW_FOUR_SPK BIT(4) #define SOF_SDW_TGL_HDMI BIT(5) #define SOF_SDW_PCH_DMIC BIT(6) -- cgit v1.2.3 From 36a621070b4854670c43138bb8b19bdf8df77bbd Mon Sep 17 00:00:00 2001 From: Brent Lu Date: Thu, 11 Apr 2024 17:03:41 -0500 Subject: ASoC: Intel: sof_da7219: mach cleanup for adl boards Add a common entry in enumeration table for all da7219 boards with/without speaker amplifier. All other adl_da7219_def entries become redundant so get removed. Reviewed-by: Bard Liao Signed-off-by: Brent Lu Signed-off-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20240411220347.131267-7-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/intel/common/soc-acpi-intel-adl-match.c | 19 +++++++------------ 1 file changed, 7 insertions(+), 12 deletions(-) diff --git a/sound/soc/intel/common/soc-acpi-intel-adl-match.c b/sound/soc/intel/common/soc-acpi-intel-adl-match.c index 1ea2d9c582ee..4167b2e9bc6a 100644 --- a/sound/soc/intel/common/soc-acpi-intel-adl-match.c +++ b/sound/soc/intel/common/soc-acpi-intel-adl-match.c @@ -453,11 +453,6 @@ static const struct snd_soc_acpi_codecs adl_max98357a_amp = { .codecs = {"MX98357A"} }; -static const struct snd_soc_acpi_codecs adl_max98360a_amp = { - .num_codecs = 1, - .codecs = {"MX98360A"} -}; - static const struct snd_soc_acpi_codecs adl_rt5682_rt5682s_hp = { .num_codecs = 2, .codecs = {RT5682_ACPI_HID, RT5682S_ACPI_HID}, @@ -510,13 +505,6 @@ struct snd_soc_acpi_mach snd_soc_acpi_intel_adl_machines[] = { SND_SOC_ACPI_TPLG_INTEL_SSP_MSB | SND_SOC_ACPI_TPLG_INTEL_DMIC_NUMBER, }, - { - .id = "DLGS7219", - .drv_name = "adl_da7219_def", - .machine_quirk = snd_soc_acpi_codec_list, - .quirk_data = &adl_max98360a_amp, - .sof_tplg_filename = "sof-adl-max98360a-da7219.tplg", - }, /* place boards for each headphone codec: sof driver will complete the * tplg name and machine driver will detect the amp type */ @@ -527,6 +515,13 @@ struct snd_soc_acpi_mach snd_soc_acpi_intel_adl_machines[] = { .tplg_quirk_mask = SND_SOC_ACPI_TPLG_INTEL_AMP_NAME | SND_SOC_ACPI_TPLG_INTEL_CODEC_NAME, }, + { + .id = DA7219_ACPI_HID, + .drv_name = "adl_da7219_def", + .sof_tplg_filename = "sof-adl", /* the tplg suffix is added at run time */ + .tplg_quirk_mask = SND_SOC_ACPI_TPLG_INTEL_AMP_NAME | + SND_SOC_ACPI_TPLG_INTEL_CODEC_NAME, + }, { .id = NAU8825_ACPI_HID, .drv_name = "adl_nau8825_def", -- cgit v1.2.3 From c3d1818f5ef5a9a930e468a799ccf1cade91e350 Mon Sep 17 00:00:00 2001 From: Brent Lu Date: Thu, 11 Apr 2024 17:03:42 -0500 Subject: ASoC: Intel: sof_da7219: mach cleanup for rpl boards Add a common entry in enumeration table for all da7219 boards with/without speaker amplifier. All other rpl_da7219_def entries become redundant so get removed. Reviewed-by: Bard Liao Signed-off-by: Brent Lu Signed-off-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20240411220347.131267-8-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/intel/common/soc-acpi-intel-rpl-match.c | 19 +++++++------------ 1 file changed, 7 insertions(+), 12 deletions(-) diff --git a/sound/soc/intel/common/soc-acpi-intel-rpl-match.c b/sound/soc/intel/common/soc-acpi-intel-rpl-match.c index 34588db6138a..b0a49e28ab09 100644 --- a/sound/soc/intel/common/soc-acpi-intel-rpl-match.c +++ b/sound/soc/intel/common/soc-acpi-intel-rpl-match.c @@ -361,11 +361,6 @@ static const struct snd_soc_acpi_codecs rpl_max98357a_amp = { .codecs = {"MX98357A"} }; -static const struct snd_soc_acpi_codecs rpl_max98360a_amp = { - .num_codecs = 1, - .codecs = {"MX98360A"}, -}; - static const struct snd_soc_acpi_codecs rpl_lt6911_hdmi = { .num_codecs = 1, .codecs = {"INTC10B0"} @@ -411,6 +406,13 @@ struct snd_soc_acpi_mach snd_soc_acpi_intel_rpl_machines[] = { .tplg_quirk_mask = SND_SOC_ACPI_TPLG_INTEL_AMP_NAME | SND_SOC_ACPI_TPLG_INTEL_CODEC_NAME, }, + { + .id = DA7219_ACPI_HID, + .drv_name = "rpl_da7219_def", + .sof_tplg_filename = "sof-rpl", /* the tplg suffix is added at run time */ + .tplg_quirk_mask = SND_SOC_ACPI_TPLG_INTEL_AMP_NAME | + SND_SOC_ACPI_TPLG_INTEL_CODEC_NAME, + }, { .id = NAU8825_ACPI_HID, .drv_name = "rpl_nau8825_def", @@ -438,13 +440,6 @@ struct snd_soc_acpi_mach snd_soc_acpi_intel_rpl_machines[] = { .drv_name = "rpl_lt6911_hdmi_ssp", .sof_tplg_filename = "sof-rpl-nocodec-hdmi-ssp02.tplg" }, - { - .id = "DLGS7219", - .drv_name = "rpl_da7219_def", - .machine_quirk = snd_soc_acpi_codec_list, - .quirk_data = &rpl_max98360a_amp, - .sof_tplg_filename = "sof-rpl-max98360a-da7219.tplg", - }, {}, }; EXPORT_SYMBOL_GPL(snd_soc_acpi_intel_rpl_machines); -- cgit v1.2.3 From fe18a4be97d4064c9f3113f819780162cc586f16 Mon Sep 17 00:00:00 2001 From: Brent Lu Date: Thu, 11 Apr 2024 17:03:43 -0500 Subject: ASoC: Intel: sof_da7219: add mtl_da7219_def for mtl boards Add the board config mtl_da7219_def to da7219 machine driver for all mtl boards using default SSP port allocation (headphone codec on SSP2, speaker amplifiers on SSP0, and BT offload on SSP1). Reviewed-by: Bard Liao Signed-off-by: Brent Lu Signed-off-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20240411220347.131267-9-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/intel/boards/sof_da7219.c | 8 ++++++++ sound/soc/intel/common/soc-acpi-intel-mtl-match.c | 7 +++++++ 2 files changed, 15 insertions(+) diff --git a/sound/soc/intel/boards/sof_da7219.c b/sound/soc/intel/boards/sof_da7219.c index fd3a7be993c1..cbbce07ec5f7 100644 --- a/sound/soc/intel/boards/sof_da7219.c +++ b/sound/soc/intel/boards/sof_da7219.c @@ -398,6 +398,14 @@ static const struct platform_device_id board_ids[] = { SOF_SSP_PORT_BT_OFFLOAD(2) | SOF_BT_OFFLOAD_PRESENT), }, + { + .name = "mtl_da7219_def", + .driver_data = (kernel_ulong_t)(SOF_DA7219_MCLK_EN | + SOF_SSP_PORT_CODEC(2) | + SOF_SSP_PORT_AMP(0) | + SOF_SSP_PORT_BT_OFFLOAD(1) | + SOF_BT_OFFLOAD_PRESENT), + }, { } }; MODULE_DEVICE_TABLE(platform, board_ids); diff --git a/sound/soc/intel/common/soc-acpi-intel-mtl-match.c b/sound/soc/intel/common/soc-acpi-intel-mtl-match.c index 264f5c19af56..f95490a16b55 100644 --- a/sound/soc/intel/common/soc-acpi-intel-mtl-match.c +++ b/sound/soc/intel/common/soc-acpi-intel-mtl-match.c @@ -76,6 +76,13 @@ struct snd_soc_acpi_mach snd_soc_acpi_intel_mtl_machines[] = { .tplg_quirk_mask = SND_SOC_ACPI_TPLG_INTEL_AMP_NAME | SND_SOC_ACPI_TPLG_INTEL_CODEC_NAME, }, + { + .id = DA7219_ACPI_HID, + .drv_name = "mtl_da7219_def", + .sof_tplg_filename = "sof-mtl", /* the tplg suffix is added at run time */ + .tplg_quirk_mask = SND_SOC_ACPI_TPLG_INTEL_AMP_NAME | + SND_SOC_ACPI_TPLG_INTEL_CODEC_NAME, + }, { .id = NAU8825_ACPI_HID, .drv_name = "mtl_nau8825_def", -- cgit v1.2.3 From 551fb5593c2bd34e8711efe01dddf22d9c6200b2 Mon Sep 17 00:00:00 2001 From: Brent Lu Date: Thu, 11 Apr 2024 17:03:44 -0500 Subject: ASoC: Intel: sof_realtek_common: support 4xALC1011 amplifier Add support for boards with four ALC1011 amplifiers. Configuration is copied from cml_rt1011_rt5682 machine driver for backward compatibility with existing cml devices. Reviewed-by: Chao Song Signed-off-by: Brent Lu Signed-off-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20240411220347.131267-10-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/intel/boards/sof_realtek_common.c | 178 ++++++++++++++++++++++++---- sound/soc/intel/boards/sof_realtek_common.h | 4 +- sound/soc/intel/boards/sof_rt5682.c | 4 +- 3 files changed, 162 insertions(+), 24 deletions(-) diff --git a/sound/soc/intel/boards/sof_realtek_common.c b/sound/soc/intel/boards/sof_realtek_common.c index 80c8687cd1da..20d094c52d28 100644 --- a/sound/soc/intel/boards/sof_realtek_common.c +++ b/sound/soc/intel/boards/sof_realtek_common.c @@ -15,10 +15,40 @@ #include "../../codecs/rt1011.h" #include "../../codecs/rt1015.h" #include "../../codecs/rt1308.h" +#include "../common/soc-intel-quirks.h" #include "sof_realtek_common.h" /* - * Current only 2-amp configuration is supported for rt1011 + * Common structures and functions + */ +static const struct snd_kcontrol_new realtek_4spk_kcontrols[] = { + SOC_DAPM_PIN_SWITCH("WL Ext Spk"), + SOC_DAPM_PIN_SWITCH("WR Ext Spk"), + SOC_DAPM_PIN_SWITCH("TL Ext Spk"), + SOC_DAPM_PIN_SWITCH("TR Ext Spk"), +}; + +static const struct snd_soc_dapm_widget realtek_4spk_widgets[] = { + SND_SOC_DAPM_SPK("WL Ext Spk", NULL), + SND_SOC_DAPM_SPK("WR Ext Spk", NULL), + SND_SOC_DAPM_SPK("TL Ext Spk", NULL), + SND_SOC_DAPM_SPK("TR Ext Spk", NULL), +}; + +/* helper function to get the number of specific codec */ +static unsigned int get_num_codecs(const char *hid) +{ + struct acpi_device *adev; + unsigned int dev_num = 0; + + for_each_acpi_dev_match(adev, hid, NULL, -1) + dev_num++; + + return dev_num; +} + +/* + * Realtek ALC1011 */ static const struct snd_soc_dapm_route speaker_map_lr[] = { /* speaker */ @@ -26,16 +56,14 @@ static const struct snd_soc_dapm_route speaker_map_lr[] = { { "Right Spk", NULL, "Right SPO" }, }; -/* - * Make sure device's Unique ID follows this configuration: - * - * Two speakers: - * 0: left, 1: right - * Four speakers: - * 0: Woofer left, 1: Woofer right - * 2: Tweeter left, 3: Tweeter right - */ -static struct snd_soc_codec_conf rt1011_codec_confs[] = { +static const struct snd_soc_dapm_route rt1011_4spk_routes[] = { + {"WL Ext Spk", NULL, "WL SPO" }, + {"WR Ext Spk", NULL, "WR SPO" }, + {"TL Ext Spk", NULL, "TL SPO" }, + {"TR Ext Spk", NULL, "TR SPO" }, +}; + +static struct snd_soc_codec_conf rt1011_2spk_codec_confs[] = { { .dlc = COMP_CODEC_CONF(RT1011_DEV0_NAME), .name_prefix = "Left", @@ -46,6 +74,25 @@ static struct snd_soc_codec_conf rt1011_codec_confs[] = { }, }; +static struct snd_soc_codec_conf rt1011_4spk_codec_confs[] = { + { + .dlc = COMP_CODEC_CONF(RT1011_DEV0_NAME), + .name_prefix = "WL", + }, + { + .dlc = COMP_CODEC_CONF(RT1011_DEV1_NAME), + .name_prefix = "WR", + }, + { + .dlc = COMP_CODEC_CONF(RT1011_DEV2_NAME), + .name_prefix = "TL", + }, + { + .dlc = COMP_CODEC_CONF(RT1011_DEV3_NAME), + .name_prefix = "TR", + }, +}; + static struct snd_soc_dai_link_component rt1011_dai_link_components[] = { { .name = RT1011_DEV0_NAME, @@ -55,6 +102,14 @@ static struct snd_soc_dai_link_component rt1011_dai_link_components[] = { .name = RT1011_DEV1_NAME, .dai_name = RT1011_CODEC_DAI, }, + { + .name = RT1011_DEV2_NAME, + .dai_name = RT1011_CODEC_DAI, + }, + { + .name = RT1011_DEV3_NAME, + .dai_name = RT1011_CODEC_DAI, + }, }; static const struct { @@ -63,6 +118,8 @@ static const struct { } rt1011_tdm_mask[] = { {.tx = 0x4, .rx = 0x1}, {.tx = 0x8, .rx = 0x2}, + {.tx = 0x1, .rx = 0x1}, + {.tx = 0x2, .rx = 0x2}, }; static int rt1011_hw_params(struct snd_pcm_substream *substream, @@ -118,28 +175,109 @@ static const struct snd_soc_ops rt1011_ops = { static int rt1011_init(struct snd_soc_pcm_runtime *rtd) { struct snd_soc_card *card = rtd->card; + unsigned int num_codecs = get_num_codecs(RT1011_ACPI_HID); int ret; - ret = snd_soc_dapm_add_routes(&card->dapm, speaker_map_lr, - ARRAY_SIZE(speaker_map_lr)); - if (ret) - dev_err(rtd->dev, "Speaker map addition failed: %d\n", ret); + switch (num_codecs) { + case 2: + if (!soc_intel_is_cml()) { + ret = snd_soc_dapm_add_routes(&card->dapm, speaker_map_lr, + ARRAY_SIZE(speaker_map_lr)); + if (ret) { + dev_err(rtd->dev, "fail to add rt1011 routes, ret %d\n", + ret); + return ret; + } + + break; + } + + /* + * register speaker widgets "WL Ext Spk" and "WR Ext Spk" to + * keep backward compatible with cml devices + */ + fallthrough; + case 4: + ret = snd_soc_dapm_new_controls(&card->dapm, realtek_4spk_widgets, + num_codecs); + if (ret) { + dev_err(rtd->dev, "fail to add rt1011 widgets, ret %d\n", + ret); + return ret; + } + + ret = snd_soc_add_card_controls(card, realtek_4spk_kcontrols, + num_codecs); + if (ret) { + dev_err(rtd->dev, "fail to add rt1011 controls, ret %d\n", + ret); + return ret; + } + + ret = snd_soc_dapm_add_routes(&card->dapm, rt1011_4spk_routes, + num_codecs); + if (ret) { + dev_err(rtd->dev, "fail to add rt1011 routes, ret %d\n", + ret); + return ret; + } + break; + default: + dev_err(rtd->dev, "rt1011: invalid num_codecs %d\n", num_codecs); + return -EINVAL; + } + return ret; } -void sof_rt1011_dai_link(struct snd_soc_dai_link *link) +void sof_rt1011_dai_link(struct device *dev, struct snd_soc_dai_link *link) { + unsigned int num_codecs = get_num_codecs(RT1011_ACPI_HID); + link->codecs = rt1011_dai_link_components; - link->num_codecs = ARRAY_SIZE(rt1011_dai_link_components); + + switch (num_codecs) { + case 2: + case 4: + link->num_codecs = num_codecs; + break; + default: + dev_err(dev, "rt1011: invalid num_codecs %d\n", num_codecs); + break; + } + link->init = rt1011_init; link->ops = &rt1011_ops; } EXPORT_SYMBOL_NS(sof_rt1011_dai_link, SND_SOC_INTEL_SOF_REALTEK_COMMON); -void sof_rt1011_codec_conf(struct snd_soc_card *card) +void sof_rt1011_codec_conf(struct device *dev, struct snd_soc_card *card) { - card->codec_conf = rt1011_codec_confs; - card->num_configs = ARRAY_SIZE(rt1011_codec_confs); + unsigned int num_codecs = get_num_codecs(RT1011_ACPI_HID); + + switch (num_codecs) { + case 2: + if (soc_intel_is_cml()) { + /* + * use name prefix 'WL' and 'WR' for speaker widgets to + * keep backward compatible with cml devices + */ + card->codec_conf = rt1011_4spk_codec_confs; + } else { + card->codec_conf = rt1011_2spk_codec_confs; + } + + card->num_configs = num_codecs; + break; + case 4: + card->codec_conf = rt1011_4spk_codec_confs; + card->num_configs = ARRAY_SIZE(rt1011_4spk_codec_confs); + break; + default: + dev_err(dev, "rt1011: invalid num_codecs %d\n", num_codecs); + break; + } + } EXPORT_SYMBOL_NS(sof_rt1011_codec_conf, SND_SOC_INTEL_SOF_REALTEK_COMMON); diff --git a/sound/soc/intel/boards/sof_realtek_common.h b/sound/soc/intel/boards/sof_realtek_common.h index 289e85b61660..d0e331530b39 100644 --- a/sound/soc/intel/boards/sof_realtek_common.h +++ b/sound/soc/intel/boards/sof_realtek_common.h @@ -23,8 +23,8 @@ #define RT1011_DEV2_NAME "i2c-" RT1011_ACPI_HID ":02" #define RT1011_DEV3_NAME "i2c-" RT1011_ACPI_HID ":03" -void sof_rt1011_dai_link(struct snd_soc_dai_link *link); -void sof_rt1011_codec_conf(struct snd_soc_card *card); +void sof_rt1011_dai_link(struct device *dev, struct snd_soc_dai_link *link); +void sof_rt1011_codec_conf(struct device *dev, struct snd_soc_card *card); /* * Realtek ALC1015 (AUTO) diff --git a/sound/soc/intel/boards/sof_rt5682.c b/sound/soc/intel/boards/sof_rt5682.c index 966bcd3e8bdc..326d23dd79de 100644 --- a/sound/soc/intel/boards/sof_rt5682.c +++ b/sound/soc/intel/boards/sof_rt5682.c @@ -576,7 +576,7 @@ sof_card_dai_links_create(struct device *dev, struct snd_soc_card *card, max_98390_dai_link(dev, ctx->amp_link); break; case CODEC_RT1011: - sof_rt1011_dai_link(ctx->amp_link); + sof_rt1011_dai_link(dev, ctx->amp_link); break; case CODEC_RT1015: sof_rt1015_dai_link(ctx->amp_link); @@ -683,7 +683,7 @@ static int sof_audio_probe(struct platform_device *pdev) max_98390_set_codec_conf(&pdev->dev, &sof_audio_card_rt5682); break; case CODEC_RT1011: - sof_rt1011_codec_conf(&sof_audio_card_rt5682); + sof_rt1011_codec_conf(&pdev->dev, &sof_audio_card_rt5682); break; case CODEC_RT1015: sof_rt1015_codec_conf(&sof_audio_card_rt5682); -- cgit v1.2.3 From 6136d879f3c2240db636d614a1c39f17c6ceaf36 Mon Sep 17 00:00:00 2001 From: Brent Lu Date: Thu, 11 Apr 2024 17:03:45 -0500 Subject: ASoC: Intel: sof_rt5682: support ALC1011 on cml boards For cml boards, ALC1011 speaker amplifier is supported by machine driver cml_rt1011_rt5682. Use same driver name for backward compatibility with existing devices on market. Reviewed-by: Chao Song Signed-off-by: Brent Lu Signed-off-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20240411220347.131267-11-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/intel/boards/sof_rt5682.c | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/sound/soc/intel/boards/sof_rt5682.c b/sound/soc/intel/boards/sof_rt5682.c index 326d23dd79de..735e07ea62bd 100644 --- a/sound/soc/intel/boards/sof_rt5682.c +++ b/sound/soc/intel/boards/sof_rt5682.c @@ -606,6 +606,7 @@ static int sof_audio_probe(struct platform_device *pdev) { struct snd_soc_acpi_mach *mach = pdev->dev.platform_data; struct sof_card_private *ctx; + char *card_name; bool is_legacy_cpu = false; int ret; @@ -631,14 +632,27 @@ static int sof_audio_probe(struct platform_device *pdev) return -ENOMEM; if (ctx->codec_type == CODEC_RT5650) { - sof_audio_card_rt5682.name = devm_kstrdup(&pdev->dev, "rt5650", - GFP_KERNEL); + card_name = devm_kstrdup(&pdev->dev, "rt5650", GFP_KERNEL); + if (!card_name) + return -ENOMEM; + + sof_audio_card_rt5682.name = card_name; /* create speaker dai link also */ if (ctx->amp_type == CODEC_NONE) ctx->amp_type = CODEC_RT5650; } + if (ctx->amp_type == CODEC_RT1011 && soc_intel_is_cml()) { + /* backward-compatible with existing cml devices */ + card_name = devm_kstrdup(&pdev->dev, "cml_rt1011_rt5682", + GFP_KERNEL); + if (!card_name) + return -ENOMEM; + + sof_audio_card_rt5682.name = card_name; + } + if (is_legacy_cpu) { ctx->rt5682.is_legacy_cpu = true; ctx->dmic_be_num = 0; -- cgit v1.2.3 From ca571e5a2e45b1a4113af2370fd1cf895f0b46d4 Mon Sep 17 00:00:00 2001 From: Brent Lu Date: Thu, 11 Apr 2024 17:03:46 -0500 Subject: ASoC: Intel: cml_rt1011_rt5682: delete driver Delete this driver and use sof_rt5682 machine driver instead. Reviewed-by: Chao Song Signed-off-by: Brent Lu Signed-off-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20240411220347.131267-12-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/intel/boards/Kconfig | 12 +- sound/soc/intel/boards/Makefile | 2 - sound/soc/intel/boards/cml_rt1011_rt5682.c | 609 ---------------------- sound/soc/intel/common/soc-acpi-intel-cml-match.c | 2 +- 4 files changed, 4 insertions(+), 621 deletions(-) delete mode 100644 sound/soc/intel/boards/cml_rt1011_rt5682.c diff --git a/sound/soc/intel/boards/Kconfig b/sound/soc/intel/boards/Kconfig index 9f4a85513702..0ad7b0a1e237 100644 --- a/sound/soc/intel/boards/Kconfig +++ b/sound/soc/intel/boards/Kconfig @@ -595,17 +595,11 @@ config SND_SOC_INTEL_CML_LP_DA7219_MAX98357A_MACH config SND_SOC_INTEL_SOF_CML_RT1011_RT5682_MACH tristate "CML with RT1011 and RT5682 in I2S Mode" - depends on I2C && ACPI - depends on MFD_INTEL_LPSS || COMPILE_TEST - depends on SND_HDA_CODEC_HDMI && SND_SOC_SOF_HDA_AUDIO_CODEC - select SND_SOC_RT1011 - select SND_SOC_RT5682_I2C - select SND_SOC_DMIC - select SND_SOC_HDAC_HDMI - select SND_SOC_INTEL_HDA_DSP_COMMON + imply SND_SOC_INTEL_SOF_RT5682_MACH help This adds support for ASoC machine driver for SOF platform with - RT1011 + RT5682 I2S codec. + RT1011 + RT5682 I2S codec. This option is deprecated and please used + SND_SOC_INTEL_SOF_RT5682_MACH instead. Say Y if you have such a device. If unsure select "N". diff --git a/sound/soc/intel/boards/Makefile b/sound/soc/intel/boards/Makefile index a93b658ed672..119413c262de 100644 --- a/sound/soc/intel/boards/Makefile +++ b/sound/soc/intel/boards/Makefile @@ -24,7 +24,6 @@ snd-soc-sof_cs42l42-objs := sof_cs42l42.o snd-soc-sof_es8336-objs := sof_es8336.o snd-soc-sof_nau8825-objs := sof_nau8825.o snd-soc-sof_da7219-objs := sof_da7219.o -snd-soc-cml_rt1011_rt5682-objs := cml_rt1011_rt5682.o snd-soc-kbl_da7219_max98357a-objs := kbl_da7219_max98357a.o snd-soc-kbl_da7219_max98927-objs := kbl_da7219_max98927.o snd-soc-kbl_rt5663_max98927-objs := kbl_rt5663_max98927.o @@ -71,7 +70,6 @@ obj-$(CONFIG_SND_SOC_INTEL_BYT_CHT_CX2072X_MACH) += snd-soc-sst-byt-cht-cx2072x. obj-$(CONFIG_SND_SOC_INTEL_BYT_CHT_DA7213_MACH) += snd-soc-sst-byt-cht-da7213.o obj-$(CONFIG_SND_SOC_INTEL_BYT_CHT_ES8316_MACH) += snd-soc-sst-byt-cht-es8316.o obj-$(CONFIG_SND_SOC_INTEL_BYT_CHT_NOCODEC_MACH) += snd-soc-sst-byt-cht-nocodec.o -obj-$(CONFIG_SND_SOC_INTEL_SOF_CML_RT1011_RT5682_MACH) += snd-soc-cml_rt1011_rt5682.o obj-$(CONFIG_SND_SOC_INTEL_KBL_DA7219_MAX98357A_MACH) += snd-soc-kbl_da7219_max98357a.o obj-$(CONFIG_SND_SOC_INTEL_KBL_DA7219_MAX98927_MACH) += snd-soc-kbl_da7219_max98927.o obj-$(CONFIG_SND_SOC_INTEL_KBL_RT5663_MAX98927_MACH) += snd-soc-kbl_rt5663_max98927.o diff --git a/sound/soc/intel/boards/cml_rt1011_rt5682.c b/sound/soc/intel/boards/cml_rt1011_rt5682.c deleted file mode 100644 index 679a09b63ea5..000000000000 --- a/sound/soc/intel/boards/cml_rt1011_rt5682.c +++ /dev/null @@ -1,609 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -// Copyright(c) 2019 Intel Corporation. - -/* - * Intel Cometlake I2S Machine driver for RT1011 + RT5682 codec - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "../../codecs/rt1011.h" -#include "../../codecs/rt5682.h" -#include "../../codecs/hdac_hdmi.h" -#include "hda_dsp_common.h" - -/* The platform clock outputs 24Mhz clock to codec as I2S MCLK */ -#define CML_PLAT_CLK 24000000 -#define CML_RT1011_CODEC_DAI "rt1011-aif" -#define CML_RT5682_CODEC_DAI "rt5682-aif1" -#define NAME_SIZE 32 - -#define SOF_RT1011_SPEAKER_WL BIT(0) -#define SOF_RT1011_SPEAKER_WR BIT(1) -#define SOF_RT1011_SPEAKER_TL BIT(2) -#define SOF_RT1011_SPEAKER_TR BIT(3) - -/* Default: Woofer speakers */ -static unsigned long sof_rt1011_quirk = SOF_RT1011_SPEAKER_WL | - SOF_RT1011_SPEAKER_WR; - -static int sof_rt1011_quirk_cb(const struct dmi_system_id *id) -{ - sof_rt1011_quirk = (unsigned long)id->driver_data; - return 1; -} - -static const struct dmi_system_id sof_rt1011_quirk_table[] = { - { - .callback = sof_rt1011_quirk_cb, - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "Google"), - DMI_MATCH(DMI_PRODUCT_NAME, "Helios"), - }, - .driver_data = (void *)(SOF_RT1011_SPEAKER_WL | SOF_RT1011_SPEAKER_WR | - SOF_RT1011_SPEAKER_TL | SOF_RT1011_SPEAKER_TR), - }, - { - } -}; - -static struct snd_soc_jack hdmi_jack[3]; - -struct hdmi_pcm { - struct list_head head; - struct snd_soc_dai *codec_dai; - int device; -}; - -struct card_private { - char codec_name[SND_ACPI_I2C_ID_LEN]; - struct snd_soc_jack headset; - struct list_head hdmi_pcm_list; - bool common_hdmi_codec_drv; -}; - -static const struct snd_kcontrol_new cml_controls[] = { - SOC_DAPM_PIN_SWITCH("Headphone Jack"), - SOC_DAPM_PIN_SWITCH("Headset Mic"), - SOC_DAPM_PIN_SWITCH("WL Ext Spk"), - SOC_DAPM_PIN_SWITCH("WR Ext Spk"), -}; - -static const struct snd_kcontrol_new cml_rt1011_tt_controls[] = { - SOC_DAPM_PIN_SWITCH("TL Ext Spk"), - SOC_DAPM_PIN_SWITCH("TR Ext Spk"), -}; - -static const struct snd_soc_dapm_widget cml_rt1011_rt5682_widgets[] = { - SND_SOC_DAPM_SPK("WL Ext Spk", NULL), - SND_SOC_DAPM_SPK("WR Ext Spk", NULL), - SND_SOC_DAPM_HP("Headphone Jack", NULL), - SND_SOC_DAPM_MIC("Headset Mic", NULL), - SND_SOC_DAPM_MIC("SoC DMIC", NULL), -}; - -static const struct snd_soc_dapm_widget cml_rt1011_tt_widgets[] = { - SND_SOC_DAPM_SPK("TL Ext Spk", NULL), - SND_SOC_DAPM_SPK("TR Ext Spk", NULL), -}; - -static const struct snd_soc_dapm_route cml_rt1011_rt5682_map[] = { - /*WL/WR speaker*/ - {"WL Ext Spk", NULL, "WL SPO"}, - {"WR Ext Spk", NULL, "WR SPO"}, - - /* HP jack connectors - unknown if we have jack detection */ - { "Headphone Jack", NULL, "HPOL" }, - { "Headphone Jack", NULL, "HPOR" }, - - /* other jacks */ - { "IN1P", NULL, "Headset Mic" }, - - /* DMIC */ - {"DMic", NULL, "SoC DMIC"}, -}; - -static const struct snd_soc_dapm_route cml_rt1011_tt_map[] = { - /*TL/TR speaker*/ - {"TL Ext Spk", NULL, "TL SPO" }, - {"TR Ext Spk", NULL, "TR SPO" }, -}; - -static struct snd_soc_jack_pin jack_pins[] = { - { - .pin = "Headphone Jack", - .mask = SND_JACK_HEADPHONE, - }, - { - .pin = "Headset Mic", - .mask = SND_JACK_MICROPHONE, - }, -}; - -static int cml_rt5682_codec_init(struct snd_soc_pcm_runtime *rtd) -{ - struct card_private *ctx = snd_soc_card_get_drvdata(rtd->card); - struct snd_soc_component *component = snd_soc_rtd_to_codec(rtd, 0)->component; - struct snd_soc_jack *jack; - int ret; - - /* need to enable ASRC function for 24MHz mclk rate */ - rt5682_sel_asrc_clk_src(component, RT5682_DA_STEREO1_FILTER | - RT5682_AD_STEREO1_FILTER, - RT5682_CLK_SEL_I2S1_ASRC); - - /* - * Headset buttons map to the google Reference headset. - * These can be configured by userspace. - */ - ret = snd_soc_card_jack_new_pins(rtd->card, "Headset Jack", - SND_JACK_HEADSET | SND_JACK_BTN_0 | - SND_JACK_BTN_1 | SND_JACK_BTN_2 | - SND_JACK_BTN_3, - &ctx->headset, - jack_pins, - ARRAY_SIZE(jack_pins)); - if (ret) { - dev_err(rtd->dev, "Headset Jack creation failed: %d\n", ret); - return ret; - } - - jack = &ctx->headset; - - snd_jack_set_key(jack->jack, SND_JACK_BTN_0, KEY_PLAYPAUSE); - snd_jack_set_key(jack->jack, SND_JACK_BTN_1, KEY_VOICECOMMAND); - snd_jack_set_key(jack->jack, SND_JACK_BTN_2, KEY_VOLUMEUP); - snd_jack_set_key(jack->jack, SND_JACK_BTN_3, KEY_VOLUMEDOWN); - ret = snd_soc_component_set_jack(component, jack, NULL); - if (ret) - dev_err(rtd->dev, "Headset Jack call-back failed: %d\n", ret); - - return ret; -}; - -static void cml_rt5682_codec_exit(struct snd_soc_pcm_runtime *rtd) -{ - struct snd_soc_component *component = snd_soc_rtd_to_codec(rtd, 0)->component; - - snd_soc_component_set_jack(component, NULL, NULL); -} - -static int cml_rt1011_spk_init(struct snd_soc_pcm_runtime *rtd) -{ - int ret = 0; - struct snd_soc_card *card = rtd->card; - - if (sof_rt1011_quirk & (SOF_RT1011_SPEAKER_TL | - SOF_RT1011_SPEAKER_TR)) { - - ret = snd_soc_add_card_controls(card, cml_rt1011_tt_controls, - ARRAY_SIZE(cml_rt1011_tt_controls)); - if (ret) - return ret; - - ret = snd_soc_dapm_new_controls(&card->dapm, - cml_rt1011_tt_widgets, - ARRAY_SIZE(cml_rt1011_tt_widgets)); - if (ret) - return ret; - - ret = snd_soc_dapm_add_routes(&card->dapm, cml_rt1011_tt_map, - ARRAY_SIZE(cml_rt1011_tt_map)); - - if (ret) - return ret; - } - - return ret; -} - -static int cml_rt5682_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *params) -{ - struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream); - struct snd_soc_dai *codec_dai = snd_soc_rtd_to_codec(rtd, 0); - int clk_id, clk_freq, pll_out, ret; - - clk_id = RT5682_PLL1_S_MCLK; - clk_freq = CML_PLAT_CLK; - - pll_out = params_rate(params) * 512; - - ret = snd_soc_dai_set_pll(codec_dai, 0, clk_id, clk_freq, pll_out); - if (ret < 0) - dev_warn(rtd->dev, "snd_soc_dai_set_pll err = %d\n", ret); - - /* Configure sysclk for codec */ - ret = snd_soc_dai_set_sysclk(codec_dai, RT5682_SCLK_S_PLL1, - pll_out, SND_SOC_CLOCK_IN); - if (ret < 0) - dev_warn(rtd->dev, "snd_soc_dai_set_sysclk err = %d\n", ret); - - /* - * slot_width should be equal or large than data length, set them - * be the same - */ - ret = snd_soc_dai_set_tdm_slot(codec_dai, 0x0, 0x0, 2, - params_width(params)); - if (ret < 0) - dev_warn(rtd->dev, "set TDM slot err:%d\n", ret); - return ret; -} - -static int cml_rt1011_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *params) -{ - struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream); - struct snd_soc_dai *codec_dai; - struct snd_soc_card *card = rtd->card; - int srate, i, ret = 0; - - srate = params_rate(params); - - for_each_rtd_codec_dais(rtd, i, codec_dai) { - - /* 100 Fs to drive 24 bit data */ - ret = snd_soc_dai_set_pll(codec_dai, 0, RT1011_PLL1_S_BCLK, - 100 * srate, 256 * srate); - if (ret < 0) { - dev_err(card->dev, "codec_dai clock not set\n"); - return ret; - } - - ret = snd_soc_dai_set_sysclk(codec_dai, - RT1011_FS_SYS_PRE_S_PLL1, - 256 * srate, SND_SOC_CLOCK_IN); - if (ret < 0) { - dev_err(card->dev, "codec_dai clock not set\n"); - return ret; - } - - /* - * Codec TDM is configured as 24 bit capture/ playback. - * 2 CH PB is done over 4 codecs - 2 Woofers and 2 Tweeters. - * The Left woofer and tweeter plays the Left playback data - * and similar by the Right. - * Hence 2 codecs (1 T and 1 W pair) share same Rx slot. - * The feedback is captured for each codec individually. - * Hence all 4 codecs use 1 Tx slot each for feedback. - */ - if (sof_rt1011_quirk & (SOF_RT1011_SPEAKER_WL | - SOF_RT1011_SPEAKER_WR)) { - if (!strcmp(codec_dai->component->name, "i2c-10EC1011:00")) { - ret = snd_soc_dai_set_tdm_slot(codec_dai, - 0x4, 0x1, 4, 24); - if (ret < 0) - break; - } - - if (!strcmp(codec_dai->component->name, "i2c-10EC1011:01")) { - ret = snd_soc_dai_set_tdm_slot(codec_dai, - 0x8, 0x2, 4, 24); - if (ret < 0) - break; - } - } - - if (sof_rt1011_quirk & (SOF_RT1011_SPEAKER_TL | - SOF_RT1011_SPEAKER_TR)) { - if (!strcmp(codec_dai->component->name, "i2c-10EC1011:02")) { - ret = snd_soc_dai_set_tdm_slot(codec_dai, - 0x1, 0x1, 4, 24); - if (ret < 0) - break; - } - - if (!strcmp(codec_dai->component->name, "i2c-10EC1011:03")) { - ret = snd_soc_dai_set_tdm_slot(codec_dai, - 0x2, 0x2, 4, 24); - if (ret < 0) - break; - } - } - } - if (ret < 0) - dev_err(rtd->dev, - "set codec TDM slot for %s failed with error %d\n", - codec_dai->component->name, ret); - return ret; -} - -static struct snd_soc_ops cml_rt5682_ops = { - .hw_params = cml_rt5682_hw_params, -}; - -static const struct snd_soc_ops cml_rt1011_ops = { - .hw_params = cml_rt1011_hw_params, -}; - -static int sof_card_late_probe(struct snd_soc_card *card) -{ - struct card_private *ctx = snd_soc_card_get_drvdata(card); - struct snd_soc_component *component = NULL; - char jack_name[NAME_SIZE]; - struct hdmi_pcm *pcm; - int ret, i = 0; - - if (list_empty(&ctx->hdmi_pcm_list)) - return -EINVAL; - - if (ctx->common_hdmi_codec_drv) { - pcm = list_first_entry(&ctx->hdmi_pcm_list, struct hdmi_pcm, - head); - component = pcm->codec_dai->component; - return hda_dsp_hdmi_build_controls(card, component); - } - - list_for_each_entry(pcm, &ctx->hdmi_pcm_list, head) { - component = pcm->codec_dai->component; - snprintf(jack_name, sizeof(jack_name), - "HDMI/DP, pcm=%d Jack", pcm->device); - ret = snd_soc_card_jack_new(card, jack_name, - SND_JACK_AVOUT, &hdmi_jack[i]); - if (ret) - return ret; - - ret = hdac_hdmi_jack_init(pcm->codec_dai, pcm->device, - &hdmi_jack[i]); - if (ret < 0) - return ret; - - i++; - } - - return hdac_hdmi_jack_port_init(component, &card->dapm); -} - -static int hdmi_init(struct snd_soc_pcm_runtime *rtd) -{ - struct card_private *ctx = snd_soc_card_get_drvdata(rtd->card); - struct snd_soc_dai *dai = snd_soc_rtd_to_codec(rtd, 0); - struct hdmi_pcm *pcm; - - pcm = devm_kzalloc(rtd->card->dev, sizeof(*pcm), GFP_KERNEL); - if (!pcm) - return -ENOMEM; - - pcm->device = dai->id; - pcm->codec_dai = dai; - - list_add_tail(&pcm->head, &ctx->hdmi_pcm_list); - - return 0; -} - -/* Cometlake digital audio interface glue - connects codec <--> CPU */ - -SND_SOC_DAILINK_DEF(ssp0_pin, - DAILINK_COMP_ARRAY(COMP_CPU("SSP0 Pin"))); -SND_SOC_DAILINK_DEF(ssp0_codec, - DAILINK_COMP_ARRAY(COMP_CODEC("i2c-10EC5682:00", - CML_RT5682_CODEC_DAI))); - -SND_SOC_DAILINK_DEF(ssp1_pin, - DAILINK_COMP_ARRAY(COMP_CPU("SSP1 Pin"))); -SND_SOC_DAILINK_DEF(ssp1_codec_2spk, - DAILINK_COMP_ARRAY( - /* WL */ COMP_CODEC("i2c-10EC1011:00", CML_RT1011_CODEC_DAI), - /* WR */ COMP_CODEC("i2c-10EC1011:01", CML_RT1011_CODEC_DAI))); -SND_SOC_DAILINK_DEF(ssp1_codec_4spk, - DAILINK_COMP_ARRAY( - /* WL */ COMP_CODEC("i2c-10EC1011:00", CML_RT1011_CODEC_DAI), - /* WR */ COMP_CODEC("i2c-10EC1011:01", CML_RT1011_CODEC_DAI), - /* TL */ COMP_CODEC("i2c-10EC1011:02", CML_RT1011_CODEC_DAI), - /* TR */ COMP_CODEC("i2c-10EC1011:03", CML_RT1011_CODEC_DAI))); - - -SND_SOC_DAILINK_DEF(dmic_pin, - DAILINK_COMP_ARRAY(COMP_CPU("DMIC01 Pin"))); - -SND_SOC_DAILINK_DEF(dmic16k_pin, - DAILINK_COMP_ARRAY(COMP_CPU("DMIC16k Pin"))); - -SND_SOC_DAILINK_DEF(dmic_codec, - DAILINK_COMP_ARRAY(COMP_CODEC("dmic-codec", "dmic-hifi"))); - -SND_SOC_DAILINK_DEF(idisp1_pin, - DAILINK_COMP_ARRAY(COMP_CPU("iDisp1 Pin"))); -SND_SOC_DAILINK_DEF(idisp1_codec, - DAILINK_COMP_ARRAY(COMP_CODEC("ehdaudio0D2", "intel-hdmi-hifi1"))); - -SND_SOC_DAILINK_DEF(idisp2_pin, - DAILINK_COMP_ARRAY(COMP_CPU("iDisp2 Pin"))); -SND_SOC_DAILINK_DEF(idisp2_codec, - DAILINK_COMP_ARRAY(COMP_CODEC("ehdaudio0D2", "intel-hdmi-hifi2"))); - -SND_SOC_DAILINK_DEF(idisp3_pin, - DAILINK_COMP_ARRAY(COMP_CPU("iDisp3 Pin"))); -SND_SOC_DAILINK_DEF(idisp3_codec, - DAILINK_COMP_ARRAY(COMP_CODEC("ehdaudio0D2", "intel-hdmi-hifi3"))); - -SND_SOC_DAILINK_DEF(platform, - DAILINK_COMP_ARRAY(COMP_PLATFORM("0000:00:1f.3"))); - -static struct snd_soc_dai_link cml_rt1011_rt5682_dailink[] = { - /* Back End DAI links */ - { - /* SSP0 - Codec */ - .name = "SSP0-Codec", - .id = 0, - .init = cml_rt5682_codec_init, - .exit = cml_rt5682_codec_exit, - .ignore_pmdown_time = 1, - .ops = &cml_rt5682_ops, - .dpcm_playback = 1, - .dpcm_capture = 1, - .no_pcm = 1, - SND_SOC_DAILINK_REG(ssp0_pin, ssp0_codec, platform), - }, - { - .name = "dmic01", - .id = 1, - .ignore_suspend = 1, - .dpcm_capture = 1, - .no_pcm = 1, - SND_SOC_DAILINK_REG(dmic_pin, dmic_codec, platform), - }, - { - .name = "dmic16k", - .id = 2, - .ignore_suspend = 1, - .dpcm_capture = 1, - .no_pcm = 1, - SND_SOC_DAILINK_REG(dmic16k_pin, dmic_codec, platform), - }, - { - .name = "iDisp1", - .id = 3, - .init = hdmi_init, - .dpcm_playback = 1, - .no_pcm = 1, - SND_SOC_DAILINK_REG(idisp1_pin, idisp1_codec, platform), - }, - { - .name = "iDisp2", - .id = 4, - .init = hdmi_init, - .dpcm_playback = 1, - .no_pcm = 1, - SND_SOC_DAILINK_REG(idisp2_pin, idisp2_codec, platform), - }, - { - .name = "iDisp3", - .id = 5, - .init = hdmi_init, - .dpcm_playback = 1, - .no_pcm = 1, - SND_SOC_DAILINK_REG(idisp3_pin, idisp3_codec, platform), - }, - { - /* - * SSP1 - Codec : added to end of list ensuring - * reuse of common topologies for other end points - * and changing only SSP1's codec - */ - .name = "SSP1-Codec", - .id = 6, - .dpcm_playback = 1, - .dpcm_capture = 1, /* Capture stream provides Feedback */ - .no_pcm = 1, - .init = cml_rt1011_spk_init, - .ops = &cml_rt1011_ops, - SND_SOC_DAILINK_REG(ssp1_pin, ssp1_codec_2spk, platform), - }, -}; - -static struct snd_soc_codec_conf rt1011_conf[] = { - { - .dlc = COMP_CODEC_CONF("i2c-10EC1011:00"), - .name_prefix = "WL", - }, - { - .dlc = COMP_CODEC_CONF("i2c-10EC1011:01"), - .name_prefix = "WR", - }, - /* single configuration structure for 2 and 4 channels */ - { - .dlc = COMP_CODEC_CONF("i2c-10EC1011:02"), - .name_prefix = "TL", - }, - { - .dlc = COMP_CODEC_CONF("i2c-10EC1011:03"), - .name_prefix = "TR", - }, -}; - -/* Cometlake audio machine driver for RT1011 and RT5682 */ -static struct snd_soc_card snd_soc_card_cml = { - .name = "cml_rt1011_rt5682", - .owner = THIS_MODULE, - .dai_link = cml_rt1011_rt5682_dailink, - .num_links = ARRAY_SIZE(cml_rt1011_rt5682_dailink), - .codec_conf = rt1011_conf, - .num_configs = ARRAY_SIZE(rt1011_conf), - .dapm_widgets = cml_rt1011_rt5682_widgets, - .num_dapm_widgets = ARRAY_SIZE(cml_rt1011_rt5682_widgets), - .dapm_routes = cml_rt1011_rt5682_map, - .num_dapm_routes = ARRAY_SIZE(cml_rt1011_rt5682_map), - .controls = cml_controls, - .num_controls = ARRAY_SIZE(cml_controls), - .fully_routed = true, - .late_probe = sof_card_late_probe, -}; - -static int snd_cml_rt1011_probe(struct platform_device *pdev) -{ - struct snd_soc_dai_link *dai_link; - struct card_private *ctx; - struct snd_soc_acpi_mach *mach; - const char *platform_name; - int ret, i; - - ctx = devm_kzalloc(&pdev->dev, sizeof(*ctx), GFP_KERNEL); - if (!ctx) - return -ENOMEM; - - INIT_LIST_HEAD(&ctx->hdmi_pcm_list); - mach = pdev->dev.platform_data; - snd_soc_card_cml.dev = &pdev->dev; - platform_name = mach->mach_params.platform; - - dmi_check_system(sof_rt1011_quirk_table); - - dev_dbg(&pdev->dev, "sof_rt1011_quirk = %lx\n", sof_rt1011_quirk); - - /* when 4 speaker is available, update codec config */ - if (sof_rt1011_quirk & (SOF_RT1011_SPEAKER_TL | - SOF_RT1011_SPEAKER_TR)) { - for_each_card_prelinks(&snd_soc_card_cml, i, dai_link) { - if (!strcmp(dai_link->codecs[0].dai_name, - CML_RT1011_CODEC_DAI)) { - dai_link->codecs = ssp1_codec_4spk; - dai_link->num_codecs = ARRAY_SIZE(ssp1_codec_4spk); - } - } - } - - /* set platform name for each dailink */ - ret = snd_soc_fixup_dai_links_platform_name(&snd_soc_card_cml, - platform_name); - if (ret) - return ret; - - ctx->common_hdmi_codec_drv = mach->mach_params.common_hdmi_codec_drv; - - snd_soc_card_set_drvdata(&snd_soc_card_cml, ctx); - - return devm_snd_soc_register_card(&pdev->dev, &snd_soc_card_cml); -} - -static struct platform_driver snd_cml_rt1011_rt5682_driver = { - .probe = snd_cml_rt1011_probe, - .driver = { - .name = "cml_rt1011_rt5682", - .pm = &snd_soc_pm_ops, - }, -}; -module_platform_driver(snd_cml_rt1011_rt5682_driver); - -/* Module information */ -MODULE_DESCRIPTION("Cometlake Audio Machine driver - RT1011 and RT5682 in I2S mode"); -MODULE_AUTHOR("Naveen Manohar "); -MODULE_AUTHOR("Sathya Prakash M R "); -MODULE_AUTHOR("Shuming Fan "); -MODULE_AUTHOR("Mac Chiang "); -MODULE_LICENSE("GPL v2"); -MODULE_ALIAS("platform:cml_rt1011_rt5682"); -MODULE_IMPORT_NS(SND_SOC_INTEL_HDA_DSP_COMMON); diff --git a/sound/soc/intel/common/soc-acpi-intel-cml-match.c b/sound/soc/intel/common/soc-acpi-intel-cml-match.c index d47a548959ea..160bfa0e5ef5 100644 --- a/sound/soc/intel/common/soc-acpi-intel-cml-match.c +++ b/sound/soc/intel/common/soc-acpi-intel-cml-match.c @@ -42,7 +42,7 @@ static const struct snd_soc_acpi_codecs max98390_spk_codecs = { struct snd_soc_acpi_mach snd_soc_acpi_intel_cml_machines[] = { { .id = "10EC5682", - .drv_name = "cml_rt1011_rt5682", + .drv_name = "cml_rt5682_def", .machine_quirk = snd_soc_acpi_codec_list, .quirk_data = &rt1011_spk_codecs, .sof_tplg_filename = "sof-cml-rt1011-rt5682.tplg", -- cgit v1.2.3 From dcc2cd8000d11a046680a7476b0d96b0b956454a Mon Sep 17 00:00:00 2001 From: Bard Liao Date: Thu, 11 Apr 2024 17:03:47 -0500 Subject: ASoC: Intel: sof_rt5682: use RT5682S_PLL1 if needed When 96KHz sample rate is used, and MCLK is 24.576MHz, we will need pll_in = 24576000 and pll_out = 49152000 which is not supported by RT5682S_PLL2. Use RT5682S_PLL1 in this case. We don't test sample rate because RT5682S_PLL2 doesn't support 24.576MHz input and in the MCLK = 24.576MHz, sample rate = 48KHz case, i.e. pll_in == pll_out, PLL will not be used at all. Reviewed-by: Ranjani Sridharan Signed-off-by: Bard Liao Signed-off-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20240411220347.131267-13-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/intel/boards/sof_rt5682.c | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/sound/soc/intel/boards/sof_rt5682.c b/sound/soc/intel/boards/sof_rt5682.c index 735e07ea62bd..062012de3de2 100644 --- a/sound/soc/intel/boards/sof_rt5682.c +++ b/sound/soc/intel/boards/sof_rt5682.c @@ -340,8 +340,19 @@ static int sof_rt5682_hw_params(struct snd_pcm_substream *substream, clk_id = RT5682_SCLK_S_PLL1; break; case CODEC_RT5682S: - pll_id = RT5682S_PLL2; - clk_id = RT5682S_SCLK_S_PLL2; + /* + * For MCLK = 24.576MHz and sample rate = 96KHz case, use PLL1 We don't test + * pll_out or params_rate() here since rt5682s PLL2 doesn't support 24.576MHz + * input, so we have no choice but to use PLL1. Besides, we will not use PLL at + * all if pll_in == pll_out. ex, MCLK = 24.576Mhz and sample rate = 48KHz + */ + if (pll_in == 24576000) { + pll_id = RT5682S_PLL1; + clk_id = RT5682S_SCLK_S_PLL1; + } else { + pll_id = RT5682S_PLL2; + clk_id = RT5682S_SCLK_S_PLL2; + } break; default: dev_err(rtd->dev, "invalid codec type %d\n", ctx->codec_type); -- cgit v1.2.3 From 4be7bc275253c0f35c8f6362af1ee5d91d5d83e9 Mon Sep 17 00:00:00 2001 From: Fabio Estevam Date: Fri, 12 Apr 2024 09:14:10 -0300 Subject: ASoC: dt-bindings: fsl-asoc-card: Document fsl,imx25-pdk-sgtl5000 Document fsl,imx25-pdk-sgtl5000 to fix the following dt-schema warning: imx25-pdk.dtb: sound: compatible: 'oneOf' conditional failed, one must be fixed: ['fsl,imx25-pdk-sgtl5000', 'fsl,imx-audio-sgtl5000'] is too long Fixes: 4189b54220e5 ("ASoC: dt-bindings: fsl-asoc-card: convert to YAML") Signed-off-by: Fabio Estevam Acked-by: Krzysztof Kozlowski Link: https://lore.kernel.org/r/20240412121410.2948048-1-festevam@gmail.com Signed-off-by: Mark Brown --- Documentation/devicetree/bindings/sound/fsl-asoc-card.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/Documentation/devicetree/bindings/sound/fsl-asoc-card.yaml b/Documentation/devicetree/bindings/sound/fsl-asoc-card.yaml index 42ca39eebd49..bbf6fa1a2012 100644 --- a/Documentation/devicetree/bindings/sound/fsl-asoc-card.yaml +++ b/Documentation/devicetree/bindings/sound/fsl-asoc-card.yaml @@ -33,6 +33,7 @@ properties: - items: - enum: - fsl,imx-sgtl5000 + - fsl,imx25-pdk-sgtl5000 - fsl,imx53-cpuvo-sgtl5000 - fsl,imx51-babbage-sgtl5000 - fsl,imx53-m53evk-sgtl5000 -- cgit v1.2.3 From a8cad4a4e431e250edc05242a8ca1be6e4b33749 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Fri, 12 Apr 2024 15:07:01 +0300 Subject: ASoC: soc-card: soc-card-test: Fix some error handling in init() There are two issues here: 1) The get_device() needs a matching put_device() on error paths. 2) The "if (!ret)" was supposed to be "if (ret)". I re-arranged the code a bit to do the allocation before the get_device(). Fixes: ef7784e41db7 ("ASoC: soc-card: Add KUnit test case for snd_soc_card_get_kcontrol") Signed-off-by: Dan Carpenter Reviewed-by: Richard Fitzgerald Link: https://lore.kernel.org/r/450dd21a-b24b-48ba-9aa4-c02e4617852f@moroto.mountain Signed-off-by: Mark Brown --- sound/soc/soc-card-test.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/sound/soc/soc-card-test.c b/sound/soc/soc-card-test.c index 075c52fe82e5..e4a4b101d743 100644 --- a/sound/soc/soc-card-test.c +++ b/sound/soc/soc-card-test.c @@ -134,22 +134,24 @@ static int soc_card_test_case_init(struct kunit *test) test->priv = priv; + priv->card = kunit_kzalloc(test, sizeof(*priv->card), GFP_KERNEL); + if (!priv->card) + return -ENOMEM; + priv->card_dev = kunit_device_register(test, "sound-soc-card-test"); priv->card_dev = get_device(priv->card_dev); if (!priv->card_dev) return -ENODEV; - priv->card = kunit_kzalloc(test, sizeof(*priv->card), GFP_KERNEL); - if (!priv->card) - return -ENOMEM; - priv->card->name = "soc-card-test"; priv->card->dev = priv->card_dev; priv->card->owner = THIS_MODULE; ret = snd_soc_register_card(priv->card); - if (!ret) + if (ret) { + put_device(priv->card_dev); return ret; + } return 0; } -- cgit v1.2.3 From d6e792ed7dd022a16a637ade224da070b60f4f3b Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Fri, 12 Apr 2024 05:46:03 +0000 Subject: ASoC: dt-bindings: renesas: add R8A779H0 V4M Add document for R-Car V4M (R8A779H0). Signed-off-by: Kuninori Morimoto Link: https://lore.kernel.org/r/871q7bcew5.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- Documentation/devicetree/bindings/sound/renesas,rsnd.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/Documentation/devicetree/bindings/sound/renesas,rsnd.yaml b/Documentation/devicetree/bindings/sound/renesas,rsnd.yaml index 0d7a6b576d88..8ce78ca838ba 100644 --- a/Documentation/devicetree/bindings/sound/renesas,rsnd.yaml +++ b/Documentation/devicetree/bindings/sound/renesas,rsnd.yaml @@ -49,6 +49,7 @@ properties: # for Gen4 SoC - items: - const: renesas,rcar_sound-r8a779g0 # R-Car V4H + - const: renesas,rcar_sound-r8a779h0 # R-Car V4M - const: renesas,rcar_sound-gen4 # for Generic - enum: -- cgit v1.2.3 From f284b23809bf54f8189f82f822f099e43d6a0a35 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Fri, 12 Apr 2024 05:45:43 +0000 Subject: ASoC: dt-bindings: renesas,rsnd: add missing renesas,rcar_sound-gen4 It is missing generic compatible for R-Car Gen4 Signed-off-by: Kuninori Morimoto Link: https://lore.kernel.org/r/8734rrcewo.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- Documentation/devicetree/bindings/sound/renesas,rsnd.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/Documentation/devicetree/bindings/sound/renesas,rsnd.yaml b/Documentation/devicetree/bindings/sound/renesas,rsnd.yaml index 8ce78ca838ba..b3da278cf141 100644 --- a/Documentation/devicetree/bindings/sound/renesas,rsnd.yaml +++ b/Documentation/devicetree/bindings/sound/renesas,rsnd.yaml @@ -56,6 +56,7 @@ properties: - renesas,rcar_sound-gen1 - renesas,rcar_sound-gen2 - renesas,rcar_sound-gen3 + - renesas,rcar_sound-gen4 reg: minItems: 1 -- cgit v1.2.3 From 69129794d94c544810e68b2b4eaa7e44063f9bf2 Mon Sep 17 00:00:00 2001 From: Josh Poimboeuf Date: Fri, 12 Apr 2024 11:10:33 -0700 Subject: x86/bugs: Fix BHI retpoline check Confusingly, X86_FEATURE_RETPOLINE doesn't mean retpolines are enabled, as it also includes the original "AMD retpoline" which isn't a retpoline at all. Also replace cpu_feature_enabled() with boot_cpu_has() because this is before alternatives are patched and cpu_feature_enabled()'s fallback path is slower than plain old boot_cpu_has(). Fixes: ec9404e40e8f ("x86/bhi: Add BHI mitigation knob") Signed-off-by: Josh Poimboeuf Signed-off-by: Ingo Molnar Reviewed-by: Pawan Gupta Cc: Borislav Petkov Cc: Linus Torvalds Link: https://lore.kernel.org/r/ad3807424a3953f0323c011a643405619f2a4927.1712944776.git.jpoimboe@kernel.org --- arch/x86/kernel/cpu/bugs.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/arch/x86/kernel/cpu/bugs.c b/arch/x86/kernel/cpu/bugs.c index ca295b0c1eee..ab18185894df 100644 --- a/arch/x86/kernel/cpu/bugs.c +++ b/arch/x86/kernel/cpu/bugs.c @@ -1652,7 +1652,8 @@ static void __init bhi_select_mitigation(void) return; /* Retpoline mitigates against BHI unless the CPU has RRSBA behavior */ - if (cpu_feature_enabled(X86_FEATURE_RETPOLINE)) { + if (boot_cpu_has(X86_FEATURE_RETPOLINE) && + !boot_cpu_has(X86_FEATURE_RETPOLINE_LFENCE)) { spec_ctrl_disable_kernel_rrsba(); if (rrsba_disabled) return; @@ -2804,11 +2805,13 @@ static const char *spectre_bhi_state(void) { if (!boot_cpu_has_bug(X86_BUG_BHI)) return "; BHI: Not affected"; - else if (boot_cpu_has(X86_FEATURE_CLEAR_BHB_HW)) + else if (boot_cpu_has(X86_FEATURE_CLEAR_BHB_HW)) return "; BHI: BHI_DIS_S"; - else if (boot_cpu_has(X86_FEATURE_CLEAR_BHB_LOOP)) + else if (boot_cpu_has(X86_FEATURE_CLEAR_BHB_LOOP)) return "; BHI: SW loop, KVM: SW loop"; - else if (boot_cpu_has(X86_FEATURE_RETPOLINE) && rrsba_disabled) + else if (boot_cpu_has(X86_FEATURE_RETPOLINE) && + !boot_cpu_has(X86_FEATURE_RETPOLINE_LFENCE) && + rrsba_disabled) return "; BHI: Retpoline"; else if (boot_cpu_has(X86_FEATURE_CLEAR_BHB_LOOP_ON_VMEXIT)) return "; BHI: Vulnerable, KVM: SW loop"; -- cgit v1.2.3 From 16b52bbee4823b01ab7fe3919373c981a38f3797 Mon Sep 17 00:00:00 2001 From: Amir Goldstein Date: Fri, 5 Apr 2024 17:56:35 +0300 Subject: kernfs: annotate different lockdep class for of->mutex of writable files The writable file /sys/power/resume may call vfs lookup helpers for arbitrary paths and readonly files can be read by overlayfs from vfs helpers when sysfs is a lower layer of overalyfs. To avoid a lockdep warning of circular dependency between overlayfs inode lock and kernfs of->mutex, use a different lockdep class for writable and readonly kernfs files. Reported-by: syzbot+9a5b0ced8b1bfb238b56@syzkaller.appspotmail.com Fixes: 0fedefd4c4e3 ("kernfs: sysfs: support custom llseek method for sysfs entries") Suggested-by: Al Viro Signed-off-by: Amir Goldstein Signed-off-by: Al Viro --- fs/kernfs/file.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/fs/kernfs/file.c b/fs/kernfs/file.c index e9df2f87072c..8502ef68459b 100644 --- a/fs/kernfs/file.c +++ b/fs/kernfs/file.c @@ -636,11 +636,18 @@ static int kernfs_fop_open(struct inode *inode, struct file *file) * each file a separate locking class. Let's differentiate on * whether the file has mmap or not for now. * - * Both paths of the branch look the same. They're supposed to + * For similar reasons, writable and readonly files are given different + * lockdep key, because the writable file /sys/power/resume may call vfs + * lookup helpers for arbitrary paths and readonly files can be read by + * overlayfs from vfs helpers when sysfs is a lower layer of overalyfs. + * + * All three cases look the same. They're supposed to * look that way and give @of->mutex different static lockdep keys. */ if (has_mmap) mutex_init(&of->mutex); + else if (file->f_mode & FMODE_WRITE) + mutex_init(&of->mutex); else mutex_init(&of->mutex); -- cgit v1.2.3 From 89f9a1e876b5a7ad884918c03a46831af202c8a0 Mon Sep 17 00:00:00 2001 From: Qiang Zhang Date: Sun, 14 Apr 2024 19:49:45 +0800 Subject: bootconfig: use memblock_free_late to free xbc memory to buddy On the time to free xbc memory in xbc_exit(), memblock may has handed over memory to buddy allocator. So it doesn't make sense to free memory back to memblock. memblock_free() called by xbc_exit() even causes UAF bugs on architectures with CONFIG_ARCH_KEEP_MEMBLOCK disabled like x86. Following KASAN logs shows this case. This patch fixes the xbc memory free problem by calling memblock_free() in early xbc init error rewind path and calling memblock_free_late() in xbc exit path to free memory to buddy allocator. [ 9.410890] ================================================================== [ 9.418962] BUG: KASAN: use-after-free in memblock_isolate_range+0x12d/0x260 [ 9.426850] Read of size 8 at addr ffff88845dd30000 by task swapper/0/1 [ 9.435901] CPU: 9 PID: 1 Comm: swapper/0 Tainted: G U 6.9.0-rc3-00208-g586b5dfb51b9 #5 [ 9.446403] Hardware name: Intel Corporation RPLP LP5 (CPU:RaptorLake)/RPLP LP5 (ID:13), BIOS IRPPN02.01.01.00.00.19.015.D-00000000 Dec 28 2023 [ 9.460789] Call Trace: [ 9.463518] [ 9.465859] dump_stack_lvl+0x53/0x70 [ 9.469949] print_report+0xce/0x610 [ 9.473944] ? __virt_addr_valid+0xf5/0x1b0 [ 9.478619] ? memblock_isolate_range+0x12d/0x260 [ 9.483877] kasan_report+0xc6/0x100 [ 9.487870] ? memblock_isolate_range+0x12d/0x260 [ 9.493125] memblock_isolate_range+0x12d/0x260 [ 9.498187] memblock_phys_free+0xb4/0x160 [ 9.502762] ? __pfx_memblock_phys_free+0x10/0x10 [ 9.508021] ? mutex_unlock+0x7e/0xd0 [ 9.512111] ? __pfx_mutex_unlock+0x10/0x10 [ 9.516786] ? kernel_init_freeable+0x2d4/0x430 [ 9.521850] ? __pfx_kernel_init+0x10/0x10 [ 9.526426] xbc_exit+0x17/0x70 [ 9.529935] kernel_init+0x38/0x1e0 [ 9.533829] ? _raw_spin_unlock_irq+0xd/0x30 [ 9.538601] ret_from_fork+0x2c/0x50 [ 9.542596] ? __pfx_kernel_init+0x10/0x10 [ 9.547170] ret_from_fork_asm+0x1a/0x30 [ 9.551552] [ 9.555649] The buggy address belongs to the physical page: [ 9.561875] page: refcount:0 mapcount:0 mapping:0000000000000000 index:0x1 pfn:0x45dd30 [ 9.570821] flags: 0x200000000000000(node=0|zone=2) [ 9.576271] page_type: 0xffffffff() [ 9.580167] raw: 0200000000000000 ffffea0011774c48 ffffea0012ba1848 0000000000000000 [ 9.588823] raw: 0000000000000001 0000000000000000 00000000ffffffff 0000000000000000 [ 9.597476] page dumped because: kasan: bad access detected [ 9.605362] Memory state around the buggy address: [ 9.610714] ffff88845dd2ff00: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 [ 9.618786] ffff88845dd2ff80: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 [ 9.626857] >ffff88845dd30000: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff [ 9.634930] ^ [ 9.638534] ffff88845dd30080: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff [ 9.646605] ffff88845dd30100: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff [ 9.654675] ================================================================== Link: https://lore.kernel.org/all/20240414114944.1012359-1-qiang4.zhang@linux.intel.com/ Fixes: 40caa127f3c7 ("init: bootconfig: Remove all bootconfig data when the init memory is removed") Cc: Stable@vger.kernel.org Signed-off-by: Qiang Zhang Acked-by: Masami Hiramatsu (Google) Signed-off-by: Masami Hiramatsu (Google) --- include/linux/bootconfig.h | 7 ++++++- lib/bootconfig.c | 19 +++++++++++-------- 2 files changed, 17 insertions(+), 9 deletions(-) diff --git a/include/linux/bootconfig.h b/include/linux/bootconfig.h index e5ee2c694401..3f4b4ac527ca 100644 --- a/include/linux/bootconfig.h +++ b/include/linux/bootconfig.h @@ -288,7 +288,12 @@ int __init xbc_init(const char *buf, size_t size, const char **emsg, int *epos); int __init xbc_get_info(int *node_size, size_t *data_size); /* XBC cleanup data structures */ -void __init xbc_exit(void); +void __init _xbc_exit(bool early); + +static inline void xbc_exit(void) +{ + _xbc_exit(false); +} /* XBC embedded bootconfig data in kernel */ #ifdef CONFIG_BOOT_CONFIG_EMBED diff --git a/lib/bootconfig.c b/lib/bootconfig.c index c59d26068a64..8841554432d5 100644 --- a/lib/bootconfig.c +++ b/lib/bootconfig.c @@ -61,9 +61,12 @@ static inline void * __init xbc_alloc_mem(size_t size) return memblock_alloc(size, SMP_CACHE_BYTES); } -static inline void __init xbc_free_mem(void *addr, size_t size) +static inline void __init xbc_free_mem(void *addr, size_t size, bool early) { - memblock_free(addr, size); + if (early) + memblock_free(addr, size); + else if (addr) + memblock_free_late(__pa(addr), size); } #else /* !__KERNEL__ */ @@ -73,7 +76,7 @@ static inline void *xbc_alloc_mem(size_t size) return malloc(size); } -static inline void xbc_free_mem(void *addr, size_t size) +static inline void xbc_free_mem(void *addr, size_t size, bool early) { free(addr); } @@ -904,13 +907,13 @@ static int __init xbc_parse_tree(void) * If you need to reuse xbc_init() with new boot config, you can * use this. */ -void __init xbc_exit(void) +void __init _xbc_exit(bool early) { - xbc_free_mem(xbc_data, xbc_data_size); + xbc_free_mem(xbc_data, xbc_data_size, early); xbc_data = NULL; xbc_data_size = 0; xbc_node_num = 0; - xbc_free_mem(xbc_nodes, sizeof(struct xbc_node) * XBC_NODE_MAX); + xbc_free_mem(xbc_nodes, sizeof(struct xbc_node) * XBC_NODE_MAX, early); xbc_nodes = NULL; brace_index = 0; } @@ -963,7 +966,7 @@ int __init xbc_init(const char *data, size_t size, const char **emsg, int *epos) if (!xbc_nodes) { if (emsg) *emsg = "Failed to allocate bootconfig nodes"; - xbc_exit(); + _xbc_exit(true); return -ENOMEM; } memset(xbc_nodes, 0, sizeof(struct xbc_node) * XBC_NODE_MAX); @@ -977,7 +980,7 @@ int __init xbc_init(const char *data, size_t size, const char **emsg, int *epos) *epos = xbc_err_pos; if (emsg) *emsg = xbc_err_msg; - xbc_exit(); + _xbc_exit(true); } else ret = xbc_node_num; -- cgit v1.2.3 From 1382e3b6a3500c245e5278c66d210c02926f804f Mon Sep 17 00:00:00 2001 From: Yuri Benditovich Date: Thu, 11 Apr 2024 08:11:24 +0300 Subject: net: change maximum number of UDP segments to 128 The commit fc8b2a619469 ("net: more strict VIRTIO_NET_HDR_GSO_UDP_L4 validation") adds check of potential number of UDP segments vs UDP_MAX_SEGMENTS in linux/virtio_net.h. After this change certification test of USO guest-to-guest transmit on Windows driver for virtio-net device fails, for example with packet size of ~64K and mss of 536 bytes. In general the USO should not be more restrictive than TSO. Indeed, in case of unreasonably small mss a lot of segments can cause queue overflow and packet loss on the destination. Limit of 128 segments is good for any practical purpose, with minimal meaningful mss of 536 the maximal UDP packet will be divided to ~120 segments. The number of segments for UDP packets is validated vs UDP_MAX_SEGMENTS also in udp.c (v4,v6), this does not affect quest-to-guest path but does affect packets sent to host, for example. It is important to mention that UDP_MAX_SEGMENTS is kernel-only define and not available to user mode socket applications. In order to request MSS smaller than MTU the applications just uses setsockopt with SOL_UDP and UDP_SEGMENT and there is no limitations on socket API level. Fixes: fc8b2a619469 ("net: more strict VIRTIO_NET_HDR_GSO_UDP_L4 validation") Signed-off-by: Yuri Benditovich Reviewed-by: Willem de Bruijn Signed-off-by: David S. Miller --- include/linux/udp.h | 2 +- tools/testing/selftests/net/udpgso.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/include/linux/udp.h b/include/linux/udp.h index 17539d089666..e398e1dbd2d3 100644 --- a/include/linux/udp.h +++ b/include/linux/udp.h @@ -108,7 +108,7 @@ struct udp_sock { #define udp_assign_bit(nr, sk, val) \ assign_bit(UDP_FLAGS_##nr, &udp_sk(sk)->udp_flags, val) -#define UDP_MAX_SEGMENTS (1 << 6UL) +#define UDP_MAX_SEGMENTS (1 << 7UL) #define udp_sk(ptr) container_of_const(ptr, struct udp_sock, inet.sk) diff --git a/tools/testing/selftests/net/udpgso.c b/tools/testing/selftests/net/udpgso.c index 1d975bf52af3..85b3baa3f7f3 100644 --- a/tools/testing/selftests/net/udpgso.c +++ b/tools/testing/selftests/net/udpgso.c @@ -34,7 +34,7 @@ #endif #ifndef UDP_MAX_SEGMENTS -#define UDP_MAX_SEGMENTS (1 << 6UL) +#define UDP_MAX_SEGMENTS (1 << 7UL) #endif #define CONST_MTU_TEST 1500 -- cgit v1.2.3 From 8541323285994528ad5be2c1bdc759e6c83b936e Mon Sep 17 00:00:00 2001 From: Jason Gunthorpe Date: Thu, 4 Apr 2024 21:05:14 -0300 Subject: iommufd: Add missing IOMMUFD_DRIVER kconfig for the selftest Some kconfigs don't automatically include this symbol which results in sub functions for some of the dirty tracking related things that are non-functional. Thus the test suite will fail. select IOMMUFD_DRIVER in the IOMMUFD_TEST kconfig to fix it. Fixes: a9af47e382a4 ("iommufd/selftest: Test IOMMU_HWPT_GET_DIRTY_BITMAP") Link: https://lore.kernel.org/r/20240327182050.GA1363414@ziepe.ca Tested-by: Muhammad Usama Anjum Signed-off-by: Jason Gunthorpe --- drivers/iommu/iommufd/Kconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/iommu/iommufd/Kconfig b/drivers/iommu/iommufd/Kconfig index 99d4b075df49..76656fe0470d 100644 --- a/drivers/iommu/iommufd/Kconfig +++ b/drivers/iommu/iommufd/Kconfig @@ -37,6 +37,7 @@ config IOMMUFD_TEST depends on DEBUG_KERNEL depends on FAULT_INJECTION depends on RUNTIME_TESTING_MENU + select IOMMUFD_DRIVER default n help This is dangerous, do not enable unless running -- cgit v1.2.3 From 2760c51b8040d7cffedc337939e7475a17cc4b19 Mon Sep 17 00:00:00 2001 From: Muhammad Usama Anjum Date: Mon, 25 Mar 2024 14:00:48 +0500 Subject: iommufd: Add config needed for iommufd_fail_nth Add FAULT_INJECTION_DEBUG_FS and FAILSLAB configurations to the kconfig fragment for the iommfd selftests. These kconfigs are needed by the iommufd_fail_nth test. Fixes: a9af47e382a4 ("iommufd/selftest: Test IOMMU_HWPT_GET_DIRTY_BITMAP") Link: https://lore.kernel.org/r/20240325090048.1423908-1-usama.anjum@collabora.com Signed-off-by: Muhammad Usama Anjum Signed-off-by: Jason Gunthorpe --- tools/testing/selftests/iommu/config | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tools/testing/selftests/iommu/config b/tools/testing/selftests/iommu/config index 110d73917615..02a2a1b267c1 100644 --- a/tools/testing/selftests/iommu/config +++ b/tools/testing/selftests/iommu/config @@ -1,3 +1,5 @@ CONFIG_IOMMUFD=y +CONFIG_FAULT_INJECTION_DEBUG_FS=y CONFIG_FAULT_INJECTION=y CONFIG_IOMMUFD_TEST=y +CONFIG_FAILSLAB=y -- cgit v1.2.3 From 0bbac3facb5d6cc0171c45c9873a2dc96bea9680 Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Sun, 14 Apr 2024 13:38:39 -0700 Subject: Linux 6.9-rc4 --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index e1bf12891cb0..59d8a7f95d0a 100644 --- a/Makefile +++ b/Makefile @@ -2,7 +2,7 @@ VERSION = 6 PATCHLEVEL = 9 SUBLEVEL = 0 -EXTRAVERSION = -rc3 +EXTRAVERSION = -rc4 NAME = Hurr durr I'ma ninja sloth # *DOCUMENTATION* -- cgit v1.2.3 From bceb86be9e970bc6d77bfd1f8e5272d9a2007c16 Mon Sep 17 00:00:00 2001 From: Kent Overstreet Date: Sat, 13 Apr 2024 23:59:06 -0400 Subject: bcachefs: add missing bounds check in __bch2_bkey_val_invalid() Signed-off-by: Kent Overstreet --- fs/bcachefs/bkey_methods.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/fs/bcachefs/bkey_methods.c b/fs/bcachefs/bkey_methods.c index 5e52684764eb..e4481e4d5f38 100644 --- a/fs/bcachefs/bkey_methods.c +++ b/fs/bcachefs/bkey_methods.c @@ -175,7 +175,10 @@ int __bch2_bkey_invalid(struct bch_fs *c, struct bkey_s_c k, !(bch2_key_types_allowed[type] & BIT_ULL(k.k->type)), c, err, bkey_invalid_type_for_btree, "invalid key type for btree %s (%s)", - bch2_btree_node_type_str(type), bch2_bkey_types[k.k->type]); + bch2_btree_node_type_str(type), + k.k->type < KEY_TYPE_MAX + ? bch2_bkey_types[k.k->type] + : "(unknown)"); if (btree_node_type_is_extents(type) && !bkey_whiteout(k.k)) { bkey_fsck_err_on(k.k->size == 0, c, err, -- cgit v1.2.3 From d789e9a7d5e2799f4d5425b0b620210d2fcad529 Mon Sep 17 00:00:00 2001 From: Kent Overstreet Date: Sat, 13 Apr 2024 23:59:28 -0400 Subject: bcachefs: Interior known are required to have known key types For forwards compatibilyt, we allow bkeys of unknown type in leaf nodes; we can simply ignore metadata we don't understand. Pointers to btree nodes must always be of known types, howwever. Signed-off-by: Kent Overstreet --- fs/bcachefs/bkey_methods.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/fs/bcachefs/bkey_methods.c b/fs/bcachefs/bkey_methods.c index e4481e4d5f38..db336a43fc08 100644 --- a/fs/bcachefs/bkey_methods.c +++ b/fs/bcachefs/bkey_methods.c @@ -171,7 +171,8 @@ int __bch2_bkey_invalid(struct bch_fs *c, struct bkey_s_c k, if (type >= BKEY_TYPE_NR) return 0; - bkey_fsck_err_on((flags & BKEY_INVALID_COMMIT) && + bkey_fsck_err_on((type == BKEY_TYPE_btree || + (flags & BKEY_INVALID_COMMIT)) && !(bch2_key_types_allowed[type] & BIT_ULL(k.k->type)), c, err, bkey_invalid_type_for_btree, "invalid key type for btree %s (%s)", -- cgit v1.2.3 From 8cf2036e7b557282667a437d409e6307d55366ab Mon Sep 17 00:00:00 2001 From: Kent Overstreet Date: Fri, 12 Apr 2024 15:34:14 -0400 Subject: bcachefs: add safety checks in bch2_btree_node_fill() Signed-off-by: Kent Overstreet --- fs/bcachefs/btree_cache.c | 25 ++++++++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) diff --git a/fs/bcachefs/btree_cache.c b/fs/bcachefs/btree_cache.c index c7f156320a35..c347d08d80bc 100644 --- a/fs/bcachefs/btree_cache.c +++ b/fs/bcachefs/btree_cache.c @@ -711,7 +711,30 @@ static noinline struct btree *bch2_btree_node_fill(struct btree_trans *trans, struct btree *b; u32 seq; - BUG_ON(level + 1 >= BTREE_MAX_DEPTH); + if (unlikely(level >= BTREE_MAX_DEPTH)) { + int ret = bch2_fs_topology_error(c, "attempting to get btree node at level %u, >= max depth %u", + level, BTREE_MAX_DEPTH); + return ERR_PTR(ret); + } + + if (unlikely(!bkey_is_btree_ptr(&k->k))) { + struct printbuf buf = PRINTBUF; + bch2_bkey_val_to_text(&buf, c, bkey_i_to_s_c(k)); + + int ret = bch2_fs_topology_error(c, "attempting to get btree node with non-btree key %s", buf.buf); + printbuf_exit(&buf); + return ERR_PTR(ret); + } + + if (unlikely(k->k.u64s > BKEY_BTREE_PTR_U64s_MAX)) { + struct printbuf buf = PRINTBUF; + bch2_bkey_val_to_text(&buf, c, bkey_i_to_s_c(k)); + + int ret = bch2_fs_topology_error(c, "attempting to get btree node with too big key %s", buf.buf); + printbuf_exit(&buf); + return ERR_PTR(ret); + } + /* * Parent node must be locked, else we could read in a btree node that's * been freed: -- cgit v1.2.3 From e879389f5777de5d94f27f8d88d7e92341afa3ef Mon Sep 17 00:00:00 2001 From: Kent Overstreet Date: Fri, 12 Apr 2024 15:54:33 -0400 Subject: bcachefs: Fix bch2_btree_node_fill() for !path We shouldn't be doing the unlock/relock dance when we're not using a path - this fixes an assertion pop when called from btree node scan. Signed-off-by: Kent Overstreet --- fs/bcachefs/btree_cache.c | 44 ++++++++++++++++++-------------------------- 1 file changed, 18 insertions(+), 26 deletions(-) diff --git a/fs/bcachefs/btree_cache.c b/fs/bcachefs/btree_cache.c index c347d08d80bc..02c70e813fac 100644 --- a/fs/bcachefs/btree_cache.c +++ b/fs/bcachefs/btree_cache.c @@ -709,7 +709,6 @@ static noinline struct btree *bch2_btree_node_fill(struct btree_trans *trans, struct bch_fs *c = trans->c; struct btree_cache *bc = &c->btree_cache; struct btree *b; - u32 seq; if (unlikely(level >= BTREE_MAX_DEPTH)) { int ret = bch2_fs_topology_error(c, "attempting to get btree node at level %u, >= max depth %u", @@ -775,34 +774,26 @@ static noinline struct btree *bch2_btree_node_fill(struct btree_trans *trans, } set_btree_node_read_in_flight(b); - six_unlock_write(&b->c.lock); - seq = six_lock_seq(&b->c.lock); - six_unlock_intent(&b->c.lock); - /* Unlock before doing IO: */ - if (path && sync) - bch2_trans_unlock_noassert(trans); - - bch2_btree_node_read(trans, b, sync); + if (path) { + u32 seq = six_lock_seq(&b->c.lock); - if (!sync) - return NULL; + /* Unlock before doing IO: */ + six_unlock_intent(&b->c.lock); + bch2_trans_unlock_noassert(trans); - if (path) { - int ret = bch2_trans_relock(trans) ?: - bch2_btree_path_relock_intent(trans, path); - if (ret) { - BUG_ON(!trans->restarted); - return ERR_PTR(ret); - } - } + bch2_btree_node_read(trans, b, sync); - if (!six_relock_type(&b->c.lock, lock_type, seq)) { - BUG_ON(!path); + if (!sync) + return NULL; - trace_and_count(c, trans_restart_relock_after_fill, trans, _THIS_IP_, path); - return ERR_PTR(btree_trans_restart(trans, BCH_ERR_transaction_restart_relock_after_fill)); + if (!six_relock_type(&b->c.lock, lock_type, seq)) + b = NULL; + } else { + bch2_btree_node_read(trans, b, sync); + if (lock_type == SIX_LOCK_read) + six_lock_downgrade(&b->c.lock); } return b; @@ -1135,18 +1126,19 @@ int bch2_btree_node_prefetch(struct btree_trans *trans, { struct bch_fs *c = trans->c; struct btree_cache *bc = &c->btree_cache; - struct btree *b; BUG_ON(path && !btree_node_locked(path, level + 1)); BUG_ON(level >= BTREE_MAX_DEPTH); - b = btree_cache_find(bc, k); + struct btree *b = btree_cache_find(bc, k); if (b) return 0; b = bch2_btree_node_fill(trans, path, k, btree_id, level, SIX_LOCK_read, false); - return PTR_ERR_OR_ZERO(b); + if (!IS_ERR_OR_NULL(b)) + six_unlock_read(&b->c.lock); + return bch2_trans_relock(trans) ?: PTR_ERR_OR_ZERO(b); } void bch2_btree_node_evict(struct btree_trans *trans, const struct bkey_i *k) -- cgit v1.2.3 From bdae2a7e6020e1cf864a30dab2af323575569dc7 Mon Sep 17 00:00:00 2001 From: Kent Overstreet Date: Sat, 13 Apr 2024 22:43:11 -0400 Subject: bcachefs: sysfs internal/trigger_journal_flush Add a sysfs knob for immediately flushing the entire journal. Signed-off-by: Kent Overstreet --- fs/bcachefs/sysfs.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/fs/bcachefs/sysfs.c b/fs/bcachefs/sysfs.c index b18b0cc81b59..5be92fe3f4ea 100644 --- a/fs/bcachefs/sysfs.c +++ b/fs/bcachefs/sysfs.c @@ -25,6 +25,7 @@ #include "ec.h" #include "inode.h" #include "journal.h" +#include "journal_reclaim.h" #include "keylist.h" #include "move.h" #include "movinggc.h" @@ -138,6 +139,7 @@ do { \ write_attribute(trigger_gc); write_attribute(trigger_discards); write_attribute(trigger_invalidates); +write_attribute(trigger_journal_flush); write_attribute(prune_cache); write_attribute(btree_wakeup); rw_attribute(btree_gc_periodic); @@ -500,7 +502,7 @@ STORE(bch2_fs) /* Debugging: */ - if (!test_bit(BCH_FS_rw, &c->flags)) + if (!bch2_write_ref_tryget(c, BCH_WRITE_REF_sysfs)) return -EROFS; if (attr == &sysfs_prune_cache) { @@ -533,6 +535,11 @@ STORE(bch2_fs) if (attr == &sysfs_trigger_invalidates) bch2_do_invalidates(c); + if (attr == &sysfs_trigger_journal_flush) { + bch2_journal_flush_all_pins(&c->journal); + bch2_journal_meta(&c->journal); + } + #ifdef CONFIG_BCACHEFS_TESTS if (attr == &sysfs_perf_test) { char *tmp = kstrdup(buf, GFP_KERNEL), *p = tmp; @@ -553,6 +560,7 @@ STORE(bch2_fs) size = ret; } #endif + bch2_write_ref_put(c, BCH_WRITE_REF_sysfs); return size; } SYSFS_OPS(bch2_fs); @@ -651,6 +659,7 @@ struct attribute *bch2_fs_internal_files[] = { &sysfs_trigger_gc, &sysfs_trigger_discards, &sysfs_trigger_invalidates, + &sysfs_trigger_journal_flush, &sysfs_prune_cache, &sysfs_btree_wakeup, -- cgit v1.2.3 From 27c15ed297cb71c2e7a839439b5a097081a32605 Mon Sep 17 00:00:00 2001 From: Kent Overstreet Date: Fri, 12 Apr 2024 18:45:47 -0400 Subject: bcachefs: bch_member.btree_allocated_bitmap This adds a small (64 bit) per-device bitmap that tracks ranges that have btree nodes, for accelerating btree node scan if it is ever needed. - New helpers, bch2_dev_btree_bitmap_marked() and bch2_dev_bitmap_mark(), for checking and updating the bitmap - Interior btree update path updates the bitmaps when required - The check_allocations pass has a new fsck_err check, btree_bitmap_not_marked - New on disk format version, mi_btree_mitmap, which indicates the new bitmap is present - Upgrade table lists the required recovery pass and expected fsck error - Btree node scan uses the bitmap to skip ranges if we're on the new version Signed-off-by: Kent Overstreet --- fs/bcachefs/bcachefs_format.h | 7 +++-- fs/bcachefs/btree_gc.c | 13 +++++++++ fs/bcachefs/btree_node_scan.c | 9 +++++-- fs/bcachefs/btree_update_interior.c | 24 +++++++++++++++++ fs/bcachefs/sb-downgrade.c | 5 +++- fs/bcachefs/sb-errors_types.h | 3 ++- fs/bcachefs/sb-members.c | 53 +++++++++++++++++++++++++++++++++++++ fs/bcachefs/sb-members.h | 21 +++++++++++++++ fs/bcachefs/super_types.h | 2 ++ 9 files changed, 131 insertions(+), 6 deletions(-) diff --git a/fs/bcachefs/bcachefs_format.h b/fs/bcachefs/bcachefs_format.h index 9480f1b44f07..085987435a5e 100644 --- a/fs/bcachefs/bcachefs_format.h +++ b/fs/bcachefs/bcachefs_format.h @@ -578,7 +578,8 @@ struct bch_member { __le64 nbuckets; /* device size */ __le16 first_bucket; /* index of first bucket used */ __le16 bucket_size; /* sectors */ - __le32 pad; + __u8 btree_bitmap_shift; + __u8 pad[3]; __le64 last_mount; /* time_t */ __le64 flags; @@ -587,6 +588,7 @@ struct bch_member { __le64 errors_at_reset[BCH_MEMBER_ERROR_NR]; __le64 errors_reset_time; __le64 seq; + __le64 btree_allocated_bitmap; }; #define BCH_MEMBER_V1_BYTES 56 @@ -876,7 +878,8 @@ struct bch_sb_field_downgrade { x(rebalance_work, BCH_VERSION(1, 3)) \ x(member_seq, BCH_VERSION(1, 4)) \ x(subvolume_fs_parent, BCH_VERSION(1, 5)) \ - x(btree_subvolume_children, BCH_VERSION(1, 6)) + x(btree_subvolume_children, BCH_VERSION(1, 6)) \ + x(mi_btree_bitmap, BCH_VERSION(1, 7)) enum bcachefs_metadata_version { bcachefs_metadata_version_min = 9, diff --git a/fs/bcachefs/btree_gc.c b/fs/bcachefs/btree_gc.c index d2555da55c6d..ecbd9598f69f 100644 --- a/fs/bcachefs/btree_gc.c +++ b/fs/bcachefs/btree_gc.c @@ -828,6 +828,7 @@ static int bch2_gc_mark_key(struct btree_trans *trans, enum btree_id btree_id, struct bch_fs *c = trans->c; struct bkey deleted = KEY(0, 0, 0); struct bkey_s_c old = (struct bkey_s_c) { &deleted, NULL }; + struct printbuf buf = PRINTBUF; int ret = 0; deleted.p = k->k->p; @@ -848,11 +849,23 @@ static int bch2_gc_mark_key(struct btree_trans *trans, enum btree_id btree_id, if (ret) goto err; + if (mustfix_fsck_err_on(level && !bch2_dev_btree_bitmap_marked(c, *k), + c, btree_bitmap_not_marked, + "btree ptr not marked in member info btree allocated bitmap\n %s", + (bch2_bkey_val_to_text(&buf, c, *k), + buf.buf))) { + mutex_lock(&c->sb_lock); + bch2_dev_btree_bitmap_mark(c, *k); + bch2_write_super(c); + mutex_unlock(&c->sb_lock); + } + ret = commit_do(trans, NULL, NULL, 0, bch2_key_trigger(trans, btree_id, level, old, unsafe_bkey_s_c_to_s(*k), BTREE_TRIGGER_GC)); fsck_err: err: + printbuf_exit(&buf); bch_err_fn(c, ret); return ret; } diff --git a/fs/bcachefs/btree_node_scan.c b/fs/bcachefs/btree_node_scan.c index 20f2b37c4474..866bd278439f 100644 --- a/fs/bcachefs/btree_node_scan.c +++ b/fs/bcachefs/btree_node_scan.c @@ -205,8 +205,13 @@ static int read_btree_nodes_worker(void *p) last_print = jiffies; } - try_read_btree_node(w->f, ca, bio, buf, - bucket * ca->mi.bucket_size + bucket_offset); + u64 sector = bucket * ca->mi.bucket_size + bucket_offset; + + if (c->sb.version_upgrade_complete >= bcachefs_metadata_version_mi_btree_bitmap && + !bch2_dev_btree_bitmap_marked_sectors(ca, sector, btree_sectors(c))) + continue; + + try_read_btree_node(w->f, ca, bio, buf, sector); } err: bio_put(bio); diff --git a/fs/bcachefs/btree_update_interior.c b/fs/bcachefs/btree_update_interior.c index 82ac00aa0f7b..6030c396754f 100644 --- a/fs/bcachefs/btree_update_interior.c +++ b/fs/bcachefs/btree_update_interior.c @@ -21,6 +21,7 @@ #include "keylist.h" #include "recovery_passes.h" #include "replicas.h" +#include "sb-members.h" #include "super-io.h" #include "trace.h" @@ -605,6 +606,26 @@ static void btree_update_add_key(struct btree_update *as, bch2_keylist_push(keys); } +static bool btree_update_new_nodes_marked_sb(struct btree_update *as) +{ + for_each_keylist_key(&as->new_keys, k) + if (!bch2_dev_btree_bitmap_marked(as->c, bkey_i_to_s_c(k))) + return false; + return true; +} + +static void btree_update_new_nodes_mark_sb(struct btree_update *as) +{ + struct bch_fs *c = as->c; + + mutex_lock(&c->sb_lock); + for_each_keylist_key(&as->new_keys, k) + bch2_dev_btree_bitmap_mark(c, bkey_i_to_s_c(k)); + + bch2_write_super(c); + mutex_unlock(&c->sb_lock); +} + /* * The transactional part of an interior btree node update, where we journal the * update we did to the interior node and update alloc info: @@ -662,6 +683,9 @@ static void btree_update_nodes_written(struct btree_update *as) if (ret) goto err; + if (!btree_update_new_nodes_marked_sb(as)) + btree_update_new_nodes_mark_sb(as); + /* * Wait for any in flight writes to finish before we free the old nodes * on disk: diff --git a/fs/bcachefs/sb-downgrade.c b/fs/bcachefs/sb-downgrade.c index d6f81179c3a2..a98ef940b7a3 100644 --- a/fs/bcachefs/sb-downgrade.c +++ b/fs/bcachefs/sb-downgrade.c @@ -51,7 +51,10 @@ BCH_FSCK_ERR_subvol_fs_path_parent_wrong) \ x(btree_subvolume_children, \ BIT_ULL(BCH_RECOVERY_PASS_check_subvols), \ - BCH_FSCK_ERR_subvol_children_not_set) + BCH_FSCK_ERR_subvol_children_not_set) \ + x(mi_btree_bitmap, \ + BIT_ULL(BCH_RECOVERY_PASS_check_allocations), \ + BCH_FSCK_ERR_btree_bitmap_not_marked) #define DOWNGRADE_TABLE() diff --git a/fs/bcachefs/sb-errors_types.h b/fs/bcachefs/sb-errors_types.h index d7d609131030..5b600c6d7aca 100644 --- a/fs/bcachefs/sb-errors_types.h +++ b/fs/bcachefs/sb-errors_types.h @@ -270,7 +270,8 @@ x(btree_ptr_v2_min_key_bad, 262) \ x(btree_root_unreadable_and_scan_found_nothing, 263) \ x(snapshot_node_missing, 264) \ - x(dup_backpointer_to_bad_csum_extent, 265) + x(dup_backpointer_to_bad_csum_extent, 265) \ + x(btree_bitmap_not_marked, 266) enum bch_sb_error_id { #define x(t, n) BCH_FSCK_ERR_##t = n, diff --git a/fs/bcachefs/sb-members.c b/fs/bcachefs/sb-members.c index eff5ce18c69c..522a969345e5 100644 --- a/fs/bcachefs/sb-members.c +++ b/fs/bcachefs/sb-members.c @@ -1,6 +1,7 @@ // SPDX-License-Identifier: GPL-2.0 #include "bcachefs.h" +#include "btree_cache.h" #include "disk_groups.h" #include "opts.h" #include "replicas.h" @@ -426,3 +427,55 @@ void bch2_dev_errors_reset(struct bch_dev *ca) bch2_write_super(c); mutex_unlock(&c->sb_lock); } + +/* + * Per member "range has btree nodes" bitmap: + * + * This is so that if we ever have to run the btree node scan to repair we don't + * have to scan full devices: + */ + +bool bch2_dev_btree_bitmap_marked(struct bch_fs *c, struct bkey_s_c k) +{ + bkey_for_each_ptr(bch2_bkey_ptrs_c(k), ptr) + if (!bch2_dev_btree_bitmap_marked_sectors(bch_dev_bkey_exists(c, ptr->dev), + ptr->offset, btree_sectors(c))) + return false; + return true; +} + +static void __bch2_dev_btree_bitmap_mark(struct bch_sb_field_members_v2 *mi, unsigned dev, + u64 start, unsigned sectors) +{ + struct bch_member *m = __bch2_members_v2_get_mut(mi, dev); + u64 bitmap = le64_to_cpu(m->btree_allocated_bitmap); + + u64 end = start + sectors; + + int resize = ilog2(roundup_pow_of_two(end)) - (m->btree_bitmap_shift + 6); + if (resize > 0) { + u64 new_bitmap = 0; + + for (unsigned i = 0; i < 64; i++) + if (bitmap & BIT_ULL(i)) + new_bitmap |= BIT_ULL(i >> resize); + bitmap = new_bitmap; + m->btree_bitmap_shift += resize; + } + + for (unsigned bit = sectors >> m->btree_bitmap_shift; + bit << m->btree_bitmap_shift < end; + bit++) + bitmap |= BIT_ULL(bit); + + m->btree_allocated_bitmap = cpu_to_le64(bitmap); +} + +void bch2_dev_btree_bitmap_mark(struct bch_fs *c, struct bkey_s_c k) +{ + lockdep_assert_held(&c->sb_lock); + + struct bch_sb_field_members_v2 *mi = bch2_sb_field_get(c->disk_sb.sb, members_v2); + bkey_for_each_ptr(bch2_bkey_ptrs_c(k), ptr) + __bch2_dev_btree_bitmap_mark(mi, ptr->dev, ptr->offset, btree_sectors(c)); +} diff --git a/fs/bcachefs/sb-members.h b/fs/bcachefs/sb-members.h index be0a94183271..b27c3e4467cf 100644 --- a/fs/bcachefs/sb-members.h +++ b/fs/bcachefs/sb-members.h @@ -3,6 +3,7 @@ #define _BCACHEFS_SB_MEMBERS_H #include "darray.h" +#include "bkey_types.h" extern char * const bch2_member_error_strs[]; @@ -220,6 +221,8 @@ static inline struct bch_member_cpu bch2_mi_to_cpu(struct bch_member *mi) : 1, .freespace_initialized = BCH_MEMBER_FREESPACE_INITIALIZED(mi), .valid = bch2_member_exists(mi), + .btree_bitmap_shift = mi->btree_bitmap_shift, + .btree_allocated_bitmap = le64_to_cpu(mi->btree_allocated_bitmap), }; } @@ -228,4 +231,22 @@ void bch2_sb_members_from_cpu(struct bch_fs *); void bch2_dev_io_errors_to_text(struct printbuf *, struct bch_dev *); void bch2_dev_errors_reset(struct bch_dev *); +static inline bool bch2_dev_btree_bitmap_marked_sectors(struct bch_dev *ca, u64 start, unsigned sectors) +{ + u64 end = start + sectors; + + if (end > 64 << ca->mi.btree_bitmap_shift) + return false; + + for (unsigned bit = sectors >> ca->mi.btree_bitmap_shift; + bit << ca->mi.btree_bitmap_shift < end; + bit++) + if (!(ca->mi.btree_allocated_bitmap & BIT_ULL(bit))) + return false; + return true; +} + +bool bch2_dev_btree_bitmap_marked(struct bch_fs *, struct bkey_s_c); +void bch2_dev_btree_bitmap_mark(struct bch_fs *, struct bkey_s_c); + #endif /* _BCACHEFS_SB_MEMBERS_H */ diff --git a/fs/bcachefs/super_types.h b/fs/bcachefs/super_types.h index ec784d975f66..11bcef170c2c 100644 --- a/fs/bcachefs/super_types.h +++ b/fs/bcachefs/super_types.h @@ -37,6 +37,8 @@ struct bch_member_cpu { u8 durability; u8 freespace_initialized; u8 valid; + u8 btree_bitmap_shift; + u64 btree_allocated_bitmap; }; #endif /* _BCACHEFS_SUPER_TYPES_H */ -- cgit v1.2.3 From f0a73d4fde5b285d94a702026216d9fd1fd2733d Mon Sep 17 00:00:00 2001 From: Kent Overstreet Date: Sun, 14 Apr 2024 00:51:48 -0400 Subject: bcachefs: Check for backpointer bucket_offset >= bucket size Signed-off-by: Kent Overstreet --- fs/bcachefs/backpointers.c | 8 +++++--- fs/bcachefs/backpointers.h | 9 +++------ fs/bcachefs/sb-errors_types.h | 2 +- 3 files changed, 9 insertions(+), 10 deletions(-) diff --git a/fs/bcachefs/backpointers.c b/fs/bcachefs/backpointers.c index 114328acde72..fadb1078903d 100644 --- a/fs/bcachefs/backpointers.c +++ b/fs/bcachefs/backpointers.c @@ -49,13 +49,15 @@ int bch2_backpointer_invalid(struct bch_fs *c, struct bkey_s_c k, if (!bch2_dev_exists2(c, bp.k->p.inode)) return 0; + struct bch_dev *ca = bch_dev_bkey_exists(c, bp.k->p.inode); struct bpos bucket = bp_pos_to_bucket(c, bp.k->p); int ret = 0; - bkey_fsck_err_on(!bpos_eq(bp.k->p, bucket_pos_to_bp(c, bucket, bp.v->bucket_offset)), + bkey_fsck_err_on((bp.v->bucket_offset >> MAX_EXTENT_COMPRESS_RATIO_SHIFT) >= ca->mi.bucket_size || + !bpos_eq(bp.k->p, bucket_pos_to_bp(c, bucket, bp.v->bucket_offset)), c, err, - backpointer_pos_wrong, - "backpointer at wrong pos"); + backpointer_bucket_offset_wrong, + "backpointer bucket_offset wrong"); fsck_err: return ret; } diff --git a/fs/bcachefs/backpointers.h b/fs/bcachefs/backpointers.h index da012ca7daee..85949b9fd880 100644 --- a/fs/bcachefs/backpointers.h +++ b/fs/bcachefs/backpointers.h @@ -53,14 +53,11 @@ static inline struct bpos bucket_pos_to_bp(const struct bch_fs *c, u64 bucket_offset) { struct bch_dev *ca = bch_dev_bkey_exists(c, bucket.inode); - struct bpos ret; - - ret = POS(bucket.inode, - (bucket_to_sector(ca, bucket.offset) << - MAX_EXTENT_COMPRESS_RATIO_SHIFT) + bucket_offset); + struct bpos ret = POS(bucket.inode, + (bucket_to_sector(ca, bucket.offset) << + MAX_EXTENT_COMPRESS_RATIO_SHIFT) + bucket_offset); EBUG_ON(!bkey_eq(bucket, bp_pos_to_bucket(c, ret))); - return ret; } diff --git a/fs/bcachefs/sb-errors_types.h b/fs/bcachefs/sb-errors_types.h index 5b600c6d7aca..4ca6e7b0d8aa 100644 --- a/fs/bcachefs/sb-errors_types.h +++ b/fs/bcachefs/sb-errors_types.h @@ -130,7 +130,7 @@ x(bucket_gens_nonzero_for_invalid_buckets, 122) \ x(need_discard_freespace_key_to_invalid_dev_bucket, 123) \ x(need_discard_freespace_key_bad, 124) \ - x(backpointer_pos_wrong, 125) \ + x(backpointer_bucket_offset_wrong, 125) \ x(backpointer_to_missing_device, 126) \ x(backpointer_to_missing_alloc, 127) \ x(backpointer_to_missing_ptr, 128) \ -- cgit v1.2.3 From c21614d5c0e76cf1d7a864f15d495fd3e5876acc Mon Sep 17 00:00:00 2001 From: "end.to.start" Date: Fri, 12 Apr 2024 10:55:33 +0300 Subject: ASoC: amd: Support microphone from Acer Aspire A315-24P Add support microphone from Acer Aspire A315-24P and for some other similar devices with such vendor Signed-off-by: "end.to.start" Link: https://lore.kernel.org/r/20240412075533.10214-1-end.to.start@mail.ru Signed-off-by: Mark Brown --- 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 69c68d8e7a6b..1760b5d42460 100644 --- a/sound/soc/amd/yc/acp6x-mach.c +++ b/sound/soc/amd/yc/acp6x-mach.c @@ -430,6 +430,13 @@ static const struct dmi_system_id yc_acp_quirk_table[] = { DMI_MATCH(DMI_BOARD_NAME, "MRID6"), } }, + { + .driver_data = &acp6x_card, + .matches = { + DMI_MATCH(DMI_BOARD_VENDOR, "MDC"), + DMI_MATCH(DMI_BOARD_NAME, "Herbag_MDU"), + } + }, { .driver_data = &acp6x_card, .matches = { -- cgit v1.2.3 From 615169c727b13ff4ec6c43b62501f73f9f88a11a Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Sun, 14 Apr 2024 17:48:38 +0200 Subject: ASoC: wcd934x: Drop unneeded MODULE_ALIAS The ID table already has respective entry and MODULE_DEVICE_TABLE and creates proper alias for platform driver. Having another MODULE_ALIAS causes the alias to be duplicated. Signed-off-by: Krzysztof Kozlowski Link: https://lore.kernel.org/r/20240414154839.126852-1-krzk@kernel.org Signed-off-by: Mark Brown --- sound/soc/codecs/wcd934x.c | 1 - 1 file changed, 1 deletion(-) diff --git a/sound/soc/codecs/wcd934x.c b/sound/soc/codecs/wcd934x.c index 6813268e6a19..de870c7819ca 100644 --- a/sound/soc/codecs/wcd934x.c +++ b/sound/soc/codecs/wcd934x.c @@ -5967,7 +5967,6 @@ static struct platform_driver wcd934x_codec_driver = { } }; -MODULE_ALIAS("platform:wcd934x-codec"); module_platform_driver(wcd934x_codec_driver); MODULE_DESCRIPTION("WCD934x codec driver"); MODULE_LICENSE("GPL v2"); -- cgit v1.2.3 From 9d85ec4e91e354ed2d8291e1ea3ba76e660205a0 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Sun, 14 Apr 2024 17:48:39 +0200 Subject: ASoC: samsung: i2s: Drop unneeded MODULE_ALIAS The ID table already has respective entry and MODULE_DEVICE_TABLE and creates proper alias for platform driver. Having another MODULE_ALIAS causes the alias to be duplicated. Signed-off-by: Krzysztof Kozlowski Link: https://lore.kernel.org/r/20240414154839.126852-2-krzk@kernel.org Signed-off-by: Mark Brown --- sound/soc/samsung/i2s.c | 1 - 1 file changed, 1 deletion(-) diff --git a/sound/soc/samsung/i2s.c b/sound/soc/samsung/i2s.c index 9552748aea2e..1bcabb114e29 100644 --- a/sound/soc/samsung/i2s.c +++ b/sound/soc/samsung/i2s.c @@ -1755,5 +1755,4 @@ module_platform_driver(samsung_i2s_driver); /* Module information */ MODULE_AUTHOR("Jaswinder Singh, "); MODULE_DESCRIPTION("Samsung I2S Interface"); -MODULE_ALIAS("platform:samsung-i2s"); MODULE_LICENSE("GPL"); -- cgit v1.2.3 From dd8c3473bbb8b4fdc44ed3a5a864cfefab9038dd Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Sun, 14 Apr 2024 18:47:03 +0200 Subject: ASoC: amd: acp-da7219-max98357a: Constify regulator_ops Neither core nor the driver modifes 'struct regulator_ops', so it can be const for code safety. Signed-off-by: Krzysztof Kozlowski Link: https://lore.kernel.org/r/20240414164703.239851-1-krzk@kernel.org Signed-off-by: Mark Brown --- sound/soc/amd/acp-da7219-max98357a.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/amd/acp-da7219-max98357a.c b/sound/soc/amd/acp-da7219-max98357a.c index 84f3d65ba52e..77cf72082e73 100644 --- a/sound/soc/amd/acp-da7219-max98357a.c +++ b/sound/soc/amd/acp-da7219-max98357a.c @@ -733,7 +733,7 @@ static struct regulator_config acp_da7219_cfg = { .init_data = &acp_da7219_data, }; -static struct regulator_ops acp_da7219_ops = { +static const struct regulator_ops acp_da7219_ops = { }; static const struct regulator_desc acp_da7219_desc = { -- cgit v1.2.3 From 356952b13af5b2c338df1e06889fd1b5e12cbbf4 Mon Sep 17 00:00:00 2001 From: bolan wang Date: Wed, 6 Mar 2024 19:03:39 +0800 Subject: USB: serial: option: add Fibocom FM135-GL variants Update the USB serial option driver support for the Fibocom FM135-GL LTE modules. - VID:PID 2cb7:0115, FM135-GL for laptop debug M.2 cards(with MBIM interface for /Linux/Chrome OS) 0x0115: mbim, diag, at, pipe Here are the outputs of usb-devices: T: Bus=01 Lev=01 Prnt=01 Port=02 Cnt=01 Dev#= 16 Spd=480 MxCh= 0 D: Ver= 2.01 Cls=00(>ifc ) Sub=00 Prot=00 MxPS=64 #Cfgs= 1 P: Vendor=2cb7 ProdID=0115 Rev=05.15 S: Manufacturer=Fibocom Wireless Inc. S: Product=Fibocom Module S: SerialNumber=12345678 C: #Ifs= 6 Cfg#= 1 Atr=a0 MxPwr=500mA I: If#= 0 Alt= 0 #EPs= 1 Cls=02(commc) Sub=0e Prot=00 Driver=cdc_mbim E: Ad=82(I) Atr=03(Int.) MxPS= 64 Ivl=32ms I: If#= 1 Alt= 1 #EPs= 2 Cls=0a(data ) Sub=00 Prot=02 Driver=cdc_mbim E: Ad=01(O) Atr=02(Bulk) MxPS= 512 Ivl=0ms E: Ad=81(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms I: If#= 2 Alt= 0 #EPs= 2 Cls=ff(vend.) Sub=ff Prot=30 Driver=option E: Ad=02(O) Atr=02(Bulk) MxPS= 512 Ivl=0ms E: Ad=83(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms I: If#= 3 Alt= 0 #EPs= 3 Cls=ff(vend.) Sub=ff Prot=40 Driver=option E: Ad=03(O) Atr=02(Bulk) MxPS= 512 Ivl=0ms E: Ad=84(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms E: Ad=85(I) Atr=03(Int.) MxPS= 10 Ivl=32ms I: If#= 4 Alt= 0 #EPs= 2 Cls=ff(vend.) Sub=00 Prot=00 Driver=option E: Ad=04(O) Atr=02(Bulk) MxPS= 512 Ivl=0ms E: Ad=86(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms I: If#= 5 Alt= 0 #EPs= 2 Cls=ff(vend.) Sub=42 Prot=01 Driver=usbfs E: Ad=05(O) Atr=02(Bulk) MxPS= 512 Ivl=0ms E: Ad=87(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms Signed-off-by: bolan wang Cc: stable@vger.kernel.org Signed-off-by: Johan Hovold --- drivers/usb/serial/option.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c index 55a65d941ccb..cedf93a3eaea 100644 --- a/drivers/usb/serial/option.c +++ b/drivers/usb/serial/option.c @@ -2272,6 +2272,8 @@ static const struct usb_device_id option_ids[] = { { USB_DEVICE_AND_INTERFACE_INFO(0x2cb7, 0x010b, 0xff, 0xff, 0x30) }, /* Fibocom FG150 Diag */ { USB_DEVICE_AND_INTERFACE_INFO(0x2cb7, 0x010b, 0xff, 0, 0) }, /* Fibocom FG150 AT */ { USB_DEVICE_INTERFACE_CLASS(0x2cb7, 0x0111, 0xff) }, /* Fibocom FM160 (MBIM mode) */ + { USB_DEVICE_INTERFACE_CLASS(0x2cb7, 0x0115, 0xff), /* Fibocom FM135 (laptop MBIM) */ + .driver_info = RSVD(5) }, { USB_DEVICE_INTERFACE_CLASS(0x2cb7, 0x01a0, 0xff) }, /* Fibocom NL668-AM/NL652-EU (laptop MBIM) */ { USB_DEVICE_INTERFACE_CLASS(0x2cb7, 0x01a2, 0xff) }, /* Fibocom FM101-GL (laptop MBIM) */ { USB_DEVICE_INTERFACE_CLASS(0x2cb7, 0x01a3, 0xff) }, /* Fibocom FM101-GL (laptop MBIM) */ -- cgit v1.2.3 From c840244aba7ad2b83ed904378b36bd6aef25511c Mon Sep 17 00:00:00 2001 From: Jerry Meng Date: Mon, 15 Apr 2024 15:04:29 +0800 Subject: USB: serial: option: support Quectel EM060K sub-models EM060K_129, EM060K_12a, EM060K_12b and EM0060K_12c are EM060K's sub-models, having the same name "Quectel EM060K-GL" and the same interface layout. MBIM + GNSS + DIAG + NMEA + AT + QDSS + DPL T: Bus=03 Lev=01 Prnt=01 Port=01 Cnt=02 Dev#= 8 Spd=480 MxCh= 0 D: Ver= 2.00 Cls=00(>ifc ) Sub=00 Prot=00 MxPS=64 #Cfgs= 1 P: Vendor=2c7c ProdID=0129 Rev= 5.04 S: Manufacturer=Quectel S: Product=Quectel EM060K-GL S: SerialNumber=f6fa08b6 C:* #Ifs= 8 Cfg#= 1 Atr=a0 MxPwr=500mA A: FirstIf#= 0 IfCount= 2 Cls=02(comm.) Sub=0e Prot=00 I:* If#= 0 Alt= 0 #EPs= 1 Cls=02(comm.) Sub=0e Prot=00 Driver=cdc_mbim E: Ad=81(I) Atr=03(Int.) MxPS= 64 Ivl=32ms I: If#= 1 Alt= 0 #EPs= 0 Cls=0a(data ) Sub=00 Prot=02 Driver=cdc_mbim I:* If#= 1 Alt= 1 #EPs= 2 Cls=0a(data ) Sub=00 Prot=02 Driver=cdc_mbim E: Ad=8e(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms E: Ad=0f(O) Atr=02(Bulk) MxPS= 512 Ivl=0ms I:* If#= 2 Alt= 0 #EPs= 1 Cls=ff(vend.) Sub=ff Prot=ff Driver=(none) E: Ad=82(I) Atr=03(Int.) MxPS= 64 Ivl=32ms I:* If#= 3 Alt= 0 #EPs= 2 Cls=ff(vend.) Sub=ff Prot=30 Driver=option E: Ad=01(O) Atr=02(Bulk) MxPS= 512 Ivl=0ms E: Ad=83(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms I:* If#= 4 Alt= 0 #EPs= 3 Cls=ff(vend.) Sub=00 Prot=40 Driver=option E: Ad=85(I) Atr=03(Int.) MxPS= 10 Ivl=32ms E: Ad=84(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms E: Ad=02(O) Atr=02(Bulk) MxPS= 512 Ivl=0ms I:* If#= 5 Alt= 0 #EPs= 3 Cls=ff(vend.) Sub=ff Prot=40 Driver=option E: Ad=87(I) Atr=03(Int.) MxPS= 10 Ivl=32ms E: Ad=86(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms E: Ad=03(O) Atr=02(Bulk) MxPS= 512 Ivl=0ms I:* If#= 6 Alt= 0 #EPs= 1 Cls=ff(vend.) Sub=ff Prot=70 Driver=(none) E: Ad=88(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms I:* If#= 7 Alt= 0 #EPs= 1 Cls=ff(vend.) Sub=ff Prot=80 Driver=(none) E: Ad=8f(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms Signed-off-by: Jerry Meng Cc: stable@vger.kernel.org Signed-off-by: Johan Hovold --- drivers/usb/serial/option.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c index cedf93a3eaea..16cf0ddaae9b 100644 --- a/drivers/usb/serial/option.c +++ b/drivers/usb/serial/option.c @@ -255,6 +255,10 @@ static void option_instat_callback(struct urb *urb); #define QUECTEL_PRODUCT_EM061K_LMS 0x0124 #define QUECTEL_PRODUCT_EC25 0x0125 #define QUECTEL_PRODUCT_EM060K_128 0x0128 +#define QUECTEL_PRODUCT_EM060K_129 0x0129 +#define QUECTEL_PRODUCT_EM060K_12a 0x012a +#define QUECTEL_PRODUCT_EM060K_12b 0x012b +#define QUECTEL_PRODUCT_EM060K_12c 0x012c #define QUECTEL_PRODUCT_EG91 0x0191 #define QUECTEL_PRODUCT_EG95 0x0195 #define QUECTEL_PRODUCT_BG96 0x0296 @@ -1218,6 +1222,18 @@ static const struct usb_device_id option_ids[] = { { USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EM060K_128, 0xff, 0xff, 0x30) }, { USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EM060K_128, 0xff, 0x00, 0x40) }, { USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EM060K_128, 0xff, 0xff, 0x40) }, + { USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EM060K_129, 0xff, 0xff, 0x30) }, + { USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EM060K_129, 0xff, 0x00, 0x40) }, + { USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EM060K_129, 0xff, 0xff, 0x40) }, + { USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EM060K_12a, 0xff, 0xff, 0x30) }, + { USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EM060K_12a, 0xff, 0x00, 0x40) }, + { USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EM060K_12a, 0xff, 0xff, 0x40) }, + { USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EM060K_12b, 0xff, 0xff, 0x30) }, + { USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EM060K_12b, 0xff, 0x00, 0x40) }, + { USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EM060K_12b, 0xff, 0xff, 0x40) }, + { USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EM060K_12c, 0xff, 0xff, 0x30) }, + { USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EM060K_12c, 0xff, 0x00, 0x40) }, + { USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EM060K_12c, 0xff, 0xff, 0x40) }, { USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EM061K_LCN, 0xff, 0xff, 0x30) }, { USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EM061K_LCN, 0xff, 0x00, 0x40) }, { USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EM061K_LCN, 0xff, 0xff, 0x40) }, -- cgit v1.2.3 From 4864a6dd8320ad856698f93009c89f66ccb1653f Mon Sep 17 00:00:00 2001 From: Amir Goldstein Date: Sun, 7 Apr 2024 18:57:56 +0300 Subject: fuse: fix wrong ff->iomode state changes from parallel dio write There is a confusion with fuse_file_uncached_io_{start,end} interface. These helpers do two things when called from passthrough open()/release(): 1. Take/drop negative refcount of fi->iocachectr (inode uncached io mode) 2. State change ff->iomode IOM_NONE <-> IOM_UNCACHED (file uncached open) The calls from parallel dio write path need to take a reference on fi->iocachectr, but they should not be changing ff->iomode state, because in this case, the fi->iocachectr reference does not stick around until file release(). Factor out helpers fuse_inode_uncached_io_{start,end}, to be used from parallel dio write path and rename fuse_file_*cached_io_{start,end} helpers to fuse_file_*cached_io_{open,release} to clarify the difference. Fixes: 205c1d802683 ("fuse: allow parallel dio writes with FUSE_DIRECT_IO_ALLOW_MMAP") Signed-off-by: Amir Goldstein Signed-off-by: Miklos Szeredi --- fs/fuse/file.c | 12 +++++++----- fs/fuse/fuse_i.h | 7 ++++--- fs/fuse/inode.c | 1 + fs/fuse/iomode.c | 56 +++++++++++++++++++++++++++++++++++++++----------------- 4 files changed, 51 insertions(+), 25 deletions(-) diff --git a/fs/fuse/file.c b/fs/fuse/file.c index a56e7bffd000..b57ce4157640 100644 --- a/fs/fuse/file.c +++ b/fs/fuse/file.c @@ -1362,7 +1362,7 @@ static void fuse_dio_lock(struct kiocb *iocb, struct iov_iter *from, bool *exclusive) { struct inode *inode = file_inode(iocb->ki_filp); - struct fuse_file *ff = iocb->ki_filp->private_data; + struct fuse_inode *fi = get_fuse_inode(inode); *exclusive = fuse_dio_wr_exclusive_lock(iocb, from); if (*exclusive) { @@ -1377,7 +1377,7 @@ static void fuse_dio_lock(struct kiocb *iocb, struct iov_iter *from, * have raced, so check it again. */ if (fuse_io_past_eof(iocb, from) || - fuse_file_uncached_io_start(inode, ff, NULL) != 0) { + fuse_inode_uncached_io_start(fi, NULL) != 0) { inode_unlock_shared(inode); inode_lock(inode); *exclusive = true; @@ -1388,13 +1388,13 @@ static void fuse_dio_lock(struct kiocb *iocb, struct iov_iter *from, static void fuse_dio_unlock(struct kiocb *iocb, bool exclusive) { struct inode *inode = file_inode(iocb->ki_filp); - struct fuse_file *ff = iocb->ki_filp->private_data; + struct fuse_inode *fi = get_fuse_inode(inode); if (exclusive) { inode_unlock(inode); } else { /* Allow opens in caching mode after last parallel dio end */ - fuse_file_uncached_io_end(inode, ff); + fuse_inode_uncached_io_end(fi); inode_unlock_shared(inode); } } @@ -2574,8 +2574,10 @@ static int fuse_file_mmap(struct file *file, struct vm_area_struct *vma) * First mmap of direct_io file enters caching inode io mode. * Also waits for parallel dio writers to go into serial mode * (exclusive instead of shared lock). + * After first mmap, the inode stays in caching io mode until + * the direct_io file release. */ - rc = fuse_file_cached_io_start(inode, ff); + rc = fuse_file_cached_io_open(inode, ff); if (rc) return rc; } diff --git a/fs/fuse/fuse_i.h b/fs/fuse/fuse_i.h index b24084b60864..f23919610313 100644 --- a/fs/fuse/fuse_i.h +++ b/fs/fuse/fuse_i.h @@ -1394,9 +1394,10 @@ int fuse_fileattr_set(struct mnt_idmap *idmap, struct dentry *dentry, struct fileattr *fa); /* iomode.c */ -int fuse_file_cached_io_start(struct inode *inode, struct fuse_file *ff); -int fuse_file_uncached_io_start(struct inode *inode, struct fuse_file *ff, struct fuse_backing *fb); -void fuse_file_uncached_io_end(struct inode *inode, struct fuse_file *ff); +int fuse_file_cached_io_open(struct inode *inode, struct fuse_file *ff); +int fuse_inode_uncached_io_start(struct fuse_inode *fi, + struct fuse_backing *fb); +void fuse_inode_uncached_io_end(struct fuse_inode *fi); int fuse_file_io_open(struct file *file, struct inode *inode); void fuse_file_io_release(struct fuse_file *ff, struct inode *inode); diff --git a/fs/fuse/inode.c b/fs/fuse/inode.c index 3a5d88878335..99e44ea7d875 100644 --- a/fs/fuse/inode.c +++ b/fs/fuse/inode.c @@ -175,6 +175,7 @@ static void fuse_evict_inode(struct inode *inode) } } if (S_ISREG(inode->i_mode) && !fuse_is_bad(inode)) { + WARN_ON(fi->iocachectr != 0); WARN_ON(!list_empty(&fi->write_files)); WARN_ON(!list_empty(&fi->queued_writes)); } diff --git a/fs/fuse/iomode.c b/fs/fuse/iomode.c index c653ddcf0578..98f1fd523dae 100644 --- a/fs/fuse/iomode.c +++ b/fs/fuse/iomode.c @@ -21,12 +21,13 @@ static inline bool fuse_is_io_cache_wait(struct fuse_inode *fi) } /* - * Start cached io mode. + * Called on cached file open() and on first mmap() of direct_io file. + * Takes cached_io inode mode reference to be dropped on file release. * * Blocks new parallel dio writes and waits for the in-progress parallel dio * writes to complete. */ -int fuse_file_cached_io_start(struct inode *inode, struct fuse_file *ff) +int fuse_file_cached_io_open(struct inode *inode, struct fuse_file *ff) { struct fuse_inode *fi = get_fuse_inode(inode); @@ -67,10 +68,9 @@ int fuse_file_cached_io_start(struct inode *inode, struct fuse_file *ff) return 0; } -static void fuse_file_cached_io_end(struct inode *inode, struct fuse_file *ff) +static void fuse_file_cached_io_release(struct fuse_file *ff, + struct fuse_inode *fi) { - struct fuse_inode *fi = get_fuse_inode(inode); - spin_lock(&fi->lock); WARN_ON(fi->iocachectr <= 0); WARN_ON(ff->iomode != IOM_CACHED); @@ -82,9 +82,8 @@ static void fuse_file_cached_io_end(struct inode *inode, struct fuse_file *ff) } /* Start strictly uncached io mode where cache access is not allowed */ -int fuse_file_uncached_io_start(struct inode *inode, struct fuse_file *ff, struct fuse_backing *fb) +int fuse_inode_uncached_io_start(struct fuse_inode *fi, struct fuse_backing *fb) { - struct fuse_inode *fi = get_fuse_inode(inode); struct fuse_backing *oldfb; int err = 0; @@ -99,9 +98,7 @@ int fuse_file_uncached_io_start(struct inode *inode, struct fuse_file *ff, struc err = -ETXTBSY; goto unlock; } - WARN_ON(ff->iomode != IOM_NONE); fi->iocachectr--; - ff->iomode = IOM_UNCACHED; /* fuse inode holds a single refcount of backing file */ if (!oldfb) { @@ -115,15 +112,29 @@ unlock: return err; } -void fuse_file_uncached_io_end(struct inode *inode, struct fuse_file *ff) +/* Takes uncached_io inode mode reference to be dropped on file release */ +static int fuse_file_uncached_io_open(struct inode *inode, + struct fuse_file *ff, + struct fuse_backing *fb) { struct fuse_inode *fi = get_fuse_inode(inode); + int err; + + err = fuse_inode_uncached_io_start(fi, fb); + if (err) + return err; + + WARN_ON(ff->iomode != IOM_NONE); + ff->iomode = IOM_UNCACHED; + return 0; +} + +void fuse_inode_uncached_io_end(struct fuse_inode *fi) +{ struct fuse_backing *oldfb = NULL; spin_lock(&fi->lock); WARN_ON(fi->iocachectr >= 0); - WARN_ON(ff->iomode != IOM_UNCACHED); - ff->iomode = IOM_NONE; fi->iocachectr++; if (!fi->iocachectr) { wake_up(&fi->direct_io_waitq); @@ -134,6 +145,15 @@ void fuse_file_uncached_io_end(struct inode *inode, struct fuse_file *ff) fuse_backing_put(oldfb); } +/* Drop uncached_io reference from passthrough open */ +static void fuse_file_uncached_io_release(struct fuse_file *ff, + struct fuse_inode *fi) +{ + WARN_ON(ff->iomode != IOM_UNCACHED); + ff->iomode = IOM_NONE; + fuse_inode_uncached_io_end(fi); +} + /* * Open flags that are allowed in combination with FOPEN_PASSTHROUGH. * A combination of FOPEN_PASSTHROUGH and FOPEN_DIRECT_IO means that read/write @@ -163,7 +183,7 @@ static int fuse_file_passthrough_open(struct inode *inode, struct file *file) return PTR_ERR(fb); /* First passthrough file open denies caching inode io mode */ - err = fuse_file_uncached_io_start(inode, ff, fb); + err = fuse_file_uncached_io_open(inode, ff, fb); if (!err) return 0; @@ -216,7 +236,7 @@ int fuse_file_io_open(struct file *file, struct inode *inode) if (ff->open_flags & FOPEN_PASSTHROUGH) err = fuse_file_passthrough_open(inode, file); else - err = fuse_file_cached_io_start(inode, ff); + err = fuse_file_cached_io_open(inode, ff); if (err) goto fail; @@ -236,8 +256,10 @@ fail: /* No more pending io and no new io possible to inode via open/mmapped file */ void fuse_file_io_release(struct fuse_file *ff, struct inode *inode) { + struct fuse_inode *fi = get_fuse_inode(inode); + /* - * Last parallel dio close allows caching inode io mode. + * Last passthrough file close allows caching inode io mode. * Last caching file close exits caching inode io mode. */ switch (ff->iomode) { @@ -245,10 +267,10 @@ void fuse_file_io_release(struct fuse_file *ff, struct inode *inode) /* Nothing to do */ break; case IOM_UNCACHED: - fuse_file_uncached_io_end(inode, ff); + fuse_file_uncached_io_release(ff, fi); break; case IOM_CACHED: - fuse_file_cached_io_end(inode, ff); + fuse_file_cached_io_release(ff, fi); break; } } -- cgit v1.2.3 From 7cc911262835419fe469ebfae89891c0e97c62ef Mon Sep 17 00:00:00 2001 From: Amir Goldstein Date: Sun, 7 Apr 2024 18:57:57 +0300 Subject: fuse: fix parallel dio write on file open in passthrough mode Parallel dio write takes a negative refcount of fi->iocachectr and so does open of file in passthrough mode. The refcount of passthrough mode is associated with attach/detach of a fuse_backing object to fuse inode. For parallel dio write, the backing file is irrelevant, so the call to fuse_inode_uncached_io_start() passes a NULL fuse_backing object. Passing a NULL fuse_backing will result in false -EBUSY error if the file is already open in passthrough mode. Allow taking negative fi->iocachectr refcount with NULL fuse_backing, because it does not conflict with an already attached fuse_backing object. Fixes: 4a90451bbc7f ("fuse: implement open in passthrough mode") Signed-off-by: Amir Goldstein Signed-off-by: Miklos Szeredi --- fs/fuse/iomode.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/fs/fuse/iomode.c b/fs/fuse/iomode.c index 98f1fd523dae..c99e285f3183 100644 --- a/fs/fuse/iomode.c +++ b/fs/fuse/iomode.c @@ -90,7 +90,7 @@ int fuse_inode_uncached_io_start(struct fuse_inode *fi, struct fuse_backing *fb) spin_lock(&fi->lock); /* deny conflicting backing files on same fuse inode */ oldfb = fuse_inode_backing(fi); - if (oldfb && oldfb != fb) { + if (fb && oldfb && oldfb != fb) { err = -EBUSY; goto unlock; } @@ -101,7 +101,7 @@ int fuse_inode_uncached_io_start(struct fuse_inode *fi, struct fuse_backing *fb) fi->iocachectr--; /* fuse inode holds a single refcount of backing file */ - if (!oldfb) { + if (fb && !oldfb) { oldfb = fuse_inode_backing_set(fi, fb); WARN_ON_ONCE(oldfb != NULL); } else { -- cgit v1.2.3 From eb4b691b9115fae4c844f5941418335575cf667f Mon Sep 17 00:00:00 2001 From: Danny Lin Date: Sat, 13 Apr 2024 17:34:31 -0700 Subject: fuse: fix leaked ENOSYS error on first statx call FUSE attempts to detect server support for statx by trying it once and setting no_statx=1 if it fails with ENOSYS, but consider the following scenario: - Userspace (e.g. sh) calls stat() on a file * succeeds - Userspace (e.g. lsd) calls statx(BTIME) on the same file - request_mask = STATX_BASIC_STATS | STATX_BTIME - first pass: sync=true due to differing cache_mask - statx fails and returns ENOSYS - set no_statx and retry - retry sets mask = STATX_BASIC_STATS - now mask == cache_mask; sync=false (time_before: still valid) - so we take the "else if (stat)" path - "err" is still ENOSYS from the failed statx call Fix this by zeroing "err" before retrying the failed call. Fixes: d3045530bdd2 ("fuse: implement statx") Cc: stable@vger.kernel.org # v6.6 Signed-off-by: Danny Lin Signed-off-by: Miklos Szeredi --- fs/fuse/dir.c | 1 + 1 file changed, 1 insertion(+) diff --git a/fs/fuse/dir.c b/fs/fuse/dir.c index 4a6df591add6..2b0d4781f394 100644 --- a/fs/fuse/dir.c +++ b/fs/fuse/dir.c @@ -1321,6 +1321,7 @@ retry: err = fuse_do_statx(inode, file, stat); if (err == -ENOSYS) { fc->no_statx = 1; + err = 0; goto retry; } } else { -- cgit v1.2.3 From fff1386cc889d8fb4089d285f883f8cba62d82ce Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Thu, 11 Apr 2024 11:15:09 +1000 Subject: nouveau: fix instmem race condition around ptr stores Running a lot of VK CTS in parallel against nouveau, once every few hours you might see something like this crash. BUG: kernel NULL pointer dereference, address: 0000000000000008 PGD 8000000114e6e067 P4D 8000000114e6e067 PUD 109046067 PMD 0 Oops: 0000 [#1] PREEMPT SMP PTI CPU: 7 PID: 53891 Comm: deqp-vk Not tainted 6.8.0-rc6+ #27 Hardware name: Gigabyte Technology Co., Ltd. Z390 I AORUS PRO WIFI/Z390 I AORUS PRO WIFI-CF, BIOS F8 11/05/2021 RIP: 0010:gp100_vmm_pgt_mem+0xe3/0x180 [nouveau] Code: c7 48 01 c8 49 89 45 58 85 d2 0f 84 95 00 00 00 41 0f b7 46 12 49 8b 7e 08 89 da 42 8d 2c f8 48 8b 47 08 41 83 c7 01 48 89 ee <48> 8b 40 08 ff d0 0f 1f 00 49 8b 7e 08 48 89 d9 48 8d 75 04 48 c1 RSP: 0000:ffffac20c5857838 EFLAGS: 00010202 RAX: 0000000000000000 RBX: 00000000004d8001 RCX: 0000000000000001 RDX: 00000000004d8001 RSI: 00000000000006d8 RDI: ffffa07afe332180 RBP: 00000000000006d8 R08: ffffac20c5857ad0 R09: 0000000000ffff10 R10: 0000000000000001 R11: ffffa07af27e2de0 R12: 000000000000001c R13: ffffac20c5857ad0 R14: ffffa07a96fe9040 R15: 000000000000001c FS: 00007fe395eed7c0(0000) GS:ffffa07e2c980000(0000) knlGS:0000000000000000 CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 CR2: 0000000000000008 CR3: 000000011febe001 CR4: 00000000003706f0 DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400 Call Trace: ... ? gp100_vmm_pgt_mem+0xe3/0x180 [nouveau] ? gp100_vmm_pgt_mem+0x37/0x180 [nouveau] nvkm_vmm_iter+0x351/0xa20 [nouveau] ? __pfx_nvkm_vmm_ref_ptes+0x10/0x10 [nouveau] ? __pfx_gp100_vmm_pgt_mem+0x10/0x10 [nouveau] ? __pfx_gp100_vmm_pgt_mem+0x10/0x10 [nouveau] ? __lock_acquire+0x3ed/0x2170 ? __pfx_gp100_vmm_pgt_mem+0x10/0x10 [nouveau] nvkm_vmm_ptes_get_map+0xc2/0x100 [nouveau] ? __pfx_nvkm_vmm_ref_ptes+0x10/0x10 [nouveau] ? __pfx_gp100_vmm_pgt_mem+0x10/0x10 [nouveau] nvkm_vmm_map_locked+0x224/0x3a0 [nouveau] Adding any sort of useful debug usually makes it go away, so I hand wrote the function in a line, and debugged the asm. Every so often pt->memory->ptrs is NULL. This ptrs ptr is set in the nv50_instobj_acquire called from nvkm_kmap. If Thread A and Thread B both get to nv50_instobj_acquire around the same time, and Thread A hits the refcount_set line, and in lockstep thread B succeeds at refcount_inc_not_zero, there is a chance the ptrs value won't have been stored since refcount_set is unordered. Force a memory barrier here, I picked smp_mb, since we want it on all CPUs and it's write followed by a read. v2: use paired smp_rmb/smp_wmb. Cc: Fixes: be55287aa5ba ("drm/nouveau/imem/nv50: embed nvkm_instobj directly into nv04_instobj") Signed-off-by: Dave Airlie Signed-off-by: Danilo Krummrich Link: https://patchwork.freedesktop.org/patch/msgid/20240411011510.2546857-1-airlied@gmail.com --- drivers/gpu/drm/nouveau/nvkm/subdev/instmem/nv50.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/instmem/nv50.c b/drivers/gpu/drm/nouveau/nvkm/subdev/instmem/nv50.c index a7f3fc342d87..dd5b5a17ece0 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/instmem/nv50.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/instmem/nv50.c @@ -222,8 +222,11 @@ nv50_instobj_acquire(struct nvkm_memory *memory) void __iomem *map = NULL; /* Already mapped? */ - if (refcount_inc_not_zero(&iobj->maps)) + if (refcount_inc_not_zero(&iobj->maps)) { + /* read barrier match the wmb on refcount set */ + smp_rmb(); return iobj->map; + } /* Take the lock, and re-check that another thread hasn't * already mapped the object in the meantime. @@ -250,6 +253,8 @@ nv50_instobj_acquire(struct nvkm_memory *memory) iobj->base.memory.ptrs = &nv50_instobj_fast; else iobj->base.memory.ptrs = &nv50_instobj_slow; + /* barrier to ensure the ptrs are written before refcount is set */ + smp_wmb(); refcount_set(&iobj->maps, 1); } -- cgit v1.2.3 From cf92bb778eda7830e79452c6917efa8474a30c1e Mon Sep 17 00:00:00 2001 From: Mikhail Kobuk Date: Thu, 11 Apr 2024 14:08:52 +0300 Subject: drm: nv04: Fix out of bounds access When Output Resource (dcb->or) value is assigned in fabricate_dcb_output(), there may be out of bounds access to dac_users array in case dcb->or is zero because ffs(dcb->or) is used as index there. The 'or' argument of fabricate_dcb_output() must be interpreted as a number of bit to set, not value. Utilize macros from 'enum nouveau_or' in calls instead of hardcoding. Found by Linux Verification Center (linuxtesting.org) with SVACE. Fixes: 2e5702aff395 ("drm/nouveau: fabricate DCB encoder table for iMac G4") Fixes: 670820c0e6a9 ("drm/nouveau: Workaround incorrect DCB entry on a GeForce3 Ti 200.") Signed-off-by: Mikhail Kobuk Signed-off-by: Danilo Krummrich Link: https://patchwork.freedesktop.org/patch/msgid/20240411110854.16701-1-m.kobuk@ispras.ru --- drivers/gpu/drm/nouveau/nouveau_bios.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/nouveau/nouveau_bios.c b/drivers/gpu/drm/nouveau/nouveau_bios.c index 479effcf607e..79cfab53f80e 100644 --- a/drivers/gpu/drm/nouveau/nouveau_bios.c +++ b/drivers/gpu/drm/nouveau/nouveau_bios.c @@ -23,6 +23,7 @@ */ #include "nouveau_drv.h" +#include "nouveau_bios.h" #include "nouveau_reg.h" #include "dispnv04/hw.h" #include "nouveau_encoder.h" @@ -1677,7 +1678,7 @@ apply_dcb_encoder_quirks(struct drm_device *dev, int idx, u32 *conn, u32 *conf) */ if (nv_match_device(dev, 0x0201, 0x1462, 0x8851)) { if (*conn == 0xf2005014 && *conf == 0xffffffff) { - fabricate_dcb_output(dcb, DCB_OUTPUT_TMDS, 1, 1, 1); + fabricate_dcb_output(dcb, DCB_OUTPUT_TMDS, 1, 1, DCB_OUTPUT_B); return false; } } @@ -1763,26 +1764,26 @@ fabricate_dcb_encoder_table(struct drm_device *dev, struct nvbios *bios) #ifdef __powerpc__ /* Apple iMac G4 NV17 */ if (of_machine_is_compatible("PowerMac4,5")) { - fabricate_dcb_output(dcb, DCB_OUTPUT_TMDS, 0, all_heads, 1); - fabricate_dcb_output(dcb, DCB_OUTPUT_ANALOG, 1, all_heads, 2); + fabricate_dcb_output(dcb, DCB_OUTPUT_TMDS, 0, all_heads, DCB_OUTPUT_B); + fabricate_dcb_output(dcb, DCB_OUTPUT_ANALOG, 1, all_heads, DCB_OUTPUT_C); return; } #endif /* Make up some sane defaults */ fabricate_dcb_output(dcb, DCB_OUTPUT_ANALOG, - bios->legacy.i2c_indices.crt, 1, 1); + bios->legacy.i2c_indices.crt, 1, DCB_OUTPUT_B); if (nv04_tv_identify(dev, bios->legacy.i2c_indices.tv) >= 0) fabricate_dcb_output(dcb, DCB_OUTPUT_TV, bios->legacy.i2c_indices.tv, - all_heads, 0); + all_heads, DCB_OUTPUT_A); else if (bios->tmds.output0_script_ptr || bios->tmds.output1_script_ptr) fabricate_dcb_output(dcb, DCB_OUTPUT_TMDS, bios->legacy.i2c_indices.panel, - all_heads, 1); + all_heads, DCB_OUTPUT_B); } static int -- cgit v1.2.3 From 09492cb45100cab909cabe164deb7cdc14e38634 Mon Sep 17 00:00:00 2001 From: Yang Li Date: Fri, 15 Mar 2024 16:02:53 +0800 Subject: cuse: add kernel-doc comments to cuse_process_init_reply() This commit adds kernel-doc style comments with complete parameter descriptions for the function cuse_process_init_reply. Signed-off-by: Yang Li Signed-off-by: Miklos Szeredi --- fs/fuse/cuse.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/fs/fuse/cuse.c b/fs/fuse/cuse.c index b6cad106c37e..0b2da7b7e2ad 100644 --- a/fs/fuse/cuse.c +++ b/fs/fuse/cuse.c @@ -310,6 +310,10 @@ struct cuse_init_args { /** * cuse_process_init_reply - finish initializing CUSE channel * + * @fm: The fuse mount information containing the CUSE connection. + * @args: The arguments passed to the init reply. + * @error: The error code signifying if any error occurred during the process. + * * This function creates the character device and sets up all the * required data structures for it. Please read the comment at the * top of this file for high level overview. -- cgit v1.2.3 From 460b0d33cf10eee33de651381d3170ef13241650 Mon Sep 17 00:00:00 2001 From: Jakub Kicinski Date: Thu, 11 Apr 2024 11:02:02 -0700 Subject: inet: bring NLM_DONE out to a separate recv() again Commit under Fixes optimized the number of recv() calls needed during RTM_GETROUTE dumps, but we got multiple reports of applications hanging on recv() calls. Applications expect that a route dump will be terminated with a recv() reading an individual NLM_DONE message. Coalescing NLM_DONE is perfectly legal in netlink, but even tho reporters fixed the code in respective projects, chances are it will take time for those applications to get updated. So revert to old behavior (for now)? Old kernel (5.19): $ ./cli.py --dbg-small-recv 4096 --spec netlink/specs/rt_route.yaml \ --dump getroute --json '{"rtm-family": 2}' Recv: read 692 bytes, 11 messages nl_len = 68 (52) nl_flags = 0x22 nl_type = 24 ... nl_len = 60 (44) nl_flags = 0x22 nl_type = 24 Recv: read 20 bytes, 1 messages nl_len = 20 (4) nl_flags = 0x2 nl_type = 3 Before (6.9-rc2): $ ./cli.py --dbg-small-recv 4096 --spec netlink/specs/rt_route.yaml \ --dump getroute --json '{"rtm-family": 2}' Recv: read 712 bytes, 12 messages nl_len = 68 (52) nl_flags = 0x22 nl_type = 24 ... nl_len = 60 (44) nl_flags = 0x22 nl_type = 24 nl_len = 20 (4) nl_flags = 0x2 nl_type = 3 After: $ ./cli.py --dbg-small-recv 4096 --spec netlink/specs/rt_route.yaml \ --dump getroute --json '{"rtm-family": 2}' Recv: read 692 bytes, 11 messages nl_len = 68 (52) nl_flags = 0x22 nl_type = 24 ... nl_len = 60 (44) nl_flags = 0x22 nl_type = 24 Recv: read 20 bytes, 1 messages nl_len = 20 (4) nl_flags = 0x2 nl_type = 3 Reported-by: Stefano Brivio Link: https://lore.kernel.org/all/20240315124808.033ff58d@elisabeth Reported-by: Ilya Maximets Link: https://lore.kernel.org/all/02b50aae-f0e9-47a4-8365-a977a85975d3@ovn.org Fixes: 4ce5dc9316de ("inet: switch inet_dump_fib() to RCU protection") Signed-off-by: Jakub Kicinski Tested-by: Ilya Maximets Reviewed-by: David Ahern Signed-off-by: David S. Miller --- net/ipv4/fib_frontend.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/net/ipv4/fib_frontend.c b/net/ipv4/fib_frontend.c index 48741352a88a..c484b1c0fc00 100644 --- a/net/ipv4/fib_frontend.c +++ b/net/ipv4/fib_frontend.c @@ -1050,6 +1050,11 @@ next: e++; } } + + /* Don't let NLM_DONE coalesce into a message, even if it could. + * Some user space expects NLM_DONE in a separate recv(). + */ + err = skb->len; out: cb->args[1] = e; -- cgit v1.2.3 From 75ce9506ee3dc66648a7d74ab3b0acfa364d6d43 Mon Sep 17 00:00:00 2001 From: Asbjørn Sloth Tønnesen Date: Fri, 12 Apr 2024 12:02:56 +0000 Subject: octeontx2-pf: fix FLOW_DIS_IS_FRAGMENT implementation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Upon reviewing the flower control flags handling in this driver, I notice that the key wasn't being used, only the mask. Ie. `tc flower ... ip_flags nofrag` was hardware offloaded as `... ip_flags frag`. Only compile tested, no access to HW. Fixes: c672e3727989 ("octeontx2-pf: Add support to filter packet based on IP fragment") Signed-off-by: Asbjørn Sloth Tønnesen Reviewed-by: Jacob Keller Signed-off-by: David S. Miller --- drivers/net/ethernet/marvell/octeontx2/nic/otx2_tc.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_tc.c b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_tc.c index 87bdb93cb066..f4655a8c0705 100644 --- a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_tc.c +++ b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_tc.c @@ -689,6 +689,7 @@ static int otx2_tc_prepare_flow(struct otx2_nic *nic, struct otx2_tc_flow *node, if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_CONTROL)) { struct flow_match_control match; + u32 val; flow_rule_match_control(rule, &match); if (match.mask->flags & FLOW_DIS_FIRST_FRAG) { @@ -697,12 +698,14 @@ static int otx2_tc_prepare_flow(struct otx2_nic *nic, struct otx2_tc_flow *node, } if (match.mask->flags & FLOW_DIS_IS_FRAGMENT) { + val = match.key->flags & FLOW_DIS_IS_FRAGMENT; if (ntohs(flow_spec->etype) == ETH_P_IP) { - flow_spec->ip_flag = IPV4_FLAG_MORE; + flow_spec->ip_flag = val ? IPV4_FLAG_MORE : 0; flow_mask->ip_flag = IPV4_FLAG_MORE; req->features |= BIT_ULL(NPC_IPFRAG_IPV4); } else if (ntohs(flow_spec->etype) == ETH_P_IPV6) { - flow_spec->next_header = IPPROTO_FRAGMENT; + flow_spec->next_header = val ? + IPPROTO_FRAGMENT : 0; flow_mask->next_header = 0xff; req->features |= BIT_ULL(NPC_IPFRAG_IPV6); } else { -- cgit v1.2.3 From 863f94ac5f4481a7c5665e8152d551701ac71bf3 Mon Sep 17 00:00:00 2001 From: John Watts Date: Wed, 3 Apr 2024 14:47:35 +1100 Subject: ASoC: sunxi: sun4i-i2s: Support 32-bit audio formats The I2S cores used in the H3 onwards support 32-bit sample rates. Support these by adding a per-variant PCM format list. Signed-off-by: John Watts Acked-by: Jernej Skrabec Link: https://lore.kernel.org/r/20240403-sunxi_s32-v2-1-29ebf6ad590a@jookia.org Signed-off-by: Mark Brown --- sound/soc/sunxi/sun4i-i2s.c | 33 ++++++++++++++++++++++++++++----- 1 file changed, 28 insertions(+), 5 deletions(-) diff --git a/sound/soc/sunxi/sun4i-i2s.c b/sound/soc/sunxi/sun4i-i2s.c index a736f632bf0b..59830f2a0d30 100644 --- a/sound/soc/sunxi/sun4i-i2s.c +++ b/sound/soc/sunxi/sun4i-i2s.c @@ -156,6 +156,7 @@ struct sun4i_i2s; /** * struct sun4i_i2s_quirks - Differences between SoC variants. * @has_reset: SoC needs reset deasserted. + * @pcm_formats: available PCM formats * @reg_offset_txdata: offset of the tx fifo. * @sun4i_i2s_regmap: regmap config to use. * @field_clkdiv_mclk_en: regmap field to enable mclk output. @@ -175,6 +176,7 @@ struct sun4i_i2s; */ struct sun4i_i2s_quirks { bool has_reset; + snd_pcm_format_t pcm_formats; unsigned int reg_offset_txdata; /* TX FIFO */ const struct regmap_config *sun4i_i2s_regmap; @@ -1092,8 +1094,18 @@ static int sun4i_i2s_dai_probe(struct snd_soc_dai *dai) return 0; } +static int sun4i_i2s_dai_startup(struct snd_pcm_substream *sub, struct snd_soc_dai *dai) +{ + struct sun4i_i2s *i2s = snd_soc_dai_get_drvdata(dai); + struct snd_pcm_runtime *runtime = sub->runtime; + + return snd_pcm_hw_constraint_mask64(runtime, SNDRV_PCM_HW_PARAM_FORMAT, + i2s->variant->pcm_formats); +} + static const struct snd_soc_dai_ops sun4i_i2s_dai_ops = { .probe = sun4i_i2s_dai_probe, + .startup = sun4i_i2s_dai_startup, .hw_params = sun4i_i2s_hw_params, .set_fmt = sun4i_i2s_set_fmt, .set_sysclk = sun4i_i2s_set_sysclk, @@ -1101,9 +1113,10 @@ static const struct snd_soc_dai_ops sun4i_i2s_dai_ops = { .trigger = sun4i_i2s_trigger, }; -#define SUN4I_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | \ - SNDRV_PCM_FMTBIT_S20_LE | \ - SNDRV_PCM_FMTBIT_S24_LE) +#define SUN4I_FORMATS_ALL (SNDRV_PCM_FMTBIT_S16_LE | \ + SNDRV_PCM_FMTBIT_S20_LE | \ + SNDRV_PCM_FMTBIT_S24_LE | \ + SNDRV_PCM_FMTBIT_S32_LE) static struct snd_soc_dai_driver sun4i_i2s_dai = { .capture = { @@ -1111,14 +1124,14 @@ static struct snd_soc_dai_driver sun4i_i2s_dai = { .channels_min = 1, .channels_max = 8, .rates = SNDRV_PCM_RATE_8000_192000, - .formats = SUN4I_FORMATS, + .formats = SUN4I_FORMATS_ALL, }, .playback = { .stream_name = "Playback", .channels_min = 1, .channels_max = 8, .rates = SNDRV_PCM_RATE_8000_192000, - .formats = SUN4I_FORMATS, + .formats = SUN4I_FORMATS_ALL, }, .ops = &sun4i_i2s_dai_ops, .symmetric_rate = 1, @@ -1340,8 +1353,12 @@ static int sun4i_i2s_runtime_suspend(struct device *dev) return 0; } +#define SUN4I_FORMATS_A10 (SUN4I_FORMATS_ALL & ~SNDRV_PCM_FMTBIT_S32_LE) +#define SUN4I_FORMATS_H3 SUN4I_FORMATS_ALL + static const struct sun4i_i2s_quirks sun4i_a10_i2s_quirks = { .has_reset = false, + .pcm_formats = SUN4I_FORMATS_A10, .reg_offset_txdata = SUN4I_I2S_FIFO_TX_REG, .sun4i_i2s_regmap = &sun4i_i2s_regmap_config, .field_clkdiv_mclk_en = REG_FIELD(SUN4I_I2S_CLK_DIV_REG, 7, 7), @@ -1360,6 +1377,7 @@ static const struct sun4i_i2s_quirks sun4i_a10_i2s_quirks = { static const struct sun4i_i2s_quirks sun6i_a31_i2s_quirks = { .has_reset = true, + .pcm_formats = SUN4I_FORMATS_A10, .reg_offset_txdata = SUN4I_I2S_FIFO_TX_REG, .sun4i_i2s_regmap = &sun4i_i2s_regmap_config, .field_clkdiv_mclk_en = REG_FIELD(SUN4I_I2S_CLK_DIV_REG, 7, 7), @@ -1383,6 +1401,7 @@ static const struct sun4i_i2s_quirks sun6i_a31_i2s_quirks = { */ static const struct sun4i_i2s_quirks sun8i_a83t_i2s_quirks = { .has_reset = true, + .pcm_formats = SUN4I_FORMATS_A10, .reg_offset_txdata = SUN8I_I2S_FIFO_TX_REG, .sun4i_i2s_regmap = &sun4i_i2s_regmap_config, .field_clkdiv_mclk_en = REG_FIELD(SUN4I_I2S_CLK_DIV_REG, 7, 7), @@ -1401,6 +1420,7 @@ static const struct sun4i_i2s_quirks sun8i_a83t_i2s_quirks = { static const struct sun4i_i2s_quirks sun8i_h3_i2s_quirks = { .has_reset = true, + .pcm_formats = SUN4I_FORMATS_H3, .reg_offset_txdata = SUN8I_I2S_FIFO_TX_REG, .sun4i_i2s_regmap = &sun8i_i2s_regmap_config, .field_clkdiv_mclk_en = REG_FIELD(SUN4I_I2S_CLK_DIV_REG, 8, 8), @@ -1419,6 +1439,7 @@ static const struct sun4i_i2s_quirks sun8i_h3_i2s_quirks = { static const struct sun4i_i2s_quirks sun50i_a64_codec_i2s_quirks = { .has_reset = true, + .pcm_formats = SUN4I_FORMATS_H3, .reg_offset_txdata = SUN8I_I2S_FIFO_TX_REG, .sun4i_i2s_regmap = &sun4i_i2s_regmap_config, .field_clkdiv_mclk_en = REG_FIELD(SUN4I_I2S_CLK_DIV_REG, 7, 7), @@ -1437,6 +1458,7 @@ static const struct sun4i_i2s_quirks sun50i_a64_codec_i2s_quirks = { static const struct sun4i_i2s_quirks sun50i_h6_i2s_quirks = { .has_reset = true, + .pcm_formats = SUN4I_FORMATS_H3, .reg_offset_txdata = SUN8I_I2S_FIFO_TX_REG, .sun4i_i2s_regmap = &sun50i_h6_i2s_regmap_config, .field_clkdiv_mclk_en = REG_FIELD(SUN4I_I2S_CLK_DIV_REG, 8, 8), @@ -1455,6 +1477,7 @@ static const struct sun4i_i2s_quirks sun50i_h6_i2s_quirks = { static const struct sun4i_i2s_quirks sun50i_r329_i2s_quirks = { .has_reset = true, + .pcm_formats = SUN4I_FORMATS_H3, .reg_offset_txdata = SUN8I_I2S_FIFO_TX_REG, .sun4i_i2s_regmap = &sun50i_h6_i2s_regmap_config, .field_clkdiv_mclk_en = REG_FIELD(SUN4I_I2S_CLK_DIV_REG, 8, 8), -- cgit v1.2.3 From b6976f323a8687cc0d55bc92c2086fd934324ed5 Mon Sep 17 00:00:00 2001 From: Christian König Date: Mon, 15 Apr 2024 15:48:21 +0200 Subject: drm/ttm: stop pooling cached NUMA pages v2 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We only pool write combined and uncached allocations because they require extra overhead on allocation and release. If we also pool cached NUMA it not only means some extra unnecessary overhead, but also that under memory pressure it can happen that pages from the wrong NUMA node enters the pool and are re-used over and over again. This can lead to performance reduction after running into memory pressure. v2: restructure and cleanup the code a bit from the internal hack to test this. Signed-off-by: Christian König Fixes: 4482d3c94d7f ("drm/ttm: add NUMA node id to the pool") CC: stable@vger.kernel.org Reviewed-by: Felix Kuehling Link: https://patchwork.freedesktop.org/patch/msgid/20240415134821.1919-1-christian.koenig@amd.com --- drivers/gpu/drm/ttm/ttm_pool.c | 38 ++++++++++++++++++++++++++++---------- 1 file changed, 28 insertions(+), 10 deletions(-) diff --git a/drivers/gpu/drm/ttm/ttm_pool.c b/drivers/gpu/drm/ttm/ttm_pool.c index 112438d965ff..6e1fd6985ffc 100644 --- a/drivers/gpu/drm/ttm/ttm_pool.c +++ b/drivers/gpu/drm/ttm/ttm_pool.c @@ -288,17 +288,23 @@ static struct ttm_pool_type *ttm_pool_select_type(struct ttm_pool *pool, enum ttm_caching caching, unsigned int order) { - if (pool->use_dma_alloc || pool->nid != NUMA_NO_NODE) + if (pool->use_dma_alloc) return &pool->caching[caching].orders[order]; #ifdef CONFIG_X86 switch (caching) { case ttm_write_combined: + if (pool->nid != NUMA_NO_NODE) + return &pool->caching[caching].orders[order]; + if (pool->use_dma32) return &global_dma32_write_combined[order]; return &global_write_combined[order]; case ttm_uncached: + if (pool->nid != NUMA_NO_NODE) + return &pool->caching[caching].orders[order]; + if (pool->use_dma32) return &global_dma32_uncached[order]; @@ -566,11 +572,17 @@ void ttm_pool_init(struct ttm_pool *pool, struct device *dev, pool->use_dma_alloc = use_dma_alloc; pool->use_dma32 = use_dma32; - if (use_dma_alloc || nid != NUMA_NO_NODE) { - for (i = 0; i < TTM_NUM_CACHING_TYPES; ++i) - for (j = 0; j < NR_PAGE_ORDERS; ++j) - ttm_pool_type_init(&pool->caching[i].orders[j], - pool, i, j); + for (i = 0; i < TTM_NUM_CACHING_TYPES; ++i) { + for (j = 0; j < NR_PAGE_ORDERS; ++j) { + struct ttm_pool_type *pt; + + /* Initialize only pool types which are actually used */ + pt = ttm_pool_select_type(pool, i, j); + if (pt != &pool->caching[i].orders[j]) + continue; + + ttm_pool_type_init(pt, pool, i, j); + } } } EXPORT_SYMBOL(ttm_pool_init); @@ -599,10 +611,16 @@ void ttm_pool_fini(struct ttm_pool *pool) { unsigned int i, j; - if (pool->use_dma_alloc || pool->nid != NUMA_NO_NODE) { - for (i = 0; i < TTM_NUM_CACHING_TYPES; ++i) - for (j = 0; j < NR_PAGE_ORDERS; ++j) - ttm_pool_type_fini(&pool->caching[i].orders[j]); + for (i = 0; i < TTM_NUM_CACHING_TYPES; ++i) { + for (j = 0; j < NR_PAGE_ORDERS; ++j) { + struct ttm_pool_type *pt; + + pt = ttm_pool_select_type(pool, i, j); + if (pt != &pool->caching[i].orders[j]) + continue; + + ttm_pool_type_fini(pt); + } } /* We removed the pool types from the LRU, but we need to also make sure -- cgit v1.2.3 From a2ac1cbc5397eb4e400efa66c3337886d9a63026 Mon Sep 17 00:00:00 2001 From: Raag Jadav Date: Mon, 15 Apr 2024 13:10:51 +0530 Subject: pwm: dwc: allow suspend/resume for 16 channels MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit With 16 channel pwm support, we're registering two instances of pwm_chip with 8 channels each. We need to update PM functions to use both instances of pwm_chip during power state transitions. Introduce struct dwc_pwm_drvdata and use it as driver_data, which will maintain both instances of pwm_chip along with dwc_pwm_info and allow us to use them inside suspend/resume handles. Fixes: ebf2c89eb95e ("pwm: dwc: Add 16 channel support for Intel Elkhart Lake") Signed-off-by: Raag Jadav Reviewed-by: Andy Shevchenko Link: https://lore.kernel.org/r/20240415074051.14681-1-raag.jadav@intel.com Signed-off-by: Uwe Kleine-König --- drivers/pwm/pwm-dwc-core.c | 1 - drivers/pwm/pwm-dwc.c | 88 ++++++++++++++++++++++++++++++---------------- drivers/pwm/pwm-dwc.h | 6 ++++ 3 files changed, 63 insertions(+), 32 deletions(-) diff --git a/drivers/pwm/pwm-dwc-core.c b/drivers/pwm/pwm-dwc-core.c index 043736972cb9..c8425493b95d 100644 --- a/drivers/pwm/pwm-dwc-core.c +++ b/drivers/pwm/pwm-dwc-core.c @@ -172,7 +172,6 @@ struct pwm_chip *dwc_pwm_alloc(struct device *dev) dwc->clk_ns = 10; chip->ops = &dwc_pwm_ops; - dev_set_drvdata(dev, chip); return chip; } EXPORT_SYMBOL_GPL(dwc_pwm_alloc); diff --git a/drivers/pwm/pwm-dwc.c b/drivers/pwm/pwm-dwc.c index 676eaf8d7a53..fb3eadf6fbc4 100644 --- a/drivers/pwm/pwm-dwc.c +++ b/drivers/pwm/pwm-dwc.c @@ -31,26 +31,34 @@ static const struct dwc_pwm_info ehl_pwm_info = { .size = 0x1000, }; -static int dwc_pwm_init_one(struct device *dev, void __iomem *base, unsigned int offset) +static int dwc_pwm_init_one(struct device *dev, struct dwc_pwm_drvdata *ddata, unsigned int idx) { struct pwm_chip *chip; struct dwc_pwm *dwc; + int ret; chip = dwc_pwm_alloc(dev); if (IS_ERR(chip)) return PTR_ERR(chip); dwc = to_dwc_pwm(chip); - dwc->base = base + offset; + dwc->base = ddata->io_base + (ddata->info->size * idx); - return devm_pwmchip_add(dev, chip); + ret = devm_pwmchip_add(dev, chip); + if (ret) + return ret; + + ddata->chips[idx] = chip; + return 0; } static int dwc_pwm_probe(struct pci_dev *pci, const struct pci_device_id *id) { const struct dwc_pwm_info *info; struct device *dev = &pci->dev; - int i, ret; + struct dwc_pwm_drvdata *ddata; + unsigned int idx; + int ret; ret = pcim_enable_device(pci); if (ret) @@ -63,17 +71,25 @@ static int dwc_pwm_probe(struct pci_dev *pci, const struct pci_device_id *id) return dev_err_probe(dev, ret, "Failed to iomap PCI BAR\n"); info = (const struct dwc_pwm_info *)id->driver_data; - - for (i = 0; i < info->nr; i++) { - /* - * No need to check for pcim_iomap_table() failure, - * pcim_iomap_regions() already does it for us. - */ - ret = dwc_pwm_init_one(dev, pcim_iomap_table(pci)[0], i * info->size); + ddata = devm_kzalloc(dev, struct_size(ddata, chips, info->nr), GFP_KERNEL); + if (!ddata) + return -ENOMEM; + + /* + * No need to check for pcim_iomap_table() failure, + * pcim_iomap_regions() already does it for us. + */ + ddata->io_base = pcim_iomap_table(pci)[0]; + ddata->info = info; + + for (idx = 0; idx < ddata->info->nr; idx++) { + ret = dwc_pwm_init_one(dev, ddata, idx); if (ret) return ret; } + dev_set_drvdata(dev, ddata); + pm_runtime_put(dev); pm_runtime_allow(dev); @@ -88,19 +104,24 @@ static void dwc_pwm_remove(struct pci_dev *pci) static int dwc_pwm_suspend(struct device *dev) { - struct pwm_chip *chip = dev_get_drvdata(dev); - struct dwc_pwm *dwc = to_dwc_pwm(chip); - int i; - - for (i = 0; i < DWC_TIMERS_TOTAL; i++) { - if (chip->pwms[i].state.enabled) { - dev_err(dev, "PWM %u in use by consumer (%s)\n", - i, chip->pwms[i].label); - return -EBUSY; + struct dwc_pwm_drvdata *ddata = dev_get_drvdata(dev); + unsigned int idx; + + for (idx = 0; idx < ddata->info->nr; idx++) { + struct pwm_chip *chip = ddata->chips[idx]; + struct dwc_pwm *dwc = to_dwc_pwm(chip); + unsigned int i; + + for (i = 0; i < DWC_TIMERS_TOTAL; i++) { + if (chip->pwms[i].state.enabled) { + dev_err(dev, "PWM %u in use by consumer (%s)\n", + i, chip->pwms[i].label); + return -EBUSY; + } + dwc->ctx[i].cnt = dwc_pwm_readl(dwc, DWC_TIM_LD_CNT(i)); + dwc->ctx[i].cnt2 = dwc_pwm_readl(dwc, DWC_TIM_LD_CNT2(i)); + dwc->ctx[i].ctrl = dwc_pwm_readl(dwc, DWC_TIM_CTRL(i)); } - dwc->ctx[i].cnt = dwc_pwm_readl(dwc, DWC_TIM_LD_CNT(i)); - dwc->ctx[i].cnt2 = dwc_pwm_readl(dwc, DWC_TIM_LD_CNT2(i)); - dwc->ctx[i].ctrl = dwc_pwm_readl(dwc, DWC_TIM_CTRL(i)); } return 0; @@ -108,14 +129,19 @@ static int dwc_pwm_suspend(struct device *dev) static int dwc_pwm_resume(struct device *dev) { - struct pwm_chip *chip = dev_get_drvdata(dev); - struct dwc_pwm *dwc = to_dwc_pwm(chip); - int i; - - for (i = 0; i < DWC_TIMERS_TOTAL; i++) { - dwc_pwm_writel(dwc, dwc->ctx[i].cnt, DWC_TIM_LD_CNT(i)); - dwc_pwm_writel(dwc, dwc->ctx[i].cnt2, DWC_TIM_LD_CNT2(i)); - dwc_pwm_writel(dwc, dwc->ctx[i].ctrl, DWC_TIM_CTRL(i)); + struct dwc_pwm_drvdata *ddata = dev_get_drvdata(dev); + unsigned int idx; + + for (idx = 0; idx < ddata->info->nr; idx++) { + struct pwm_chip *chip = ddata->chips[idx]; + struct dwc_pwm *dwc = to_dwc_pwm(chip); + unsigned int i; + + for (i = 0; i < DWC_TIMERS_TOTAL; i++) { + dwc_pwm_writel(dwc, dwc->ctx[i].cnt, DWC_TIM_LD_CNT(i)); + dwc_pwm_writel(dwc, dwc->ctx[i].cnt2, DWC_TIM_LD_CNT2(i)); + dwc_pwm_writel(dwc, dwc->ctx[i].ctrl, DWC_TIM_CTRL(i)); + } } return 0; diff --git a/drivers/pwm/pwm-dwc.h b/drivers/pwm/pwm-dwc.h index a8b074841ae8..c6e2df5a6122 100644 --- a/drivers/pwm/pwm-dwc.h +++ b/drivers/pwm/pwm-dwc.h @@ -38,6 +38,12 @@ struct dwc_pwm_info { unsigned int size; }; +struct dwc_pwm_drvdata { + const struct dwc_pwm_info *info; + void __iomem *io_base; + struct pwm_chip *chips[]; +}; + struct dwc_pwm_ctx { u32 cnt; u32 cnt2; -- cgit v1.2.3 From fb7c3d8ba039df877886fd457538d8b24ca9c84b Mon Sep 17 00:00:00 2001 From: AngeloGioacchino Del Regno Date: Thu, 4 Apr 2024 10:18:08 +0200 Subject: dt-bindings: pwm: mediatek,pwm-disp: Document power-domains property MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Allow the power-domains property to the PWM_DISP block as on some SoCs this does need at most one power domain. Fixes: b09b179bac0a ("dt-bindings: pwm: Convert pwm-mtk-disp.txt to mediatek,pwm-disp.yaml format") Signed-off-by: AngeloGioacchino Del Regno Acked-by: Krzysztof Kozlowski Link: https://lore.kernel.org/r/20240404081808.92199-1-angelogioacchino.delregno@collabora.com Signed-off-by: Uwe Kleine-König --- Documentation/devicetree/bindings/pwm/mediatek,pwm-disp.yaml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Documentation/devicetree/bindings/pwm/mediatek,pwm-disp.yaml b/Documentation/devicetree/bindings/pwm/mediatek,pwm-disp.yaml index afcdeed4e88a..bc813fe74fab 100644 --- a/Documentation/devicetree/bindings/pwm/mediatek,pwm-disp.yaml +++ b/Documentation/devicetree/bindings/pwm/mediatek,pwm-disp.yaml @@ -52,6 +52,9 @@ properties: - const: main - const: mm + power-domains: + maxItems: 1 + required: - compatible - reg -- cgit v1.2.3 From abbb99301e9d2c91567e1893dbe34f2f8b52ea9a Mon Sep 17 00:00:00 2001 From: Thorsten Leemhuis Date: Tue, 9 Apr 2024 09:30:44 +0200 Subject: docs: verify/bisect: use git switch, tag kernel, and various fixes Various small improvements and fixes: * Use the more modern 'git switch' instead of 'git checkout', which makes it more obvious what's happening (among others due to the --discard-changes parameter that is more clear than --force). * Provide a hint how a mainline version number and one from a stable series look like. * When trying to validate the bisection result with a revert, add a special tag to facilitate the identification. * Sync version numbers used in various examples for consistency: stick to 6.0.13, 6.0.15, and 6.1.5. * Fix a few typos and oddities. Signed-off-by: Thorsten Leemhuis Signed-off-by: Jonathan Corbet Link: https://lore.kernel.org/r/85029aa004447b0eeb5043fb014630f2acafacec.1712647788.git.linux@leemhuis.info --- .../verify-bugs-and-bisect-regressions.rst | 117 ++++++++++++--------- 1 file changed, 67 insertions(+), 50 deletions(-) diff --git a/Documentation/admin-guide/verify-bugs-and-bisect-regressions.rst b/Documentation/admin-guide/verify-bugs-and-bisect-regressions.rst index d3504826f401..c999e40c79ab 100644 --- a/Documentation/admin-guide/verify-bugs-and-bisect-regressions.rst +++ b/Documentation/admin-guide/verify-bugs-and-bisect-regressions.rst @@ -38,8 +38,8 @@ aspects, all of which might be essential in your present case.]* **In case you want to check if a bug is present in code currently supported by developers**, execute just the *preparations* and *segment 1*; while doing so, consider the newest Linux kernel you regularly use to be the 'working' kernel. -In the following example that's assumed to be 6.0.13, which is why the sources -of 6.0 will be used to prepare the .config file. +In the following example that's assumed to be 6.0, which is why its sources +will be used to prepare the .config file. **In case you face a regression**, follow the steps at least till the end of *segment 2*. Then you can submit a preliminary report -- or continue with @@ -61,7 +61,7 @@ will be considered the 'good' release and used to prepare the .config file. cd ~/linux/ git remote add -t master stable \ https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git - git checkout --detach v6.0 + git switch --detach v6.0 # * Hint: if you used an existing clone, ensure no stale .config is around. make olddefconfig # * Ensure the former command picked the .config of the 'working' kernel. @@ -87,7 +87,7 @@ will be considered the 'good' release and used to prepare the .config file. a) Checking out latest mainline code:: cd ~/linux/ - git checkout --force --detach mainline/master + git switch --discard-changes --detach mainline/master b) Build, install, and boot a kernel:: @@ -125,7 +125,7 @@ will be considered the 'good' release and used to prepare the .config file. a) Start by checking out the sources of the 'good' version:: cd ~/linux/ - git checkout --force --detach v6.0 + git switch --discard-changes --detach v6.0 b) Build, install, and boot a kernel as described earlier in *segment 1, section b* -- just feel free to skip the 'du' commands, as you have a rough @@ -157,11 +157,12 @@ will be considered the 'good' release and used to prepare the .config file. works with the newly built kernel. If it does, tell Git by executing ``git bisect good``; if it does not, run ``git bisect bad`` instead. - All three commands will make Git checkout another commit; then re-execute + All three commands will make Git check out another commit; then re-execute this step (e.g. build, install, boot, and test a kernel to then tell Git the outcome). Do so again and again until Git shows which commit broke things. If you run short of disk space during this process, check the - "Supplementary tasks" section below. + section 'Supplementary tasks: cleanup during and after the process' + below. d) Once your finished the bisection, put a few things away:: @@ -172,12 +173,15 @@ will be considered the 'good' release and used to prepare the .config file. e) Try to verify the bisection result:: - git checkout --force --detach mainline/master + git switch --discard-changes --detach mainline/master git revert --no-edit cafec0cacaca0 + cp ~/kernel-config-working .config + ./scripts/config --set-str CONFIG_LOCALVERSION '-local-cafec0cacaca0-reverted' This is optional, as some commits are impossible to revert. But if the second command worked flawlessly, build, install, and boot one more kernel - kernel, which should not show the regression. + kernel; just this time skip the first command copying the base .config file + over, as that already has been taken care off. * **Supplementary tasks**: cleanup during and after the process. @@ -208,7 +212,7 @@ Step-by-step guide on how to verify bugs and bisect regressions =============================================================== This guide describes how to set up your own Linux kernels for investigating bugs -or regressions you intent to report. How far you want to follow the instructions +or regressions you intend to report. How far you want to follow the instructions depends on your issue: Execute all steps till the end of *segment 1* to **verify if your kernel problem @@ -240,12 +244,17 @@ to get things rolling again. For further details on how to report Linux kernel issues or regressions check out Documentation/admin-guide/reporting-issues.rst, which works in conjunction with this document. It among others explains why you need to verify bugs with -the latest 'mainline' kernel, even if you face a problem with a kernel from a -'stable/longterm' series; for users facing a regression it also explains that -sending a preliminary report after finishing segment 2 might be wise, as the -regression and its culprit might be known already. For further details on -what actually qualifies as a regression check out -Documentation/admin-guide/reporting-regressions.rst. +the latest 'mainline' kernel (e.g. versions like 6.0, 6.1-rc1, or 6.1-rc6), +even if you face a problem with a kernel from a 'stable/longterm' series +(say 6.0.13). + +For users facing a regression that document also explains why sending a +preliminary report after segment 2 might be wise, as the regression and its +culprit might be known already. For further details on what actually qualifies +as a regression check out Documentation/admin-guide/reporting-regressions.rst. + +If you run into any problems while following this guide or have ideas how to +improve it, :ref:`please let the kernel developers know `. .. _introprep_bissbs: @@ -286,7 +295,7 @@ Preparations: set up everything to build your own kernels Do you follow this guide to verify if a bug is present in the code developers care for? Then consider the mainline release your 'working' kernel (the newest one you regularly use) is based on to be the 'good' version; if your 'working' - kernel for example is 6.0.11, then your 'good' kernel is 6.0. + kernel for example is 6.0.13, then your 'good' kernel is 6.0. In case you face a regression, it depends on the version range where the regression was introduced: @@ -295,14 +304,14 @@ Preparations: set up everything to build your own kernels 6.1-rc1? Then henceforth regard 6.0 as the last known 'good' version and 6.1-rc1 as the first 'bad' one. - * Some function stopped working when updating from 6.0.11 to 6.1.4? Then for - the time being consider 6.0 as the last 'good' version and 6.1.4 as + * Some function stopped working when updating from 6.0.13 to 6.1.5? Then for + the time being consider 6.0 as the last 'good' version and 6.1.5 as the 'bad' one. Note, at this point it is merely assumed that 6.0 is fine; this assumption will be checked in segment 2. - * A feature you used in 6.0.11 does not work at all or worse in 6.1.13? In + * A feature you used in 6.0.13 does not work at all or worse in 6.1.15? In that case you want to bisect within a stable/longterm series: consider - 6.0.11 as the last known 'good' version and 6.0.13 as the first 'bad' + 6.0.13 as the last known 'good' version and 6.0.15 as the first 'bad' one. Note, in this case you still want to compile and test a mainline kernel as explained in segment 1: the outcome will determine if you need to report your issue to the regular developers or the stable team. @@ -367,7 +376,7 @@ Preparations: set up everything to build your own kernels * Start preparing a kernel build configuration (the '.config' file). Before doing so, ensure you are still running the 'working' kernel an earlier - step told you to boot; if you are unsure, check the current kernel release + step told you to boot; if you are unsure, check the current kernelrelease identifier using ``uname -r``. Afterwards check out the source code for the version earlier established as @@ -375,7 +384,7 @@ Preparations: set up everything to build your own kernels the version number in this and all later Git commands needs to be prefixed with a 'v':: - git checkout --detach v6.0 + git switch --discard-changes --detach v6.0 Now create a build configuration file:: @@ -505,7 +514,7 @@ be a waste of time. [:ref:`details`] * Check out the latest Linux codebase:: cd ~/linux/ - git checkout --force --detach mainline/master + git switch --discard-changes --detach mainline/master [:ref:`details`] @@ -617,7 +626,7 @@ be a waste of time. [:ref:`details`] cd ~/linux/ git remote set-branches --add stable linux-6.0.y git fetch stable - git checkout --force --detach linux-6.0.y + git switch --discard-changes --detach linux-6.0.y Now use the checked out code to build and install another kernel using the commands the earlier steps already described in more detail:: @@ -669,7 +678,7 @@ otherwise would be a waste of time. [:ref:`details`] 'good' (once again assumed to be 6.0 here):: cd ~/linux/ - git checkout --detach v6.0 + git switch --discard-changes --detach v6.0 Now use the checked out code to configure, build, and install another kernel using the commands the previous subsection explained in more detail:: @@ -703,7 +712,7 @@ Segment 3: perform the bisection and validate the result With all the preparations and precaution builds taken care of, you are now ready to begin the bisection. This will make you build quite a few kernels -- usually about 15 in case you encountered a regression when updating to a newer series -(say from 6.0.11 to 6.1.3). But do not worry, due to the trimmed build +(say from 6.0.13 to 6.1.5). But do not worry, due to the trimmed build configuration created earlier this works a lot faster than many people assume: overall on average it will often just take about 10 to 15 minutes to compile each kernel on commodity x86 machines. @@ -745,7 +754,7 @@ each kernel on commodity x86 machines. If compilation fails for some reason, run ``git bisect skip`` and restart executing the stack of commands from the beginning. - In case you skipped the "test latest codebase" step in the guide, check its + In case you skipped the 'test latest codebase' step in the guide, check its description as for why the 'df [...]' and 'make -s kernelrelease [...]' commands are here. @@ -823,16 +832,16 @@ each kernel on commodity x86 machines. Begin by checking out the latest codebase depending on the range you bisected: * Did you face a regression within a stable/longterm series (say between - 6.0.11 and 6.0.13) that does not happen in mainline? Then check out the + 6.0.13 and 6.0.15) that does not happen in mainline? Then check out the latest codebase for the affected series like this:: git fetch stable - git checkout --force --detach linux-6.0.y + git switch --discard-changes --detach linux-6.0.y * In all other cases check out latest mainline:: git fetch mainline - git checkout --force --detach mainline/master + git switch --discard-changes --detach mainline/master If you bisected a regression within a stable/longterm series that also happens in mainline, there is one more thing to do: look up the mainline @@ -846,21 +855,27 @@ each kernel on commodity x86 machines. git revert --no-edit cafec0cacaca0 - If that fails, give up trying and move on to the next step. But if it works, - build a kernel again using the familiar command sequence:: + If that fails, give up trying and move on to the next step; if it works, + adjust the tag to facilitate the identification and prevent accidentally + overwriting another kernel:: cp ~/kernel-config-working .config + ./scripts/config --set-str CONFIG_LOCALVERSION '-local-cafec0cacaca0-reverted' + + Build a kernel using the familiar command sequence, just without copying the + the base .config over:: + make olddefconfig && - make -j $(nproc --all) && + make -j $(nproc --all) # * Check if the free space suffices holding another kernel: df -h /boot/ /lib/modules/ sudo make modules_install command -v installkernel && sudo make install - Make -s kernelrelease | tee -a ~/kernels-built + make -s kernelrelease | tee -a ~/kernels-built reboot - Now check one last time if the feature that made you perform a bisection work - with that kernel. + Now check one last time if the feature that made you perform a bisection works + with that kernel: if everything went well, it should not show the regression. [:ref:`details`] @@ -934,10 +949,12 @@ This concludes the step-by-step guide. Did you run into trouble following any of the above steps not cleared up by the reference section below? Did you spot errors? Or do you have ideas how to -improve the guide? Then please take a moment and let the maintainer of this +improve the guide? + +If any of that applies, please take a moment and let the maintainer of this document know by email (Thorsten Leemhuis ), ideally while CCing the Linux docs mailing list (linux-doc@vger.kernel.org). Such feedback is -vital to improve this document further, which is in everybody's interest, as it +vital to improve this text further, which is in everybody's interest, as it will enable more people to master the task described here -- and hopefully also improve similar guides inspired by this one. @@ -1059,18 +1076,18 @@ Bisection range Establishing the range of commits to be checked is mostly straightforward, except when a regression occurred when switching from a release of one stable -series to a release of a later series (e.g. from 6.0.11 to 6.1.4). In that case +series to a release of a later series (e.g. from 6.0.13 to 6.1.5). In that case Git will need some hand holding, as there is no straight line of descent. That's because with the release of 6.0 mainline carried on to 6.1 while the stable series 6.0.y branched to the side. It's therefore theoretically possible -that the issue you face with 6.1.4 only worked in 6.0.11, as it was fixed by a +that the issue you face with 6.1.5 only worked in 6.0.13, as it was fixed by a commit that went into one of the 6.0.y releases, but never hit mainline or the 6.1.y series. Thankfully that normally should not happen due to the way the stable/longterm maintainers maintain the code. It's thus pretty safe to assume 6.0 as a 'good' kernel. That assumption will be tested anyway, as that kernel will be built and tested in the segment '2' of this guide; Git would force you -to do this as well, if you tried bisecting between 6.0.11 and 6.1.13. +to do this as well, if you tried bisecting between 6.0.13 and 6.1.15. [:ref:`back to step-by-step guide `] @@ -1117,7 +1134,7 @@ These commands install a few packages that are often, but not always needed. You for example might want to skip installing the development headers for ncurses, which you will only need in case you later might want to adjust the kernel build configuration using make the targets 'menuconfig' or 'nconfig'; likewise omit -the headers of Qt6 is you do not plan to adjust the .config using 'xconfig'. +the headers of Qt6 if you do not plan to adjust the .config using 'xconfig'. You furthermore might need additional libraries and their development headers for tasks not covered in this guide -- for example when building utilities from @@ -1184,7 +1201,7 @@ First, execute the following command to retrieve the latest mainline codebase:: https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git Now deepen your clone's history to the second predecessor of the mainline -release of your 'good' version. In case the latter are 6.0 or 6.0.11, 5.19 would +release of your 'good' version. In case the latter are 6.0 or 6.0.13, 5.19 would be the first predecessor and 5.18 the second -- hence deepen the history up to that version:: @@ -1490,7 +1507,7 @@ highly recommended for these reasons: Your report might be ignored if you send it to the wrong party -- and even when you get a reply there is a decent chance that developers tell you to - evaluate which of the two cases it is before they take a closer look. + evaluate which of the two cases it is before they take a closer look. [:ref:`back to step-by-step guide `] @@ -1552,8 +1569,8 @@ by modifying your search terms or using another line from the error messages. In the end, most issues you run into have likely been encountered and reported by others already. That includes issues where the cause is not your -system, but lies in the code. If you run into one of those, you might thus find a -solution (e.g. a patch) or workaround for your issue, too. +system, but lies in the code. If you run into one of those, you might thus find +a solution (e.g. a patch) or workaround for your issue, too. Package your kernel up ~~~~~~~~~~~~~~~~~~~~~~ @@ -1767,8 +1784,8 @@ multitude of reasons why this might happen. Some ideas where to look: Note, if you found and fixed problems with the .config file, you want to use it to build another kernel from the latest codebase, as your earlier tests with -mainline and the latest version from an affected stable/longterm series were most -likely flawed. +mainline and the latest version from an affected stable/longterm series were +most likely flawed. [:ref:`back to step-by-step guide `] @@ -1911,7 +1928,7 @@ Now remove the boot entry for the kernel from your bootloader's configuration; the steps to do that vary quite a bit between Linux distributions. Note, be careful with wildcards like '*' when deleting files or directories -for kernels manually: you might accidentally remove files of a 6.0.11 kernel +for kernels manually: you might accidentally remove files of a 6.0.13 kernel when all you want is to remove 6.0 or 6.0.1. [:ref:`back to step-by-step guide `] -- cgit v1.2.3 From 932c9a5398a7b41cb8e7a0264e5470133b373e11 Mon Sep 17 00:00:00 2001 From: Thorsten Leemhuis Date: Tue, 9 Apr 2024 09:30:45 +0200 Subject: docs: verify/bisect: add and fetch stable branches ahead of time Add and fetch all required stable branches ahead of time. This fixes a bug, as readers that wanted to bisect a regression within a stable or longterm series otherwise did not have them available at the right time. This way also matches the flow somewhat better and avoids some "if you haven't already added it" phrases that otherwise become necessary in future changes. Signed-off-by: Thorsten Leemhuis Signed-off-by: Jonathan Corbet Link: https://lore.kernel.org/r/57dcf312959476abe6151bf3d35eb79e3e9a83d1.1712647788.git.linux@leemhuis.info --- .../verify-bugs-and-bisect-regressions.rst | 31 +++++++++++++--------- 1 file changed, 18 insertions(+), 13 deletions(-) diff --git a/Documentation/admin-guide/verify-bugs-and-bisect-regressions.rst b/Documentation/admin-guide/verify-bugs-and-bisect-regressions.rst index c999e40c79ab..06278501a4bd 100644 --- a/Documentation/admin-guide/verify-bugs-and-bisect-regressions.rst +++ b/Documentation/admin-guide/verify-bugs-and-bisect-regressions.rst @@ -136,8 +136,7 @@ will be considered the 'good' release and used to prepare the .config file. * **Segment 3**: perform and validate the bisection. - a) In case your 'broken' version is a stable/longterm release, add the Git - branch holding it:: + a) Retrieve the sources for your 'bad' version:: git remote set-branches --add stable linux-6.1.y git fetch stable @@ -371,6 +370,21 @@ Preparations: set up everything to build your own kernels [:ref:`details`] +.. _stablesources_bissbs: + +* Retrieve the sources for any stable or longterm series you might need. + + Is the version you earlier established as 'bad' a stable or longterm release? + Then download the code for the series it belongs to ('linux-6.1.y' in this + example):: + + git remote set-branches --add stable linux-6.1.y + git fetch stable + + If the version earlier established as 'good' is from a different stable or + longterm series (say 6.0.13), repeat the previous step, but this time for the + branch holding the series the 'good' version belongs to (e.g. linux-6.0.y). + .. _oldconfig_bissbs: * Start preparing a kernel build configuration (the '.config' file). @@ -620,12 +634,10 @@ be a waste of time. [:ref:`details`] reproduce it with the mainline kernel you just built? One that according to the `front page of kernel.org `_ is still supported? Then check if the latest codebase for the particular series might already fix the - problem. To do so, add the stable series Git branch for your 'good' kernel - (again, this here is assumed to be 6.0) and check out the latest version:: + problem. To do so, check out that series latest version (again, this here is + assumed to be 6.0):: cd ~/linux/ - git remote set-branches --add stable linux-6.0.y - git fetch stable git switch --discard-changes --detach linux-6.0.y Now use the checked out code to build and install another kernel using the @@ -717,13 +729,6 @@ configuration created earlier this works a lot faster than many people assume: overall on average it will often just take about 10 to 15 minutes to compile each kernel on commodity x86 machines. -* In case your 'bad' version is a stable/longterm release (say 6.1.5), add its - stable branch, unless you already did so earlier:: - - cd ~/linux/ - git remote set-branches --add stable linux-6.1.y - git fetch stable - .. _bisectstart_bissbs: * Start the bisection and tell Git about the versions earlier established as -- cgit v1.2.3 From 453de3207ff3534dd7165a32a73dd28cc9e8f14f Mon Sep 17 00:00:00 2001 From: Thorsten Leemhuis Date: Tue, 9 Apr 2024 09:30:46 +0200 Subject: docs: verify/bisect: proper headlines and more spacing Various small improvements and fixes: * Separate ref links from their target with a space for better readability. * Add a proper heading for the note at the end of the step-by-step guide. * Use proper 3rd and 4th level headlines in the reference section and add short intros for the 2nd level headlines that lacked one. Signed-off-by: Thorsten Leemhuis Signed-off-by: Jonathan Corbet Link: https://lore.kernel.org/r/f59f0f235a2192ed93899a7338153e4cb71075f0.1712647788.git.linux@leemhuis.info --- .../verify-bugs-and-bisect-regressions.rst | 194 ++++++++++++--------- 1 file changed, 113 insertions(+), 81 deletions(-) diff --git a/Documentation/admin-guide/verify-bugs-and-bisect-regressions.rst b/Documentation/admin-guide/verify-bugs-and-bisect-regressions.rst index 06278501a4bd..355c2cea5230 100644 --- a/Documentation/admin-guide/verify-bugs-and-bisect-regressions.rst +++ b/Documentation/admin-guide/verify-bugs-and-bisect-regressions.rst @@ -29,7 +29,7 @@ The essence of the process (aka 'TL;DR') ======================================== *[If you are new to building or bisecting Linux, ignore this section and head -over to the* ":ref:`step-by-step guide`" *below. It utilizes +over to the* ':ref:`step-by-step guide `' *below. It utilizes the same commands as this section while describing them in brief fashion. The steps are nevertheless easy to follow and together with accompanying entries in a reference section mention many alternatives, pitfalls, and additional @@ -224,15 +224,15 @@ report; instead of the latter your could also head straight on and follow *segment 3* to **perform a bisection** for a full-fledged regression report developers are obliged to act upon. - :ref:`Preparations: set up everything to build your own kernels.` + :ref:`Preparations: set up everything to build your own kernels `. - :ref:`Segment 1: try to reproduce the problem with the latest codebase.` + :ref:`Segment 1: try to reproduce the problem with the latest codebase `. - :ref:`Segment 2: check if the kernels you build work fine.` + :ref:`Segment 2: check if the kernels you build work fine `. - :ref:`Segment 3: perform a bisection and validate the result.` + :ref:`Segment 3: perform a bisection and validate the result `. - :ref:`Supplementary tasks: cleanup during and after following this guide.` + :ref:`Supplementary tasks: cleanup during and after following this guide `. The steps in each segment illustrate the important aspects of the process, while a comprehensive reference section holds additional details for almost all of the @@ -260,12 +260,14 @@ improve it, :ref:`please let the kernel developers know `. Preparations: set up everything to build your own kernels --------------------------------------------------------- +The following steps lay the groundwork for all further tasks. + .. _backup_bissbs: * Create a fresh backup and put system repair and restore tools at hand, just to be prepared for the unlikely case of something going sideways. - [:ref:`details`] + [:ref:`details `] .. _vanilla_bissbs: @@ -273,7 +275,7 @@ Preparations: set up everything to build your own kernels builds them automatically. That includes but is not limited to DKMS, openZFS, VirtualBox, and Nvidia's graphics drivers (including the GPLed kernel module). - [:ref:`details`] + [:ref:`details `] .. _secureboot_bissbs: @@ -284,7 +286,7 @@ Preparations: set up everything to build your own kernels their restrictions through a process initiated by ``mokutil --disable-validation``. - [:ref:`details`] + [:ref:`details `] .. _rangecheck_bissbs: @@ -319,13 +321,13 @@ Preparations: set up everything to build your own kernels throughout this guide will refer to the last kernel that has been working fine.* - [:ref:`details`] + [:ref:`details `] .. _bootworking_bissbs: * Boot into the 'working' kernel and briefly use the apparently broken feature. - [:ref:`details`] + [:ref:`details `] .. _diskspace_bissbs: @@ -335,7 +337,7 @@ Preparations: set up everything to build your own kernels debug symbols: both explain approaches reducing the amount of space, which should allow you to master these tasks with about 4 Gigabytes free space. - [:ref:`details`] + [:ref:`details `] .. _buildrequires_bissbs: @@ -345,7 +347,7 @@ Preparations: set up everything to build your own kernels reference section shows how to quickly install those on various popular Linux distributions. - [:ref:`details`] + [:ref:`details `] .. _sources_bissbs: @@ -368,7 +370,7 @@ Preparations: set up everything to build your own kernels git remote add -t master stable \ https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git - [:ref:`details`] + [:ref:`details `] .. _stablesources_bissbs: @@ -421,7 +423,7 @@ Preparations: set up everything to build your own kernels 'make olddefconfig' again and check if it now picked up the right config file as base. - [:ref:`details`] + [:ref:`details `] .. _localmodconfig_bissbs: @@ -455,7 +457,7 @@ Preparations: set up everything to build your own kernels spending much effort on, as long as it boots and allows to properly test the feature that causes trouble. - [:ref:`details`] + [:ref:`details `] .. _tagging_bissbs: @@ -465,7 +467,7 @@ Preparations: set up everything to build your own kernels ./scripts/config --set-str CONFIG_LOCALVERSION '-local' ./scripts/config -e CONFIG_LOCALVERSION_AUTO - [:ref:`details`] + [:ref:`details `] .. _debugsymbols_bissbs: @@ -484,7 +486,7 @@ Preparations: set up everything to build your own kernels ./scripts/config -d DEBUG_INFO -d DEBUG_INFO_DWARF_TOOLCHAIN_DEFAULT \ -d DEBUG_INFO_DWARF4 -d DEBUG_INFO_DWARF5 -e CONFIG_DEBUG_INFO_NONE - [:ref:`details`] + [:ref:`details `] .. _configmods_bissbs: @@ -494,14 +496,14 @@ Preparations: set up everything to build your own kernels * Are you running Debian? Then you want to avoid known problems by performing additional adjustments explained in the reference section. - [:ref:`details`]. + [:ref:`details `]. * If you want to influence other aspects of the configuration, do so now using your preferred tool. Note, to use make targets like 'menuconfig' or 'nconfig', you will need to install the development files of ncurses; for 'xconfig' you likewise need the Qt5 or Qt6 headers. - [:ref:`details`]. + [:ref:`details `]. .. _saveconfig_bissbs: @@ -511,7 +513,7 @@ Preparations: set up everything to build your own kernels make olddefconfig cp .config ~/kernel-config-working - [:ref:`details`] + [:ref:`details `] .. _introlatestcheck_bissbs: @@ -521,7 +523,7 @@ Segment 1: try to reproduce the problem with the latest codebase The following steps verify if the problem occurs with the code currently supported by developers. In case you face a regression, it also checks that the problem is not caused by some .config change, as reporting the issue then would -be a waste of time. [:ref:`details`] +be a waste of time. [:ref:`details `] .. _checkoutmaster_bissbs: @@ -530,7 +532,7 @@ be a waste of time. [:ref:`details`] cd ~/linux/ git switch --discard-changes --detach mainline/master - [:ref:`details`] + [:ref:`details `] .. _build_bissbs: @@ -545,7 +547,7 @@ be a waste of time. [:ref:`details`] reference section for alternatives, which obviously will require other steps to install as well. - [:ref:`details`] + [:ref:`details `] .. _install_bissbs: @@ -578,7 +580,7 @@ be a waste of time. [:ref:`details`] down: if you will build more kernels as described in segment 2 and 3, you will have to perform those again after executing ``command -v installkernel [...]``. - [:ref:`details`] + [:ref:`details `] .. _storagespace_bissbs: @@ -591,7 +593,7 @@ be a waste of time. [:ref:`details`] Write down or remember those two values for later: they enable you to prevent running out of disk space accidentally during a bisection. - [:ref:`details`] + [:ref:`details `] .. _kernelrelease_bissbs: @@ -618,7 +620,7 @@ be a waste of time. [:ref:`details`] If that command does not return '0', check the reference section, as the cause for this might interfere with your testing. - [:ref:`details`] + [:ref:`details `] .. _recheckbroken_bissbs: @@ -626,7 +628,7 @@ be a waste of time. [:ref:`details`] out the instructions in the reference section to ensure nothing went sideways during your tests. - [:ref:`details`] + [:ref:`details `] .. _recheckstablebroken_bissbs: @@ -662,12 +664,12 @@ be a waste of time. [:ref:`details`] Now verify if this kernel is showing the problem. - [:ref:`details`] + [:ref:`details `] Do you follow this guide to verify if a problem is present in the code currently supported by Linux kernel developers? Then you are done at this point. If you later want to remove the kernel you just built, check out -:ref:`Supplementary tasks: cleanup during and after following this guide`. +:ref:`Supplementary tasks: cleanup during and after following this guide `. In case you face a regression, move on and execute at least the next segment as well. @@ -679,7 +681,7 @@ Segment 2: check if the kernels you build work fine In case of a regression, you now want to ensure the trimmed configuration file you created earlier works as expected; a bisection with the .config file -otherwise would be a waste of time. [:ref:`details`] +otherwise would be a waste of time. [:ref:`details `] .. _recheckworking_bissbs: @@ -714,7 +716,7 @@ otherwise would be a waste of time. [:ref:`details`] Now check if this kernel works as expected; if not, consult the reference section for further instructions. - [:ref:`details`] + [:ref:`details `] .. _introbisect_bissbs: @@ -739,7 +741,7 @@ each kernel on commodity x86 machines. git bisect good v6.0 git bisect bad v6.1.5 - [:ref:`details`] + [:ref:`details `] .. _bisectbuild_bissbs: @@ -768,7 +770,7 @@ each kernel on commodity x86 machines. totally normal to see release identifiers like '6.0-rc1-local-gcafec0cacaca0' if you bisect between versions 6.1 and 6.2 for example. - [:ref:`details`] + [:ref:`details `] .. _bisecttest_bissbs: @@ -808,7 +810,7 @@ each kernel on commodity x86 machines. might need to scroll up to see the message mentioning the culprit; alternatively, run ``git bisect log > ~/bisection-log``. - [:ref:`details`] + [:ref:`details `] .. _bisectlog_bissbs: @@ -820,7 +822,7 @@ each kernel on commodity x86 machines. cp .config ~/bisection-config-culprit git bisect reset - [:ref:`details`] + [:ref:`details `] .. _revert_bissbs: @@ -882,7 +884,7 @@ each kernel on commodity x86 machines. Now check one last time if the feature that made you perform a bisection works with that kernel: if everything went well, it should not show the regression. - [:ref:`details`] + [:ref:`details `] .. _introclosure_bissbs: @@ -923,7 +925,7 @@ space might run out. kernel image and related files behind; in that case remove them as described in the reference section. - [:ref:`details`] + [:ref:`details `] .. _finishingtouch_bissbs: @@ -946,11 +948,15 @@ space might run out. the version considered 'good', and the last three or four you compiled during the actual bisection process. - [:ref:`details`] + [:ref:`details `] + .. _submit_improvements: -This concludes the step-by-step guide. +Conclusion +---------- + +You have reached the end of the step-by-step guide. Did you run into trouble following any of the above steps not cleared up by the reference section below? Did you spot errors? Or do you have ideas how to @@ -970,10 +976,20 @@ Reference section for the step-by-step guide This section holds additional information for almost all the items in the above step-by-step guide. +Preparations for building your own kernels +------------------------------------------ + + *The steps in this section lay the groundwork for all further tests.* + [:ref:`... `] + +The steps in all later sections of this guide depend on those described here. + +[:ref:`back to step-by-step guide `]. + .. _backup_bisref: Prepare for emergencies ------------------------ +~~~~~~~~~~~~~~~~~~~~~~~ *Create a fresh backup and put system repair and restore tools at hand.* [:ref:`... `] @@ -988,7 +1004,7 @@ for something going sideways, even if that should not happen. .. _vanilla_bisref: Remove anything related to externally maintained kernel modules ---------------------------------------------------------------- +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ *Remove all software that depends on externally developed kernel drivers or builds them automatically.* [:ref:`...`] @@ -1006,7 +1022,7 @@ explains in more detail. .. _secureboot_bisref: Deal with techniques like Secure Boot -------------------------------------- +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ *On platforms with 'Secure Boot' or similar techniques, prepare everything to ensure the system will permit your self-compiled kernel to boot later.* @@ -1043,7 +1059,7 @@ Afterwards, permit MokManager to reboot the machine. .. _bootworking_bisref: Boot the last kernel that was working -------------------------------------- +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ *Boot into the last working kernel and briefly recheck if the feature that regressed really works.* [:ref:`...`] @@ -1056,7 +1072,7 @@ the right thing. .. _diskspace_bisref: Space requirements ------------------- +~~~~~~~~~~~~~~~~~~ *Ensure to have enough free space for building Linux.* [:ref:`... `] @@ -1074,7 +1090,7 @@ space by quite a few gigabytes. .. _rangecheck_bisref: Bisection range ---------------- +~~~~~~~~~~~~~~~ *Determine the kernel versions considered 'good' and 'bad' throughout this guide.* [:ref:`...`] @@ -1099,7 +1115,7 @@ to do this as well, if you tried bisecting between 6.0.13 and 6.1.15. .. _buildrequires_bisref: Install build requirements --------------------------- +~~~~~~~~~~~~~~~~~~~~~~~~~~ *Install all software required to build a Linux kernel.* [:ref:`...`] @@ -1150,7 +1166,7 @@ the kernel's tools/ directory. .. _sources_bisref: Download the sources using Git ------------------------------- +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ *Retrieve the Linux mainline sources.* [:ref:`...`] @@ -1170,7 +1186,7 @@ work better for you: .. _sources_bundle_bisref: Downloading Linux mainline sources using a bundle -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +""""""""""""""""""""""""""""""""""""""""""""""""" Use the following commands to retrieve the Linux mainline sources using a bundle:: @@ -1241,7 +1257,7 @@ Note, shallow clones have a few peculiar characteristics: .. _oldconfig_bisref: Start defining the build configuration for your kernel ------------------------------------------------------- +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ *Start preparing a kernel build configuration (the '.config' file).* [:ref:`... `] @@ -1301,7 +1317,7 @@ that file to the build machine and store it as ~/linux/.config; afterwards run .. _localmodconfig_bisref: Trim the build configuration for your kernel --------------------------------------------- +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ *Disable any kernel modules apparently superfluous for your setup.* [:ref:`... `] @@ -1350,7 +1366,7 @@ step-by-step guide mentions:: .. _tagging_bisref: Tag the kernels about to be build ---------------------------------- +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ *Ensure all the kernels you will build are clearly identifiable using a special tag and a unique version identifier.* [:ref:`... `] @@ -1366,7 +1382,7 @@ confusing during the bisection. .. _debugsymbols_bisref: Decide to enable or disable debug symbols ------------------------------------------ +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ *Decide how to handle debug symbols.* [:ref:`... `] @@ -1395,7 +1411,7 @@ explains this process in more detail. .. _configmods_bisref: Adjust build configuration --------------------------- +~~~~~~~~~~~~~~~~~~~~~~~~~~ *Check if you may want or need to adjust some other kernel configuration options:* @@ -1406,7 +1422,7 @@ kernel configuration options. .. _configmods_distros_bisref: Distro specific adjustments -~~~~~~~~~~~~~~~~~~~~~~~~~~~ +""""""""""""""""""""""""""" *Are you running* [:ref:`... `] @@ -1431,7 +1447,7 @@ when following this guide on a few commodity distributions. .. _configmods_individual_bisref: Individual adjustments -~~~~~~~~~~~~~~~~~~~~~~ +"""""""""""""""""""""" *If you want to influence the other aspects of the configuration, do so now.* [:ref:`... `] @@ -1448,13 +1464,13 @@ is missing. .. _saveconfig_bisref: Put the .config file aside --------------------------- +~~~~~~~~~~~~~~~~~~~~~~~~~~ *Reprocess the .config after the latest changes and store it in a safe place.* [:ref:`... `] Put the .config you prepared aside, as you want to copy it back to the build -directory every time during this guide before you start building another +directory every time during this guide before you start building another kernel. That's because going back and forth between different versions can alter .config files in odd ways; those occasionally cause side effects that could confuse testing or in some cases render the result of your bisection @@ -1464,8 +1480,8 @@ meaningless. .. _introlatestcheck_bisref: -Try to reproduce the regression ------------------------------------------ +Try to reproduce the problem with the latest codebase +----------------------------------------------------- *Verify the regression is not caused by some .config change and check if it still occurs with the latest codebase.* [:ref:`... `] @@ -1519,21 +1535,21 @@ highly recommended for these reasons: .. _checkoutmaster_bisref: Check out the latest Linux codebase ------------------------------------ +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ *Check out the latest Linux codebase.* - [:ref:`... `] + [:ref:`... `] In case you later want to recheck if an ever newer codebase might fix the problem, remember to run that ``git fetch --shallow-exclude [...]`` command again mentioned earlier to update your local Git repository. -[:ref:`back to step-by-step guide `] +[:ref:`back to step-by-step guide `] .. _build_bisref: Build your kernel ------------------ +~~~~~~~~~~~~~~~~~ *Build the image and the modules of your first kernel using the config file you prepared.* [:ref:`... `] @@ -1543,7 +1559,7 @@ yourself. Another subsection explains how to directly package your kernel up as deb, rpm or tar file. Dealing with build errors -~~~~~~~~~~~~~~~~~~~~~~~~~ +""""""""""""""""""""""""" When a build error occurs, it might be caused by some aspect of your machine's setup that often can be fixed quickly; other times though the problem lies in @@ -1578,7 +1594,7 @@ system, but lies in the code. If you run into one of those, you might thus find a solution (e.g. a patch) or workaround for your issue, too. Package your kernel up -~~~~~~~~~~~~~~~~~~~~~~ +"""""""""""""""""""""" The step-by-step guide uses the default make targets (e.g. 'bzImage' and 'modules' on x86) to build the image and the modules of your kernel, which later @@ -1609,7 +1625,7 @@ distribution's kernel packages. .. _install_bisref: Put the kernel in place ------------------------ +~~~~~~~~~~~~~~~~~~~~~~~ *Install the kernel you just built.* [:ref:`... `] @@ -1652,7 +1668,7 @@ process. Afterwards add your kernel to your bootloader configuration and reboot. .. _storagespace_bisref: Storage requirements per kernel -------------------------------- +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ *Check how much storage space the kernel, its modules, and other related files like the initramfs consume.* [:ref:`... `] @@ -1673,7 +1689,7 @@ need to look in different places. .. _tainted_bisref: Check if your newly built kernel considers itself 'tainted' ------------------------------------------------------------ +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ *Check if the kernel marked itself as 'tainted'.* [:ref:`... `] @@ -1692,7 +1708,7 @@ interest, as your testing might be flawed otherwise. .. _recheckbroken_bisref: Check the kernel built from a recent mainline codebase ------------------------------------------------------- +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ *Verify if your bug occurs with the newly built kernel.* [:ref:`... `] @@ -1718,7 +1734,7 @@ the kernel you built from the latest codebase. These are the most frequent: .. _recheckstablebroken_bisref: Check the kernel built from the latest stable/longterm codebase ---------------------------------------------------------------- +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ *Are you facing a regression within a stable/longterm release, but failed to reproduce it with the kernel you just built using the latest mainline sources? @@ -1763,7 +1779,7 @@ ensure the kernel version you assumed to be 'good' earlier in the process (e.g. .. _recheckworking_bisref: Build your own version of the 'good' kernel -------------------------------------------- +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ *Build your own variant of the working kernel and check if the feature that regressed works as expected with it.* [:ref:`... `] @@ -1794,10 +1810,20 @@ most likely flawed. [:ref:`back to step-by-step guide `] +Perform a bisection and validate the result +------------------------------------------- + + *With all the preparations and precaution builds taken care of, you are now + ready to begin the bisection.* [:ref:`... `] + +The steps in this segment perform and validate the bisection. + +[:ref:`back to step-by-step guide `]. + .. _bisectstart_bisref: Start the bisection -------------------- +~~~~~~~~~~~~~~~~~~~ *Start the bisection and tell Git about the versions earlier established as 'good' and 'bad'.* [:ref:`... `] @@ -1811,7 +1837,7 @@ for you to test. .. _bisectbuild_bisref: Build a kernel from the bisection point ---------------------------------------- +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ *Build, install, and boot a kernel from the code Git checked out using the same commands you used earlier.* [:ref:`... `] @@ -1839,7 +1865,7 @@ There are two things worth of note here: .. _bisecttest_bisref: Bisection checkpoint --------------------- +~~~~~~~~~~~~~~~~~~~~ *Check if the feature that regressed works in the kernel you just built.* [:ref:`... `] @@ -1853,7 +1879,7 @@ will be for nothing. .. _bisectlog_bisref: Put the bisection log away --------------------------- +~~~~~~~~~~~~~~~~~~~~~~~~~~ *Store Git's bisection log and the current .config file in a safe place.* [:ref:`... `] @@ -1873,7 +1899,7 @@ ask for it after you report the regression. .. _revert_bisref: Try reverting the culprit -------------------------- +~~~~~~~~~~~~~~~~~~~~~~~~~ *Try reverting the culprit on top of the latest codebase to see if this fixes your regression.* [:ref:`... `] @@ -1891,14 +1917,20 @@ succeeds, test that kernel version instead. [:ref:`back to step-by-step guide `] +Cleanup steps during and after following this guide +--------------------------------------------------- -Supplementary tasks: cleanup during and after the bisection ------------------------------------------------------------ + *During and after following this guide you might want or need to remove some + of the kernels you installed.* [:ref:`... `] + +The steps in this section describe clean-up procedures. + +[:ref:`back to step-by-step guide `]. .. _makeroom_bisref: Cleaning up during the bisection --------------------------------- +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ *To remove one of the kernels you installed, look up its 'kernelrelease' identifier.* [:ref:`... `] @@ -1939,7 +1971,7 @@ when all you want is to remove 6.0 or 6.0.1. [:ref:`back to step-by-step guide `] Cleaning up after the bisection -------------------------------- +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .. _finishingtouch_bisref: -- cgit v1.2.3 From a421835a2a327f2b3472dcb755adb57d0f82e478 Mon Sep 17 00:00:00 2001 From: Thorsten Leemhuis Date: Tue, 9 Apr 2024 09:30:47 +0200 Subject: docs: verify/bisect: explain testing reverts, patches and newer code Rename 'Supplementary tasks' to 'Complementary tasks' while introducing a section 'Optional tasks: test reverts, patches, or later versions': the latter is something readers occasionally will have to do after reporting a bug and thus is best covered here. Signed-off-by: Thorsten Leemhuis Signed-off-by: Jonathan Corbet Link: https://lore.kernel.org/r/dacf26a4c48e9e8f04ecbc77e0a74c9b2a6a1103.1712647788.git.linux@leemhuis.info --- .../verify-bugs-and-bisect-regressions.rst | 128 ++++++++++++++++++--- 1 file changed, 115 insertions(+), 13 deletions(-) diff --git a/Documentation/admin-guide/verify-bugs-and-bisect-regressions.rst b/Documentation/admin-guide/verify-bugs-and-bisect-regressions.rst index 355c2cea5230..1987c827211f 100644 --- a/Documentation/admin-guide/verify-bugs-and-bisect-regressions.rst +++ b/Documentation/admin-guide/verify-bugs-and-bisect-regressions.rst @@ -160,7 +160,7 @@ will be considered the 'good' release and used to prepare the .config file. this step (e.g. build, install, boot, and test a kernel to then tell Git the outcome). Do so again and again until Git shows which commit broke things. If you run short of disk space during this process, check the - section 'Supplementary tasks: cleanup during and after the process' + section 'Complementary tasks: cleanup during and after the process' below. d) Once your finished the bisection, put a few things away:: @@ -182,7 +182,7 @@ will be considered the 'good' release and used to prepare the .config file. kernel; just this time skip the first command copying the base .config file over, as that already has been taken care off. -* **Supplementary tasks**: cleanup during and after the process. +* **Complementary tasks**: cleanup during and after the process. a) To avoid running out of disk space during a bisection, you might need to remove some kernels you built earlier. You most likely want to keep those @@ -205,6 +205,18 @@ will be considered the 'good' release and used to prepare the .config file. the kernels you built earlier and later you might want to keep around for a week or two. +* **Optional task**: test a debug patch or a proposed fix later:: + + git fetch mainline + git switch --discard-changes --detach mainline/master + git apply /tmp/foobars-proposed-fix-v1.patch + cp ~/kernel-config-working .config + ./scripts/config --set-str CONFIG_LOCALVERSION '-local-foobars-fix-v1' + + Build, install, and boot a kernel as described in *segment 1, section b* -- + but this time omit the first command copying the build configuration over, + as that has been taken care of already. + .. _introguide_bissbs: Step-by-step guide on how to verify bugs and bisect regressions @@ -232,7 +244,9 @@ developers are obliged to act upon. :ref:`Segment 3: perform a bisection and validate the result `. - :ref:`Supplementary tasks: cleanup during and after following this guide `. + :ref:`Complementary tasks: cleanup during and after following this guide `. + + :ref:`Optional tasks: test reverts, patches, or later versions `. The steps in each segment illustrate the important aspects of the process, while a comprehensive reference section holds additional details for almost all of the @@ -669,7 +683,7 @@ be a waste of time. [:ref:`details `] Do you follow this guide to verify if a problem is present in the code currently supported by Linux kernel developers? Then you are done at this point. If you later want to remove the kernel you just built, check out -:ref:`Supplementary tasks: cleanup during and after following this guide `. +:ref:`Complementary tasks: cleanup during and after following this guide `. In case you face a regression, move on and execute at least the next segment as well. @@ -888,7 +902,7 @@ each kernel on commodity x86 machines. .. _introclosure_bissbs: -Supplementary tasks: cleanup during and after the bisection +Complementary tasks: cleanup during and after the bisection ----------------------------------------------------------- During and after following this guide you might want or need to remove some of @@ -950,6 +964,81 @@ space might run out. [:ref:`details `] +.. _introoptional_bissbs: + +Optional: test reverts, patches, or later versions +-------------------------------------------------- + +While or after reporting a bug, you might want or potentially will be asked to +test reverts, debug patches, proposed fixes, or other versions. In that case +follow these instructions. + +* Update your Git clone and check out the latest code. + + * In case you want to test mainline, fetch its latest changes before checking + its code out:: + + git fetch mainline + git switch --discard-changes --detach mainline/master + + * In case you want to test a stable or longterm kernel, first add the branch + holding the series you are interested in (6.2 in the example), unless you + already did so earlier:: + + git remote set-branches --add stable linux-6.2.y + + Then fetch the latest changes and check out the latest version from the + series:: + + git fetch stable + git switch --discard-changes --detach stable/linux-6.2.y + +* Copy your kernel build configuration over:: + + cp ~/kernel-config-working .config + +* Your next step depends on what you want to do: + + * In case you just want to test the latest codebase, head to the next step, + you are already all set. + + * In case you want to test if a revert fixes an issue, revert one or multiple + changes by specifying their commit ids:: + + git revert --no-edit cafec0cacaca0 + + Now give that kernel a special tag to facilitates its identification and + prevent accidentally overwriting another kernel:: + + ./scripts/config --set-str CONFIG_LOCALVERSION '-local-cafec0cacaca0-reverted' + + * In case you want to test a patch, store the patch in a file like + '/tmp/foobars-proposed-fix-v1.patch' and apply it like this:: + + git apply /tmp/foobars-proposed-fix-v1.patch + + In case of multiple patches, repeat this step with the others. + + Now give that kernel a special tag to facilitates its identification and + prevent accidentally overwriting another kernel:: + + ./scripts/config --set-str CONFIG_LOCALVERSION '-local-foobars-fix-v1' + +* Build a kernel using the familiar commands, just without copying the kernel + build configuration over, as that has been taken care of already:: + + make olddefconfig && + make -j $(nproc --all) + # * Check if the free space suffices holding another kernel: + df -h /boot/ /lib/modules/ + sudo make modules_install + command -v installkernel && sudo make install + make -s kernelrelease | tee -a ~/kernels-built + reboot + +* Now verify you booted the newly built kernel and check it. + +[:ref:`details `] .. _submit_improvements: @@ -1986,20 +2075,33 @@ build artifacts and the Linux sources, but will leave the Git repository (~/linux/.git/) behind -- a simple ``git reset --hard`` thus will bring the sources back. -Removing the repository as well would likely be unwise at this point: there is a -decent chance developers will ask you to build another kernel to perform -additional tests. This is often required to debug an issue or check proposed -fixes. Before doing so you want to run the ``git fetch mainline`` command again -followed by ``git checkout mainline/master`` to bring your clone up to date and -checkout the latest codebase. Then apply the patch using ``git apply -`` or ``git am `` and build yet another kernel using the -familiar commands. +Removing the repository as well would likely be unwise at this point: there +is a decent chance developers will ask you to build another kernel to +perform additional tests -- like testing a debug patch or a proposed fix. +Details on how to perform those can be found in the section :ref:`Optional +tasks: test reverts, patches, or later versions `. Additional tests are also the reason why you want to keep the ~/kernel-config-working file around for a few weeks. [:ref:`back to step-by-step guide `] +.. _introoptional_bisref: + +Test reverts, patches, or later versions +---------------------------------------- + + *While or after reporting a bug, you might want or potentially will be asked + to test reverts, patches, proposed fixes, or other versions.* + [:ref:`... `] + +All the commands used in this section should be pretty straight forward, so +there is not much to add except one thing: when setting a kernel tag as +instructed, ensure it is not much longer than the one used in the example, as +problems will arise if the kernelrelease identifier exceeds 63 characters. + +[:ref:`back to step-by-step guide `]. + Additional reading material =========================== -- cgit v1.2.3 From 2bcfd71e8dfca5047f9fbcc2e2ba62c5bb39aa3a Mon Sep 17 00:00:00 2001 From: Thorsten Leemhuis Date: Tue, 9 Apr 2024 09:30:48 +0200 Subject: docs: verify/bisect: describe how to use a build host Describe how to build kernels on another system (with and without cross-compiling), as building locally can be quite painfully on some slow systems. This is done in an add-on section, as it would make the step-by-step guide to complicated if this special case would be described there. Signed-off-by: Thorsten Leemhuis Signed-off-by: Jonathan Corbet Link: https://lore.kernel.org/r/288160cb4769e46a3280250ca71da0abc4aa002d.1712647788.git.linux@leemhuis.info --- .../verify-bugs-and-bisect-regressions.rst | 78 ++++++++++++++++++++-- 1 file changed, 74 insertions(+), 4 deletions(-) diff --git a/Documentation/admin-guide/verify-bugs-and-bisect-regressions.rst b/Documentation/admin-guide/verify-bugs-and-bisect-regressions.rst index 1987c827211f..6193c7976427 100644 --- a/Documentation/admin-guide/verify-bugs-and-bisect-regressions.rst +++ b/Documentation/admin-guide/verify-bugs-and-bisect-regressions.rst @@ -276,6 +276,10 @@ Preparations: set up everything to build your own kernels The following steps lay the groundwork for all further tasks. +Note: the instructions assume you are building and testing on the same +machine; if you want to compile the kernel on another system, check +:ref:`Build kernels on a different machine ` below. + .. _backup_bissbs: * Create a fresh backup and put system repair and restore tools at hand, just @@ -2103,11 +2107,77 @@ problems will arise if the kernelrelease identifier exceeds 63 characters. [:ref:`back to step-by-step guide `]. -Additional reading material -=========================== +Additional information +====================== + +.. _buildhost_bis: + +Build kernels on a different machine +------------------------------------ + +To compile kernels on another system, slightly alter the step-by-step guide's +instructions: + +* Start following the guide on the machine where you want to install and test + the kernels later. + +* After executing ':ref:`Boot into the working kernel and briefly use the + apparently broken feature `', save the list of loaded + modules to a file using ``lsmod > ~/test-machine-lsmod``. Then locate the + build configuration for the running kernel (see ':ref:`Start defining the + build configuration for your kernel `' for hints on where + to find it) and store it as '~/test-machine-config-working'. Transfer both + files to the home directory of your build host. + +* Continue the guide on the build host (e.g. with ':ref:`Ensure to have enough + free space for building [...] `'). + +* When you reach ':ref:`Start preparing a kernel build configuration[...] + `': before running ``make olddefconfig`` for the first time, + execute the following command to base your configuration on the one from the + test machine's 'working' kernel:: + + cp ~/test-machine-config-working ~/linux/.config + +* During the next step to ':ref:`disable any apparently superfluous kernel + modules `' use the following command instead:: + + yes '' | make localmodconfig LSMOD=~/lsmod_foo-machine localmodconfig + +* Continue the guide, but ignore the instructions outlining how to compile, + install, and reboot into a kernel every time they come up. Instead build + like this:: -Further sources ---------------- + cp ~/kernel-config-working .config + make olddefconfig && + make -j $(nproc --all) targz-pkg + + This will generate a gzipped tar file whose name is printed in the last + line shown; for example, a kernel with the kernelrelease identifier + '6.0.0-rc1-local-g928a87efa423' built for x86 machines usually will + be stored as '~/linux/linux-6.0.0-rc1-local-g928a87efa423-x86.tar.gz'. + + Copy that file to your test machine's home directory. + +* Switch to the test machine to check if you have enough space to hold another + kernel. Then extract the file you transferred:: + + sudo tar -xvzf ~/linux-6.0.0-rc1-local-g928a87efa423-x86.tar.gz -C / + + Afterwards :ref:`generate the initramfs and add the kernel to your boot + loader's configuration `; on some distributions the following + command will take care of both these tasks:: + + sudo /sbin/installkernel 6.0.0-rc1-local-g928a87efa423 /boot/vmlinuz-6.0.0-rc1-local-g928a87efa423 + + Now reboot and ensure you started the intended kernel. + +This approach even works when building for another architecture: just install +cross-compilers and add the appropriate parameters to every invocation of make +(e.g. ``make ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- [...]``). + +Additional reading material +--------------------------- * The `man page for 'git bisect' `_ and `fighting regressions with 'git bisect' `_ -- cgit v1.2.3 From 8d939ae349343b55984ea821164e2be526d48cd1 Mon Sep 17 00:00:00 2001 From: Thorsten Leemhuis Date: Tue, 9 Apr 2024 09:30:49 +0200 Subject: docs: verify/bisect: stable regressions: first stable, then mainline Rearrange the instructions so that readers facing a regression within a stable or longterm series first test its latest release before testing mainline. This is less scary for some people. It also reduces the chance that something goes sideways for readers that compile their first kernel, as mainline can cause slightly more trouble. Signed-off-by: Thorsten Leemhuis Signed-off-by: Jonathan Corbet Link: https://lore.kernel.org/r/efd3cb9c68db450091021326bf9c334553df0ec2.1712647788.git.linux@leemhuis.info --- .../verify-bugs-and-bisect-regressions.rst | 91 ++++++++++++---------- 1 file changed, 51 insertions(+), 40 deletions(-) diff --git a/Documentation/admin-guide/verify-bugs-and-bisect-regressions.rst b/Documentation/admin-guide/verify-bugs-and-bisect-regressions.rst index 6193c7976427..c389d4fd7599 100644 --- a/Documentation/admin-guide/verify-bugs-and-bisect-regressions.rst +++ b/Documentation/admin-guide/verify-bugs-and-bisect-regressions.rst @@ -309,31 +309,32 @@ machine; if you want to compile the kernel on another system, check .. _rangecheck_bissbs: * Determine the kernel versions considered 'good' and 'bad' throughout this - guide. + guide: - Do you follow this guide to verify if a bug is present in the code developers - care for? Then consider the mainline release your 'working' kernel (the newest - one you regularly use) is based on to be the 'good' version; if your 'working' - kernel for example is 6.0.13, then your 'good' kernel is 6.0. + * Do you follow this guide to verify if a bug is present in the code the + primary developers care for? Then consider the version of the newest kernel + you regularly use currently as 'good' (e.g. 6.0, 6.0.13, or 6.1-rc2). - In case you face a regression, it depends on the version range where the - regression was introduced: + * Do you face a regression, e.g. something broke or works worse after + switching to a newer kernel version? In that case it depends on the version + range during which the problem appeared: - * Something which used to work in Linux 6.0 broke when switching to Linux - 6.1-rc1? Then henceforth regard 6.0 as the last known 'good' version - and 6.1-rc1 as the first 'bad' one. + * Something regressed when updating from a stable/longterm release + (say 6.0.13) to a newer mainline series (like 6.1-rc7 or 6.1) or a + stable/longterm version based on one (say 6.1.5)? Then consider the + mainline release your working kernel is based on to be the 'good' + version (e.g. 6.0) and the first version to be broken as the 'bad' one + (e.g. 6.1-rc7, 6.1, or 6.1.5). Note, at this point it is merely assumed + that 6.0 is fine; this hypothesis will be checked in segment 2. - * Some function stopped working when updating from 6.0.13 to 6.1.5? Then for - the time being consider 6.0 as the last 'good' version and 6.1.5 as - the 'bad' one. Note, at this point it is merely assumed that 6.0 is fine; - this assumption will be checked in segment 2. + * Something regressed when switching from one mainline version (say 6.0) to + a later one (like 6.1-rc1) or a stable/longterm release based on it + (say 6.1.5)? Then regard the last working version (e.g. 6.0) as 'good' and + the first broken (e.g. 6.1-rc1 or 6.1.5) as 'bad'. - * A feature you used in 6.0.13 does not work at all or worse in 6.1.15? In - that case you want to bisect within a stable/longterm series: consider - 6.0.13 as the last known 'good' version and 6.0.15 as the first 'bad' - one. Note, in this case you still want to compile and test a mainline kernel - as explained in segment 1: the outcome will determine if you need to report - your issue to the regular developers or the stable team. + * Something regressed when updating within a stable/longterm series (say + from 6.0.13 to 6.0.15)? Then consider those versions as 'good' and 'bad' + (e.g. 6.0.13 and 6.0.15), as you need to bisect within that series. *Note, do not confuse 'good' version with 'working' kernel; the latter term throughout this guide will refer to the last kernel that has been working @@ -392,19 +393,13 @@ machine; if you want to compile the kernel on another system, check .. _stablesources_bissbs: -* Retrieve the sources for any stable or longterm series you might need. - - Is the version you earlier established as 'bad' a stable or longterm release? - Then download the code for the series it belongs to ('linux-6.1.y' in this - example):: +* Is one of the versions you earlier established as 'good' or 'bad' a stable or + longterm release (say 6.1.5)? Then download the code for the series it belongs + to ('linux-6.1.y' in this example):: git remote set-branches --add stable linux-6.1.y git fetch stable - If the version earlier established as 'good' is from a different stable or - longterm series (say 6.0.13), repeat the previous step, but this time for the - branch holding the series the 'good' version belongs to (e.g. linux-6.0.y). - .. _oldconfig_bissbs: * Start preparing a kernel build configuration (the '.config' file). @@ -545,10 +540,24 @@ be a waste of time. [:ref:`details `] .. _checkoutmaster_bissbs: -* Check out the latest Linux codebase:: +* Check out the latest Linux codebase. - cd ~/linux/ - git switch --discard-changes --detach mainline/master + * Are your 'good' and 'bad' versions from the same stable or longterm series? + Then check the `front page of kernel.org `_: if it + lists a release from that series without an '[EOL]' tag, checkout the series + latest version ('linux-6.1.y' in the following example):: + + cd ~/linux/ + git switch --discard-changes --detach stable/linux-6.1.y + + Your series is unsupported, if is not listed or carrying a 'end of life' + tag. In that case you might want to check if a successor series (say + linux-6.2.y) or mainline (see next point) fix the bug. + + * In all other cases, run:: + + cd ~/linux/ + git switch --discard-changes --detach mainline/master [:ref:`details `] @@ -650,15 +659,15 @@ be a waste of time. [:ref:`details `] .. _recheckstablebroken_bissbs: -* Are you facing a problem within a stable/longterm series, but failed to - reproduce it with the mainline kernel you just built? One that according to - the `front page of kernel.org `_ is still supported? Then - check if the latest codebase for the particular series might already fix the - problem. To do so, check out that series latest version (again, this here is - assumed to be 6.0):: +* Did you just built a stable or longterm kernel? And were you able to reproduce + the regression with it? Then you should test the latest mainline codebase as + well, because the result determines which developers the bug must be submitted + to. + + To prepare that test, check out current mainline:: cd ~/linux/ - git switch --discard-changes --detach linux-6.0.y + git switch --discard-changes --detach mainline/master Now use the checked out code to build and install another kernel using the commands the earlier steps already described in more detail:: @@ -680,7 +689,9 @@ be a waste of time. [:ref:`details `] uname -r cat /proc/sys/kernel/tainted - Now verify if this kernel is showing the problem. + Now verify if this kernel is showing the problem. If it does, then you need + to report the bug to the primary developers; if it does not, report it to the + stable team. See Documentation/admin-guide/reporting-issues.rst for details. [:ref:`details `] -- cgit v1.2.3 From b32233accefff1338806f064fb9b62cf5bc0609f Mon Sep 17 00:00:00 2001 From: Zack Rusin Date: Thu, 11 Apr 2024 22:55:09 -0400 Subject: drm/vmwgfx: Fix prime import/export vmwgfx never supported prime import of external buffers. Furthermore the driver exposes two different objects to userspace: vmw_surface's and gem buffers but prime import/export only worked with vmw_surfaces. Because gem buffers are used through the dumb_buffer interface this meant that the driver created buffers couldn't have been prime exported or imported. Fix prime import/export. Makes IGT's kms_prime pass. Signed-off-by: Zack Rusin Fixes: 8afa13a0583f ("drm/vmwgfx: Implement DRIVER_GEM") Cc: # v6.6+ Reviewed-by: Martin Krastev Link: https://patchwork.freedesktop.org/patch/msgid/20240412025511.78553-4-zack.rusin@broadcom.com --- drivers/gpu/drm/vmwgfx/vmwgfx_blit.c | 35 ++++++++++++++++++++++-- drivers/gpu/drm/vmwgfx/vmwgfx_bo.c | 7 +++-- drivers/gpu/drm/vmwgfx/vmwgfx_bo.h | 2 ++ drivers/gpu/drm/vmwgfx/vmwgfx_drv.c | 1 + drivers/gpu/drm/vmwgfx/vmwgfx_drv.h | 3 ++ drivers/gpu/drm/vmwgfx/vmwgfx_gem.c | 32 ++++++++++++++++++++++ drivers/gpu/drm/vmwgfx/vmwgfx_prime.c | 15 ++++++++-- drivers/gpu/drm/vmwgfx/vmwgfx_ttm_buffer.c | 44 ++++++++++++++++++++---------- 8 files changed, 117 insertions(+), 22 deletions(-) diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_blit.c b/drivers/gpu/drm/vmwgfx/vmwgfx_blit.c index c52c7bf1485b..717d624e9a05 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_blit.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_blit.c @@ -456,8 +456,10 @@ int vmw_bo_cpu_blit(struct ttm_buffer_object *dst, .no_wait_gpu = false }; u32 j, initial_line = dst_offset / dst_stride; - struct vmw_bo_blit_line_data d; + struct vmw_bo_blit_line_data d = {0}; int ret = 0; + struct page **dst_pages = NULL; + struct page **src_pages = NULL; /* Buffer objects need to be either pinned or reserved: */ if (!(dst->pin_count)) @@ -477,12 +479,35 @@ int vmw_bo_cpu_blit(struct ttm_buffer_object *dst, return ret; } + if (!src->ttm->pages && src->ttm->sg) { + src_pages = kvmalloc_array(src->ttm->num_pages, + sizeof(struct page *), GFP_KERNEL); + if (!src_pages) + return -ENOMEM; + ret = drm_prime_sg_to_page_array(src->ttm->sg, src_pages, + src->ttm->num_pages); + if (ret) + goto out; + } + if (!dst->ttm->pages && dst->ttm->sg) { + dst_pages = kvmalloc_array(dst->ttm->num_pages, + sizeof(struct page *), GFP_KERNEL); + if (!dst_pages) { + ret = -ENOMEM; + goto out; + } + ret = drm_prime_sg_to_page_array(dst->ttm->sg, dst_pages, + dst->ttm->num_pages); + if (ret) + goto out; + } + d.mapped_dst = 0; d.mapped_src = 0; d.dst_addr = NULL; d.src_addr = NULL; - d.dst_pages = dst->ttm->pages; - d.src_pages = src->ttm->pages; + d.dst_pages = dst->ttm->pages ? dst->ttm->pages : dst_pages; + d.src_pages = src->ttm->pages ? src->ttm->pages : src_pages; d.dst_num_pages = PFN_UP(dst->resource->size); d.src_num_pages = PFN_UP(src->resource->size); d.dst_prot = ttm_io_prot(dst, dst->resource, PAGE_KERNEL); @@ -504,6 +529,10 @@ out: kunmap_atomic(d.src_addr); if (d.dst_addr) kunmap_atomic(d.dst_addr); + if (src_pages) + kvfree(src_pages); + if (dst_pages) + kvfree(dst_pages); return ret; } diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_bo.c b/drivers/gpu/drm/vmwgfx/vmwgfx_bo.c index bfd41ce3c8f4..e5eb21a471a6 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_bo.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_bo.c @@ -377,7 +377,8 @@ static int vmw_bo_init(struct vmw_private *dev_priv, { struct ttm_operation_ctx ctx = { .interruptible = params->bo_type != ttm_bo_type_kernel, - .no_wait_gpu = false + .no_wait_gpu = false, + .resv = params->resv, }; struct ttm_device *bdev = &dev_priv->bdev; struct drm_device *vdev = &dev_priv->drm; @@ -394,8 +395,8 @@ static int vmw_bo_init(struct vmw_private *dev_priv, vmw_bo_placement_set(vmw_bo, params->domain, params->busy_domain); ret = ttm_bo_init_reserved(bdev, &vmw_bo->tbo, params->bo_type, - &vmw_bo->placement, 0, &ctx, NULL, - NULL, destroy); + &vmw_bo->placement, 0, &ctx, + params->sg, params->resv, destroy); if (unlikely(ret)) return ret; diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_bo.h b/drivers/gpu/drm/vmwgfx/vmwgfx_bo.h index 0d496dc9c6af..f349642e6190 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_bo.h +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_bo.h @@ -55,6 +55,8 @@ struct vmw_bo_params { enum ttm_bo_type bo_type; size_t size; bool pin; + struct dma_resv *resv; + struct sg_table *sg; }; /** diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c index 0a304706e013..58fb40c93100 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c @@ -1628,6 +1628,7 @@ static const struct drm_driver driver = { .prime_fd_to_handle = vmw_prime_fd_to_handle, .prime_handle_to_fd = vmw_prime_handle_to_fd, + .gem_prime_import_sg_table = vmw_prime_import_sg_table, .fops = &vmwgfx_driver_fops, .name = VMWGFX_DRIVER_NAME, diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h index 12efecc17df6..b019a1a1787a 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h @@ -1130,6 +1130,9 @@ extern int vmw_prime_handle_to_fd(struct drm_device *dev, struct drm_file *file_priv, uint32_t handle, uint32_t flags, int *prime_fd); +struct drm_gem_object *vmw_prime_import_sg_table(struct drm_device *dev, + struct dma_buf_attachment *attach, + struct sg_table *table); /* * MemoryOBject management - vmwgfx_mob.c diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_gem.c b/drivers/gpu/drm/vmwgfx/vmwgfx_gem.c index 12787bb9c111..d6bcaf078b1f 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_gem.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_gem.c @@ -149,6 +149,38 @@ out_no_bo: return ret; } +struct drm_gem_object *vmw_prime_import_sg_table(struct drm_device *dev, + struct dma_buf_attachment *attach, + struct sg_table *table) +{ + int ret; + struct vmw_private *dev_priv = vmw_priv(dev); + struct drm_gem_object *gem = NULL; + struct vmw_bo *vbo; + struct vmw_bo_params params = { + .domain = (dev_priv->has_mob) ? VMW_BO_DOMAIN_SYS : VMW_BO_DOMAIN_VRAM, + .busy_domain = VMW_BO_DOMAIN_SYS, + .bo_type = ttm_bo_type_sg, + .size = attach->dmabuf->size, + .pin = false, + .resv = attach->dmabuf->resv, + .sg = table, + + }; + + dma_resv_lock(params.resv, NULL); + + ret = vmw_bo_create(dev_priv, ¶ms, &vbo); + if (ret != 0) + goto out_no_bo; + + vbo->tbo.base.funcs = &vmw_gem_object_funcs; + + gem = &vbo->tbo.base; +out_no_bo: + dma_resv_unlock(params.resv); + return gem; +} int vmw_gem_object_create_ioctl(struct drm_device *dev, void *data, struct drm_file *filp) diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_prime.c b/drivers/gpu/drm/vmwgfx/vmwgfx_prime.c index 2d72a5ee7c0c..c99cad444991 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_prime.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_prime.c @@ -75,8 +75,12 @@ int vmw_prime_fd_to_handle(struct drm_device *dev, int fd, u32 *handle) { struct ttm_object_file *tfile = vmw_fpriv(file_priv)->tfile; + int ret = ttm_prime_fd_to_handle(tfile, fd, handle); - return ttm_prime_fd_to_handle(tfile, fd, handle); + if (ret) + ret = drm_gem_prime_fd_to_handle(dev, file_priv, fd, handle); + + return ret; } int vmw_prime_handle_to_fd(struct drm_device *dev, @@ -85,5 +89,12 @@ int vmw_prime_handle_to_fd(struct drm_device *dev, int *prime_fd) { struct ttm_object_file *tfile = vmw_fpriv(file_priv)->tfile; - return ttm_prime_handle_to_fd(tfile, handle, flags, prime_fd); + int ret; + + if (handle > VMWGFX_NUM_MOB) + ret = ttm_prime_handle_to_fd(tfile, handle, flags, prime_fd); + else + ret = drm_gem_prime_handle_to_fd(dev, file_priv, handle, flags, prime_fd); + + return ret; } diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_ttm_buffer.c b/drivers/gpu/drm/vmwgfx/vmwgfx_ttm_buffer.c index 4d23d0a70bcb..621d98b376bb 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_ttm_buffer.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_ttm_buffer.c @@ -188,13 +188,18 @@ static int vmw_ttm_map_dma(struct vmw_ttm_tt *vmw_tt) switch (dev_priv->map_mode) { case vmw_dma_map_bind: case vmw_dma_map_populate: - vsgt->sgt = &vmw_tt->sgt; - ret = sg_alloc_table_from_pages_segment( - &vmw_tt->sgt, vsgt->pages, vsgt->num_pages, 0, - (unsigned long)vsgt->num_pages << PAGE_SHIFT, - dma_get_max_seg_size(dev_priv->drm.dev), GFP_KERNEL); - if (ret) - goto out_sg_alloc_fail; + if (vmw_tt->dma_ttm.page_flags & TTM_TT_FLAG_EXTERNAL) { + vsgt->sgt = vmw_tt->dma_ttm.sg; + } else { + vsgt->sgt = &vmw_tt->sgt; + ret = sg_alloc_table_from_pages_segment(&vmw_tt->sgt, + vsgt->pages, vsgt->num_pages, 0, + (unsigned long)vsgt->num_pages << PAGE_SHIFT, + dma_get_max_seg_size(dev_priv->drm.dev), + GFP_KERNEL); + if (ret) + goto out_sg_alloc_fail; + } ret = vmw_ttm_map_for_dma(vmw_tt); if (unlikely(ret != 0)) @@ -209,8 +214,9 @@ static int vmw_ttm_map_dma(struct vmw_ttm_tt *vmw_tt) return 0; out_map_fail: - sg_free_table(vmw_tt->vsgt.sgt); - vmw_tt->vsgt.sgt = NULL; + drm_warn(&dev_priv->drm, "VSG table map failed!"); + sg_free_table(vsgt->sgt); + vsgt->sgt = NULL; out_sg_alloc_fail: return ret; } @@ -356,15 +362,17 @@ static void vmw_ttm_destroy(struct ttm_device *bdev, struct ttm_tt *ttm) static int vmw_ttm_populate(struct ttm_device *bdev, struct ttm_tt *ttm, struct ttm_operation_ctx *ctx) { - int ret; + bool external = (ttm->page_flags & TTM_TT_FLAG_EXTERNAL) != 0; - /* TODO: maybe completely drop this ? */ if (ttm_tt_is_populated(ttm)) return 0; - ret = ttm_pool_alloc(&bdev->pool, ttm, ctx); + if (external && ttm->sg) + return drm_prime_sg_to_dma_addr_array(ttm->sg, + ttm->dma_address, + ttm->num_pages); - return ret; + return ttm_pool_alloc(&bdev->pool, ttm, ctx); } static void vmw_ttm_unpopulate(struct ttm_device *bdev, @@ -372,6 +380,10 @@ static void vmw_ttm_unpopulate(struct ttm_device *bdev, { struct vmw_ttm_tt *vmw_tt = container_of(ttm, struct vmw_ttm_tt, dma_ttm); + bool external = (ttm->page_flags & TTM_TT_FLAG_EXTERNAL) != 0; + + if (external) + return; vmw_ttm_unbind(bdev, ttm); @@ -390,6 +402,7 @@ static struct ttm_tt *vmw_ttm_tt_create(struct ttm_buffer_object *bo, { struct vmw_ttm_tt *vmw_be; int ret; + bool external = bo->type == ttm_bo_type_sg; vmw_be = kzalloc(sizeof(*vmw_be), GFP_KERNEL); if (!vmw_be) @@ -398,7 +411,10 @@ static struct ttm_tt *vmw_ttm_tt_create(struct ttm_buffer_object *bo, vmw_be->dev_priv = vmw_priv_from_ttm(bo->bdev); vmw_be->mob = NULL; - if (vmw_be->dev_priv->map_mode == vmw_dma_alloc_coherent) + if (external) + page_flags |= TTM_TT_FLAG_EXTERNAL | TTM_TT_FLAG_EXTERNAL_MAPPABLE; + + if (vmw_be->dev_priv->map_mode == vmw_dma_alloc_coherent || external) ret = ttm_sg_tt_init(&vmw_be->dma_ttm, bo, page_flags, ttm_cached); else -- cgit v1.2.3 From a60ccade88f926e871a57176e86a34bbf0db0098 Mon Sep 17 00:00:00 2001 From: Zack Rusin Date: Thu, 11 Apr 2024 22:55:10 -0400 Subject: drm/vmwgfx: Fix crtc's atomic check conditional The conditional was supposed to prevent enabling of a crtc state without a set primary plane. Accidently it also prevented disabling crtc state with a set primary plane. Neither is correct. Fix the conditional and just driver-warn when a crtc state has been enabled without a primary plane which will help debug broken userspace. Fixes IGT's kms_atomic_interruptible and kms_atomic_transition tests. Signed-off-by: Zack Rusin Fixes: 06ec41909e31 ("drm/vmwgfx: Add and connect CRTC helper functions") Cc: Broadcom internal kernel review list Cc: dri-devel@lists.freedesktop.org Cc: # v4.12+ Reviewed-by: Ian Forbes Reviewed-by: Martin Krastev Link: https://patchwork.freedesktop.org/patch/msgid/20240412025511.78553-5-zack.rusin@broadcom.com --- drivers/gpu/drm/vmwgfx/vmwgfx_kms.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c index cd4925346ed4..84ae4e10a2eb 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c @@ -933,6 +933,7 @@ int vmw_du_cursor_plane_atomic_check(struct drm_plane *plane, int vmw_du_crtc_atomic_check(struct drm_crtc *crtc, struct drm_atomic_state *state) { + struct vmw_private *vmw = vmw_priv(crtc->dev); struct drm_crtc_state *new_state = drm_atomic_get_new_crtc_state(state, crtc); struct vmw_display_unit *du = vmw_crtc_to_du(new_state->crtc); @@ -940,9 +941,13 @@ int vmw_du_crtc_atomic_check(struct drm_crtc *crtc, bool has_primary = new_state->plane_mask & drm_plane_mask(crtc->primary); - /* We always want to have an active plane with an active CRTC */ - if (has_primary != new_state->enable) - return -EINVAL; + /* + * This is fine in general, but broken userspace might expect + * some actual rendering so give a clue as why it's blank. + */ + if (new_state->enable && !has_primary) + drm_dbg_driver(&vmw->drm, + "CRTC without a primary plane will be blank.\n"); if (new_state->connector_mask != connector_mask && -- cgit v1.2.3 From d4c972bff3129a9dd4c22a3999fd8eba1a81531a Mon Sep 17 00:00:00 2001 From: Zack Rusin Date: Thu, 11 Apr 2024 22:55:11 -0400 Subject: drm/vmwgfx: Sort primary plane formats by order of preference The table of primary plane formats wasn't sorted at all, leading to applications picking our least desirable formats by defaults. Sort the primary plane formats according to our order of preference. Nice side-effect of this change is that it makes IGT's kms_atomic plane-invalid-params pass because the test picks the first format which for vmwgfx was DRM_FORMAT_XRGB1555 and uses fb's with odd sizes which make Pixman, which IGT depends on assert due to the fact that our 16bpp formats aren't 32 bit aligned like Pixman requires all formats to be. Signed-off-by: Zack Rusin Fixes: 36cc79bc9077 ("drm/vmwgfx: Add universal plane support") Cc: Broadcom internal kernel review list Cc: dri-devel@lists.freedesktop.org Cc: # v4.12+ Acked-by: Pekka Paalanen Link: https://patchwork.freedesktop.org/patch/msgid/20240412025511.78553-6-zack.rusin@broadcom.com --- drivers/gpu/drm/vmwgfx/vmwgfx_kms.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.h b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.h index a94947b588e8..19a843da87b7 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.h +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.h @@ -243,10 +243,10 @@ struct vmw_framebuffer_bo { static const uint32_t __maybe_unused vmw_primary_plane_formats[] = { - DRM_FORMAT_XRGB1555, - DRM_FORMAT_RGB565, DRM_FORMAT_XRGB8888, DRM_FORMAT_ARGB8888, + DRM_FORMAT_RGB565, + DRM_FORMAT_XRGB1555, }; static const uint32_t __maybe_unused vmw_cursor_plane_formats[] = { -- cgit v1.2.3 From 015a12a4a6708d9cadcaea8334e270747923394c Mon Sep 17 00:00:00 2001 From: Anshuman Khandual Date: Mon, 15 Apr 2024 15:10:03 +0530 Subject: arm64/hugetlb: Fix page table walk in huge_pte_alloc() Currently normal HugeTLB fault ends up crashing the kernel, as p4dp derived from p4d_offset() is an invalid address when PGTABLE_LEVEL = 5. A p4d level entry needs to be allocated when not available while walking the page table during HugeTLB faults. Let's call p4d_alloc() to allocate such entries when required instead of current p4d_offset(). Unable to handle kernel paging request at virtual address ffffffff80000000 Mem abort info: ESR = 0x0000000096000005 EC = 0x25: DABT (current EL), IL = 32 bits SET = 0, FnV = 0 EA = 0, S1PTW = 0 FSC = 0x05: level 1 translation fault Data abort info: ISV = 0, ISS = 0x00000005, ISS2 = 0x00000000 CM = 0, WnR = 0, TnD = 0, TagAccess = 0 GCS = 0, Overlay = 0, DirtyBit = 0, Xs = 0 swapper pgtable: 4k pages, 52-bit VAs, pgdp=0000000081da9000 [ffffffff80000000] pgd=1000000082cec003, p4d=0000000082c32003, pud=0000000000000000 Internal error: Oops: 0000000096000005 [#1] PREEMPT SMP Modules linked in: CPU: 1 PID: 108 Comm: high_addr_hugep Not tainted 6.9.0-rc4 #48 Hardware name: Foundation-v8A (DT) pstate: 01402005 (nzcv daif +PAN -UAO -TCO +DIT -SSBS BTYPE=--) pc : huge_pte_alloc+0xd4/0x334 lr : hugetlb_fault+0x1b8/0xc68 sp : ffff8000833bbc20 x29: ffff8000833bbc20 x28: fff000080080cb58 x27: ffff800082a7cc58 x26: 0000000000000000 x25: fff0000800378e40 x24: fff00008008d6c60 x23: 00000000de9dbf07 x22: fff0000800378e40 x21: 0004000000000000 x20: 0004000000000000 x19: ffffffff80000000 x18: 1ffe00010011d7a1 x17: 0000000000000001 x16: ffffffffffffffff x15: 0000000000000001 x14: 0000000000000000 x13: ffff8000816120d0 x12: ffffffffffffffff x11: 0000000000000000 x10: fff00008008ebd0c x9 : 0004000000000000 x8 : 0000000000001255 x7 : fff00008003e2000 x6 : 00000000061d54b0 x5 : 0000000000001000 x4 : ffffffff80000000 x3 : 0000000000200000 x2 : 0000000000000004 x1 : 0000000080000000 x0 : 0000000000000000 Call trace: huge_pte_alloc+0xd4/0x334 hugetlb_fault+0x1b8/0xc68 handle_mm_fault+0x260/0x29c do_page_fault+0xfc/0x47c do_translation_fault+0x68/0x74 do_mem_abort+0x44/0x94 el0_da+0x2c/0x9c el0t_64_sync_handler+0x70/0xc4 el0t_64_sync+0x190/0x194 Code: aa000084 cb010084 b24c2c84 8b130c93 (f9400260) ---[ end trace 0000000000000000 ]--- Cc: Will Deacon Cc: Ard Biesheuvel Cc: Ryan Roberts Cc: Mark Rutland Cc: linux-arm-kernel@lists.infradead.org Cc: linux-kernel@vger.kernel.org Fixes: a6bbf5d4d9d1 ("arm64: mm: Add definitions to support 5 levels of paging") Reported-by: Dev Jain Acked-by: Ard Biesheuvel Acked-by: Mark Rutland Signed-off-by: Anshuman Khandual Reviewed-by: Ryan Roberts Link: https://lore.kernel.org/r/20240415094003.1812018-1-anshuman.khandual@arm.com Signed-off-by: Catalin Marinas --- arch/arm64/mm/hugetlbpage.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/arch/arm64/mm/hugetlbpage.c b/arch/arm64/mm/hugetlbpage.c index 0f0e10bb0a95..b872b003a55f 100644 --- a/arch/arm64/mm/hugetlbpage.c +++ b/arch/arm64/mm/hugetlbpage.c @@ -276,7 +276,10 @@ pte_t *huge_pte_alloc(struct mm_struct *mm, struct vm_area_struct *vma, pte_t *ptep = NULL; pgdp = pgd_offset(mm, addr); - p4dp = p4d_offset(pgdp, addr); + p4dp = p4d_alloc(mm, pgdp, addr); + if (!p4dp) + return NULL; + pudp = pud_alloc(mm, p4dp, addr); if (!pudp) return NULL; -- cgit v1.2.3 From 3078e059a5e984663c5c2b04485375c84c2700f9 Mon Sep 17 00:00:00 2001 From: Chao Yu Date: Fri, 12 Apr 2024 14:36:38 +0800 Subject: bcachefs: fix error path of __bch2_read_super() In __bch2_read_super(), if kstrdup() fails, it needs to release memory in sb->holder, fix to call bch2_free_super() in the error path. Signed-off-by: Chao Yu Reviewed-by: Hongbo Li Signed-off-by: Kent Overstreet --- fs/bcachefs/super-io.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/fs/bcachefs/super-io.c b/fs/bcachefs/super-io.c index e0aa3655b63b..648986a7dbde 100644 --- a/fs/bcachefs/super-io.c +++ b/fs/bcachefs/super-io.c @@ -700,8 +700,11 @@ retry: return -ENOMEM; sb->sb_name = kstrdup(path, GFP_KERNEL); - if (!sb->sb_name) - return -ENOMEM; + if (!sb->sb_name) { + ret = -ENOMEM; + prt_printf(&err, "error allocating memory for sb_name"); + goto err; + } #ifndef __KERNEL__ if (opt_get(*opts, direct_io) == false) -- cgit v1.2.3 From ad29cf999a9161e7849aa229d2028854f90728c2 Mon Sep 17 00:00:00 2001 From: Kent Overstreet Date: Sat, 13 Apr 2024 18:02:15 -0400 Subject: bcachefs: set_btree_iter_dontneed also clears should_be_locked This is part of a larger series cleaning up the semantics of should_be_locked and adding assertions around it; if we don't need an iterator/path anymore, it clearly doesn't need to be locked. Signed-off-by: Kent Overstreet --- fs/bcachefs/btree_iter.h | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/fs/bcachefs/btree_iter.h b/fs/bcachefs/btree_iter.h index 1d58d447b386..1c70836dd7cc 100644 --- a/fs/bcachefs/btree_iter.h +++ b/fs/bcachefs/btree_iter.h @@ -498,8 +498,13 @@ static inline void set_btree_iter_dontneed(struct btree_iter *iter) { struct btree_trans *trans = iter->trans; - if (!trans->restarted) - btree_iter_path(trans, iter)->preserve = false; + if (!iter->path || trans->restarted) + return; + + struct btree_path *path = btree_iter_path(trans, iter); + path->preserve = false; + if (path->ref == 1) + path->should_be_locked = false; } void *__bch2_trans_kmalloc(struct btree_trans *, size_t); -- cgit v1.2.3 From 35f4f8c9fc972248055096d63b782060e473311b Mon Sep 17 00:00:00 2001 From: Maíra Canal Date: Wed, 3 Apr 2024 17:24:50 -0300 Subject: drm/v3d: Don't increment `enabled_ns` twice MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The commit 509433d8146c ("drm/v3d: Expose the total GPU usage stats on sysfs") introduced the calculation of global GPU stats. For the regards, it used the already existing infrastructure provided by commit 09a93cc4f7d1 ("drm/v3d: Implement show_fdinfo() callback for GPU usage stats"). While adding global GPU stats calculation ability, the author forgot to delete the existing one. Currently, the value of `enabled_ns` is incremented twice by the end of the job, when it should be added just once. Therefore, delete the leftovers from commit 509433d8146c ("drm/v3d: Expose the total GPU usage stats on sysfs"). Fixes: 509433d8146c ("drm/v3d: Expose the total GPU usage stats on sysfs") Reported-by: Tvrtko Ursulin Signed-off-by: Maíra Canal Reviewed-by: Tvrtko Ursulin Reviewed-by: Jose Maria Casanova Crespo Link: https://patchwork.freedesktop.org/patch/msgid/20240403203517.731876-2-mcanal@igalia.com --- drivers/gpu/drm/v3d/v3d_irq.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/drivers/gpu/drm/v3d/v3d_irq.c b/drivers/gpu/drm/v3d/v3d_irq.c index 2e04f6cb661e..ce6b2fb341d1 100644 --- a/drivers/gpu/drm/v3d/v3d_irq.c +++ b/drivers/gpu/drm/v3d/v3d_irq.c @@ -105,7 +105,6 @@ v3d_irq(int irq, void *arg) struct v3d_file_priv *file = v3d->bin_job->base.file->driver_priv; u64 runtime = local_clock() - file->start_ns[V3D_BIN]; - file->enabled_ns[V3D_BIN] += local_clock() - file->start_ns[V3D_BIN]; file->jobs_sent[V3D_BIN]++; v3d->queue[V3D_BIN].jobs_sent++; @@ -126,7 +125,6 @@ v3d_irq(int irq, void *arg) struct v3d_file_priv *file = v3d->render_job->base.file->driver_priv; u64 runtime = local_clock() - file->start_ns[V3D_RENDER]; - file->enabled_ns[V3D_RENDER] += local_clock() - file->start_ns[V3D_RENDER]; file->jobs_sent[V3D_RENDER]++; v3d->queue[V3D_RENDER].jobs_sent++; @@ -147,7 +145,6 @@ v3d_irq(int irq, void *arg) struct v3d_file_priv *file = v3d->csd_job->base.file->driver_priv; u64 runtime = local_clock() - file->start_ns[V3D_CSD]; - file->enabled_ns[V3D_CSD] += local_clock() - file->start_ns[V3D_CSD]; file->jobs_sent[V3D_CSD]++; v3d->queue[V3D_CSD].jobs_sent++; @@ -195,7 +192,6 @@ v3d_hub_irq(int irq, void *arg) struct v3d_file_priv *file = v3d->tfu_job->base.file->driver_priv; u64 runtime = local_clock() - file->start_ns[V3D_TFU]; - file->enabled_ns[V3D_TFU] += local_clock() - file->start_ns[V3D_TFU]; file->jobs_sent[V3D_TFU]++; v3d->queue[V3D_TFU].jobs_sent++; -- cgit v1.2.3 From e048d668f2969cf2b76e0fa21882a1b3bb323eca Mon Sep 17 00:00:00 2001 From: Nathan Chancellor Date: Thu, 11 Apr 2024 11:11:06 -0700 Subject: configs/hardening: Fix disabling UBSAN configurations The initial change that added kernel/configs/hardening.config attempted to disable all UBSAN sanitizers except for the array bounds one while turning on UBSAN_TRAP. Unfortunately, it only got the syntax for CONFIG_UBSAN_SHIFT correct, so configurations that are on by default with CONFIG_UBSAN=y such as CONFIG_UBSAN_{BOOL,ENUM} do not get disabled properly. CONFIG_ARCH_HAS_UBSAN=y CONFIG_UBSAN=y CONFIG_UBSAN_TRAP=y CONFIG_CC_HAS_UBSAN_BOUNDS_STRICT=y CONFIG_UBSAN_BOUNDS=y CONFIG_UBSAN_BOUNDS_STRICT=y # CONFIG_UBSAN_SHIFT is not set # CONFIG_UBSAN_DIV_ZERO is not set # CONFIG_UBSAN_UNREACHABLE is not set CONFIG_UBSAN_SIGNED_WRAP=y CONFIG_UBSAN_BOOL=y CONFIG_UBSAN_ENUM=y # CONFIG_TEST_UBSAN is not set Add the missing 'is not set' to each configuration that needs it so that they get disabled as intended. CONFIG_ARCH_HAS_UBSAN=y CONFIG_UBSAN=y CONFIG_UBSAN_TRAP=y CONFIG_CC_HAS_UBSAN_BOUNDS_STRICT=y CONFIG_UBSAN_BOUNDS=y CONFIG_UBSAN_BOUNDS_STRICT=y # CONFIG_UBSAN_SHIFT is not set # CONFIG_UBSAN_DIV_ZERO is not set # CONFIG_UBSAN_UNREACHABLE is not set CONFIG_UBSAN_SIGNED_WRAP=y # CONFIG_UBSAN_BOOL is not set # CONFIG_UBSAN_ENUM is not set # CONFIG_TEST_UBSAN is not set Fixes: 215199e3d9f3 ("hardening: Provide Kconfig fragments for basic options") Signed-off-by: Nathan Chancellor Link: https://lore.kernel.org/r/20240411-fix-ubsan-in-hardening-config-v1-1-e0177c80ffaa@kernel.org Signed-off-by: Kees Cook --- kernel/configs/hardening.config | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/kernel/configs/hardening.config b/kernel/configs/hardening.config index 7a5bbfc024b7..d6f6dc45628a 100644 --- a/kernel/configs/hardening.config +++ b/kernel/configs/hardening.config @@ -39,11 +39,11 @@ CONFIG_UBSAN=y CONFIG_UBSAN_TRAP=y CONFIG_UBSAN_BOUNDS=y # CONFIG_UBSAN_SHIFT is not set -# CONFIG_UBSAN_DIV_ZERO -# CONFIG_UBSAN_UNREACHABLE -# CONFIG_UBSAN_BOOL -# CONFIG_UBSAN_ENUM -# CONFIG_UBSAN_ALIGNMENT +# CONFIG_UBSAN_DIV_ZERO is not set +# CONFIG_UBSAN_UNREACHABLE is not set +# CONFIG_UBSAN_BOOL is not set +# CONFIG_UBSAN_ENUM is not set +# CONFIG_UBSAN_ALIGNMENT is not set # Sampling-based heap out-of-bounds and use-after-free detection. CONFIG_KFENCE=y -- cgit v1.2.3 From 7fcb91d94e897413c0345bb32ea11293f33efbb1 Mon Sep 17 00:00:00 2001 From: Nathan Chancellor Date: Thu, 11 Apr 2024 11:11:07 -0700 Subject: configs/hardening: Disable CONFIG_UBSAN_SIGNED_WRAP kernel/configs/hardening.config turns on UBSAN for the bounds sanitizer, as that in combination with trapping can stop the exploitation of buffer overflows within the kernel. At the same time, hardening.config turns off every other UBSAN sanitizer because trapping means all UBSAN reports will be fatal and the problems brought up by other sanitizers generally do not have security implications. The signed integer overflow sanitizer was recently added back to the kernel and it is default on with just CONFIG_UBSAN=y, meaning that it gets enabled when merging hardening.config into another configuration. While this sanitizer does have security implications like the array bounds sanitizer, work to clean up enough instances to allow this to run in production environments is still ramping up, which means regular users and testers may be broken by these instances with CONFIG_UBSAN_TRAP=y. Disable CONFIG_UBSAN_SIGNED_WRAP in hardening.config to avoid this situation. Fixes: 557f8c582a9b ("ubsan: Reintroduce signed overflow sanitizer") Signed-off-by: Nathan Chancellor Link: https://lore.kernel.org/r/20240411-fix-ubsan-in-hardening-config-v1-2-e0177c80ffaa@kernel.org Signed-off-by: Kees Cook --- kernel/configs/hardening.config | 1 + 1 file changed, 1 insertion(+) diff --git a/kernel/configs/hardening.config b/kernel/configs/hardening.config index d6f6dc45628a..4b4cfcba3190 100644 --- a/kernel/configs/hardening.config +++ b/kernel/configs/hardening.config @@ -41,6 +41,7 @@ CONFIG_UBSAN_BOUNDS=y # CONFIG_UBSAN_SHIFT is not set # CONFIG_UBSAN_DIV_ZERO is not set # CONFIG_UBSAN_UNREACHABLE is not set +# CONFIG_UBSAN_SIGNED_WRAP is not set # CONFIG_UBSAN_BOOL is not set # CONFIG_UBSAN_ENUM is not set # CONFIG_UBSAN_ALIGNMENT is not set -- cgit v1.2.3 From ee7e980dc7c9f22c142807c5f582a6524138f57a Mon Sep 17 00:00:00 2001 From: Lyude Paul Date: Thu, 4 Apr 2024 19:35:53 -0400 Subject: drm/nouveau/kms/nv50-: Disable AUX bus for disconnected DP ports GSP has its own state for keeping track of whether or not a given display connector is plugged in or not, and enforces this state on the driver. In particular, AUX transactions on a DisplayPort connector which GSP says is disconnected can never succeed - and can in some cases even cause unexpected timeouts, which can trickle up to cause other problems. A good example of this is runtime power management: where we can actually get stuck trying to resume the GPU if a userspace application like fwupd tries accessing a drm_aux_dev for a disconnected port. This was an issue I hit a few times with my Slimbook Executive 16 - where trying to offload something to the discrete GPU would wake it up, and then potentially cause it to timeout as fwupd tried to immediately access the dp_aux_dev nodes for nouveau. Likewise: we don't really have any cases I know of where we'd want to ignore this state and try an aux transaction anyway - and failing pointless aux transactions immediately can even speed things up. So - let's start enabling/disabling the aux bus in nouveau_dp_detect() to fix this. We enable the aux bus during connector probing, and leave it enabled if we discover something is actually on the connector. Otherwise, we just shut it off. This should fix some people's runtime PM issues (like myself), and also get rid of quite of a lot of GSP error spam in dmesg. Signed-off-by: Lyude Paul Reviewed-by: Dave Airlie Link: https://patchwork.freedesktop.org/patch/msgid/20240404233736.7946-2-lyude@redhat.com (cherry picked from commit 9c8a10bf1f3467b2c16f6848249bdc7692ace825) --- drivers/gpu/drm/nouveau/nouveau_dp.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/drivers/gpu/drm/nouveau/nouveau_dp.c b/drivers/gpu/drm/nouveau/nouveau_dp.c index 7de7707ec6a8..3f6ccce20ea0 100644 --- a/drivers/gpu/drm/nouveau/nouveau_dp.c +++ b/drivers/gpu/drm/nouveau/nouveau_dp.c @@ -232,6 +232,9 @@ nouveau_dp_detect(struct nouveau_connector *nv_connector, dpcd[DP_DPCD_REV] != 0) return NOUVEAU_DP_SST; + // Ensure that the aux bus is enabled for probing + drm_dp_dpcd_set_powered(&nv_connector->aux, true); + mutex_lock(&nv_encoder->dp.hpd_irq_lock); if (mstm) { /* If we're not ready to handle MST state changes yet, just @@ -293,6 +296,13 @@ out: if (mstm && !mstm->suspended && ret != NOUVEAU_DP_MST) nv50_mstm_remove(mstm); + /* GSP doesn't like when we try to do aux transactions on a port it considers disconnected, + * and since we don't really have a usecase for that anyway - just disable the aux bus here + * if we've decided the connector is disconnected + */ + if (ret == NOUVEAU_DP_NONE) + drm_dp_dpcd_set_powered(&nv_connector->aux, false); + mutex_unlock(&nv_encoder->dp.hpd_irq_lock); return ret; } -- cgit v1.2.3 From bf52d7f9b2067f02efe7e32697479097aba4a055 Mon Sep 17 00:00:00 2001 From: Lyude Paul Date: Thu, 4 Apr 2024 19:35:54 -0400 Subject: drm/nouveau/dp: Don't probe eDP ports twice harder I didn't pay close enough attention the last time I tried to fix this problem - while we currently do correctly take care to make sure we don't probe a connected eDP port more then once, we don't do the same thing for eDP ports we found to be disconnected. So, fix this and make sure we only ever probe eDP ports once and then leave them at that connector state forever (since without HPD, it's not going to change on its own anyway). This should get rid of the last few GSP errors getting spit out during runtime suspend and resume on some machines, as we tried to reprobe eDP ports in response to ACPI hotplug probe events. Signed-off-by: Lyude Paul Reviewed-by: Dave Airlie Link: https://patchwork.freedesktop.org/patch/msgid/20240404233736.7946-3-lyude@redhat.com (cherry picked from commit fe6660b661c3397af0867d5d098f5b26581f1290) --- drivers/gpu/drm/nouveau/nouveau_dp.c | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/nouveau/nouveau_dp.c b/drivers/gpu/drm/nouveau/nouveau_dp.c index 3f6ccce20ea0..a72c45809484 100644 --- a/drivers/gpu/drm/nouveau/nouveau_dp.c +++ b/drivers/gpu/drm/nouveau/nouveau_dp.c @@ -225,12 +225,15 @@ nouveau_dp_detect(struct nouveau_connector *nv_connector, u8 *dpcd = nv_encoder->dp.dpcd; int ret = NOUVEAU_DP_NONE, hpd; - /* If we've already read the DPCD on an eDP device, we don't need to - * reread it as it won't change + /* eDP ports don't support hotplugging - so there's no point in probing eDP ports unless we + * haven't probed them once before. */ - if (connector->connector_type == DRM_MODE_CONNECTOR_eDP && - dpcd[DP_DPCD_REV] != 0) - return NOUVEAU_DP_SST; + if (connector->connector_type == DRM_MODE_CONNECTOR_eDP) { + if (connector->status == connector_status_connected) + return NOUVEAU_DP_SST; + else if (connector->status == connector_status_disconnected) + return NOUVEAU_DP_NONE; + } // Ensure that the aux bus is enabled for probing drm_dp_dpcd_set_powered(&nv_connector->aux, true); -- cgit v1.2.3 From 51f67862ea6ea83f9fa4cda2e59d7bfd4387f63b Mon Sep 17 00:00:00 2001 From: Shengjiu Wang Date: Mon, 15 Apr 2024 15:17:35 +0800 Subject: ASoC: fsl-asoc-card: add wm8904 codec support wm8904 codec is used on i.MX95 Toradex board Signed-off-by: Shengjiu Wang Link: https://lore.kernel.org/r/1713165456-3494-2-git-send-email-shengjiu.wang@nxp.com Signed-off-by: Mark Brown --- sound/soc/fsl/fsl-asoc-card.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/sound/soc/fsl/fsl-asoc-card.c b/sound/soc/fsl/fsl-asoc-card.c index bc07f26ba303..f6d2564864c6 100644 --- a/sound/soc/fsl/fsl-asoc-card.c +++ b/sound/soc/fsl/fsl-asoc-card.c @@ -28,6 +28,7 @@ #include "../codecs/wm8994.h" #include "../codecs/tlv320aic31xx.h" #include "../codecs/nau8822.h" +#include "../codecs/wm8904.h" #define DRIVER_NAME "fsl-asoc-card" @@ -709,6 +710,12 @@ static int fsl_asoc_card_probe(struct platform_device *pdev) priv->dai_fmt |= SND_SOC_DAIFMT_CBM_CFM; if (codec_dev) priv->codec_priv.mclk = devm_clk_get(codec_dev, NULL); + } else if (of_device_is_compatible(np, "fsl,imx-audio-wm8904")) { + codec_dai_name = "wm8904-hifi"; + priv->codec_priv.mclk_id = WM8904_FLL_MCLK; + priv->codec_priv.fll_id = WM8904_CLK_FLL; + priv->codec_priv.pll_id = WM8904_FLL_MCLK; + priv->dai_fmt |= SND_SOC_DAIFMT_CBP_CFP; } else { dev_err(&pdev->dev, "unknown Device Tree compatible\n"); ret = -EINVAL; @@ -935,6 +942,7 @@ static const struct of_device_id fsl_asoc_card_dt_ids[] = { { .compatible = "fsl,imx-audio-si476x", }, { .compatible = "fsl,imx-audio-wm8958", }, { .compatible = "fsl,imx-audio-nau8822", }, + { .compatible = "fsl,imx-audio-wm8904", }, {} }; MODULE_DEVICE_TABLE(of, fsl_asoc_card_dt_ids); -- cgit v1.2.3 From 62c48dd33b4f2e037554d1322ae4f9f60e9461ef Mon Sep 17 00:00:00 2001 From: Shengjiu Wang Date: Mon, 15 Apr 2024 15:17:36 +0800 Subject: ASoC: dt-bindings: fsl-asoc-card: Add compatbile string for wm8904 codec The wm8904 codec is used on an i.MX95 Toradex board. Signed-off-by: Shengjiu Wang Link: https://lore.kernel.org/r/1713165456-3494-3-git-send-email-shengjiu.wang@nxp.com Signed-off-by: Mark Brown --- Documentation/devicetree/bindings/sound/fsl-asoc-card.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/Documentation/devicetree/bindings/sound/fsl-asoc-card.yaml b/Documentation/devicetree/bindings/sound/fsl-asoc-card.yaml index bbf6fa1a2012..9922664d5ccc 100644 --- a/Documentation/devicetree/bindings/sound/fsl-asoc-card.yaml +++ b/Documentation/devicetree/bindings/sound/fsl-asoc-card.yaml @@ -77,6 +77,7 @@ properties: - fsl,imx-audio-tlv320aic31xx - fsl,imx-audio-tlv320aic32x4 - fsl,imx-audio-wm8524 + - fsl,imx-audio-wm8904 - fsl,imx-audio-wm8960 - fsl,imx-audio-wm8962 - fsl,imx-audio-wm8958 -- cgit v1.2.3 From f4626c12e4b538f757a73d08f4d86d564175b4f7 Mon Sep 17 00:00:00 2001 From: Kees Cook Date: Mon, 15 Apr 2024 11:28:35 -0700 Subject: ubsan: Add awareness of signed integer overflow traps On arm64, UBSAN traps can be decoded from the trap instruction. Add the add, sub, and mul overflow trap codes now that CONFIG_UBSAN_SIGNED_WRAP exists. Seen under clang 19: Internal error: UBSAN: unrecognized failure code: 00000000f2005515 [#1] PREEMPT SMP Reported-by: Nathan Chancellor Closes: https://lore.kernel.org/lkml/20240411-fix-ubsan-in-hardening-config-v1-0-e0177c80ffaa@kernel.org Fixes: 557f8c582a9b ("ubsan: Reintroduce signed overflow sanitizer") Tested-by: Nathan Chancellor Link: https://lore.kernel.org/r/20240415182832.work.932-kees@kernel.org Signed-off-by: Kees Cook --- lib/ubsan.c | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/lib/ubsan.c b/lib/ubsan.c index 5fc107f61934..a1c983d148f1 100644 --- a/lib/ubsan.c +++ b/lib/ubsan.c @@ -44,9 +44,10 @@ const char *report_ubsan_failure(struct pt_regs *regs, u32 check_type) case ubsan_shift_out_of_bounds: return "UBSAN: shift out of bounds"; #endif -#ifdef CONFIG_UBSAN_DIV_ZERO +#if defined(CONFIG_UBSAN_DIV_ZERO) || defined(CONFIG_UBSAN_SIGNED_WRAP) /* - * SanitizerKind::IntegerDivideByZero emits + * SanitizerKind::IntegerDivideByZero and + * SanitizerKind::SignedIntegerOverflow emit * SanitizerHandler::DivremOverflow. */ case ubsan_divrem_overflow: @@ -77,6 +78,19 @@ const char *report_ubsan_failure(struct pt_regs *regs, u32 check_type) return "UBSAN: alignment assumption"; case ubsan_type_mismatch: return "UBSAN: type mismatch"; +#endif +#ifdef CONFIG_UBSAN_SIGNED_WRAP + /* + * SanitizerKind::SignedIntegerOverflow emits + * SanitizerHandler::AddOverflow, SanitizerHandler::SubOverflow, + * or SanitizerHandler::MulOverflow. + */ + case ubsan_add_overflow: + return "UBSAN: integer addition overflow"; + case ubsan_sub_overflow: + return "UBSAN: integer subtraction overflow"; + case ubsan_mul_overflow: + return "UBSAN: integer multiplication overflow"; #endif default: return "UBSAN: unrecognized failure code"; -- cgit v1.2.3 From bce93a162505f0bc0499888ace2f66bd56fb94b3 Mon Sep 17 00:00:00 2001 From: AngeloGioacchino Del Regno Date: Tue, 16 Apr 2024 09:13:53 +0200 Subject: ASoC: mediatek: Add common machine soundcard driver probe mechanism Add a common machine soundcard driver probe function that supports both DSP and AFE-direct usecases and also provides a hook for legacy machine soundcard driver probe mechanisms. Note that the hook is there because, even for legacy probe, a lot of the actual code can still be commonized, hence still reducing duplication for the legacy devicetree retrocompatibility cases. This common probe function deprecates all of the inconsistent previous probe mechanisms and aims to settle all of the MediaTek card drivers on consistent and common devicetree properties describing wanted DAIs, device specific DAI configuration and DAI links to codecs found on each device/board. Reviewed-by: Alexandre Mergnat Signed-off-by: AngeloGioacchino Del Regno Link: https://lore.kernel.org/r/20240416071410.75620-2-angelogioacchino.delregno@collabora.com Signed-off-by: Mark Brown --- sound/soc/mediatek/common/mtk-soc-card.h | 7 +- sound/soc/mediatek/common/mtk-soundcard-driver.c | 148 +++++++++++++++++++++++ sound/soc/mediatek/common/mtk-soundcard-driver.h | 18 +++ 3 files changed, 172 insertions(+), 1 deletion(-) diff --git a/sound/soc/mediatek/common/mtk-soc-card.h b/sound/soc/mediatek/common/mtk-soc-card.h index eeda79370049..d92dc36d4577 100644 --- a/sound/soc/mediatek/common/mtk-soc-card.h +++ b/sound/soc/mediatek/common/mtk-soc-card.h @@ -9,9 +9,14 @@ #ifndef _MTK_SOC_CARD_H_ #define _MTK_SOC_CARD_H_ +struct mtk_platform_card_data; +struct mtk_sof_priv; + struct mtk_soc_card_data { + struct mtk_sof_priv *sof_priv; + struct list_head sof_dai_link_list; + struct mtk_platform_card_data *card_data; void *mach_priv; - void *sof_priv; }; #endif diff --git a/sound/soc/mediatek/common/mtk-soundcard-driver.c b/sound/soc/mediatek/common/mtk-soundcard-driver.c index 000a086a8cf4..b1db17e392d5 100644 --- a/sound/soc/mediatek/common/mtk-soundcard-driver.c +++ b/sound/soc/mediatek/common/mtk-soundcard-driver.c @@ -10,6 +10,8 @@ #include #include +#include "mtk-dsp-sof-common.h" +#include "mtk-soc-card.h" #include "mtk-soundcard-driver.h" static int set_card_codec_info(struct snd_soc_card *card, @@ -136,3 +138,149 @@ void clean_card_reference(struct snd_soc_card *card) snd_soc_of_put_dai_link_codecs(dai_link); } EXPORT_SYMBOL_GPL(clean_card_reference); + +int mtk_soundcard_common_probe(struct platform_device *pdev) +{ + struct device_node *platform_node, *adsp_node; + const struct mtk_soundcard_pdata *pdata; + struct mtk_soc_card_data *soc_card_data; + struct snd_soc_dai_link *orig_dai_link, *dai_link; + struct snd_soc_jack *jacks; + struct snd_soc_card *card; + int i, orig_num_links, ret; + bool needs_legacy_probe; + + pdata = device_get_match_data(&pdev->dev); + if (!pdata) + return -EINVAL; + + card = pdata->card_data->card; + card->dev = &pdev->dev; + orig_dai_link = card->dai_link; + orig_num_links = card->num_links; + + ret = snd_soc_of_parse_card_name(card, "model"); + if (ret) + return ret; + + if (!card->name) { + if (!pdata->card_name) + return -EINVAL; + + card->name = pdata->card_name; + } + + needs_legacy_probe = !of_property_read_bool(pdev->dev.of_node, "audio-routing"); + if (needs_legacy_probe) { + /* + * If we have no .soc_probe() callback there's no way of using + * any legacy probe mechanism, as that cannot not be generic. + */ + if (!pdata->soc_probe) + return -EINVAL; + + dev_info_once(&pdev->dev, "audio-routing not found: using legacy probe\n"); + } else { + ret = snd_soc_of_parse_audio_routing(card, "audio-routing"); + if (ret) + return ret; + } + + soc_card_data = devm_kzalloc(&pdev->dev, sizeof(*soc_card_data), GFP_KERNEL); + if (!soc_card_data) + return -ENOMEM; + + soc_card_data->card_data = pdata->card_data; + + jacks = devm_kcalloc(card->dev, soc_card_data->card_data->num_jacks, + sizeof(*jacks), GFP_KERNEL); + if (!jacks) + return -ENOMEM; + + soc_card_data->card_data->jacks = jacks; + + platform_node = of_parse_phandle(pdev->dev.of_node, "mediatek,platform", 0); + if (!platform_node) + return dev_err_probe(&pdev->dev, -EINVAL, + "Property mediatek,platform missing or invalid\n"); + + /* Check if this SoC has an Audio DSP */ + if (pdata->sof_priv) + adsp_node = of_parse_phandle(pdev->dev.of_node, "mediatek,adsp", 0); + else + adsp_node = NULL; + + if (adsp_node) { + if (of_property_read_bool(pdev->dev.of_node, "mediatek,dai-link")) { + ret = mtk_sof_dailink_parse_of(card, pdev->dev.of_node, + "mediatek,dai-link", + card->dai_link, card->num_links); + if (ret) { + of_node_put(adsp_node); + of_node_put(platform_node); + return dev_err_probe(&pdev->dev, ret, + "Cannot parse mediatek,dai-link\n"); + } + } + + soc_card_data->sof_priv = pdata->sof_priv; + card->probe = mtk_sof_card_probe; + card->late_probe = mtk_sof_card_late_probe; + if (!card->topology_shortname_created) { + snprintf(card->topology_shortname, 32, "sof-%s", card->name); + card->topology_shortname_created = true; + } + card->name = card->topology_shortname; + } + + /* + * Regardless of whether the ADSP is wanted and/or present in a machine + * specific device tree or not and regardless of whether any AFE_SOF + * link is present, we have to make sure that the platforms->of_node + * is not NULL, and set to either ADSP (adsp_node) or AFE (platform_node). + */ + for_each_card_prelinks(card, i, dai_link) { + if (adsp_node && !strncmp(dai_link->name, "AFE_SOF", strlen("AFE_SOF"))) + dai_link->platforms->of_node = adsp_node; + else if (!dai_link->platforms->name && !dai_link->platforms->of_node) + dai_link->platforms->of_node = platform_node; + } + + if (!needs_legacy_probe) { + ret = parse_dai_link_info(card); + if (ret) + goto err_restore_dais; + } else { + if (adsp_node) + of_node_put(adsp_node); + of_node_put(platform_node); + } + + if (pdata->soc_probe) { + ret = pdata->soc_probe(soc_card_data, needs_legacy_probe); + if (ret) { + if (!needs_legacy_probe) + clean_card_reference(card); + goto err_restore_dais; + } + } + snd_soc_card_set_drvdata(card, soc_card_data); + + ret = devm_snd_soc_register_card(&pdev->dev, card); + + if (!needs_legacy_probe) + clean_card_reference(card); + + if (ret) { + dev_err_probe(&pdev->dev, ret, "Cannot register card\n"); + goto err_restore_dais; + } + + return 0; + +err_restore_dais: + card->dai_link = orig_dai_link; + card->num_links = orig_num_links; + return ret; +} +EXPORT_SYMBOL_GPL(mtk_soundcard_common_probe); diff --git a/sound/soc/mediatek/common/mtk-soundcard-driver.h b/sound/soc/mediatek/common/mtk-soundcard-driver.h index d92cac1d7b72..44320efff5f8 100644 --- a/sound/soc/mediatek/common/mtk-soundcard-driver.h +++ b/sound/soc/mediatek/common/mtk-soundcard-driver.h @@ -9,6 +9,24 @@ #ifndef _MTK_SOUNDCARD_DRIVER_H_ #define _MTK_SOUNDCARD_DRIVER_H_ +struct mtk_sof_priv; +struct mtk_soc_card_data; + +struct mtk_platform_card_data { + struct snd_soc_card *card; + struct snd_soc_jack *jacks; + u8 num_jacks; + u8 flags; +}; + +struct mtk_soundcard_pdata { + const char *card_name; + struct mtk_platform_card_data *card_data; + struct mtk_sof_priv *sof_priv; + int (*soc_probe)(struct mtk_soc_card_data *card_data, bool legacy); +}; + int parse_dai_link_info(struct snd_soc_card *card); void clean_card_reference(struct snd_soc_card *card); +int mtk_soundcard_common_probe(struct platform_device *pdev); #endif -- cgit v1.2.3 From f8782f776db33066a9b1cd14d319142c4175561f Mon Sep 17 00:00:00 2001 From: AngeloGioacchino Del Regno Date: Tue, 16 Apr 2024 09:13:54 +0200 Subject: ASoC: mediatek: common: Constify struct mtk_sof_priv Apart from a dai_link_list variable, the mtk_sof_priv currently holds data that never gets modified during runtime. Constify the mtk_sof_priv structure and move the SOF dai_link_list as sof_dai_link_list in struct mtk_soc_card_data, which is a structure that already holds the card's machine specific, runtime modified data. This allows to safely pass the mtk_sof_priv structure as platform data for the commonized card probe mechanism. Reviewed-by: Alexandre Mergnat Signed-off-by: AngeloGioacchino Del Regno Link: https://lore.kernel.org/r/20240416071410.75620-3-angelogioacchino.delregno@collabora.com Signed-off-by: Mark Brown --- sound/soc/mediatek/common/mtk-dsp-sof-common.c | 15 +++++++-------- sound/soc/mediatek/common/mtk-dsp-sof-common.h | 1 - sound/soc/mediatek/common/mtk-soc-card.h | 2 +- sound/soc/mediatek/common/mtk-soundcard-driver.h | 2 +- 4 files changed, 9 insertions(+), 11 deletions(-) diff --git a/sound/soc/mediatek/common/mtk-dsp-sof-common.c b/sound/soc/mediatek/common/mtk-dsp-sof-common.c index 7ec8965a70c0..bca758dca2c9 100644 --- a/sound/soc/mediatek/common/mtk-dsp-sof-common.c +++ b/sound/soc/mediatek/common/mtk-dsp-sof-common.c @@ -15,7 +15,7 @@ int mtk_sof_dai_link_fixup(struct snd_soc_pcm_runtime *rtd, { struct snd_soc_card *card = rtd->card; struct mtk_soc_card_data *soc_card_data = snd_soc_card_get_drvdata(card); - struct mtk_sof_priv *sof_priv = soc_card_data->sof_priv; + const struct mtk_sof_priv *sof_priv = soc_card_data->sof_priv; int i, j, ret = 0; for (i = 0; i < sof_priv->num_streams; i++) { @@ -55,7 +55,6 @@ int mtk_sof_card_probe(struct snd_soc_card *card) int i; struct snd_soc_dai_link *dai_link; struct mtk_soc_card_data *soc_card_data = snd_soc_card_get_drvdata(card); - struct mtk_sof_priv *sof_priv = soc_card_data->sof_priv; /* Set stream_name to help sof bind widgets */ for_each_card_prelinks(card, i, dai_link) { @@ -63,7 +62,7 @@ int mtk_sof_card_probe(struct snd_soc_card *card) dai_link->stream_name = dai_link->name; } - INIT_LIST_HEAD(&sof_priv->dai_link_list); + INIT_LIST_HEAD(&soc_card_data->sof_dai_link_list); return 0; } @@ -73,7 +72,7 @@ static struct snd_soc_pcm_runtime *mtk_sof_find_tplg_be(struct snd_soc_pcm_runti { struct snd_soc_card *card = rtd->card; struct mtk_soc_card_data *soc_card_data = snd_soc_card_get_drvdata(card); - struct mtk_sof_priv *sof_priv = soc_card_data->sof_priv; + const struct mtk_sof_priv *sof_priv = soc_card_data->sof_priv; struct snd_soc_pcm_runtime *fe; struct snd_soc_pcm_runtime *be; struct snd_soc_dpcm *dpcm; @@ -113,7 +112,7 @@ static int mtk_sof_check_tplg_be_dai_link_fixup(struct snd_soc_pcm_runtime *rtd, { struct snd_soc_card *card = rtd->card; struct mtk_soc_card_data *soc_card_data = snd_soc_card_get_drvdata(card); - struct mtk_sof_priv *sof_priv = soc_card_data->sof_priv; + const struct mtk_sof_priv *sof_priv = soc_card_data->sof_priv; struct snd_soc_pcm_runtime *sof_be; struct mtk_dai_link *dai_link; int ret = 0; @@ -125,7 +124,7 @@ static int mtk_sof_check_tplg_be_dai_link_fixup(struct snd_soc_pcm_runtime *rtd, else if (sof_be->dai_link->be_hw_params_fixup) ret = sof_be->dai_link->be_hw_params_fixup(sof_be, params); } else { - list_for_each_entry(dai_link, &sof_priv->dai_link_list, list) { + list_for_each_entry(dai_link, &soc_card_data->sof_dai_link_list, list) { if (strcmp(dai_link->name, rtd->dai_link->name) == 0) { if (dai_link->be_hw_params_fixup) ret = dai_link->be_hw_params_fixup(rtd, params); @@ -144,7 +143,7 @@ int mtk_sof_card_late_probe(struct snd_soc_card *card) struct snd_soc_component *sof_comp = NULL; struct mtk_soc_card_data *soc_card_data = snd_soc_card_get_drvdata(card); - struct mtk_sof_priv *sof_priv = soc_card_data->sof_priv; + const struct mtk_sof_priv *sof_priv = soc_card_data->sof_priv; struct snd_soc_dai_link *dai_link; struct mtk_dai_link *mtk_dai_link; int i; @@ -173,7 +172,7 @@ int mtk_sof_card_late_probe(struct snd_soc_card *card) mtk_dai_link->be_hw_params_fixup = dai_link->be_hw_params_fixup; mtk_dai_link->name = dai_link->name; - list_add(&mtk_dai_link->list, &sof_priv->dai_link_list); + list_add(&mtk_dai_link->list, &soc_card_data->sof_dai_link_list); } if (dai_link->no_pcm) diff --git a/sound/soc/mediatek/common/mtk-dsp-sof-common.h b/sound/soc/mediatek/common/mtk-dsp-sof-common.h index 4bc5e1c0c8ed..8784ee471132 100644 --- a/sound/soc/mediatek/common/mtk-dsp-sof-common.h +++ b/sound/soc/mediatek/common/mtk-dsp-sof-common.h @@ -30,7 +30,6 @@ struct mtk_sof_priv { int num_streams; int (*sof_dai_link_fixup)(struct snd_soc_pcm_runtime *rtd, struct snd_pcm_hw_params *params); - struct list_head dai_link_list; }; int mtk_sof_dai_link_fixup(struct snd_soc_pcm_runtime *rtd, diff --git a/sound/soc/mediatek/common/mtk-soc-card.h b/sound/soc/mediatek/common/mtk-soc-card.h index d92dc36d4577..3f6e24dd22df 100644 --- a/sound/soc/mediatek/common/mtk-soc-card.h +++ b/sound/soc/mediatek/common/mtk-soc-card.h @@ -13,7 +13,7 @@ struct mtk_platform_card_data; struct mtk_sof_priv; struct mtk_soc_card_data { - struct mtk_sof_priv *sof_priv; + const struct mtk_sof_priv *sof_priv; struct list_head sof_dai_link_list; struct mtk_platform_card_data *card_data; void *mach_priv; diff --git a/sound/soc/mediatek/common/mtk-soundcard-driver.h b/sound/soc/mediatek/common/mtk-soundcard-driver.h index 44320efff5f8..4fd2ffb7e486 100644 --- a/sound/soc/mediatek/common/mtk-soundcard-driver.h +++ b/sound/soc/mediatek/common/mtk-soundcard-driver.h @@ -22,7 +22,7 @@ struct mtk_platform_card_data { struct mtk_soundcard_pdata { const char *card_name; struct mtk_platform_card_data *card_data; - struct mtk_sof_priv *sof_priv; + const struct mtk_sof_priv *sof_priv; int (*soc_probe)(struct mtk_soc_card_data *card_data, bool legacy); }; -- cgit v1.2.3 From aad45b8aa973a863dee2f256cea8c527acaaf56e Mon Sep 17 00:00:00 2001 From: AngeloGioacchino Del Regno Date: Tue, 16 Apr 2024 09:13:55 +0200 Subject: ASoC: mediatek: mt8188: Migrate to mtk_soundcard_common_probe Add mtk_soundcard_pdata platform data for the MediaTek common sound card probe mechanism, including a driver/soc-specific probe extension (used for bits that cannot be commonized hence specific to this driver), and change the probe function to mtk_soundcard_common_probe. Reviewed-by: Alexandre Mergnat Signed-off-by: AngeloGioacchino Del Regno Link: https://lore.kernel.org/r/20240416071410.75620-4-angelogioacchino.delregno@collabora.com Signed-off-by: Mark Brown --- sound/soc/mediatek/mt8188/mt8188-mt6359.c | 203 ++++++++++-------------------- 1 file changed, 64 insertions(+), 139 deletions(-) diff --git a/sound/soc/mediatek/mt8188/mt8188-mt6359.c b/sound/soc/mediatek/mt8188/mt8188-mt6359.c index a391066ab204..f629fc6bbb53 100644 --- a/sound/soc/mediatek/mt8188/mt8188-mt6359.c +++ b/sound/soc/mediatek/mt8188/mt8188-mt6359.c @@ -236,11 +236,11 @@ static const struct sof_conn_stream g_sof_conn_streams[] = { }, }; -struct mt8188_mt6359_priv { - struct snd_soc_jack dp_jack; - struct snd_soc_jack hdmi_jack; - struct snd_soc_jack headset_jack; - void *private_data; +enum mt8188_jacks { + MT8188_JACK_HEADSET, + MT8188_JACK_DP, + MT8188_JACK_HDMI, + MT8188_JACK_MAX, }; static struct snd_soc_jack_pin mt8188_hdmi_jack_pins[] = { @@ -268,11 +268,6 @@ static struct snd_soc_jack_pin nau8825_jack_pins[] = { }, }; -struct mt8188_card_data { - const char *name; - unsigned long quirk; -}; - static const struct snd_kcontrol_new mt8188_dumb_spk_controls[] = { SOC_DAPM_PIN_SWITCH("Ext Spk"), }; @@ -590,12 +585,12 @@ static int mt8188_dptx_hw_params_fixup(struct snd_soc_pcm_runtime *rtd, static int mt8188_hdmi_codec_init(struct snd_soc_pcm_runtime *rtd) { struct mtk_soc_card_data *soc_card_data = snd_soc_card_get_drvdata(rtd->card); - struct mt8188_mt6359_priv *priv = soc_card_data->mach_priv; + struct snd_soc_jack *jack = &soc_card_data->card_data->jacks[MT8188_JACK_HDMI]; struct snd_soc_component *component = snd_soc_rtd_to_codec(rtd, 0)->component; int ret = 0; ret = snd_soc_card_jack_new_pins(rtd->card, "HDMI Jack", - SND_JACK_LINEOUT, &priv->hdmi_jack, + SND_JACK_LINEOUT, jack, mt8188_hdmi_jack_pins, ARRAY_SIZE(mt8188_hdmi_jack_pins)); if (ret) { @@ -603,7 +598,7 @@ static int mt8188_hdmi_codec_init(struct snd_soc_pcm_runtime *rtd) return ret; } - ret = snd_soc_component_set_jack(component, &priv->hdmi_jack, NULL); + ret = snd_soc_component_set_jack(component, jack, NULL); if (ret) { dev_err(rtd->dev, "%s, set jack failed on %s (ret=%d)\n", __func__, component->name, ret); @@ -616,19 +611,19 @@ static int mt8188_hdmi_codec_init(struct snd_soc_pcm_runtime *rtd) static int mt8188_dptx_codec_init(struct snd_soc_pcm_runtime *rtd) { struct mtk_soc_card_data *soc_card_data = snd_soc_card_get_drvdata(rtd->card); - struct mt8188_mt6359_priv *priv = soc_card_data->mach_priv; + struct snd_soc_jack *jack = &soc_card_data->card_data->jacks[MT8188_JACK_DP]; struct snd_soc_component *component = snd_soc_rtd_to_codec(rtd, 0)->component; int ret = 0; ret = snd_soc_card_jack_new_pins(rtd->card, "DP Jack", SND_JACK_LINEOUT, - &priv->dp_jack, mt8188_dp_jack_pins, + jack, mt8188_dp_jack_pins, ARRAY_SIZE(mt8188_dp_jack_pins)); if (ret) { dev_err(rtd->dev, "%s, new jack failed: %d\n", __func__, ret); return ret; } - ret = snd_soc_component_set_jack(component, &priv->dp_jack, NULL); + ret = snd_soc_component_set_jack(component, jack, NULL); if (ret) { dev_err(rtd->dev, "%s, set jack failed on %s (ret=%d)\n", __func__, component->name, ret); @@ -736,10 +731,9 @@ static int mt8188_max98390_codec_init(struct snd_soc_pcm_runtime *rtd) static int mt8188_headset_codec_init(struct snd_soc_pcm_runtime *rtd) { struct snd_soc_card *card = rtd->card; - struct mtk_soc_card_data *soc_card_data = snd_soc_card_get_drvdata(card); - struct mt8188_mt6359_priv *priv = soc_card_data->mach_priv; + struct mtk_soc_card_data *soc_card_data = snd_soc_card_get_drvdata(rtd->card); + struct snd_soc_jack *jack = &soc_card_data->card_data->jacks[MT8188_JACK_HEADSET]; struct snd_soc_component *component = snd_soc_rtd_to_codec(rtd, 0)->component; - struct snd_soc_jack *jack = &priv->headset_jack; int ret; ret = snd_soc_dapm_new_controls(&card->dapm, mt8188_nau8825_widgets, @@ -1224,11 +1218,10 @@ static struct snd_soc_dai_link mt8188_mt6359_dai_links[] = { static void mt8188_fixup_controls(struct snd_soc_card *card) { struct mtk_soc_card_data *soc_card_data = snd_soc_card_get_drvdata(card); - struct mt8188_mt6359_priv *priv = soc_card_data->mach_priv; - struct mt8188_card_data *card_data = (struct mt8188_card_data *)priv->private_data; + struct mtk_platform_card_data *card_data = soc_card_data->card_data; struct snd_kcontrol *kctl; - if (card_data->quirk & (NAU8825_HS_PRESENT | RT5682S_HS_PRESENT | ES8326_HS_PRESENT)) { + if (card_data->flags & (NAU8825_HS_PRESENT | RT5682S_HS_PRESENT | ES8326_HS_PRESENT)) { struct snd_soc_dapm_widget *w, *next_w; for_each_card_widgets_safe(card, w, next_w) { @@ -1259,14 +1252,10 @@ static struct snd_soc_card mt8188_mt6359_soc_card = { .fixup_controls = mt8188_fixup_controls, }; -static int mt8188_mt6359_dev_probe(struct platform_device *pdev) +static int mt8188_mt6359_soc_card_probe(struct mtk_soc_card_data *soc_card_data, bool legacy) { - struct snd_soc_card *card = &mt8188_mt6359_soc_card; - struct device_node *platform_node; - struct device_node *adsp_node; - struct mtk_soc_card_data *soc_card_data; - struct mt8188_mt6359_priv *priv; - struct mt8188_card_data *card_data; + struct mtk_platform_card_data *card_data = soc_card_data->card_data; + struct snd_soc_card *card = soc_card_data->card_data->card; struct snd_soc_dai_link *dai_link; bool init_mt6359 = false; bool init_es8326 = false; @@ -1274,91 +1263,12 @@ static int mt8188_mt6359_dev_probe(struct platform_device *pdev) bool init_rt5682s = false; bool init_max98390 = false; bool init_dumb = false; - int ret, i; - - card_data = (struct mt8188_card_data *)of_device_get_match_data(&pdev->dev); - card->dev = &pdev->dev; - - ret = snd_soc_of_parse_card_name(card, "model"); - if (ret) - return dev_err_probe(&pdev->dev, ret, "%s new card name parsing error\n", - __func__); - - if (!card->name) - card->name = card_data->name; - - if (of_property_read_bool(pdev->dev.of_node, "audio-routing")) { - ret = snd_soc_of_parse_audio_routing(card, "audio-routing"); - if (ret) - return ret; - } - - priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL); - if (!priv) - return -ENOMEM; - - soc_card_data = devm_kzalloc(&pdev->dev, sizeof(*card_data), GFP_KERNEL); - if (!soc_card_data) - return -ENOMEM; - - soc_card_data->mach_priv = priv; - - adsp_node = of_parse_phandle(pdev->dev.of_node, "mediatek,adsp", 0); - if (adsp_node) { - struct mtk_sof_priv *sof_priv; - - sof_priv = devm_kzalloc(&pdev->dev, sizeof(*sof_priv), GFP_KERNEL); - if (!sof_priv) { - ret = -ENOMEM; - goto err_adsp_node; - } - sof_priv->conn_streams = g_sof_conn_streams; - sof_priv->num_streams = ARRAY_SIZE(g_sof_conn_streams); - soc_card_data->sof_priv = sof_priv; - card->probe = mtk_sof_card_probe; - card->late_probe = mtk_sof_card_late_probe; - if (!card->topology_shortname_created) { - snprintf(card->topology_shortname, 32, "sof-%s", card->name); - card->topology_shortname_created = true; - } - card->name = card->topology_shortname; - } - - if (of_property_read_bool(pdev->dev.of_node, "mediatek,dai-link")) { - ret = mtk_sof_dailink_parse_of(card, pdev->dev.of_node, - "mediatek,dai-link", - mt8188_mt6359_dai_links, - ARRAY_SIZE(mt8188_mt6359_dai_links)); - if (ret) { - dev_err_probe(&pdev->dev, ret, "Parse dai-link fail\n"); - goto err_adsp_node; - } - } else { - if (!adsp_node) - card->num_links = DAI_LINK_REGULAR_NUM; - } - - platform_node = of_parse_phandle(pdev->dev.of_node, - "mediatek,platform", 0); - if (!platform_node) { - ret = dev_err_probe(&pdev->dev, -EINVAL, - "Property 'platform' missing or invalid\n"); - goto err_adsp_node; - - } + int i; - ret = parse_dai_link_info(card); - if (ret) - goto err; + if (legacy) + return -EINVAL; for_each_card_prelinks(card, i, dai_link) { - if (!dai_link->platforms->name) { - if (!strncmp(dai_link->name, "AFE_SOF", strlen("AFE_SOF")) && adsp_node) - dai_link->platforms->of_node = adsp_node; - else - dai_link->platforms->of_node = platform_node; - } - if (strcmp(dai_link->name, "DPTX_BE") == 0) { if (strcmp(dai_link->codecs->dai_name, "snd-soc-dummy-dai")) dai_link->init = mt8188_dptx_codec_init; @@ -1381,7 +1291,7 @@ static int mt8188_mt6359_dev_probe(struct platform_device *pdev) * mt8188_max98390_ops. Two amps is I2S mode, * SOC and codec don't require TDM settings. */ - if (!(card_data->quirk & MAX98390_TWO_AMP)) { + if (!(card_data->flags & MAX98390_TWO_AMP)) { dai_link->ops = &mt8188_max98390_ops; } if (!init_max98390) { @@ -1420,40 +1330,55 @@ static int mt8188_mt6359_dev_probe(struct platform_device *pdev) } } - priv->private_data = card_data; - snd_soc_card_set_drvdata(card, soc_card_data); - - ret = devm_snd_soc_register_card(&pdev->dev, card); - if (ret) - dev_err_probe(&pdev->dev, ret, "%s snd_soc_register_card fail\n", - __func__); -err: - of_node_put(platform_node); - clean_card_reference(card); - -err_adsp_node: - of_node_put(adsp_node); - - return ret; + return 0; } -static struct mt8188_card_data mt8188_evb_card = { - .name = "mt8188_mt6359", +static const struct mtk_sof_priv mt8188_sof_priv = { + .conn_streams = g_sof_conn_streams, + .num_streams = ARRAY_SIZE(g_sof_conn_streams), +}; + +static const struct mtk_soundcard_pdata mt8188_evb_card = { + .card_name = "mt8188_mt6359", + .card_data = &(struct mtk_platform_card_data) { + .card = &mt8188_mt6359_soc_card, + .num_jacks = MT8188_JACK_MAX, + }, + .sof_priv = &mt8188_sof_priv, + .soc_probe = mt8188_mt6359_soc_card_probe, }; -static struct mt8188_card_data mt8188_nau8825_card = { - .name = "mt8188_nau8825", - .quirk = NAU8825_HS_PRESENT, +static const struct mtk_soundcard_pdata mt8188_nau8825_card = { + .card_name = "mt8188_nau8825", + .card_data = &(struct mtk_platform_card_data) { + .card = &mt8188_mt6359_soc_card, + .num_jacks = MT8188_JACK_MAX, + .flags = NAU8825_HS_PRESENT + }, + .sof_priv = &mt8188_sof_priv, + .soc_probe = mt8188_mt6359_soc_card_probe, }; -static struct mt8188_card_data mt8188_rt5682s_card = { - .name = "mt8188_rt5682s", - .quirk = RT5682S_HS_PRESENT | MAX98390_TWO_AMP, +static const struct mtk_soundcard_pdata mt8188_rt5682s_card = { + .card_name = "mt8188_rt5682s", + .card_data = &(struct mtk_platform_card_data) { + .card = &mt8188_mt6359_soc_card, + .num_jacks = MT8188_JACK_MAX, + .flags = RT5682S_HS_PRESENT | MAX98390_TWO_AMP + }, + .sof_priv = &mt8188_sof_priv, + .soc_probe = mt8188_mt6359_soc_card_probe, }; -static struct mt8188_card_data mt8188_es8326_card = { - .name = "mt8188_es8326", - .quirk = ES8326_HS_PRESENT | MAX98390_TWO_AMP, +static const struct mtk_soundcard_pdata mt8188_es8326_card = { + .card_name = "mt8188_es8326", + .card_data = &(struct mtk_platform_card_data) { + .card = &mt8188_mt6359_soc_card, + .num_jacks = MT8188_JACK_MAX, + .flags = ES8326_HS_PRESENT | MAX98390_TWO_AMP + }, + .sof_priv = &mt8188_sof_priv, + .soc_probe = mt8188_mt6359_soc_card_probe, }; static const struct of_device_id mt8188_mt6359_dt_match[] = { @@ -1471,7 +1396,7 @@ static struct platform_driver mt8188_mt6359_driver = { .of_match_table = mt8188_mt6359_dt_match, .pm = &snd_soc_pm_ops, }, - .probe = mt8188_mt6359_dev_probe, + .probe = mtk_soundcard_common_probe, }; module_platform_driver(mt8188_mt6359_driver); -- cgit v1.2.3 From 6718e1ed93cc28f0faefe21b7d21679ff0b04020 Mon Sep 17 00:00:00 2001 From: AngeloGioacchino Del Regno Date: Tue, 16 Apr 2024 09:13:56 +0200 Subject: ASoC: mediatek: mt8195: Migrate to mtk_soundcard_common_probe Add mtk_soundcard_pdata platform data for the MediaTek common sound card probe mechanism, including a driver/soc-specific probe extension (used for bits that cannot be commonized hence specific to this driver), and change the probe function to mtk_soundcard_common_probe. This is also adding the possibility of specifying the links and routing with the audio-routing property and (x)-dai-link nodes in device trees to stop hardcoding machine specific links in the card driver assupported by the common probe function, but support for legacy device trees is retained with a legacy_probe function, which is used only in case the new properties are not found. Signed-off-by: AngeloGioacchino Del Regno Link: https://lore.kernel.org/r/20240416071410.75620-5-angelogioacchino.delregno@collabora.com Signed-off-by: Mark Brown --- sound/soc/mediatek/mt8195/mt8195-mt6359.c | 292 ++++++++++++++++-------------- 1 file changed, 159 insertions(+), 133 deletions(-) diff --git a/sound/soc/mediatek/mt8195/mt8195-mt6359.c b/sound/soc/mediatek/mt8195/mt8195-mt6359.c index 53fd8a897b9d..f694618e7635 100644 --- a/sound/soc/mediatek/mt8195/mt8195-mt6359.c +++ b/sound/soc/mediatek/mt8195/mt8195-mt6359.c @@ -22,6 +22,7 @@ #include "../common/mtk-afe-platform-driver.h" #include "../common/mtk-dsp-sof-common.h" #include "../common/mtk-soc-card.h" +#include "../common/mtk-soundcard-driver.h" #include "mt8195-afe-clk.h" #include "mt8195-afe-common.h" @@ -29,6 +30,13 @@ #define RT1019_SPEAKER_AMP_PRESENT BIT(1) #define MAX98390_SPEAKER_AMP_PRESENT BIT(2) +#define DUMB_CODEC_INIT BIT(0) +#define MT6359_CODEC_INIT BIT(1) +#define RT1011_CODEC_INIT BIT(2) +#define RT1019_CODEC_INIT BIT(3) +#define MAX98390_CODEC_INIT BIT(4) +#define RT5682_CODEC_INIT BIT(5) + #define RT1011_CODEC_DAI "rt1011-aif" #define RT1011_DEV0_NAME "rt1011.2-0038" #define RT1011_DEV1_NAME "rt1011.2-0039" @@ -51,18 +59,17 @@ #define SOF_DMA_UL4 "SOF_DMA_UL4" #define SOF_DMA_UL5 "SOF_DMA_UL5" -struct mt8195_card_data { - const char *name; - unsigned long quirk; -}; - struct mt8195_mt6359_priv { - struct snd_soc_jack headset_jack; - struct snd_soc_jack dp_jack; - struct snd_soc_jack hdmi_jack; struct clk *i2so1_mclk; }; +enum mt8195_jacks { + MT8195_JACK_HEADSET, + MT8195_JACK_DP, + MT8195_JACK_HDMI, + MT8195_JACK_MAX, +}; + /* Headset jack detection DAPM pins */ static struct snd_soc_jack_pin mt8195_jack_pins[] = { { @@ -382,33 +389,31 @@ static const struct snd_soc_ops mt8195_dptx_ops = { static int mt8195_dptx_codec_init(struct snd_soc_pcm_runtime *rtd) { struct mtk_soc_card_data *soc_card_data = snd_soc_card_get_drvdata(rtd->card); - struct mt8195_mt6359_priv *priv = soc_card_data->mach_priv; + struct snd_soc_jack *jack = &soc_card_data->card_data->jacks[MT8195_JACK_DP]; struct snd_soc_component *cmpnt_codec = snd_soc_rtd_to_codec(rtd, 0)->component; int ret; - ret = snd_soc_card_jack_new(rtd->card, "DP Jack", SND_JACK_LINEOUT, - &priv->dp_jack); + ret = snd_soc_card_jack_new(rtd->card, "DP Jack", SND_JACK_LINEOUT, jack); if (ret) return ret; - return snd_soc_component_set_jack(cmpnt_codec, &priv->dp_jack, NULL); + return snd_soc_component_set_jack(cmpnt_codec, jack, NULL); } static int mt8195_hdmi_codec_init(struct snd_soc_pcm_runtime *rtd) { struct mtk_soc_card_data *soc_card_data = snd_soc_card_get_drvdata(rtd->card); - struct mt8195_mt6359_priv *priv = soc_card_data->mach_priv; + struct snd_soc_jack *jack = &soc_card_data->card_data->jacks[MT8195_JACK_HDMI]; struct snd_soc_component *cmpnt_codec = snd_soc_rtd_to_codec(rtd, 0)->component; int ret; - ret = snd_soc_card_jack_new(rtd->card, "HDMI Jack", SND_JACK_LINEOUT, - &priv->hdmi_jack); + ret = snd_soc_card_jack_new(rtd->card, "HDMI Jack", SND_JACK_LINEOUT, jack); if (ret) return ret; - return snd_soc_component_set_jack(cmpnt_codec, &priv->hdmi_jack, NULL); + return snd_soc_component_set_jack(cmpnt_codec, jack, NULL); } static int mt8195_dptx_hw_params_fixup(struct snd_soc_pcm_runtime *rtd, @@ -566,7 +571,7 @@ static int mt8195_rt5682_init(struct snd_soc_pcm_runtime *rtd) snd_soc_rtd_to_codec(rtd, 0)->component; struct mtk_soc_card_data *soc_card_data = snd_soc_card_get_drvdata(rtd->card); struct mt8195_mt6359_priv *priv = soc_card_data->mach_priv; - struct snd_soc_jack *jack = &priv->headset_jack; + struct snd_soc_jack *jack = &soc_card_data->card_data->jacks[MT8195_JACK_HEADSET]; struct snd_soc_component *cmpnt_afe = snd_soc_rtdcom_lookup(rtd, AFE_PCM_NAME); struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt_afe); @@ -687,7 +692,7 @@ static int mt8195_rt1011_init(struct snd_soc_pcm_runtime *rtd) return ret; } -static int mt8195_rt1019_init(struct snd_soc_pcm_runtime *rtd) +static int mt8195_dumb_amp_init(struct snd_soc_pcm_runtime *rtd) { struct snd_soc_card *card = rtd->card; int ret; @@ -707,6 +712,18 @@ static int mt8195_rt1019_init(struct snd_soc_pcm_runtime *rtd) return ret; } + return 0; +} + +static int mt8195_rt1019_init(struct snd_soc_pcm_runtime *rtd) +{ + struct snd_soc_card *card = rtd->card; + int ret; + + ret = mt8195_dumb_amp_init(rtd); + if (ret) + return ret; + ret = snd_soc_dapm_add_routes(&card->dapm, mt8195_rt1019_routes, ARRAY_SIZE(mt8195_rt1019_routes)); if (ret) @@ -1371,108 +1388,31 @@ static int mt8195_dai_link_fixup(struct snd_soc_pcm_runtime *rtd, return ret; } -static int mt8195_mt6359_dev_probe(struct platform_device *pdev) +static int mt8195_mt6359_legacy_probe(struct mtk_soc_card_data *soc_card_data) { - struct snd_soc_card *card = &mt8195_mt6359_soc_card; + struct mtk_platform_card_data *card_data = soc_card_data->card_data; + struct snd_soc_card *card = card_data->card; + struct device_node *codec_node, *dp_node, *hdmi_node; struct snd_soc_dai_link *dai_link; - struct mtk_soc_card_data *soc_card_data; - struct mt8195_mt6359_priv *mach_priv; - struct device_node *platform_node, *adsp_node, *codec_node, *dp_node, *hdmi_node; - struct mt8195_card_data *card_data; - int is5682s = 0; - int init6359 = 0; - int sof_on = 0; - int ret, i; - - card_data = (struct mt8195_card_data *)of_device_get_match_data(&pdev->dev); - card->dev = &pdev->dev; - - ret = snd_soc_of_parse_card_name(card, "model"); - if (ret) { - dev_err(&pdev->dev, "%s new card name parsing error %d\n", - __func__, ret); - return ret; - } - - if (!card->name) - card->name = card_data->name; + struct device *dev = card->dev; + bool is5682s, init6359 = false; + int i; if (strstr(card->name, "_5682s")) { codec_node = of_find_compatible_node(NULL, NULL, "realtek,rt5682s"); - is5682s = 1; - } else - codec_node = of_find_compatible_node(NULL, NULL, "realtek,rt5682i"); - - soc_card_data = devm_kzalloc(&pdev->dev, sizeof(*card_data), GFP_KERNEL); - if (!soc_card_data) - return -ENOMEM; - - mach_priv = devm_kzalloc(&pdev->dev, sizeof(*mach_priv), GFP_KERNEL); - if (!mach_priv) - return -ENOMEM; - - soc_card_data->mach_priv = mach_priv; - - adsp_node = of_parse_phandle(pdev->dev.of_node, "mediatek,adsp", 0); - if (adsp_node) { - struct mtk_sof_priv *sof_priv; - - sof_priv = devm_kzalloc(&pdev->dev, sizeof(*sof_priv), GFP_KERNEL); - if (!sof_priv) { - ret = -ENOMEM; - goto err_kzalloc; - } - sof_priv->conn_streams = g_sof_conn_streams; - sof_priv->num_streams = ARRAY_SIZE(g_sof_conn_streams); - sof_priv->sof_dai_link_fixup = mt8195_dai_link_fixup; - soc_card_data->sof_priv = sof_priv; - card->probe = mtk_sof_card_probe; - card->late_probe = mtk_sof_card_late_probe; - if (!card->topology_shortname_created) { - snprintf(card->topology_shortname, 32, "sof-%s", card->name); - card->topology_shortname_created = true; - } - card->name = card->topology_shortname; - sof_on = 1; - } - - if (of_property_read_bool(pdev->dev.of_node, "mediatek,dai-link")) { - ret = mtk_sof_dailink_parse_of(card, pdev->dev.of_node, - "mediatek,dai-link", - mt8195_mt6359_dai_links, - ARRAY_SIZE(mt8195_mt6359_dai_links)); - if (ret) { - dev_dbg(&pdev->dev, "Parse dai-link fail\n"); - goto err_parse_of; - } + is5682s = true; } else { - if (!sof_on) - card->num_links = DAI_LINK_REGULAR_NUM; - } - - platform_node = of_parse_phandle(pdev->dev.of_node, - "mediatek,platform", 0); - if (!platform_node) { - dev_dbg(&pdev->dev, "Property 'platform' missing or invalid\n"); - ret = -EINVAL; - goto err_platform_node; + codec_node = of_find_compatible_node(NULL, NULL, "realtek,rt5682i"); + is5682s = false; } - dp_node = of_parse_phandle(pdev->dev.of_node, "mediatek,dptx-codec", 0); - hdmi_node = of_parse_phandle(pdev->dev.of_node, - "mediatek,hdmi-codec", 0); + dp_node = of_parse_phandle(dev->of_node, "mediatek,dptx-codec", 0); + hdmi_node = of_parse_phandle(dev->of_node, "mediatek,hdmi-codec", 0); for_each_card_prelinks(card, i, dai_link) { - if (!dai_link->platforms->name) { - if (!strncmp(dai_link->name, "AFE_SOF", strlen("AFE_SOF")) && sof_on) - dai_link->platforms->of_node = adsp_node; - else - dai_link->platforms->of_node = platform_node; - } - if (strcmp(dai_link->name, "DPTX_BE") == 0) { if (!dp_node) { - dev_dbg(&pdev->dev, "No property 'dptx-codec'\n"); + dev_dbg(dev, "No property 'dptx-codec'\n"); } else { dai_link->codecs->of_node = dp_node; dai_link->codecs->name = NULL; @@ -1481,7 +1421,7 @@ static int mt8195_mt6359_dev_probe(struct platform_device *pdev) } } else if (strcmp(dai_link->name, "ETDM3_OUT_BE") == 0) { if (!hdmi_node) { - dev_dbg(&pdev->dev, "No property 'hdmi-codec'\n"); + dev_dbg(dev, "No property 'hdmi-codec'\n"); } else { dai_link->codecs->of_node = hdmi_node; dai_link->codecs->name = NULL; @@ -1490,7 +1430,7 @@ static int mt8195_mt6359_dev_probe(struct platform_device *pdev) } } else if (strcmp(dai_link->name, "ETDM1_OUT_BE") == 0) { if (!codec_node) { - dev_err(&pdev->dev, "Codec not found!\n"); + dev_err(dev, "Codec not found!\n"); } else { dai_link->codecs->of_node = codec_node; dai_link->codecs->name = NULL; @@ -1501,7 +1441,7 @@ static int mt8195_mt6359_dev_probe(struct platform_device *pdev) } } else if (strcmp(dai_link->name, "ETDM2_IN_BE") == 0) { if (!codec_node) { - dev_err(&pdev->dev, "Codec not found!\n"); + dev_err(dev, "Codec not found!\n"); } else { dai_link->codecs->of_node = codec_node; dai_link->codecs->name = NULL; @@ -1514,10 +1454,10 @@ static int mt8195_mt6359_dev_probe(struct platform_device *pdev) strcmp(dai_link->name, "UL_SRC2_BE") == 0) { if (!init6359) { dai_link->init = mt8195_mt6359_init; - init6359 = 1; + init6359 = true; } } else if (strcmp(dai_link->name, "ETDM2_OUT_BE") == 0) { - switch (card_data->quirk) { + switch (card_data->flags) { case RT1011_SPEAKER_AMP_PRESENT: dai_link->codecs = rt1011_comps; dai_link->num_codecs = ARRAY_SIZE(rt1011_comps); @@ -1545,33 +1485,119 @@ static int mt8195_mt6359_dev_probe(struct platform_device *pdev) } } - snd_soc_card_set_drvdata(card, soc_card_data); + return 0; +} - ret = devm_snd_soc_register_card(&pdev->dev, card); +static int mt8195_mt6359_soc_card_probe(struct mtk_soc_card_data *soc_card_data, bool legacy) +{ + struct mtk_platform_card_data *card_data = soc_card_data->card_data; + struct snd_soc_card *card = card_data->card; + struct mt8195_mt6359_priv *mach_priv; + struct snd_soc_dai_link *dai_link; + u8 codec_init = 0; + int i; - of_node_put(platform_node); - of_node_put(dp_node); - of_node_put(hdmi_node); -err_kzalloc: -err_parse_of: -err_platform_node: - of_node_put(adsp_node); - return ret; + mach_priv = devm_kzalloc(card->dev, sizeof(*mach_priv), GFP_KERNEL); + if (!mach_priv) + return -ENOMEM; + + soc_card_data->mach_priv = mach_priv; + + if (legacy) + return mt8195_mt6359_legacy_probe(soc_card_data); + + for_each_card_prelinks(card, i, dai_link) { + if (strcmp(dai_link->name, "DPTX_BE") == 0) { + if (strcmp(dai_link->codecs->dai_name, "snd-soc-dummy-dai")) + dai_link->init = mt8195_dptx_codec_init; + } else if (strcmp(dai_link->name, "ETDM3_OUT_BE") == 0) { + if (strcmp(dai_link->codecs->dai_name, "snd-soc-dummy-dai")) + dai_link->init = mt8195_hdmi_codec_init; + } else if (strcmp(dai_link->name, "DL_SRC_BE") == 0 || + strcmp(dai_link->name, "UL_SRC1_BE") == 0 || + strcmp(dai_link->name, "UL_SRC2_BE") == 0) { + if (!(codec_init & MT6359_CODEC_INIT)) { + dai_link->init = mt8195_mt6359_init; + codec_init |= MT6359_CODEC_INIT; + } + } else if (strcmp(dai_link->name, "ETDM1_OUT_BE") == 0 || + strcmp(dai_link->name, "ETDM2_OUT_BE") == 0 || + strcmp(dai_link->name, "ETDM1_IN_BE") == 0 || + strcmp(dai_link->name, "ETDM2_IN_BE") == 0) { + if (!strcmp(dai_link->codecs->dai_name, MAX98390_CODEC_DAI)) { + if (!(codec_init & MAX98390_CODEC_INIT)) { + dai_link->init = mt8195_max98390_init; + codec_init |= MAX98390_CODEC_INIT; + } + } else if (!strcmp(dai_link->codecs->dai_name, RT1011_CODEC_DAI)) { + dai_link->ops = &mt8195_rt1011_etdm_ops; + if (!(codec_init & RT1011_CODEC_INIT)) { + dai_link->init = mt8195_rt1011_init; + codec_init |= RT1011_CODEC_INIT; + } + } else if (!strcmp(dai_link->codecs->dai_name, RT1019_CODEC_DAI)) { + if (!(codec_init & RT1019_CODEC_INIT)) { + dai_link->init = mt8195_rt1019_init; + codec_init |= RT1019_CODEC_INIT; + } + } else if (!strcmp(dai_link->codecs->dai_name, RT5682_CODEC_DAI) || + !strcmp(dai_link->codecs->dai_name, RT5682S_CODEC_DAI)) { + dai_link->ops = &mt8195_rt5682_etdm_ops; + if (!(codec_init & RT5682_CODEC_INIT)) { + dai_link->init = mt8195_rt5682_init; + codec_init |= RT5682_CODEC_INIT; + } + } else { + if (strcmp(dai_link->codecs->dai_name, "snd-soc-dummy-dai")) { + if (!(codec_init & DUMB_CODEC_INIT)) { + dai_link->init = mt8195_dumb_amp_init; + codec_init |= DUMB_CODEC_INIT; + } + } + } + } + } + + return 0; } -static struct mt8195_card_data mt8195_mt6359_rt1019_rt5682_card = { - .name = "mt8195_r1019_5682", - .quirk = RT1019_SPEAKER_AMP_PRESENT, +static const struct mtk_sof_priv mt8195_sof_priv = { + .conn_streams = g_sof_conn_streams, + .num_streams = ARRAY_SIZE(g_sof_conn_streams), + .sof_dai_link_fixup = mt8195_dai_link_fixup }; -static struct mt8195_card_data mt8195_mt6359_rt1011_rt5682_card = { - .name = "mt8195_r1011_5682", - .quirk = RT1011_SPEAKER_AMP_PRESENT, +static const struct mtk_soundcard_pdata mt8195_mt6359_rt1019_rt5682_card = { + .card_name = "mt8195_r1019_5682", + .card_data = &(struct mtk_platform_card_data) { + .card = &mt8195_mt6359_soc_card, + .num_jacks = MT8195_JACK_MAX, + .flags = RT1019_SPEAKER_AMP_PRESENT + }, + .sof_priv = &mt8195_sof_priv, + .soc_probe = mt8195_mt6359_soc_card_probe }; -static struct mt8195_card_data mt8195_mt6359_max98390_rt5682_card = { - .name = "mt8195_m98390_r5682", - .quirk = MAX98390_SPEAKER_AMP_PRESENT, +static const struct mtk_soundcard_pdata mt8195_mt6359_rt1011_rt5682_card = { + .card_name = "mt8195_r1011_5682", + .card_data = &(struct mtk_platform_card_data) { + .card = &mt8195_mt6359_soc_card, + .num_jacks = MT8195_JACK_MAX, + .flags = RT1011_SPEAKER_AMP_PRESENT + }, + .sof_priv = &mt8195_sof_priv, + .soc_probe = mt8195_mt6359_soc_card_probe +}; + +static const struct mtk_soundcard_pdata mt8195_mt6359_max98390_rt5682_card = { + .card_name = "mt8195_m98390_r5682", + .card_data = &(struct mtk_platform_card_data) { + .card = &mt8195_mt6359_soc_card, + .num_jacks = MT8195_JACK_MAX, + .flags = MAX98390_SPEAKER_AMP_PRESENT + }, + .sof_priv = &mt8195_sof_priv, + .soc_probe = mt8195_mt6359_soc_card_probe }; static const struct of_device_id mt8195_mt6359_dt_match[] = { @@ -1597,7 +1623,7 @@ static struct platform_driver mt8195_mt6359_driver = { .of_match_table = mt8195_mt6359_dt_match, .pm = &snd_soc_pm_ops, }, - .probe = mt8195_mt6359_dev_probe, + .probe = mtk_soundcard_common_probe, }; module_platform_driver(mt8195_mt6359_driver); -- cgit v1.2.3 From 2d72cbb56327205ae04a9376c5b78a35b6347294 Mon Sep 17 00:00:00 2001 From: AngeloGioacchino Del Regno Date: Tue, 16 Apr 2024 09:13:57 +0200 Subject: ASoC: mediatek: mt8192: Migrate to mtk_soundcard_common_probe Add mtk_soundcard_pdata platform data for the MediaTek common sound card probe mechanism, including a driver/soc-specific probe extension (used for bits that cannot be commonized hence specific to this driver), and change the probe function to mtk_soundcard_common_probe. This is also adding the possibility of specifying the links and routing with the audio-routing property and (x)-dai-link nodes in device trees to stop hardcoding machine specific links in the card driver assupported by the common probe function, but support for legacy device trees is retained with a legacy_probe function, which is used only in case the new properties are not found. Reviewed-by: Alexandre Mergnat Signed-off-by: AngeloGioacchino Del Regno Link: https://lore.kernel.org/r/20240416071410.75620-6-angelogioacchino.delregno@collabora.com Signed-off-by: Mark Brown --- .../mediatek/mt8192/mt8192-mt6359-rt1015-rt5682.c | 164 ++++++++++++--------- 1 file changed, 91 insertions(+), 73 deletions(-) diff --git a/sound/soc/mediatek/mt8192/mt8192-mt6359-rt1015-rt5682.c b/sound/soc/mediatek/mt8192/mt8192-mt6359-rt1015-rt5682.c index bfcb2c486c39..645bc1aa67c7 100644 --- a/sound/soc/mediatek/mt8192/mt8192-mt6359-rt1015-rt5682.c +++ b/sound/soc/mediatek/mt8192/mt8192-mt6359-rt1015-rt5682.c @@ -20,6 +20,8 @@ #include "../../codecs/rt1015.h" #include "../../codecs/rt5682.h" #include "../common/mtk-afe-platform-driver.h" +#include "../common/mtk-soc-card.h" +#include "../common/mtk-soundcard-driver.h" #include "mt8192-afe-common.h" #include "mt8192-afe-clk.h" #include "mt8192-afe-gpio.h" @@ -38,9 +40,10 @@ #define RT1015P_RT5682_OF_NAME "mediatek,mt8192_mt6359_rt1015p_rt5682" #define RT1015P_RT5682S_OF_NAME "mediatek,mt8192_mt6359_rt1015p_rt5682s" -struct mt8192_mt6359_priv { - struct snd_soc_jack headset_jack; - struct snd_soc_jack hdmi_jack; +enum mt8192_jacks { + MT8192_JACK_HEADSET, + MT8192_JACK_HDMI, + MT8192_JACK_MAX, }; /* Headset jack detection DAPM pins */ @@ -323,13 +326,13 @@ static int mt8192_mt6359_init(struct snd_soc_pcm_runtime *rtd) static int mt8192_rt5682_init(struct snd_soc_pcm_runtime *rtd) { + struct mtk_soc_card_data *soc_card_data = snd_soc_card_get_drvdata(rtd->card); + struct snd_soc_jack *jack = &soc_card_data->card_data->jacks[MT8192_JACK_HEADSET]; struct snd_soc_component *cmpnt_afe = snd_soc_rtdcom_lookup(rtd, AFE_PCM_NAME); struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt_afe); struct snd_soc_component *cmpnt_codec = snd_soc_rtd_to_codec(rtd, 0)->component; - struct mt8192_mt6359_priv *priv = snd_soc_card_get_drvdata(rtd->card); - struct snd_soc_jack *jack = &priv->headset_jack; int ret; ret = mt8192_dai_i2s_set_share(afe, "I2S8", "I2S9"); @@ -359,19 +362,19 @@ static int mt8192_rt5682_init(struct snd_soc_pcm_runtime *rtd) static int mt8192_mt6359_hdmi_init(struct snd_soc_pcm_runtime *rtd) { + struct mtk_soc_card_data *soc_card_data = snd_soc_card_get_drvdata(rtd->card); + struct snd_soc_jack *jack = &soc_card_data->card_data->jacks[MT8192_JACK_HDMI]; struct snd_soc_component *cmpnt_codec = snd_soc_rtd_to_codec(rtd, 0)->component; - struct mt8192_mt6359_priv *priv = snd_soc_card_get_drvdata(rtd->card); int ret; - ret = snd_soc_card_jack_new(rtd->card, "HDMI Jack", SND_JACK_LINEOUT, - &priv->hdmi_jack); + ret = snd_soc_card_jack_new(rtd->card, "HDMI Jack", SND_JACK_LINEOUT, jack); if (ret) { dev_err(rtd->dev, "HDMI Jack creation failed: %d\n", ret); return ret; } - return snd_soc_component_set_jack(cmpnt_codec, &priv->hdmi_jack, NULL); + return snd_soc_component_set_jack(cmpnt_codec, jack, NULL); } static int mt8192_i2s_hw_params_fixup(struct snd_soc_pcm_runtime *rtd, @@ -1136,71 +1139,53 @@ static int mt8192_mt6359_card_set_be_link(struct snd_soc_card *card, return 0; } -static int mt8192_mt6359_dev_probe(struct platform_device *pdev) +static int mt8192_mt6359_legacy_probe(struct mtk_soc_card_data *soc_card_data) { - struct snd_soc_card *card; - struct device_node *platform_node, *hdmi_codec, *headset_codec, *speaker_codec; - int ret, i; + struct mtk_platform_card_data *card_data = soc_card_data->card_data; + struct snd_soc_card *card = card_data->card; + struct device *dev = card->dev; + struct device_node *hdmi_codec, *headset_codec, *speaker_codec; struct snd_soc_dai_link *dai_link; - struct mt8192_mt6359_priv *priv; - - card = (struct snd_soc_card *)of_device_get_match_data(&pdev->dev); - if (!card) - return -EINVAL; - card->dev = &pdev->dev; - - if (of_device_is_compatible(pdev->dev.of_node, RT1015P_RT5682_OF_NAME)) - card->name = RT1015P_RT5682_CARD_NAME; - else if (of_device_is_compatible(pdev->dev.of_node, RT1015P_RT5682S_OF_NAME)) - card->name = RT1015P_RT5682S_CARD_NAME; - else - dev_dbg(&pdev->dev, "No need to set card name\n"); + int ret, i; - hdmi_codec = of_parse_phandle(pdev->dev.of_node, "mediatek,hdmi-codec", 0); + hdmi_codec = of_parse_phandle(dev->of_node, "mediatek,hdmi-codec", 0); if (!hdmi_codec) - dev_dbg(&pdev->dev, "The machine has no hdmi-codec\n"); + dev_dbg(dev, "The machine has no hdmi-codec\n"); - platform_node = of_parse_phandle(pdev->dev.of_node, "mediatek,platform", 0); - if (!platform_node) { - ret = -EINVAL; - dev_err_probe(&pdev->dev, ret, "Property 'platform' missing or invalid\n"); - goto err_platform_node; - } - - speaker_codec = of_get_child_by_name(pdev->dev.of_node, "speaker-codecs"); + speaker_codec = of_get_child_by_name(dev->of_node, "speaker-codecs"); if (!speaker_codec) { ret = -EINVAL; - dev_err_probe(&pdev->dev, ret, "Property 'speaker-codecs' missing or invalid\n"); + dev_err_probe(dev, ret, "Property 'speaker-codecs' missing or invalid\n"); goto err_speaker_codec; } - headset_codec = of_get_child_by_name(pdev->dev.of_node, "headset-codec"); + headset_codec = of_get_child_by_name(dev->of_node, "headset-codec"); if (!headset_codec) { ret = -EINVAL; - dev_err_probe(&pdev->dev, ret, "Property 'headset-codec' missing or invalid\n"); + dev_err_probe(dev, ret, "Property 'headset-codec' missing or invalid\n"); goto err_headset_codec; } for_each_card_prelinks(card, i, dai_link) { ret = mt8192_mt6359_card_set_be_link(card, dai_link, speaker_codec, "I2S3"); if (ret) { - dev_err_probe(&pdev->dev, ret, "%s set speaker_codec fail\n", + dev_err_probe(dev, ret, "%s set speaker_codec fail\n", dai_link->name); - goto err_probe; + break; } ret = mt8192_mt6359_card_set_be_link(card, dai_link, headset_codec, "I2S8"); if (ret) { - dev_err_probe(&pdev->dev, ret, "%s set headset_codec fail\n", + dev_err_probe(dev, ret, "%s set headset_codec fail\n", dai_link->name); - goto err_probe; + break; } ret = mt8192_mt6359_card_set_be_link(card, dai_link, headset_codec, "I2S9"); if (ret) { - dev_err_probe(&pdev->dev, ret, "%s set headset_codec fail\n", + dev_err_probe(dev, ret, "%s set headset_codec fail\n", dai_link->name); - goto err_probe; + break; } if (hdmi_codec && strcmp(dai_link->name, "TDM") == 0) { @@ -1211,52 +1196,85 @@ static int mt8192_mt6359_dev_probe(struct platform_device *pdev) if (dai_link->num_codecs && dai_link->codecs[0].dai_name && strcmp(dai_link->codecs[0].dai_name, RT1015_CODEC_DAI) == 0) dai_link->ops = &mt8192_rt1015_i2s_ops; - - if (!dai_link->platforms->name) - dai_link->platforms->of_node = platform_node; - } - - priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL); - if (!priv) { - ret = -ENOMEM; - goto err_probe; - } - snd_soc_card_set_drvdata(card, priv); - - ret = mt8192_afe_gpio_init(&pdev->dev); - if (ret) { - dev_err_probe(&pdev->dev, ret, "%s init gpio error\n", __func__); - goto err_probe; } - ret = devm_snd_soc_register_card(&pdev->dev, card); - if (ret) - dev_err_probe(&pdev->dev, ret, "%s snd_soc_register_card fail\n", __func__); - -err_probe: of_node_put(headset_codec); err_headset_codec: of_node_put(speaker_codec); err_speaker_codec: - of_node_put(platform_node); -err_platform_node: - of_node_put(hdmi_codec); + if (hdmi_codec) + of_node_put(hdmi_codec); + return ret; } +static int mt8192_mt6359_soc_card_probe(struct mtk_soc_card_data *soc_card_data, bool legacy) +{ + struct mtk_platform_card_data *card_data = soc_card_data->card_data; + struct snd_soc_card *card = card_data->card; + int ret; + + if (legacy) { + ret = mt8192_mt6359_legacy_probe(soc_card_data); + if (ret) + return ret; + } else { + struct snd_soc_dai_link *dai_link; + int i; + + for_each_card_prelinks(card, i, dai_link) + if (dai_link->num_codecs && dai_link->codecs[0].dai_name && + strcmp(dai_link->codecs[0].dai_name, RT1015_CODEC_DAI) == 0) + dai_link->ops = &mt8192_rt1015_i2s_ops; + } + + ret = mt8192_afe_gpio_init(card->dev); + if (ret) + return dev_err_probe(card->dev, ret, "%s init gpio error\n", __func__); + + return 0; +} + +static const struct mtk_soundcard_pdata mt8192_mt6359_rt1015_rt5682_pdata = { + .card_name = RT1015_RT5682_CARD_NAME, + .card_data = &(struct mtk_platform_card_data) { + .card = &mt8192_mt6359_rt1015_rt5682_card, + .num_jacks = MT8192_JACK_MAX, + }, + .soc_probe = mt8192_mt6359_soc_card_probe +}; + +static const struct mtk_soundcard_pdata mt8192_mt6359_rt1015p_rt5682_pdata = { + .card_name = RT1015P_RT5682_CARD_NAME, + .card_data = &(struct mtk_platform_card_data) { + .card = &mt8192_mt6359_rt1015p_rt5682x_card, + .num_jacks = MT8192_JACK_MAX, + }, + .soc_probe = mt8192_mt6359_soc_card_probe +}; + +static const struct mtk_soundcard_pdata mt8192_mt6359_rt1015p_rt5682s_pdata = { + .card_name = RT1015P_RT5682S_CARD_NAME, + .card_data = &(struct mtk_platform_card_data) { + .card = &mt8192_mt6359_rt1015p_rt5682x_card, + .num_jacks = MT8192_JACK_MAX, + }, + .soc_probe = mt8192_mt6359_soc_card_probe +}; + #ifdef CONFIG_OF static const struct of_device_id mt8192_mt6359_dt_match[] = { { .compatible = RT1015_RT5682_OF_NAME, - .data = &mt8192_mt6359_rt1015_rt5682_card, + .data = &mt8192_mt6359_rt1015_rt5682_pdata, }, { .compatible = RT1015P_RT5682_OF_NAME, - .data = &mt8192_mt6359_rt1015p_rt5682x_card, + .data = &mt8192_mt6359_rt1015p_rt5682_pdata, }, { .compatible = RT1015P_RT5682S_OF_NAME, - .data = &mt8192_mt6359_rt1015p_rt5682x_card, + .data = &mt8192_mt6359_rt1015p_rt5682s_pdata, }, {} }; @@ -1276,7 +1294,7 @@ static struct platform_driver mt8192_mt6359_driver = { #endif .pm = &mt8192_mt6359_pm_ops, }, - .probe = mt8192_mt6359_dev_probe, + .probe = mtk_soundcard_common_probe, }; module_platform_driver(mt8192_mt6359_driver); -- cgit v1.2.3 From 44a53c8ec9cad02ce7dfd55094e8d7aeb48eb73c Mon Sep 17 00:00:00 2001 From: AngeloGioacchino Del Regno Date: Tue, 16 Apr 2024 09:13:58 +0200 Subject: ASoC: mediatek: mt8186: Migrate to mtk_soundcard_common_probe Add mtk_soundcard_pdata platform data for the MediaTek common sound card probe mechanism, including a driver/soc-specific probe extension (used for bits that cannot be commonized hence specific to this driver), and change the probe function to mtk_soundcard_common_probe. This is also adding the possibility of specifying the links and routing with the audio-routing property and (x)-dai-link nodes in device trees to stop hardcoding machine specific links in the card driver assupported by the common probe function, but support for legacy device trees is retained with a legacy_probe function, which is used only in case the new properties are not found. Reviewed-by: Alexandre Mergnat Signed-off-by: AngeloGioacchino Del Regno Link: https://lore.kernel.org/r/20240416071410.75620-7-angelogioacchino.delregno@collabora.com Signed-off-by: Mark Brown --- .../mediatek/mt8186/mt8186-mt6366-rt1019-rt5682s.c | 220 +++++++++------------ 1 file changed, 96 insertions(+), 124 deletions(-) diff --git a/sound/soc/mediatek/mt8186/mt8186-mt6366-rt1019-rt5682s.c b/sound/soc/mediatek/mt8186/mt8186-mt6366-rt1019-rt5682s.c index f78197c8e582..f8856a100b27 100644 --- a/sound/soc/mediatek/mt8186/mt8186-mt6366-rt1019-rt5682s.c +++ b/sound/soc/mediatek/mt8186/mt8186-mt6366-rt1019-rt5682s.c @@ -21,6 +21,7 @@ #include "../common/mtk-afe-platform-driver.h" #include "../common/mtk-dsp-sof-common.h" #include "../common/mtk-soc-card.h" +#include "../common/mtk-soundcard-driver.h" #include "mt8186-afe-common.h" #include "mt8186-afe-clk.h" #include "mt8186-afe-gpio.h" @@ -38,11 +39,16 @@ #define SOF_DMA_UL2 "SOF_DMA_UL2" struct mt8186_mt6366_rt1019_rt5682s_priv { - struct snd_soc_jack headset_jack, hdmi_jack; struct gpio_desc *dmic_sel; int dmic_switch; }; +enum mt8186_jacks { + MT8186_JACK_HEADSET, + MT8186_JACK_HDMI, + MT8186_JACK_MAX, +}; + /* Headset jack detection DAPM pins */ static struct snd_soc_jack_pin mt8186_jack_pins[] = { { @@ -165,8 +171,7 @@ static int mt8186_rt5682s_init(struct snd_soc_pcm_runtime *rtd) struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt_afe); struct mtk_soc_card_data *soc_card_data = snd_soc_card_get_drvdata(rtd->card); - struct mt8186_mt6366_rt1019_rt5682s_priv *priv = soc_card_data->mach_priv; - struct snd_soc_jack *jack = &priv->headset_jack; + struct snd_soc_jack *jack = &soc_card_data->card_data->jacks[MT8186_JACK_HEADSET]; struct snd_soc_component *cmpnt_codec = snd_soc_rtd_to_codec(rtd, 0)->component; int ret; @@ -257,7 +262,7 @@ static int mt8186_mt6366_rt1019_rt5682s_hdmi_init(struct snd_soc_pcm_runtime *rt snd_soc_rtd_to_codec(rtd, 0)->component; struct mtk_soc_card_data *soc_card_data = snd_soc_card_get_drvdata(rtd->card); - struct mt8186_mt6366_rt1019_rt5682s_priv *priv = soc_card_data->mach_priv; + struct snd_soc_jack *jack = &soc_card_data->card_data->jacks[MT8186_JACK_HDMI]; int ret; ret = mt8186_dai_i2s_set_share(afe, "I2S2", "I2S3"); @@ -266,13 +271,13 @@ static int mt8186_mt6366_rt1019_rt5682s_hdmi_init(struct snd_soc_pcm_runtime *rt return ret; } - ret = snd_soc_card_jack_new(rtd->card, "HDMI Jack", SND_JACK_LINEOUT, &priv->hdmi_jack); + ret = snd_soc_card_jack_new(rtd->card, "HDMI Jack", SND_JACK_LINEOUT, jack); if (ret) { dev_err(rtd->dev, "HDMI Jack creation failed: %d\n", ret); return ret; } - return snd_soc_component_set_jack(cmpnt_codec, &priv->hdmi_jack, NULL); + return snd_soc_component_set_jack(cmpnt_codec, jack, NULL); } static int mt8186_hw_params_fixup(struct snd_soc_pcm_runtime *rtd, @@ -1134,166 +1139,133 @@ static struct snd_soc_card mt8186_mt6366_rt5650_soc_card = { .num_configs = ARRAY_SIZE(mt8186_mt6366_rt1019_rt5682s_codec_conf), }; -static int mt8186_mt6366_rt1019_rt5682s_dev_probe(struct platform_device *pdev) +static int mt8186_mt6366_legacy_probe(struct mtk_soc_card_data *soc_card_data) { - struct snd_soc_card *card; + struct mtk_platform_card_data *card_data = soc_card_data->card_data; + struct snd_soc_card *card = card_data->card; + struct device *dev = card->dev; struct snd_soc_dai_link *dai_link; - struct mtk_soc_card_data *soc_card_data; - struct mt8186_mt6366_rt1019_rt5682s_priv *mach_priv; - struct device_node *platform_node, *headset_codec, *playback_codec, *adsp_node; - int sof_on = 0; + struct device_node *headset_codec, *playback_codec; int ret, i; - card = (struct snd_soc_card *)device_get_match_data(&pdev->dev); - if (!card) - return -EINVAL; - card->dev = &pdev->dev; - - soc_card_data = devm_kzalloc(&pdev->dev, sizeof(*soc_card_data), GFP_KERNEL); - if (!soc_card_data) - return -ENOMEM; - mach_priv = devm_kzalloc(&pdev->dev, sizeof(*mach_priv), GFP_KERNEL); - if (!mach_priv) - return -ENOMEM; - - soc_card_data->mach_priv = mach_priv; - - mach_priv->dmic_sel = devm_gpiod_get_optional(&pdev->dev, - "dmic", GPIOD_OUT_LOW); - if (IS_ERR(mach_priv->dmic_sel)) { - dev_err(&pdev->dev, "DMIC gpio failed err=%ld\n", - PTR_ERR(mach_priv->dmic_sel)); - return PTR_ERR(mach_priv->dmic_sel); - } - - adsp_node = of_parse_phandle(pdev->dev.of_node, "mediatek,adsp", 0); - if (adsp_node) { - struct mtk_sof_priv *sof_priv; + playback_codec = of_get_child_by_name(dev->of_node, "playback-codecs"); + if (!playback_codec) + return dev_err_probe(dev, -EINVAL, + "Property 'playback-codecs' missing or invalid\n"); - sof_priv = devm_kzalloc(&pdev->dev, sizeof(*sof_priv), GFP_KERNEL); - if (!sof_priv) { - ret = -ENOMEM; - goto err_adsp_node; - } - sof_priv->conn_streams = g_sof_conn_streams; - sof_priv->num_streams = ARRAY_SIZE(g_sof_conn_streams); - sof_priv->sof_dai_link_fixup = mt8186_sof_dai_link_fixup; - soc_card_data->sof_priv = sof_priv; - card->probe = mtk_sof_card_probe; - card->late_probe = mtk_sof_card_late_probe; - if (!card->topology_shortname_created) { - snprintf(card->topology_shortname, 32, "sof-%s", card->name); - card->topology_shortname_created = true; - } - card->name = card->topology_shortname; - sof_on = 1; - } else { - dev_dbg(&pdev->dev, "Probe without adsp\n"); - } - - if (of_property_read_bool(pdev->dev.of_node, "mediatek,dai-link")) { - ret = mtk_sof_dailink_parse_of(card, pdev->dev.of_node, - "mediatek,dai-link", - mt8186_mt6366_rt1019_rt5682s_dai_links, - ARRAY_SIZE(mt8186_mt6366_rt1019_rt5682s_dai_links)); - if (ret) { - dev_dbg(&pdev->dev, "Parse dai-link fail\n"); - goto err_adsp_node; - } - } else { - if (!sof_on) - card->num_links = ARRAY_SIZE(mt8186_mt6366_rt1019_rt5682s_dai_links) - - ARRAY_SIZE(g_sof_conn_streams); - } - - platform_node = of_parse_phandle(pdev->dev.of_node, "mediatek,platform", 0); - if (!platform_node) { - ret = -EINVAL; - dev_err_probe(&pdev->dev, ret, "Property 'platform' missing or invalid\n"); - goto err_platform_node; - } - - playback_codec = of_get_child_by_name(pdev->dev.of_node, "playback-codecs"); - if (!playback_codec) { - ret = -EINVAL; - dev_err_probe(&pdev->dev, ret, "Property 'playback-codecs' missing or invalid\n"); - goto err_playback_codec; - } - - headset_codec = of_get_child_by_name(pdev->dev.of_node, "headset-codec"); + headset_codec = of_get_child_by_name(dev->of_node, "headset-codec"); if (!headset_codec) { - ret = -EINVAL; - dev_err_probe(&pdev->dev, ret, "Property 'headset-codec' missing or invalid\n"); - goto err_headset_codec; + of_node_put(playback_codec); + return dev_err_probe(dev, -EINVAL, + "Property 'headset-codec' missing or invalid\n"); } for_each_card_prelinks(card, i, dai_link) { ret = mt8186_mt6366_card_set_be_link(card, dai_link, playback_codec, "I2S3"); if (ret) { - dev_err_probe(&pdev->dev, ret, "%s set playback_codec fail\n", + dev_err_probe(dev, ret, "%s set playback_codec fail\n", dai_link->name); - goto err_probe; + break; } ret = mt8186_mt6366_card_set_be_link(card, dai_link, headset_codec, "I2S0"); if (ret) { - dev_err_probe(&pdev->dev, ret, "%s set headset_codec fail\n", + dev_err_probe(dev, ret, "%s set headset_codec fail\n", dai_link->name); - goto err_probe; + break; } ret = mt8186_mt6366_card_set_be_link(card, dai_link, headset_codec, "I2S1"); if (ret) { - dev_err_probe(&pdev->dev, ret, "%s set headset_codec fail\n", + dev_err_probe(dev, ret, "%s set headset_codec fail\n", dai_link->name); - goto err_probe; + break; } + } + of_node_put(headset_codec); + of_node_put(playback_codec); - if (!strncmp(dai_link->name, "AFE_SOF", strlen("AFE_SOF")) && sof_on) - dai_link->platforms->of_node = adsp_node; + return ret; +} - if (!dai_link->platforms->name && !dai_link->platforms->of_node) - dai_link->platforms->of_node = platform_node; - } +static int mt8186_mt6366_soc_card_probe(struct mtk_soc_card_data *soc_card_data, bool legacy) +{ + struct mtk_platform_card_data *card_data = soc_card_data->card_data; + struct snd_soc_card *card = card_data->card; + struct mt8186_mt6366_rt1019_rt5682s_priv *mach_priv; + int ret; - snd_soc_card_set_drvdata(card, soc_card_data); + mach_priv = devm_kzalloc(card->dev, sizeof(*mach_priv), GFP_KERNEL); + if (!mach_priv) + return -ENOMEM; - ret = mt8186_afe_gpio_init(&pdev->dev); - if (ret) { - dev_err_probe(&pdev->dev, ret, "%s init gpio error\n", __func__); - goto err_probe; + soc_card_data->mach_priv = mach_priv; + + mach_priv->dmic_sel = devm_gpiod_get_optional(card->dev, + "dmic", GPIOD_OUT_LOW); + if (IS_ERR(mach_priv->dmic_sel)) + return dev_err_probe(card->dev, PTR_ERR(mach_priv->dmic_sel), + "DMIC gpio failed\n"); + + if (legacy) { + ret = mt8186_mt6366_legacy_probe(soc_card_data); + if (ret) + return ret; } - ret = devm_snd_soc_register_card(&pdev->dev, card); + ret = mt8186_afe_gpio_init(card->dev); if (ret) - dev_err_probe(&pdev->dev, ret, "%s snd_soc_register_card fail\n", __func__); + return dev_err_probe(card->dev, ret, "init AFE gpio error\n"); -err_probe: - of_node_put(headset_codec); -err_headset_codec: - of_node_put(playback_codec); -err_playback_codec: - of_node_put(platform_node); -err_platform_node: -err_adsp_node: - of_node_put(adsp_node); - - return ret; + return 0; } +static const struct mtk_sof_priv mt8186_sof_priv = { + .conn_streams = g_sof_conn_streams, + .num_streams = ARRAY_SIZE(g_sof_conn_streams), + .sof_dai_link_fixup = mt8186_sof_dai_link_fixup +}; + +static const struct mtk_soundcard_pdata mt8186_mt6366_rt1019_rt5682s_pdata = { + .card_data = &(struct mtk_platform_card_data) { + .card = &mt8186_mt6366_rt1019_rt5682s_soc_card, + .num_jacks = MT8186_JACK_MAX, + }, + .sof_priv = &mt8186_sof_priv, + .soc_probe = mt8186_mt6366_soc_card_probe +}; + +static const struct mtk_soundcard_pdata mt8186_mt6366_rt5682s_max98360_pdata = { + .card_data = &(struct mtk_platform_card_data) { + .card = &mt8186_mt6366_rt5682s_max98360_soc_card, + .num_jacks = MT8186_JACK_MAX, + }, + .sof_priv = &mt8186_sof_priv, + .soc_probe = mt8186_mt6366_soc_card_probe +}; + +static const struct mtk_soundcard_pdata mt8186_mt6366_rt5650_pdata = { + .card_data = &(struct mtk_platform_card_data) { + .card = &mt8186_mt6366_rt5650_soc_card, + .num_jacks = MT8186_JACK_MAX, + }, + .sof_priv = &mt8186_sof_priv, + .soc_probe = mt8186_mt6366_soc_card_probe +}; + #if IS_ENABLED(CONFIG_OF) static const struct of_device_id mt8186_mt6366_rt1019_rt5682s_dt_match[] = { { .compatible = "mediatek,mt8186-mt6366-rt1019-rt5682s-sound", - .data = &mt8186_mt6366_rt1019_rt5682s_soc_card, + .data = &mt8186_mt6366_rt1019_rt5682s_pdata, }, { .compatible = "mediatek,mt8186-mt6366-rt5682s-max98360-sound", - .data = &mt8186_mt6366_rt5682s_max98360_soc_card, + .data = &mt8186_mt6366_rt5682s_max98360_pdata, }, { .compatible = "mediatek,mt8186-mt6366-rt5650-sound", - .data = &mt8186_mt6366_rt5650_soc_card, + .data = &mt8186_mt6366_rt5650_pdata, }, {} }; @@ -1308,7 +1280,7 @@ static struct platform_driver mt8186_mt6366_rt1019_rt5682s_driver = { #endif .pm = &snd_soc_pm_ops, }, - .probe = mt8186_mt6366_rt1019_rt5682s_dev_probe, + .probe = mtk_soundcard_common_probe, }; module_platform_driver(mt8186_mt6366_rt1019_rt5682s_driver); -- cgit v1.2.3 From fe071237dee6d617e5cb0eb4856b23576a877479 Mon Sep 17 00:00:00 2001 From: AngeloGioacchino Del Regno Date: Tue, 16 Apr 2024 09:13:59 +0200 Subject: ASoC: mediatek: Add common snd_soc_ops .startup() callback MediaTek platforms are typically setting PCM rate and channels constraints for playback, capture and HDMI/DisplayPort playback: commonize the startup callback by adding the PCM constraints data to the mtk_platform_card_data structure and by reusing the common mtk_soundcard_startup() function for all of them by getting back the parameters from the aforementioned struct. Reviewed-by: Alexandre Mergnat Signed-off-by: AngeloGioacchino Del Regno Link: https://lore.kernel.org/r/20240416071410.75620-8-angelogioacchino.delregno@collabora.com Signed-off-by: Mark Brown --- sound/soc/mediatek/common/mtk-soundcard-driver.c | 51 ++++++++++++++++++++++++ sound/soc/mediatek/common/mtk-soundcard-driver.h | 24 +++++++++++ 2 files changed, 75 insertions(+) diff --git a/sound/soc/mediatek/common/mtk-soundcard-driver.c b/sound/soc/mediatek/common/mtk-soundcard-driver.c index b1db17e392d5..3bbf42c42805 100644 --- a/sound/soc/mediatek/common/mtk-soundcard-driver.c +++ b/sound/soc/mediatek/common/mtk-soundcard-driver.c @@ -139,6 +139,57 @@ void clean_card_reference(struct snd_soc_card *card) } EXPORT_SYMBOL_GPL(clean_card_reference); +int mtk_soundcard_startup(struct snd_pcm_substream *substream, + enum mtk_pcm_constraint_type ctype) +{ + struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream); + struct mtk_soc_card_data *soc_card = snd_soc_card_get_drvdata(rtd->card); + const struct mtk_pcm_constraints_data *mpc = &soc_card->card_data->pcm_constraints[ctype]; + int ret; + + if (unlikely(!mpc)) + return -EINVAL; + + ret = snd_pcm_hw_constraint_list(substream->runtime, 0, + SNDRV_PCM_HW_PARAM_RATE, + mpc->rates); + if (ret < 0) { + dev_err(rtd->dev, "hw_constraint_list rate failed\n"); + return ret; + } + + ret = snd_pcm_hw_constraint_list(substream->runtime, 0, + SNDRV_PCM_HW_PARAM_CHANNELS, + mpc->channels); + if (ret < 0) { + dev_err(rtd->dev, "hw_constraint_list channel failed\n"); + return ret; + } + + return 0; +} +EXPORT_SYMBOL_GPL(mtk_soundcard_startup); + +static int mtk_soundcard_playback_startup(struct snd_pcm_substream *substream) +{ + return mtk_soundcard_startup(substream, MTK_CONSTRAINT_PLAYBACK); +} + +const struct snd_soc_ops mtk_soundcard_common_playback_ops = { + .startup = mtk_soundcard_playback_startup, +}; +EXPORT_SYMBOL_GPL(mtk_soundcard_common_playback_ops); + +static int mtk_soundcard_capture_startup(struct snd_pcm_substream *substream) +{ + return mtk_soundcard_startup(substream, MTK_CONSTRAINT_CAPTURE); +} + +const struct snd_soc_ops mtk_soundcard_common_capture_ops = { + .startup = mtk_soundcard_capture_startup, +}; +EXPORT_SYMBOL_GPL(mtk_soundcard_common_capture_ops); + int mtk_soundcard_common_probe(struct platform_device *pdev) { struct device_node *platform_node, *adsp_node; diff --git a/sound/soc/mediatek/common/mtk-soundcard-driver.h b/sound/soc/mediatek/common/mtk-soundcard-driver.h index 4fd2ffb7e486..f6c275b54025 100644 --- a/sound/soc/mediatek/common/mtk-soundcard-driver.h +++ b/sound/soc/mediatek/common/mtk-soundcard-driver.h @@ -11,11 +11,26 @@ struct mtk_sof_priv; struct mtk_soc_card_data; +struct snd_pcm_hw_constraint_list; + +enum mtk_pcm_constraint_type { + MTK_CONSTRAINT_PLAYBACK, + MTK_CONSTRAINT_CAPTURE, + MTK_CONSTRAINT_HDMIDP, + MTK_CONSTRAINT_MAX +}; + +struct mtk_pcm_constraints_data { + const struct snd_pcm_hw_constraint_list *channels; + const struct snd_pcm_hw_constraint_list *rates; +}; struct mtk_platform_card_data { struct snd_soc_card *card; struct snd_soc_jack *jacks; + const struct mtk_pcm_constraints_data *pcm_constraints; u8 num_jacks; + u8 num_pcm_constraints; u8 flags; }; @@ -23,9 +38,18 @@ struct mtk_soundcard_pdata { const char *card_name; struct mtk_platform_card_data *card_data; const struct mtk_sof_priv *sof_priv; + int (*soc_probe)(struct mtk_soc_card_data *card_data, bool legacy); }; +/* Common playback/capture card startup ops */ +extern const struct snd_soc_ops mtk_soundcard_common_playback_ops; +extern const struct snd_soc_ops mtk_soundcard_common_capture_ops; + +/* Exported for custom/extended soundcard startup ops */ +int mtk_soundcard_startup(struct snd_pcm_substream *substream, + enum mtk_pcm_constraint_type ctype); + int parse_dai_link_info(struct snd_soc_card *card); void clean_card_reference(struct snd_soc_card *card); int mtk_soundcard_common_probe(struct platform_device *pdev); -- cgit v1.2.3 From 386fe4ceaf196360ef96cbd68d045ed2730251a7 Mon Sep 17 00:00:00 2001 From: AngeloGioacchino Del Regno Date: Tue, 16 Apr 2024 09:14:00 +0200 Subject: ASoC: mediatek: mt8195: Migrate to the common mtk_soundcard_startup Add a const mtk_pcm_constraints_data struct array with all of the (again, constant) constraints for all of the supported usecases, remove the duplicated functions and call mtk_soundcard_startup() instead in all of the .startup() callbacks. Reviewed-by: Alexandre Mergnat Signed-off-by: AngeloGioacchino Del Regno Link: https://lore.kernel.org/r/20240416071410.75620-9-angelogioacchino.delregno@collabora.com Signed-off-by: Mark Brown --- sound/soc/mediatek/mt8195/mt8195-mt6359.c | 195 ++++++++---------------------- 1 file changed, 53 insertions(+), 142 deletions(-) diff --git a/sound/soc/mediatek/mt8195/mt8195-mt6359.c b/sound/soc/mediatek/mt8195/mt8195-mt6359.c index f694618e7635..62e4e34cffbb 100644 --- a/sound/soc/mediatek/mt8195/mt8195-mt6359.c +++ b/sound/soc/mediatek/mt8195/mt8195-mt6359.c @@ -328,44 +328,7 @@ static int mt8195_mt6359_init(struct snd_soc_pcm_runtime *rtd) static int mt8195_hdmitx_dptx_startup(struct snd_pcm_substream *substream) { - static const unsigned int rates[] = { - 48000 - }; - static const unsigned int channels[] = { - 2, 4, 6, 8 - }; - static const struct snd_pcm_hw_constraint_list constraints_rates = { - .count = ARRAY_SIZE(rates), - .list = rates, - .mask = 0, - }; - static const struct snd_pcm_hw_constraint_list constraints_channels = { - .count = ARRAY_SIZE(channels), - .list = channels, - .mask = 0, - }; - - struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream); - struct snd_pcm_runtime *runtime = substream->runtime; - int ret; - - ret = snd_pcm_hw_constraint_list(runtime, 0, - SNDRV_PCM_HW_PARAM_RATE, - &constraints_rates); - if (ret < 0) { - dev_err(rtd->dev, "hw_constraint_list rate failed\n"); - return ret; - } - - ret = snd_pcm_hw_constraint_list(runtime, 0, - SNDRV_PCM_HW_PARAM_CHANNELS, - &constraints_channels); - if (ret < 0) { - dev_err(rtd->dev, "hw_constraint_list channel failed\n"); - return ret; - } - - return 0; + return mtk_soundcard_startup(substream, MTK_CONSTRAINT_HDMIDP); } static const struct snd_soc_ops mt8195_hdmitx_dptx_playback_ops = { @@ -428,98 +391,6 @@ static int mt8195_dptx_hw_params_fixup(struct snd_soc_pcm_runtime *rtd, return 0; } -static int mt8195_playback_startup(struct snd_pcm_substream *substream) -{ - static const unsigned int rates[] = { - 48000 - }; - static const unsigned int channels[] = { - 2 - }; - static const struct snd_pcm_hw_constraint_list constraints_rates = { - .count = ARRAY_SIZE(rates), - .list = rates, - .mask = 0, - }; - static const struct snd_pcm_hw_constraint_list constraints_channels = { - .count = ARRAY_SIZE(channels), - .list = channels, - .mask = 0, - }; - - struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream); - struct snd_pcm_runtime *runtime = substream->runtime; - int ret; - - ret = snd_pcm_hw_constraint_list(runtime, 0, - SNDRV_PCM_HW_PARAM_RATE, - &constraints_rates); - if (ret < 0) { - dev_err(rtd->dev, "hw_constraint_list rate failed\n"); - return ret; - } - - ret = snd_pcm_hw_constraint_list(runtime, 0, - SNDRV_PCM_HW_PARAM_CHANNELS, - &constraints_channels); - if (ret < 0) { - dev_err(rtd->dev, "hw_constraint_list channel failed\n"); - return ret; - } - - return 0; -} - -static const struct snd_soc_ops mt8195_playback_ops = { - .startup = mt8195_playback_startup, -}; - -static int mt8195_capture_startup(struct snd_pcm_substream *substream) -{ - static const unsigned int rates[] = { - 48000 - }; - static const unsigned int channels[] = { - 1, 2 - }; - static const struct snd_pcm_hw_constraint_list constraints_rates = { - .count = ARRAY_SIZE(rates), - .list = rates, - .mask = 0, - }; - static const struct snd_pcm_hw_constraint_list constraints_channels = { - .count = ARRAY_SIZE(channels), - .list = channels, - .mask = 0, - }; - - struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream); - struct snd_pcm_runtime *runtime = substream->runtime; - int ret; - - ret = snd_pcm_hw_constraint_list(runtime, 0, - SNDRV_PCM_HW_PARAM_RATE, - &constraints_rates); - if (ret < 0) { - dev_err(rtd->dev, "hw_constraint_list rate failed\n"); - return ret; - } - - ret = snd_pcm_hw_constraint_list(runtime, 0, - SNDRV_PCM_HW_PARAM_CHANNELS, - &constraints_channels); - if (ret < 0) { - dev_err(rtd->dev, "hw_constraint_list channel failed\n"); - return ret; - } - - return 0; -} - -static const struct snd_soc_ops mt8195_capture_ops = { - .startup = mt8195_capture_startup, -}; - static int mt8195_rt5682_etdm_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { @@ -1042,7 +913,7 @@ static struct snd_soc_dai_link mt8195_mt6359_dai_links[] = { }, .dynamic = 1, .dpcm_playback = 1, - .ops = &mt8195_playback_ops, + .ops = &mtk_soundcard_common_playback_ops, SND_SOC_DAILINK_REG(DL2_FE), }, [DAI_LINK_DL3_FE] = { @@ -1054,7 +925,7 @@ static struct snd_soc_dai_link mt8195_mt6359_dai_links[] = { }, .dynamic = 1, .dpcm_playback = 1, - .ops = &mt8195_playback_ops, + .ops = &mtk_soundcard_common_playback_ops, SND_SOC_DAILINK_REG(DL3_FE), }, [DAI_LINK_DL6_FE] = { @@ -1066,7 +937,7 @@ static struct snd_soc_dai_link mt8195_mt6359_dai_links[] = { }, .dynamic = 1, .dpcm_playback = 1, - .ops = &mt8195_playback_ops, + .ops = &mtk_soundcard_common_playback_ops, SND_SOC_DAILINK_REG(DL6_FE), }, [DAI_LINK_DL7_FE] = { @@ -1089,7 +960,7 @@ static struct snd_soc_dai_link mt8195_mt6359_dai_links[] = { }, .dynamic = 1, .dpcm_playback = 1, - .ops = &mt8195_playback_ops, + .ops = &mtk_soundcard_common_playback_ops, SND_SOC_DAILINK_REG(DL8_FE), }, [DAI_LINK_DL10_FE] = { @@ -1113,7 +984,7 @@ static struct snd_soc_dai_link mt8195_mt6359_dai_links[] = { }, .dynamic = 1, .dpcm_playback = 1, - .ops = &mt8195_playback_ops, + .ops = &mtk_soundcard_common_playback_ops, SND_SOC_DAILINK_REG(DL11_FE), }, [DAI_LINK_UL1_FE] = { @@ -1136,7 +1007,7 @@ static struct snd_soc_dai_link mt8195_mt6359_dai_links[] = { }, .dynamic = 1, .dpcm_capture = 1, - .ops = &mt8195_capture_ops, + .ops = &mtk_soundcard_common_capture_ops, SND_SOC_DAILINK_REG(UL2_FE), }, [DAI_LINK_UL3_FE] = { @@ -1148,7 +1019,7 @@ static struct snd_soc_dai_link mt8195_mt6359_dai_links[] = { }, .dynamic = 1, .dpcm_capture = 1, - .ops = &mt8195_capture_ops, + .ops = &mtk_soundcard_common_capture_ops, SND_SOC_DAILINK_REG(UL3_FE), }, [DAI_LINK_UL4_FE] = { @@ -1160,7 +1031,7 @@ static struct snd_soc_dai_link mt8195_mt6359_dai_links[] = { }, .dynamic = 1, .dpcm_capture = 1, - .ops = &mt8195_capture_ops, + .ops = &mtk_soundcard_common_capture_ops, SND_SOC_DAILINK_REG(UL4_FE), }, [DAI_LINK_UL5_FE] = { @@ -1172,7 +1043,7 @@ static struct snd_soc_dai_link mt8195_mt6359_dai_links[] = { }, .dynamic = 1, .dpcm_capture = 1, - .ops = &mt8195_capture_ops, + .ops = &mtk_soundcard_common_capture_ops, SND_SOC_DAILINK_REG(UL5_FE), }, [DAI_LINK_UL6_FE] = { @@ -1195,7 +1066,7 @@ static struct snd_soc_dai_link mt8195_mt6359_dai_links[] = { }, .dynamic = 1, .dpcm_capture = 1, - .ops = &mt8195_capture_ops, + .ops = &mtk_soundcard_common_capture_ops, SND_SOC_DAILINK_REG(UL8_FE), }, [DAI_LINK_UL9_FE] = { @@ -1207,7 +1078,7 @@ static struct snd_soc_dai_link mt8195_mt6359_dai_links[] = { }, .dynamic = 1, .dpcm_capture = 1, - .ops = &mt8195_capture_ops, + .ops = &mtk_soundcard_common_capture_ops, SND_SOC_DAILINK_REG(UL9_FE), }, [DAI_LINK_UL10_FE] = { @@ -1219,7 +1090,7 @@ static struct snd_soc_dai_link mt8195_mt6359_dai_links[] = { }, .dynamic = 1, .dpcm_capture = 1, - .ops = &mt8195_capture_ops, + .ops = &mtk_soundcard_common_capture_ops, SND_SOC_DAILINK_REG(UL10_FE), }, /* BE */ @@ -1561,6 +1432,40 @@ static int mt8195_mt6359_soc_card_probe(struct mtk_soc_card_data *soc_card_data, return 0; } +static const unsigned int mt8195_pcm_playback_channels[] = { 2 }; +static const unsigned int mt8195_pcm_capture_channels[] = { 1, 2 }; +static const unsigned int mt8195_pcm_hdmidp_channels[] = { 2, 4, 6, 8 }; +static const unsigned int mt8195_pcm_rates[] = { 48000 }; + +static const struct snd_pcm_hw_constraint_list mt8195_rate_constraint = { + .list = mt8195_pcm_rates, + .count = ARRAY_SIZE(mt8195_pcm_rates) +}; + +static const struct mtk_pcm_constraints_data mt8195_pcm_constraints[MTK_CONSTRAINT_HDMIDP + 1] = { + [MTK_CONSTRAINT_PLAYBACK] = { + .channels = &(const struct snd_pcm_hw_constraint_list) { + .list = mt8195_pcm_playback_channels, + .count = ARRAY_SIZE(mt8195_pcm_playback_channels) + }, + .rates = &mt8195_rate_constraint, + }, + [MTK_CONSTRAINT_CAPTURE] = { + .channels = &(const struct snd_pcm_hw_constraint_list) { + .list = mt8195_pcm_capture_channels, + .count = ARRAY_SIZE(mt8195_pcm_capture_channels) + }, + .rates = &mt8195_rate_constraint, + }, + [MTK_CONSTRAINT_HDMIDP] = { + .channels = &(const struct snd_pcm_hw_constraint_list) { + .list = mt8195_pcm_hdmidp_channels, + .count = ARRAY_SIZE(mt8195_pcm_hdmidp_channels) + }, + .rates = &mt8195_rate_constraint, + }, +}; + static const struct mtk_sof_priv mt8195_sof_priv = { .conn_streams = g_sof_conn_streams, .num_streams = ARRAY_SIZE(g_sof_conn_streams), @@ -1572,6 +1477,8 @@ static const struct mtk_soundcard_pdata mt8195_mt6359_rt1019_rt5682_card = { .card_data = &(struct mtk_platform_card_data) { .card = &mt8195_mt6359_soc_card, .num_jacks = MT8195_JACK_MAX, + .pcm_constraints = mt8195_pcm_constraints, + .num_pcm_constraints = ARRAY_SIZE(mt8195_pcm_constraints), .flags = RT1019_SPEAKER_AMP_PRESENT }, .sof_priv = &mt8195_sof_priv, @@ -1583,6 +1490,8 @@ static const struct mtk_soundcard_pdata mt8195_mt6359_rt1011_rt5682_card = { .card_data = &(struct mtk_platform_card_data) { .card = &mt8195_mt6359_soc_card, .num_jacks = MT8195_JACK_MAX, + .pcm_constraints = mt8195_pcm_constraints, + .num_pcm_constraints = ARRAY_SIZE(mt8195_pcm_constraints), .flags = RT1011_SPEAKER_AMP_PRESENT }, .sof_priv = &mt8195_sof_priv, @@ -1594,6 +1503,8 @@ static const struct mtk_soundcard_pdata mt8195_mt6359_max98390_rt5682_card = { .card_data = &(struct mtk_platform_card_data) { .card = &mt8195_mt6359_soc_card, .num_jacks = MT8195_JACK_MAX, + .pcm_constraints = mt8195_pcm_constraints, + .num_pcm_constraints = ARRAY_SIZE(mt8195_pcm_constraints), .flags = MAX98390_SPEAKER_AMP_PRESENT }, .sof_priv = &mt8195_sof_priv, -- cgit v1.2.3 From 94142cc1ffd959aa8e83857515a75779e8ba8064 Mon Sep 17 00:00:00 2001 From: AngeloGioacchino Del Regno Date: Tue, 16 Apr 2024 09:14:01 +0200 Subject: ASoC: mediatek: mt8192: Migrate to the common mtk_soundcard_startup Add a const mtk_pcm_constraints_data struct array with all of the (again, constant) constraints for all of the supported usecases, remove the duplicated functions and call mtk_soundcard_startup() instead in all of the .startup() callbacks. Reviewed-by: Alexandre Mergnat Signed-off-by: AngeloGioacchino Del Regno Link: https://lore.kernel.org/r/20240416071410.75620-10-angelogioacchino.delregno@collabora.com Signed-off-by: Mark Brown --- .../mediatek/mt8192/mt8192-mt6359-rt1015-rt5682.c | 139 ++++++--------------- 1 file changed, 41 insertions(+), 98 deletions(-) diff --git a/sound/soc/mediatek/mt8192/mt8192-mt6359-rt1015-rt5682.c b/sound/soc/mediatek/mt8192/mt8192-mt6359-rt1015-rt5682.c index 645bc1aa67c7..8b323fb19925 100644 --- a/sound/soc/mediatek/mt8192/mt8192-mt6359-rt1015-rt5682.c +++ b/sound/soc/mediatek/mt8192/mt8192-mt6359-rt1015-rt5682.c @@ -389,100 +389,6 @@ static int mt8192_i2s_hw_params_fixup(struct snd_soc_pcm_runtime *rtd, return 0; } -static int -mt8192_mt6359_cap1_startup(struct snd_pcm_substream *substream) -{ - static const unsigned int channels[] = { - 1, 2, 4 - }; - static const struct snd_pcm_hw_constraint_list constraints_channels = { - .count = ARRAY_SIZE(channels), - .list = channels, - .mask = 0, - }; - static const unsigned int rates[] = { - 8000, 16000, 32000, 48000, 96000, 192000 - }; - static const struct snd_pcm_hw_constraint_list constraints_rates = { - .count = ARRAY_SIZE(rates), - .list = rates, - .mask = 0, - }; - - struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream); - struct snd_pcm_runtime *runtime = substream->runtime; - int ret; - - ret = snd_pcm_hw_constraint_list(runtime, 0, - SNDRV_PCM_HW_PARAM_CHANNELS, - &constraints_channels); - if (ret < 0) { - dev_err(rtd->dev, "hw_constraint_list channels failed\n"); - return ret; - } - - ret = snd_pcm_hw_constraint_list(runtime, 0, - SNDRV_PCM_HW_PARAM_RATE, - &constraints_rates); - if (ret < 0) { - dev_err(rtd->dev, "hw_constraint_list rate failed\n"); - return ret; - } - - return 0; -} - -static const struct snd_soc_ops mt8192_mt6359_capture1_ops = { - .startup = mt8192_mt6359_cap1_startup, -}; - -static int -mt8192_mt6359_rt5682_startup(struct snd_pcm_substream *substream) -{ - static const unsigned int channels[] = { - 1, 2 - }; - static const struct snd_pcm_hw_constraint_list constraints_channels = { - .count = ARRAY_SIZE(channels), - .list = channels, - .mask = 0, - }; - static const unsigned int rates[] = { - 48000 - }; - static const struct snd_pcm_hw_constraint_list constraints_rates = { - .count = ARRAY_SIZE(rates), - .list = rates, - .mask = 0, - }; - - struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream); - struct snd_pcm_runtime *runtime = substream->runtime; - int ret; - - ret = snd_pcm_hw_constraint_list(runtime, 0, - SNDRV_PCM_HW_PARAM_CHANNELS, - &constraints_channels); - if (ret < 0) { - dev_err(rtd->dev, "hw_constraint_list channels failed\n"); - return ret; - } - - ret = snd_pcm_hw_constraint_list(runtime, 0, - SNDRV_PCM_HW_PARAM_RATE, - &constraints_rates); - if (ret < 0) { - dev_err(rtd->dev, "hw_constraint_list rate failed\n"); - return ret; - } - - return 0; -} - -static const struct snd_soc_ops mt8192_mt6359_rt5682_ops = { - .startup = mt8192_mt6359_rt5682_startup, -}; - /* FE */ SND_SOC_DAILINK_DEFS(playback1, DAILINK_COMP_ARRAY(COMP_CPU("DL1")), @@ -720,7 +626,7 @@ static struct snd_soc_dai_link mt8192_mt6359_dai_links[] = { SND_SOC_DPCM_TRIGGER_PRE}, .dynamic = 1, .dpcm_playback = 1, - .ops = &mt8192_mt6359_rt5682_ops, + .ops = &mtk_soundcard_common_playback_ops, SND_SOC_DAILINK_REG(playback3), }, { @@ -784,7 +690,7 @@ static struct snd_soc_dai_link mt8192_mt6359_dai_links[] = { SND_SOC_DPCM_TRIGGER_PRE}, .dynamic = 1, .dpcm_capture = 1, - .ops = &mt8192_mt6359_capture1_ops, + .ops = &mtk_soundcard_common_capture_ops, SND_SOC_DAILINK_REG(capture1), }, { @@ -794,7 +700,7 @@ static struct snd_soc_dai_link mt8192_mt6359_dai_links[] = { SND_SOC_DPCM_TRIGGER_PRE}, .dynamic = 1, .dpcm_capture = 1, - .ops = &mt8192_mt6359_rt5682_ops, + .ops = &mtk_soundcard_common_playback_ops, SND_SOC_DAILINK_REG(capture2), }, { @@ -1146,7 +1052,7 @@ static int mt8192_mt6359_legacy_probe(struct mtk_soc_card_data *soc_card_data) struct device *dev = card->dev; struct device_node *hdmi_codec, *headset_codec, *speaker_codec; struct snd_soc_dai_link *dai_link; - int ret, i; + int i, ret = 0; hdmi_codec = of_parse_phandle(dev->of_node, "mediatek,hdmi-codec", 0); if (!hdmi_codec) @@ -1235,11 +1141,44 @@ static int mt8192_mt6359_soc_card_probe(struct mtk_soc_card_data *soc_card_data, return 0; } +static const unsigned int mt8192_pcm_playback_channels[] = { 1, 2 }; +static const unsigned int mt8192_pcm_playback_rates[] = { 48000 }; + +static const unsigned int mt8192_pcm_capture_channels[] = { 1, 2, 4 }; +static const unsigned int mt8192_pcm_capture_rates[] = { + 8000, 16000, 32000, 48000, 96000, 192000 +}; + +static const struct mtk_pcm_constraints_data mt8192_pcm_constraints[MTK_CONSTRAINT_CAPTURE + 1] = { + [MTK_CONSTRAINT_PLAYBACK] = { + .channels = &(const struct snd_pcm_hw_constraint_list) { + .list = mt8192_pcm_playback_channels, + .count = ARRAY_SIZE(mt8192_pcm_playback_channels) + }, + .rates = &(const struct snd_pcm_hw_constraint_list) { + .list = mt8192_pcm_playback_rates, + .count = ARRAY_SIZE(mt8192_pcm_playback_rates) + } + }, + [MTK_CONSTRAINT_CAPTURE] = { + .channels = &(const struct snd_pcm_hw_constraint_list) { + .list = mt8192_pcm_capture_channels, + .count = ARRAY_SIZE(mt8192_pcm_capture_channels) + }, + .rates = &(const struct snd_pcm_hw_constraint_list) { + .list = mt8192_pcm_capture_rates, + .count = ARRAY_SIZE(mt8192_pcm_capture_rates) + } + } +}; + static const struct mtk_soundcard_pdata mt8192_mt6359_rt1015_rt5682_pdata = { .card_name = RT1015_RT5682_CARD_NAME, .card_data = &(struct mtk_platform_card_data) { .card = &mt8192_mt6359_rt1015_rt5682_card, .num_jacks = MT8192_JACK_MAX, + .pcm_constraints = mt8192_pcm_constraints, + .num_pcm_constraints = ARRAY_SIZE(mt8192_pcm_constraints), }, .soc_probe = mt8192_mt6359_soc_card_probe }; @@ -1249,6 +1188,8 @@ static const struct mtk_soundcard_pdata mt8192_mt6359_rt1015p_rt5682_pdata = { .card_data = &(struct mtk_platform_card_data) { .card = &mt8192_mt6359_rt1015p_rt5682x_card, .num_jacks = MT8192_JACK_MAX, + .pcm_constraints = mt8192_pcm_constraints, + .num_pcm_constraints = ARRAY_SIZE(mt8192_pcm_constraints), }, .soc_probe = mt8192_mt6359_soc_card_probe }; @@ -1258,6 +1199,8 @@ static const struct mtk_soundcard_pdata mt8192_mt6359_rt1015p_rt5682s_pdata = { .card_data = &(struct mtk_platform_card_data) { .card = &mt8192_mt6359_rt1015p_rt5682x_card, .num_jacks = MT8192_JACK_MAX, + .pcm_constraints = mt8192_pcm_constraints, + .num_pcm_constraints = ARRAY_SIZE(mt8192_pcm_constraints), }, .soc_probe = mt8192_mt6359_soc_card_probe }; -- cgit v1.2.3 From f103ce4ff6932b6991e1922d1a39c29971ab2938 Mon Sep 17 00:00:00 2001 From: AngeloGioacchino Del Regno Date: Tue, 16 Apr 2024 09:14:02 +0200 Subject: ASoC: mediatek: mt8186-rt1019: Migrate to the common mtk_soundcard_startup Add a const mtk_pcm_constraints_data struct array with all of the (again, constant) constraints for all of the supported usecases, remove the duplicated functions and call mtk_soundcard_startup() instead in all of the .startup() callbacks. Signed-off-by: AngeloGioacchino Del Regno Link: https://lore.kernel.org/r/20240416071410.75620-11-angelogioacchino.delregno@collabora.com Signed-off-by: Mark Brown --- .../mediatek/mt8186/mt8186-mt6366-rt1019-rt5682s.c | 132 ++++++--------------- 1 file changed, 36 insertions(+), 96 deletions(-) diff --git a/sound/soc/mediatek/mt8186/mt8186-mt6366-rt1019-rt5682s.c b/sound/soc/mediatek/mt8186/mt8186-mt6366-rt1019-rt5682s.c index f8856a100b27..28140ca0ebff 100644 --- a/sound/soc/mediatek/mt8186/mt8186-mt6366-rt1019-rt5682s.c +++ b/sound/soc/mediatek/mt8186/mt8186-mt6366-rt1019-rt5682s.c @@ -332,98 +332,6 @@ static int mt8186_sof_dai_link_fixup(struct snd_soc_pcm_runtime *rtd, return ret; } -static int mt8186_mt6366_rt1019_rt5682s_playback_startup(struct snd_pcm_substream *substream) -{ - static const unsigned int rates[] = { - 48000 - }; - static const unsigned int channels[] = { - 2 - }; - static const struct snd_pcm_hw_constraint_list constraints_rates = { - .count = ARRAY_SIZE(rates), - .list = rates, - .mask = 0, - }; - static const struct snd_pcm_hw_constraint_list constraints_channels = { - .count = ARRAY_SIZE(channels), - .list = channels, - .mask = 0, - }; - - struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream); - struct snd_pcm_runtime *runtime = substream->runtime; - int ret; - - ret = snd_pcm_hw_constraint_list(runtime, 0, - SNDRV_PCM_HW_PARAM_RATE, - &constraints_rates); - if (ret < 0) { - dev_err(rtd->dev, "hw_constraint_list rate failed\n"); - return ret; - } - - ret = snd_pcm_hw_constraint_list(runtime, 0, - SNDRV_PCM_HW_PARAM_CHANNELS, - &constraints_channels); - if (ret < 0) { - dev_err(rtd->dev, "hw_constraint_list channel failed\n"); - return ret; - } - - return 0; -} - -static const struct snd_soc_ops mt8186_mt6366_rt1019_rt5682s_playback_ops = { - .startup = mt8186_mt6366_rt1019_rt5682s_playback_startup, -}; - -static int mt8186_mt6366_rt1019_rt5682s_capture_startup(struct snd_pcm_substream *substream) -{ - static const unsigned int rates[] = { - 48000 - }; - static const unsigned int channels[] = { - 1, 2 - }; - static const struct snd_pcm_hw_constraint_list constraints_rates = { - .count = ARRAY_SIZE(rates), - .list = rates, - .mask = 0, - }; - static const struct snd_pcm_hw_constraint_list constraints_channels = { - .count = ARRAY_SIZE(channels), - .list = channels, - .mask = 0, - }; - - struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream); - struct snd_pcm_runtime *runtime = substream->runtime; - int ret; - - ret = snd_pcm_hw_constraint_list(runtime, 0, - SNDRV_PCM_HW_PARAM_RATE, - &constraints_rates); - if (ret < 0) { - dev_err(rtd->dev, "hw_constraint_list rate failed\n"); - return ret; - } - - ret = snd_pcm_hw_constraint_list(runtime, 0, - SNDRV_PCM_HW_PARAM_CHANNELS, - &constraints_channels); - if (ret < 0) { - dev_err(rtd->dev, "hw_constraint_list channel failed\n"); - return ret; - } - - return 0; -} - -static const struct snd_soc_ops mt8186_mt6366_rt1019_rt5682s_capture_ops = { - .startup = mt8186_mt6366_rt1019_rt5682s_capture_startup, -}; - /* FE */ SND_SOC_DAILINK_DEFS(playback1, DAILINK_COMP_ARRAY(COMP_CPU("DL1")), @@ -644,7 +552,7 @@ static struct snd_soc_dai_link mt8186_mt6366_rt1019_rt5682s_dai_links[] = { .dpcm_merged_format = 1, .dpcm_merged_chan = 1, .dpcm_merged_rate = 1, - .ops = &mt8186_mt6366_rt1019_rt5682s_playback_ops, + .ops = &mtk_soundcard_common_playback_ops, SND_SOC_DAILINK_REG(playback1), }, { @@ -678,7 +586,7 @@ static struct snd_soc_dai_link mt8186_mt6366_rt1019_rt5682s_dai_links[] = { .dpcm_merged_format = 1, .dpcm_merged_chan = 1, .dpcm_merged_rate = 1, - .ops = &mt8186_mt6366_rt1019_rt5682s_playback_ops, + .ops = &mtk_soundcard_common_playback_ops, SND_SOC_DAILINK_REG(playback3), }, { @@ -745,7 +653,7 @@ static struct snd_soc_dai_link mt8186_mt6366_rt1019_rt5682s_dai_links[] = { .dpcm_merged_format = 1, .dpcm_merged_chan = 1, .dpcm_merged_rate = 1, - .ops = &mt8186_mt6366_rt1019_rt5682s_capture_ops, + .ops = &mtk_soundcard_common_capture_ops, SND_SOC_DAILINK_REG(capture2), }, { @@ -767,7 +675,7 @@ static struct snd_soc_dai_link mt8186_mt6366_rt1019_rt5682s_dai_links[] = { .dpcm_merged_format = 1, .dpcm_merged_chan = 1, .dpcm_merged_rate = 1, - .ops = &mt8186_mt6366_rt1019_rt5682s_capture_ops, + .ops = &mtk_soundcard_common_capture_ops, SND_SOC_DAILINK_REG(capture4), }, { @@ -1220,6 +1128,32 @@ static int mt8186_mt6366_soc_card_probe(struct mtk_soc_card_data *soc_card_data, return 0; } +static const unsigned int mt8186_pcm_playback_channels[] = { 2 }; +static const unsigned int mt8186_pcm_capture_channels[] = { 1, 2 }; +static const unsigned int mt8186_pcm_rates[] = { 48000 }; + +static const struct snd_pcm_hw_constraint_list mt8186_rate_constraint = { + .list = mt8186_pcm_rates, + .count = ARRAY_SIZE(mt8186_pcm_rates) +}; + +static const struct mtk_pcm_constraints_data mt8186_pcm_constraints[MTK_CONSTRAINT_CAPTURE + 1] = { + [MTK_CONSTRAINT_PLAYBACK] = { + .channels = &(const struct snd_pcm_hw_constraint_list) { + .list = mt8186_pcm_playback_channels, + .count = ARRAY_SIZE(mt8186_pcm_playback_channels) + }, + .rates = &mt8186_rate_constraint, + }, + [MTK_CONSTRAINT_CAPTURE] = { + .channels = &(const struct snd_pcm_hw_constraint_list) { + .list = mt8186_pcm_capture_channels, + .count = ARRAY_SIZE(mt8186_pcm_capture_channels) + }, + .rates = &mt8186_rate_constraint, + } +}; + static const struct mtk_sof_priv mt8186_sof_priv = { .conn_streams = g_sof_conn_streams, .num_streams = ARRAY_SIZE(g_sof_conn_streams), @@ -1230,6 +1164,8 @@ static const struct mtk_soundcard_pdata mt8186_mt6366_rt1019_rt5682s_pdata = { .card_data = &(struct mtk_platform_card_data) { .card = &mt8186_mt6366_rt1019_rt5682s_soc_card, .num_jacks = MT8186_JACK_MAX, + .pcm_constraints = mt8186_pcm_constraints, + .num_pcm_constraints = ARRAY_SIZE(mt8186_pcm_constraints), }, .sof_priv = &mt8186_sof_priv, .soc_probe = mt8186_mt6366_soc_card_probe @@ -1239,6 +1175,8 @@ static const struct mtk_soundcard_pdata mt8186_mt6366_rt5682s_max98360_pdata = { .card_data = &(struct mtk_platform_card_data) { .card = &mt8186_mt6366_rt5682s_max98360_soc_card, .num_jacks = MT8186_JACK_MAX, + .pcm_constraints = mt8186_pcm_constraints, + .num_pcm_constraints = ARRAY_SIZE(mt8186_pcm_constraints), }, .sof_priv = &mt8186_sof_priv, .soc_probe = mt8186_mt6366_soc_card_probe @@ -1248,6 +1186,8 @@ static const struct mtk_soundcard_pdata mt8186_mt6366_rt5650_pdata = { .card_data = &(struct mtk_platform_card_data) { .card = &mt8186_mt6366_rt5650_soc_card, .num_jacks = MT8186_JACK_MAX, + .pcm_constraints = mt8186_pcm_constraints, + .num_pcm_constraints = ARRAY_SIZE(mt8186_pcm_constraints), }, .sof_priv = &mt8186_sof_priv, .soc_probe = mt8186_mt6366_soc_card_probe -- cgit v1.2.3 From 9d9b182876a249b393158e9f43c255aeee4ef898 Mon Sep 17 00:00:00 2001 From: AngeloGioacchino Del Regno Date: Tue, 16 Apr 2024 09:14:03 +0200 Subject: ASoC: mediatek: Add common mtk_afe_component_probe callback Multiple MediaTek AFE PCM component drivers are using their own .probe() callback, but most of those are simply duplicated functions as they are doing exactly the same thing over and over. Add a common probe callback for this component to reduce duplication. Reviewed-by: Alexandre Mergnat Signed-off-by: AngeloGioacchino Del Regno Link: https://lore.kernel.org/r/20240416071410.75620-12-angelogioacchino.delregno@collabora.com Signed-off-by: Mark Brown --- sound/soc/mediatek/common/mtk-afe-platform-driver.c | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/sound/soc/mediatek/common/mtk-afe-platform-driver.c b/sound/soc/mediatek/common/mtk-afe-platform-driver.c index 32edcb6d5219..9b72b2a7ae91 100644 --- a/sound/soc/mediatek/common/mtk-afe-platform-driver.c +++ b/sound/soc/mediatek/common/mtk-afe-platform-driver.c @@ -126,10 +126,28 @@ int mtk_afe_pcm_new(struct snd_soc_component *component, } EXPORT_SYMBOL_GPL(mtk_afe_pcm_new); +static int mtk_afe_component_probe(struct snd_soc_component *component) +{ + struct mtk_base_afe *afe = snd_soc_component_get_drvdata(component); + int ret; + + snd_soc_component_init_regmap(component, afe->regmap); + + /* If the list was never initialized there are no sub-DAIs */ + if (afe->sub_dais.next && afe->sub_dais.prev) { + ret = mtk_afe_add_sub_dai_control(component); + if (ret) + return ret; + } + + return 0; +} + const struct snd_soc_component_driver mtk_afe_pcm_platform = { .name = AFE_PCM_NAME, .pointer = mtk_afe_pcm_pointer, .pcm_construct = mtk_afe_pcm_new, + .probe = mtk_afe_component_probe, }; EXPORT_SYMBOL_GPL(mtk_afe_pcm_platform); -- cgit v1.2.3 From 1d2a6b3b5189b6c3e51f29e050aa9b2337b774e8 Mon Sep 17 00:00:00 2001 From: AngeloGioacchino Del Regno Date: Tue, 16 Apr 2024 09:14:04 +0200 Subject: ASoC: mediatek: Use common mtk_afe_pcm_platform with common probe cb Since the mtk-afe-platform-driver generic mtk_afe_pcm_platform now has a common .probe() callback, there is no reason to keep duplicating this function over and over in the SoC specific AFE-PCM drivers: switch over to register with the common bits instead. Note that MT8186 was left out of this because it is registering some extra sinegen controls in the AFE-PCM probe callback and needs extra cleanups to be able to use the common bits. Reviewed-by: Alexandre Mergnat Signed-off-by: AngeloGioacchino Del Regno Link: https://lore.kernel.org/r/20240416071410.75620-13-angelogioacchino.delregno@collabora.com Signed-off-by: Mark Brown --- sound/soc/mediatek/mt6797/mt6797-afe-pcm.c | 14 +------------- sound/soc/mediatek/mt7986/mt7986-afe-pcm.c | 14 +------------- sound/soc/mediatek/mt8183/mt8183-afe-pcm.c | 14 +------------- sound/soc/mediatek/mt8188/mt8188-afe-pcm.c | 21 +-------------------- sound/soc/mediatek/mt8192/mt8192-afe-pcm.c | 25 ++----------------------- sound/soc/mediatek/mt8195/mt8195-afe-pcm.c | 21 +-------------------- 6 files changed, 7 insertions(+), 102 deletions(-) diff --git a/sound/soc/mediatek/mt6797/mt6797-afe-pcm.c b/sound/soc/mediatek/mt6797/mt6797-afe-pcm.c index da7267c684b1..c1dee119e93a 100644 --- a/sound/soc/mediatek/mt6797/mt6797-afe-pcm.c +++ b/sound/soc/mediatek/mt6797/mt6797-afe-pcm.c @@ -704,18 +704,6 @@ static int mt6797_afe_runtime_resume(struct device *dev) return 0; } -static int mt6797_afe_component_probe(struct snd_soc_component *component) -{ - return mtk_afe_add_sub_dai_control(component); -} - -static const struct snd_soc_component_driver mt6797_afe_component = { - .name = AFE_PCM_NAME, - .probe = mt6797_afe_component_probe, - .pointer = mtk_afe_pcm_pointer, - .pcm_construct = mtk_afe_pcm_new, -}; - static int mt6797_dai_memif_register(struct mtk_base_afe *afe) { struct mtk_base_afe_dai *dai; @@ -852,7 +840,7 @@ static int mt6797_afe_pcm_dev_probe(struct platform_device *pdev) pm_runtime_get_sync(&pdev->dev); /* register component */ - ret = devm_snd_soc_register_component(dev, &mt6797_afe_component, + ret = devm_snd_soc_register_component(dev, &mtk_afe_pcm_platform, NULL, 0); if (ret) { dev_warn(dev, "err_platform\n"); diff --git a/sound/soc/mediatek/mt7986/mt7986-afe-pcm.c b/sound/soc/mediatek/mt7986/mt7986-afe-pcm.c index d497e1129889..c1c486e275b9 100644 --- a/sound/soc/mediatek/mt7986/mt7986-afe-pcm.c +++ b/sound/soc/mediatek/mt7986/mt7986-afe-pcm.c @@ -429,18 +429,6 @@ static int mt7986_afe_runtime_resume(struct device *dev) return 0; } -static int mt7986_afe_component_probe(struct snd_soc_component *component) -{ - return mtk_afe_add_sub_dai_control(component); -} - -static const struct snd_soc_component_driver mt7986_afe_component = { - .name = AFE_PCM_NAME, - .probe = mt7986_afe_component_probe, - .pointer = mtk_afe_pcm_pointer, - .pcm_construct = mtk_afe_pcm_new, -}; - static int mt7986_dai_memif_register(struct mtk_base_afe *afe) { struct mtk_base_afe_dai *dai; @@ -573,7 +561,7 @@ static int mt7986_afe_pcm_dev_probe(struct platform_device *pdev) /* register component */ ret = devm_snd_soc_register_component(&pdev->dev, - &mt7986_afe_component, + &mtk_afe_pcm_platform, NULL, 0); if (ret) return dev_err_probe(dev, ret, "Cannot register AFE component\n"); diff --git a/sound/soc/mediatek/mt8183/mt8183-afe-pcm.c b/sound/soc/mediatek/mt8183/mt8183-afe-pcm.c index 9e432ed9124b..25348fdf75fa 100644 --- a/sound/soc/mediatek/mt8183/mt8183-afe-pcm.c +++ b/sound/soc/mediatek/mt8183/mt8183-afe-pcm.c @@ -1042,18 +1042,6 @@ skip_regmap: return 0; } -static int mt8183_afe_component_probe(struct snd_soc_component *component) -{ - return mtk_afe_add_sub_dai_control(component); -} - -static const struct snd_soc_component_driver mt8183_afe_component = { - .name = AFE_PCM_NAME, - .probe = mt8183_afe_component_probe, - .pointer = mtk_afe_pcm_pointer, - .pcm_construct = mtk_afe_pcm_new, -}; - static int mt8183_dai_memif_register(struct mtk_base_afe *afe) { struct mtk_base_afe_dai *dai; @@ -1232,7 +1220,7 @@ static int mt8183_afe_pcm_dev_probe(struct platform_device *pdev) /* register component */ ret = devm_snd_soc_register_component(&pdev->dev, - &mt8183_afe_component, + &mtk_afe_pcm_platform, NULL, 0); if (ret) { dev_warn(dev, "err_platform\n"); diff --git a/sound/soc/mediatek/mt8188/mt8188-afe-pcm.c b/sound/soc/mediatek/mt8188/mt8188-afe-pcm.c index 46d6a5540403..9647fe133dc8 100644 --- a/sound/soc/mediatek/mt8188/mt8188-afe-pcm.c +++ b/sound/soc/mediatek/mt8188/mt8188-afe-pcm.c @@ -3030,25 +3030,6 @@ skip_regmap: return 0; } -static int mt8188_afe_component_probe(struct snd_soc_component *component) -{ - struct mtk_base_afe *afe = snd_soc_component_get_drvdata(component); - int ret; - - snd_soc_component_init_regmap(component, afe->regmap); - - ret = mtk_afe_add_sub_dai_control(component); - - return ret; -} - -static const struct snd_soc_component_driver mt8188_afe_component = { - .name = AFE_PCM_NAME, - .pointer = mtk_afe_pcm_pointer, - .pcm_construct = mtk_afe_pcm_new, - .probe = mt8188_afe_component_probe, -}; - static int init_memif_priv_data(struct mtk_base_afe *afe) { struct mt8188_afe_private *afe_priv = afe->platform_priv; @@ -3350,7 +3331,7 @@ static int mt8188_afe_pcm_dev_probe(struct platform_device *pdev) } /* register component */ - ret = devm_snd_soc_register_component(dev, &mt8188_afe_component, + ret = devm_snd_soc_register_component(dev, &mtk_afe_pcm_platform, afe->dai_drivers, afe->num_dai_drivers); if (ret) { dev_warn(dev, "err_platform\n"); diff --git a/sound/soc/mediatek/mt8192/mt8192-afe-pcm.c b/sound/soc/mediatek/mt8192/mt8192-afe-pcm.c index aed22baef9fb..424c5c68f78a 100644 --- a/sound/soc/mediatek/mt8192/mt8192-afe-pcm.c +++ b/sound/soc/mediatek/mt8192/mt8192-afe-pcm.c @@ -2125,22 +2125,6 @@ skip_regmap: return 0; } -static int mt8192_afe_component_probe(struct snd_soc_component *component) -{ - return mtk_afe_add_sub_dai_control(component); -} - -static const struct snd_soc_component_driver mt8192_afe_component = { - .name = AFE_PCM_NAME, - .probe = mt8192_afe_component_probe, - .pointer = mtk_afe_pcm_pointer, - .pcm_construct = mtk_afe_pcm_new, -}; - -static const struct snd_soc_component_driver mt8192_afe_pcm_component = { - .name = "mt8192-afe-pcm-dai", -}; - static int mt8192_dai_memif_register(struct mtk_base_afe *afe) { struct mtk_base_afe_dai *dai; @@ -2302,16 +2286,11 @@ static int mt8192_afe_pcm_dev_probe(struct platform_device *pdev) /* register platform */ ret = devm_snd_soc_register_component(&pdev->dev, - &mt8192_afe_component, NULL, 0); - if (ret) - return dev_err_probe(dev, ret, "Couldn't register AFE component\n"); - - ret = devm_snd_soc_register_component(&pdev->dev, - &mt8192_afe_pcm_component, + &mtk_afe_pcm_platform, afe->dai_drivers, afe->num_dai_drivers); if (ret) - return dev_err_probe(dev, ret, "Couldn't register AFE-PCM component\n"); + return dev_err_probe(dev, ret, "Couldn't register AFE component\n"); return 0; } diff --git a/sound/soc/mediatek/mt8195/mt8195-afe-pcm.c b/sound/soc/mediatek/mt8195/mt8195-afe-pcm.c index 620d7ade1992..64af9bf363fd 100644 --- a/sound/soc/mediatek/mt8195/mt8195-afe-pcm.c +++ b/sound/soc/mediatek/mt8195/mt8195-afe-pcm.c @@ -2944,25 +2944,6 @@ skip_regmap: return 0; } -static int mt8195_afe_component_probe(struct snd_soc_component *component) -{ - struct mtk_base_afe *afe = snd_soc_component_get_drvdata(component); - int ret = 0; - - snd_soc_component_init_regmap(component, afe->regmap); - - ret = mtk_afe_add_sub_dai_control(component); - - return ret; -} - -static const struct snd_soc_component_driver mt8195_afe_component = { - .name = AFE_PCM_NAME, - .pointer = mtk_afe_pcm_pointer, - .pcm_construct = mtk_afe_pcm_new, - .probe = mt8195_afe_component_probe, -}; - static int init_memif_priv_data(struct mtk_base_afe *afe) { struct mt8195_afe_private *afe_priv = afe->platform_priv; @@ -3164,7 +3145,7 @@ static int mt8195_afe_pcm_dev_probe(struct platform_device *pdev) } /* register component */ - ret = devm_snd_soc_register_component(dev, &mt8195_afe_component, + ret = devm_snd_soc_register_component(dev, &mtk_afe_pcm_platform, afe->dai_drivers, afe->num_dai_drivers); if (ret) { dev_warn(dev, "err_platform\n"); -- cgit v1.2.3 From 6ed619b348bf0a490e70dea7a330cf44dc81c16d Mon Sep 17 00:00:00 2001 From: AngeloGioacchino Del Regno Date: Tue, 16 Apr 2024 09:14:05 +0200 Subject: ASoC: mediatek: mt8186: Unify mt8186-mt6366 machine drivers Copy the few differences from mt8186-mt6166-da7219-max98357 in the mt8186-mt6366-rt1019-rt5682s driver to greatly reduce code duplication; since now the driver is meant to support MT8186 with the MT6366 PMIC codec and various combinations of I2S codecs, rename the driver to mt8186-mt6366 for consistency with MT8195 and MT8188, and rename the configuration option to SND_SOC_MT8186_MT6366. Since right now there is no machine using the da7219-max98357 yet, the snd_soc_dapm_route array was omitted as it's now possible to specify the audio routing in device trees instead. While at it, also add the missing sentinel comment to the last entry of the of_device_id array. Signed-off-by: AngeloGioacchino Del Regno Link: https://lore.kernel.org/r/20240416071410.75620-14-angelogioacchino.delregno@collabora.com Signed-off-by: Mark Brown --- sound/soc/mediatek/Kconfig | 24 +- sound/soc/mediatek/mt8186/Makefile | 3 +- .../mt8186/mt8186-mt6366-da7219-max98357.c | 1189 ----------------- .../mediatek/mt8186/mt8186-mt6366-rt1019-rt5682s.c | 1232 ----------------- sound/soc/mediatek/mt8186/mt8186-mt6366.c | 1398 ++++++++++++++++++++ 5 files changed, 1403 insertions(+), 2443 deletions(-) delete mode 100644 sound/soc/mediatek/mt8186/mt8186-mt6366-da7219-max98357.c delete mode 100644 sound/soc/mediatek/mt8186/mt8186-mt6366-rt1019-rt5682s.c create mode 100644 sound/soc/mediatek/mt8186/mt8186-mt6366.c diff --git a/sound/soc/mediatek/Kconfig b/sound/soc/mediatek/Kconfig index 296b434caf81..5a8476e1ecca 100644 --- a/sound/soc/mediatek/Kconfig +++ b/sound/soc/mediatek/Kconfig @@ -185,27 +185,11 @@ config SND_SOC_MT8186 Select Y if you have such device. If unsure select "N". -config SND_SOC_MT8186_MT6366_DA7219_MAX98357 - tristate "ASoC Audio driver for MT8186 with DA7219 MAX98357A codec" +config SND_SOC_MT8186_MT6366 + tristate "ASoC Audio driver for MT8186 with MT6366 and I2S codecs" depends on I2C && GPIOLIB depends on SND_SOC_MT8186 && MTK_PMIC_WRAP - select SND_SOC_MT6358 - select SND_SOC_MAX98357A select SND_SOC_DA7219 - select SND_SOC_BT_SCO - select SND_SOC_DMIC - select SND_SOC_HDMI_CODEC - help - This adds ASoC driver for Mediatek MT8186 boards - with the MT6366(MT6358) DA7219 MAX98357A codecs. - Select Y if you have such device. - If unsure select "N". - -config SND_SOC_MT8186_MT6366_RT1019_RT5682S - tristate "ASoC Audio driver for MT8186 with RT1019 RT5682S MAX98357A/MAX98360 codec" - depends on I2C && GPIOLIB - depends on SND_SOC_MT8186 && MTK_PMIC_WRAP - select SND_SOC_MAX98357A select SND_SOC_MT6358 select SND_SOC_MAX98357A select SND_SOC_RT1015P @@ -215,8 +199,8 @@ config SND_SOC_MT8186_MT6366_RT1019_RT5682S select SND_SOC_DMIC select SND_SOC_HDMI_CODEC help - This adds ASoC driver for Mediatek MT8186 boards - with the MT6366(MT6358) RT1019 RT5682S codecs. + This adds the ASoC machine driver for Mediatek MT8186 boards + with the MT6366(MT6358) and other I2S audio codecs. Select Y if you have such device. If unsure select "N". diff --git a/sound/soc/mediatek/mt8186/Makefile b/sound/soc/mediatek/mt8186/Makefile index 49b0026628a0..fa2f0efce815 100644 --- a/sound/soc/mediatek/mt8186/Makefile +++ b/sound/soc/mediatek/mt8186/Makefile @@ -18,5 +18,4 @@ snd-soc-mt8186-afe-objs := \ mt8186-mt6366-common.o obj-$(CONFIG_SND_SOC_MT8186) += snd-soc-mt8186-afe.o -obj-$(CONFIG_SND_SOC_MT8186_MT6366_DA7219_MAX98357) += mt8186-mt6366-da7219-max98357.o -obj-$(CONFIG_SND_SOC_MT8186_MT6366_RT1019_RT5682S) += mt8186-mt6366-rt1019-rt5682s.o +obj-$(CONFIG_SND_SOC_MT8186_MT6366) += mt8186-mt6366.o diff --git a/sound/soc/mediatek/mt8186/mt8186-mt6366-da7219-max98357.c b/sound/soc/mediatek/mt8186/mt8186-mt6366-da7219-max98357.c deleted file mode 100644 index d86dc45be30c..000000000000 --- a/sound/soc/mediatek/mt8186/mt8186-mt6366-da7219-max98357.c +++ /dev/null @@ -1,1189 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -// -// mt8186-mt6366-da7219-max98357.c -// -- MT8186-MT6366-DA7219-MAX98357 ALSA SoC machine driver -// -// Copyright (c) 2022 MediaTek Inc. -// Author: Jiaxin Yu -// - -#include -#include -#include -#include -#include -#include - -#include "../../codecs/da7219.h" -#include "../../codecs/mt6358.h" -#include "../common/mtk-afe-platform-driver.h" -#include "../common/mtk-dsp-sof-common.h" -#include "../common/mtk-soc-card.h" -#include "mt8186-afe-common.h" -#include "mt8186-afe-clk.h" -#include "mt8186-afe-gpio.h" -#include "mt8186-mt6366-common.h" - -#define DA7219_CODEC_DAI "da7219-hifi" -#define DA7219_DEV_NAME "da7219.5-001a" - -#define SOF_DMA_DL1 "SOF_DMA_DL1" -#define SOF_DMA_DL2 "SOF_DMA_DL2" -#define SOF_DMA_UL1 "SOF_DMA_UL1" -#define SOF_DMA_UL2 "SOF_DMA_UL2" - -struct mt8186_mt6366_da7219_max98357_priv { - struct snd_soc_jack headset_jack, hdmi_jack; -}; - -/* Headset jack detection DAPM pins */ -static struct snd_soc_jack_pin mt8186_jack_pins[] = { - { - .pin = "Headphones", - .mask = SND_JACK_HEADPHONE, - }, - { - .pin = "Headset Mic", - .mask = SND_JACK_MICROPHONE, - }, - { - .pin = "Line Out", - .mask = SND_JACK_LINEOUT, - }, -}; - -static struct snd_soc_codec_conf mt8186_mt6366_da7219_max98357_codec_conf[] = { - { - .dlc = COMP_CODEC_CONF("mt6358-sound"), - .name_prefix = "Mt6366", - }, - { - .dlc = COMP_CODEC_CONF("bt-sco"), - .name_prefix = "Mt8186 bt", - }, - { - .dlc = COMP_CODEC_CONF("hdmi-audio-codec"), - .name_prefix = "Mt8186 hdmi", - }, -}; - -static int mt8186_da7219_init(struct snd_soc_pcm_runtime *rtd) -{ - struct snd_soc_component *cmpnt_afe = - snd_soc_rtdcom_lookup(rtd, AFE_PCM_NAME); - struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt_afe); - struct mtk_soc_card_data *soc_card_data = - snd_soc_card_get_drvdata(rtd->card); - struct mt8186_mt6366_da7219_max98357_priv *priv = soc_card_data->mach_priv; - struct snd_soc_jack *jack = &priv->headset_jack; - struct snd_soc_component *cmpnt_codec = - snd_soc_rtd_to_codec(rtd, 0)->component; - int ret; - - ret = mt8186_dai_i2s_set_share(afe, "I2S1", "I2S0"); - if (ret) { - dev_err(rtd->dev, "Failed to set up shared clocks\n"); - return ret; - } - - /* Enable Headset and 4 Buttons Jack detection */ - ret = snd_soc_card_jack_new_pins(rtd->card, "Headset Jack", - SND_JACK_HEADSET | SND_JACK_BTN_0 | - SND_JACK_BTN_1 | SND_JACK_BTN_2 | - SND_JACK_BTN_3 | SND_JACK_LINEOUT, - jack, mt8186_jack_pins, - ARRAY_SIZE(mt8186_jack_pins)); - if (ret) { - dev_err(rtd->dev, "Headset Jack creation failed: %d\n", ret); - return ret; - } - - snd_jack_set_key(jack->jack, SND_JACK_BTN_0, KEY_PLAYPAUSE); - snd_jack_set_key(jack->jack, SND_JACK_BTN_1, KEY_VOLUMEUP); - snd_jack_set_key(jack->jack, SND_JACK_BTN_2, KEY_VOLUMEDOWN); - snd_jack_set_key(jack->jack, SND_JACK_BTN_3, KEY_VOICECOMMAND); - - snd_soc_component_set_jack(cmpnt_codec, &priv->headset_jack, NULL); - - return 0; -} - -static int mt8186_da7219_i2s_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *params) -{ - struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream); - struct snd_soc_dai *codec_dai; - unsigned int rate = params_rate(params); - unsigned int mclk_fs_ratio = 256; - unsigned int mclk_fs = rate * mclk_fs_ratio; - unsigned int freq; - int ret, j; - - ret = snd_soc_dai_set_sysclk(snd_soc_rtd_to_cpu(rtd, 0), 0, - mclk_fs, SND_SOC_CLOCK_OUT); - if (ret < 0) { - dev_err(rtd->dev, "failed to set cpu dai sysclk: %d\n", ret); - return ret; - } - - for_each_rtd_codec_dais(rtd, j, codec_dai) { - if (!strcmp(codec_dai->component->name, DA7219_DEV_NAME)) { - ret = snd_soc_dai_set_sysclk(codec_dai, - DA7219_CLKSRC_MCLK, - mclk_fs, - SND_SOC_CLOCK_IN); - if (ret < 0) { - dev_err(rtd->dev, "failed to set sysclk: %d\n", - ret); - return ret; - } - - if ((rate % 8000) == 0) - freq = DA7219_PLL_FREQ_OUT_98304; - else - freq = DA7219_PLL_FREQ_OUT_90316; - - ret = snd_soc_dai_set_pll(codec_dai, 0, - DA7219_SYSCLK_PLL_SRM, - 0, freq); - if (ret) { - dev_err(rtd->dev, "failed to start PLL: %d\n", - ret); - return ret; - } - } - } - - return 0; -} - -static int mt8186_da7219_i2s_hw_free(struct snd_pcm_substream *substream) -{ - struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream); - struct snd_soc_dai *codec_dai; - int ret = 0, j; - - for_each_rtd_codec_dais(rtd, j, codec_dai) { - if (!strcmp(codec_dai->component->name, DA7219_DEV_NAME)) { - ret = snd_soc_dai_set_pll(codec_dai, - 0, DA7219_SYSCLK_MCLK, 0, 0); - if (ret < 0) { - dev_err(rtd->dev, "failed to stop PLL: %d\n", - ret); - return ret; - } - } - } - - return 0; -} - -static const struct snd_soc_ops mt8186_da7219_i2s_ops = { - .hw_params = mt8186_da7219_i2s_hw_params, - .hw_free = mt8186_da7219_i2s_hw_free, -}; - -static int mt8186_mt6366_da7219_max98357_hdmi_init(struct snd_soc_pcm_runtime *rtd) -{ - struct snd_soc_component *cmpnt_afe = - snd_soc_rtdcom_lookup(rtd, AFE_PCM_NAME); - struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt_afe); - struct snd_soc_component *cmpnt_codec = - snd_soc_rtd_to_codec(rtd, 0)->component; - struct mtk_soc_card_data *soc_card_data = - snd_soc_card_get_drvdata(rtd->card); - struct mt8186_mt6366_da7219_max98357_priv *priv = soc_card_data->mach_priv; - int ret; - - ret = mt8186_dai_i2s_set_share(afe, "I2S2", "I2S3"); - if (ret) { - dev_err(rtd->dev, "Failed to set up shared clocks\n"); - return ret; - } - - ret = snd_soc_card_jack_new(rtd->card, "HDMI Jack", SND_JACK_LINEOUT, &priv->hdmi_jack); - if (ret) { - dev_err(rtd->dev, "HDMI Jack creation failed: %d\n", ret); - return ret; - } - - return snd_soc_component_set_jack(cmpnt_codec, &priv->hdmi_jack, NULL); -} - -static int mt8186_hw_params_fixup(struct snd_soc_pcm_runtime *rtd, - struct snd_pcm_hw_params *params, - snd_pcm_format_t fmt) -{ - struct snd_interval *channels = hw_param_interval(params, - SNDRV_PCM_HW_PARAM_CHANNELS); - - dev_dbg(rtd->dev, "%s(), fix format to %d\n", __func__, fmt); - - /* fix BE i2s channel to 2 channel */ - channels->min = 2; - channels->max = 2; - - /* clean param mask first */ - snd_mask_reset_range(hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT), - 0, (__force unsigned int)SNDRV_PCM_FORMAT_LAST); - - params_set_format(params, fmt); - - return 0; -} - -static int mt8186_i2s_hw_params_fixup(struct snd_soc_pcm_runtime *rtd, - struct snd_pcm_hw_params *params) -{ - return mt8186_hw_params_fixup(rtd, params, SNDRV_PCM_FORMAT_S32_LE); -} - -static int mt8186_anx7625_i2s_hw_params_fixup(struct snd_soc_pcm_runtime *rtd, - struct snd_pcm_hw_params *params) -{ - return mt8186_hw_params_fixup(rtd, params, SNDRV_PCM_FORMAT_S24_LE); -} - -/* fixup the BE DAI link to match any values from topology */ -static int mt8186_sof_dai_link_fixup(struct snd_soc_pcm_runtime *rtd, - struct snd_pcm_hw_params *params) -{ - int ret; - - ret = mtk_sof_dai_link_fixup(rtd, params); - - if (!strcmp(rtd->dai_link->name, "I2S0") || - !strcmp(rtd->dai_link->name, "I2S1") || - !strcmp(rtd->dai_link->name, "I2S2")) - mt8186_i2s_hw_params_fixup(rtd, params); - else if (!strcmp(rtd->dai_link->name, "I2S3")) - mt8186_anx7625_i2s_hw_params_fixup(rtd, params); - - return ret; -} - -static int mt8186_mt6366_da7219_max98357_playback_startup(struct snd_pcm_substream *substream) -{ - static const unsigned int rates[] = { - 48000 - }; - static const unsigned int channels[] = { - 2 - }; - static const struct snd_pcm_hw_constraint_list constraints_rates = { - .count = ARRAY_SIZE(rates), - .list = rates, - .mask = 0, - }; - static const struct snd_pcm_hw_constraint_list constraints_channels = { - .count = ARRAY_SIZE(channels), - .list = channels, - .mask = 0, - }; - - struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream); - struct snd_pcm_runtime *runtime = substream->runtime; - int ret; - - ret = snd_pcm_hw_constraint_list(runtime, 0, - SNDRV_PCM_HW_PARAM_RATE, - &constraints_rates); - if (ret < 0) { - dev_err(rtd->dev, "hw_constraint_list rate failed\n"); - return ret; - } - - ret = snd_pcm_hw_constraint_list(runtime, 0, - SNDRV_PCM_HW_PARAM_CHANNELS, - &constraints_channels); - if (ret < 0) { - dev_err(rtd->dev, "hw_constraint_list channel failed\n"); - return ret; - } - - return 0; -} - -static const struct snd_soc_ops mt8186_mt6366_da7219_max98357_playback_ops = { - .startup = mt8186_mt6366_da7219_max98357_playback_startup, -}; - -static int mt8186_mt6366_da7219_max98357_capture_startup(struct snd_pcm_substream *substream) -{ - static const unsigned int rates[] = { - 48000 - }; - static const unsigned int channels[] = { - 1, 2 - }; - static const struct snd_pcm_hw_constraint_list constraints_rates = { - .count = ARRAY_SIZE(rates), - .list = rates, - .mask = 0, - }; - static const struct snd_pcm_hw_constraint_list constraints_channels = { - .count = ARRAY_SIZE(channels), - .list = channels, - .mask = 0, - }; - - struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream); - struct snd_pcm_runtime *runtime = substream->runtime; - int ret; - - ret = snd_pcm_hw_constraint_list(runtime, 0, - SNDRV_PCM_HW_PARAM_RATE, - &constraints_rates); - if (ret < 0) { - dev_err(rtd->dev, "hw_constraint_list rate failed\n"); - return ret; - } - - ret = snd_pcm_hw_constraint_list(runtime, 0, - SNDRV_PCM_HW_PARAM_CHANNELS, - &constraints_channels); - if (ret < 0) { - dev_err(rtd->dev, "hw_constraint_list channel failed\n"); - return ret; - } - - return 0; -} - -static const struct snd_soc_ops mt8186_mt6366_da7219_max98357_capture_ops = { - .startup = mt8186_mt6366_da7219_max98357_capture_startup, -}; - -/* FE */ -SND_SOC_DAILINK_DEFS(playback1, - DAILINK_COMP_ARRAY(COMP_CPU("DL1")), - DAILINK_COMP_ARRAY(COMP_DUMMY()), - DAILINK_COMP_ARRAY(COMP_EMPTY())); - -SND_SOC_DAILINK_DEFS(playback12, - DAILINK_COMP_ARRAY(COMP_CPU("DL12")), - DAILINK_COMP_ARRAY(COMP_DUMMY()), - DAILINK_COMP_ARRAY(COMP_EMPTY())); - -SND_SOC_DAILINK_DEFS(playback2, - DAILINK_COMP_ARRAY(COMP_CPU("DL2")), - DAILINK_COMP_ARRAY(COMP_DUMMY()), - DAILINK_COMP_ARRAY(COMP_EMPTY())); - -SND_SOC_DAILINK_DEFS(playback3, - DAILINK_COMP_ARRAY(COMP_CPU("DL3")), - DAILINK_COMP_ARRAY(COMP_DUMMY()), - DAILINK_COMP_ARRAY(COMP_EMPTY())); - -SND_SOC_DAILINK_DEFS(playback4, - DAILINK_COMP_ARRAY(COMP_CPU("DL4")), - DAILINK_COMP_ARRAY(COMP_DUMMY()), - DAILINK_COMP_ARRAY(COMP_EMPTY())); - -SND_SOC_DAILINK_DEFS(playback5, - DAILINK_COMP_ARRAY(COMP_CPU("DL5")), - DAILINK_COMP_ARRAY(COMP_DUMMY()), - DAILINK_COMP_ARRAY(COMP_EMPTY())); - -SND_SOC_DAILINK_DEFS(playback6, - DAILINK_COMP_ARRAY(COMP_CPU("DL6")), - DAILINK_COMP_ARRAY(COMP_DUMMY()), - DAILINK_COMP_ARRAY(COMP_EMPTY())); - -SND_SOC_DAILINK_DEFS(playback7, - DAILINK_COMP_ARRAY(COMP_CPU("DL7")), - DAILINK_COMP_ARRAY(COMP_DUMMY()), - DAILINK_COMP_ARRAY(COMP_EMPTY())); - -SND_SOC_DAILINK_DEFS(playback8, - DAILINK_COMP_ARRAY(COMP_CPU("DL8")), - DAILINK_COMP_ARRAY(COMP_DUMMY()), - DAILINK_COMP_ARRAY(COMP_EMPTY())); - -SND_SOC_DAILINK_DEFS(capture1, - DAILINK_COMP_ARRAY(COMP_CPU("UL1")), - DAILINK_COMP_ARRAY(COMP_DUMMY()), - DAILINK_COMP_ARRAY(COMP_EMPTY())); - -SND_SOC_DAILINK_DEFS(capture2, - DAILINK_COMP_ARRAY(COMP_CPU("UL2")), - DAILINK_COMP_ARRAY(COMP_DUMMY()), - DAILINK_COMP_ARRAY(COMP_EMPTY())); - -SND_SOC_DAILINK_DEFS(capture3, - DAILINK_COMP_ARRAY(COMP_CPU("UL3")), - DAILINK_COMP_ARRAY(COMP_DUMMY()), - DAILINK_COMP_ARRAY(COMP_EMPTY())); - -SND_SOC_DAILINK_DEFS(capture4, - DAILINK_COMP_ARRAY(COMP_CPU("UL4")), - DAILINK_COMP_ARRAY(COMP_DUMMY()), - DAILINK_COMP_ARRAY(COMP_EMPTY())); - -SND_SOC_DAILINK_DEFS(capture5, - DAILINK_COMP_ARRAY(COMP_CPU("UL5")), - DAILINK_COMP_ARRAY(COMP_DUMMY()), - DAILINK_COMP_ARRAY(COMP_EMPTY())); - -SND_SOC_DAILINK_DEFS(capture6, - DAILINK_COMP_ARRAY(COMP_CPU("UL6")), - DAILINK_COMP_ARRAY(COMP_DUMMY()), - DAILINK_COMP_ARRAY(COMP_EMPTY())); - -SND_SOC_DAILINK_DEFS(capture7, - DAILINK_COMP_ARRAY(COMP_CPU("UL7")), - DAILINK_COMP_ARRAY(COMP_DUMMY()), - DAILINK_COMP_ARRAY(COMP_EMPTY())); - -/* hostless */ -SND_SOC_DAILINK_DEFS(hostless_lpbk, - DAILINK_COMP_ARRAY(COMP_CPU("Hostless LPBK DAI")), - DAILINK_COMP_ARRAY(COMP_DUMMY()), - DAILINK_COMP_ARRAY(COMP_EMPTY())); -SND_SOC_DAILINK_DEFS(hostless_fm, - DAILINK_COMP_ARRAY(COMP_CPU("Hostless FM DAI")), - DAILINK_COMP_ARRAY(COMP_DUMMY()), - DAILINK_COMP_ARRAY(COMP_EMPTY())); -SND_SOC_DAILINK_DEFS(hostless_src1, - DAILINK_COMP_ARRAY(COMP_CPU("Hostless_SRC_1_DAI")), - DAILINK_COMP_ARRAY(COMP_DUMMY()), - DAILINK_COMP_ARRAY(COMP_EMPTY())); -SND_SOC_DAILINK_DEFS(hostless_src_bargein, - DAILINK_COMP_ARRAY(COMP_CPU("Hostless_SRC_Bargein_DAI")), - DAILINK_COMP_ARRAY(COMP_DUMMY()), - DAILINK_COMP_ARRAY(COMP_EMPTY())); - -/* BE */ -SND_SOC_DAILINK_DEFS(adda, - DAILINK_COMP_ARRAY(COMP_CPU("ADDA")), - DAILINK_COMP_ARRAY(COMP_CODEC("mt6358-sound", - "mt6358-snd-codec-aif1"), - COMP_CODEC("dmic-codec", - "dmic-hifi")), - DAILINK_COMP_ARRAY(COMP_EMPTY())); -SND_SOC_DAILINK_DEFS(i2s0, - DAILINK_COMP_ARRAY(COMP_CPU("I2S0")), - DAILINK_COMP_ARRAY(COMP_EMPTY()), - DAILINK_COMP_ARRAY(COMP_EMPTY())); -SND_SOC_DAILINK_DEFS(i2s1, - DAILINK_COMP_ARRAY(COMP_CPU("I2S1")), - DAILINK_COMP_ARRAY(COMP_EMPTY()), - DAILINK_COMP_ARRAY(COMP_EMPTY())); -SND_SOC_DAILINK_DEFS(i2s2, - DAILINK_COMP_ARRAY(COMP_CPU("I2S2")), - DAILINK_COMP_ARRAY(COMP_DUMMY()), - DAILINK_COMP_ARRAY(COMP_EMPTY())); -SND_SOC_DAILINK_DEFS(i2s3, - DAILINK_COMP_ARRAY(COMP_CPU("I2S3")), - DAILINK_COMP_ARRAY(COMP_EMPTY()), - DAILINK_COMP_ARRAY(COMP_EMPTY())); -SND_SOC_DAILINK_DEFS(hw_gain1, - DAILINK_COMP_ARRAY(COMP_CPU("HW Gain 1")), - DAILINK_COMP_ARRAY(COMP_DUMMY()), - DAILINK_COMP_ARRAY(COMP_EMPTY())); -SND_SOC_DAILINK_DEFS(hw_gain2, - DAILINK_COMP_ARRAY(COMP_CPU("HW Gain 2")), - DAILINK_COMP_ARRAY(COMP_DUMMY()), - DAILINK_COMP_ARRAY(COMP_EMPTY())); -SND_SOC_DAILINK_DEFS(hw_src1, - DAILINK_COMP_ARRAY(COMP_CPU("HW_SRC_1")), - DAILINK_COMP_ARRAY(COMP_DUMMY()), - DAILINK_COMP_ARRAY(COMP_EMPTY())); -SND_SOC_DAILINK_DEFS(hw_src2, - DAILINK_COMP_ARRAY(COMP_CPU("HW_SRC_2")), - DAILINK_COMP_ARRAY(COMP_DUMMY()), - DAILINK_COMP_ARRAY(COMP_EMPTY())); -SND_SOC_DAILINK_DEFS(connsys_i2s, - DAILINK_COMP_ARRAY(COMP_CPU("CONNSYS_I2S")), - DAILINK_COMP_ARRAY(COMP_DUMMY()), - DAILINK_COMP_ARRAY(COMP_EMPTY())); -SND_SOC_DAILINK_DEFS(pcm1, - DAILINK_COMP_ARRAY(COMP_CPU("PCM 1")), - DAILINK_COMP_ARRAY(COMP_CODEC("bt-sco", "bt-sco-pcm-wb")), - DAILINK_COMP_ARRAY(COMP_EMPTY())); -SND_SOC_DAILINK_DEFS(tdm_in, - DAILINK_COMP_ARRAY(COMP_CPU("TDM IN")), - DAILINK_COMP_ARRAY(COMP_DUMMY()), - DAILINK_COMP_ARRAY(COMP_EMPTY())); - -/* hostless */ -SND_SOC_DAILINK_DEFS(hostless_ul1, - DAILINK_COMP_ARRAY(COMP_CPU("Hostless_UL1 DAI")), - DAILINK_COMP_ARRAY(COMP_DUMMY()), - DAILINK_COMP_ARRAY(COMP_EMPTY())); -SND_SOC_DAILINK_DEFS(hostless_ul2, - DAILINK_COMP_ARRAY(COMP_CPU("Hostless_UL2 DAI")), - DAILINK_COMP_ARRAY(COMP_DUMMY()), - DAILINK_COMP_ARRAY(COMP_EMPTY())); -SND_SOC_DAILINK_DEFS(hostless_ul3, - DAILINK_COMP_ARRAY(COMP_CPU("Hostless_UL3 DAI")), - DAILINK_COMP_ARRAY(COMP_DUMMY()), - DAILINK_COMP_ARRAY(COMP_EMPTY())); -SND_SOC_DAILINK_DEFS(hostless_ul5, - DAILINK_COMP_ARRAY(COMP_CPU("Hostless_UL5 DAI")), - DAILINK_COMP_ARRAY(COMP_DUMMY()), - DAILINK_COMP_ARRAY(COMP_EMPTY())); -SND_SOC_DAILINK_DEFS(hostless_ul6, - DAILINK_COMP_ARRAY(COMP_CPU("Hostless_UL6 DAI")), - DAILINK_COMP_ARRAY(COMP_DUMMY()), - DAILINK_COMP_ARRAY(COMP_EMPTY())); -SND_SOC_DAILINK_DEFS(hostless_hw_gain_aaudio, - DAILINK_COMP_ARRAY(COMP_CPU("Hostless HW Gain AAudio DAI")), - DAILINK_COMP_ARRAY(COMP_DUMMY()), - DAILINK_COMP_ARRAY(COMP_EMPTY())); -SND_SOC_DAILINK_DEFS(hostless_src_aaudio, - DAILINK_COMP_ARRAY(COMP_CPU("Hostless SRC AAudio DAI")), - DAILINK_COMP_ARRAY(COMP_DUMMY()), - DAILINK_COMP_ARRAY(COMP_EMPTY())); -SND_SOC_DAILINK_DEFS(AFE_SOF_DL1, - DAILINK_COMP_ARRAY(COMP_CPU("SOF_DL1")), - DAILINK_COMP_ARRAY(COMP_DUMMY()), - DAILINK_COMP_ARRAY(COMP_EMPTY())); - -SND_SOC_DAILINK_DEFS(AFE_SOF_DL2, - DAILINK_COMP_ARRAY(COMP_CPU("SOF_DL2")), - DAILINK_COMP_ARRAY(COMP_DUMMY()), - DAILINK_COMP_ARRAY(COMP_EMPTY())); - -SND_SOC_DAILINK_DEFS(AFE_SOF_UL1, - DAILINK_COMP_ARRAY(COMP_CPU("SOF_UL1")), - DAILINK_COMP_ARRAY(COMP_DUMMY()), - DAILINK_COMP_ARRAY(COMP_EMPTY())); - -SND_SOC_DAILINK_DEFS(AFE_SOF_UL2, - DAILINK_COMP_ARRAY(COMP_CPU("SOF_UL2")), - DAILINK_COMP_ARRAY(COMP_DUMMY()), - DAILINK_COMP_ARRAY(COMP_EMPTY())); - -static const struct sof_conn_stream g_sof_conn_streams[] = { - { "I2S1", "AFE_SOF_DL1", SOF_DMA_DL1, SNDRV_PCM_STREAM_PLAYBACK}, - { "I2S3", "AFE_SOF_DL2", SOF_DMA_DL2, SNDRV_PCM_STREAM_PLAYBACK}, - { "Primary Codec", "AFE_SOF_UL1", SOF_DMA_UL1, SNDRV_PCM_STREAM_CAPTURE}, - { "I2S0", "AFE_SOF_UL2", SOF_DMA_UL2, SNDRV_PCM_STREAM_CAPTURE}, -}; - -static struct snd_soc_dai_link mt8186_mt6366_da7219_max98357_dai_links[] = { - /* Front End DAI links */ - { - .name = "Playback_1", - .stream_name = "Playback_1", - .trigger = {SND_SOC_DPCM_TRIGGER_PRE, - SND_SOC_DPCM_TRIGGER_PRE}, - .dynamic = 1, - .dpcm_playback = 1, - .dpcm_merged_format = 1, - .dpcm_merged_chan = 1, - .dpcm_merged_rate = 1, - .ops = &mt8186_mt6366_da7219_max98357_playback_ops, - SND_SOC_DAILINK_REG(playback1), - }, - { - .name = "Playback_12", - .stream_name = "Playback_12", - .trigger = {SND_SOC_DPCM_TRIGGER_PRE, - SND_SOC_DPCM_TRIGGER_PRE}, - .dynamic = 1, - .dpcm_playback = 1, - SND_SOC_DAILINK_REG(playback12), - }, - { - .name = "Playback_2", - .stream_name = "Playback_2", - .trigger = {SND_SOC_DPCM_TRIGGER_PRE, - SND_SOC_DPCM_TRIGGER_PRE}, - .dynamic = 1, - .dpcm_playback = 1, - .dpcm_merged_format = 1, - .dpcm_merged_chan = 1, - .dpcm_merged_rate = 1, - SND_SOC_DAILINK_REG(playback2), - }, - { - .name = "Playback_3", - .stream_name = "Playback_3", - .trigger = {SND_SOC_DPCM_TRIGGER_PRE, - SND_SOC_DPCM_TRIGGER_PRE}, - .dynamic = 1, - .dpcm_playback = 1, - .dpcm_merged_format = 1, - .dpcm_merged_chan = 1, - .dpcm_merged_rate = 1, - .ops = &mt8186_mt6366_da7219_max98357_playback_ops, - SND_SOC_DAILINK_REG(playback3), - }, - { - .name = "Playback_4", - .stream_name = "Playback_4", - .trigger = {SND_SOC_DPCM_TRIGGER_PRE, - SND_SOC_DPCM_TRIGGER_PRE}, - .dynamic = 1, - .dpcm_playback = 1, - SND_SOC_DAILINK_REG(playback4), - }, - { - .name = "Playback_5", - .stream_name = "Playback_5", - .trigger = {SND_SOC_DPCM_TRIGGER_PRE, - SND_SOC_DPCM_TRIGGER_PRE}, - .dynamic = 1, - .dpcm_playback = 1, - SND_SOC_DAILINK_REG(playback5), - }, - { - .name = "Playback_6", - .stream_name = "Playback_6", - .trigger = {SND_SOC_DPCM_TRIGGER_PRE, - SND_SOC_DPCM_TRIGGER_PRE}, - .dynamic = 1, - .dpcm_playback = 1, - SND_SOC_DAILINK_REG(playback6), - }, - { - .name = "Playback_7", - .stream_name = "Playback_7", - .trigger = {SND_SOC_DPCM_TRIGGER_PRE, - SND_SOC_DPCM_TRIGGER_PRE}, - .dynamic = 1, - .dpcm_playback = 1, - SND_SOC_DAILINK_REG(playback7), - }, - { - .name = "Playback_8", - .stream_name = "Playback_8", - .trigger = {SND_SOC_DPCM_TRIGGER_PRE, - SND_SOC_DPCM_TRIGGER_PRE}, - .dynamic = 1, - .dpcm_playback = 1, - SND_SOC_DAILINK_REG(playback8), - }, - { - .name = "Capture_1", - .stream_name = "Capture_1", - .trigger = {SND_SOC_DPCM_TRIGGER_PRE, - SND_SOC_DPCM_TRIGGER_PRE}, - .dynamic = 1, - .dpcm_capture = 1, - SND_SOC_DAILINK_REG(capture1), - }, - { - .name = "Capture_2", - .stream_name = "Capture_2", - .trigger = {SND_SOC_DPCM_TRIGGER_PRE, - SND_SOC_DPCM_TRIGGER_PRE}, - .dynamic = 1, - .dpcm_capture = 1, - .dpcm_merged_format = 1, - .dpcm_merged_chan = 1, - .dpcm_merged_rate = 1, - .ops = &mt8186_mt6366_da7219_max98357_capture_ops, - SND_SOC_DAILINK_REG(capture2), - }, - { - .name = "Capture_3", - .stream_name = "Capture_3", - .trigger = {SND_SOC_DPCM_TRIGGER_PRE, - SND_SOC_DPCM_TRIGGER_PRE}, - .dynamic = 1, - .dpcm_capture = 1, - SND_SOC_DAILINK_REG(capture3), - }, - { - .name = "Capture_4", - .stream_name = "Capture_4", - .trigger = {SND_SOC_DPCM_TRIGGER_PRE, - SND_SOC_DPCM_TRIGGER_PRE}, - .dynamic = 1, - .dpcm_capture = 1, - .dpcm_merged_format = 1, - .dpcm_merged_chan = 1, - .dpcm_merged_rate = 1, - .ops = &mt8186_mt6366_da7219_max98357_capture_ops, - SND_SOC_DAILINK_REG(capture4), - }, - { - .name = "Capture_5", - .stream_name = "Capture_5", - .trigger = {SND_SOC_DPCM_TRIGGER_PRE, - SND_SOC_DPCM_TRIGGER_PRE}, - .dynamic = 1, - .dpcm_capture = 1, - SND_SOC_DAILINK_REG(capture5), - }, - { - .name = "Capture_6", - .stream_name = "Capture_6", - .trigger = {SND_SOC_DPCM_TRIGGER_PRE, - SND_SOC_DPCM_TRIGGER_PRE}, - .dynamic = 1, - .dpcm_capture = 1, - .dpcm_merged_format = 1, - .dpcm_merged_chan = 1, - .dpcm_merged_rate = 1, - SND_SOC_DAILINK_REG(capture6), - }, - { - .name = "Capture_7", - .stream_name = "Capture_7", - .trigger = {SND_SOC_DPCM_TRIGGER_PRE, - SND_SOC_DPCM_TRIGGER_PRE}, - .dynamic = 1, - .dpcm_capture = 1, - SND_SOC_DAILINK_REG(capture7), - }, - { - .name = "Hostless_LPBK", - .stream_name = "Hostless_LPBK", - .trigger = {SND_SOC_DPCM_TRIGGER_PRE, - SND_SOC_DPCM_TRIGGER_PRE}, - .dynamic = 1, - .dpcm_playback = 1, - .dpcm_capture = 1, - .ignore_suspend = 1, - SND_SOC_DAILINK_REG(hostless_lpbk), - }, - { - .name = "Hostless_FM", - .stream_name = "Hostless_FM", - .trigger = {SND_SOC_DPCM_TRIGGER_PRE, - SND_SOC_DPCM_TRIGGER_PRE}, - .dynamic = 1, - .dpcm_playback = 1, - .dpcm_capture = 1, - .ignore_suspend = 1, - SND_SOC_DAILINK_REG(hostless_fm), - }, - { - .name = "Hostless_SRC_1", - .stream_name = "Hostless_SRC_1", - .trigger = {SND_SOC_DPCM_TRIGGER_PRE, - SND_SOC_DPCM_TRIGGER_PRE}, - .dynamic = 1, - .dpcm_playback = 1, - .dpcm_capture = 1, - .ignore_suspend = 1, - SND_SOC_DAILINK_REG(hostless_src1), - }, - { - .name = "Hostless_SRC_Bargein", - .stream_name = "Hostless_SRC_Bargein", - .trigger = {SND_SOC_DPCM_TRIGGER_PRE, - SND_SOC_DPCM_TRIGGER_PRE}, - .dynamic = 1, - .dpcm_playback = 1, - .dpcm_capture = 1, - .ignore_suspend = 1, - SND_SOC_DAILINK_REG(hostless_src_bargein), - }, - { - .name = "Hostless_HW_Gain_AAudio", - .stream_name = "Hostless_HW_Gain_AAudio", - .trigger = {SND_SOC_DPCM_TRIGGER_PRE, - SND_SOC_DPCM_TRIGGER_PRE}, - .dynamic = 1, - .dpcm_capture = 1, - .ignore_suspend = 1, - SND_SOC_DAILINK_REG(hostless_hw_gain_aaudio), - }, - { - .name = "Hostless_SRC_AAudio", - .stream_name = "Hostless_SRC_AAudio", - .trigger = {SND_SOC_DPCM_TRIGGER_PRE, - SND_SOC_DPCM_TRIGGER_PRE}, - .dynamic = 1, - .dpcm_playback = 1, - .dpcm_capture = 1, - .ignore_suspend = 1, - SND_SOC_DAILINK_REG(hostless_src_aaudio), - }, - /* Back End DAI links */ - { - .name = "Primary Codec", - .no_pcm = 1, - .dpcm_playback = 1, - .dpcm_capture = 1, - .ignore_suspend = 1, - .init = mt8186_mt6366_init, - SND_SOC_DAILINK_REG(adda), - }, - { - .name = "I2S3", - .no_pcm = 1, - .dai_fmt = SND_SOC_DAIFMT_I2S | - SND_SOC_DAIFMT_IB_IF | - SND_SOC_DAIFMT_CBM_CFM, - .dpcm_playback = 1, - .ignore_suspend = 1, - .init = mt8186_mt6366_da7219_max98357_hdmi_init, - .be_hw_params_fixup = mt8186_anx7625_i2s_hw_params_fixup, - SND_SOC_DAILINK_REG(i2s3), - }, - { - .name = "I2S0", - .no_pcm = 1, - .dpcm_capture = 1, - .ignore_suspend = 1, - .be_hw_params_fixup = mt8186_i2s_hw_params_fixup, - .ops = &mt8186_da7219_i2s_ops, - SND_SOC_DAILINK_REG(i2s0), - }, - { - .name = "I2S1", - .no_pcm = 1, - .dpcm_playback = 1, - .ignore_suspend = 1, - .be_hw_params_fixup = mt8186_i2s_hw_params_fixup, - .init = mt8186_da7219_init, - .ops = &mt8186_da7219_i2s_ops, - SND_SOC_DAILINK_REG(i2s1), - }, - { - .name = "I2S2", - .no_pcm = 1, - .dpcm_capture = 1, - .ignore_suspend = 1, - .be_hw_params_fixup = mt8186_i2s_hw_params_fixup, - SND_SOC_DAILINK_REG(i2s2), - }, - { - .name = "HW Gain 1", - .no_pcm = 1, - .dpcm_playback = 1, - .dpcm_capture = 1, - .ignore_suspend = 1, - SND_SOC_DAILINK_REG(hw_gain1), - }, - { - .name = "HW Gain 2", - .no_pcm = 1, - .dpcm_playback = 1, - .dpcm_capture = 1, - .ignore_suspend = 1, - SND_SOC_DAILINK_REG(hw_gain2), - }, - { - .name = "HW_SRC_1", - .no_pcm = 1, - .dpcm_playback = 1, - .dpcm_capture = 1, - .ignore_suspend = 1, - SND_SOC_DAILINK_REG(hw_src1), - }, - { - .name = "HW_SRC_2", - .no_pcm = 1, - .dpcm_playback = 1, - .dpcm_capture = 1, - .ignore_suspend = 1, - SND_SOC_DAILINK_REG(hw_src2), - }, - { - .name = "CONNSYS_I2S", - .no_pcm = 1, - .dpcm_capture = 1, - .ignore_suspend = 1, - SND_SOC_DAILINK_REG(connsys_i2s), - }, - { - .name = "PCM 1", - .dai_fmt = SND_SOC_DAIFMT_I2S | - SND_SOC_DAIFMT_NB_IF, - .no_pcm = 1, - .dpcm_playback = 1, - .dpcm_capture = 1, - .ignore_suspend = 1, - SND_SOC_DAILINK_REG(pcm1), - }, - { - .name = "TDM IN", - .no_pcm = 1, - .dpcm_capture = 1, - .ignore_suspend = 1, - SND_SOC_DAILINK_REG(tdm_in), - }, - /* dummy BE for ul memif to record from dl memif */ - { - .name = "Hostless_UL1", - .no_pcm = 1, - .dpcm_capture = 1, - .ignore_suspend = 1, - SND_SOC_DAILINK_REG(hostless_ul1), - }, - { - .name = "Hostless_UL2", - .no_pcm = 1, - .dpcm_capture = 1, - .ignore_suspend = 1, - SND_SOC_DAILINK_REG(hostless_ul2), - }, - { - .name = "Hostless_UL3", - .no_pcm = 1, - .dpcm_capture = 1, - .ignore_suspend = 1, - SND_SOC_DAILINK_REG(hostless_ul3), - }, - { - .name = "Hostless_UL5", - .no_pcm = 1, - .dpcm_capture = 1, - .ignore_suspend = 1, - SND_SOC_DAILINK_REG(hostless_ul5), - }, - { - .name = "Hostless_UL6", - .no_pcm = 1, - .dpcm_capture = 1, - .ignore_suspend = 1, - SND_SOC_DAILINK_REG(hostless_ul6), - }, - /* SOF BE */ - { - .name = "AFE_SOF_DL1", - .no_pcm = 1, - .dpcm_playback = 1, - SND_SOC_DAILINK_REG(AFE_SOF_DL1), - }, - { - .name = "AFE_SOF_DL2", - .no_pcm = 1, - .dpcm_playback = 1, - SND_SOC_DAILINK_REG(AFE_SOF_DL2), - }, - { - .name = "AFE_SOF_UL1", - .no_pcm = 1, - .dpcm_capture = 1, - SND_SOC_DAILINK_REG(AFE_SOF_UL1), - }, - { - .name = "AFE_SOF_UL2", - .no_pcm = 1, - .dpcm_capture = 1, - SND_SOC_DAILINK_REG(AFE_SOF_UL2), - }, -}; - -static const struct snd_soc_dapm_widget -mt8186_mt6366_da7219_max98357_widgets[] = { - SND_SOC_DAPM_SPK("Speakers", NULL), - SND_SOC_DAPM_HP("Headphones", NULL), - SND_SOC_DAPM_MIC("Headset Mic", NULL), - SND_SOC_DAPM_LINE("Line Out", NULL), - SND_SOC_DAPM_OUTPUT("HDMI1"), - SND_SOC_DAPM_MIXER(SOF_DMA_DL1, SND_SOC_NOPM, 0, 0, NULL, 0), - SND_SOC_DAPM_MIXER(SOF_DMA_DL2, SND_SOC_NOPM, 0, 0, NULL, 0), - SND_SOC_DAPM_MIXER(SOF_DMA_UL1, SND_SOC_NOPM, 0, 0, NULL, 0), - SND_SOC_DAPM_MIXER(SOF_DMA_UL2, SND_SOC_NOPM, 0, 0, NULL, 0), -}; - -static const struct snd_soc_dapm_route -mt8186_mt6366_da7219_max98357_routes[] = { - /* SPK */ - { "Speakers", NULL, "Speaker"}, - /* Headset */ - { "Headphones", NULL, "HPL" }, - { "Headphones", NULL, "HPR" }, - { "MIC", NULL, "Headset Mic" }, - /* HDMI */ - { "HDMI1", NULL, "TX"}, - /* SOF Uplink */ - {SOF_DMA_UL1, NULL, "UL1_CH1"}, - {SOF_DMA_UL1, NULL, "UL1_CH2"}, - {SOF_DMA_UL2, NULL, "UL2_CH1"}, - {SOF_DMA_UL2, NULL, "UL2_CH2"}, - /* SOF Downlink */ - {"DSP_DL1_VIRT", NULL, SOF_DMA_DL1}, - {"DSP_DL2_VIRT", NULL, SOF_DMA_DL2}, -}; - -static const struct snd_kcontrol_new -mt8186_mt6366_da7219_max98357_controls[] = { - SOC_DAPM_PIN_SWITCH("Speakers"), - SOC_DAPM_PIN_SWITCH("Headphones"), - SOC_DAPM_PIN_SWITCH("Headset Mic"), - SOC_DAPM_PIN_SWITCH("Line Out"), - SOC_DAPM_PIN_SWITCH("HDMI1"), -}; - -static struct snd_soc_card mt8186_mt6366_da7219_max98357_soc_card = { - .name = "mt8186_da7219_max98357", - .owner = THIS_MODULE, - .dai_link = mt8186_mt6366_da7219_max98357_dai_links, - .num_links = ARRAY_SIZE(mt8186_mt6366_da7219_max98357_dai_links), - .controls = mt8186_mt6366_da7219_max98357_controls, - .num_controls = ARRAY_SIZE(mt8186_mt6366_da7219_max98357_controls), - .dapm_widgets = mt8186_mt6366_da7219_max98357_widgets, - .num_dapm_widgets = ARRAY_SIZE(mt8186_mt6366_da7219_max98357_widgets), - .dapm_routes = mt8186_mt6366_da7219_max98357_routes, - .num_dapm_routes = ARRAY_SIZE(mt8186_mt6366_da7219_max98357_routes), - .codec_conf = mt8186_mt6366_da7219_max98357_codec_conf, - .num_configs = ARRAY_SIZE(mt8186_mt6366_da7219_max98357_codec_conf), -}; - -static int mt8186_mt6366_da7219_max98357_dev_probe(struct platform_device *pdev) -{ - struct snd_soc_card *card; - struct snd_soc_dai_link *dai_link; - struct mtk_soc_card_data *soc_card_data; - struct mt8186_mt6366_da7219_max98357_priv *mach_priv; - struct device_node *platform_node, *headset_codec, *playback_codec, *adsp_node; - int sof_on = 0; - int ret, i; - - card = (struct snd_soc_card *)device_get_match_data(&pdev->dev); - if (!card) - return -EINVAL; - card->dev = &pdev->dev; - - soc_card_data = devm_kzalloc(&pdev->dev, sizeof(*soc_card_data), GFP_KERNEL); - if (!soc_card_data) - return -ENOMEM; - mach_priv = devm_kzalloc(&pdev->dev, sizeof(*mach_priv), GFP_KERNEL); - if (!mach_priv) - return -ENOMEM; - - soc_card_data->mach_priv = mach_priv; - - adsp_node = of_parse_phandle(pdev->dev.of_node, "mediatek,adsp", 0); - if (adsp_node) { - struct mtk_sof_priv *sof_priv; - - sof_priv = devm_kzalloc(&pdev->dev, sizeof(*sof_priv), GFP_KERNEL); - if (!sof_priv) { - ret = -ENOMEM; - goto err_adsp_node; - } - sof_priv->conn_streams = g_sof_conn_streams; - sof_priv->num_streams = ARRAY_SIZE(g_sof_conn_streams); - sof_priv->sof_dai_link_fixup = mt8186_sof_dai_link_fixup; - soc_card_data->sof_priv = sof_priv; - card->probe = mtk_sof_card_probe; - card->late_probe = mtk_sof_card_late_probe; - if (!card->topology_shortname_created) { - snprintf(card->topology_shortname, 32, "sof-%s", card->name); - card->topology_shortname_created = true; - } - card->name = card->topology_shortname; - sof_on = 1; - } else { - dev_dbg(&pdev->dev, "Probe without adsp\n"); - } - - if (of_property_read_bool(pdev->dev.of_node, "mediatek,dai-link")) { - ret = mtk_sof_dailink_parse_of(card, pdev->dev.of_node, - "mediatek,dai-link", - mt8186_mt6366_da7219_max98357_dai_links, - ARRAY_SIZE(mt8186_mt6366_da7219_max98357_dai_links)); - if (ret) { - dev_dbg(&pdev->dev, "Parse dai-link fail\n"); - goto err_adsp_node; - } - } else { - if (!sof_on) - card->num_links = ARRAY_SIZE(mt8186_mt6366_da7219_max98357_dai_links) - - ARRAY_SIZE(g_sof_conn_streams); - } - - platform_node = of_parse_phandle(pdev->dev.of_node, "mediatek,platform", 0); - if (!platform_node) { - ret = -EINVAL; - dev_err_probe(&pdev->dev, ret, "Property 'platform' missing or invalid\n"); - goto err_platform_node; - } - - playback_codec = of_get_child_by_name(pdev->dev.of_node, "playback-codecs"); - if (!playback_codec) { - ret = -EINVAL; - dev_err_probe(&pdev->dev, ret, "Property 'speaker-codecs' missing or invalid\n"); - goto err_playback_codec; - } - - headset_codec = of_get_child_by_name(pdev->dev.of_node, "headset-codec"); - if (!headset_codec) { - ret = -EINVAL; - dev_err_probe(&pdev->dev, ret, "Property 'headset-codec' missing or invalid\n"); - goto err_headset_codec; - } - - for_each_card_prelinks(card, i, dai_link) { - ret = mt8186_mt6366_card_set_be_link(card, dai_link, playback_codec, "I2S3"); - if (ret) { - dev_err_probe(&pdev->dev, ret, "%s set speaker_codec fail\n", - dai_link->name); - goto err_probe; - } - - ret = mt8186_mt6366_card_set_be_link(card, dai_link, headset_codec, "I2S0"); - if (ret) { - dev_err_probe(&pdev->dev, ret, "%s set headset_codec fail\n", - dai_link->name); - goto err_probe; - } - - ret = mt8186_mt6366_card_set_be_link(card, dai_link, headset_codec, "I2S1"); - if (ret) { - dev_err_probe(&pdev->dev, ret, "%s set headset_codec fail\n", - dai_link->name); - goto err_probe; - } - - if (!strncmp(dai_link->name, "AFE_SOF", strlen("AFE_SOF")) && sof_on) - dai_link->platforms->of_node = adsp_node; - - if (!dai_link->platforms->name && !dai_link->platforms->of_node) - dai_link->platforms->of_node = platform_node; - } - - snd_soc_card_set_drvdata(card, soc_card_data); - - ret = mt8186_afe_gpio_init(&pdev->dev); - if (ret) { - dev_err_probe(&pdev->dev, ret, "%s init gpio error\n", __func__); - goto err_probe; - } - - ret = devm_snd_soc_register_card(&pdev->dev, card); - if (ret) - dev_err_probe(&pdev->dev, ret, "%s snd_soc_register_card fail\n", __func__); - -err_probe: - of_node_put(headset_codec); -err_headset_codec: - of_node_put(playback_codec); -err_playback_codec: - of_node_put(platform_node); -err_platform_node: -err_adsp_node: - of_node_put(adsp_node); - - return ret; -} - -#if IS_ENABLED(CONFIG_OF) -static const struct of_device_id mt8186_mt6366_da7219_max98357_dt_match[] = { - { .compatible = "mediatek,mt8186-mt6366-da7219-max98357-sound", - .data = &mt8186_mt6366_da7219_max98357_soc_card, - }, - {} -}; -MODULE_DEVICE_TABLE(of, mt8186_mt6366_da7219_max98357_dt_match); -#endif - -static struct platform_driver mt8186_mt6366_da7219_max98357_driver = { - .driver = { - .name = "mt8186_mt6366_da7219_max98357", -#if IS_ENABLED(CONFIG_OF) - .of_match_table = mt8186_mt6366_da7219_max98357_dt_match, -#endif - .pm = &snd_soc_pm_ops, - }, - .probe = mt8186_mt6366_da7219_max98357_dev_probe, -}; - -module_platform_driver(mt8186_mt6366_da7219_max98357_driver); - -/* Module information */ -MODULE_DESCRIPTION("MT8186-MT6366-DA7219-MAX98357 ALSA SoC machine driver"); -MODULE_AUTHOR("Jiaxin Yu "); -MODULE_LICENSE("GPL v2"); -MODULE_ALIAS("mt8186_mt6366_da7219_max98357 soc card"); diff --git a/sound/soc/mediatek/mt8186/mt8186-mt6366-rt1019-rt5682s.c b/sound/soc/mediatek/mt8186/mt8186-mt6366-rt1019-rt5682s.c deleted file mode 100644 index 28140ca0ebff..000000000000 --- a/sound/soc/mediatek/mt8186/mt8186-mt6366-rt1019-rt5682s.c +++ /dev/null @@ -1,1232 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -// -// mt8186-mt6366-rt1019-rt5682s.c -// -- MT8186-MT6366-RT1019-RT5682S ALSA SoC machine driver -// -// Copyright (c) 2022 MediaTek Inc. -// Author: Jiaxin Yu -// - -#include -#include -#include -#include -#include -#include -#include -#include - -#include "../../codecs/mt6358.h" -#include "../../codecs/rt5682.h" -#include "../common/mtk-afe-platform-driver.h" -#include "../common/mtk-dsp-sof-common.h" -#include "../common/mtk-soc-card.h" -#include "../common/mtk-soundcard-driver.h" -#include "mt8186-afe-common.h" -#include "mt8186-afe-clk.h" -#include "mt8186-afe-gpio.h" -#include "mt8186-mt6366-common.h" - -#define RT1019_CODEC_DAI "HiFi" -#define RT1019_DEV0_NAME "rt1019p" - -#define RT5682S_CODEC_DAI "rt5682s-aif1" -#define RT5682S_DEV0_NAME "rt5682s.5-001a" - -#define SOF_DMA_DL1 "SOF_DMA_DL1" -#define SOF_DMA_DL2 "SOF_DMA_DL2" -#define SOF_DMA_UL1 "SOF_DMA_UL1" -#define SOF_DMA_UL2 "SOF_DMA_UL2" - -struct mt8186_mt6366_rt1019_rt5682s_priv { - struct gpio_desc *dmic_sel; - int dmic_switch; -}; - -enum mt8186_jacks { - MT8186_JACK_HEADSET, - MT8186_JACK_HDMI, - MT8186_JACK_MAX, -}; - -/* Headset jack detection DAPM pins */ -static struct snd_soc_jack_pin mt8186_jack_pins[] = { - { - .pin = "Headphone", - .mask = SND_JACK_HEADPHONE, - }, - { - .pin = "Headset Mic", - .mask = SND_JACK_MICROPHONE, - }, -}; - -static struct snd_soc_codec_conf mt8186_mt6366_rt1019_rt5682s_codec_conf[] = { - { - .dlc = COMP_CODEC_CONF("mt6358-sound"), - .name_prefix = "Mt6366", - }, - { - .dlc = COMP_CODEC_CONF("bt-sco"), - .name_prefix = "Mt8186 bt", - }, - { - .dlc = COMP_CODEC_CONF("hdmi-audio-codec"), - .name_prefix = "Mt8186 hdmi", - }, -}; - -static int dmic_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_soc_dapm_context *dapm = snd_soc_dapm_kcontrol_dapm(kcontrol); - struct mtk_soc_card_data *soc_card_data = - snd_soc_card_get_drvdata(dapm->card); - struct mt8186_mt6366_rt1019_rt5682s_priv *priv = soc_card_data->mach_priv; - - ucontrol->value.integer.value[0] = priv->dmic_switch; - return 0; -} - -static int dmic_set(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct snd_soc_dapm_context *dapm = snd_soc_dapm_kcontrol_dapm(kcontrol); - struct mtk_soc_card_data *soc_card_data = - snd_soc_card_get_drvdata(dapm->card); - struct mt8186_mt6366_rt1019_rt5682s_priv *priv = soc_card_data->mach_priv; - - priv->dmic_switch = ucontrol->value.integer.value[0]; - if (priv->dmic_sel) { - gpiod_set_value(priv->dmic_sel, priv->dmic_switch); - dev_dbg(dapm->card->dev, "dmic_set_value %d\n", - priv->dmic_switch); - } - return 0; -} - -static const char * const dmic_mux_text[] = { - "Front Mic", - "Rear Mic", -}; - -static SOC_ENUM_SINGLE_DECL(mt8186_dmic_enum, - SND_SOC_NOPM, 0, dmic_mux_text); - -static const struct snd_kcontrol_new mt8186_dmic_mux_control = - SOC_DAPM_ENUM_EXT("DMIC Select Mux", mt8186_dmic_enum, - dmic_get, dmic_set); - -static const struct snd_soc_dapm_widget dmic_widgets[] = { - SND_SOC_DAPM_MIC("DMIC", NULL), - SND_SOC_DAPM_MUX("Dmic Mux", SND_SOC_NOPM, 0, 0, &mt8186_dmic_mux_control), -}; - -static const struct snd_soc_dapm_route dmic_map[] = { - /* digital mics */ - {"Dmic Mux", "Front Mic", "DMIC"}, - {"Dmic Mux", "Rear Mic", "DMIC"}, -}; - -static int primary_codec_init(struct snd_soc_pcm_runtime *rtd) -{ - struct snd_soc_card *card = rtd->card; - struct mtk_soc_card_data *soc_card_data = snd_soc_card_get_drvdata(card); - struct mt8186_mt6366_rt1019_rt5682s_priv *priv = soc_card_data->mach_priv; - int ret; - - ret = mt8186_mt6366_init(rtd); - - if (ret) { - dev_err(card->dev, "mt8186_mt6366_init failed: %d\n", ret); - return ret; - } - - if (!priv->dmic_sel) { - dev_dbg(card->dev, "dmic_sel is null\n"); - return 0; - } - - ret = snd_soc_dapm_new_controls(&card->dapm, dmic_widgets, - ARRAY_SIZE(dmic_widgets)); - if (ret) { - dev_err(card->dev, "DMic widget addition failed: %d\n", ret); - /* Don't need to add routes if widget addition failed */ - return ret; - } - - ret = snd_soc_dapm_add_routes(&card->dapm, dmic_map, - ARRAY_SIZE(dmic_map)); - - if (ret) - dev_err(card->dev, "DMic map addition failed: %d\n", ret); - - return ret; -} - -static int mt8186_rt5682s_init(struct snd_soc_pcm_runtime *rtd) -{ - struct snd_soc_component *cmpnt_afe = - snd_soc_rtdcom_lookup(rtd, AFE_PCM_NAME); - struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt_afe); - struct mtk_soc_card_data *soc_card_data = - snd_soc_card_get_drvdata(rtd->card); - struct snd_soc_jack *jack = &soc_card_data->card_data->jacks[MT8186_JACK_HEADSET]; - struct snd_soc_component *cmpnt_codec = - snd_soc_rtd_to_codec(rtd, 0)->component; - int ret; - int type; - - ret = mt8186_dai_i2s_set_share(afe, "I2S1", "I2S0"); - if (ret) { - dev_err(rtd->dev, "Failed to set up shared clocks\n"); - return ret; - } - - ret = snd_soc_card_jack_new_pins(rtd->card, "Headset Jack", - SND_JACK_HEADSET | SND_JACK_BTN_0 | - SND_JACK_BTN_1 | SND_JACK_BTN_2 | - SND_JACK_BTN_3, - jack, mt8186_jack_pins, - ARRAY_SIZE(mt8186_jack_pins)); - if (ret) { - dev_err(rtd->dev, "Headset Jack creation failed: %d\n", ret); - return ret; - } - - snd_jack_set_key(jack->jack, SND_JACK_BTN_0, KEY_PLAYPAUSE); - snd_jack_set_key(jack->jack, SND_JACK_BTN_1, KEY_VOICECOMMAND); - snd_jack_set_key(jack->jack, SND_JACK_BTN_2, KEY_VOLUMEUP); - snd_jack_set_key(jack->jack, SND_JACK_BTN_3, KEY_VOLUMEDOWN); - - type = SND_JACK_HEADSET | SND_JACK_BTN_0 | SND_JACK_BTN_1 | SND_JACK_BTN_2 | SND_JACK_BTN_3; - return snd_soc_component_set_jack(cmpnt_codec, jack, (void *)&type); -} - -static int mt8186_rt5682s_i2s_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *params) -{ - struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_card *card = rtd->card; - struct snd_soc_dai *cpu_dai = snd_soc_rtd_to_cpu(rtd, 0); - struct snd_soc_dai *codec_dai = snd_soc_rtd_to_codec(rtd, 0); - unsigned int rate = params_rate(params); - unsigned int mclk_fs_ratio = 128; - unsigned int mclk_fs = rate * mclk_fs_ratio; - int bitwidth; - int ret; - - bitwidth = snd_pcm_format_width(params_format(params)); - if (bitwidth < 0) { - dev_err(card->dev, "invalid bit width: %d\n", bitwidth); - return bitwidth; - } - - ret = snd_soc_dai_set_tdm_slot(codec_dai, 0x00, 0x0, 0x2, bitwidth); - if (ret) { - dev_err(card->dev, "failed to set tdm slot\n"); - return ret; - } - - ret = snd_soc_dai_set_pll(codec_dai, RT5682_PLL1, - RT5682_PLL1_S_BCLK1, - params_rate(params) * 64, - params_rate(params) * 512); - if (ret) { - dev_err(card->dev, "failed to set pll\n"); - return ret; - } - - ret = snd_soc_dai_set_sysclk(codec_dai, - RT5682_SCLK_S_PLL1, - params_rate(params) * 512, - SND_SOC_CLOCK_IN); - if (ret) { - dev_err(card->dev, "failed to set sysclk\n"); - return ret; - } - - return snd_soc_dai_set_sysclk(cpu_dai, 0, mclk_fs, SND_SOC_CLOCK_OUT); -} - -static const struct snd_soc_ops mt8186_rt5682s_i2s_ops = { - .hw_params = mt8186_rt5682s_i2s_hw_params, -}; - -static int mt8186_mt6366_rt1019_rt5682s_hdmi_init(struct snd_soc_pcm_runtime *rtd) -{ - struct snd_soc_component *cmpnt_afe = - snd_soc_rtdcom_lookup(rtd, AFE_PCM_NAME); - struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt_afe); - struct snd_soc_component *cmpnt_codec = - snd_soc_rtd_to_codec(rtd, 0)->component; - struct mtk_soc_card_data *soc_card_data = - snd_soc_card_get_drvdata(rtd->card); - struct snd_soc_jack *jack = &soc_card_data->card_data->jacks[MT8186_JACK_HDMI]; - int ret; - - ret = mt8186_dai_i2s_set_share(afe, "I2S2", "I2S3"); - if (ret) { - dev_err(rtd->dev, "Failed to set up shared clocks\n"); - return ret; - } - - ret = snd_soc_card_jack_new(rtd->card, "HDMI Jack", SND_JACK_LINEOUT, jack); - if (ret) { - dev_err(rtd->dev, "HDMI Jack creation failed: %d\n", ret); - return ret; - } - - return snd_soc_component_set_jack(cmpnt_codec, jack, NULL); -} - -static int mt8186_hw_params_fixup(struct snd_soc_pcm_runtime *rtd, - struct snd_pcm_hw_params *params, - snd_pcm_format_t fmt) -{ - struct snd_interval *channels = hw_param_interval(params, - SNDRV_PCM_HW_PARAM_CHANNELS); - - dev_dbg(rtd->dev, "%s(), fix format to %d\n", __func__, fmt); - - /* fix BE i2s channel to 2 channel */ - channels->min = 2; - channels->max = 2; - - /* clean param mask first */ - snd_mask_reset_range(hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT), - 0, (__force unsigned int)SNDRV_PCM_FORMAT_LAST); - - params_set_format(params, fmt); - - return 0; -} - -static int mt8186_i2s_hw_params_fixup(struct snd_soc_pcm_runtime *rtd, - struct snd_pcm_hw_params *params) -{ - return mt8186_hw_params_fixup(rtd, params, SNDRV_PCM_FORMAT_S24_LE); -} - -static int mt8186_it6505_i2s_hw_params_fixup(struct snd_soc_pcm_runtime *rtd, - struct snd_pcm_hw_params *params) -{ - return mt8186_hw_params_fixup(rtd, params, SNDRV_PCM_FORMAT_S32_LE); -} - -/* fixup the BE DAI link to match any values from topology */ -static int mt8186_sof_dai_link_fixup(struct snd_soc_pcm_runtime *rtd, - struct snd_pcm_hw_params *params) -{ - int ret; - - ret = mtk_sof_dai_link_fixup(rtd, params); - - if (!strcmp(rtd->dai_link->name, "I2S0") || - !strcmp(rtd->dai_link->name, "I2S1") || - !strcmp(rtd->dai_link->name, "I2S2")) - mt8186_i2s_hw_params_fixup(rtd, params); - else if (!strcmp(rtd->dai_link->name, "I2S3")) - mt8186_it6505_i2s_hw_params_fixup(rtd, params); - - return ret; -} - -/* FE */ -SND_SOC_DAILINK_DEFS(playback1, - DAILINK_COMP_ARRAY(COMP_CPU("DL1")), - DAILINK_COMP_ARRAY(COMP_DUMMY()), - DAILINK_COMP_ARRAY(COMP_EMPTY())); - -SND_SOC_DAILINK_DEFS(playback12, - DAILINK_COMP_ARRAY(COMP_CPU("DL12")), - DAILINK_COMP_ARRAY(COMP_DUMMY()), - DAILINK_COMP_ARRAY(COMP_EMPTY())); - -SND_SOC_DAILINK_DEFS(playback2, - DAILINK_COMP_ARRAY(COMP_CPU("DL2")), - DAILINK_COMP_ARRAY(COMP_DUMMY()), - DAILINK_COMP_ARRAY(COMP_EMPTY())); - -SND_SOC_DAILINK_DEFS(playback3, - DAILINK_COMP_ARRAY(COMP_CPU("DL3")), - DAILINK_COMP_ARRAY(COMP_DUMMY()), - DAILINK_COMP_ARRAY(COMP_EMPTY())); - -SND_SOC_DAILINK_DEFS(playback4, - DAILINK_COMP_ARRAY(COMP_CPU("DL4")), - DAILINK_COMP_ARRAY(COMP_DUMMY()), - DAILINK_COMP_ARRAY(COMP_EMPTY())); - -SND_SOC_DAILINK_DEFS(playback5, - DAILINK_COMP_ARRAY(COMP_CPU("DL5")), - DAILINK_COMP_ARRAY(COMP_DUMMY()), - DAILINK_COMP_ARRAY(COMP_EMPTY())); - -SND_SOC_DAILINK_DEFS(playback6, - DAILINK_COMP_ARRAY(COMP_CPU("DL6")), - DAILINK_COMP_ARRAY(COMP_DUMMY()), - DAILINK_COMP_ARRAY(COMP_EMPTY())); - -SND_SOC_DAILINK_DEFS(playback7, - DAILINK_COMP_ARRAY(COMP_CPU("DL7")), - DAILINK_COMP_ARRAY(COMP_DUMMY()), - DAILINK_COMP_ARRAY(COMP_EMPTY())); - -SND_SOC_DAILINK_DEFS(playback8, - DAILINK_COMP_ARRAY(COMP_CPU("DL8")), - DAILINK_COMP_ARRAY(COMP_DUMMY()), - DAILINK_COMP_ARRAY(COMP_EMPTY())); - -SND_SOC_DAILINK_DEFS(capture1, - DAILINK_COMP_ARRAY(COMP_CPU("UL1")), - DAILINK_COMP_ARRAY(COMP_DUMMY()), - DAILINK_COMP_ARRAY(COMP_EMPTY())); - -SND_SOC_DAILINK_DEFS(capture2, - DAILINK_COMP_ARRAY(COMP_CPU("UL2")), - DAILINK_COMP_ARRAY(COMP_DUMMY()), - DAILINK_COMP_ARRAY(COMP_EMPTY())); - -SND_SOC_DAILINK_DEFS(capture3, - DAILINK_COMP_ARRAY(COMP_CPU("UL3")), - DAILINK_COMP_ARRAY(COMP_DUMMY()), - DAILINK_COMP_ARRAY(COMP_EMPTY())); - -SND_SOC_DAILINK_DEFS(capture4, - DAILINK_COMP_ARRAY(COMP_CPU("UL4")), - DAILINK_COMP_ARRAY(COMP_DUMMY()), - DAILINK_COMP_ARRAY(COMP_EMPTY())); - -SND_SOC_DAILINK_DEFS(capture5, - DAILINK_COMP_ARRAY(COMP_CPU("UL5")), - DAILINK_COMP_ARRAY(COMP_DUMMY()), - DAILINK_COMP_ARRAY(COMP_EMPTY())); - -SND_SOC_DAILINK_DEFS(capture6, - DAILINK_COMP_ARRAY(COMP_CPU("UL6")), - DAILINK_COMP_ARRAY(COMP_DUMMY()), - DAILINK_COMP_ARRAY(COMP_EMPTY())); - -SND_SOC_DAILINK_DEFS(capture7, - DAILINK_COMP_ARRAY(COMP_CPU("UL7")), - DAILINK_COMP_ARRAY(COMP_DUMMY()), - DAILINK_COMP_ARRAY(COMP_EMPTY())); - -/* hostless */ -SND_SOC_DAILINK_DEFS(hostless_lpbk, - DAILINK_COMP_ARRAY(COMP_CPU("Hostless LPBK DAI")), - DAILINK_COMP_ARRAY(COMP_DUMMY()), - DAILINK_COMP_ARRAY(COMP_EMPTY())); -SND_SOC_DAILINK_DEFS(hostless_fm, - DAILINK_COMP_ARRAY(COMP_CPU("Hostless FM DAI")), - DAILINK_COMP_ARRAY(COMP_DUMMY()), - DAILINK_COMP_ARRAY(COMP_EMPTY())); -SND_SOC_DAILINK_DEFS(hostless_src1, - DAILINK_COMP_ARRAY(COMP_CPU("Hostless_SRC_1_DAI")), - DAILINK_COMP_ARRAY(COMP_DUMMY()), - DAILINK_COMP_ARRAY(COMP_EMPTY())); -SND_SOC_DAILINK_DEFS(hostless_src_bargein, - DAILINK_COMP_ARRAY(COMP_CPU("Hostless_SRC_Bargein_DAI")), - DAILINK_COMP_ARRAY(COMP_DUMMY()), - DAILINK_COMP_ARRAY(COMP_EMPTY())); - -/* BE */ -SND_SOC_DAILINK_DEFS(adda, - DAILINK_COMP_ARRAY(COMP_CPU("ADDA")), - DAILINK_COMP_ARRAY(COMP_CODEC("mt6358-sound", - "mt6358-snd-codec-aif1"), - COMP_CODEC("dmic-codec", - "dmic-hifi")), - DAILINK_COMP_ARRAY(COMP_EMPTY())); -SND_SOC_DAILINK_DEFS(i2s0, - DAILINK_COMP_ARRAY(COMP_CPU("I2S0")), - DAILINK_COMP_ARRAY(COMP_EMPTY()), - DAILINK_COMP_ARRAY(COMP_EMPTY())); -SND_SOC_DAILINK_DEFS(i2s1, - DAILINK_COMP_ARRAY(COMP_CPU("I2S1")), - DAILINK_COMP_ARRAY(COMP_EMPTY()), - DAILINK_COMP_ARRAY(COMP_EMPTY())); -SND_SOC_DAILINK_DEFS(i2s2, - DAILINK_COMP_ARRAY(COMP_CPU("I2S2")), - DAILINK_COMP_ARRAY(COMP_DUMMY()), - DAILINK_COMP_ARRAY(COMP_EMPTY())); -SND_SOC_DAILINK_DEFS(i2s3, - DAILINK_COMP_ARRAY(COMP_CPU("I2S3")), - DAILINK_COMP_ARRAY(COMP_EMPTY()), - DAILINK_COMP_ARRAY(COMP_EMPTY())); -SND_SOC_DAILINK_DEFS(hw_gain1, - DAILINK_COMP_ARRAY(COMP_CPU("HW Gain 1")), - DAILINK_COMP_ARRAY(COMP_DUMMY()), - DAILINK_COMP_ARRAY(COMP_EMPTY())); -SND_SOC_DAILINK_DEFS(hw_gain2, - DAILINK_COMP_ARRAY(COMP_CPU("HW Gain 2")), - DAILINK_COMP_ARRAY(COMP_DUMMY()), - DAILINK_COMP_ARRAY(COMP_EMPTY())); -SND_SOC_DAILINK_DEFS(hw_src1, - DAILINK_COMP_ARRAY(COMP_CPU("HW_SRC_1")), - DAILINK_COMP_ARRAY(COMP_DUMMY()), - DAILINK_COMP_ARRAY(COMP_EMPTY())); -SND_SOC_DAILINK_DEFS(hw_src2, - DAILINK_COMP_ARRAY(COMP_CPU("HW_SRC_2")), - DAILINK_COMP_ARRAY(COMP_DUMMY()), - DAILINK_COMP_ARRAY(COMP_EMPTY())); -SND_SOC_DAILINK_DEFS(connsys_i2s, - DAILINK_COMP_ARRAY(COMP_CPU("CONNSYS_I2S")), - DAILINK_COMP_ARRAY(COMP_DUMMY()), - DAILINK_COMP_ARRAY(COMP_EMPTY())); -SND_SOC_DAILINK_DEFS(pcm1, - DAILINK_COMP_ARRAY(COMP_CPU("PCM 1")), - DAILINK_COMP_ARRAY(COMP_CODEC("bt-sco", "bt-sco-pcm-wb")), - DAILINK_COMP_ARRAY(COMP_EMPTY())); -SND_SOC_DAILINK_DEFS(tdm_in, - DAILINK_COMP_ARRAY(COMP_CPU("TDM IN")), - DAILINK_COMP_ARRAY(COMP_DUMMY()), - DAILINK_COMP_ARRAY(COMP_EMPTY())); - -/* hostless */ -SND_SOC_DAILINK_DEFS(hostless_ul1, - DAILINK_COMP_ARRAY(COMP_CPU("Hostless_UL1 DAI")), - DAILINK_COMP_ARRAY(COMP_DUMMY()), - DAILINK_COMP_ARRAY(COMP_EMPTY())); -SND_SOC_DAILINK_DEFS(hostless_ul2, - DAILINK_COMP_ARRAY(COMP_CPU("Hostless_UL2 DAI")), - DAILINK_COMP_ARRAY(COMP_DUMMY()), - DAILINK_COMP_ARRAY(COMP_EMPTY())); -SND_SOC_DAILINK_DEFS(hostless_ul3, - DAILINK_COMP_ARRAY(COMP_CPU("Hostless_UL3 DAI")), - DAILINK_COMP_ARRAY(COMP_DUMMY()), - DAILINK_COMP_ARRAY(COMP_EMPTY())); -SND_SOC_DAILINK_DEFS(hostless_ul5, - DAILINK_COMP_ARRAY(COMP_CPU("Hostless_UL5 DAI")), - DAILINK_COMP_ARRAY(COMP_DUMMY()), - DAILINK_COMP_ARRAY(COMP_EMPTY())); -SND_SOC_DAILINK_DEFS(hostless_ul6, - DAILINK_COMP_ARRAY(COMP_CPU("Hostless_UL6 DAI")), - DAILINK_COMP_ARRAY(COMP_DUMMY()), - DAILINK_COMP_ARRAY(COMP_EMPTY())); -SND_SOC_DAILINK_DEFS(hostless_hw_gain_aaudio, - DAILINK_COMP_ARRAY(COMP_CPU("Hostless HW Gain AAudio DAI")), - DAILINK_COMP_ARRAY(COMP_DUMMY()), - DAILINK_COMP_ARRAY(COMP_EMPTY())); -SND_SOC_DAILINK_DEFS(hostless_src_aaudio, - DAILINK_COMP_ARRAY(COMP_CPU("Hostless SRC AAudio DAI")), - DAILINK_COMP_ARRAY(COMP_DUMMY()), - DAILINK_COMP_ARRAY(COMP_EMPTY())); -SND_SOC_DAILINK_DEFS(AFE_SOF_DL1, - DAILINK_COMP_ARRAY(COMP_CPU("SOF_DL1")), - DAILINK_COMP_ARRAY(COMP_DUMMY()), - DAILINK_COMP_ARRAY(COMP_EMPTY())); - -SND_SOC_DAILINK_DEFS(AFE_SOF_DL2, - DAILINK_COMP_ARRAY(COMP_CPU("SOF_DL2")), - DAILINK_COMP_ARRAY(COMP_DUMMY()), - DAILINK_COMP_ARRAY(COMP_EMPTY())); - -SND_SOC_DAILINK_DEFS(AFE_SOF_UL1, - DAILINK_COMP_ARRAY(COMP_CPU("SOF_UL1")), - DAILINK_COMP_ARRAY(COMP_DUMMY()), - DAILINK_COMP_ARRAY(COMP_EMPTY())); - -SND_SOC_DAILINK_DEFS(AFE_SOF_UL2, - DAILINK_COMP_ARRAY(COMP_CPU("SOF_UL2")), - DAILINK_COMP_ARRAY(COMP_DUMMY()), - DAILINK_COMP_ARRAY(COMP_EMPTY())); - -static const struct sof_conn_stream g_sof_conn_streams[] = { - { "I2S1", "AFE_SOF_DL1", SOF_DMA_DL1, SNDRV_PCM_STREAM_PLAYBACK}, - { "I2S3", "AFE_SOF_DL2", SOF_DMA_DL2, SNDRV_PCM_STREAM_PLAYBACK}, - { "Primary Codec", "AFE_SOF_UL1", SOF_DMA_UL1, SNDRV_PCM_STREAM_CAPTURE}, - { "I2S0", "AFE_SOF_UL2", SOF_DMA_UL2, SNDRV_PCM_STREAM_CAPTURE}, -}; - -static struct snd_soc_dai_link mt8186_mt6366_rt1019_rt5682s_dai_links[] = { - /* Front End DAI links */ - { - .name = "Playback_1", - .stream_name = "Playback_1", - .trigger = {SND_SOC_DPCM_TRIGGER_PRE, - SND_SOC_DPCM_TRIGGER_PRE}, - .dynamic = 1, - .dpcm_playback = 1, - .dpcm_merged_format = 1, - .dpcm_merged_chan = 1, - .dpcm_merged_rate = 1, - .ops = &mtk_soundcard_common_playback_ops, - SND_SOC_DAILINK_REG(playback1), - }, - { - .name = "Playback_12", - .stream_name = "Playback_12", - .trigger = {SND_SOC_DPCM_TRIGGER_PRE, - SND_SOC_DPCM_TRIGGER_PRE}, - .dynamic = 1, - .dpcm_playback = 1, - SND_SOC_DAILINK_REG(playback12), - }, - { - .name = "Playback_2", - .stream_name = "Playback_2", - .trigger = {SND_SOC_DPCM_TRIGGER_PRE, - SND_SOC_DPCM_TRIGGER_PRE}, - .dynamic = 1, - .dpcm_playback = 1, - .dpcm_merged_format = 1, - .dpcm_merged_chan = 1, - .dpcm_merged_rate = 1, - SND_SOC_DAILINK_REG(playback2), - }, - { - .name = "Playback_3", - .stream_name = "Playback_3", - .trigger = {SND_SOC_DPCM_TRIGGER_PRE, - SND_SOC_DPCM_TRIGGER_PRE}, - .dynamic = 1, - .dpcm_playback = 1, - .dpcm_merged_format = 1, - .dpcm_merged_chan = 1, - .dpcm_merged_rate = 1, - .ops = &mtk_soundcard_common_playback_ops, - SND_SOC_DAILINK_REG(playback3), - }, - { - .name = "Playback_4", - .stream_name = "Playback_4", - .trigger = {SND_SOC_DPCM_TRIGGER_PRE, - SND_SOC_DPCM_TRIGGER_PRE}, - .dynamic = 1, - .dpcm_playback = 1, - SND_SOC_DAILINK_REG(playback4), - }, - { - .name = "Playback_5", - .stream_name = "Playback_5", - .trigger = {SND_SOC_DPCM_TRIGGER_PRE, - SND_SOC_DPCM_TRIGGER_PRE}, - .dynamic = 1, - .dpcm_playback = 1, - SND_SOC_DAILINK_REG(playback5), - }, - { - .name = "Playback_6", - .stream_name = "Playback_6", - .trigger = {SND_SOC_DPCM_TRIGGER_PRE, - SND_SOC_DPCM_TRIGGER_PRE}, - .dynamic = 1, - .dpcm_playback = 1, - SND_SOC_DAILINK_REG(playback6), - }, - { - .name = "Playback_7", - .stream_name = "Playback_7", - .trigger = {SND_SOC_DPCM_TRIGGER_PRE, - SND_SOC_DPCM_TRIGGER_PRE}, - .dynamic = 1, - .dpcm_playback = 1, - SND_SOC_DAILINK_REG(playback7), - }, - { - .name = "Playback_8", - .stream_name = "Playback_8", - .trigger = {SND_SOC_DPCM_TRIGGER_PRE, - SND_SOC_DPCM_TRIGGER_PRE}, - .dynamic = 1, - .dpcm_playback = 1, - SND_SOC_DAILINK_REG(playback8), - }, - { - .name = "Capture_1", - .stream_name = "Capture_1", - .trigger = {SND_SOC_DPCM_TRIGGER_PRE, - SND_SOC_DPCM_TRIGGER_PRE}, - .dynamic = 1, - .dpcm_capture = 1, - SND_SOC_DAILINK_REG(capture1), - }, - { - .name = "Capture_2", - .stream_name = "Capture_2", - .trigger = {SND_SOC_DPCM_TRIGGER_PRE, - SND_SOC_DPCM_TRIGGER_PRE}, - .dynamic = 1, - .dpcm_capture = 1, - .dpcm_merged_format = 1, - .dpcm_merged_chan = 1, - .dpcm_merged_rate = 1, - .ops = &mtk_soundcard_common_capture_ops, - SND_SOC_DAILINK_REG(capture2), - }, - { - .name = "Capture_3", - .stream_name = "Capture_3", - .trigger = {SND_SOC_DPCM_TRIGGER_PRE, - SND_SOC_DPCM_TRIGGER_PRE}, - .dynamic = 1, - .dpcm_capture = 1, - SND_SOC_DAILINK_REG(capture3), - }, - { - .name = "Capture_4", - .stream_name = "Capture_4", - .trigger = {SND_SOC_DPCM_TRIGGER_PRE, - SND_SOC_DPCM_TRIGGER_PRE}, - .dynamic = 1, - .dpcm_capture = 1, - .dpcm_merged_format = 1, - .dpcm_merged_chan = 1, - .dpcm_merged_rate = 1, - .ops = &mtk_soundcard_common_capture_ops, - SND_SOC_DAILINK_REG(capture4), - }, - { - .name = "Capture_5", - .stream_name = "Capture_5", - .trigger = {SND_SOC_DPCM_TRIGGER_PRE, - SND_SOC_DPCM_TRIGGER_PRE}, - .dynamic = 1, - .dpcm_capture = 1, - SND_SOC_DAILINK_REG(capture5), - }, - { - .name = "Capture_6", - .stream_name = "Capture_6", - .trigger = {SND_SOC_DPCM_TRIGGER_PRE, - SND_SOC_DPCM_TRIGGER_PRE}, - .dynamic = 1, - .dpcm_capture = 1, - .dpcm_merged_format = 1, - .dpcm_merged_chan = 1, - .dpcm_merged_rate = 1, - SND_SOC_DAILINK_REG(capture6), - }, - { - .name = "Capture_7", - .stream_name = "Capture_7", - .trigger = {SND_SOC_DPCM_TRIGGER_PRE, - SND_SOC_DPCM_TRIGGER_PRE}, - .dynamic = 1, - .dpcm_capture = 1, - SND_SOC_DAILINK_REG(capture7), - }, - { - .name = "Hostless_LPBK", - .stream_name = "Hostless_LPBK", - .trigger = {SND_SOC_DPCM_TRIGGER_PRE, - SND_SOC_DPCM_TRIGGER_PRE}, - .dynamic = 1, - .dpcm_playback = 1, - .dpcm_capture = 1, - .ignore_suspend = 1, - SND_SOC_DAILINK_REG(hostless_lpbk), - }, - { - .name = "Hostless_FM", - .stream_name = "Hostless_FM", - .trigger = {SND_SOC_DPCM_TRIGGER_PRE, - SND_SOC_DPCM_TRIGGER_PRE}, - .dynamic = 1, - .dpcm_playback = 1, - .dpcm_capture = 1, - .ignore_suspend = 1, - SND_SOC_DAILINK_REG(hostless_fm), - }, - { - .name = "Hostless_SRC_1", - .stream_name = "Hostless_SRC_1", - .trigger = {SND_SOC_DPCM_TRIGGER_PRE, - SND_SOC_DPCM_TRIGGER_PRE}, - .dynamic = 1, - .dpcm_playback = 1, - .dpcm_capture = 1, - .ignore_suspend = 1, - SND_SOC_DAILINK_REG(hostless_src1), - }, - { - .name = "Hostless_SRC_Bargein", - .stream_name = "Hostless_SRC_Bargein", - .trigger = {SND_SOC_DPCM_TRIGGER_PRE, - SND_SOC_DPCM_TRIGGER_PRE}, - .dynamic = 1, - .dpcm_playback = 1, - .dpcm_capture = 1, - .ignore_suspend = 1, - SND_SOC_DAILINK_REG(hostless_src_bargein), - }, - { - .name = "Hostless_HW_Gain_AAudio", - .stream_name = "Hostless_HW_Gain_AAudio", - .trigger = {SND_SOC_DPCM_TRIGGER_PRE, - SND_SOC_DPCM_TRIGGER_PRE}, - .dynamic = 1, - .dpcm_capture = 1, - .ignore_suspend = 1, - SND_SOC_DAILINK_REG(hostless_hw_gain_aaudio), - }, - { - .name = "Hostless_SRC_AAudio", - .stream_name = "Hostless_SRC_AAudio", - .trigger = {SND_SOC_DPCM_TRIGGER_PRE, - SND_SOC_DPCM_TRIGGER_PRE}, - .dynamic = 1, - .dpcm_playback = 1, - .dpcm_capture = 1, - .ignore_suspend = 1, - SND_SOC_DAILINK_REG(hostless_src_aaudio), - }, - /* Back End DAI links */ - { - .name = "Primary Codec", - .no_pcm = 1, - .dpcm_playback = 1, - .dpcm_capture = 1, - .ignore_suspend = 1, - .init = primary_codec_init, - SND_SOC_DAILINK_REG(adda), - }, - { - .name = "I2S3", - .no_pcm = 1, - .dai_fmt = SND_SOC_DAIFMT_I2S | - SND_SOC_DAIFMT_IB_IF | - SND_SOC_DAIFMT_CBM_CFM, - .dpcm_playback = 1, - .ignore_suspend = 1, - .init = mt8186_mt6366_rt1019_rt5682s_hdmi_init, - .be_hw_params_fixup = mt8186_it6505_i2s_hw_params_fixup, - SND_SOC_DAILINK_REG(i2s3), - }, - { - .name = "I2S0", - .no_pcm = 1, - .dpcm_capture = 1, - .ignore_suspend = 1, - .be_hw_params_fixup = mt8186_i2s_hw_params_fixup, - .ops = &mt8186_rt5682s_i2s_ops, - SND_SOC_DAILINK_REG(i2s0), - }, - { - .name = "I2S1", - .no_pcm = 1, - .dpcm_playback = 1, - .ignore_suspend = 1, - .be_hw_params_fixup = mt8186_i2s_hw_params_fixup, - .init = mt8186_rt5682s_init, - .ops = &mt8186_rt5682s_i2s_ops, - SND_SOC_DAILINK_REG(i2s1), - }, - { - .name = "I2S2", - .no_pcm = 1, - .dpcm_capture = 1, - .ignore_suspend = 1, - .be_hw_params_fixup = mt8186_i2s_hw_params_fixup, - SND_SOC_DAILINK_REG(i2s2), - }, - { - .name = "HW Gain 1", - .no_pcm = 1, - .dpcm_playback = 1, - .dpcm_capture = 1, - .ignore_suspend = 1, - SND_SOC_DAILINK_REG(hw_gain1), - }, - { - .name = "HW Gain 2", - .no_pcm = 1, - .dpcm_playback = 1, - .dpcm_capture = 1, - .ignore_suspend = 1, - SND_SOC_DAILINK_REG(hw_gain2), - }, - { - .name = "HW_SRC_1", - .no_pcm = 1, - .dpcm_playback = 1, - .dpcm_capture = 1, - .ignore_suspend = 1, - SND_SOC_DAILINK_REG(hw_src1), - }, - { - .name = "HW_SRC_2", - .no_pcm = 1, - .dpcm_playback = 1, - .dpcm_capture = 1, - .ignore_suspend = 1, - SND_SOC_DAILINK_REG(hw_src2), - }, - { - .name = "CONNSYS_I2S", - .no_pcm = 1, - .dpcm_capture = 1, - .ignore_suspend = 1, - SND_SOC_DAILINK_REG(connsys_i2s), - }, - { - .name = "PCM 1", - .dai_fmt = SND_SOC_DAIFMT_I2S | - SND_SOC_DAIFMT_NB_IF, - .no_pcm = 1, - .dpcm_playback = 1, - .dpcm_capture = 1, - .ignore_suspend = 1, - SND_SOC_DAILINK_REG(pcm1), - }, - { - .name = "TDM IN", - .no_pcm = 1, - .dpcm_capture = 1, - .ignore_suspend = 1, - SND_SOC_DAILINK_REG(tdm_in), - }, - /* dummy BE for ul memif to record from dl memif */ - { - .name = "Hostless_UL1", - .no_pcm = 1, - .dpcm_capture = 1, - .ignore_suspend = 1, - SND_SOC_DAILINK_REG(hostless_ul1), - }, - { - .name = "Hostless_UL2", - .no_pcm = 1, - .dpcm_capture = 1, - .ignore_suspend = 1, - SND_SOC_DAILINK_REG(hostless_ul2), - }, - { - .name = "Hostless_UL3", - .no_pcm = 1, - .dpcm_capture = 1, - .ignore_suspend = 1, - SND_SOC_DAILINK_REG(hostless_ul3), - }, - { - .name = "Hostless_UL5", - .no_pcm = 1, - .dpcm_capture = 1, - .ignore_suspend = 1, - SND_SOC_DAILINK_REG(hostless_ul5), - }, - { - .name = "Hostless_UL6", - .no_pcm = 1, - .dpcm_capture = 1, - .ignore_suspend = 1, - SND_SOC_DAILINK_REG(hostless_ul6), - }, - /* SOF BE */ - { - .name = "AFE_SOF_DL1", - .no_pcm = 1, - .dpcm_playback = 1, - SND_SOC_DAILINK_REG(AFE_SOF_DL1), - }, - { - .name = "AFE_SOF_DL2", - .no_pcm = 1, - .dpcm_playback = 1, - SND_SOC_DAILINK_REG(AFE_SOF_DL2), - }, - { - .name = "AFE_SOF_UL1", - .no_pcm = 1, - .dpcm_capture = 1, - SND_SOC_DAILINK_REG(AFE_SOF_UL1), - }, - { - .name = "AFE_SOF_UL2", - .no_pcm = 1, - .dpcm_capture = 1, - SND_SOC_DAILINK_REG(AFE_SOF_UL2), - }, -}; - -static const struct snd_soc_dapm_widget -mt8186_mt6366_rt1019_rt5682s_widgets[] = { - SND_SOC_DAPM_SPK("Speakers", NULL), - SND_SOC_DAPM_HP("Headphone", NULL), - SND_SOC_DAPM_MIC("Headset Mic", NULL), - SND_SOC_DAPM_OUTPUT("HDMI1"), - SND_SOC_DAPM_MIXER(SOF_DMA_DL1, SND_SOC_NOPM, 0, 0, NULL, 0), - SND_SOC_DAPM_MIXER(SOF_DMA_DL2, SND_SOC_NOPM, 0, 0, NULL, 0), - SND_SOC_DAPM_MIXER(SOF_DMA_UL1, SND_SOC_NOPM, 0, 0, NULL, 0), - SND_SOC_DAPM_MIXER(SOF_DMA_UL2, SND_SOC_NOPM, 0, 0, NULL, 0), -}; - -static const struct snd_soc_dapm_route -mt8186_mt6366_rt1019_rt5682s_routes[] = { - /* SPK */ - { "Speakers", NULL, "Speaker" }, - /* Headset */ - { "Headphone", NULL, "HPOL" }, - { "Headphone", NULL, "HPOR" }, - { "IN1P", NULL, "Headset Mic" }, - /* HDMI */ - { "HDMI1", NULL, "TX" }, - /* SOF Uplink */ - {SOF_DMA_UL1, NULL, "UL1_CH1"}, - {SOF_DMA_UL1, NULL, "UL1_CH2"}, - {SOF_DMA_UL2, NULL, "UL2_CH1"}, - {SOF_DMA_UL2, NULL, "UL2_CH2"}, - /* SOF Downlink */ - {"DSP_DL1_VIRT", NULL, SOF_DMA_DL1}, - {"DSP_DL2_VIRT", NULL, SOF_DMA_DL2}, -}; - -static const struct snd_soc_dapm_route mt8186_mt6366_rt5650_routes[] = { - /* SPK */ - {"Speakers", NULL, "SPOL"}, - {"Speakers", NULL, "SPOR"}, - /* Headset */ - { "Headphone", NULL, "HPOL" }, - { "Headphone", NULL, "HPOR" }, - { "IN1P", NULL, "Headset Mic" }, - { "IN1N", NULL, "Headset Mic"}, - /* HDMI */ - { "HDMI1", NULL, "TX" }, - /* SOF Uplink */ - {SOF_DMA_UL1, NULL, "UL1_CH1"}, - {SOF_DMA_UL1, NULL, "UL1_CH2"}, - {SOF_DMA_UL2, NULL, "UL2_CH1"}, - {SOF_DMA_UL2, NULL, "UL2_CH2"}, - /* SOF Downlink */ - {"DSP_DL1_VIRT", NULL, SOF_DMA_DL1}, - {"DSP_DL2_VIRT", NULL, SOF_DMA_DL2}, -}; - -static const struct snd_kcontrol_new -mt8186_mt6366_rt1019_rt5682s_controls[] = { - SOC_DAPM_PIN_SWITCH("Speakers"), - SOC_DAPM_PIN_SWITCH("Headphone"), - SOC_DAPM_PIN_SWITCH("Headset Mic"), - SOC_DAPM_PIN_SWITCH("HDMI1"), -}; - -static struct snd_soc_card mt8186_mt6366_rt1019_rt5682s_soc_card = { - .name = "mt8186_rt1019_rt5682s", - .owner = THIS_MODULE, - .dai_link = mt8186_mt6366_rt1019_rt5682s_dai_links, - .num_links = ARRAY_SIZE(mt8186_mt6366_rt1019_rt5682s_dai_links), - .controls = mt8186_mt6366_rt1019_rt5682s_controls, - .num_controls = ARRAY_SIZE(mt8186_mt6366_rt1019_rt5682s_controls), - .dapm_widgets = mt8186_mt6366_rt1019_rt5682s_widgets, - .num_dapm_widgets = ARRAY_SIZE(mt8186_mt6366_rt1019_rt5682s_widgets), - .dapm_routes = mt8186_mt6366_rt1019_rt5682s_routes, - .num_dapm_routes = ARRAY_SIZE(mt8186_mt6366_rt1019_rt5682s_routes), - .codec_conf = mt8186_mt6366_rt1019_rt5682s_codec_conf, - .num_configs = ARRAY_SIZE(mt8186_mt6366_rt1019_rt5682s_codec_conf), -}; - -static struct snd_soc_card mt8186_mt6366_rt5682s_max98360_soc_card = { - .name = "mt8186_rt5682s_max98360", - .owner = THIS_MODULE, - .dai_link = mt8186_mt6366_rt1019_rt5682s_dai_links, - .num_links = ARRAY_SIZE(mt8186_mt6366_rt1019_rt5682s_dai_links), - .controls = mt8186_mt6366_rt1019_rt5682s_controls, - .num_controls = ARRAY_SIZE(mt8186_mt6366_rt1019_rt5682s_controls), - .dapm_widgets = mt8186_mt6366_rt1019_rt5682s_widgets, - .num_dapm_widgets = ARRAY_SIZE(mt8186_mt6366_rt1019_rt5682s_widgets), - .dapm_routes = mt8186_mt6366_rt1019_rt5682s_routes, - .num_dapm_routes = ARRAY_SIZE(mt8186_mt6366_rt1019_rt5682s_routes), - .codec_conf = mt8186_mt6366_rt1019_rt5682s_codec_conf, - .num_configs = ARRAY_SIZE(mt8186_mt6366_rt1019_rt5682s_codec_conf), -}; - -static struct snd_soc_card mt8186_mt6366_rt5650_soc_card = { - .name = "mt8186_rt5650", - .owner = THIS_MODULE, - .dai_link = mt8186_mt6366_rt1019_rt5682s_dai_links, - .num_links = ARRAY_SIZE(mt8186_mt6366_rt1019_rt5682s_dai_links), - .controls = mt8186_mt6366_rt1019_rt5682s_controls, - .num_controls = ARRAY_SIZE(mt8186_mt6366_rt1019_rt5682s_controls), - .dapm_widgets = mt8186_mt6366_rt1019_rt5682s_widgets, - .num_dapm_widgets = ARRAY_SIZE(mt8186_mt6366_rt1019_rt5682s_widgets), - .dapm_routes = mt8186_mt6366_rt5650_routes, - .num_dapm_routes = ARRAY_SIZE(mt8186_mt6366_rt5650_routes), - .codec_conf = mt8186_mt6366_rt1019_rt5682s_codec_conf, - .num_configs = ARRAY_SIZE(mt8186_mt6366_rt1019_rt5682s_codec_conf), -}; - -static int mt8186_mt6366_legacy_probe(struct mtk_soc_card_data *soc_card_data) -{ - struct mtk_platform_card_data *card_data = soc_card_data->card_data; - struct snd_soc_card *card = card_data->card; - struct device *dev = card->dev; - struct snd_soc_dai_link *dai_link; - struct device_node *headset_codec, *playback_codec; - int ret, i; - - playback_codec = of_get_child_by_name(dev->of_node, "playback-codecs"); - if (!playback_codec) - return dev_err_probe(dev, -EINVAL, - "Property 'playback-codecs' missing or invalid\n"); - - headset_codec = of_get_child_by_name(dev->of_node, "headset-codec"); - if (!headset_codec) { - of_node_put(playback_codec); - return dev_err_probe(dev, -EINVAL, - "Property 'headset-codec' missing or invalid\n"); - } - - for_each_card_prelinks(card, i, dai_link) { - ret = mt8186_mt6366_card_set_be_link(card, dai_link, playback_codec, "I2S3"); - if (ret) { - dev_err_probe(dev, ret, "%s set playback_codec fail\n", - dai_link->name); - break; - } - - ret = mt8186_mt6366_card_set_be_link(card, dai_link, headset_codec, "I2S0"); - if (ret) { - dev_err_probe(dev, ret, "%s set headset_codec fail\n", - dai_link->name); - break; - } - - ret = mt8186_mt6366_card_set_be_link(card, dai_link, headset_codec, "I2S1"); - if (ret) { - dev_err_probe(dev, ret, "%s set headset_codec fail\n", - dai_link->name); - break; - } - } - of_node_put(headset_codec); - of_node_put(playback_codec); - - return ret; -} - -static int mt8186_mt6366_soc_card_probe(struct mtk_soc_card_data *soc_card_data, bool legacy) -{ - struct mtk_platform_card_data *card_data = soc_card_data->card_data; - struct snd_soc_card *card = card_data->card; - struct mt8186_mt6366_rt1019_rt5682s_priv *mach_priv; - int ret; - - mach_priv = devm_kzalloc(card->dev, sizeof(*mach_priv), GFP_KERNEL); - if (!mach_priv) - return -ENOMEM; - - soc_card_data->mach_priv = mach_priv; - - mach_priv->dmic_sel = devm_gpiod_get_optional(card->dev, - "dmic", GPIOD_OUT_LOW); - if (IS_ERR(mach_priv->dmic_sel)) - return dev_err_probe(card->dev, PTR_ERR(mach_priv->dmic_sel), - "DMIC gpio failed\n"); - - if (legacy) { - ret = mt8186_mt6366_legacy_probe(soc_card_data); - if (ret) - return ret; - } - - ret = mt8186_afe_gpio_init(card->dev); - if (ret) - return dev_err_probe(card->dev, ret, "init AFE gpio error\n"); - - return 0; -} - -static const unsigned int mt8186_pcm_playback_channels[] = { 2 }; -static const unsigned int mt8186_pcm_capture_channels[] = { 1, 2 }; -static const unsigned int mt8186_pcm_rates[] = { 48000 }; - -static const struct snd_pcm_hw_constraint_list mt8186_rate_constraint = { - .list = mt8186_pcm_rates, - .count = ARRAY_SIZE(mt8186_pcm_rates) -}; - -static const struct mtk_pcm_constraints_data mt8186_pcm_constraints[MTK_CONSTRAINT_CAPTURE + 1] = { - [MTK_CONSTRAINT_PLAYBACK] = { - .channels = &(const struct snd_pcm_hw_constraint_list) { - .list = mt8186_pcm_playback_channels, - .count = ARRAY_SIZE(mt8186_pcm_playback_channels) - }, - .rates = &mt8186_rate_constraint, - }, - [MTK_CONSTRAINT_CAPTURE] = { - .channels = &(const struct snd_pcm_hw_constraint_list) { - .list = mt8186_pcm_capture_channels, - .count = ARRAY_SIZE(mt8186_pcm_capture_channels) - }, - .rates = &mt8186_rate_constraint, - } -}; - -static const struct mtk_sof_priv mt8186_sof_priv = { - .conn_streams = g_sof_conn_streams, - .num_streams = ARRAY_SIZE(g_sof_conn_streams), - .sof_dai_link_fixup = mt8186_sof_dai_link_fixup -}; - -static const struct mtk_soundcard_pdata mt8186_mt6366_rt1019_rt5682s_pdata = { - .card_data = &(struct mtk_platform_card_data) { - .card = &mt8186_mt6366_rt1019_rt5682s_soc_card, - .num_jacks = MT8186_JACK_MAX, - .pcm_constraints = mt8186_pcm_constraints, - .num_pcm_constraints = ARRAY_SIZE(mt8186_pcm_constraints), - }, - .sof_priv = &mt8186_sof_priv, - .soc_probe = mt8186_mt6366_soc_card_probe -}; - -static const struct mtk_soundcard_pdata mt8186_mt6366_rt5682s_max98360_pdata = { - .card_data = &(struct mtk_platform_card_data) { - .card = &mt8186_mt6366_rt5682s_max98360_soc_card, - .num_jacks = MT8186_JACK_MAX, - .pcm_constraints = mt8186_pcm_constraints, - .num_pcm_constraints = ARRAY_SIZE(mt8186_pcm_constraints), - }, - .sof_priv = &mt8186_sof_priv, - .soc_probe = mt8186_mt6366_soc_card_probe -}; - -static const struct mtk_soundcard_pdata mt8186_mt6366_rt5650_pdata = { - .card_data = &(struct mtk_platform_card_data) { - .card = &mt8186_mt6366_rt5650_soc_card, - .num_jacks = MT8186_JACK_MAX, - .pcm_constraints = mt8186_pcm_constraints, - .num_pcm_constraints = ARRAY_SIZE(mt8186_pcm_constraints), - }, - .sof_priv = &mt8186_sof_priv, - .soc_probe = mt8186_mt6366_soc_card_probe -}; - -#if IS_ENABLED(CONFIG_OF) -static const struct of_device_id mt8186_mt6366_rt1019_rt5682s_dt_match[] = { - { - .compatible = "mediatek,mt8186-mt6366-rt1019-rt5682s-sound", - .data = &mt8186_mt6366_rt1019_rt5682s_pdata, - }, - { - .compatible = "mediatek,mt8186-mt6366-rt5682s-max98360-sound", - .data = &mt8186_mt6366_rt5682s_max98360_pdata, - }, - { - .compatible = "mediatek,mt8186-mt6366-rt5650-sound", - .data = &mt8186_mt6366_rt5650_pdata, - }, - {} -}; -MODULE_DEVICE_TABLE(of, mt8186_mt6366_rt1019_rt5682s_dt_match); -#endif - -static struct platform_driver mt8186_mt6366_rt1019_rt5682s_driver = { - .driver = { - .name = "mt8186_mt6366_rt1019_rt5682s", -#if IS_ENABLED(CONFIG_OF) - .of_match_table = mt8186_mt6366_rt1019_rt5682s_dt_match, -#endif - .pm = &snd_soc_pm_ops, - }, - .probe = mtk_soundcard_common_probe, -}; - -module_platform_driver(mt8186_mt6366_rt1019_rt5682s_driver); - -/* Module information */ -MODULE_DESCRIPTION("MT8186-MT6366-RT1019-RT5682S ALSA SoC machine driver"); -MODULE_AUTHOR("Jiaxin Yu "); -MODULE_LICENSE("GPL v2"); -MODULE_ALIAS("mt8186_mt6366_rt1019_rt5682s soc card"); diff --git a/sound/soc/mediatek/mt8186/mt8186-mt6366.c b/sound/soc/mediatek/mt8186/mt8186-mt6366.c new file mode 100644 index 000000000000..8fd31c52b077 --- /dev/null +++ b/sound/soc/mediatek/mt8186/mt8186-mt6366.c @@ -0,0 +1,1398 @@ +// SPDX-License-Identifier: GPL-2.0 +// +// mt8186-mt6366.c +// -- MT8186-MT6366 ALSA SoC machine driver +// +// Copyright (c) 2022 MediaTek Inc. +// Author: Jiaxin Yu +// +// Copyright (c) 2024 Collabora Ltd. +// AngeloGioacchino Del Regno +// + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "../../codecs/da7219.h" +#include "../../codecs/mt6358.h" +#include "../../codecs/rt5682.h" +#include "../common/mtk-afe-platform-driver.h" +#include "../common/mtk-dsp-sof-common.h" +#include "../common/mtk-soc-card.h" +#include "../common/mtk-soundcard-driver.h" +#include "mt8186-afe-common.h" +#include "mt8186-afe-clk.h" +#include "mt8186-afe-gpio.h" +#include "mt8186-mt6366-common.h" + +#define RT1019_CODEC_DAI "HiFi" +#define RT1019_DEV0_NAME "rt1019p" + +#define RT5682S_CODEC_DAI "rt5682s-aif1" +#define RT5682S_DEV0_NAME "rt5682s.5-001a" + +#define DA7219_CODEC_DAI "da7219-hifi" +#define DA7219_DEV_NAME "da7219.5-001a" + +#define SOF_DMA_DL1 "SOF_DMA_DL1" +#define SOF_DMA_DL2 "SOF_DMA_DL2" +#define SOF_DMA_UL1 "SOF_DMA_UL1" +#define SOF_DMA_UL2 "SOF_DMA_UL2" + +#define DA7219_CODEC_PRESENT BIT(0) + +struct mt8186_mt6366_rt1019_rt5682s_priv { + struct gpio_desc *dmic_sel; + int dmic_switch; +}; + +enum mt8186_jacks { + MT8186_JACK_HEADSET, + MT8186_JACK_HDMI, + MT8186_JACK_MAX, +}; + +/* Headset jack detection DAPM pins */ +static struct snd_soc_jack_pin mt8186_jack_pins[] = { + { + .pin = "Headphone", + .mask = SND_JACK_HEADPHONE, + }, + { + .pin = "Headset Mic", + .mask = SND_JACK_MICROPHONE, + }, +}; + +static struct snd_soc_codec_conf mt8186_mt6366_rt1019_rt5682s_codec_conf[] = { + { + .dlc = COMP_CODEC_CONF("mt6358-sound"), + .name_prefix = "Mt6366", + }, + { + .dlc = COMP_CODEC_CONF("bt-sco"), + .name_prefix = "Mt8186 bt", + }, + { + .dlc = COMP_CODEC_CONF("hdmi-audio-codec"), + .name_prefix = "Mt8186 hdmi", + }, +}; + +static int dmic_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_dapm_context *dapm = snd_soc_dapm_kcontrol_dapm(kcontrol); + struct mtk_soc_card_data *soc_card_data = + snd_soc_card_get_drvdata(dapm->card); + struct mt8186_mt6366_rt1019_rt5682s_priv *priv = soc_card_data->mach_priv; + + ucontrol->value.integer.value[0] = priv->dmic_switch; + return 0; +} + +static int dmic_set(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_dapm_context *dapm = snd_soc_dapm_kcontrol_dapm(kcontrol); + struct mtk_soc_card_data *soc_card_data = + snd_soc_card_get_drvdata(dapm->card); + struct mt8186_mt6366_rt1019_rt5682s_priv *priv = soc_card_data->mach_priv; + + priv->dmic_switch = ucontrol->value.integer.value[0]; + if (priv->dmic_sel) { + gpiod_set_value(priv->dmic_sel, priv->dmic_switch); + dev_dbg(dapm->card->dev, "dmic_set_value %d\n", + priv->dmic_switch); + } + return 0; +} + +static const char * const dmic_mux_text[] = { + "Front Mic", + "Rear Mic", +}; + +static SOC_ENUM_SINGLE_DECL(mt8186_dmic_enum, + SND_SOC_NOPM, 0, dmic_mux_text); + +static const struct snd_kcontrol_new mt8186_dmic_mux_control = + SOC_DAPM_ENUM_EXT("DMIC Select Mux", mt8186_dmic_enum, + dmic_get, dmic_set); + +static const struct snd_soc_dapm_widget dmic_widgets[] = { + SND_SOC_DAPM_MIC("DMIC", NULL), + SND_SOC_DAPM_MUX("Dmic Mux", SND_SOC_NOPM, 0, 0, &mt8186_dmic_mux_control), +}; + +static const struct snd_soc_dapm_route dmic_map[] = { + /* digital mics */ + {"Dmic Mux", "Front Mic", "DMIC"}, + {"Dmic Mux", "Rear Mic", "DMIC"}, +}; + +static int primary_codec_init(struct snd_soc_pcm_runtime *rtd) +{ + struct snd_soc_card *card = rtd->card; + struct mtk_soc_card_data *soc_card_data = snd_soc_card_get_drvdata(card); + struct mt8186_mt6366_rt1019_rt5682s_priv *priv = soc_card_data->mach_priv; + int ret; + + ret = mt8186_mt6366_init(rtd); + + if (ret) { + dev_err(card->dev, "mt8186_mt6366_init failed: %d\n", ret); + return ret; + } + + if (!priv->dmic_sel) { + dev_dbg(card->dev, "dmic_sel is null\n"); + return 0; + } + + ret = snd_soc_dapm_new_controls(&card->dapm, dmic_widgets, + ARRAY_SIZE(dmic_widgets)); + if (ret) { + dev_err(card->dev, "DMic widget addition failed: %d\n", ret); + /* Don't need to add routes if widget addition failed */ + return ret; + } + + ret = snd_soc_dapm_add_routes(&card->dapm, dmic_map, + ARRAY_SIZE(dmic_map)); + + if (ret) + dev_err(card->dev, "DMic map addition failed: %d\n", ret); + + return ret; +} + +static int mt8186_headset_codec_init(struct snd_soc_pcm_runtime *rtd) +{ + struct snd_soc_component *cmpnt_afe = + snd_soc_rtdcom_lookup(rtd, AFE_PCM_NAME); + struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt_afe); + struct mtk_soc_card_data *soc_card_data = + snd_soc_card_get_drvdata(rtd->card); + struct snd_soc_jack *jack = &soc_card_data->card_data->jacks[MT8186_JACK_HEADSET]; + struct snd_soc_component *cmpnt_codec = + snd_soc_rtd_to_codec(rtd, 0)->component; + const int hs_keys_rt5682[] = { + KEY_PLAYPAUSE, KEY_VOLUMEUP, KEY_VOLUMEDOWN, KEY_VOICECOMMAND + }; + const int hs_keys_da7219[] = { + KEY_PLAYPAUSE, KEY_VOICECOMMAND, KEY_VOLUMEUP, KEY_VOLUMEDOWN + }; + const int *hs_keys; + int ret; + int type; + + ret = mt8186_dai_i2s_set_share(afe, "I2S1", "I2S0"); + if (ret) { + dev_err(rtd->dev, "Failed to set up shared clocks\n"); + return ret; + } + + ret = snd_soc_card_jack_new_pins(rtd->card, "Headset Jack", + SND_JACK_HEADSET | SND_JACK_BTN_0 | + SND_JACK_BTN_1 | SND_JACK_BTN_2 | + SND_JACK_BTN_3, + jack, mt8186_jack_pins, + ARRAY_SIZE(mt8186_jack_pins)); + if (ret) { + dev_err(rtd->dev, "Headset Jack creation failed: %d\n", ret); + return ret; + } + + if (soc_card_data->card_data->flags & DA7219_CODEC_PRESENT) + hs_keys = hs_keys_da7219; + else + hs_keys = hs_keys_rt5682; + + snd_jack_set_key(jack->jack, SND_JACK_BTN_0, hs_keys[0]); + snd_jack_set_key(jack->jack, SND_JACK_BTN_1, hs_keys[1]); + snd_jack_set_key(jack->jack, SND_JACK_BTN_2, hs_keys[2]); + snd_jack_set_key(jack->jack, SND_JACK_BTN_3, hs_keys[3]); + + type = SND_JACK_HEADSET | SND_JACK_BTN_0 | SND_JACK_BTN_1 | SND_JACK_BTN_2 | SND_JACK_BTN_3; + return snd_soc_component_set_jack(cmpnt_codec, jack, (void *)&type); +} + +static int mt8186_da7219_i2s_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params) +{ + struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream); + struct snd_soc_dai *cpu_dai = snd_soc_rtd_to_cpu(rtd, 0); + struct snd_soc_dai *codec_dai; + unsigned int rate = params_rate(params); + unsigned int mclk_fs_ratio = 256; + unsigned int mclk_fs = rate * mclk_fs_ratio; + unsigned int freq; + int ret, j; + + ret = snd_soc_dai_set_sysclk(cpu_dai, 0, mclk_fs, SND_SOC_CLOCK_OUT); + if (ret < 0) { + dev_err(rtd->dev, "failed to set cpu dai sysclk: %d\n", ret); + return ret; + } + + for_each_rtd_codec_dais(rtd, j, codec_dai) { + if (strcmp(codec_dai->component->name, DA7219_DEV_NAME)) + continue; + + ret = snd_soc_dai_set_sysclk(codec_dai, DA7219_CLKSRC_MCLK, + mclk_fs, SND_SOC_CLOCK_IN); + if (ret < 0) { + dev_err(rtd->dev, "failed to set sysclk: %d\n", ret); + return ret; + } + + if ((rate % 8000) == 0) + freq = DA7219_PLL_FREQ_OUT_98304; + else + freq = DA7219_PLL_FREQ_OUT_90316; + + ret = snd_soc_dai_set_pll(codec_dai, 0, DA7219_SYSCLK_PLL_SRM, + 0, freq); + if (ret) { + dev_err(rtd->dev, "failed to start PLL: %d\n", ret); + return ret; + } + } + + return 0; +} + +static int mt8186_da7219_i2s_hw_free(struct snd_pcm_substream *substream) +{ + struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream); + struct snd_soc_dai *codec_dai; + int j, ret; + + for_each_rtd_codec_dais(rtd, j, codec_dai) { + if (strcmp(codec_dai->component->name, DA7219_DEV_NAME)) + continue; + + ret = snd_soc_dai_set_pll(codec_dai, 0, DA7219_SYSCLK_MCLK, 0, 0); + if (ret < 0) { + dev_err(rtd->dev, "failed to stop PLL: %d\n", ret); + return ret; + } + } + + return 0; +} + +static const struct snd_soc_ops mt8186_da7219_i2s_ops = { + .hw_params = mt8186_da7219_i2s_hw_params, + .hw_free = mt8186_da7219_i2s_hw_free, +}; + +static int mt8186_rt5682s_i2s_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params) +{ + struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_card *card = rtd->card; + struct snd_soc_dai *cpu_dai = snd_soc_rtd_to_cpu(rtd, 0); + struct snd_soc_dai *codec_dai = snd_soc_rtd_to_codec(rtd, 0); + unsigned int rate = params_rate(params); + unsigned int mclk_fs_ratio = 128; + unsigned int mclk_fs = rate * mclk_fs_ratio; + int bitwidth; + int ret; + + bitwidth = snd_pcm_format_width(params_format(params)); + if (bitwidth < 0) { + dev_err(card->dev, "invalid bit width: %d\n", bitwidth); + return bitwidth; + } + + ret = snd_soc_dai_set_tdm_slot(codec_dai, 0x00, 0x0, 0x2, bitwidth); + if (ret) { + dev_err(card->dev, "failed to set tdm slot\n"); + return ret; + } + + ret = snd_soc_dai_set_pll(codec_dai, RT5682_PLL1, + RT5682_PLL1_S_BCLK1, + params_rate(params) * 64, + params_rate(params) * 512); + if (ret) { + dev_err(card->dev, "failed to set pll\n"); + return ret; + } + + ret = snd_soc_dai_set_sysclk(codec_dai, + RT5682_SCLK_S_PLL1, + params_rate(params) * 512, + SND_SOC_CLOCK_IN); + if (ret) { + dev_err(card->dev, "failed to set sysclk\n"); + return ret; + } + + return snd_soc_dai_set_sysclk(cpu_dai, 0, mclk_fs, SND_SOC_CLOCK_OUT); +} + +static const struct snd_soc_ops mt8186_rt5682s_i2s_ops = { + .hw_params = mt8186_rt5682s_i2s_hw_params, +}; + +static int mt8186_mt6366_rt1019_rt5682s_hdmi_init(struct snd_soc_pcm_runtime *rtd) +{ + struct snd_soc_component *cmpnt_afe = + snd_soc_rtdcom_lookup(rtd, AFE_PCM_NAME); + struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt_afe); + struct snd_soc_component *cmpnt_codec = + snd_soc_rtd_to_codec(rtd, 0)->component; + struct mtk_soc_card_data *soc_card_data = + snd_soc_card_get_drvdata(rtd->card); + struct snd_soc_jack *jack = &soc_card_data->card_data->jacks[MT8186_JACK_HDMI]; + int ret; + + ret = mt8186_dai_i2s_set_share(afe, "I2S2", "I2S3"); + if (ret) { + dev_err(rtd->dev, "Failed to set up shared clocks\n"); + return ret; + } + + ret = snd_soc_card_jack_new(rtd->card, "HDMI Jack", SND_JACK_LINEOUT, jack); + if (ret) { + dev_err(rtd->dev, "HDMI Jack creation failed: %d\n", ret); + return ret; + } + + return snd_soc_component_set_jack(cmpnt_codec, jack, NULL); +} + +static int mt8186_hw_params_fixup(struct snd_soc_pcm_runtime *rtd, + struct snd_pcm_hw_params *params, + snd_pcm_format_t fmt) +{ + struct snd_interval *channels = hw_param_interval(params, + SNDRV_PCM_HW_PARAM_CHANNELS); + + dev_dbg(rtd->dev, "%s(), fix format to %d\n", __func__, fmt); + + /* fix BE i2s channel to 2 channel */ + channels->min = 2; + channels->max = 2; + + /* clean param mask first */ + snd_mask_reset_range(hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT), + 0, (__force unsigned int)SNDRV_PCM_FORMAT_LAST); + + params_set_format(params, fmt); + + return 0; +} + +static int mt8186_i2s_hw_params_24le_fixup(struct snd_soc_pcm_runtime *rtd, + struct snd_pcm_hw_params *params) +{ + return mt8186_hw_params_fixup(rtd, params, SNDRV_PCM_FORMAT_S24_LE); +} + +static int mt8186_i2s_hw_params_32le_fixup(struct snd_soc_pcm_runtime *rtd, + struct snd_pcm_hw_params *params) +{ + return mt8186_hw_params_fixup(rtd, params, SNDRV_PCM_FORMAT_S32_LE); +} + +/* fixup the BE DAI link to match any values from topology */ +static int mt8186_sof_dai_link_fixup(struct snd_soc_pcm_runtime *rtd, + struct snd_pcm_hw_params *params) +{ + struct mtk_soc_card_data *soc_card_data = snd_soc_card_get_drvdata(rtd->card); + int ret; + + ret = mtk_sof_dai_link_fixup(rtd, params); + + if (!strcmp(rtd->dai_link->name, "I2S0") || + !strcmp(rtd->dai_link->name, "I2S1") || + !strcmp(rtd->dai_link->name, "I2S2")) { + if (soc_card_data->card_data->flags & DA7219_CODEC_PRESENT) + mt8186_i2s_hw_params_32le_fixup(rtd, params); + else + mt8186_i2s_hw_params_24le_fixup(rtd, params); + } else if (!strcmp(rtd->dai_link->name, "I2S3")) { + if (soc_card_data->card_data->flags & DA7219_CODEC_PRESENT) + mt8186_i2s_hw_params_24le_fixup(rtd, params); + else + mt8186_i2s_hw_params_32le_fixup(rtd, params); + } + + return ret; +} + +/* FE */ +SND_SOC_DAILINK_DEFS(playback1, + DAILINK_COMP_ARRAY(COMP_CPU("DL1")), + DAILINK_COMP_ARRAY(COMP_DUMMY()), + DAILINK_COMP_ARRAY(COMP_EMPTY())); + +SND_SOC_DAILINK_DEFS(playback12, + DAILINK_COMP_ARRAY(COMP_CPU("DL12")), + DAILINK_COMP_ARRAY(COMP_DUMMY()), + DAILINK_COMP_ARRAY(COMP_EMPTY())); + +SND_SOC_DAILINK_DEFS(playback2, + DAILINK_COMP_ARRAY(COMP_CPU("DL2")), + DAILINK_COMP_ARRAY(COMP_DUMMY()), + DAILINK_COMP_ARRAY(COMP_EMPTY())); + +SND_SOC_DAILINK_DEFS(playback3, + DAILINK_COMP_ARRAY(COMP_CPU("DL3")), + DAILINK_COMP_ARRAY(COMP_DUMMY()), + DAILINK_COMP_ARRAY(COMP_EMPTY())); + +SND_SOC_DAILINK_DEFS(playback4, + DAILINK_COMP_ARRAY(COMP_CPU("DL4")), + DAILINK_COMP_ARRAY(COMP_DUMMY()), + DAILINK_COMP_ARRAY(COMP_EMPTY())); + +SND_SOC_DAILINK_DEFS(playback5, + DAILINK_COMP_ARRAY(COMP_CPU("DL5")), + DAILINK_COMP_ARRAY(COMP_DUMMY()), + DAILINK_COMP_ARRAY(COMP_EMPTY())); + +SND_SOC_DAILINK_DEFS(playback6, + DAILINK_COMP_ARRAY(COMP_CPU("DL6")), + DAILINK_COMP_ARRAY(COMP_DUMMY()), + DAILINK_COMP_ARRAY(COMP_EMPTY())); + +SND_SOC_DAILINK_DEFS(playback7, + DAILINK_COMP_ARRAY(COMP_CPU("DL7")), + DAILINK_COMP_ARRAY(COMP_DUMMY()), + DAILINK_COMP_ARRAY(COMP_EMPTY())); + +SND_SOC_DAILINK_DEFS(playback8, + DAILINK_COMP_ARRAY(COMP_CPU("DL8")), + DAILINK_COMP_ARRAY(COMP_DUMMY()), + DAILINK_COMP_ARRAY(COMP_EMPTY())); + +SND_SOC_DAILINK_DEFS(capture1, + DAILINK_COMP_ARRAY(COMP_CPU("UL1")), + DAILINK_COMP_ARRAY(COMP_DUMMY()), + DAILINK_COMP_ARRAY(COMP_EMPTY())); + +SND_SOC_DAILINK_DEFS(capture2, + DAILINK_COMP_ARRAY(COMP_CPU("UL2")), + DAILINK_COMP_ARRAY(COMP_DUMMY()), + DAILINK_COMP_ARRAY(COMP_EMPTY())); + +SND_SOC_DAILINK_DEFS(capture3, + DAILINK_COMP_ARRAY(COMP_CPU("UL3")), + DAILINK_COMP_ARRAY(COMP_DUMMY()), + DAILINK_COMP_ARRAY(COMP_EMPTY())); + +SND_SOC_DAILINK_DEFS(capture4, + DAILINK_COMP_ARRAY(COMP_CPU("UL4")), + DAILINK_COMP_ARRAY(COMP_DUMMY()), + DAILINK_COMP_ARRAY(COMP_EMPTY())); + +SND_SOC_DAILINK_DEFS(capture5, + DAILINK_COMP_ARRAY(COMP_CPU("UL5")), + DAILINK_COMP_ARRAY(COMP_DUMMY()), + DAILINK_COMP_ARRAY(COMP_EMPTY())); + +SND_SOC_DAILINK_DEFS(capture6, + DAILINK_COMP_ARRAY(COMP_CPU("UL6")), + DAILINK_COMP_ARRAY(COMP_DUMMY()), + DAILINK_COMP_ARRAY(COMP_EMPTY())); + +SND_SOC_DAILINK_DEFS(capture7, + DAILINK_COMP_ARRAY(COMP_CPU("UL7")), + DAILINK_COMP_ARRAY(COMP_DUMMY()), + DAILINK_COMP_ARRAY(COMP_EMPTY())); + +/* hostless */ +SND_SOC_DAILINK_DEFS(hostless_lpbk, + DAILINK_COMP_ARRAY(COMP_CPU("Hostless LPBK DAI")), + DAILINK_COMP_ARRAY(COMP_DUMMY()), + DAILINK_COMP_ARRAY(COMP_EMPTY())); +SND_SOC_DAILINK_DEFS(hostless_fm, + DAILINK_COMP_ARRAY(COMP_CPU("Hostless FM DAI")), + DAILINK_COMP_ARRAY(COMP_DUMMY()), + DAILINK_COMP_ARRAY(COMP_EMPTY())); +SND_SOC_DAILINK_DEFS(hostless_src1, + DAILINK_COMP_ARRAY(COMP_CPU("Hostless_SRC_1_DAI")), + DAILINK_COMP_ARRAY(COMP_DUMMY()), + DAILINK_COMP_ARRAY(COMP_EMPTY())); +SND_SOC_DAILINK_DEFS(hostless_src_bargein, + DAILINK_COMP_ARRAY(COMP_CPU("Hostless_SRC_Bargein_DAI")), + DAILINK_COMP_ARRAY(COMP_DUMMY()), + DAILINK_COMP_ARRAY(COMP_EMPTY())); + +/* BE */ +SND_SOC_DAILINK_DEFS(adda, + DAILINK_COMP_ARRAY(COMP_CPU("ADDA")), + DAILINK_COMP_ARRAY(COMP_CODEC("mt6358-sound", + "mt6358-snd-codec-aif1"), + COMP_CODEC("dmic-codec", + "dmic-hifi")), + DAILINK_COMP_ARRAY(COMP_EMPTY())); +SND_SOC_DAILINK_DEFS(i2s0, + DAILINK_COMP_ARRAY(COMP_CPU("I2S0")), + DAILINK_COMP_ARRAY(COMP_EMPTY()), + DAILINK_COMP_ARRAY(COMP_EMPTY())); +SND_SOC_DAILINK_DEFS(i2s1, + DAILINK_COMP_ARRAY(COMP_CPU("I2S1")), + DAILINK_COMP_ARRAY(COMP_EMPTY()), + DAILINK_COMP_ARRAY(COMP_EMPTY())); +SND_SOC_DAILINK_DEFS(i2s2, + DAILINK_COMP_ARRAY(COMP_CPU("I2S2")), + DAILINK_COMP_ARRAY(COMP_DUMMY()), + DAILINK_COMP_ARRAY(COMP_EMPTY())); +SND_SOC_DAILINK_DEFS(i2s3, + DAILINK_COMP_ARRAY(COMP_CPU("I2S3")), + DAILINK_COMP_ARRAY(COMP_EMPTY()), + DAILINK_COMP_ARRAY(COMP_EMPTY())); +SND_SOC_DAILINK_DEFS(hw_gain1, + DAILINK_COMP_ARRAY(COMP_CPU("HW Gain 1")), + DAILINK_COMP_ARRAY(COMP_DUMMY()), + DAILINK_COMP_ARRAY(COMP_EMPTY())); +SND_SOC_DAILINK_DEFS(hw_gain2, + DAILINK_COMP_ARRAY(COMP_CPU("HW Gain 2")), + DAILINK_COMP_ARRAY(COMP_DUMMY()), + DAILINK_COMP_ARRAY(COMP_EMPTY())); +SND_SOC_DAILINK_DEFS(hw_src1, + DAILINK_COMP_ARRAY(COMP_CPU("HW_SRC_1")), + DAILINK_COMP_ARRAY(COMP_DUMMY()), + DAILINK_COMP_ARRAY(COMP_EMPTY())); +SND_SOC_DAILINK_DEFS(hw_src2, + DAILINK_COMP_ARRAY(COMP_CPU("HW_SRC_2")), + DAILINK_COMP_ARRAY(COMP_DUMMY()), + DAILINK_COMP_ARRAY(COMP_EMPTY())); +SND_SOC_DAILINK_DEFS(connsys_i2s, + DAILINK_COMP_ARRAY(COMP_CPU("CONNSYS_I2S")), + DAILINK_COMP_ARRAY(COMP_DUMMY()), + DAILINK_COMP_ARRAY(COMP_EMPTY())); +SND_SOC_DAILINK_DEFS(pcm1, + DAILINK_COMP_ARRAY(COMP_CPU("PCM 1")), + DAILINK_COMP_ARRAY(COMP_CODEC("bt-sco", "bt-sco-pcm-wb")), + DAILINK_COMP_ARRAY(COMP_EMPTY())); +SND_SOC_DAILINK_DEFS(tdm_in, + DAILINK_COMP_ARRAY(COMP_CPU("TDM IN")), + DAILINK_COMP_ARRAY(COMP_DUMMY()), + DAILINK_COMP_ARRAY(COMP_EMPTY())); + +/* hostless */ +SND_SOC_DAILINK_DEFS(hostless_ul1, + DAILINK_COMP_ARRAY(COMP_CPU("Hostless_UL1 DAI")), + DAILINK_COMP_ARRAY(COMP_DUMMY()), + DAILINK_COMP_ARRAY(COMP_EMPTY())); +SND_SOC_DAILINK_DEFS(hostless_ul2, + DAILINK_COMP_ARRAY(COMP_CPU("Hostless_UL2 DAI")), + DAILINK_COMP_ARRAY(COMP_DUMMY()), + DAILINK_COMP_ARRAY(COMP_EMPTY())); +SND_SOC_DAILINK_DEFS(hostless_ul3, + DAILINK_COMP_ARRAY(COMP_CPU("Hostless_UL3 DAI")), + DAILINK_COMP_ARRAY(COMP_DUMMY()), + DAILINK_COMP_ARRAY(COMP_EMPTY())); +SND_SOC_DAILINK_DEFS(hostless_ul5, + DAILINK_COMP_ARRAY(COMP_CPU("Hostless_UL5 DAI")), + DAILINK_COMP_ARRAY(COMP_DUMMY()), + DAILINK_COMP_ARRAY(COMP_EMPTY())); +SND_SOC_DAILINK_DEFS(hostless_ul6, + DAILINK_COMP_ARRAY(COMP_CPU("Hostless_UL6 DAI")), + DAILINK_COMP_ARRAY(COMP_DUMMY()), + DAILINK_COMP_ARRAY(COMP_EMPTY())); +SND_SOC_DAILINK_DEFS(hostless_hw_gain_aaudio, + DAILINK_COMP_ARRAY(COMP_CPU("Hostless HW Gain AAudio DAI")), + DAILINK_COMP_ARRAY(COMP_DUMMY()), + DAILINK_COMP_ARRAY(COMP_EMPTY())); +SND_SOC_DAILINK_DEFS(hostless_src_aaudio, + DAILINK_COMP_ARRAY(COMP_CPU("Hostless SRC AAudio DAI")), + DAILINK_COMP_ARRAY(COMP_DUMMY()), + DAILINK_COMP_ARRAY(COMP_EMPTY())); +SND_SOC_DAILINK_DEFS(AFE_SOF_DL1, + DAILINK_COMP_ARRAY(COMP_CPU("SOF_DL1")), + DAILINK_COMP_ARRAY(COMP_DUMMY()), + DAILINK_COMP_ARRAY(COMP_EMPTY())); + +SND_SOC_DAILINK_DEFS(AFE_SOF_DL2, + DAILINK_COMP_ARRAY(COMP_CPU("SOF_DL2")), + DAILINK_COMP_ARRAY(COMP_DUMMY()), + DAILINK_COMP_ARRAY(COMP_EMPTY())); + +SND_SOC_DAILINK_DEFS(AFE_SOF_UL1, + DAILINK_COMP_ARRAY(COMP_CPU("SOF_UL1")), + DAILINK_COMP_ARRAY(COMP_DUMMY()), + DAILINK_COMP_ARRAY(COMP_EMPTY())); + +SND_SOC_DAILINK_DEFS(AFE_SOF_UL2, + DAILINK_COMP_ARRAY(COMP_CPU("SOF_UL2")), + DAILINK_COMP_ARRAY(COMP_DUMMY()), + DAILINK_COMP_ARRAY(COMP_EMPTY())); + +static const struct sof_conn_stream g_sof_conn_streams[] = { + { "I2S1", "AFE_SOF_DL1", SOF_DMA_DL1, SNDRV_PCM_STREAM_PLAYBACK}, + { "I2S3", "AFE_SOF_DL2", SOF_DMA_DL2, SNDRV_PCM_STREAM_PLAYBACK}, + { "Primary Codec", "AFE_SOF_UL1", SOF_DMA_UL1, SNDRV_PCM_STREAM_CAPTURE}, + { "I2S0", "AFE_SOF_UL2", SOF_DMA_UL2, SNDRV_PCM_STREAM_CAPTURE}, +}; + +static struct snd_soc_dai_link mt8186_mt6366_rt1019_rt5682s_dai_links[] = { + /* Front End DAI links */ + { + .name = "Playback_1", + .stream_name = "Playback_1", + .trigger = {SND_SOC_DPCM_TRIGGER_PRE, + SND_SOC_DPCM_TRIGGER_PRE}, + .dynamic = 1, + .dpcm_playback = 1, + .dpcm_merged_format = 1, + .dpcm_merged_chan = 1, + .dpcm_merged_rate = 1, + .ops = &mtk_soundcard_common_playback_ops, + SND_SOC_DAILINK_REG(playback1), + }, + { + .name = "Playback_12", + .stream_name = "Playback_12", + .trigger = {SND_SOC_DPCM_TRIGGER_PRE, + SND_SOC_DPCM_TRIGGER_PRE}, + .dynamic = 1, + .dpcm_playback = 1, + SND_SOC_DAILINK_REG(playback12), + }, + { + .name = "Playback_2", + .stream_name = "Playback_2", + .trigger = {SND_SOC_DPCM_TRIGGER_PRE, + SND_SOC_DPCM_TRIGGER_PRE}, + .dynamic = 1, + .dpcm_playback = 1, + .dpcm_merged_format = 1, + .dpcm_merged_chan = 1, + .dpcm_merged_rate = 1, + SND_SOC_DAILINK_REG(playback2), + }, + { + .name = "Playback_3", + .stream_name = "Playback_3", + .trigger = {SND_SOC_DPCM_TRIGGER_PRE, + SND_SOC_DPCM_TRIGGER_PRE}, + .dynamic = 1, + .dpcm_playback = 1, + .dpcm_merged_format = 1, + .dpcm_merged_chan = 1, + .dpcm_merged_rate = 1, + .ops = &mtk_soundcard_common_playback_ops, + SND_SOC_DAILINK_REG(playback3), + }, + { + .name = "Playback_4", + .stream_name = "Playback_4", + .trigger = {SND_SOC_DPCM_TRIGGER_PRE, + SND_SOC_DPCM_TRIGGER_PRE}, + .dynamic = 1, + .dpcm_playback = 1, + SND_SOC_DAILINK_REG(playback4), + }, + { + .name = "Playback_5", + .stream_name = "Playback_5", + .trigger = {SND_SOC_DPCM_TRIGGER_PRE, + SND_SOC_DPCM_TRIGGER_PRE}, + .dynamic = 1, + .dpcm_playback = 1, + SND_SOC_DAILINK_REG(playback5), + }, + { + .name = "Playback_6", + .stream_name = "Playback_6", + .trigger = {SND_SOC_DPCM_TRIGGER_PRE, + SND_SOC_DPCM_TRIGGER_PRE}, + .dynamic = 1, + .dpcm_playback = 1, + SND_SOC_DAILINK_REG(playback6), + }, + { + .name = "Playback_7", + .stream_name = "Playback_7", + .trigger = {SND_SOC_DPCM_TRIGGER_PRE, + SND_SOC_DPCM_TRIGGER_PRE}, + .dynamic = 1, + .dpcm_playback = 1, + SND_SOC_DAILINK_REG(playback7), + }, + { + .name = "Playback_8", + .stream_name = "Playback_8", + .trigger = {SND_SOC_DPCM_TRIGGER_PRE, + SND_SOC_DPCM_TRIGGER_PRE}, + .dynamic = 1, + .dpcm_playback = 1, + SND_SOC_DAILINK_REG(playback8), + }, + { + .name = "Capture_1", + .stream_name = "Capture_1", + .trigger = {SND_SOC_DPCM_TRIGGER_PRE, + SND_SOC_DPCM_TRIGGER_PRE}, + .dynamic = 1, + .dpcm_capture = 1, + SND_SOC_DAILINK_REG(capture1), + }, + { + .name = "Capture_2", + .stream_name = "Capture_2", + .trigger = {SND_SOC_DPCM_TRIGGER_PRE, + SND_SOC_DPCM_TRIGGER_PRE}, + .dynamic = 1, + .dpcm_capture = 1, + .dpcm_merged_format = 1, + .dpcm_merged_chan = 1, + .dpcm_merged_rate = 1, + .ops = &mtk_soundcard_common_capture_ops, + SND_SOC_DAILINK_REG(capture2), + }, + { + .name = "Capture_3", + .stream_name = "Capture_3", + .trigger = {SND_SOC_DPCM_TRIGGER_PRE, + SND_SOC_DPCM_TRIGGER_PRE}, + .dynamic = 1, + .dpcm_capture = 1, + SND_SOC_DAILINK_REG(capture3), + }, + { + .name = "Capture_4", + .stream_name = "Capture_4", + .trigger = {SND_SOC_DPCM_TRIGGER_PRE, + SND_SOC_DPCM_TRIGGER_PRE}, + .dynamic = 1, + .dpcm_capture = 1, + .dpcm_merged_format = 1, + .dpcm_merged_chan = 1, + .dpcm_merged_rate = 1, + .ops = &mtk_soundcard_common_capture_ops, + SND_SOC_DAILINK_REG(capture4), + }, + { + .name = "Capture_5", + .stream_name = "Capture_5", + .trigger = {SND_SOC_DPCM_TRIGGER_PRE, + SND_SOC_DPCM_TRIGGER_PRE}, + .dynamic = 1, + .dpcm_capture = 1, + SND_SOC_DAILINK_REG(capture5), + }, + { + .name = "Capture_6", + .stream_name = "Capture_6", + .trigger = {SND_SOC_DPCM_TRIGGER_PRE, + SND_SOC_DPCM_TRIGGER_PRE}, + .dynamic = 1, + .dpcm_capture = 1, + .dpcm_merged_format = 1, + .dpcm_merged_chan = 1, + .dpcm_merged_rate = 1, + SND_SOC_DAILINK_REG(capture6), + }, + { + .name = "Capture_7", + .stream_name = "Capture_7", + .trigger = {SND_SOC_DPCM_TRIGGER_PRE, + SND_SOC_DPCM_TRIGGER_PRE}, + .dynamic = 1, + .dpcm_capture = 1, + SND_SOC_DAILINK_REG(capture7), + }, + { + .name = "Hostless_LPBK", + .stream_name = "Hostless_LPBK", + .trigger = {SND_SOC_DPCM_TRIGGER_PRE, + SND_SOC_DPCM_TRIGGER_PRE}, + .dynamic = 1, + .dpcm_playback = 1, + .dpcm_capture = 1, + .ignore_suspend = 1, + SND_SOC_DAILINK_REG(hostless_lpbk), + }, + { + .name = "Hostless_FM", + .stream_name = "Hostless_FM", + .trigger = {SND_SOC_DPCM_TRIGGER_PRE, + SND_SOC_DPCM_TRIGGER_PRE}, + .dynamic = 1, + .dpcm_playback = 1, + .dpcm_capture = 1, + .ignore_suspend = 1, + SND_SOC_DAILINK_REG(hostless_fm), + }, + { + .name = "Hostless_SRC_1", + .stream_name = "Hostless_SRC_1", + .trigger = {SND_SOC_DPCM_TRIGGER_PRE, + SND_SOC_DPCM_TRIGGER_PRE}, + .dynamic = 1, + .dpcm_playback = 1, + .dpcm_capture = 1, + .ignore_suspend = 1, + SND_SOC_DAILINK_REG(hostless_src1), + }, + { + .name = "Hostless_SRC_Bargein", + .stream_name = "Hostless_SRC_Bargein", + .trigger = {SND_SOC_DPCM_TRIGGER_PRE, + SND_SOC_DPCM_TRIGGER_PRE}, + .dynamic = 1, + .dpcm_playback = 1, + .dpcm_capture = 1, + .ignore_suspend = 1, + SND_SOC_DAILINK_REG(hostless_src_bargein), + }, + { + .name = "Hostless_HW_Gain_AAudio", + .stream_name = "Hostless_HW_Gain_AAudio", + .trigger = {SND_SOC_DPCM_TRIGGER_PRE, + SND_SOC_DPCM_TRIGGER_PRE}, + .dynamic = 1, + .dpcm_capture = 1, + .ignore_suspend = 1, + SND_SOC_DAILINK_REG(hostless_hw_gain_aaudio), + }, + { + .name = "Hostless_SRC_AAudio", + .stream_name = "Hostless_SRC_AAudio", + .trigger = {SND_SOC_DPCM_TRIGGER_PRE, + SND_SOC_DPCM_TRIGGER_PRE}, + .dynamic = 1, + .dpcm_playback = 1, + .dpcm_capture = 1, + .ignore_suspend = 1, + SND_SOC_DAILINK_REG(hostless_src_aaudio), + }, + /* Back End DAI links */ + { + .name = "Primary Codec", + .no_pcm = 1, + .dpcm_playback = 1, + .dpcm_capture = 1, + .ignore_suspend = 1, + .init = primary_codec_init, + SND_SOC_DAILINK_REG(adda), + }, + { + .name = "I2S3", + .no_pcm = 1, + .dai_fmt = SND_SOC_DAIFMT_I2S | + SND_SOC_DAIFMT_IB_IF | + SND_SOC_DAIFMT_CBM_CFM, + .dpcm_playback = 1, + .ignore_suspend = 1, + .init = mt8186_mt6366_rt1019_rt5682s_hdmi_init, + SND_SOC_DAILINK_REG(i2s3), + }, + { + .name = "I2S0", + .no_pcm = 1, + .dpcm_capture = 1, + .ignore_suspend = 1, + .ops = &mt8186_rt5682s_i2s_ops, + SND_SOC_DAILINK_REG(i2s0), + }, + { + .name = "I2S1", + .no_pcm = 1, + .dpcm_playback = 1, + .ignore_suspend = 1, + .init = mt8186_headset_codec_init, + SND_SOC_DAILINK_REG(i2s1), + }, + { + .name = "I2S2", + .no_pcm = 1, + .dpcm_capture = 1, + .ignore_suspend = 1, + SND_SOC_DAILINK_REG(i2s2), + }, + { + .name = "HW Gain 1", + .no_pcm = 1, + .dpcm_playback = 1, + .dpcm_capture = 1, + .ignore_suspend = 1, + SND_SOC_DAILINK_REG(hw_gain1), + }, + { + .name = "HW Gain 2", + .no_pcm = 1, + .dpcm_playback = 1, + .dpcm_capture = 1, + .ignore_suspend = 1, + SND_SOC_DAILINK_REG(hw_gain2), + }, + { + .name = "HW_SRC_1", + .no_pcm = 1, + .dpcm_playback = 1, + .dpcm_capture = 1, + .ignore_suspend = 1, + SND_SOC_DAILINK_REG(hw_src1), + }, + { + .name = "HW_SRC_2", + .no_pcm = 1, + .dpcm_playback = 1, + .dpcm_capture = 1, + .ignore_suspend = 1, + SND_SOC_DAILINK_REG(hw_src2), + }, + { + .name = "CONNSYS_I2S", + .no_pcm = 1, + .dpcm_capture = 1, + .ignore_suspend = 1, + SND_SOC_DAILINK_REG(connsys_i2s), + }, + { + .name = "PCM 1", + .dai_fmt = SND_SOC_DAIFMT_I2S | + SND_SOC_DAIFMT_NB_IF, + .no_pcm = 1, + .dpcm_playback = 1, + .dpcm_capture = 1, + .ignore_suspend = 1, + SND_SOC_DAILINK_REG(pcm1), + }, + { + .name = "TDM IN", + .no_pcm = 1, + .dpcm_capture = 1, + .ignore_suspend = 1, + SND_SOC_DAILINK_REG(tdm_in), + }, + /* dummy BE for ul memif to record from dl memif */ + { + .name = "Hostless_UL1", + .no_pcm = 1, + .dpcm_capture = 1, + .ignore_suspend = 1, + SND_SOC_DAILINK_REG(hostless_ul1), + }, + { + .name = "Hostless_UL2", + .no_pcm = 1, + .dpcm_capture = 1, + .ignore_suspend = 1, + SND_SOC_DAILINK_REG(hostless_ul2), + }, + { + .name = "Hostless_UL3", + .no_pcm = 1, + .dpcm_capture = 1, + .ignore_suspend = 1, + SND_SOC_DAILINK_REG(hostless_ul3), + }, + { + .name = "Hostless_UL5", + .no_pcm = 1, + .dpcm_capture = 1, + .ignore_suspend = 1, + SND_SOC_DAILINK_REG(hostless_ul5), + }, + { + .name = "Hostless_UL6", + .no_pcm = 1, + .dpcm_capture = 1, + .ignore_suspend = 1, + SND_SOC_DAILINK_REG(hostless_ul6), + }, + /* SOF BE */ + { + .name = "AFE_SOF_DL1", + .no_pcm = 1, + .dpcm_playback = 1, + SND_SOC_DAILINK_REG(AFE_SOF_DL1), + }, + { + .name = "AFE_SOF_DL2", + .no_pcm = 1, + .dpcm_playback = 1, + SND_SOC_DAILINK_REG(AFE_SOF_DL2), + }, + { + .name = "AFE_SOF_UL1", + .no_pcm = 1, + .dpcm_capture = 1, + SND_SOC_DAILINK_REG(AFE_SOF_UL1), + }, + { + .name = "AFE_SOF_UL2", + .no_pcm = 1, + .dpcm_capture = 1, + SND_SOC_DAILINK_REG(AFE_SOF_UL2), + }, +}; + +static const struct snd_soc_dapm_widget +mt8186_mt6366_da7219_max98357_widgets[] = { + SND_SOC_DAPM_SPK("Speakers", NULL), + SND_SOC_DAPM_HP("Headphones", NULL), + SND_SOC_DAPM_MIC("Headset Mic", NULL), + SND_SOC_DAPM_LINE("Line Out", NULL), + SND_SOC_DAPM_LINE("HDMI1", NULL), + SND_SOC_DAPM_MIXER(SOF_DMA_DL1, SND_SOC_NOPM, 0, 0, NULL, 0), + SND_SOC_DAPM_MIXER(SOF_DMA_DL2, SND_SOC_NOPM, 0, 0, NULL, 0), + SND_SOC_DAPM_MIXER(SOF_DMA_UL1, SND_SOC_NOPM, 0, 0, NULL, 0), + SND_SOC_DAPM_MIXER(SOF_DMA_UL2, SND_SOC_NOPM, 0, 0, NULL, 0), +}; + +static const struct snd_soc_dapm_widget +mt8186_mt6366_rt1019_rt5682s_widgets[] = { + SND_SOC_DAPM_SPK("Speakers", NULL), + SND_SOC_DAPM_HP("Headphone", NULL), + SND_SOC_DAPM_MIC("Headset Mic", NULL), + SND_SOC_DAPM_OUTPUT("HDMI1"), + SND_SOC_DAPM_MIXER(SOF_DMA_DL1, SND_SOC_NOPM, 0, 0, NULL, 0), + SND_SOC_DAPM_MIXER(SOF_DMA_DL2, SND_SOC_NOPM, 0, 0, NULL, 0), + SND_SOC_DAPM_MIXER(SOF_DMA_UL1, SND_SOC_NOPM, 0, 0, NULL, 0), + SND_SOC_DAPM_MIXER(SOF_DMA_UL2, SND_SOC_NOPM, 0, 0, NULL, 0), +}; + +static const struct snd_soc_dapm_route +mt8186_mt6366_rt1019_rt5682s_routes[] = { + /* SPK */ + { "Speakers", NULL, "Speaker" }, + /* Headset */ + { "Headphone", NULL, "HPOL" }, + { "Headphone", NULL, "HPOR" }, + { "IN1P", NULL, "Headset Mic" }, + /* HDMI */ + { "HDMI1", NULL, "TX" }, + /* SOF Uplink */ + {SOF_DMA_UL1, NULL, "UL1_CH1"}, + {SOF_DMA_UL1, NULL, "UL1_CH2"}, + {SOF_DMA_UL2, NULL, "UL2_CH1"}, + {SOF_DMA_UL2, NULL, "UL2_CH2"}, + /* SOF Downlink */ + {"DSP_DL1_VIRT", NULL, SOF_DMA_DL1}, + {"DSP_DL2_VIRT", NULL, SOF_DMA_DL2}, +}; + +static const struct snd_soc_dapm_route mt8186_mt6366_rt5650_routes[] = { + /* SPK */ + {"Speakers", NULL, "SPOL"}, + {"Speakers", NULL, "SPOR"}, + /* Headset */ + { "Headphone", NULL, "HPOL" }, + { "Headphone", NULL, "HPOR" }, + { "IN1P", NULL, "Headset Mic" }, + { "IN1N", NULL, "Headset Mic"}, + /* HDMI */ + { "HDMI1", NULL, "TX" }, + /* SOF Uplink */ + {SOF_DMA_UL1, NULL, "UL1_CH1"}, + {SOF_DMA_UL1, NULL, "UL1_CH2"}, + {SOF_DMA_UL2, NULL, "UL2_CH1"}, + {SOF_DMA_UL2, NULL, "UL2_CH2"}, + /* SOF Downlink */ + {"DSP_DL1_VIRT", NULL, SOF_DMA_DL1}, + {"DSP_DL2_VIRT", NULL, SOF_DMA_DL2}, +}; + +static const struct snd_kcontrol_new mt8186_mt6366_da7219_max98357_controls[] = { + SOC_DAPM_PIN_SWITCH("Speakers"), + SOC_DAPM_PIN_SWITCH("Headphones"), + SOC_DAPM_PIN_SWITCH("Headset Mic"), + SOC_DAPM_PIN_SWITCH("Line Out"), + SOC_DAPM_PIN_SWITCH("HDMI1"), +}; + +static const struct snd_kcontrol_new +mt8186_mt6366_rt1019_rt5682s_controls[] = { + SOC_DAPM_PIN_SWITCH("Speakers"), + SOC_DAPM_PIN_SWITCH("Headphone"), + SOC_DAPM_PIN_SWITCH("Headset Mic"), + SOC_DAPM_PIN_SWITCH("HDMI1"), +}; + +static struct snd_soc_card mt8186_mt6366_da7219_max98357_soc_card = { + .name = "mt8186_da7219_max98357", + .owner = THIS_MODULE, + .dai_link = mt8186_mt6366_rt1019_rt5682s_dai_links, + .num_links = ARRAY_SIZE(mt8186_mt6366_rt1019_rt5682s_dai_links), + .controls = mt8186_mt6366_da7219_max98357_controls, + .num_controls = ARRAY_SIZE(mt8186_mt6366_da7219_max98357_controls), + .dapm_widgets = mt8186_mt6366_da7219_max98357_widgets, + .num_dapm_widgets = ARRAY_SIZE(mt8186_mt6366_da7219_max98357_widgets), + .dapm_routes = mt8186_mt6366_rt1019_rt5682s_routes, + .num_dapm_routes = ARRAY_SIZE(mt8186_mt6366_rt1019_rt5682s_routes), + .codec_conf = mt8186_mt6366_rt1019_rt5682s_codec_conf, + .num_configs = ARRAY_SIZE(mt8186_mt6366_rt1019_rt5682s_codec_conf), +}; + +static struct snd_soc_card mt8186_mt6366_rt1019_rt5682s_soc_card = { + .name = "mt8186_rt1019_rt5682s", + .owner = THIS_MODULE, + .dai_link = mt8186_mt6366_rt1019_rt5682s_dai_links, + .num_links = ARRAY_SIZE(mt8186_mt6366_rt1019_rt5682s_dai_links), + .controls = mt8186_mt6366_rt1019_rt5682s_controls, + .num_controls = ARRAY_SIZE(mt8186_mt6366_rt1019_rt5682s_controls), + .dapm_widgets = mt8186_mt6366_rt1019_rt5682s_widgets, + .num_dapm_widgets = ARRAY_SIZE(mt8186_mt6366_rt1019_rt5682s_widgets), + .dapm_routes = mt8186_mt6366_rt1019_rt5682s_routes, + .num_dapm_routes = ARRAY_SIZE(mt8186_mt6366_rt1019_rt5682s_routes), + .codec_conf = mt8186_mt6366_rt1019_rt5682s_codec_conf, + .num_configs = ARRAY_SIZE(mt8186_mt6366_rt1019_rt5682s_codec_conf), +}; + +static struct snd_soc_card mt8186_mt6366_rt5682s_max98360_soc_card = { + .name = "mt8186_rt5682s_max98360", + .owner = THIS_MODULE, + .dai_link = mt8186_mt6366_rt1019_rt5682s_dai_links, + .num_links = ARRAY_SIZE(mt8186_mt6366_rt1019_rt5682s_dai_links), + .controls = mt8186_mt6366_rt1019_rt5682s_controls, + .num_controls = ARRAY_SIZE(mt8186_mt6366_rt1019_rt5682s_controls), + .dapm_widgets = mt8186_mt6366_rt1019_rt5682s_widgets, + .num_dapm_widgets = ARRAY_SIZE(mt8186_mt6366_rt1019_rt5682s_widgets), + .dapm_routes = mt8186_mt6366_rt1019_rt5682s_routes, + .num_dapm_routes = ARRAY_SIZE(mt8186_mt6366_rt1019_rt5682s_routes), + .codec_conf = mt8186_mt6366_rt1019_rt5682s_codec_conf, + .num_configs = ARRAY_SIZE(mt8186_mt6366_rt1019_rt5682s_codec_conf), +}; + +static struct snd_soc_card mt8186_mt6366_rt5650_soc_card = { + .name = "mt8186_rt5650", + .owner = THIS_MODULE, + .dai_link = mt8186_mt6366_rt1019_rt5682s_dai_links, + .num_links = ARRAY_SIZE(mt8186_mt6366_rt1019_rt5682s_dai_links), + .controls = mt8186_mt6366_rt1019_rt5682s_controls, + .num_controls = ARRAY_SIZE(mt8186_mt6366_rt1019_rt5682s_controls), + .dapm_widgets = mt8186_mt6366_rt1019_rt5682s_widgets, + .num_dapm_widgets = ARRAY_SIZE(mt8186_mt6366_rt1019_rt5682s_widgets), + .dapm_routes = mt8186_mt6366_rt5650_routes, + .num_dapm_routes = ARRAY_SIZE(mt8186_mt6366_rt5650_routes), + .codec_conf = mt8186_mt6366_rt1019_rt5682s_codec_conf, + .num_configs = ARRAY_SIZE(mt8186_mt6366_rt1019_rt5682s_codec_conf), +}; + +static int mt8186_mt6366_legacy_probe(struct mtk_soc_card_data *soc_card_data) +{ + struct mtk_platform_card_data *card_data = soc_card_data->card_data; + struct snd_soc_card *card = card_data->card; + struct device *dev = card->dev; + struct snd_soc_dai_link *dai_link; + struct device_node *headset_codec, *playback_codec; + int ret, i; + + playback_codec = of_get_child_by_name(dev->of_node, "playback-codecs"); + if (!playback_codec) + return dev_err_probe(dev, -EINVAL, + "Property 'playback-codecs' missing or invalid\n"); + + headset_codec = of_get_child_by_name(dev->of_node, "headset-codec"); + if (!headset_codec) { + of_node_put(playback_codec); + return dev_err_probe(dev, -EINVAL, + "Property 'headset-codec' missing or invalid\n"); + } + + for_each_card_prelinks(card, i, dai_link) { + ret = mt8186_mt6366_card_set_be_link(card, dai_link, playback_codec, "I2S3"); + if (ret) { + dev_err_probe(dev, ret, "%s set playback_codec fail\n", + dai_link->name); + break; + } + + ret = mt8186_mt6366_card_set_be_link(card, dai_link, headset_codec, "I2S0"); + if (ret) { + dev_err_probe(dev, ret, "%s set headset_codec fail\n", + dai_link->name); + break; + } + + ret = mt8186_mt6366_card_set_be_link(card, dai_link, headset_codec, "I2S1"); + if (ret) { + dev_err_probe(dev, ret, "%s set headset_codec fail\n", + dai_link->name); + break; + } + } + of_node_put(headset_codec); + of_node_put(playback_codec); + + return ret; +} + +static int mt8186_mt6366_soc_card_probe(struct mtk_soc_card_data *soc_card_data, bool legacy) +{ + struct mtk_platform_card_data *card_data = soc_card_data->card_data; + struct snd_soc_card *card = card_data->card; + struct snd_soc_dai_link *dai_link; + struct mt8186_mt6366_rt1019_rt5682s_priv *mach_priv; + int i, ret; + + mach_priv = devm_kzalloc(card->dev, sizeof(*mach_priv), GFP_KERNEL); + if (!mach_priv) + return -ENOMEM; + + soc_card_data->mach_priv = mach_priv; + + mach_priv->dmic_sel = devm_gpiod_get_optional(card->dev, + "dmic", GPIOD_OUT_LOW); + if (IS_ERR(mach_priv->dmic_sel)) + return dev_err_probe(card->dev, PTR_ERR(mach_priv->dmic_sel), + "DMIC gpio failed\n"); + + for_each_card_prelinks(card, i, dai_link) { + if (strcmp(dai_link->name, "I2S0") == 0 || + strcmp(dai_link->name, "I2S1") == 0 || + strcmp(dai_link->name, "I2S2") == 0) { + if (card_data->flags & DA7219_CODEC_PRESENT) { + dai_link->be_hw_params_fixup = mt8186_i2s_hw_params_32le_fixup; + dai_link->ops = &mt8186_da7219_i2s_ops; + } else { + dai_link->be_hw_params_fixup = mt8186_i2s_hw_params_24le_fixup; + dai_link->ops = &mt8186_rt5682s_i2s_ops; + } + } else if (strcmp(dai_link->name, "I2S3") == 0) { + if (card_data->flags & DA7219_CODEC_PRESENT) + dai_link->be_hw_params_fixup = mt8186_i2s_hw_params_24le_fixup; + else + dai_link->be_hw_params_fixup = mt8186_i2s_hw_params_32le_fixup; + } + } + + if (legacy) { + ret = mt8186_mt6366_legacy_probe(soc_card_data); + if (ret) + return ret; + } + + ret = mt8186_afe_gpio_init(card->dev); + if (ret) + return dev_err_probe(card->dev, ret, "init AFE gpio error\n"); + + return 0; +} + +static const unsigned int mt8186_pcm_playback_channels[] = { 2 }; +static const unsigned int mt8186_pcm_capture_channels[] = { 1, 2 }; +static const unsigned int mt8186_pcm_rates[] = { 48000 }; + +static const struct snd_pcm_hw_constraint_list mt8186_rate_constraint = { + .list = mt8186_pcm_rates, + .count = ARRAY_SIZE(mt8186_pcm_rates) +}; + +static const struct mtk_pcm_constraints_data mt8186_pcm_constraints[MTK_CONSTRAINT_CAPTURE + 1] = { + [MTK_CONSTRAINT_PLAYBACK] = { + .channels = &(const struct snd_pcm_hw_constraint_list) { + .list = mt8186_pcm_playback_channels, + .count = ARRAY_SIZE(mt8186_pcm_playback_channels) + }, + .rates = &mt8186_rate_constraint, + }, + [MTK_CONSTRAINT_CAPTURE] = { + .channels = &(const struct snd_pcm_hw_constraint_list) { + .list = mt8186_pcm_capture_channels, + .count = ARRAY_SIZE(mt8186_pcm_capture_channels) + }, + .rates = &mt8186_rate_constraint, + } +}; + +static const struct mtk_sof_priv mt8186_sof_priv = { + .conn_streams = g_sof_conn_streams, + .num_streams = ARRAY_SIZE(g_sof_conn_streams), + .sof_dai_link_fixup = mt8186_sof_dai_link_fixup +}; + +static const struct mtk_soundcard_pdata mt8186_mt6366_da7219_max98357_pdata = { + .card_data = &(struct mtk_platform_card_data) { + .card = &mt8186_mt6366_da7219_max98357_soc_card, + .num_jacks = MT8186_JACK_MAX, + .pcm_constraints = mt8186_pcm_constraints, + .num_pcm_constraints = ARRAY_SIZE(mt8186_pcm_constraints), + .flags = DA7219_CODEC_PRESENT, + }, + .sof_priv = &mt8186_sof_priv, + .soc_probe = mt8186_mt6366_soc_card_probe +}; + +static const struct mtk_soundcard_pdata mt8186_mt6366_rt1019_rt5682s_pdata = { + .card_data = &(struct mtk_platform_card_data) { + .card = &mt8186_mt6366_rt1019_rt5682s_soc_card, + .num_jacks = MT8186_JACK_MAX, + .pcm_constraints = mt8186_pcm_constraints, + .num_pcm_constraints = ARRAY_SIZE(mt8186_pcm_constraints), + }, + .sof_priv = &mt8186_sof_priv, + .soc_probe = mt8186_mt6366_soc_card_probe +}; + +static const struct mtk_soundcard_pdata mt8186_mt6366_rt5682s_max98360_pdata = { + .card_data = &(struct mtk_platform_card_data) { + .card = &mt8186_mt6366_rt5682s_max98360_soc_card, + .num_jacks = MT8186_JACK_MAX, + .pcm_constraints = mt8186_pcm_constraints, + .num_pcm_constraints = ARRAY_SIZE(mt8186_pcm_constraints), + }, + .sof_priv = &mt8186_sof_priv, + .soc_probe = mt8186_mt6366_soc_card_probe +}; + +static const struct mtk_soundcard_pdata mt8186_mt6366_rt5650_pdata = { + .card_data = &(struct mtk_platform_card_data) { + .card = &mt8186_mt6366_rt5650_soc_card, + .num_jacks = MT8186_JACK_MAX, + .pcm_constraints = mt8186_pcm_constraints, + .num_pcm_constraints = ARRAY_SIZE(mt8186_pcm_constraints), + }, + .sof_priv = &mt8186_sof_priv, + .soc_probe = mt8186_mt6366_soc_card_probe +}; + +#if IS_ENABLED(CONFIG_OF) +static const struct of_device_id mt8186_mt6366_dt_match[] = { + { + .compatible = "mediatek,mt8186-mt6366-rt1019-rt5682s-sound", + .data = &mt8186_mt6366_rt1019_rt5682s_pdata, + }, + { + .compatible = "mediatek,mt8186-mt6366-rt5682s-max98360-sound", + .data = &mt8186_mt6366_rt5682s_max98360_pdata, + }, + { + .compatible = "mediatek,mt8186-mt6366-rt5650-sound", + .data = &mt8186_mt6366_rt5650_pdata, + }, + { + .compatible = "mediatek,mt8186-mt6366-da7219-max98357-sound", + .data = &mt8186_mt6366_da7219_max98357_pdata, + }, + { /* sentinel */ } +}; +MODULE_DEVICE_TABLE(of, mt8186_mt6366_dt_match); +#endif + +static struct platform_driver mt8186_mt6366_driver = { + .driver = { + .name = "mt8186_mt6366", +#if IS_ENABLED(CONFIG_OF) + .of_match_table = mt8186_mt6366_dt_match, +#endif + .pm = &snd_soc_pm_ops, + }, + .probe = mtk_soundcard_common_probe, +}; + +module_platform_driver(mt8186_mt6366_driver); + +/* Module information */ +MODULE_DESCRIPTION("MT8186-MT6366 ALSA SoC machine driver"); +MODULE_AUTHOR("Jiaxin Yu "); +MODULE_LICENSE("GPL v2"); +MODULE_ALIAS("mt8186_mt6366 soc card"); -- cgit v1.2.3 From dc7a31300a8f28af282974512c2d403ada0658b5 Mon Sep 17 00:00:00 2001 From: AngeloGioacchino Del Regno Date: Tue, 16 Apr 2024 09:14:06 +0200 Subject: ASoC: dt-bindings: mt8195: Document audio-routing and dai-link subnode Document the dai-link subnodes and the audio-routing property, allowing to describe machine specific audio hardware and links in device tree. While at it, also deprecate the old properties which were previously used with driver hardcoded configuration. Also, since describing machine specific audio hardware and links replaces the now deprecated old logic doing the same in a driver hardcoded fashion, it is not allowed to have both the old and new properties together. Reviewed-by: Rob Herring Signed-off-by: AngeloGioacchino Del Regno Link: https://lore.kernel.org/r/20240416071410.75620-15-angelogioacchino.delregno@collabora.com Signed-off-by: Mark Brown --- .../devicetree/bindings/sound/mt8195-mt6359.yaml | 134 +++++++++++++++++++++ 1 file changed, 134 insertions(+) diff --git a/Documentation/devicetree/bindings/sound/mt8195-mt6359.yaml b/Documentation/devicetree/bindings/sound/mt8195-mt6359.yaml index c1ddbf672ca3..2af1d8ffbd8b 100644 --- a/Documentation/devicetree/bindings/sound/mt8195-mt6359.yaml +++ b/Documentation/devicetree/bindings/sound/mt8195-mt6359.yaml @@ -12,6 +12,9 @@ maintainers: description: This binding describes the MT8195 sound card. +allOf: + - $ref: sound-card-common.yaml# + properties: compatible: enum: @@ -23,6 +26,33 @@ properties: $ref: /schemas/types.yaml#/definitions/string description: User specified audio sound card name + audio-routing: + description: + A list of the connections between audio components. Each entry is a + pair of strings, the first being the connection's sink, the second + being the connection's source. + Valid names could be the input or output widgets of audio components, + power supplies, MicBias of codec and the software switch. + minItems: 2 + items: + enum: + # Sinks + - Ext Spk + - Headphone + - IN1P + - Left Spk + - Right Spk + + # Sources + - Headset Mic + - HPOL + - HPOR + - Left BE_OUT + - Left SPO + - Right BE_OUT + - Right SPO + - Speaker + mediatek,platform: $ref: /schemas/types.yaml#/definitions/phandle description: The phandle of MT8195 ASoC platform. @@ -30,10 +60,12 @@ properties: mediatek,dptx-codec: $ref: /schemas/types.yaml#/definitions/phandle description: The phandle of MT8195 Display Port Tx codec node. + deprecated: true mediatek,hdmi-codec: $ref: /schemas/types.yaml#/definitions/phandle description: The phandle of MT8195 HDMI codec node. + deprecated: true mediatek,adsp: $ref: /schemas/types.yaml#/definitions/phandle @@ -45,20 +77,122 @@ properties: A list of the desired dai-links in the sound card. Each entry is a name defined in the machine driver. +patternProperties: + ".*-dai-link$": + type: object + additionalProperties: false + description: + Container for dai-link level properties and CODEC sub-nodes. + + properties: + link-name: + description: Indicates dai-link name and PCM stream name + enum: + - DPTX_BE + - ETDM1_IN_BE + - ETDM2_IN_BE + - ETDM1_OUT_BE + - ETDM2_OUT_BE + - ETDM3_OUT_BE + - PCM1_BE + + codec: + description: Holds subnode which indicates codec dai. + type: object + additionalProperties: false + properties: + sound-dai: + minItems: 1 + maxItems: 2 + required: + - sound-dai + + dai-format: + description: audio format + enum: [ i2s, right_j, left_j, dsp_a, dsp_b ] + + mediatek,clk-provider: + $ref: /schemas/types.yaml#/definitions/string + description: Indicates dai-link clock master. + enum: [ cpu, codec ] + + required: + - link-name + additionalProperties: false required: - compatible - mediatek,platform +# Disallow legacy properties if xxx-dai-link nodes are specified +if: + not: + patternProperties: + ".*-dai-link$": false +then: + properties: + mediatek,dptx-codec: false + mediatek,hdmi-codec: false + examples: - | sound: mt8195-sound { compatible = "mediatek,mt8195_mt6359_rt1019_rt5682"; + model = "mt8195_r1019_5682"; mediatek,platform = <&afe>; pinctrl-names = "default"; pinctrl-0 = <&aud_pins_default>; + + audio-routing = + "Headphone", "HPOL", + "Headphone", "HPOR", + "IN1P", "Headset Mic", + "Ext Spk", "Speaker"; + + mm-dai-link { + link-name = "ETDM1_IN_BE"; + mediatek,clk-provider = "cpu"; + }; + + hs-playback-dai-link { + link-name = "ETDM1_OUT_BE"; + mediatek,clk-provider = "cpu"; + codec { + sound-dai = <&headset_codec>; + }; + }; + + hs-capture-dai-link { + link-name = "ETDM2_IN_BE"; + mediatek,clk-provider = "cpu"; + codec { + sound-dai = <&headset_codec>; + }; + }; + + spk-playback-dai-link { + link-name = "ETDM2_OUT_BE"; + mediatek,clk-provider = "cpu"; + codec { + sound-dai = <&spk_amplifier>; + }; + }; + + hdmi-dai-link { + link-name = "ETDM3_OUT_BE"; + codec { + sound-dai = <&hdmi_tx>; + }; + }; + + displayport-dai-link { + link-name = "DPTX_BE"; + codec { + sound-dai = <&dp_tx>; + }; + }; }; ... -- cgit v1.2.3 From 5a50483c47b8cf3066eb151fa21e195f3dfab5a8 Mon Sep 17 00:00:00 2001 From: AngeloGioacchino Del Regno Date: Tue, 16 Apr 2024 09:14:07 +0200 Subject: ASoC: dt-bindings: mt8192: Document audio-routing and dai-link subnode Document the dai-link subnodes and the audio-routing property, allowing to describe machine specific audio hardware and links in device tree. While at it, also deprecate the old properties which were previously used with the driver's partially hardcoded configuration. Also, since describing machine specific audio hardware and links replaces the now deprecated old logic doing the same in a driver hardcoded fashion, it is not allowed to have both the old and new properties together. Reviewed-by: Rob Herring Signed-off-by: AngeloGioacchino Del Regno Link: https://lore.kernel.org/r/20240416071410.75620-16-angelogioacchino.delregno@collabora.com Signed-off-by: Mark Brown --- .../sound/mt8192-mt6359-rt1015-rt5682.yaml | 139 +++++++++++++++++++-- 1 file changed, 129 insertions(+), 10 deletions(-) diff --git a/Documentation/devicetree/bindings/sound/mt8192-mt6359-rt1015-rt5682.yaml b/Documentation/devicetree/bindings/sound/mt8192-mt6359-rt1015-rt5682.yaml index 7e50f5d65c8f..c4e68f31aaab 100644 --- a/Documentation/devicetree/bindings/sound/mt8192-mt6359-rt1015-rt5682.yaml +++ b/Documentation/devicetree/bindings/sound/mt8192-mt6359-rt1015-rt5682.yaml @@ -13,6 +13,9 @@ maintainers: description: This binding describes the MT8192 sound card. +allOf: + - $ref: sound-card-common.yaml# + properties: compatible: enum: @@ -20,6 +23,31 @@ properties: - mediatek,mt8192_mt6359_rt1015p_rt5682 - mediatek,mt8192_mt6359_rt1015p_rt5682s + audio-routing: + description: + A list of the connections between audio components. Each entry is a + pair of strings, the first being the connection's sink, the second + being the connection's source. + Valid names could be the input or output widgets of audio components, + power supplies, MicBias of codec and the software switch. + minItems: 2 + items: + enum: + # Sinks + - Speakers + - Headphone Jack + - IN1P + - Left Spk + - Right Spk + + # Sources + - Headset Mic + - HPOL + - HPOR + - Left SPO + - Right SPO + - Speaker + mediatek,platform: $ref: /schemas/types.yaml#/definitions/phandle description: The phandle of MT8192 ASoC platform. @@ -27,10 +55,12 @@ properties: mediatek,hdmi-codec: $ref: /schemas/types.yaml#/definitions/phandle description: The phandle of HDMI codec. + deprecated: true headset-codec: type: object additionalProperties: false + deprecated: true properties: sound-dai: @@ -41,6 +71,7 @@ properties: speaker-codecs: type: object additionalProperties: false + deprecated: true properties: sound-dai: @@ -51,33 +82,121 @@ properties: required: - sound-dai -additionalProperties: false +patternProperties: + ".*-dai-link$": + type: object + additionalProperties: false + + description: + Container for dai-link level properties and CODEC sub-nodes. + + properties: + link-name: + description: Indicates dai-link name and PCM stream name + enum: + - I2S0 + - I2S1 + - I2S2 + - I2S3 + - I2S4 + - I2S5 + - I2S6 + - I2S7 + - I2S8 + - I2S9 + - TDM + + codec: + description: Holds subnode which indicates codec dai. + type: object + additionalProperties: false + properties: + sound-dai: + minItems: 1 + maxItems: 2 + required: + - sound-dai + + dai-format: + description: audio format + enum: [ i2s, right_j, left_j, dsp_a, dsp_b ] + + mediatek,clk-provider: + $ref: /schemas/types.yaml#/definitions/string + description: Indicates dai-link clock master. + enum: [ cpu, codec ] + + required: + - link-name + +unevaluatedProperties: false required: - compatible - mediatek,platform - - headset-codec - - speaker-codecs + +# Disallow legacy properties if xxx-dai-link nodes are specified +if: + not: + patternProperties: + ".*-dai-link$": false +then: + properties: + headset-codec: false + speaker-codecs: false + mediatek,hdmi-codec: false examples: - | sound: mt8192-sound { compatible = "mediatek,mt8192_mt6359_rt1015_rt5682"; - mediatek,platform = <&afe>; - mediatek,hdmi-codec = <&anx_bridge_dp>; + model = "mt8192_mt6359_rt1015_rt5682"; pinctrl-names = "aud_clk_mosi_off", "aud_clk_mosi_on"; pinctrl-0 = <&aud_clk_mosi_off>; pinctrl-1 = <&aud_clk_mosi_on>; + mediatek,platform = <&afe>; + + audio-routing = + "Headphone Jack", "HPOL", + "Headphone Jack", "HPOR", + "IN1P", "Headset Mic", + "Speakers", "Speaker"; + + spk-playback-dai-link { + link-name = "I2S3"; + dai-format = "i2s"; + mediatek,clk-provider = "cpu"; + codec { + sound-dai = <&rt1015p>; + }; + }; + + hs-playback-dai-link { + link-name = "I2S8"; + dai-format = "i2s"; + mediatek,clk-provider = "cpu"; + codec { + sound-dai = <&rt5682 0>; + }; + }; - headset-codec { - sound-dai = <&rt5682>; + hs-capture-dai-link { + link-name = "I2S9"; + dai-format = "i2s"; + mediatek,clk-provider = "cpu"; + codec { + sound-dai = <&rt5682 0>; + }; }; - speaker-codecs { - sound-dai = <&rt1015_l>, - <&rt1015_r>; + displayport-dai-link { + link-name = "TDM"; + dai-format = "dsp_a"; + codec { + sound-dai = <&anx_bridge_dp>; + }; }; }; -- cgit v1.2.3 From 787f190cd1cd3123555e33a3400f3e919ec94a81 Mon Sep 17 00:00:00 2001 From: AngeloGioacchino Del Regno Date: Tue, 16 Apr 2024 09:14:08 +0200 Subject: ASoC: dt-bindings: mt8186: Document audio-routing and dai-link subnode Document the dai-link subnodes and the audio-routing property, allowing to describe machine specific audio hardware and links in device tree. While at it, also deprecate the old properties which were previously used with the driver's partially hardcoded configuration. Also, since describing machine specific audio hardware and links replaces the now deprecated old logic doing the same in a driver hardcoded fashion, it is not allowed to have both the old and new properties together. Reviewed-by: Rob Herring Signed-off-by: AngeloGioacchino Del Regno Link: https://lore.kernel.org/r/20240416071410.75620-17-angelogioacchino.delregno@collabora.com Signed-off-by: Mark Brown --- .../sound/mt8186-mt6366-da7219-max98357.yaml | 131 +++++++++++++++++++-- .../sound/mt8186-mt6366-rt1019-rt5682s.yaml | 120 +++++++++++++++++-- 2 files changed, 233 insertions(+), 18 deletions(-) diff --git a/Documentation/devicetree/bindings/sound/mt8186-mt6366-da7219-max98357.yaml b/Documentation/devicetree/bindings/sound/mt8186-mt6366-da7219-max98357.yaml index 9853c11a1330..cbc641ecbe94 100644 --- a/Documentation/devicetree/bindings/sound/mt8186-mt6366-da7219-max98357.yaml +++ b/Documentation/devicetree/bindings/sound/mt8186-mt6366-da7219-max98357.yaml @@ -12,17 +12,46 @@ maintainers: description: This binding describes the MT8186 sound card. +allOf: + - $ref: sound-card-common.yaml# + properties: compatible: enum: - mediatek,mt8186-mt6366-da7219-max98357-sound + audio-routing: + $ref: /schemas/types.yaml#/definitions/non-unique-string-array + description: + A list of the connections between audio components. Each entry is a + pair of strings, the first being the connection's sink, the second + being the connection's source. + Valid names could be the input or output widgets of audio components, + power supplies, MicBias of codec and the software switch. + minItems: 2 + items: + enum: + # Sinks + - HDMI1 + - Headphones + - Line Out + - MIC + - Speakers + + # Sources + - Headset Mic + - HPL + - HPR + - Speaker + - TX + mediatek,platform: $ref: /schemas/types.yaml#/definitions/phandle description: The phandle of MT8186 ASoC platform. headset-codec: type: object + deprecated: true additionalProperties: false properties: sound-dai: @@ -32,6 +61,7 @@ properties: playback-codecs: type: object + deprecated: true additionalProperties: false properties: sound-dai: @@ -53,32 +83,115 @@ properties: A list of the desired dai-links in the sound card. Each entry is a name defined in the machine driver. -additionalProperties: false +patternProperties: + ".*-dai-link$": + type: object + additionalProperties: false + description: + Container for dai-link level properties and CODEC sub-nodes. + + properties: + link-name: + description: Indicates dai-link name and PCM stream name + items: + enum: + - I2S0 + - I2S1 + - I2S2 + - I2S3 + + codec: + description: Holds subnode which indicates codec dai. + type: object + additionalProperties: false + properties: + sound-dai: + minItems: 1 + maxItems: 2 + required: + - sound-dai + + dai-format: + description: audio format + items: + enum: + - i2s + - right_j + - left_j + - dsp_a + - dsp_b + + mediatek,clk-provider: + $ref: /schemas/types.yaml#/definitions/string + description: Indicates dai-link clock master. + items: + enum: + - cpu + - codec + + required: + - link-name + +unevaluatedProperties: false required: - compatible - mediatek,platform - - headset-codec - - playback-codecs + +# Disallow legacy properties if xxx-dai-link nodes are specified +if: + not: + patternProperties: + ".*-dai-link$": false +then: + properties: + headset-codec: false + speaker-codecs: false examples: - | sound: mt8186-sound { compatible = "mediatek,mt8186-mt6366-da7219-max98357-sound"; - mediatek,platform = <&afe>; + model = "mt8186_da7219_m98357"; pinctrl-names = "aud_clk_mosi_off", "aud_clk_mosi_on"; pinctrl-0 = <&aud_clk_mosi_off>; pinctrl-1 = <&aud_clk_mosi_on>; + mediatek,platform = <&afe>; + + audio-routing = + "Headphones", "HPL", + "Headphones", "HPR", + "MIC", "Headset Mic", + "Speakers", "Speaker", + "HDMI1", "TX"; + + hs-playback-dai-link { + link-name = "I2S0"; + dai-format = "i2s"; + mediatek,clk-provider = "cpu"; + codec { + sound-dai = <&da7219>; + }; + }; - headset-codec { - sound-dai = <&da7219>; + hs-capture-dai-link { + link-name = "I2S1"; + dai-format = "i2s"; + mediatek,clk-provider = "cpu"; + codec { + sound-dai = <&da7219>; + }; }; - playback-codecs { - sound-dai = <&anx_bridge_dp>, - <&max98357a>; + spk-dp-playback-dai-link { + link-name = "I2S3"; + dai-format = "i2s"; + mediatek,clk-provider = "cpu"; + codec { + sound-dai = <&anx_bridge_dp>, <&max98357a>; + }; }; }; diff --git a/Documentation/devicetree/bindings/sound/mt8186-mt6366-rt1019-rt5682s.yaml b/Documentation/devicetree/bindings/sound/mt8186-mt6366-rt1019-rt5682s.yaml index bdf7b0960533..ed93f18ef985 100644 --- a/Documentation/devicetree/bindings/sound/mt8186-mt6366-rt1019-rt5682s.yaml +++ b/Documentation/devicetree/bindings/sound/mt8186-mt6366-rt1019-rt5682s.yaml @@ -12,6 +12,9 @@ maintainers: description: This binding describes the MT8186 sound card. +allOf: + - $ref: sound-card-common.yaml# + properties: compatible: enum: @@ -19,6 +22,34 @@ properties: - mediatek,mt8186-mt6366-rt5682s-max98360-sound - mediatek,mt8186-mt6366-rt5650-sound + audio-routing: + $ref: /schemas/types.yaml#/definitions/non-unique-string-array + description: + A list of the connections between audio components. Each entry is a + pair of strings, the first being the connection's sink, the second + being the connection's source. + Valid names could be the input or output widgets of audio components, + power supplies, MicBias of codec and the software switch. + minItems: 2 + items: + enum: + # Sinks + - HDMI1 + - Headphone + - IN1P + - IN1N + - Line Out + - Speakers + + # Sources + - Headset Mic + - HPOL + - HPOR + - Speaker + - SPOL + - SPOR + - TX + mediatek,platform: $ref: /schemas/types.yaml#/definitions/phandle description: The phandle of MT8186 ASoC platform. @@ -32,6 +63,7 @@ properties: headset-codec: type: object + deprecated: true additionalProperties: false properties: sound-dai: @@ -41,6 +73,7 @@ properties: playback-codecs: type: object + deprecated: true additionalProperties: false properties: sound-dai: @@ -62,13 +95,56 @@ properties: A list of the desired dai-links in the sound card. Each entry is a name defined in the machine driver. -additionalProperties: false +patternProperties: + ".*-dai-link$": + type: object + additionalProperties: false + description: + Container for dai-link level properties and CODEC sub-nodes. + + properties: + link-name: + description: Indicates dai-link name and PCM stream name + enum: [ I2S0, I2S1, I2S2, I2S3 ] + + codec: + description: Holds subnode which indicates codec dai. + type: object + additionalProperties: false + properties: + sound-dai: + minItems: 1 + maxItems: 2 + required: + - sound-dai + + dai-format: + description: audio format + enum: [ i2s, right_j, left_j, dsp_a, dsp_b ] + + mediatek,clk-provider: + $ref: /schemas/types.yaml#/definitions/string + description: Indicates dai-link clock master. + enum: [ cpu, codec ] + + required: + - link-name + +unevaluatedProperties: false required: - compatible - mediatek,platform - - headset-codec - - playback-codecs + +# Disallow legacy properties if xxx-dai-link nodes are specified +if: + not: + patternProperties: + ".*-dai-link$": false +then: + properties: + headset-codec: false + speaker-codecs: false examples: - | @@ -76,23 +152,49 @@ examples: sound: mt8186-sound { compatible = "mediatek,mt8186-mt6366-rt1019-rt5682s-sound"; - mediatek,platform = <&afe>; + model = "mt8186_rt1019_rt5682s"; pinctrl-names = "aud_clk_mosi_off", "aud_clk_mosi_on", "aud_gpio_dmic_sec"; pinctrl-0 = <&aud_clk_mosi_off>; pinctrl-1 = <&aud_clk_mosi_on>; pinctrl-2 = <&aud_gpio_dmic_sec>; + mediatek,platform = <&afe>; dmic-gpios = <&pio 23 GPIO_ACTIVE_HIGH>; - headset-codec { - sound-dai = <&rt5682s>; + audio-routing = + "Headphone", "HPOL", + "Headphone", "HPOR", + "IN1P", "Headset Mic", + "Speakers", "Speaker", + "HDMI1", "TX"; + + hs-playback-dai-link { + link-name = "I2S0"; + dai-format = "i2s"; + mediatek,clk-provider = "cpu"; + codec { + sound-dai = <&rt5682s 0>; + }; + }; + + hs-capture-dai-link { + link-name = "I2S1"; + dai-format = "i2s"; + mediatek,clk-provider = "cpu"; + codec { + sound-dai = <&rt5682s 0>; + }; }; - playback-codecs { - sound-dai = <&it6505dptx>, - <&rt1019p>; + spk-hdmi-playback-dai-link { + link-name = "I2S3"; + dai-format = "i2s"; + mediatek,clk-provider = "cpu"; + codec { + sound-dai = <&it6505dptx>, <&rt1019p>; + }; }; }; -- cgit v1.2.3 From 58300f8d6a48e58d1843199be743f819e2791ea3 Mon Sep 17 00:00:00 2001 From: Steven Rostedt Date: Tue, 16 Apr 2024 00:03:03 -0400 Subject: ASoC: tracing: Export SND_SOC_DAPM_DIR_OUT to its value The string SND_SOC_DAPM_DIR_OUT is printed in the snd_soc_dapm_path trace event instead of its value: (((REC->path_dir) == SND_SOC_DAPM_DIR_OUT) ? "->" : "<-") User space cannot parse this, as it has no idea what SND_SOC_DAPM_DIR_OUT is. Use TRACE_DEFINE_ENUM() to convert it to its value: (((REC->path_dir) == 1) ? "->" : "<-") So that user space tools, such as perf and trace-cmd, can parse it correctly. Reported-by: Luca Ceresoli Fixes: 6e588a0d839b5 ("ASoC: dapm: Consolidate path trace events") Signed-off-by: Steven Rostedt (Google) Link: https://lore.kernel.org/r/20240416000303.04670cdf@rorschach.local.home Signed-off-by: Mark Brown --- include/trace/events/asoc.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/include/trace/events/asoc.h b/include/trace/events/asoc.h index 4eed9028bb11..517015ef36a8 100644 --- a/include/trace/events/asoc.h +++ b/include/trace/events/asoc.h @@ -12,6 +12,8 @@ #define DAPM_DIRECT "(direct)" #define DAPM_ARROW(dir) (((dir) == SND_SOC_DAPM_DIR_OUT) ? "->" : "<-") +TRACE_DEFINE_ENUM(SND_SOC_DAPM_DIR_OUT); + struct snd_soc_jack; struct snd_soc_card; struct snd_soc_dapm_widget; -- cgit v1.2.3 From 4225dfa4535f219b03ae14147d9c6e7e82ec8df4 Mon Sep 17 00:00:00 2001 From: Dmitry Safonov <0x7f454c46@gmail.com> Date: Sat, 13 Apr 2024 02:42:52 +0100 Subject: selftests/tcp_ao: Make RST tests less flaky Currently, "active reset" cases are flaky, because select() is called for 3 sockets, while only 2 are expected to receive RST. The idea of the third socket was to get into request_sock_queue, but the test mistakenly attempted to connect() after the listener socket was shut down. Repair this test, it's important to check the different kernel code-paths for signing RST TCP-AO segments. Fixes: c6df7b2361d7 ("selftests/net: Add TCP-AO RST test") Reported-by: Jakub Kicinski Signed-off-by: Dmitry Safonov <0x7f454c46@gmail.com> Signed-off-by: Paolo Abeni --- tools/testing/selftests/net/tcp_ao/rst.c | 23 +++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/tools/testing/selftests/net/tcp_ao/rst.c b/tools/testing/selftests/net/tcp_ao/rst.c index 7df8b8700e39..a2fe88d35ac0 100644 --- a/tools/testing/selftests/net/tcp_ao/rst.c +++ b/tools/testing/selftests/net/tcp_ao/rst.c @@ -256,8 +256,6 @@ static int test_wait_fds(int sk[], size_t nr, bool is_writable[], static void test_client_active_rst(unsigned int port) { - /* one in queue, another accept()ed */ - unsigned int wait_for = backlog + 2; int i, sk[3], err; bool is_writable[ARRAY_SIZE(sk)] = {false}; unsigned int last = ARRAY_SIZE(sk) - 1; @@ -275,16 +273,20 @@ static void test_client_active_rst(unsigned int port) for (i = 0; i < last; i++) { err = _test_connect_socket(sk[i], this_ip_dest, port, (i == 0) ? TEST_TIMEOUT_SEC : -1); - if (err < 0) test_error("failed to connect()"); } - synchronize_threads(); /* 2: connection accept()ed, another queued */ - err = test_wait_fds(sk, last, is_writable, wait_for, TEST_TIMEOUT_SEC); + synchronize_threads(); /* 2: two connections: one accept()ed, another queued */ + err = test_wait_fds(sk, last, is_writable, last, TEST_TIMEOUT_SEC); if (err < 0) test_error("test_wait_fds(): %d", err); + /* async connect() with third sk to get into request_sock_queue */ + err = _test_connect_socket(sk[last], this_ip_dest, port, -1); + if (err < 0) + test_error("failed to connect()"); + synchronize_threads(); /* 3: close listen socket */ if (test_client_verify(sk[0], packet_sz, quota / packet_sz, TEST_TIMEOUT_SEC)) test_fail("Failed to send data on connected socket"); @@ -292,13 +294,14 @@ static void test_client_active_rst(unsigned int port) test_ok("Verified established tcp connection"); synchronize_threads(); /* 4: finishing up */ - err = _test_connect_socket(sk[last], this_ip_dest, port, -1); - if (err < 0) - test_error("failed to connect()"); synchronize_threads(); /* 5: closed active sk */ - err = test_wait_fds(sk, ARRAY_SIZE(sk), NULL, - wait_for, TEST_TIMEOUT_SEC); + /* + * Wait for 2 connections: one accepted, another in the accept queue, + * the one in request_sock_queue won't get fully established, so + * doesn't receive an active RST, see inet_csk_listen_stop(). + */ + err = test_wait_fds(sk, last, NULL, last, TEST_TIMEOUT_SEC); if (err < 0) test_error("select(): %d", err); -- cgit v1.2.3 From b089b3bead532419cdcbd8e4e0a3e23c49d11573 Mon Sep 17 00:00:00 2001 From: Dmitry Safonov <0x7f454c46@gmail.com> Date: Sat, 13 Apr 2024 02:42:53 +0100 Subject: selftests/tcp_ao: Zero-init tcp_ao_info_opt The structure is on the stack and has to be zero-initialized as the kernel checks for: > if (in.reserved != 0 || in.reserved2 != 0) > return -EINVAL; Fixes: b26660531cf6 ("selftests/net: Add test for TCP-AO add setsockopt() command") Signed-off-by: Dmitry Safonov <0x7f454c46@gmail.com> Signed-off-by: Paolo Abeni --- tools/testing/selftests/net/tcp_ao/setsockopt-closed.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/testing/selftests/net/tcp_ao/setsockopt-closed.c b/tools/testing/selftests/net/tcp_ao/setsockopt-closed.c index 452de131fa3a..517930f9721b 100644 --- a/tools/testing/selftests/net/tcp_ao/setsockopt-closed.c +++ b/tools/testing/selftests/net/tcp_ao/setsockopt-closed.c @@ -21,7 +21,7 @@ static void make_listen(int sk) static void test_vefify_ao_info(int sk, struct tcp_ao_info_opt *info, const char *tst) { - struct tcp_ao_info_opt tmp; + struct tcp_ao_info_opt tmp = {}; socklen_t len = sizeof(tmp); if (getsockopt(sk, IPPROTO_TCP, TCP_AO_INFO, &tmp, &len)) -- cgit v1.2.3 From beb78cd1329d039d73487ca05633d1b92e1ab2ea Mon Sep 17 00:00:00 2001 From: Dmitry Safonov <0x7f454c46@gmail.com> Date: Sat, 13 Apr 2024 02:42:54 +0100 Subject: selftests/tcp_ao: Fix fscanf() call for format-security MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit On my new laptop with packages from nixos-unstable, gcc 12.3.0 produces: > lib/proc.c: In function ‘netstat_read_type’: > lib/proc.c:89:9: error: format not a string literal and no format arguments [-Werror=format-security] > 89 | if (fscanf(fnetstat, type->header_name) == EOF) > | ^~ > cc1: some warnings being treated as errors Here the selftests lib parses header name, while expectes non-space word ending with a column. Fixes: cfbab37b3da0 ("selftests/net: Add TCP-AO library") Signed-off-by: Dmitry Safonov <0x7f454c46@gmail.com> Reported-by: Muhammad Usama Anjum Signed-off-by: Paolo Abeni --- tools/testing/selftests/net/tcp_ao/lib/proc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/testing/selftests/net/tcp_ao/lib/proc.c b/tools/testing/selftests/net/tcp_ao/lib/proc.c index 2fb6dd8adba6..8b984fa04286 100644 --- a/tools/testing/selftests/net/tcp_ao/lib/proc.c +++ b/tools/testing/selftests/net/tcp_ao/lib/proc.c @@ -86,7 +86,7 @@ static void netstat_read_type(FILE *fnetstat, struct netstat **dest, char *line) pos = strchr(line, ' ') + 1; - if (fscanf(fnetstat, type->header_name) == EOF) + if (fscanf(fnetstat, "%[^ :]", type->header_name) == EOF) test_error("fscanf(%s)", type->header_name); if (fread(&tmp, 1, 1, fnetstat) != 1 || tmp != ':') test_error("Unexpected netstat format (%c)", tmp); -- cgit v1.2.3 From b476c93654d748c13624f7c7d0ba191c56a8092e Mon Sep 17 00:00:00 2001 From: Dmitry Safonov <0x7f454c46@gmail.com> Date: Sat, 13 Apr 2024 02:42:55 +0100 Subject: selftests/tcp_ao: Printing fixes to confirm with format-security MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit On my new laptop with packages from nixos-unstable, gcc 12.3.0 produces > lib/setup.c: In function ‘__test_msg’: > lib/setup.c:20:9: error: format not a string literal and no format arguments [-Werror=format-security] > 20 | ksft_print_msg(buf); > | ^~~~~~~~~~~~~~ > lib/setup.c: In function ‘__test_ok’: > lib/setup.c:26:9: error: format not a string literal and no format arguments [-Werror=format-security] > 26 | ksft_test_result_pass(buf); > | ^~~~~~~~~~~~~~~~~~~~~ > lib/setup.c: In function ‘__test_fail’: > lib/setup.c:32:9: error: format not a string literal and no format arguments [-Werror=format-security] > 32 | ksft_test_result_fail(buf); > | ^~~~~~~~~~~~~~~~~~~~~ > lib/setup.c: In function ‘__test_xfail’: > lib/setup.c:38:9: error: format not a string literal and no format arguments [-Werror=format-security] > 38 | ksft_test_result_xfail(buf); > | ^~~~~~~~~~~~~~~~~~~~~~ > lib/setup.c: In function ‘__test_error’: > lib/setup.c:44:9: error: format not a string literal and no format arguments [-Werror=format-security] > 44 | ksft_test_result_error(buf); > | ^~~~~~~~~~~~~~~~~~~~~~ > lib/setup.c: In function ‘__test_skip’: > lib/setup.c:50:9: error: format not a string literal and no format arguments [-Werror=format-security] > 50 | ksft_test_result_skip(buf); > | ^~~~~~~~~~~~~~~~~~~~~ > cc1: some warnings being treated as errors As the buffer was already pre-printed into, print it as a string rather than a format-string. Fixes: cfbab37b3da0 ("selftests/net: Add TCP-AO library") Signed-off-by: Dmitry Safonov <0x7f454c46@gmail.com> Reported-by: Muhammad Usama Anjum Signed-off-by: Paolo Abeni --- tools/testing/selftests/net/tcp_ao/lib/setup.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/tools/testing/selftests/net/tcp_ao/lib/setup.c b/tools/testing/selftests/net/tcp_ao/lib/setup.c index 92276f916f2f..e408b9243b2c 100644 --- a/tools/testing/selftests/net/tcp_ao/lib/setup.c +++ b/tools/testing/selftests/net/tcp_ao/lib/setup.c @@ -17,37 +17,37 @@ static pthread_mutex_t ksft_print_lock = PTHREAD_MUTEX_INITIALIZER; void __test_msg(const char *buf) { pthread_mutex_lock(&ksft_print_lock); - ksft_print_msg(buf); + ksft_print_msg("%s", buf); pthread_mutex_unlock(&ksft_print_lock); } void __test_ok(const char *buf) { pthread_mutex_lock(&ksft_print_lock); - ksft_test_result_pass(buf); + ksft_test_result_pass("%s", buf); pthread_mutex_unlock(&ksft_print_lock); } void __test_fail(const char *buf) { pthread_mutex_lock(&ksft_print_lock); - ksft_test_result_fail(buf); + ksft_test_result_fail("%s", buf); pthread_mutex_unlock(&ksft_print_lock); } void __test_xfail(const char *buf) { pthread_mutex_lock(&ksft_print_lock); - ksft_test_result_xfail(buf); + ksft_test_result_xfail("%s", buf); pthread_mutex_unlock(&ksft_print_lock); } void __test_error(const char *buf) { pthread_mutex_lock(&ksft_print_lock); - ksft_test_result_error(buf); + ksft_test_result_error("%s", buf); pthread_mutex_unlock(&ksft_print_lock); } void __test_skip(const char *buf) { pthread_mutex_lock(&ksft_print_lock); - ksft_test_result_skip(buf); + ksft_test_result_skip("%s", buf); pthread_mutex_unlock(&ksft_print_lock); } -- cgit v1.2.3 From fe90f3967bdb3e13f133e5f44025e15f943a99c5 Mon Sep 17 00:00:00 2001 From: Mathieu Desnoyers Date: Mon, 15 Apr 2024 11:21:13 -0400 Subject: sched: Add missing memory barrier in switch_mm_cid Many architectures' switch_mm() (e.g. arm64) do not have an smp_mb() which the core scheduler code has depended upon since commit: commit 223baf9d17f25 ("sched: Fix performance regression introduced by mm_cid") If switch_mm() doesn't call smp_mb(), sched_mm_cid_remote_clear() can unset the actively used cid when it fails to observe active task after it sets lazy_put. There *is* a memory barrier between storing to rq->curr and _return to userspace_ (as required by membarrier), but the rseq mm_cid has stricter requirements: the barrier needs to be issued between store to rq->curr and switch_mm_cid(), which happens earlier than: - spin_unlock(), - switch_to(). So it's fine when the architecture switch_mm() happens to have that barrier already, but less so when the architecture only provides the full barrier in switch_to() or spin_unlock(). It is a bug in the rseq switch_mm_cid() implementation. All architectures that don't have memory barriers in switch_mm(), but rather have the full barrier either in finish_lock_switch() or switch_to() have them too late for the needs of switch_mm_cid(). Introduce a new smp_mb__after_switch_mm(), defined as smp_mb() in the generic barrier.h header, and use it in switch_mm_cid() for scheduler transitions where switch_mm() is expected to provide a memory barrier. Architectures can override smp_mb__after_switch_mm() if their switch_mm() implementation provides an implicit memory barrier. Override it with a no-op on x86 which implicitly provide this memory barrier by writing to CR3. Fixes: 223baf9d17f2 ("sched: Fix performance regression introduced by mm_cid") Reported-by: levi.yun Signed-off-by: Mathieu Desnoyers Signed-off-by: Ingo Molnar Reviewed-by: Catalin Marinas # for arm64 Acked-by: Dave Hansen # for x86 Cc: # 6.4.x Cc: Linus Torvalds Link: https://lore.kernel.org/r/20240415152114.59122-2-mathieu.desnoyers@efficios.com --- arch/x86/include/asm/barrier.h | 3 +++ include/asm-generic/barrier.h | 8 ++++++++ kernel/sched/sched.h | 20 ++++++++++++++------ 3 files changed, 25 insertions(+), 6 deletions(-) diff --git a/arch/x86/include/asm/barrier.h b/arch/x86/include/asm/barrier.h index fe1e7e3cc844..63bdc6b85219 100644 --- a/arch/x86/include/asm/barrier.h +++ b/arch/x86/include/asm/barrier.h @@ -79,6 +79,9 @@ do { \ #define __smp_mb__before_atomic() do { } while (0) #define __smp_mb__after_atomic() do { } while (0) +/* Writing to CR3 provides a full memory barrier in switch_mm(). */ +#define smp_mb__after_switch_mm() do { } while (0) + #include #endif /* _ASM_X86_BARRIER_H */ diff --git a/include/asm-generic/barrier.h b/include/asm-generic/barrier.h index 0c0695763bea..d4f581c1e21d 100644 --- a/include/asm-generic/barrier.h +++ b/include/asm-generic/barrier.h @@ -294,5 +294,13 @@ do { \ #define io_stop_wc() do { } while (0) #endif +/* + * Architectures that guarantee an implicit smp_mb() in switch_mm() + * can override smp_mb__after_switch_mm. + */ +#ifndef smp_mb__after_switch_mm +# define smp_mb__after_switch_mm() smp_mb() +#endif + #endif /* !__ASSEMBLY__ */ #endif /* __ASM_GENERIC_BARRIER_H */ diff --git a/kernel/sched/sched.h b/kernel/sched/sched.h index d2242679239e..ae50f212775e 100644 --- a/kernel/sched/sched.h +++ b/kernel/sched/sched.h @@ -79,6 +79,8 @@ # include #endif +#include + #include "cpupri.h" #include "cpudeadline.h" @@ -3445,13 +3447,19 @@ static inline void switch_mm_cid(struct rq *rq, * between rq->curr store and load of {prev,next}->mm->pcpu_cid[cpu]. * Provide it here. */ - if (!prev->mm) // from kernel + if (!prev->mm) { // from kernel smp_mb(); - /* - * user -> user transition guarantees a memory barrier through - * switch_mm() when current->mm changes. If current->mm is - * unchanged, no barrier is needed. - */ + } else { // from user + /* + * user->user transition relies on an implicit + * memory barrier in switch_mm() when + * current->mm changes. If the architecture + * switch_mm() does not have an implicit memory + * barrier, it is emitted here. If current->mm + * is unchanged, no barrier is needed. + */ + smp_mb__after_switch_mm(); + } } if (prev->mm_cid_active) { mm_cid_snapshot_time(rq, prev->mm); -- cgit v1.2.3 From 03cea821b82cbf0ee4a285f9dca6cc1d660dbef3 Mon Sep 17 00:00:00 2001 From: Mario Limonciello Date: Wed, 10 Apr 2024 09:09:54 -0500 Subject: platform/x86/amd: pmf: Decrease error message to debug MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ASUS ROG Zephyrus G14 doesn't have _CRS in AMDI0102 device and so there are no resources to walk. This is expected behavior because it doesn't support Smart PC. Decrease error message to debug. Link: https://bugzilla.kernel.org/show_bug.cgi?id=218685 Signed-off-by: Mario Limonciello Reviewed-by: Hans de Goede Link: https://lore.kernel.org/r/20240410140956.385-1-mario.limonciello@amd.com Reviewed-by: Ilpo Järvinen Signed-off-by: Ilpo Järvinen --- drivers/platform/x86/amd/pmf/acpi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/platform/x86/amd/pmf/acpi.c b/drivers/platform/x86/amd/pmf/acpi.c index d0cf46e2fc8e..60fc71c9fb0f 100644 --- a/drivers/platform/x86/amd/pmf/acpi.c +++ b/drivers/platform/x86/amd/pmf/acpi.c @@ -437,7 +437,7 @@ int apmf_check_smart_pc(struct amd_pmf_dev *pmf_dev) status = acpi_walk_resources(ahandle, METHOD_NAME__CRS, apmf_walk_resources, pmf_dev); if (ACPI_FAILURE(status)) { - dev_err(pmf_dev->dev, "acpi_walk_resources failed :%d\n", status); + dev_dbg(pmf_dev->dev, "acpi_walk_resources failed :%d\n", status); return -EINVAL; } -- cgit v1.2.3 From ed13f622bcd594d6cefd6239b1722ed8b84ba98f Mon Sep 17 00:00:00 2001 From: Mario Limonciello Date: Wed, 10 Apr 2024 09:09:55 -0500 Subject: platform/x86/amd: pmf: Add infrastructure for quirking supported funcs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In the event of a BIOS bug add infrastructure that will be utilized to override the return value for supported_funcs to avoid enabling features. Signed-off-by: Mario Limonciello Link: https://lore.kernel.org/r/20240410140956.385-2-mario.limonciello@amd.com Reviewed-by: Ilpo Järvinen Signed-off-by: Ilpo Järvinen --- drivers/platform/x86/amd/pmf/Makefile | 2 +- drivers/platform/x86/amd/pmf/acpi.c | 5 +++- drivers/platform/x86/amd/pmf/core.c | 1 + drivers/platform/x86/amd/pmf/pmf-quirks.c | 43 +++++++++++++++++++++++++++++++ drivers/platform/x86/amd/pmf/pmf.h | 3 +++ 5 files changed, 52 insertions(+), 2 deletions(-) create mode 100644 drivers/platform/x86/amd/pmf/pmf-quirks.c diff --git a/drivers/platform/x86/amd/pmf/Makefile b/drivers/platform/x86/amd/pmf/Makefile index 6b26e48ce8ad..7d6079b02589 100644 --- a/drivers/platform/x86/amd/pmf/Makefile +++ b/drivers/platform/x86/amd/pmf/Makefile @@ -7,4 +7,4 @@ obj-$(CONFIG_AMD_PMF) += amd-pmf.o amd-pmf-objs := core.o acpi.o sps.o \ auto-mode.o cnqf.o \ - tee-if.o spc.o + tee-if.o spc.o pmf-quirks.o diff --git a/drivers/platform/x86/amd/pmf/acpi.c b/drivers/platform/x86/amd/pmf/acpi.c index 60fc71c9fb0f..1157ec148880 100644 --- a/drivers/platform/x86/amd/pmf/acpi.c +++ b/drivers/platform/x86/amd/pmf/acpi.c @@ -343,7 +343,10 @@ static int apmf_if_verify_interface(struct amd_pmf_dev *pdev) if (err) return err; - pdev->supported_func = output.supported_functions; + /* only set if not already set by a quirk */ + if (!pdev->supported_func) + pdev->supported_func = output.supported_functions; + dev_dbg(pdev->dev, "supported functions:0x%x notifications:0x%x version:%u\n", output.supported_functions, output.notification_mask, output.version); diff --git a/drivers/platform/x86/amd/pmf/core.c b/drivers/platform/x86/amd/pmf/core.c index 5d4f80698a8b..64e6e34a2a9a 100644 --- a/drivers/platform/x86/amd/pmf/core.c +++ b/drivers/platform/x86/amd/pmf/core.c @@ -445,6 +445,7 @@ static int amd_pmf_probe(struct platform_device *pdev) mutex_init(&dev->lock); mutex_init(&dev->update_mutex); + amd_pmf_quirks_init(dev); apmf_acpi_init(dev); platform_set_drvdata(pdev, dev); amd_pmf_dbgfs_register(dev); diff --git a/drivers/platform/x86/amd/pmf/pmf-quirks.c b/drivers/platform/x86/amd/pmf/pmf-quirks.c new file mode 100644 index 000000000000..9f3790eaaa30 --- /dev/null +++ b/drivers/platform/x86/amd/pmf/pmf-quirks.c @@ -0,0 +1,43 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * AMD Platform Management Framework Driver Quirks + * + * Copyright (c) 2024, Advanced Micro Devices, Inc. + * All Rights Reserved. + * + * Author: Mario Limonciello + */ + +#include + +#include "pmf.h" + +struct quirk_entry { + u32 supported_func; +}; + +static struct quirk_entry quirk_no_sps_bug = { + .supported_func = 0x4003, +}; + +static const struct dmi_system_id fwbug_list[] = { + {} +}; + +void amd_pmf_quirks_init(struct amd_pmf_dev *dev) +{ + const struct dmi_system_id *dmi_id; + struct quirk_entry *quirks; + + dmi_id = dmi_first_match(fwbug_list); + if (!dmi_id) + return; + + quirks = dmi_id->driver_data; + if (quirks->supported_func) { + dev->supported_func = quirks->supported_func; + pr_info("Using supported funcs quirk to avoid %s platform firmware bug\n", + dmi_id->ident); + } +} + diff --git a/drivers/platform/x86/amd/pmf/pmf.h b/drivers/platform/x86/amd/pmf/pmf.h index 8c4df5753f40..eeedd0c0395a 100644 --- a/drivers/platform/x86/amd/pmf/pmf.h +++ b/drivers/platform/x86/amd/pmf/pmf.h @@ -720,4 +720,7 @@ int apmf_check_smart_pc(struct amd_pmf_dev *pmf_dev); void amd_pmf_populate_ta_inputs(struct amd_pmf_dev *dev, struct ta_pmf_enact_table *in); void amd_pmf_dump_ta_inputs(struct amd_pmf_dev *dev, struct ta_pmf_enact_table *in); +/* Quirk infrastructure */ +void amd_pmf_quirks_init(struct amd_pmf_dev *dev); + #endif /* PMF_H */ -- cgit v1.2.3 From 9d893061ed68820de24b572d1e193b5e4737f2e0 Mon Sep 17 00:00:00 2001 From: Mario Limonciello Date: Wed, 10 Apr 2024 09:09:56 -0500 Subject: platform/x86/amd: pmf: Add quirk for ROG Zephyrus G14 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ROG Zephyrus G14 advertises support for SPS notifications to the BIOS but doesn't actually use them. Instead the asus-nb-wmi driver utilizes such events. Add a quirk to prevent the system from registering for ACPI platform profile when this system is found to avoid conflicts. Reported-by: al0uette@outlook.com Closes: https://bugzilla.kernel.org/show_bug.cgi?id=218685 Signed-off-by: Mario Limonciello Link: https://lore.kernel.org/r/20240410140956.385-3-mario.limonciello@amd.com Reviewed-by: Ilpo Järvinen Signed-off-by: Ilpo Järvinen --- drivers/platform/x86/amd/pmf/pmf-quirks.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/drivers/platform/x86/amd/pmf/pmf-quirks.c b/drivers/platform/x86/amd/pmf/pmf-quirks.c index 9f3790eaaa30..0b2eb0ae85fe 100644 --- a/drivers/platform/x86/amd/pmf/pmf-quirks.c +++ b/drivers/platform/x86/amd/pmf/pmf-quirks.c @@ -21,6 +21,14 @@ static struct quirk_entry quirk_no_sps_bug = { }; static const struct dmi_system_id fwbug_list[] = { + { + .ident = "ROG Zephyrus G14", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), + DMI_MATCH(DMI_PRODUCT_NAME, "GA403UV"), + }, + .driver_data = &quirk_no_sps_bug, + }, {} }; -- cgit v1.2.3 From d8c2d38c4d1dee8fe8e015b9ebf65bdd8e4da99b Mon Sep 17 00:00:00 2001 From: Srinivas Pandruvada Date: Mon, 15 Apr 2024 14:28:53 -0700 Subject: platform/x86: ISST: Add Granite Rapids-D to HPM CPU list MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add Granite Rapids-D to hpm_cpu_ids, so that MSR 0x54 can be used. Signed-off-by: Srinivas Pandruvada Link: https://lore.kernel.org/r/20240415212853.2820470-1-srinivas.pandruvada@linux.intel.com Reviewed-by: Ilpo Järvinen Signed-off-by: Ilpo Järvinen --- drivers/platform/x86/intel/speed_select_if/isst_if_common.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/platform/x86/intel/speed_select_if/isst_if_common.c b/drivers/platform/x86/intel/speed_select_if/isst_if_common.c index 08df9494603c..30951f7131cd 100644 --- a/drivers/platform/x86/intel/speed_select_if/isst_if_common.c +++ b/drivers/platform/x86/intel/speed_select_if/isst_if_common.c @@ -719,6 +719,7 @@ static struct miscdevice isst_if_char_driver = { }; static const struct x86_cpu_id hpm_cpu_ids[] = { + X86_MATCH_INTEL_FAM6_MODEL(GRANITERAPIDS_D, NULL), X86_MATCH_INTEL_FAM6_MODEL(GRANITERAPIDS_X, NULL), X86_MATCH_INTEL_FAM6_MODEL(ATOM_CRESTMONT_X, NULL), {} -- cgit v1.2.3 From bc774d46b41482534c7ba92f6342ca0a355c13af Mon Sep 17 00:00:00 2001 From: Srinivas Pandruvada Date: Mon, 15 Apr 2024 15:06:25 -0700 Subject: platform/x86/intel-uncore-freq: Increase minor number support MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit No new changes will be added for minor version 2. Change the minor version number to 2 and stop displaying log message for unsupported minor version 2. Signed-off-by: Srinivas Pandruvada Link: https://lore.kernel.org/r/20240415220625.2828339-1-srinivas.pandruvada@linux.intel.com Reviewed-by: Ilpo Järvinen Signed-off-by: Ilpo Järvinen --- drivers/platform/x86/intel/uncore-frequency/uncore-frequency-tpmi.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/platform/x86/intel/uncore-frequency/uncore-frequency-tpmi.c b/drivers/platform/x86/intel/uncore-frequency/uncore-frequency-tpmi.c index bd75d61ff8a6..ef730200a04b 100644 --- a/drivers/platform/x86/intel/uncore-frequency/uncore-frequency-tpmi.c +++ b/drivers/platform/x86/intel/uncore-frequency/uncore-frequency-tpmi.c @@ -29,7 +29,7 @@ #include "uncore-frequency-common.h" #define UNCORE_MAJOR_VERSION 0 -#define UNCORE_MINOR_VERSION 1 +#define UNCORE_MINOR_VERSION 2 #define UNCORE_HEADER_INDEX 0 #define UNCORE_FABRIC_CLUSTER_OFFSET 8 @@ -329,7 +329,7 @@ static int uncore_probe(struct auxiliary_device *auxdev, const struct auxiliary_ goto remove_clusters; } - if (TPMI_MINOR_VERSION(pd_info->ufs_header_ver) != UNCORE_MINOR_VERSION) + if (TPMI_MINOR_VERSION(pd_info->ufs_header_ver) > UNCORE_MINOR_VERSION) dev_info(&auxdev->dev, "Uncore: Ignore: Unsupported minor version:%lx\n", TPMI_MINOR_VERSION(pd_info->ufs_header_ver)); -- cgit v1.2.3 From 0ebd96f5da4410c0cb8fc75e44f1009530b2f90b Mon Sep 17 00:00:00 2001 From: Serge Semin Date: Fri, 12 Apr 2024 21:03:14 +0300 Subject: net: stmmac: Apply half-duplex-less constraint for DW QoS Eth only There are three DW MAC IP-cores which can have the multiple Tx/Rx queues enabled: DW GMAC v3.7+ with AV feature, DW QoS Eth v4.x/v5.x, DW XGMAC/XLGMAC Based on the respective HW databooks, only the DW QoS Eth IP-core doesn't support the half-duplex link mode in case if more than one queues enabled: "In multiple queue/channel configurations, for half-duplex operation, enable only the Q0/CH0 on Tx and Rx. For single queue/channel in full-duplex operation, any queue/channel can be enabled." The rest of the IP-cores don't have such constraint. Thus in order to have the constraint applied for the DW QoS Eth MACs only, let's move the it' implementation to the respective MAC-capabilities getter and make sure the getter is called in the queues re-init procedure. Fixes: b6cfffa7ad92 ("stmmac: fix DMA channel hang in half-duplex mode") Signed-off-by: Serge Semin Reviewed-by: Romain Gantois Signed-off-by: Paolo Abeni --- drivers/net/ethernet/stmicro/stmmac/dwmac4_core.c | 7 +++++++ drivers/net/ethernet/stmicro/stmmac/stmmac_main.c | 19 +++---------------- 2 files changed, 10 insertions(+), 16 deletions(-) diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac4_core.c b/drivers/net/ethernet/stmicro/stmmac/dwmac4_core.c index cef25efbdff9..ec6a13e644b3 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac4_core.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac4_core.c @@ -71,6 +71,13 @@ static void dwmac4_core_init(struct mac_device_info *hw, static void dwmac4_phylink_get_caps(struct stmmac_priv *priv) { priv->phylink_config.mac_capabilities |= MAC_2500FD; + + if (priv->plat->tx_queues_to_use > 1) + priv->phylink_config.mac_capabilities &= + ~(MAC_10HD | MAC_100HD | MAC_1000HD); + else + priv->phylink_config.mac_capabilities |= + (MAC_10HD | MAC_100HD | MAC_1000HD); } static void dwmac4_rx_queue_enable(struct mac_device_info *hw, diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c index 24cd80490d19..dd58c21b53ee 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c @@ -1198,17 +1198,6 @@ static int stmmac_init_phy(struct net_device *dev) return ret; } -static void stmmac_set_half_duplex(struct stmmac_priv *priv) -{ - /* Half-Duplex can only work with single tx queue */ - if (priv->plat->tx_queues_to_use > 1) - priv->phylink_config.mac_capabilities &= - ~(MAC_10HD | MAC_100HD | MAC_1000HD); - else - priv->phylink_config.mac_capabilities |= - (MAC_10HD | MAC_100HD | MAC_1000HD); -} - static int stmmac_phy_setup(struct stmmac_priv *priv) { struct stmmac_mdio_bus_data *mdio_bus_data; @@ -1237,10 +1226,7 @@ static int stmmac_phy_setup(struct stmmac_priv *priv) priv->phylink_config.supported_interfaces); priv->phylink_config.mac_capabilities = MAC_ASYM_PAUSE | MAC_SYM_PAUSE | - MAC_10FD | MAC_100FD | - MAC_1000FD; - - stmmac_set_half_duplex(priv); + MAC_10 | MAC_100 | MAC_1000; /* Get the MAC specific capabilities */ stmmac_mac_phylink_get_caps(priv); @@ -7355,7 +7341,8 @@ int stmmac_reinit_queues(struct net_device *dev, u32 rx_cnt, u32 tx_cnt) priv->rss.table[i] = ethtool_rxfh_indir_default(i, rx_cnt); - stmmac_set_half_duplex(priv); + stmmac_mac_phylink_get_caps(priv); + stmmac_napi_add(dev); if (netif_running(dev)) -- cgit v1.2.3 From 59c3d6ca6cbded6c6599e975b42a9d6a27fcbaf2 Mon Sep 17 00:00:00 2001 From: Serge Semin Date: Fri, 12 Apr 2024 21:03:15 +0300 Subject: net: stmmac: Fix max-speed being ignored on queue re-init It's possible to have the maximum link speed being artificially limited on the platform-specific basis. It's done either by setting up the plat_stmmacenet_data::max_speed field or by specifying the "max-speed" DT-property. In such cases it's required that any specific MAC-capabilities re-initializations would take the limit into account. In particular the link speed capabilities may change during the number of active Tx/Rx queues re-initialization. But the currently implemented procedure doesn't take the speed limit into account. Fix that by calling phylink_limit_mac_speed() in the stmmac_reinit_queues() method if the speed limitation was required in the same way as it's done in the stmmac_phy_setup() function. Fixes: 95201f36f395 ("net: stmmac: update MAC capabilities when tx queues are updated") Signed-off-by: Serge Semin Reviewed-by: Romain Gantois Signed-off-by: Paolo Abeni --- drivers/net/ethernet/stmicro/stmmac/stmmac_main.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c index dd58c21b53ee..b8a1f02398ee 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c @@ -7328,6 +7328,7 @@ int stmmac_reinit_queues(struct net_device *dev, u32 rx_cnt, u32 tx_cnt) { struct stmmac_priv *priv = netdev_priv(dev); int ret = 0, i; + int max_speed; if (netif_running(dev)) stmmac_release(dev); @@ -7343,6 +7344,10 @@ int stmmac_reinit_queues(struct net_device *dev, u32 rx_cnt, u32 tx_cnt) stmmac_mac_phylink_get_caps(priv); + max_speed = priv->plat->max_speed; + if (max_speed) + phylink_limit_mac_speed(&priv->phylink_config, max_speed); + stmmac_napi_add(dev); if (netif_running(dev)) -- cgit v1.2.3 From 9cb54af214a7cdc91577ec083e5569f2ce2c86d8 Mon Sep 17 00:00:00 2001 From: Serge Semin Date: Fri, 12 Apr 2024 21:03:16 +0300 Subject: net: stmmac: Fix IP-cores specific MAC capabilities Here is the list of the MAC capabilities specific to the particular DW MAC IP-cores currently supported by the driver: DW MAC100: MAC_ASYM_PAUSE | MAC_SYM_PAUSE | MAC_10 | MAC_100 DW GMAC: MAC_ASYM_PAUSE | MAC_SYM_PAUSE | MAC_10 | MAC_100 | MAC_1000 Allwinner sun8i MAC: MAC_ASYM_PAUSE | MAC_SYM_PAUSE | MAC_10 | MAC_100 | MAC_1000 DW QoS Eth: MAC_ASYM_PAUSE | MAC_SYM_PAUSE | MAC_10 | MAC_100 | MAC_1000 | MAC_2500FD if there is more than 1 active Tx/Rx queues: MAC_ASYM_PAUSE | MAC_SYM_PAUSE | MAC_10FD | MAC_100FD | MAC_1000FD | MAC_2500FD DW XGMAC: MAC_ASYM_PAUSE | MAC_SYM_PAUSE | MAC_1000FD | MAC_2500FD | MAC_5000FD | MAC_10000FD DW XLGMAC: MAC_ASYM_PAUSE | MAC_SYM_PAUSE | MAC_1000FD | MAC_2500FD | MAC_5000FD | MAC_10000FD | MAC_25000FD | MAC_40000FD | MAC_50000FD | MAC_100000FD As you can see there are only two common capabilities: MAC_ASYM_PAUSE | MAC_SYM_PAUSE. Meanwhile what is currently implemented defines 10/100/1000 link speeds for all IP-cores, which is definitely incorrect for DW MAC100, DW XGMAC and DW XLGMAC devices. Seeing the flow-control is implemented as a callback for each MAC IP-core (see dwmac100_flow_ctrl(), dwmac1000_flow_ctrl(), sun8i_dwmac_flow_ctrl(), etc) and since the MAC-specific setup() method is supposed to be called for each available DW MAC-based device, the capabilities initialization can be freely moved to these setup() functions, thus correctly setting up the MAC-capabilities for each IP-core (including the Allwinner Sun8i). A new stmmac_link::caps field was specifically introduced for that so to have all link-specific info preserved in a single structure. Note the suggested change fixes three earlier commits at a time. The commit 5b0d7d7da64b ("net: stmmac: Add the missing speeds that XGMAC supports") permitted the 10-100 link speeds and 1G half-duplex mode for DW XGMAC IP-core even though it doesn't support them. The commit df7699c70c1b ("net: stmmac: Do not cut down 1G modes") incorrectly added the MAC1000 capability to the DW MAC100 IP-core. Similarly to the DW XGMAC the commit 8a880936e902 ("net: stmmac: Add XLGMII support") incorrectly permitted the 10-100 link speeds and 1G half-duplex mode for DW XLGMAC IP-core. Fixes: 5b0d7d7da64b ("net: stmmac: Add the missing speeds that XGMAC supports") Fixes: df7699c70c1b ("net: stmmac: Do not cut down 1G modes") Fixes: 8a880936e902 ("net: stmmac: Add XLGMII support") Suggested-by: Russell King (Oracle) Signed-off-by: Serge Semin Reviewed-by: Romain Gantois Signed-off-by: Paolo Abeni --- drivers/net/ethernet/stmicro/stmmac/common.h | 1 + drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c | 2 ++ drivers/net/ethernet/stmicro/stmmac/dwmac1000_core.c | 2 ++ drivers/net/ethernet/stmicro/stmmac/dwmac100_core.c | 2 ++ drivers/net/ethernet/stmicro/stmmac/dwmac4_core.c | 10 ++++------ drivers/net/ethernet/stmicro/stmmac/dwxgmac2_core.c | 18 ++++++++---------- drivers/net/ethernet/stmicro/stmmac/stmmac_main.c | 7 ++++--- 7 files changed, 23 insertions(+), 19 deletions(-) diff --git a/drivers/net/ethernet/stmicro/stmmac/common.h b/drivers/net/ethernet/stmicro/stmmac/common.h index a6fefe675ef1..3b7d4ac1e7be 100644 --- a/drivers/net/ethernet/stmicro/stmmac/common.h +++ b/drivers/net/ethernet/stmicro/stmmac/common.h @@ -553,6 +553,7 @@ extern const struct stmmac_hwtimestamp stmmac_ptp; extern const struct stmmac_mode_ops dwmac4_ring_mode_ops; struct mac_link { + u32 caps; u32 speed_mask; u32 speed10; u32 speed100; diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c index b21d99faa2d0..e1b761dcfa1d 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c @@ -1096,6 +1096,8 @@ static struct mac_device_info *sun8i_dwmac_setup(void *ppriv) priv->dev->priv_flags |= IFF_UNICAST_FLT; + mac->link.caps = MAC_ASYM_PAUSE | MAC_SYM_PAUSE | + MAC_10 | MAC_100 | MAC_1000; /* The loopback bit seems to be re-set when link change * Simply mask it each time * Speed 10/100/1000 are set in BIT(2)/BIT(3) diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac1000_core.c b/drivers/net/ethernet/stmicro/stmmac/dwmac1000_core.c index 3927609abc44..8555299443f4 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac1000_core.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac1000_core.c @@ -539,6 +539,8 @@ int dwmac1000_setup(struct stmmac_priv *priv) if (mac->multicast_filter_bins) mac->mcast_bits_log2 = ilog2(mac->multicast_filter_bins); + mac->link.caps = MAC_ASYM_PAUSE | MAC_SYM_PAUSE | + MAC_10 | MAC_100 | MAC_1000; mac->link.duplex = GMAC_CONTROL_DM; mac->link.speed10 = GMAC_CONTROL_PS; mac->link.speed100 = GMAC_CONTROL_PS | GMAC_CONTROL_FES; diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac100_core.c b/drivers/net/ethernet/stmicro/stmmac/dwmac100_core.c index a6e8d7bd9588..7667d103cd0e 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac100_core.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac100_core.c @@ -175,6 +175,8 @@ int dwmac100_setup(struct stmmac_priv *priv) dev_info(priv->device, "\tDWMAC100\n"); mac->pcsr = priv->ioaddr; + mac->link.caps = MAC_ASYM_PAUSE | MAC_SYM_PAUSE | + MAC_10 | MAC_100; mac->link.duplex = MAC_CONTROL_F; mac->link.speed10 = 0; mac->link.speed100 = 0; diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac4_core.c b/drivers/net/ethernet/stmicro/stmmac/dwmac4_core.c index ec6a13e644b3..a38226d7cc6a 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac4_core.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac4_core.c @@ -70,14 +70,10 @@ static void dwmac4_core_init(struct mac_device_info *hw, static void dwmac4_phylink_get_caps(struct stmmac_priv *priv) { - priv->phylink_config.mac_capabilities |= MAC_2500FD; - if (priv->plat->tx_queues_to_use > 1) - priv->phylink_config.mac_capabilities &= - ~(MAC_10HD | MAC_100HD | MAC_1000HD); + priv->hw->link.caps &= ~(MAC_10HD | MAC_100HD | MAC_1000HD); else - priv->phylink_config.mac_capabilities |= - (MAC_10HD | MAC_100HD | MAC_1000HD); + priv->hw->link.caps |= (MAC_10HD | MAC_100HD | MAC_1000HD); } static void dwmac4_rx_queue_enable(struct mac_device_info *hw, @@ -1385,6 +1381,8 @@ int dwmac4_setup(struct stmmac_priv *priv) if (mac->multicast_filter_bins) mac->mcast_bits_log2 = ilog2(mac->multicast_filter_bins); + mac->link.caps = MAC_ASYM_PAUSE | MAC_SYM_PAUSE | + MAC_10 | MAC_100 | MAC_1000 | MAC_2500FD; mac->link.duplex = GMAC_CONFIG_DM; mac->link.speed10 = GMAC_CONFIG_PS; mac->link.speed100 = GMAC_CONFIG_FES | GMAC_CONFIG_PS; diff --git a/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_core.c b/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_core.c index e841e312077e..f8e7775bb633 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_core.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_core.c @@ -47,14 +47,6 @@ static void dwxgmac2_core_init(struct mac_device_info *hw, writel(XGMAC_INT_DEFAULT_EN, ioaddr + XGMAC_INT_EN); } -static void xgmac_phylink_get_caps(struct stmmac_priv *priv) -{ - priv->phylink_config.mac_capabilities |= MAC_2500FD | MAC_5000FD | - MAC_10000FD | MAC_25000FD | - MAC_40000FD | MAC_50000FD | - MAC_100000FD; -} - static void dwxgmac2_set_mac(void __iomem *ioaddr, bool enable) { u32 tx = readl(ioaddr + XGMAC_TX_CONFIG); @@ -1540,7 +1532,6 @@ static void dwxgmac3_fpe_configure(void __iomem *ioaddr, struct stmmac_fpe_cfg * const struct stmmac_ops dwxgmac210_ops = { .core_init = dwxgmac2_core_init, - .phylink_get_caps = xgmac_phylink_get_caps, .set_mac = dwxgmac2_set_mac, .rx_ipc = dwxgmac2_rx_ipc, .rx_queue_enable = dwxgmac2_rx_queue_enable, @@ -1601,7 +1592,6 @@ static void dwxlgmac2_rx_queue_enable(struct mac_device_info *hw, u8 mode, const struct stmmac_ops dwxlgmac2_ops = { .core_init = dwxgmac2_core_init, - .phylink_get_caps = xgmac_phylink_get_caps, .set_mac = dwxgmac2_set_mac, .rx_ipc = dwxgmac2_rx_ipc, .rx_queue_enable = dwxlgmac2_rx_queue_enable, @@ -1661,6 +1651,9 @@ int dwxgmac2_setup(struct stmmac_priv *priv) if (mac->multicast_filter_bins) mac->mcast_bits_log2 = ilog2(mac->multicast_filter_bins); + mac->link.caps = MAC_ASYM_PAUSE | MAC_SYM_PAUSE | + MAC_1000FD | MAC_2500FD | MAC_5000FD | + MAC_10000FD; mac->link.duplex = 0; mac->link.speed10 = XGMAC_CONFIG_SS_10_MII; mac->link.speed100 = XGMAC_CONFIG_SS_100_MII; @@ -1698,6 +1691,11 @@ int dwxlgmac2_setup(struct stmmac_priv *priv) if (mac->multicast_filter_bins) mac->mcast_bits_log2 = ilog2(mac->multicast_filter_bins); + mac->link.caps = MAC_ASYM_PAUSE | MAC_SYM_PAUSE | + MAC_1000FD | MAC_2500FD | MAC_5000FD | + MAC_10000FD | MAC_25000FD | + MAC_40000FD | MAC_50000FD | + MAC_100000FD; mac->link.duplex = 0; mac->link.speed1000 = XLGMAC_CONFIG_SS_1000; mac->link.speed2500 = XLGMAC_CONFIG_SS_2500; diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c index b8a1f02398ee..7c6fb14b5555 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c @@ -1225,12 +1225,11 @@ static int stmmac_phy_setup(struct stmmac_priv *priv) xpcs_get_interfaces(priv->hw->xpcs, priv->phylink_config.supported_interfaces); - priv->phylink_config.mac_capabilities = MAC_ASYM_PAUSE | MAC_SYM_PAUSE | - MAC_10 | MAC_100 | MAC_1000; - /* Get the MAC specific capabilities */ stmmac_mac_phylink_get_caps(priv); + priv->phylink_config.mac_capabilities = priv->hw->link.caps; + max_speed = priv->plat->max_speed; if (max_speed) phylink_limit_mac_speed(&priv->phylink_config, max_speed); @@ -7344,6 +7343,8 @@ int stmmac_reinit_queues(struct net_device *dev, u32 rx_cnt, u32 tx_cnt) stmmac_mac_phylink_get_caps(priv); + priv->phylink_config.mac_capabilities = priv->hw->link.caps; + max_speed = priv->plat->max_speed; if (max_speed) phylink_limit_mac_speed(&priv->phylink_config, max_speed); -- cgit v1.2.3 From feafe59c897500e11becd238a30be1c33eb188a2 Mon Sep 17 00:00:00 2001 From: Kalle Valo Date: Thu, 11 Apr 2024 19:55:15 +0300 Subject: wifi: ath11k: use RCU when accessing struct inet6_dev::ac_list Commit c3718936ec47 ("ipv6: anycast: complete RCU handling of struct ifacaddr6") converted struct inet6_dev::ac_list to use RCU but missed that ath11k also accesses this list. Now sparse warns: drivers/net/wireless/ath/ath11k/mac.c:9145:21: warning: incorrect type in assignment (different address spaces) drivers/net/wireless/ath/ath11k/mac.c:9145:21: expected struct ifacaddr6 *ifaca6 drivers/net/wireless/ath/ath11k/mac.c:9145:21: got struct ifacaddr6 [noderef] __rcu *ac_list drivers/net/wireless/ath/ath11k/mac.c:9145:53: warning: incorrect type in assignment (different address spaces) drivers/net/wireless/ath/ath11k/mac.c:9145:53: expected struct ifacaddr6 *ifaca6 drivers/net/wireless/ath/ath11k/mac.c:9145:53: got struct ifacaddr6 [noderef] __rcu *aca_next Fix it by using rtnl_dereference(). Also add a note that read_lock_bh() calls rcu_read_lock() which I was not aware of. Tested-on: WCN6855 hw2.0 PCI WLAN.HSP.1.1-03125-QCAHSPSWPL_V1_V2_SILICONZ_LITE-3.6510.37 Fixes: c3718936ec47 ("ipv6: anycast: complete RCU handling of struct ifacaddr6") Signed-off-by: Kalle Valo Acked-by: Jeff Johnson Signed-off-by: Kalle Valo Link: https://msgid.link/20240411165516.4070649-2-kvalo@kernel.org --- drivers/net/wireless/ath/ath11k/mac.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/ath/ath11k/mac.c b/drivers/net/wireless/ath/ath11k/mac.c index a6a37d67a50a..9f4bf41a3d41 100644 --- a/drivers/net/wireless/ath/ath11k/mac.c +++ b/drivers/net/wireless/ath/ath11k/mac.c @@ -9020,6 +9020,7 @@ static void ath11k_mac_op_ipv6_changed(struct ieee80211_hw *hw, offload = &arvif->arp_ns_offload; count = 0; + /* Note: read_lock_bh() calls rcu_read_lock() */ read_lock_bh(&idev->lock); memset(offload->ipv6_addr, 0, sizeof(offload->ipv6_addr)); @@ -9050,7 +9051,8 @@ static void ath11k_mac_op_ipv6_changed(struct ieee80211_hw *hw, } /* get anycast address */ - for (ifaca6 = idev->ac_list; ifaca6; ifaca6 = ifaca6->aca_next) { + for (ifaca6 = rcu_dereference(idev->ac_list); ifaca6; + ifaca6 = rcu_dereference(ifaca6->aca_next)) { if (count >= ATH11K_IPV6_MAX_COUNT) goto generate; -- cgit v1.2.3 From 428051600cb4e5a61d81aba3f8009b6c4f5e7582 Mon Sep 17 00:00:00 2001 From: Michal Swiatkowski Date: Fri, 15 Mar 2024 12:08:20 +0100 Subject: ice: tc: check src_vsi in case of traffic from VF In case of traffic going from the VF (so ingress for port representor) source VSI should be consider during packet classification. It is needed for hardware to not match packets from different ports with filters added on other port. It is only for "from VF" traffic, because other traffic direction doesn't have source VSI. Set correct ::src_vsi in rule_info to pass it to the hardware filter. For example this rule should drop only ipv4 packets from eth10, not from the others VF PRs. It is needed to check source VSI in this case. $tc filter add dev eth10 ingress protocol ip flower skip_sw action drop Fixes: 0d08a441fb1a ("ice: ndo_setup_tc implementation for PF") Reviewed-by: Jedrzej Jagielski Reviewed-by: Sridhar Samudrala Signed-off-by: Michal Swiatkowski Reviewed-by: Simon Horman Tested-by: Sujai Buvaneswaran Signed-off-by: Tony Nguyen --- drivers/net/ethernet/intel/ice/ice_tc_lib.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/drivers/net/ethernet/intel/ice/ice_tc_lib.c b/drivers/net/ethernet/intel/ice/ice_tc_lib.c index b890410a2bc0..49ed5fd7db10 100644 --- a/drivers/net/ethernet/intel/ice/ice_tc_lib.c +++ b/drivers/net/ethernet/intel/ice/ice_tc_lib.c @@ -28,6 +28,8 @@ ice_tc_count_lkups(u32 flags, struct ice_tc_flower_lyr_2_4_hdrs *headers, * - ICE_TC_FLWR_FIELD_VLAN_TPID (present if specified) * - Tunnel flag (present if tunnel) */ + if (fltr->direction == ICE_ESWITCH_FLTR_EGRESS) + lkups_cnt++; if (flags & ICE_TC_FLWR_FIELD_TENANT_ID) lkups_cnt++; @@ -363,6 +365,11 @@ ice_tc_fill_rules(struct ice_hw *hw, u32 flags, /* Always add direction metadata */ ice_rule_add_direction_metadata(&list[ICE_TC_METADATA_LKUP_IDX]); + if (tc_fltr->direction == ICE_ESWITCH_FLTR_EGRESS) { + ice_rule_add_src_vsi_metadata(&list[i]); + i++; + } + rule_info->tun_type = ice_sw_type_from_tunnel(tc_fltr->tunnel_type); if (tc_fltr->tunnel_type != TNL_LAST) { i = ice_tc_fill_tunnel_outer(flags, tc_fltr, list, i); @@ -820,6 +827,7 @@ ice_eswitch_add_tc_fltr(struct ice_vsi *vsi, struct ice_tc_flower_fltr *fltr) /* specify the cookie as filter_rule_id */ rule_info.fltr_rule_id = fltr->cookie; + rule_info.src_vsi = vsi->idx; ret = ice_add_adv_rule(hw, list, lkups_cnt, &rule_info, &rule_added); if (ret == -EEXIST) { -- cgit v1.2.3 From 73278715725a8347032acf233082ca4eb31e6a56 Mon Sep 17 00:00:00 2001 From: Michal Swiatkowski Date: Fri, 15 Mar 2024 12:08:21 +0100 Subject: ice: tc: allow zero flags in parsing tc flower The check for flags is done to not pass empty lookups to adding switch rule functions. Since metadata is always added to lookups there is no need to check against the flag. It is also fixing the problem with such rule: $ tc filter add dev gtp_dev ingress protocol ip prio 0 flower \ enc_dst_port 2123 action drop Switch block in case of GTP can't parse the destination port, because it should always be set to GTP specific value. The same with ethertype. The result is that there is no other matching criteria than GTP tunnel. In this case flags is 0, rule can't be added only because of defensive check against flags. Fixes: 9a225f81f540 ("ice: Support GTP-U and GTP-C offload in switchdev") Reviewed-by: Wojciech Drewek Signed-off-by: Michal Swiatkowski Reviewed-by: Simon Horman Tested-by: Sujai Buvaneswaran Signed-off-by: Tony Nguyen --- drivers/net/ethernet/intel/ice/ice_tc_lib.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/ethernet/intel/ice/ice_tc_lib.c b/drivers/net/ethernet/intel/ice/ice_tc_lib.c index 49ed5fd7db10..bcbcfc67e560 100644 --- a/drivers/net/ethernet/intel/ice/ice_tc_lib.c +++ b/drivers/net/ethernet/intel/ice/ice_tc_lib.c @@ -779,7 +779,7 @@ ice_eswitch_add_tc_fltr(struct ice_vsi *vsi, struct ice_tc_flower_fltr *fltr) int ret; int i; - if (!flags || (flags & ICE_TC_FLWR_FIELD_ENC_SRC_L4_PORT)) { + if (flags & ICE_TC_FLWR_FIELD_ENC_SRC_L4_PORT) { NL_SET_ERR_MSG_MOD(fltr->extack, "Unsupported encap field(s)"); return -EOPNOTSUPP; } -- cgit v1.2.3 From 2cca35f5dd78b9f8297c879c5db5ab137c5d86c3 Mon Sep 17 00:00:00 2001 From: Marcin Szycik Date: Tue, 9 Apr 2024 17:45:44 +0200 Subject: ice: Fix checking for unsupported keys on non-tunnel device Add missing FLOW_DISSECTOR_KEY_ENC_* checks to TC flower filter parsing. Without these checks, it would be possible to add filters with tunnel options on non-tunnel devices. enc_* options are only valid for tunnel devices. Example: devlink dev eswitch set $PF1_PCI mode switchdev echo 1 > /sys/class/net/$PF1/device/sriov_numvfs tc qdisc add dev $VF1_PR ingress ethtool -K $PF1 hw-tc-offload on tc filter add dev $VF1_PR ingress flower enc_ttl 12 skip_sw action drop Fixes: 9e300987d4a8 ("ice: VXLAN and Geneve TC support") Reviewed-by: Michal Swiatkowski Signed-off-by: Marcin Szycik Reviewed-by: Jacob Keller Tested-by: Sujai Buvaneswaran Signed-off-by: Tony Nguyen --- drivers/net/ethernet/intel/ice/ice_tc_lib.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/net/ethernet/intel/ice/ice_tc_lib.c b/drivers/net/ethernet/intel/ice/ice_tc_lib.c index bcbcfc67e560..688ccb0615ab 100644 --- a/drivers/net/ethernet/intel/ice/ice_tc_lib.c +++ b/drivers/net/ethernet/intel/ice/ice_tc_lib.c @@ -1489,7 +1489,10 @@ ice_parse_cls_flower(struct net_device *filter_dev, struct ice_vsi *vsi, (BIT_ULL(FLOW_DISSECTOR_KEY_ENC_IPV4_ADDRS) | BIT_ULL(FLOW_DISSECTOR_KEY_ENC_IPV6_ADDRS) | BIT_ULL(FLOW_DISSECTOR_KEY_ENC_KEYID) | - BIT_ULL(FLOW_DISSECTOR_KEY_ENC_PORTS))) { + BIT_ULL(FLOW_DISSECTOR_KEY_ENC_PORTS) | + BIT_ULL(FLOW_DISSECTOR_KEY_ENC_IP) | + BIT_ULL(FLOW_DISSECTOR_KEY_ENC_OPTS) | + BIT_ULL(FLOW_DISSECTOR_KEY_ENC_CONTROL))) { NL_SET_ERR_MSG_MOD(fltr->extack, "Tunnel key used, but device isn't a tunnel"); return -EOPNOTSUPP; } else { -- cgit v1.2.3 From 9e4d3f4f34455abbaa9930bf6b7575a5cd081496 Mon Sep 17 00:00:00 2001 From: Dmitry Baryshkov Date: Thu, 4 Apr 2024 13:07:59 +0300 Subject: drm/panel: visionox-rm69299: don't unregister DSI device The DSI device for the panel was registered by the DSI host, so it is an error to unregister it from the panel driver. Drop the call to mipi_dsi_device_unregister(). Fixes: c7f66d32dd43 ("drm/panel: add support for rm69299 visionox panel") Reviewed-by: Jessica Zhang Signed-off-by: Dmitry Baryshkov Link: https://patchwork.freedesktop.org/patch/msgid/20240404-drop-panel-unregister-v1-1-9f56953c5fb9@linaro.org --- drivers/gpu/drm/panel/panel-visionox-rm69299.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/gpu/drm/panel/panel-visionox-rm69299.c b/drivers/gpu/drm/panel/panel-visionox-rm69299.c index 775144695283..b15ca56a09a7 100644 --- a/drivers/gpu/drm/panel/panel-visionox-rm69299.c +++ b/drivers/gpu/drm/panel/panel-visionox-rm69299.c @@ -253,8 +253,6 @@ static void visionox_rm69299_remove(struct mipi_dsi_device *dsi) struct visionox_rm69299 *ctx = mipi_dsi_get_drvdata(dsi); mipi_dsi_detach(ctx->dsi); - mipi_dsi_device_unregister(ctx->dsi); - drm_panel_remove(&ctx->panel); } -- cgit v1.2.3 From 941c0bdbc176df825adf77052263b2d63db6fef7 Mon Sep 17 00:00:00 2001 From: Dmitry Baryshkov Date: Thu, 4 Apr 2024 13:08:00 +0300 Subject: drm/panel: novatek-nt36682e: don't unregister DSI device The DSI device for the panel was registered by the DSI host, so it is an error to unregister it from the panel driver. Drop the call to mipi_dsi_device_unregister(). Fixes: ea4f9975625a ("drm/panel: Add support for Novatek NT36672E panel driver") Reviewed-by: Jessica Zhang Signed-off-by: Dmitry Baryshkov Link: https://patchwork.freedesktop.org/patch/msgid/20240404-drop-panel-unregister-v1-2-9f56953c5fb9@linaro.org --- drivers/gpu/drm/panel/panel-novatek-nt36672e.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/gpu/drm/panel/panel-novatek-nt36672e.c b/drivers/gpu/drm/panel/panel-novatek-nt36672e.c index cb7406d74466..c39fe0fc5d69 100644 --- a/drivers/gpu/drm/panel/panel-novatek-nt36672e.c +++ b/drivers/gpu/drm/panel/panel-novatek-nt36672e.c @@ -614,8 +614,6 @@ static void nt36672e_panel_remove(struct mipi_dsi_device *dsi) struct nt36672e_panel *ctx = mipi_dsi_get_drvdata(dsi); mipi_dsi_detach(ctx->dsi); - mipi_dsi_device_unregister(ctx->dsi); - drm_panel_remove(&ctx->panel); } -- cgit v1.2.3 From 631426ba1d45a8672b177ee85ad4cabe760dd131 Mon Sep 17 00:00:00 2001 From: David Hildenbrand Date: Thu, 14 Mar 2024 17:12:59 +0100 Subject: mm/madvise: make MADV_POPULATE_(READ|WRITE) handle VM_FAULT_RETRY properly Darrick reports that in some cases where pread() would fail with -EIO and mmap()+access would generate a SIGBUS signal, MADV_POPULATE_READ / MADV_POPULATE_WRITE will keep retrying forever and not fail with -EFAULT. While the madvise() call can be interrupted by a signal, this is not the desired behavior. MADV_POPULATE_READ / MADV_POPULATE_WRITE should behave like page faults in that case: fail and not retry forever. A reproducer can be found at [1]. The reason is that __get_user_pages(), as called by faultin_vma_page_range(), will not handle VM_FAULT_RETRY in a proper way: it will simply return 0 when VM_FAULT_RETRY happened, making madvise_populate()->faultin_vma_page_range() retry again and again, never setting FOLL_TRIED->FAULT_FLAG_TRIED for __get_user_pages(). __get_user_pages_locked() does what we want, but duplicating that logic in faultin_vma_page_range() feels wrong. So let's use __get_user_pages_locked() instead, that will detect VM_FAULT_RETRY and set FOLL_TRIED when retrying, making the fault handler return VM_FAULT_SIGBUS (VM_FAULT_ERROR) at some point, propagating -EFAULT from faultin_page() to __get_user_pages(), all the way to madvise_populate(). But, there is an issue: __get_user_pages_locked() will end up re-taking the MM lock and then __get_user_pages() will do another VMA lookup. In the meantime, the VMA layout could have changed and we'd fail with different error codes than we'd want to. As __get_user_pages() will currently do a new VMA lookup either way, let it do the VMA handling in a different way, controlled by a new FOLL_MADV_POPULATE flag, effectively moving these checks from madvise_populate() + faultin_page_range() in there. With this change, Darricks reproducer properly fails with -EFAULT, as documented for MADV_POPULATE_READ / MADV_POPULATE_WRITE. [1] https://lore.kernel.org/all/20240313171936.GN1927156@frogsfrogsfrogs/ Link: https://lkml.kernel.org/r/20240314161300.382526-1-david@redhat.com Link: https://lkml.kernel.org/r/20240314161300.382526-2-david@redhat.com Fixes: 4ca9b3859dac ("mm/madvise: introduce MADV_POPULATE_(READ|WRITE) to prefault page tables") Signed-off-by: David Hildenbrand Reported-by: Darrick J. Wong Closes: https://lore.kernel.org/all/20240311223815.GW1927156@frogsfrogsfrogs/ Cc: Darrick J. Wong Cc: Hugh Dickins Cc: Jason Gunthorpe Cc: John Hubbard Cc: Signed-off-by: Andrew Morton --- mm/gup.c | 54 ++++++++++++++++++++++++++++++++---------------------- mm/internal.h | 10 ++++++---- mm/madvise.c | 17 ++--------------- 3 files changed, 40 insertions(+), 41 deletions(-) diff --git a/mm/gup.c b/mm/gup.c index af8edadc05d1..1611e73b1121 100644 --- a/mm/gup.c +++ b/mm/gup.c @@ -1206,6 +1206,22 @@ static long __get_user_pages(struct mm_struct *mm, /* first iteration or cross vma bound */ if (!vma || start >= vma->vm_end) { + /* + * MADV_POPULATE_(READ|WRITE) wants to handle VMA + * lookups+error reporting differently. + */ + if (gup_flags & FOLL_MADV_POPULATE) { + vma = vma_lookup(mm, start); + if (!vma) { + ret = -ENOMEM; + goto out; + } + if (check_vma_flags(vma, gup_flags)) { + ret = -EINVAL; + goto out; + } + goto retry; + } vma = gup_vma_lookup(mm, start); if (!vma && in_gate_area(mm, start)) { ret = get_gate_page(mm, start & PAGE_MASK, @@ -1685,35 +1701,35 @@ long populate_vma_page_range(struct vm_area_struct *vma, } /* - * faultin_vma_page_range() - populate (prefault) page tables inside the - * given VMA range readable/writable + * faultin_page_range() - populate (prefault) page tables inside the + * given range readable/writable * * This takes care of mlocking the pages, too, if VM_LOCKED is set. * - * @vma: target vma + * @mm: the mm to populate page tables in * @start: start address * @end: end address * @write: whether to prefault readable or writable * @locked: whether the mmap_lock is still held * - * Returns either number of processed pages in the vma, or a negative error - * code on error (see __get_user_pages()). + * Returns either number of processed pages in the MM, or a negative error + * code on error (see __get_user_pages()). Note that this function reports + * errors related to VMAs, such as incompatible mappings, as expected by + * MADV_POPULATE_(READ|WRITE). * - * vma->vm_mm->mmap_lock must be held. The range must be page-aligned and - * covered by the VMA. If it's released, *@locked will be set to 0. + * The range must be page-aligned. + * + * mm->mmap_lock must be held. If it's released, *@locked will be set to 0. */ -long faultin_vma_page_range(struct vm_area_struct *vma, unsigned long start, - unsigned long end, bool write, int *locked) +long faultin_page_range(struct mm_struct *mm, unsigned long start, + unsigned long end, bool write, int *locked) { - struct mm_struct *mm = vma->vm_mm; unsigned long nr_pages = (end - start) / PAGE_SIZE; int gup_flags; long ret; VM_BUG_ON(!PAGE_ALIGNED(start)); VM_BUG_ON(!PAGE_ALIGNED(end)); - VM_BUG_ON_VMA(start < vma->vm_start, vma); - VM_BUG_ON_VMA(end > vma->vm_end, vma); mmap_assert_locked(mm); /* @@ -1725,19 +1741,13 @@ long faultin_vma_page_range(struct vm_area_struct *vma, unsigned long start, * a poisoned page. * !FOLL_FORCE: Require proper access permissions. */ - gup_flags = FOLL_TOUCH | FOLL_HWPOISON | FOLL_UNLOCKABLE; + gup_flags = FOLL_TOUCH | FOLL_HWPOISON | FOLL_UNLOCKABLE | + FOLL_MADV_POPULATE; if (write) gup_flags |= FOLL_WRITE; - /* - * We want to report -EINVAL instead of -EFAULT for any permission - * problems or incompatible mappings. - */ - if (check_vma_flags(vma, gup_flags)) - return -EINVAL; - - ret = __get_user_pages(mm, start, nr_pages, gup_flags, - NULL, locked); + ret = __get_user_pages_locked(mm, start, nr_pages, NULL, locked, + gup_flags); lru_add_drain(); return ret; } diff --git a/mm/internal.h b/mm/internal.h index 7e486f2c502c..07ad2675a88b 100644 --- a/mm/internal.h +++ b/mm/internal.h @@ -686,9 +686,8 @@ struct anon_vma *folio_anon_vma(struct folio *folio); void unmap_mapping_folio(struct folio *folio); extern long populate_vma_page_range(struct vm_area_struct *vma, unsigned long start, unsigned long end, int *locked); -extern long faultin_vma_page_range(struct vm_area_struct *vma, - unsigned long start, unsigned long end, - bool write, int *locked); +extern long faultin_page_range(struct mm_struct *mm, unsigned long start, + unsigned long end, bool write, int *locked); extern bool mlock_future_ok(struct mm_struct *mm, unsigned long flags, unsigned long bytes); @@ -1127,10 +1126,13 @@ enum { FOLL_FAST_ONLY = 1 << 20, /* allow unlocking the mmap lock */ FOLL_UNLOCKABLE = 1 << 21, + /* VMA lookup+checks compatible with MADV_POPULATE_(READ|WRITE) */ + FOLL_MADV_POPULATE = 1 << 22, }; #define INTERNAL_GUP_FLAGS (FOLL_TOUCH | FOLL_TRIED | FOLL_REMOTE | FOLL_PIN | \ - FOLL_FAST_ONLY | FOLL_UNLOCKABLE) + FOLL_FAST_ONLY | FOLL_UNLOCKABLE | \ + FOLL_MADV_POPULATE) /* * Indicates for which pages that are write-protected in the page table, diff --git a/mm/madvise.c b/mm/madvise.c index 44a498c94158..1a073fcc4c0c 100644 --- a/mm/madvise.c +++ b/mm/madvise.c @@ -908,27 +908,14 @@ static long madvise_populate(struct vm_area_struct *vma, { const bool write = behavior == MADV_POPULATE_WRITE; struct mm_struct *mm = vma->vm_mm; - unsigned long tmp_end; int locked = 1; long pages; *prev = vma; while (start < end) { - /* - * We might have temporarily dropped the lock. For example, - * our VMA might have been split. - */ - if (!vma || start >= vma->vm_end) { - vma = vma_lookup(mm, start); - if (!vma) - return -ENOMEM; - } - - tmp_end = min_t(unsigned long, end, vma->vm_end); /* Populate (prefault) page tables readable/writable. */ - pages = faultin_vma_page_range(vma, start, tmp_end, write, - &locked); + pages = faultin_page_range(mm, start, end, write, &locked); if (!locked) { mmap_read_lock(mm); locked = 1; @@ -949,7 +936,7 @@ static long madvise_populate(struct vm_area_struct *vma, pr_warn_once("%s: unhandled return value: %ld\n", __func__, pages); fallthrough; - case -ENOMEM: + case -ENOMEM: /* No VMA or out of memory. */ return -ENOMEM; } } -- cgit v1.2.3 From c0205eaf3af9f5db14d4b5ee4abacf4a583c3c50 Mon Sep 17 00:00:00 2001 From: Lokesh Gidra Date: Thu, 4 Apr 2024 10:17:26 -0700 Subject: userfaultfd: change src_folio after ensuring it's unpinned in UFFDIO_MOVE Commit d7a08838ab74 ("mm: userfaultfd: fix unexpected change to src_folio when UFFDIO_MOVE fails") moved the src_folio->{mapping, index} changing to after clearing the page-table and ensuring that it's not pinned. This avoids failure of swapout+migration and possibly memory corruption. However, the commit missed fixing it in the huge-page case. Link: https://lkml.kernel.org/r/20240404171726.2302435-1-lokeshgidra@google.com Fixes: adef440691ba ("userfaultfd: UFFDIO_MOVE uABI") Signed-off-by: Lokesh Gidra Acked-by: David Hildenbrand Cc: Andrea Arcangeli Cc: Kalesh Singh Cc: Lokesh Gidra Cc: Nicolas Geoffray Cc: Peter Xu Cc: Qi Zheng Cc: Matthew Wilcox Cc: Signed-off-by: Andrew Morton --- mm/huge_memory.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/mm/huge_memory.c b/mm/huge_memory.c index 9859aa4f7553..89f58c7603b2 100644 --- a/mm/huge_memory.c +++ b/mm/huge_memory.c @@ -2259,9 +2259,6 @@ int move_pages_huge_pmd(struct mm_struct *mm, pmd_t *dst_pmd, pmd_t *src_pmd, pm goto unlock_ptls; } - folio_move_anon_rmap(src_folio, dst_vma); - WRITE_ONCE(src_folio->index, linear_page_index(dst_vma, dst_addr)); - src_pmdval = pmdp_huge_clear_flush(src_vma, src_addr, src_pmd); /* Folio got pinned from under us. Put it back and fail the move. */ if (folio_maybe_dma_pinned(src_folio)) { @@ -2270,6 +2267,9 @@ int move_pages_huge_pmd(struct mm_struct *mm, pmd_t *dst_pmd, pmd_t *src_pmd, pm goto unlock_ptls; } + folio_move_anon_rmap(src_folio, dst_vma); + WRITE_ONCE(src_folio->index, linear_page_index(dst_vma, dst_addr)); + _dst_pmd = mk_huge_pmd(&src_folio->page, dst_vma->vm_page_prot); /* Follow mremap() behavior and treat the entry dirty after the move */ _dst_pmd = pmd_mkwrite(pmd_mkdirty(_dst_pmd), dst_vma); -- cgit v1.2.3 From ea4b5b33bf8a4936cfb07759d926db697c43fb1e Mon Sep 17 00:00:00 2001 From: Oscar Salvador Date: Thu, 4 Apr 2024 09:06:59 +0200 Subject: mm,page_owner: update metadata for tail pages Patch series "page_owner: Fix refcount imbalance and print fixup", v4. This series consists of a refactoring/correctness of updating the metadata of tail pages, a couple of fixups for the refcounting part and a fixup for the stack_start() function. From this series on, instead of counting the stacks, we count the outstanding nr_base_pages each stack has, which gives us a much better memory overview. The other fixup is for the migration part. A more detailed explanation can be found in the changelog of the respective patches. This patch (of 4): __set_page_owner_handle() and __reset_page_owner() update the metadata of all pages when the page is of a higher-order, but we miss to do the same when the pages are migrated. __folio_copy_owner() only updates the metadata of the head page, meaning that the information stored in the first page and the tail pages will not match. Strictly speaking that is not a big problem because 1) we do not print tail pages and 2) upon splitting all tail pages will inherit the metadata of the head page, but it is better to have all metadata in check should there be any problem, so it can ease debugging. For that purpose, a couple of helpers are created __update_page_owner_handle() which updates the metadata on allocation, and __update_page_owner_free_handle() which does the same when the page is freed. __folio_copy_owner() will make use of both as it needs to entirely replace the page_owner metadata for the new page. Link: https://lkml.kernel.org/r/20240404070702.2744-1-osalvador@suse.de Link: https://lkml.kernel.org/r/20240404070702.2744-2-osalvador@suse.de Signed-off-by: Oscar Salvador Reviewed-by: Vlastimil Babka Tested-by: Kefeng Wang Cc: Alexander Potapenko Cc: Alexandre Ghiti Cc: Andrey Konovalov Cc: Marco Elver Cc: Michal Hocko Cc: Oscar Salvador Cc: Palmer Dabbelt Cc: Alexandre Ghiti Signed-off-by: Andrew Morton --- mm/page_owner.c | 137 ++++++++++++++++++++++++++++++-------------------------- 1 file changed, 74 insertions(+), 63 deletions(-) diff --git a/mm/page_owner.c b/mm/page_owner.c index d17d1351ec84..52d1ced0b57f 100644 --- a/mm/page_owner.c +++ b/mm/page_owner.c @@ -228,9 +228,58 @@ static void dec_stack_record_count(depot_stack_handle_t handle) refcount_dec(&stack_record->count); } -void __reset_page_owner(struct page *page, unsigned short order) +static inline void __update_page_owner_handle(struct page_ext *page_ext, + depot_stack_handle_t handle, + unsigned short order, + gfp_t gfp_mask, + short last_migrate_reason, u64 ts_nsec, + pid_t pid, pid_t tgid, char *comm) { int i; + struct page_owner *page_owner; + + for (i = 0; i < (1 << order); i++) { + page_owner = get_page_owner(page_ext); + page_owner->handle = handle; + page_owner->order = order; + page_owner->gfp_mask = gfp_mask; + page_owner->last_migrate_reason = last_migrate_reason; + page_owner->pid = pid; + page_owner->tgid = tgid; + page_owner->ts_nsec = ts_nsec; + strscpy(page_owner->comm, comm, + sizeof(page_owner->comm)); + __set_bit(PAGE_EXT_OWNER, &page_ext->flags); + __set_bit(PAGE_EXT_OWNER_ALLOCATED, &page_ext->flags); + page_ext = page_ext_next(page_ext); + } +} + +static inline void __update_page_owner_free_handle(struct page_ext *page_ext, + depot_stack_handle_t handle, + unsigned short order, + pid_t pid, pid_t tgid, + u64 free_ts_nsec) +{ + int i; + struct page_owner *page_owner; + + for (i = 0; i < (1 << order); i++) { + page_owner = get_page_owner(page_ext); + /* Only __reset_page_owner() wants to clear the bit */ + if (handle) { + __clear_bit(PAGE_EXT_OWNER_ALLOCATED, &page_ext->flags); + page_owner->free_handle = handle; + } + page_owner->free_ts_nsec = free_ts_nsec; + page_owner->free_pid = current->pid; + page_owner->free_tgid = current->tgid; + page_ext = page_ext_next(page_ext); + } +} + +void __reset_page_owner(struct page *page, unsigned short order) +{ struct page_ext *page_ext; depot_stack_handle_t handle; depot_stack_handle_t alloc_handle; @@ -245,16 +294,10 @@ void __reset_page_owner(struct page *page, unsigned short order) alloc_handle = page_owner->handle; handle = save_stack(GFP_NOWAIT | __GFP_NOWARN); - for (i = 0; i < (1 << order); i++) { - __clear_bit(PAGE_EXT_OWNER_ALLOCATED, &page_ext->flags); - page_owner->free_handle = handle; - page_owner->free_ts_nsec = free_ts_nsec; - page_owner->free_pid = current->pid; - page_owner->free_tgid = current->tgid; - page_ext = page_ext_next(page_ext); - page_owner = get_page_owner(page_ext); - } + __update_page_owner_free_handle(page_ext, handle, order, current->pid, + current->tgid, free_ts_nsec); page_ext_put(page_ext); + if (alloc_handle != early_handle) /* * early_handle is being set as a handle for all those @@ -266,36 +309,11 @@ void __reset_page_owner(struct page *page, unsigned short order) dec_stack_record_count(alloc_handle); } -static inline void __set_page_owner_handle(struct page_ext *page_ext, - depot_stack_handle_t handle, - unsigned short order, gfp_t gfp_mask) -{ - struct page_owner *page_owner; - int i; - u64 ts_nsec = local_clock(); - - for (i = 0; i < (1 << order); i++) { - page_owner = get_page_owner(page_ext); - page_owner->handle = handle; - page_owner->order = order; - page_owner->gfp_mask = gfp_mask; - page_owner->last_migrate_reason = -1; - page_owner->pid = current->pid; - page_owner->tgid = current->tgid; - page_owner->ts_nsec = ts_nsec; - strscpy(page_owner->comm, current->comm, - sizeof(page_owner->comm)); - __set_bit(PAGE_EXT_OWNER, &page_ext->flags); - __set_bit(PAGE_EXT_OWNER_ALLOCATED, &page_ext->flags); - - page_ext = page_ext_next(page_ext); - } -} - noinline void __set_page_owner(struct page *page, unsigned short order, gfp_t gfp_mask) { struct page_ext *page_ext; + u64 ts_nsec = local_clock(); depot_stack_handle_t handle; handle = save_stack(gfp_mask); @@ -303,7 +321,9 @@ noinline void __set_page_owner(struct page *page, unsigned short order, page_ext = page_ext_get(page); if (unlikely(!page_ext)) return; - __set_page_owner_handle(page_ext, handle, order, gfp_mask); + __update_page_owner_handle(page_ext, handle, order, gfp_mask, -1, + current->pid, current->tgid, ts_nsec, + current->comm); page_ext_put(page_ext); inc_stack_record_count(handle, gfp_mask); } @@ -342,7 +362,7 @@ void __folio_copy_owner(struct folio *newfolio, struct folio *old) { struct page_ext *old_ext; struct page_ext *new_ext; - struct page_owner *old_page_owner, *new_page_owner; + struct page_owner *old_page_owner; old_ext = page_ext_get(&old->page); if (unlikely(!old_ext)) @@ -355,31 +375,21 @@ void __folio_copy_owner(struct folio *newfolio, struct folio *old) } old_page_owner = get_page_owner(old_ext); - new_page_owner = get_page_owner(new_ext); - new_page_owner->order = old_page_owner->order; - new_page_owner->gfp_mask = old_page_owner->gfp_mask; - new_page_owner->last_migrate_reason = - old_page_owner->last_migrate_reason; - new_page_owner->handle = old_page_owner->handle; - new_page_owner->pid = old_page_owner->pid; - new_page_owner->tgid = old_page_owner->tgid; - new_page_owner->free_pid = old_page_owner->free_pid; - new_page_owner->free_tgid = old_page_owner->free_tgid; - new_page_owner->ts_nsec = old_page_owner->ts_nsec; - new_page_owner->free_ts_nsec = old_page_owner->ts_nsec; - strcpy(new_page_owner->comm, old_page_owner->comm); - + __update_page_owner_handle(new_ext, old_page_owner->handle, + old_page_owner->order, old_page_owner->gfp_mask, + old_page_owner->last_migrate_reason, + old_page_owner->ts_nsec, old_page_owner->pid, + old_page_owner->tgid, old_page_owner->comm); /* - * We don't clear the bit on the old folio as it's going to be freed - * after migration. Until then, the info can be useful in case of - * a bug, and the overall stats will be off a bit only temporarily. - * Also, migrate_misplaced_transhuge_page() can still fail the - * migration and then we want the old folio to retain the info. But - * in that case we also don't need to explicitly clear the info from - * the new page, which will be freed. + * Do not proactively clear PAGE_EXT_OWNER{_ALLOCATED} bits as the folio + * will be freed after migration. Keep them until then as they may be + * useful. */ - __set_bit(PAGE_EXT_OWNER, &new_ext->flags); - __set_bit(PAGE_EXT_OWNER_ALLOCATED, &new_ext->flags); + __update_page_owner_free_handle(new_ext, 0, old_page_owner->order, + old_page_owner->free_pid, + old_page_owner->free_tgid, + old_page_owner->free_ts_nsec); + page_ext_put(new_ext); page_ext_put(old_ext); } @@ -787,8 +797,9 @@ static void init_pages_in_zone(pg_data_t *pgdat, struct zone *zone) goto ext_put_continue; /* Found early allocated page */ - __set_page_owner_handle(page_ext, early_handle, - 0, 0); + __update_page_owner_handle(page_ext, early_handle, 0, 0, + -1, local_clock(), current->pid, + current->tgid, current->comm); count++; ext_put_continue: page_ext_put(page_ext); -- cgit v1.2.3 From f5c12105c15f0ddf0ff37646290568dd986fa2f3 Mon Sep 17 00:00:00 2001 From: Oscar Salvador Date: Thu, 4 Apr 2024 09:07:00 +0200 Subject: mm,page_owner: fix refcount imbalance Current code does not contemplate scenarios were an allocation and free operation on the same pages do not handle it in the same amount at once. To give an example, page_alloc_exact(), where we will allocate a page of enough order to stafisfy the size request, but we will free the remainings right away. In the above example, we will increment the stack_record refcount only once, but we will decrease it the same number of times as number of unused pages we have to free. This will lead to a warning because of refcount imbalance. Fix this by recording the number of base pages in the refcount field. Link: https://lkml.kernel.org/r/20240404070702.2744-3-osalvador@suse.de Reported-by: syzbot+41bbfdb8d41003d12c0f@syzkaller.appspotmail.com Closes: https://lore.kernel.org/linux-mm/00000000000090e8ff0613eda0e5@google.com Fixes: 217b2119b9e2 ("mm,page_owner: implement the tracking of the stacks count") Signed-off-by: Oscar Salvador Reviewed-by: Vlastimil Babka Tested-by: Alexandre Ghiti Cc: Alexander Potapenko Cc: Andrey Konovalov Cc: Marco Elver Cc: Michal Hocko Cc: Palmer Dabbelt Signed-off-by: Andrew Morton --- Documentation/mm/page_owner.rst | 73 +++++++++++++++++++++-------------------- mm/page_owner.c | 34 +++++++++++-------- 2 files changed, 58 insertions(+), 49 deletions(-) diff --git a/Documentation/mm/page_owner.rst b/Documentation/mm/page_owner.rst index 0d0334cd5179..3a45a20fc05a 100644 --- a/Documentation/mm/page_owner.rst +++ b/Documentation/mm/page_owner.rst @@ -24,10 +24,10 @@ fragmentation statistics can be obtained through gfp flag information of each page. It is already implemented and activated if page owner is enabled. Other usages are more than welcome. -It can also be used to show all the stacks and their outstanding -allocations, which gives us a quick overview of where the memory is going -without the need to screen through all the pages and match the allocation -and free operation. +It can also be used to show all the stacks and their current number of +allocated base pages, which gives us a quick overview of where the memory +is going without the need to screen through all the pages and match the +allocation and free operation. page owner is disabled by default. So, if you'd like to use it, you need to add "page_owner=on" to your boot cmdline. If the kernel is built @@ -75,42 +75,45 @@ Usage cat /sys/kernel/debug/page_owner_stacks/show_stacks > stacks.txt cat stacks.txt - prep_new_page+0xa9/0x120 - get_page_from_freelist+0x7e6/0x2140 - __alloc_pages+0x18a/0x370 - new_slab+0xc8/0x580 - ___slab_alloc+0x1f2/0xaf0 - __slab_alloc.isra.86+0x22/0x40 - kmem_cache_alloc+0x31b/0x350 - __khugepaged_enter+0x39/0x100 - dup_mmap+0x1c7/0x5ce - copy_process+0x1afe/0x1c90 - kernel_clone+0x9a/0x3c0 - __do_sys_clone+0x66/0x90 - do_syscall_64+0x7f/0x160 - entry_SYSCALL_64_after_hwframe+0x6c/0x74 - stack_count: 234 + post_alloc_hook+0x177/0x1a0 + get_page_from_freelist+0xd01/0xd80 + __alloc_pages+0x39e/0x7e0 + allocate_slab+0xbc/0x3f0 + ___slab_alloc+0x528/0x8a0 + kmem_cache_alloc+0x224/0x3b0 + sk_prot_alloc+0x58/0x1a0 + sk_alloc+0x32/0x4f0 + inet_create+0x427/0xb50 + __sock_create+0x2e4/0x650 + inet_ctl_sock_create+0x30/0x180 + igmp_net_init+0xc1/0x130 + ops_init+0x167/0x410 + setup_net+0x304/0xa60 + copy_net_ns+0x29b/0x4a0 + create_new_namespaces+0x4a1/0x820 + nr_base_pages: 16 ... ... echo 7000 > /sys/kernel/debug/page_owner_stacks/count_threshold cat /sys/kernel/debug/page_owner_stacks/show_stacks> stacks_7000.txt cat stacks_7000.txt - prep_new_page+0xa9/0x120 - get_page_from_freelist+0x7e6/0x2140 - __alloc_pages+0x18a/0x370 - alloc_pages_mpol+0xdf/0x1e0 - folio_alloc+0x14/0x50 - filemap_alloc_folio+0xb0/0x100 - page_cache_ra_unbounded+0x97/0x180 - filemap_fault+0x4b4/0x1200 - __do_fault+0x2d/0x110 - do_pte_missing+0x4b0/0xa30 - __handle_mm_fault+0x7fa/0xb70 - handle_mm_fault+0x125/0x300 - do_user_addr_fault+0x3c9/0x840 - exc_page_fault+0x68/0x150 - asm_exc_page_fault+0x22/0x30 - stack_count: 8248 + post_alloc_hook+0x177/0x1a0 + get_page_from_freelist+0xd01/0xd80 + __alloc_pages+0x39e/0x7e0 + alloc_pages_mpol+0x22e/0x490 + folio_alloc+0xd5/0x110 + filemap_alloc_folio+0x78/0x230 + page_cache_ra_order+0x287/0x6f0 + filemap_get_pages+0x517/0x1160 + filemap_read+0x304/0x9f0 + xfs_file_buffered_read+0xe6/0x1d0 [xfs] + xfs_file_read_iter+0x1f0/0x380 [xfs] + __kernel_read+0x3b9/0x730 + kernel_read_file+0x309/0x4d0 + __do_sys_finit_module+0x381/0x730 + do_syscall_64+0x8d/0x150 + entry_SYSCALL_64_after_hwframe+0x62/0x6a + nr_base_pages: 20824 ... cat /sys/kernel/debug/page_owner > page_owner_full.txt diff --git a/mm/page_owner.c b/mm/page_owner.c index 52d1ced0b57f..5df0d6892bdc 100644 --- a/mm/page_owner.c +++ b/mm/page_owner.c @@ -196,7 +196,8 @@ static void add_stack_record_to_list(struct stack_record *stack_record, spin_unlock_irqrestore(&stack_list_lock, flags); } -static void inc_stack_record_count(depot_stack_handle_t handle, gfp_t gfp_mask) +static void inc_stack_record_count(depot_stack_handle_t handle, gfp_t gfp_mask, + int nr_base_pages) { struct stack_record *stack_record = __stack_depot_get_stack_record(handle); @@ -217,15 +218,20 @@ static void inc_stack_record_count(depot_stack_handle_t handle, gfp_t gfp_mask) /* Add the new stack_record to our list */ add_stack_record_to_list(stack_record, gfp_mask); } - refcount_inc(&stack_record->count); + refcount_add(nr_base_pages, &stack_record->count); } -static void dec_stack_record_count(depot_stack_handle_t handle) +static void dec_stack_record_count(depot_stack_handle_t handle, + int nr_base_pages) { struct stack_record *stack_record = __stack_depot_get_stack_record(handle); - if (stack_record) - refcount_dec(&stack_record->count); + if (!stack_record) + return; + + if (refcount_sub_and_test(nr_base_pages, &stack_record->count)) + pr_warn("%s: refcount went to 0 for %u handle\n", __func__, + handle); } static inline void __update_page_owner_handle(struct page_ext *page_ext, @@ -306,7 +312,7 @@ void __reset_page_owner(struct page *page, unsigned short order) * the machinery is not ready yet, we cannot decrement * their refcount either. */ - dec_stack_record_count(alloc_handle); + dec_stack_record_count(alloc_handle, 1 << order); } noinline void __set_page_owner(struct page *page, unsigned short order, @@ -325,7 +331,7 @@ noinline void __set_page_owner(struct page *page, unsigned short order, current->pid, current->tgid, ts_nsec, current->comm); page_ext_put(page_ext); - inc_stack_record_count(handle, gfp_mask); + inc_stack_record_count(handle, gfp_mask, 1 << order); } void __set_page_owner_migrate_reason(struct page *page, int reason) @@ -872,11 +878,11 @@ static void *stack_next(struct seq_file *m, void *v, loff_t *ppos) return stack; } -static unsigned long page_owner_stack_threshold; +static unsigned long page_owner_pages_threshold; static int stack_print(struct seq_file *m, void *v) { - int i, stack_count; + int i, nr_base_pages; struct stack *stack = v; unsigned long *entries; unsigned long nr_entries; @@ -887,14 +893,14 @@ static int stack_print(struct seq_file *m, void *v) nr_entries = stack_record->size; entries = stack_record->entries; - stack_count = refcount_read(&stack_record->count) - 1; + nr_base_pages = refcount_read(&stack_record->count) - 1; - if (stack_count < 1 || stack_count < page_owner_stack_threshold) + if (nr_base_pages < 1 || nr_base_pages < page_owner_pages_threshold) return 0; for (i = 0; i < nr_entries; i++) seq_printf(m, " %pS\n", (void *)entries[i]); - seq_printf(m, "stack_count: %d\n\n", stack_count); + seq_printf(m, "nr_base_pages: %d\n\n", nr_base_pages); return 0; } @@ -924,13 +930,13 @@ static const struct file_operations page_owner_stack_operations = { static int page_owner_threshold_get(void *data, u64 *val) { - *val = READ_ONCE(page_owner_stack_threshold); + *val = READ_ONCE(page_owner_pages_threshold); return 0; } static int page_owner_threshold_set(void *data, u64 val) { - WRITE_ONCE(page_owner_stack_threshold, val); + WRITE_ONCE(page_owner_pages_threshold, val); return 0; } -- cgit v1.2.3 From 718b1f3373a7999f77e617c17abdcb98a3c001ea Mon Sep 17 00:00:00 2001 From: Oscar Salvador Date: Thu, 4 Apr 2024 09:07:01 +0200 Subject: mm,page_owner: fix accounting of pages when migrating Upon migration, new allocated pages are being given the handle of the old pages. This is problematic because it means that for the stack which allocated the old page, we will be substracting the old page + the new one when that page is freed, creating an accounting imbalance. There is an interest in keeping it that way, as otherwise the output will biased towards migration stacks should those operations occur often, but that is not really helpful. The link from the new page to the old stack is being performed by calling __update_page_owner_handle() in __folio_copy_owner(). The only thing that is left is to link the migrate stack to the old page, so the old page will be subtracted from the migrate stack, avoiding by doing so any possible imbalance. Link: https://lkml.kernel.org/r/20240404070702.2744-4-osalvador@suse.de Fixes: 217b2119b9e2 ("mm,page_owner: implement the tracking of the stacks count") Signed-off-by: Oscar Salvador Reviewed-by: Vlastimil Babka Cc: Alexander Potapenko Cc: Alexandre Ghiti Cc: Andrey Konovalov Cc: Marco Elver Cc: Michal Hocko Cc: Palmer Dabbelt Signed-off-by: Andrew Morton --- mm/page_owner.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/mm/page_owner.c b/mm/page_owner.c index 5df0d6892bdc..b4476f45b376 100644 --- a/mm/page_owner.c +++ b/mm/page_owner.c @@ -366,9 +366,12 @@ void __split_page_owner(struct page *page, int old_order, int new_order) void __folio_copy_owner(struct folio *newfolio, struct folio *old) { + int i; struct page_ext *old_ext; struct page_ext *new_ext; struct page_owner *old_page_owner; + struct page_owner *new_page_owner; + depot_stack_handle_t migrate_handle; old_ext = page_ext_get(&old->page); if (unlikely(!old_ext)) @@ -381,6 +384,8 @@ void __folio_copy_owner(struct folio *newfolio, struct folio *old) } old_page_owner = get_page_owner(old_ext); + new_page_owner = get_page_owner(new_ext); + migrate_handle = new_page_owner->handle; __update_page_owner_handle(new_ext, old_page_owner->handle, old_page_owner->order, old_page_owner->gfp_mask, old_page_owner->last_migrate_reason, @@ -395,6 +400,16 @@ void __folio_copy_owner(struct folio *newfolio, struct folio *old) old_page_owner->free_pid, old_page_owner->free_tgid, old_page_owner->free_ts_nsec); + /* + * We linked the original stack to the new folio, we need to do the same + * for the new one and the old folio otherwise there will be an imbalance + * when subtracting those pages from the stack. + */ + for (i = 0; i < (1 << new_page_owner->order); i++) { + old_page_owner->handle = migrate_handle; + old_ext = page_ext_next(old_ext); + old_page_owner = get_page_owner(old_ext); + } page_ext_put(new_ext); page_ext_put(old_ext); -- cgit v1.2.3 From 74017458017127ca6bf14b1f9fda69e03f43389b Mon Sep 17 00:00:00 2001 From: Oscar Salvador Date: Thu, 4 Apr 2024 09:07:02 +0200 Subject: mm,page_owner: fix printing of stack records When seq_* code sees that its buffer overflowed, it re-allocates a bigger onecand calls seq_operations->start() callback again. stack_start() naively though that if it got called again, it meant that the old record got already printed so it returned the next object, but that is not true. The consequence of that is that every time stack_stop() -> stack_start() get called because we needed a bigger buffer, stack_start() will skip entries, and those will not be printed. Fix it by not advancing to the next object in stack_start(). Link: https://lkml.kernel.org/r/20240404070702.2744-5-osalvador@suse.de Fixes: 765973a09803 ("mm,page_owner: display all stacks and their count") Signed-off-by: Oscar Salvador Reviewed-by: Vlastimil Babka Cc: Alexander Potapenko Cc: Alexandre Ghiti Cc: Andrey Konovalov Cc: Marco Elver Cc: Michal Hocko Cc: Palmer Dabbelt Signed-off-by: Andrew Morton --- mm/page_owner.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/mm/page_owner.c b/mm/page_owner.c index b4476f45b376..9bef0b442863 100644 --- a/mm/page_owner.c +++ b/mm/page_owner.c @@ -872,13 +872,11 @@ static void *stack_start(struct seq_file *m, loff_t *ppos) * value of stack_list. */ stack = smp_load_acquire(&stack_list); + m->private = stack; } else { stack = m->private; - stack = stack->next; } - m->private = stack; - return stack; } -- cgit v1.2.3 From c5977c95dff182d6ee06f4d6f60bcb0284912969 Mon Sep 17 00:00:00 2001 From: Peter Xu Date: Fri, 5 Apr 2024 19:19:20 -0400 Subject: mm/userfaultfd: allow hugetlb change protection upon poison entry After UFFDIO_POISON, there can be two kinds of hugetlb pte markers, either the POISON one or UFFD_WP one. Allow change protection to run on a poisoned marker just like !hugetlb cases, ignoring the marker irrelevant of the permission. Here the two bits are mutual exclusive. For example, when install a poisoned entry it must not be UFFD_WP already (by checking pte_none() before such install). And it also means if UFFD_WP is set there must have no POISON bit set. It makes sense because UFFD_WP is a bit to reflect permission, and permissions do not apply if the pte is poisoned and destined to sigbus. So here we simply check uffd_wp bit set first, do nothing otherwise. Attach the Fixes to UFFDIO_POISON work, as before that it should not be possible to have poison entry for hugetlb (e.g., hugetlb doesn't do swap, so no chance of swapin errors). Link: https://lkml.kernel.org/r/20240405231920.1772199-1-peterx@redhat.com Link: https://lore.kernel.org/r/000000000000920d5e0615602dd1@google.com Fixes: fc71884a5f59 ("mm: userfaultfd: add new UFFDIO_POISON ioctl") Signed-off-by: Peter Xu Reported-by: syzbot+b07c8ac8eee3d4d8440f@syzkaller.appspotmail.com Reviewed-by: David Hildenbrand Reviewed-by: Axel Rasmussen Cc: [6.6+] Signed-off-by: Andrew Morton --- mm/hugetlb.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/mm/hugetlb.c b/mm/hugetlb.c index 23ef240ba48a..31d00eee028f 100644 --- a/mm/hugetlb.c +++ b/mm/hugetlb.c @@ -7044,9 +7044,13 @@ long hugetlb_change_protection(struct vm_area_struct *vma, if (!pte_same(pte, newpte)) set_huge_pte_at(mm, address, ptep, newpte, psize); } else if (unlikely(is_pte_marker(pte))) { - /* No other markers apply for now. */ - WARN_ON_ONCE(!pte_marker_uffd_wp(pte)); - if (uffd_wp_resolve) + /* + * Do nothing on a poison marker; page is + * corrupted, permissons do not apply. Here + * pte_marker_uffd_wp()==true implies !poison + * because they're mutual exclusive. + */ + if (pte_marker_uffd_wp(pte) && uffd_wp_resolve) /* Safe to modify directly (non-present->none). */ huge_pte_clear(mm, address, ptep, psize); } else if (!huge_pte_none(pte)) { -- cgit v1.2.3 From 1983184c22dd84a4d95a71e5c6775c2638557dc7 Mon Sep 17 00:00:00 2001 From: Miaohe Lin Date: Sun, 7 Apr 2024 16:54:56 +0800 Subject: mm/memory-failure: fix deadlock when hugetlb_optimize_vmemmap is enabled When I did hard offline test with hugetlb pages, below deadlock occurs: ====================================================== WARNING: possible circular locking dependency detected 6.8.0-11409-gf6cef5f8c37f #1 Not tainted ------------------------------------------------------ bash/46904 is trying to acquire lock: ffffffffabe68910 (cpu_hotplug_lock){++++}-{0:0}, at: static_key_slow_dec+0x16/0x60 but task is already holding lock: ffffffffabf92ea8 (pcp_batch_high_lock){+.+.}-{3:3}, at: zone_pcp_disable+0x16/0x40 which lock already depends on the new lock. the existing dependency chain (in reverse order) is: -> #1 (pcp_batch_high_lock){+.+.}-{3:3}: __mutex_lock+0x6c/0x770 page_alloc_cpu_online+0x3c/0x70 cpuhp_invoke_callback+0x397/0x5f0 __cpuhp_invoke_callback_range+0x71/0xe0 _cpu_up+0xeb/0x210 cpu_up+0x91/0xe0 cpuhp_bringup_mask+0x49/0xb0 bringup_nonboot_cpus+0xb7/0xe0 smp_init+0x25/0xa0 kernel_init_freeable+0x15f/0x3e0 kernel_init+0x15/0x1b0 ret_from_fork+0x2f/0x50 ret_from_fork_asm+0x1a/0x30 -> #0 (cpu_hotplug_lock){++++}-{0:0}: __lock_acquire+0x1298/0x1cd0 lock_acquire+0xc0/0x2b0 cpus_read_lock+0x2a/0xc0 static_key_slow_dec+0x16/0x60 __hugetlb_vmemmap_restore_folio+0x1b9/0x200 dissolve_free_huge_page+0x211/0x260 __page_handle_poison+0x45/0xc0 memory_failure+0x65e/0xc70 hard_offline_page_store+0x55/0xa0 kernfs_fop_write_iter+0x12c/0x1d0 vfs_write+0x387/0x550 ksys_write+0x64/0xe0 do_syscall_64+0xca/0x1e0 entry_SYSCALL_64_after_hwframe+0x6d/0x75 other info that might help us debug this: Possible unsafe locking scenario: CPU0 CPU1 ---- ---- lock(pcp_batch_high_lock); lock(cpu_hotplug_lock); lock(pcp_batch_high_lock); rlock(cpu_hotplug_lock); *** DEADLOCK *** 5 locks held by bash/46904: #0: ffff98f6c3bb23f0 (sb_writers#5){.+.+}-{0:0}, at: ksys_write+0x64/0xe0 #1: ffff98f6c328e488 (&of->mutex){+.+.}-{3:3}, at: kernfs_fop_write_iter+0xf8/0x1d0 #2: ffff98ef83b31890 (kn->active#113){.+.+}-{0:0}, at: kernfs_fop_write_iter+0x100/0x1d0 #3: ffffffffabf9db48 (mf_mutex){+.+.}-{3:3}, at: memory_failure+0x44/0xc70 #4: ffffffffabf92ea8 (pcp_batch_high_lock){+.+.}-{3:3}, at: zone_pcp_disable+0x16/0x40 stack backtrace: CPU: 10 PID: 46904 Comm: bash Kdump: loaded Not tainted 6.8.0-11409-gf6cef5f8c37f #1 Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS rel-1.14.0-0-g155821a1990b-prebuilt.qemu.org 04/01/2014 Call Trace: dump_stack_lvl+0x68/0xa0 check_noncircular+0x129/0x140 __lock_acquire+0x1298/0x1cd0 lock_acquire+0xc0/0x2b0 cpus_read_lock+0x2a/0xc0 static_key_slow_dec+0x16/0x60 __hugetlb_vmemmap_restore_folio+0x1b9/0x200 dissolve_free_huge_page+0x211/0x260 __page_handle_poison+0x45/0xc0 memory_failure+0x65e/0xc70 hard_offline_page_store+0x55/0xa0 kernfs_fop_write_iter+0x12c/0x1d0 vfs_write+0x387/0x550 ksys_write+0x64/0xe0 do_syscall_64+0xca/0x1e0 entry_SYSCALL_64_after_hwframe+0x6d/0x75 RIP: 0033:0x7fc862314887 Code: 10 00 f7 d8 64 89 02 48 c7 c0 ff ff ff ff eb b7 0f 1f 00 f3 0f 1e fa 64 8b 04 25 18 00 00 00 85 c0 75 10 b8 01 00 00 00 0f 05 <48> 3d 00 f0 ff ff 77 51 c3 48 83 ec 28 48 89 54 24 18 48 89 74 24 RSP: 002b:00007fff19311268 EFLAGS: 00000246 ORIG_RAX: 0000000000000001 RAX: ffffffffffffffda RBX: 000000000000000c RCX: 00007fc862314887 RDX: 000000000000000c RSI: 000056405645fe10 RDI: 0000000000000001 RBP: 000056405645fe10 R08: 00007fc8623d1460 R09: 000000007fffffff R10: 0000000000000000 R11: 0000000000000246 R12: 000000000000000c R13: 00007fc86241b780 R14: 00007fc862417600 R15: 00007fc862416a00 In short, below scene breaks the lock dependency chain: memory_failure __page_handle_poison zone_pcp_disable -- lock(pcp_batch_high_lock) dissolve_free_huge_page __hugetlb_vmemmap_restore_folio static_key_slow_dec cpus_read_lock -- rlock(cpu_hotplug_lock) Fix this by calling drain_all_pages() instead. This issue won't occur until commit a6b40850c442 ("mm: hugetlb: replace hugetlb_free_vmemmap_enabled with a static_key"). As it introduced rlock(cpu_hotplug_lock) in dissolve_free_huge_page() code path while lock(pcp_batch_high_lock) is already in the __page_handle_poison(). [linmiaohe@huawei.com: extend comment per Oscar] [akpm@linux-foundation.org: reflow block comment] Link: https://lkml.kernel.org/r/20240407085456.2798193-1-linmiaohe@huawei.com Fixes: a6b40850c442 ("mm: hugetlb: replace hugetlb_free_vmemmap_enabled with a static_key") Signed-off-by: Miaohe Lin Acked-by: Oscar Salvador Reviewed-by: Jane Chu Cc: Naoya Horiguchi Cc: Signed-off-by: Andrew Morton --- mm/memory-failure.c | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/mm/memory-failure.c b/mm/memory-failure.c index 9349948f1abf..9e62a00b46dd 100644 --- a/mm/memory-failure.c +++ b/mm/memory-failure.c @@ -154,11 +154,23 @@ static int __page_handle_poison(struct page *page) { int ret; - zone_pcp_disable(page_zone(page)); + /* + * zone_pcp_disable() can't be used here. It will + * hold pcp_batch_high_lock and dissolve_free_huge_page() might hold + * cpu_hotplug_lock via static_key_slow_dec() when hugetlb vmemmap + * optimization is enabled. This will break current lock dependency + * chain and leads to deadlock. + * Disabling pcp before dissolving the page was a deterministic + * approach because we made sure that those pages cannot end up in any + * PCP list. Draining PCP lists expels those pages to the buddy system, + * but nothing guarantees that those pages do not get back to a PCP + * queue if we need to refill those. + */ ret = dissolve_free_huge_page(page); - if (!ret) + if (!ret) { + drain_all_pages(page_zone(page)); ret = take_page_off_buddy(page); - zone_pcp_enable(page_zone(page)); + } return ret; } -- cgit v1.2.3 From 07a57a338adb6ec9e766d6a6790f76527f45ceb5 Mon Sep 17 00:00:00 2001 From: Oscar Salvador Date: Sun, 7 Apr 2024 15:05:37 +0200 Subject: mm,swapops: update check in is_pfn_swap_entry for hwpoison entries Tony reported that the Machine check recovery was broken in v6.9-rc1, as he was hitting a VM_BUG_ON when injecting uncorrectable memory errors to DRAM. After some more digging and debugging on his side, he realized that this went back to v6.1, with the introduction of 'commit 0d206b5d2e0d ("mm/swap: add swp_offset_pfn() to fetch PFN from swap entry")'. That commit, among other things, introduced swp_offset_pfn(), replacing hwpoison_entry_to_pfn() in its favour. The patch also introduced a VM_BUG_ON() check for is_pfn_swap_entry(), but is_pfn_swap_entry() never got updated to cover hwpoison entries, which means that we would hit the VM_BUG_ON whenever we would call swp_offset_pfn() for such entries on environments with CONFIG_DEBUG_VM set. Fix this by updating the check to cover hwpoison entries as well, and update the comment while we are it. Link: https://lkml.kernel.org/r/20240407130537.16977-1-osalvador@suse.de Fixes: 0d206b5d2e0d ("mm/swap: add swp_offset_pfn() to fetch PFN from swap entry") Signed-off-by: Oscar Salvador Reported-by: Tony Luck Closes: https://lore.kernel.org/all/Zg8kLSl2yAlA3o5D@agluck-desk3/ Tested-by: Tony Luck Reviewed-by: Peter Xu Reviewed-by: David Hildenbrand Acked-by: Miaohe Lin Cc: [6.1.x] Signed-off-by: Andrew Morton --- include/linux/swapops.h | 65 +++++++++++++++++++++++++------------------------ 1 file changed, 33 insertions(+), 32 deletions(-) diff --git a/include/linux/swapops.h b/include/linux/swapops.h index 48b700ba1d18..a5c560a2f8c2 100644 --- a/include/linux/swapops.h +++ b/include/linux/swapops.h @@ -390,6 +390,35 @@ static inline bool is_migration_entry_dirty(swp_entry_t entry) } #endif /* CONFIG_MIGRATION */ +#ifdef CONFIG_MEMORY_FAILURE + +/* + * Support for hardware poisoned pages + */ +static inline swp_entry_t make_hwpoison_entry(struct page *page) +{ + BUG_ON(!PageLocked(page)); + return swp_entry(SWP_HWPOISON, page_to_pfn(page)); +} + +static inline int is_hwpoison_entry(swp_entry_t entry) +{ + return swp_type(entry) == SWP_HWPOISON; +} + +#else + +static inline swp_entry_t make_hwpoison_entry(struct page *page) +{ + return swp_entry(0, 0); +} + +static inline int is_hwpoison_entry(swp_entry_t swp) +{ + return 0; +} +#endif + typedef unsigned long pte_marker; #define PTE_MARKER_UFFD_WP BIT(0) @@ -483,8 +512,9 @@ static inline struct folio *pfn_swap_entry_folio(swp_entry_t entry) /* * A pfn swap entry is a special type of swap entry that always has a pfn stored - * in the swap offset. They are used to represent unaddressable device memory - * and to restrict access to a page undergoing migration. + * in the swap offset. They can either be used to represent unaddressable device + * memory, to restrict access to a page undergoing migration or to represent a + * pfn which has been hwpoisoned and unmapped. */ static inline bool is_pfn_swap_entry(swp_entry_t entry) { @@ -492,7 +522,7 @@ static inline bool is_pfn_swap_entry(swp_entry_t entry) BUILD_BUG_ON(SWP_TYPE_SHIFT < SWP_PFN_BITS); return is_migration_entry(entry) || is_device_private_entry(entry) || - is_device_exclusive_entry(entry); + is_device_exclusive_entry(entry) || is_hwpoison_entry(entry); } struct page_vma_mapped_walk; @@ -561,35 +591,6 @@ static inline int is_pmd_migration_entry(pmd_t pmd) } #endif /* CONFIG_ARCH_ENABLE_THP_MIGRATION */ -#ifdef CONFIG_MEMORY_FAILURE - -/* - * Support for hardware poisoned pages - */ -static inline swp_entry_t make_hwpoison_entry(struct page *page) -{ - BUG_ON(!PageLocked(page)); - return swp_entry(SWP_HWPOISON, page_to_pfn(page)); -} - -static inline int is_hwpoison_entry(swp_entry_t entry) -{ - return swp_type(entry) == SWP_HWPOISON; -} - -#else - -static inline swp_entry_t make_hwpoison_entry(struct page *page) -{ - return swp_entry(0, 0); -} - -static inline int is_hwpoison_entry(swp_entry_t swp) -{ - return 0; -} -#endif - static inline int non_swap_entry(swp_entry_t entry) { return swp_type(entry) >= MAX_SWAPFILES; -- cgit v1.2.3 From 9253c54e01b6505d348afbc02abaa4d9f8a01395 Mon Sep 17 00:00:00 2001 From: Phillip Lougher Date: Mon, 8 Apr 2024 23:02:06 +0100 Subject: Squashfs: check the inode number is not the invalid value of zero Syskiller has produced an out of bounds access in fill_meta_index(). That out of bounds access is ultimately caused because the inode has an inode number with the invalid value of zero, which was not checked. The reason this causes the out of bounds access is due to following sequence of events: 1. Fill_meta_index() is called to allocate (via empty_meta_index()) and fill a metadata index. It however suffers a data read error and aborts, invalidating the newly returned empty metadata index. It does this by setting the inode number of the index to zero, which means unused (zero is not a valid inode number). 2. When fill_meta_index() is subsequently called again on another read operation, locate_meta_index() returns the previous index because it matches the inode number of 0. Because this index has been returned it is expected to have been filled, and because it hasn't been, an out of bounds access is performed. This patch adds a sanity check which checks that the inode number is not zero when the inode is created and returns -EINVAL if it is. [phillip@squashfs.org.uk: whitespace fix] Link: https://lkml.kernel.org/r/20240409204723.446925-1-phillip@squashfs.org.uk Link: https://lkml.kernel.org/r/20240408220206.435788-1-phillip@squashfs.org.uk Signed-off-by: Phillip Lougher Reported-by: "Ubisectech Sirius" Closes: https://lore.kernel.org/lkml/87f5c007-b8a5-41ae-8b57-431e924c5915.bugreport@ubisectech.com/ Cc: Christian Brauner Cc: Signed-off-by: Andrew Morton --- fs/squashfs/inode.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/fs/squashfs/inode.c b/fs/squashfs/inode.c index aa3411354e66..16bd693d0b3a 100644 --- a/fs/squashfs/inode.c +++ b/fs/squashfs/inode.c @@ -48,6 +48,10 @@ static int squashfs_new_inode(struct super_block *sb, struct inode *inode, gid_t i_gid; int err; + inode->i_ino = le32_to_cpu(sqsh_ino->inode_number); + if (inode->i_ino == 0) + return -EINVAL; + err = squashfs_get_id(sb, le16_to_cpu(sqsh_ino->uid), &i_uid); if (err) return err; @@ -58,7 +62,6 @@ static int squashfs_new_inode(struct super_block *sb, struct inode *inode, i_uid_write(inode, i_uid); i_gid_write(inode, i_gid); - inode->i_ino = le32_to_cpu(sqsh_ino->inode_number); inode_set_mtime(inode, le32_to_cpu(sqsh_ino->mtime), 0); inode_set_atime(inode, inode_get_mtime_sec(inode), 0); inode_set_ctime(inode, inode_get_mtime_sec(inode), 0); -- cgit v1.2.3 From 0b2cf0a45e06d9538a2371f90150297a87b20eea Mon Sep 17 00:00:00 2001 From: Oscar Salvador Date: Tue, 9 Apr 2024 15:17:15 +0200 Subject: mm,page_owner: defer enablement of static branch Kefeng Wang reported that he was seeing some memory leaks with kmemleak with page_owner enabled. The reason is that we enable the page_owner_inited static branch and then proceed with the linking of stack_list struct to dummy_stack, which means that exists a race window between these two steps where we can have pages already being allocated calling add_stack_record_to_list(), allocating objects and linking them to stack_list, but then we set stack_list pointing to dummy_stack in init_page_owner. Which means that the objects that have been allocated during that time window are unreferenced and lost. Fix this by deferring the enablement of the branch until we have properly set up the list. Link: https://lkml.kernel.org/r/20240409131715.13632-1-osalvador@suse.de Fixes: 4bedfb314bdd ("mm,page_owner: maintain own list of stack_records structs") Signed-off-by: Oscar Salvador Reported-by: Kefeng Wang Closes: https://lore.kernel.org/linux-mm/74b147b0-718d-4d50-be75-d6afc801cd24@huawei.com/ Tested-by: Kefeng Wang Acked-by: Vlastimil Babka Signed-off-by: Andrew Morton --- mm/page_owner.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mm/page_owner.c b/mm/page_owner.c index 9bef0b442863..742f432e5bf0 100644 --- a/mm/page_owner.c +++ b/mm/page_owner.c @@ -118,7 +118,6 @@ static __init void init_page_owner(void) register_dummy_stack(); register_failure_stack(); register_early_stack(); - static_branch_enable(&page_owner_inited); init_early_allocated_pages(); /* Initialize dummy and failure stacks and link them to stack_list */ dummy_stack.stack_record = __stack_depot_get_stack_record(dummy_handle); @@ -129,6 +128,7 @@ static __init void init_page_owner(void) refcount_set(&failure_stack.stack_record->count, 1); dummy_stack.next = &failure_stack; stack_list = &dummy_stack; + static_branch_enable(&page_owner_inited); } struct page_ext_operations page_owner_ops = { -- cgit v1.2.3 From 1f737846aa3c45f07a06fa0d018b39e1afb8084a Mon Sep 17 00:00:00 2001 From: Sumanth Korikkar Date: Tue, 9 Apr 2024 17:54:07 +0200 Subject: mm/shmem: inline shmem_is_huge() for disabled transparent hugepages In order to minimize code size (CONFIG_CC_OPTIMIZE_FOR_SIZE=y), compiler might choose to make a regular function call (out-of-line) for shmem_is_huge() instead of inlining it. When transparent hugepages are disabled (CONFIG_TRANSPARENT_HUGEPAGE=n), it can cause compilation error. mm/shmem.c: In function `shmem_getattr': ./include/linux/huge_mm.h:383:27: note: in expansion of macro `BUILD_BUG' 383 | #define HPAGE_PMD_SIZE ({ BUILD_BUG(); 0; }) | ^~~~~~~~~ mm/shmem.c:1148:33: note: in expansion of macro `HPAGE_PMD_SIZE' 1148 | stat->blksize = HPAGE_PMD_SIZE; To prevent the possible error, always inline shmem_is_huge() when transparent hugepages are disabled. Link: https://lkml.kernel.org/r/20240409155407.2322714-1-sumanthk@linux.ibm.com Signed-off-by: Sumanth Korikkar Acked-by: David Hildenbrand Cc: Alexander Gordeev Cc: Heiko Carstens Cc: Hugh Dickins Cc: Ilya Leoshkevich Cc: Vasily Gorbik Cc: Signed-off-by: Andrew Morton --- include/linux/shmem_fs.h | 9 +++++++++ mm/shmem.c | 6 ------ 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/include/linux/shmem_fs.h b/include/linux/shmem_fs.h index a4c15db2f5e5..3fb18f7eb73e 100644 --- a/include/linux/shmem_fs.h +++ b/include/linux/shmem_fs.h @@ -110,8 +110,17 @@ extern struct page *shmem_read_mapping_page_gfp(struct address_space *mapping, extern void shmem_truncate_range(struct inode *inode, loff_t start, loff_t end); int shmem_unuse(unsigned int type); +#ifdef CONFIG_TRANSPARENT_HUGEPAGE extern bool shmem_is_huge(struct inode *inode, pgoff_t index, bool shmem_huge_force, struct mm_struct *mm, unsigned long vm_flags); +#else +static __always_inline bool shmem_is_huge(struct inode *inode, pgoff_t index, bool shmem_huge_force, + struct mm_struct *mm, unsigned long vm_flags) +{ + return false; +} +#endif + #ifdef CONFIG_SHMEM extern unsigned long shmem_swap_usage(struct vm_area_struct *vma); #else diff --git a/mm/shmem.c b/mm/shmem.c index 0aad0d9a621b..94ab99b6b574 100644 --- a/mm/shmem.c +++ b/mm/shmem.c @@ -748,12 +748,6 @@ static long shmem_unused_huge_count(struct super_block *sb, #define shmem_huge SHMEM_HUGE_DENY -bool shmem_is_huge(struct inode *inode, pgoff_t index, bool shmem_huge_force, - struct mm_struct *mm, unsigned long vm_flags) -{ - return false; -} - static unsigned long shmem_unused_huge_shrink(struct shmem_sb_info *sbinfo, struct shrink_control *sc, unsigned long nr_to_split) { -- cgit v1.2.3 From 35e351780fa9d8240dd6f7e4f245f9ea37e96c19 Mon Sep 17 00:00:00 2001 From: Miaohe Lin Date: Wed, 10 Apr 2024 17:14:41 +0800 Subject: fork: defer linking file vma until vma is fully initialized Thorvald reported a WARNING [1]. And the root cause is below race: CPU 1 CPU 2 fork hugetlbfs_fallocate dup_mmap hugetlbfs_punch_hole i_mmap_lock_write(mapping); vma_interval_tree_insert_after -- Child vma is visible through i_mmap tree. i_mmap_unlock_write(mapping); hugetlb_dup_vma_private -- Clear vma_lock outside i_mmap_rwsem! i_mmap_lock_write(mapping); hugetlb_vmdelete_list vma_interval_tree_foreach hugetlb_vma_trylock_write -- Vma_lock is cleared. tmp->vm_ops->open -- Alloc new vma_lock outside i_mmap_rwsem! hugetlb_vma_unlock_write -- Vma_lock is assigned!!! i_mmap_unlock_write(mapping); hugetlb_dup_vma_private() and hugetlb_vm_op_open() are called outside i_mmap_rwsem lock while vma lock can be used in the same time. Fix this by deferring linking file vma until vma is fully initialized. Those vmas should be initialized first before they can be used. Link: https://lkml.kernel.org/r/20240410091441.3539905-1-linmiaohe@huawei.com Fixes: 8d9bfb260814 ("hugetlb: add vma based lock for pmd sharing") Signed-off-by: Miaohe Lin Reported-by: Thorvald Natvig Closes: https://lore.kernel.org/linux-mm/20240129161735.6gmjsswx62o4pbja@revolver/T/ [1] Reviewed-by: Jane Chu Cc: Christian Brauner Cc: Heiko Carstens Cc: Kent Overstreet Cc: Liam R. Howlett Cc: Mateusz Guzik Cc: Matthew Wilcox (Oracle) Cc: Miaohe Lin Cc: Muchun Song Cc: Oleg Nesterov Cc: Peng Zhang Cc: Tycho Andersen Cc: Signed-off-by: Andrew Morton --- kernel/fork.c | 33 +++++++++++++++++---------------- 1 file changed, 17 insertions(+), 16 deletions(-) diff --git a/kernel/fork.c b/kernel/fork.c index 39a5046c2f0b..aebb3e6c96dc 100644 --- a/kernel/fork.c +++ b/kernel/fork.c @@ -714,6 +714,23 @@ static __latent_entropy int dup_mmap(struct mm_struct *mm, } else if (anon_vma_fork(tmp, mpnt)) goto fail_nomem_anon_vma_fork; vm_flags_clear(tmp, VM_LOCKED_MASK); + /* + * Copy/update hugetlb private vma information. + */ + if (is_vm_hugetlb_page(tmp)) + hugetlb_dup_vma_private(tmp); + + /* + * Link the vma into the MT. After using __mt_dup(), memory + * allocation is not necessary here, so it cannot fail. + */ + vma_iter_bulk_store(&vmi, tmp); + + mm->map_count++; + + if (tmp->vm_ops && tmp->vm_ops->open) + tmp->vm_ops->open(tmp); + file = tmp->vm_file; if (file) { struct address_space *mapping = file->f_mapping; @@ -730,25 +747,9 @@ static __latent_entropy int dup_mmap(struct mm_struct *mm, i_mmap_unlock_write(mapping); } - /* - * Copy/update hugetlb private vma information. - */ - if (is_vm_hugetlb_page(tmp)) - hugetlb_dup_vma_private(tmp); - - /* - * Link the vma into the MT. After using __mt_dup(), memory - * allocation is not necessary here, so it cannot fail. - */ - vma_iter_bulk_store(&vmi, tmp); - - mm->map_count++; if (!(tmp->vm_flags & VM_WIPEONFORK)) retval = copy_page_range(tmp, mpnt); - if (tmp->vm_ops && tmp->vm_ops->open) - tmp->vm_ops->open(tmp); - if (retval) { mpnt = vma_next(&vmi); goto loop_out; -- cgit v1.2.3 From 8247bf1db92a9697d4ee26db3259d2a1959d1366 Mon Sep 17 00:00:00 2001 From: Naoya Horiguchi Date: Sat, 13 Apr 2024 03:17:20 +0900 Subject: MAINTAINERS: update Naoya Horiguchi's email address My old NEC address has been removed, so update MAINTAINERS and .mailmap to map it to my gmail address. Link: https://lkml.kernel.org/r/20240412181720.18452-1-nao.horiguchi@gmail.com Signed-off-by: Naoya Horiguchi Acked-by: Miaohe Lin Cc: Oscar Salvador Signed-off-by: Andrew Morton --- .mailmap | 3 ++- MAINTAINERS | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/.mailmap b/.mailmap index 8284692f9610..625b496bf5f4 100644 --- a/.mailmap +++ b/.mailmap @@ -446,7 +446,8 @@ Mythri P K Nadav Amit Nadav Amit Nadia Yvette Chambers William Lee Irwin III -Naoya Horiguchi +Naoya Horiguchi +Naoya Horiguchi Nathan Chancellor Neeraj Upadhyay Neil Armstrong diff --git a/MAINTAINERS b/MAINTAINERS index c23fda1aa1f0..ee9cc2b40409 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -10024,7 +10024,7 @@ F: drivers/media/platform/st/sti/hva HWPOISON MEMORY FAILURE HANDLING M: Miaohe Lin -R: Naoya Horiguchi +R: Naoya Horiguchi L: linux-mm@kvack.org S: Maintained F: mm/hwpoison-inject.c -- cgit v1.2.3 From c4a7dc9523b59b3e73fd522c73e95e072f876b16 Mon Sep 17 00:00:00 2001 From: Jeongjun Park Date: Tue, 16 Apr 2024 03:20:48 +0900 Subject: nilfs2: fix OOB in nilfs_set_de_type The size of the nilfs_type_by_mode array in the fs/nilfs2/dir.c file is defined as "S_IFMT >> S_SHIFT", but the nilfs_set_de_type() function, which uses this array, specifies the index to read from the array in the same way as "(mode & S_IFMT) >> S_SHIFT". static void nilfs_set_de_type(struct nilfs_dir_entry *de, struct inode *inode) { umode_t mode = inode->i_mode; de->file_type = nilfs_type_by_mode[(mode & S_IFMT)>>S_SHIFT]; // oob } However, when the index is determined this way, an out-of-bounds (OOB) error occurs by referring to an index that is 1 larger than the array size when the condition "mode & S_IFMT == S_IFMT" is satisfied. Therefore, a patch to resize the nilfs_type_by_mode array should be applied to prevent OOB errors. Link: https://lkml.kernel.org/r/20240415182048.7144-1-konishi.ryusuke@gmail.com Reported-by: syzbot+2e22057de05b9f3b30d8@syzkaller.appspotmail.com Closes: https://syzkaller.appspot.com/bug?extid=2e22057de05b9f3b30d8 Fixes: 2ba466d74ed7 ("nilfs2: directory entry operations") Signed-off-by: Jeongjun Park Signed-off-by: Ryusuke Konishi Tested-by: Ryusuke Konishi Cc: Signed-off-by: Andrew Morton --- fs/nilfs2/dir.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/nilfs2/dir.c b/fs/nilfs2/dir.c index bc846b904b68..aee40db7a036 100644 --- a/fs/nilfs2/dir.c +++ b/fs/nilfs2/dir.c @@ -240,7 +240,7 @@ nilfs_filetype_table[NILFS_FT_MAX] = { #define S_SHIFT 12 static unsigned char -nilfs_type_by_mode[S_IFMT >> S_SHIFT] = { +nilfs_type_by_mode[(S_IFMT >> S_SHIFT) + 1] = { [S_IFREG >> S_SHIFT] = NILFS_FT_REG_FILE, [S_IFDIR >> S_SHIFT] = NILFS_FT_DIR, [S_IFCHR >> S_SHIFT] = NILFS_FT_CHRDEV, -- cgit v1.2.3 From 02bed83d59e37da30b745e30129511b1cc595c92 Mon Sep 17 00:00:00 2001 From: Kent Overstreet Date: Tue, 16 Apr 2024 17:55:02 -0400 Subject: bcachefs: Fix null ptr deref in twf from BCH_IOCTL_FSCK_OFFLINE We need to initialize the stdio redirects before they're used. Signed-off-by: Kent Overstreet --- fs/bcachefs/chardev.c | 4 +++- fs/bcachefs/thread_with_file.c | 15 +++++++++++++-- fs/bcachefs/thread_with_file.h | 3 +++ 3 files changed, 19 insertions(+), 3 deletions(-) diff --git a/fs/bcachefs/chardev.c b/fs/bcachefs/chardev.c index 72781aad6ba7..4d14f19f5185 100644 --- a/fs/bcachefs/chardev.c +++ b/fs/bcachefs/chardev.c @@ -232,13 +232,15 @@ static long bch2_ioctl_fsck_offline(struct bch_ioctl_fsck_offline __user *user_a /* We need request_key() to be called before we punt to kthread: */ opt_set(thr->opts, nostart, true); + bch2_thread_with_stdio_init(&thr->thr, &bch2_offline_fsck_ops); + thr->c = bch2_fs_open(devs.data, arg.nr_devs, thr->opts); if (!IS_ERR(thr->c) && thr->c->opts.errors == BCH_ON_ERROR_panic) thr->c->opts.errors = BCH_ON_ERROR_ro; - ret = bch2_run_thread_with_stdio(&thr->thr, &bch2_offline_fsck_ops); + ret = __bch2_run_thread_with_stdio(&thr->thr); out: darray_for_each(devs, i) kfree(*i); diff --git a/fs/bcachefs/thread_with_file.c b/fs/bcachefs/thread_with_file.c index 940db15d6a93..b1af7ac430f6 100644 --- a/fs/bcachefs/thread_with_file.c +++ b/fs/bcachefs/thread_with_file.c @@ -294,16 +294,27 @@ static int thread_with_stdio_fn(void *arg) return 0; } -int bch2_run_thread_with_stdio(struct thread_with_stdio *thr, - const struct thread_with_stdio_ops *ops) +void bch2_thread_with_stdio_init(struct thread_with_stdio *thr, + const struct thread_with_stdio_ops *ops) { stdio_buf_init(&thr->stdio.input); stdio_buf_init(&thr->stdio.output); thr->ops = ops; +} +int __bch2_run_thread_with_stdio(struct thread_with_stdio *thr) +{ return bch2_run_thread_with_file(&thr->thr, &thread_with_stdio_fops, thread_with_stdio_fn); } +int bch2_run_thread_with_stdio(struct thread_with_stdio *thr, + const struct thread_with_stdio_ops *ops) +{ + bch2_thread_with_stdio_init(thr, ops); + + return __bch2_run_thread_with_stdio(thr); +} + int bch2_run_thread_with_stdout(struct thread_with_stdio *thr, const struct thread_with_stdio_ops *ops) { diff --git a/fs/bcachefs/thread_with_file.h b/fs/bcachefs/thread_with_file.h index af54ea8f5b0f..1d63d14d7dca 100644 --- a/fs/bcachefs/thread_with_file.h +++ b/fs/bcachefs/thread_with_file.h @@ -63,6 +63,9 @@ struct thread_with_stdio { const struct thread_with_stdio_ops *ops; }; +void bch2_thread_with_stdio_init(struct thread_with_stdio *, + const struct thread_with_stdio_ops *); +int __bch2_run_thread_with_stdio(struct thread_with_stdio *); int bch2_run_thread_with_stdio(struct thread_with_stdio *, const struct thread_with_stdio_ops *); int bch2_run_thread_with_stdout(struct thread_with_stdio *, -- cgit v1.2.3 From 9fd5a48a1e3ff79ed54922668279ccb4d7190a62 Mon Sep 17 00:00:00 2001 From: Nathan Chancellor Date: Tue, 16 Apr 2024 08:16:02 -0700 Subject: bcachefs: Fix format specifier in validate_bset_keys() When building for 32-bit platforms, for which size_t is 'unsigned int', there is a warning from a format string in validate_bset_keys(): fs/bcachefs/btree_io.c: In function 'validate_bset_keys': fs/bcachefs/btree_io.c:891:34: error: format '%lu' expects argument of type 'long unsigned int', but argument 12 has type 'unsigned int' [-Werror=format=] 891 | "bad k->u64s %u (min %u max %lu)", k->u64s, | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ fs/bcachefs/btree_io.c:603:32: note: in definition of macro 'btree_err' 603 | msg, ##__VA_ARGS__); \ | ^~~ fs/bcachefs/btree_io.c:887:21: note: in expansion of macro 'btree_err_on' 887 | if (btree_err_on(!bkeyp_u64s_valid(&b->format, k), | ^~~~~~~~~~~~ fs/bcachefs/btree_io.c:891:64: note: format string is defined here 891 | "bad k->u64s %u (min %u max %lu)", k->u64s, | ~~^ | | | long unsigned int | %u cc1: all warnings being treated as errors BKEY_U64s is size_t so the entire expression is promoted to size_t. Use the '%zu' specifier so that there is no warning regardless of the width of size_t. Fixes: 031ad9e7dbd1 ("bcachefs: Check for packed bkeys that are too big") Reported-by: kernel test robot Closes: https://lore.kernel.org/oe-kbuild-all/202404130747.wH6Dd23p-lkp@intel.com/ Closes: https://lore.kernel.org/oe-kbuild-all/202404131536.HdAMBOVc-lkp@intel.com/ Signed-off-by: Nathan Chancellor Signed-off-by: Kent Overstreet --- fs/bcachefs/btree_io.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/bcachefs/btree_io.c b/fs/bcachefs/btree_io.c index 9678b2375bed..debb0edc3455 100644 --- a/fs/bcachefs/btree_io.c +++ b/fs/bcachefs/btree_io.c @@ -888,7 +888,7 @@ static int validate_bset_keys(struct bch_fs *c, struct btree *b, -BCH_ERR_btree_node_read_err_fixable, c, NULL, b, i, btree_node_bkey_bad_u64s, - "bad k->u64s %u (min %u max %lu)", k->u64s, + "bad k->u64s %u (min %u max %zu)", k->u64s, bkeyp_key_u64s(&b->format, k), U8_MAX - BKEY_U64s + bkeyp_key_u64s(&b->format, k))) goto drop_this_key; -- cgit v1.2.3 From fabb4d49854281027454b0fa305d33f6c9ec4b47 Mon Sep 17 00:00:00 2001 From: Kent Overstreet Date: Mon, 15 Apr 2024 22:54:10 -0400 Subject: bcachefs: node scan: ignore multiple nodes with same seq if interior Interior nodes are not really needed, when we have to scan - but if this pops up for leaf nodes we'll need a real heuristic. Signed-off-by: Kent Overstreet --- fs/bcachefs/btree_node_scan.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/fs/bcachefs/btree_node_scan.c b/fs/bcachefs/btree_node_scan.c index 866bd278439f..c60794264da2 100644 --- a/fs/bcachefs/btree_node_scan.c +++ b/fs/bcachefs/btree_node_scan.c @@ -302,6 +302,8 @@ again: start->max_key = bpos_predecessor(n->min_key); start->range_updated = true; + } else if (n->level) { + n->overwritten = true; } else { struct printbuf buf = PRINTBUF; -- cgit v1.2.3 From 79055f50a65fe5eb58e9da1f79fb0a4f4bc82fff Mon Sep 17 00:00:00 2001 From: Kent Overstreet Date: Mon, 15 Apr 2024 23:53:12 -0400 Subject: bcachefs: make sure to release last journal pin in replay This fixes a deadlock when journal replay has many keys to insert that were from fsck, not the journal. Signed-off-by: Kent Overstreet --- fs/bcachefs/recovery.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/fs/bcachefs/recovery.c b/fs/bcachefs/recovery.c index 0f328aba9760..be5b47619327 100644 --- a/fs/bcachefs/recovery.c +++ b/fs/bcachefs/recovery.c @@ -249,7 +249,10 @@ int bch2_journal_replay(struct bch_fs *c) struct journal_key *k = *kp; - replay_now_at(j, k->journal_seq); + if (k->journal_seq) + replay_now_at(j, k->journal_seq); + else + replay_now_at(j, j->replay_journal_seq_end); ret = commit_do(trans, NULL, NULL, BCH_TRANS_COMMIT_no_enospc| -- cgit v1.2.3 From f8bbc07ac535593139c875ffa19af924b1084540 Mon Sep 17 00:00:00 2001 From: Lei Chen Date: Sun, 14 Apr 2024 22:02:46 -0400 Subject: tun: limit printing rate when illegal packet received by tun dev vhost_worker will call tun call backs to receive packets. If too many illegal packets arrives, tun_do_read will keep dumping packet contents. When console is enabled, it will costs much more cpu time to dump packet and soft lockup will be detected. net_ratelimit mechanism can be used to limit the dumping rate. PID: 33036 TASK: ffff949da6f20000 CPU: 23 COMMAND: "vhost-32980" #0 [fffffe00003fce50] crash_nmi_callback at ffffffff89249253 #1 [fffffe00003fce58] nmi_handle at ffffffff89225fa3 #2 [fffffe00003fceb0] default_do_nmi at ffffffff8922642e #3 [fffffe00003fced0] do_nmi at ffffffff8922660d #4 [fffffe00003fcef0] end_repeat_nmi at ffffffff89c01663 [exception RIP: io_serial_in+20] RIP: ffffffff89792594 RSP: ffffa655314979e8 RFLAGS: 00000002 RAX: ffffffff89792500 RBX: ffffffff8af428a0 RCX: 0000000000000000 RDX: 00000000000003fd RSI: 0000000000000005 RDI: ffffffff8af428a0 RBP: 0000000000002710 R8: 0000000000000004 R9: 000000000000000f R10: 0000000000000000 R11: ffffffff8acbf64f R12: 0000000000000020 R13: ffffffff8acbf698 R14: 0000000000000058 R15: 0000000000000000 ORIG_RAX: ffffffffffffffff CS: 0010 SS: 0018 #5 [ffffa655314979e8] io_serial_in at ffffffff89792594 #6 [ffffa655314979e8] wait_for_xmitr at ffffffff89793470 #7 [ffffa65531497a08] serial8250_console_putchar at ffffffff897934f6 #8 [ffffa65531497a20] uart_console_write at ffffffff8978b605 #9 [ffffa65531497a48] serial8250_console_write at ffffffff89796558 #10 [ffffa65531497ac8] console_unlock at ffffffff89316124 #11 [ffffa65531497b10] vprintk_emit at ffffffff89317c07 #12 [ffffa65531497b68] printk at ffffffff89318306 #13 [ffffa65531497bc8] print_hex_dump at ffffffff89650765 #14 [ffffa65531497ca8] tun_do_read at ffffffffc0b06c27 [tun] #15 [ffffa65531497d38] tun_recvmsg at ffffffffc0b06e34 [tun] #16 [ffffa65531497d68] handle_rx at ffffffffc0c5d682 [vhost_net] #17 [ffffa65531497ed0] vhost_worker at ffffffffc0c644dc [vhost] #18 [ffffa65531497f10] kthread at ffffffff892d2e72 #19 [ffffa65531497f50] ret_from_fork at ffffffff89c0022f Fixes: ef3db4a59542 ("tun: avoid BUG, dump packet on GSO errors") Signed-off-by: Lei Chen Reviewed-by: Willem de Bruijn Acked-by: Jason Wang Reviewed-by: Eric Dumazet Acked-by: Michael S. Tsirkin Link: https://lore.kernel.org/r/20240415020247.2207781-1-lei.chen@smartx.com Signed-off-by: Jakub Kicinski --- drivers/net/tun.c | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/drivers/net/tun.c b/drivers/net/tun.c index 0b3f21cba552..92da8c03d960 100644 --- a/drivers/net/tun.c +++ b/drivers/net/tun.c @@ -2125,14 +2125,16 @@ static ssize_t tun_put_user(struct tun_struct *tun, tun_is_little_endian(tun), true, vlan_hlen)) { struct skb_shared_info *sinfo = skb_shinfo(skb); - pr_err("unexpected GSO type: " - "0x%x, gso_size %d, hdr_len %d\n", - sinfo->gso_type, tun16_to_cpu(tun, gso.gso_size), - tun16_to_cpu(tun, gso.hdr_len)); - print_hex_dump(KERN_ERR, "tun: ", - DUMP_PREFIX_NONE, - 16, 1, skb->head, - min((int)tun16_to_cpu(tun, gso.hdr_len), 64), true); + + if (net_ratelimit()) { + netdev_err(tun->dev, "unexpected GSO type: 0x%x, gso_size %d, hdr_len %d\n", + sinfo->gso_type, tun16_to_cpu(tun, gso.gso_size), + tun16_to_cpu(tun, gso.hdr_len)); + print_hex_dump(KERN_ERR, "tun: ", + DUMP_PREFIX_NONE, + 16, 1, skb->head, + min((int)tun16_to_cpu(tun, gso.hdr_len), 64), true); + } WARN_ON_ONCE(1); return -EINVAL; } -- cgit v1.2.3 From 5894ff6c4707af645f2faa36cf07cc2745e1658f Mon Sep 17 00:00:00 2001 From: Frank Li Date: Tue, 16 Apr 2024 10:47:47 -0400 Subject: ASoC: dt-bindings: fsl-esai: Remove 'fsl,*' from required list fsl,fifo-depth have default value 64 in driver(sound/soc/fsl/fsl_esai.c). fsl,esai-synchronous is flag(bool) type. It doesn't make sense to put flag type into 'required'. Fix warning: arch/arm/boot/dts/nxp/imx/imx6q-sabreauto.dtb: esai@2024000: 'fsl,fifo-depth' is a required property arch/arm/boot/dts/nxp/imx/imx6q-sabreauto.dtb: esai@2024000: 'fsl,esai-synchronous' is a required property Signed-off-by: Frank Li Link: https://lore.kernel.org/r/20240416-esai_arm_dts_warning-v2-1-879e59c0c3b8@nxp.com Signed-off-by: Mark Brown --- Documentation/devicetree/bindings/sound/fsl,esai.yaml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/Documentation/devicetree/bindings/sound/fsl,esai.yaml b/Documentation/devicetree/bindings/sound/fsl,esai.yaml index f167f1634d7e..2a64e682b517 100644 --- a/Documentation/devicetree/bindings/sound/fsl,esai.yaml +++ b/Documentation/devicetree/bindings/sound/fsl,esai.yaml @@ -67,6 +67,7 @@ properties: fsl,fifo-depth: $ref: /schemas/types.yaml#/definitions/uint32 + default: 64 description: The number of elements in the transmit and receive FIFOs. This number is the maximum allowed value for @@ -95,8 +96,6 @@ required: - clock-names - dmas - dma-names - - fsl,fifo-depth - - fsl,esai-synchronous unevaluatedProperties: false -- cgit v1.2.3 From 9aea6d64bb3acbff6b2f33cb5bbff65e824ab9a7 Mon Sep 17 00:00:00 2001 From: Frank Li Date: Tue, 16 Apr 2024 10:47:48 -0400 Subject: ASoC: dt-bindings: fsl-esai: Add ref: dai-common.yaml Add ref: dai-common.yaml to fix below warning. arch/arm/boot/dts/nxp/imx/imx6q-sabreauto.dtb: esai@2024000: Unevaluated properties are not allowed ('#sound-dai-cells' was unexpected) Reviewed-by: Rob Herring Signed-off-by: Frank Li Link: https://lore.kernel.org/r/20240416-esai_arm_dts_warning-v2-2-879e59c0c3b8@nxp.com Signed-off-by: Mark Brown --- Documentation/devicetree/bindings/sound/fsl,esai.yaml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Documentation/devicetree/bindings/sound/fsl,esai.yaml b/Documentation/devicetree/bindings/sound/fsl,esai.yaml index 2a64e682b517..f99ed20fa684 100644 --- a/Documentation/devicetree/bindings/sound/fsl,esai.yaml +++ b/Documentation/devicetree/bindings/sound/fsl,esai.yaml @@ -99,6 +99,9 @@ required: unevaluatedProperties: false +allOf: + - $ref: dai-common.yaml# + examples: - | esai@2024000 { -- cgit v1.2.3 From 8c75cdcdf869acabfdc7858827099dcde9f24e6c Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Mon, 15 Apr 2024 14:18:11 +0200 Subject: wifi: mac80211: split mesh fast tx cache into local/proxied/forwarded Depending on the origin of the packets (and their SA), 802.11 + mesh headers could be filled in differently. In order to properly deal with that, add a new field to the lookup key, indicating the type (local, proxied or forwarded). This can fix spurious packet drop issues that depend on the order in which nodes/hosts communicate with each other. Fixes: d5edb9ae8d56 ("wifi: mac80211: mesh fast xmit support") Signed-off-by: Felix Fietkau Link: https://msgid.link/20240415121811.13391-1-nbd@nbd.name [use sizeof_field() for key_len] Signed-off-by: Johannes Berg --- net/mac80211/mesh.c | 8 +++++++- net/mac80211/mesh.h | 36 +++++++++++++++++++++++++++++++++--- net/mac80211/mesh_pathtbl.c | 31 ++++++++++++++++++++++--------- net/mac80211/rx.c | 13 ++++++++++--- 4 files changed, 72 insertions(+), 16 deletions(-) diff --git a/net/mac80211/mesh.c b/net/mac80211/mesh.c index 32475da98d73..cbc9b5e40cb3 100644 --- a/net/mac80211/mesh.c +++ b/net/mac80211/mesh.c @@ -747,6 +747,9 @@ bool ieee80211_mesh_xmit_fast(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb, u32 ctrl_flags) { struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; + struct ieee80211_mesh_fast_tx_key key = { + .type = MESH_FAST_TX_TYPE_LOCAL + }; struct ieee80211_mesh_fast_tx *entry; struct ieee80211s_hdr *meshhdr; u8 sa[ETH_ALEN] __aligned(2); @@ -782,7 +785,10 @@ bool ieee80211_mesh_xmit_fast(struct ieee80211_sub_if_data *sdata, return false; } - entry = mesh_fast_tx_get(sdata, skb->data); + ether_addr_copy(key.addr, skb->data); + if (!ether_addr_equal(skb->data + ETH_ALEN, sdata->vif.addr)) + key.type = MESH_FAST_TX_TYPE_PROXIED; + entry = mesh_fast_tx_get(sdata, &key); if (!entry) return false; diff --git a/net/mac80211/mesh.h b/net/mac80211/mesh.h index d913ce7ba72e..3f9664e4e00c 100644 --- a/net/mac80211/mesh.h +++ b/net/mac80211/mesh.h @@ -134,10 +134,39 @@ struct mesh_path { #define MESH_FAST_TX_CACHE_THRESHOLD_SIZE 384 #define MESH_FAST_TX_CACHE_TIMEOUT 8000 /* msecs */ +/** + * enum ieee80211_mesh_fast_tx_type - cached mesh fast tx entry type + * + * @MESH_FAST_TX_TYPE_LOCAL: tx from the local vif address as SA + * @MESH_FAST_TX_TYPE_PROXIED: local tx with a different SA (e.g. bridged) + * @MESH_FAST_TX_TYPE_FORWARDED: forwarded from a different mesh point + * @NUM_MESH_FAST_TX_TYPE: number of entry types + */ +enum ieee80211_mesh_fast_tx_type { + MESH_FAST_TX_TYPE_LOCAL, + MESH_FAST_TX_TYPE_PROXIED, + MESH_FAST_TX_TYPE_FORWARDED, + + /* must be last */ + NUM_MESH_FAST_TX_TYPE +}; + + +/** + * struct ieee80211_mesh_fast_tx_key - cached mesh fast tx entry key + * + * @addr: The Ethernet DA for this entry + * @type: cache entry type + */ +struct ieee80211_mesh_fast_tx_key { + u8 addr[ETH_ALEN] __aligned(2); + u16 type; +}; + /** * struct ieee80211_mesh_fast_tx - cached mesh fast tx entry * @rhash: rhashtable pointer - * @addr_key: The Ethernet DA which is the key for this entry + * @key: the lookup key for this cache entry * @fast_tx: base fast_tx data * @hdr: cached mesh and rfc1042 headers * @hdrlen: length of mesh + rfc1042 @@ -148,7 +177,7 @@ struct mesh_path { */ struct ieee80211_mesh_fast_tx { struct rhash_head rhash; - u8 addr_key[ETH_ALEN] __aligned(2); + struct ieee80211_mesh_fast_tx_key key; struct ieee80211_fast_tx fast_tx; u8 hdr[sizeof(struct ieee80211s_hdr) + sizeof(rfc1042_header)]; @@ -334,7 +363,8 @@ void mesh_path_tx_root_frame(struct ieee80211_sub_if_data *sdata); bool mesh_action_is_path_sel(struct ieee80211_mgmt *mgmt); struct ieee80211_mesh_fast_tx * -mesh_fast_tx_get(struct ieee80211_sub_if_data *sdata, const u8 *addr); +mesh_fast_tx_get(struct ieee80211_sub_if_data *sdata, + struct ieee80211_mesh_fast_tx_key *key); bool ieee80211_mesh_xmit_fast(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb, u32 ctrl_flags); void mesh_fast_tx_cache(struct ieee80211_sub_if_data *sdata, diff --git a/net/mac80211/mesh_pathtbl.c b/net/mac80211/mesh_pathtbl.c index 91b55d6a68b9..a6b62169f084 100644 --- a/net/mac80211/mesh_pathtbl.c +++ b/net/mac80211/mesh_pathtbl.c @@ -37,8 +37,8 @@ static const struct rhashtable_params mesh_rht_params = { static const struct rhashtable_params fast_tx_rht_params = { .nelem_hint = 10, .automatic_shrinking = true, - .key_len = ETH_ALEN, - .key_offset = offsetof(struct ieee80211_mesh_fast_tx, addr_key), + .key_len = sizeof_field(struct ieee80211_mesh_fast_tx, key), + .key_offset = offsetof(struct ieee80211_mesh_fast_tx, key), .head_offset = offsetof(struct ieee80211_mesh_fast_tx, rhash), .hashfn = mesh_table_hash, }; @@ -431,20 +431,21 @@ static void mesh_fast_tx_entry_free(struct mesh_tx_cache *cache, } struct ieee80211_mesh_fast_tx * -mesh_fast_tx_get(struct ieee80211_sub_if_data *sdata, const u8 *addr) +mesh_fast_tx_get(struct ieee80211_sub_if_data *sdata, + struct ieee80211_mesh_fast_tx_key *key) { struct ieee80211_mesh_fast_tx *entry; struct mesh_tx_cache *cache; cache = &sdata->u.mesh.tx_cache; - entry = rhashtable_lookup(&cache->rht, addr, fast_tx_rht_params); + entry = rhashtable_lookup(&cache->rht, key, fast_tx_rht_params); if (!entry) return NULL; if (!(entry->mpath->flags & MESH_PATH_ACTIVE) || mpath_expired(entry->mpath)) { spin_lock_bh(&cache->walk_lock); - entry = rhashtable_lookup(&cache->rht, addr, fast_tx_rht_params); + entry = rhashtable_lookup(&cache->rht, key, fast_tx_rht_params); if (entry) mesh_fast_tx_entry_free(cache, entry); spin_unlock_bh(&cache->walk_lock); @@ -489,18 +490,24 @@ void mesh_fast_tx_cache(struct ieee80211_sub_if_data *sdata, if (!sta) return; + build.key.type = MESH_FAST_TX_TYPE_LOCAL; if ((meshhdr->flags & MESH_FLAGS_AE) == MESH_FLAGS_AE_A5_A6) { /* This is required to keep the mppath alive */ mppath = mpp_path_lookup(sdata, meshhdr->eaddr1); if (!mppath) return; build.mppath = mppath; + if (!ether_addr_equal(meshhdr->eaddr2, sdata->vif.addr)) + build.key.type = MESH_FAST_TX_TYPE_PROXIED; } else if (ieee80211_has_a4(hdr->frame_control)) { mppath = mpath; } else { return; } + if (!ether_addr_equal(hdr->addr4, sdata->vif.addr)) + build.key.type = MESH_FAST_TX_TYPE_FORWARDED; + /* rate limit, in case fast xmit can't be enabled */ if (mppath->fast_tx_check == jiffies) return; @@ -547,7 +554,7 @@ void mesh_fast_tx_cache(struct ieee80211_sub_if_data *sdata, } } - memcpy(build.addr_key, mppath->dst, ETH_ALEN); + memcpy(build.key.addr, mppath->dst, ETH_ALEN); build.timestamp = jiffies; build.fast_tx.band = info->band; build.fast_tx.da_offs = offsetof(struct ieee80211_hdr, addr3); @@ -646,12 +653,18 @@ void mesh_fast_tx_flush_addr(struct ieee80211_sub_if_data *sdata, const u8 *addr) { struct mesh_tx_cache *cache = &sdata->u.mesh.tx_cache; + struct ieee80211_mesh_fast_tx_key key = {}; struct ieee80211_mesh_fast_tx *entry; + int i; + ether_addr_copy(key.addr, addr); spin_lock_bh(&cache->walk_lock); - entry = rhashtable_lookup_fast(&cache->rht, addr, fast_tx_rht_params); - if (entry) - mesh_fast_tx_entry_free(cache, entry); + for (i = 0; i < NUM_MESH_FAST_TX_TYPE; i++) { + key.type = i; + entry = rhashtable_lookup_fast(&cache->rht, &key, fast_tx_rht_params); + if (entry) + mesh_fast_tx_entry_free(cache, entry); + } spin_unlock_bh(&cache->walk_lock); } diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index 685185dc04f9..6e24864f9a40 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c @@ -2763,7 +2763,10 @@ ieee80211_rx_mesh_fast_forward(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb, int hdrlen) { struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; - struct ieee80211_mesh_fast_tx *entry = NULL; + struct ieee80211_mesh_fast_tx_key key = { + .type = MESH_FAST_TX_TYPE_FORWARDED + }; + struct ieee80211_mesh_fast_tx *entry; struct ieee80211s_hdr *mesh_hdr; struct tid_ampdu_tx *tid_tx; struct sta_info *sta; @@ -2772,9 +2775,13 @@ ieee80211_rx_mesh_fast_forward(struct ieee80211_sub_if_data *sdata, mesh_hdr = (struct ieee80211s_hdr *)(skb->data + sizeof(eth)); if ((mesh_hdr->flags & MESH_FLAGS_AE) == MESH_FLAGS_AE_A5_A6) - entry = mesh_fast_tx_get(sdata, mesh_hdr->eaddr1); + ether_addr_copy(key.addr, mesh_hdr->eaddr1); else if (!(mesh_hdr->flags & MESH_FLAGS_AE)) - entry = mesh_fast_tx_get(sdata, skb->data); + ether_addr_copy(key.addr, skb->data); + else + return false; + + entry = mesh_fast_tx_get(sdata, &key); if (!entry) return false; -- cgit v1.2.3 From dbfff5bf9292714f02ace002fea8ce6599ea1145 Mon Sep 17 00:00:00 2001 From: Avraham Stern Date: Mon, 15 Apr 2024 11:54:43 +0300 Subject: wifi: iwlwifi: mvm: remove old PASN station when adding a new one If a PASN station is added, and an old PASN station already exists for the same mac address, remove the old station before adding the new one. Keeping the old station caueses old security context to be used in measurements. Fixes: 0739a7d70e00 ("iwlwifi: mvm: initiator: add option for adding a PASN responder") Signed-off-by: Avraham Stern Signed-off-by: Miri Korenblit Link: https://msgid.link/20240415114847.ef3544a416f2.I4e8c7c8ca22737f4f908ae5cd4fc0b920c703dd3@changeid Signed-off-by: Johannes Berg --- drivers/net/wireless/intel/iwlwifi/mvm/ftm-initiator.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/ftm-initiator.c b/drivers/net/wireless/intel/iwlwifi/mvm/ftm-initiator.c index 4863a3c74640..d84d7e955bb0 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/ftm-initiator.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/ftm-initiator.c @@ -53,6 +53,8 @@ int iwl_mvm_ftm_add_pasn_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif, if (!pasn) return -ENOBUFS; + iwl_mvm_ftm_remove_pasn_sta(mvm, addr); + pasn->cipher = iwl_mvm_cipher_to_location_cipher(cipher); switch (pasn->cipher) { -- cgit v1.2.3 From bada85a3f584763deadd201147778c3e791d279c Mon Sep 17 00:00:00 2001 From: Miri Korenblit Date: Mon, 15 Apr 2024 11:54:44 +0300 Subject: wifi: iwlwifi: mvm: return uid from iwl_mvm_build_scan_cmd This function is supposed to return a uid on success, and an errno in failure. But it currently returns the return value of the specific cmd version handler, which in turn returns 0 on success and errno otherwise. This means that on success, iwl_mvm_build_scan_cmd will return 0 regardless if the actual uid. Fix this by returning the uid if the handler succeeded. Fixes: 687db6ff5b70 ("iwlwifi: scan: make new scan req versioning flow") Signed-off-by: Miri Korenblit Reviewed-by: Ilan Peer Link: https://msgid.link/20240415114847.5e2d602b3190.I4c4931021be74a67a869384c8f8ee7463e0c7857@changeid Signed-off-by: Johannes Berg --- drivers/net/wireless/intel/iwlwifi/mvm/scan.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/scan.c b/drivers/net/wireless/intel/iwlwifi/mvm/scan.c index f3e3986b4c72..11559563ae38 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/scan.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/scan.c @@ -2813,7 +2813,8 @@ static int iwl_mvm_build_scan_cmd(struct iwl_mvm *mvm, if (ver_handler->version != scan_ver) continue; - return ver_handler->handler(mvm, vif, params, type, uid); + err = ver_handler->handler(mvm, vif, params, type, uid); + return err ? : uid; } err = iwl_mvm_scan_umac(mvm, vif, params, type, uid); -- cgit v1.2.3 From fb1f4584b1215e8c209f6b3a4028ed8351a0e961 Mon Sep 17 00:00:00 2001 From: Chuanhong Guo Date: Tue, 12 Mar 2024 14:29:12 +0800 Subject: USB: serial: option: add support for Fibocom FM650/FG650 Fibocom FM650/FG650 are 5G modems with ECM/NCM/RNDIS/MBIM modes. This patch adds support to all 4 modes. In all 4 modes, the first serial port is the AT console while the other 3 appear to be diagnostic interfaces for dumping modem logs. usb-devices output for all modes: ECM: T: Bus=04 Lev=01 Prnt=01 Port=00 Cnt=01 Dev#= 5 Spd=5000 MxCh= 0 D: Ver= 3.10 Cls=00(>ifc ) Sub=00 Prot=00 MxPS= 9 #Cfgs= 1 P: Vendor=2cb7 ProdID=0a04 Rev=04.04 S: Manufacturer=Fibocom Wireless Inc. S: Product=FG650 Module S: SerialNumber=0123456789ABCDEF C: #Ifs= 5 Cfg#= 1 Atr=c0 MxPwr=504mA I: If#= 0 Alt= 0 #EPs= 1 Cls=02(commc) Sub=06 Prot=00 Driver=cdc_ether E: Ad=82(I) Atr=03(Int.) MxPS= 16 Ivl=32ms I: If#= 1 Alt= 1 #EPs= 2 Cls=0a(data ) Sub=00 Prot=00 Driver=cdc_ether E: Ad=01(O) Atr=02(Bulk) MxPS=1024 Ivl=0ms E: Ad=81(I) Atr=02(Bulk) MxPS=1024 Ivl=0ms I: If#= 2 Alt= 0 #EPs= 2 Cls=ff(vend.) Sub=00 Prot=00 Driver=option E: Ad=02(O) Atr=02(Bulk) MxPS=1024 Ivl=0ms E: Ad=83(I) Atr=02(Bulk) MxPS=1024 Ivl=0ms I: If#= 3 Alt= 0 #EPs= 2 Cls=ff(vend.) Sub=00 Prot=00 Driver=option E: Ad=03(O) Atr=02(Bulk) MxPS=1024 Ivl=0ms E: Ad=84(I) Atr=02(Bulk) MxPS=1024 Ivl=0ms I: If#= 4 Alt= 0 #EPs= 2 Cls=ff(vend.) Sub=00 Prot=00 Driver=option E: Ad=04(O) Atr=02(Bulk) MxPS=1024 Ivl=0ms E: Ad=85(I) Atr=02(Bulk) MxPS=1024 Ivl=0ms NCM: T: Bus=04 Lev=01 Prnt=01 Port=00 Cnt=01 Dev#= 6 Spd=5000 MxCh= 0 D: Ver= 3.10 Cls=00(>ifc ) Sub=00 Prot=00 MxPS= 9 #Cfgs= 1 P: Vendor=2cb7 ProdID=0a05 Rev=04.04 S: Manufacturer=Fibocom Wireless Inc. S: Product=FG650 Module S: SerialNumber=0123456789ABCDEF C: #Ifs= 6 Cfg#= 1 Atr=c0 MxPwr=504mA I: If#= 0 Alt= 0 #EPs= 1 Cls=02(commc) Sub=0d Prot=00 Driver=cdc_ncm E: Ad=82(I) Atr=03(Int.) MxPS= 16 Ivl=32ms I: If#= 1 Alt= 1 #EPs= 2 Cls=0a(data ) Sub=00 Prot=01 Driver=cdc_ncm E: Ad=01(O) Atr=02(Bulk) MxPS=1024 Ivl=0ms E: Ad=81(I) Atr=02(Bulk) MxPS=1024 Ivl=0ms I: If#= 2 Alt= 0 #EPs= 2 Cls=ff(vend.) Sub=00 Prot=00 Driver=option E: Ad=02(O) Atr=02(Bulk) MxPS=1024 Ivl=0ms E: Ad=83(I) Atr=02(Bulk) MxPS=1024 Ivl=0ms I: If#= 3 Alt= 0 #EPs= 2 Cls=ff(vend.) Sub=00 Prot=00 Driver=option E: Ad=03(O) Atr=02(Bulk) MxPS=1024 Ivl=0ms E: Ad=84(I) Atr=02(Bulk) MxPS=1024 Ivl=0ms I: If#= 4 Alt= 0 #EPs= 2 Cls=ff(vend.) Sub=00 Prot=00 Driver=option E: Ad=04(O) Atr=02(Bulk) MxPS=1024 Ivl=0ms E: Ad=85(I) Atr=02(Bulk) MxPS=1024 Ivl=0ms I: If#= 5 Alt= 0 #EPs= 2 Cls=ff(vend.) Sub=00 Prot=00 Driver=option E: Ad=05(O) Atr=02(Bulk) MxPS=1024 Ivl=0ms E: Ad=86(I) Atr=02(Bulk) MxPS=1024 Ivl=0ms RNDIS: T: Bus=04 Lev=01 Prnt=01 Port=00 Cnt=01 Dev#= 4 Spd=5000 MxCh= 0 D: Ver= 3.10 Cls=00(>ifc ) Sub=00 Prot=00 MxPS= 9 #Cfgs= 1 P: Vendor=2cb7 ProdID=0a06 Rev=04.04 S: Manufacturer=Fibocom Wireless Inc. S: Product=FG650 Module S: SerialNumber=0123456789ABCDEF C: #Ifs= 6 Cfg#= 1 Atr=c0 MxPwr=504mA I: If#= 0 Alt= 0 #EPs= 1 Cls=e0(wlcon) Sub=01 Prot=03 Driver=rndis_host E: Ad=82(I) Atr=03(Int.) MxPS= 8 Ivl=32ms I: If#= 1 Alt= 0 #EPs= 2 Cls=0a(data ) Sub=00 Prot=00 Driver=rndis_host E: Ad=01(O) Atr=02(Bulk) MxPS=1024 Ivl=0ms E: Ad=81(I) Atr=02(Bulk) MxPS=1024 Ivl=0ms I: If#= 2 Alt= 0 #EPs= 2 Cls=ff(vend.) Sub=00 Prot=00 Driver=option E: Ad=02(O) Atr=02(Bulk) MxPS=1024 Ivl=0ms E: Ad=83(I) Atr=02(Bulk) MxPS=1024 Ivl=0ms I: If#= 3 Alt= 0 #EPs= 2 Cls=ff(vend.) Sub=00 Prot=00 Driver=option E: Ad=03(O) Atr=02(Bulk) MxPS=1024 Ivl=0ms E: Ad=84(I) Atr=02(Bulk) MxPS=1024 Ivl=0ms I: If#= 4 Alt= 0 #EPs= 2 Cls=ff(vend.) Sub=00 Prot=00 Driver=option E: Ad=04(O) Atr=02(Bulk) MxPS=1024 Ivl=0ms E: Ad=85(I) Atr=02(Bulk) MxPS=1024 Ivl=0ms I: If#= 5 Alt= 0 #EPs= 2 Cls=ff(vend.) Sub=00 Prot=00 Driver=option E: Ad=05(O) Atr=02(Bulk) MxPS=1024 Ivl=0ms E: Ad=86(I) Atr=02(Bulk) MxPS=1024 Ivl=0ms MBIM: T: Bus=04 Lev=01 Prnt=01 Port=00 Cnt=01 Dev#= 7 Spd=5000 MxCh= 0 D: Ver= 3.10 Cls=00(>ifc ) Sub=00 Prot=00 MxPS= 9 #Cfgs= 1 P: Vendor=2cb7 ProdID=0a07 Rev=04.04 S: Manufacturer=Fibocom Wireless Inc. S: Product=FG650 Module S: SerialNumber=0123456789ABCDEF C: #Ifs= 6 Cfg#= 1 Atr=c0 MxPwr=504mA I: If#= 0 Alt= 0 #EPs= 1 Cls=02(commc) Sub=0e Prot=00 Driver=cdc_mbim E: Ad=82(I) Atr=03(Int.) MxPS= 64 Ivl=32ms I: If#= 1 Alt= 1 #EPs= 2 Cls=0a(data ) Sub=00 Prot=02 Driver=cdc_mbim E: Ad=01(O) Atr=02(Bulk) MxPS=1024 Ivl=0ms E: Ad=81(I) Atr=02(Bulk) MxPS=1024 Ivl=0ms I: If#= 2 Alt= 0 #EPs= 2 Cls=ff(vend.) Sub=00 Prot=00 Driver=option E: Ad=02(O) Atr=02(Bulk) MxPS=1024 Ivl=0ms E: Ad=83(I) Atr=02(Bulk) MxPS=1024 Ivl=0ms I: If#= 3 Alt= 0 #EPs= 2 Cls=ff(vend.) Sub=00 Prot=00 Driver=option E: Ad=03(O) Atr=02(Bulk) MxPS=1024 Ivl=0ms E: Ad=84(I) Atr=02(Bulk) MxPS=1024 Ivl=0ms I: If#= 4 Alt= 0 #EPs= 2 Cls=ff(vend.) Sub=00 Prot=00 Driver=option E: Ad=04(O) Atr=02(Bulk) MxPS=1024 Ivl=0ms E: Ad=85(I) Atr=02(Bulk) MxPS=1024 Ivl=0ms I: If#= 5 Alt= 0 #EPs= 2 Cls=ff(vend.) Sub=00 Prot=00 Driver=option E: Ad=05(O) Atr=02(Bulk) MxPS=1024 Ivl=0ms E: Ad=86(I) Atr=02(Bulk) MxPS=1024 Ivl=0ms Signed-off-by: Chuanhong Guo Cc: stable@vger.kernel.org Signed-off-by: Johan Hovold --- drivers/usb/serial/option.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c index 16cf0ddaae9b..ad0fff1e889d 100644 --- a/drivers/usb/serial/option.c +++ b/drivers/usb/serial/option.c @@ -2295,6 +2295,10 @@ static const struct usb_device_id option_ids[] = { { USB_DEVICE_INTERFACE_CLASS(0x2cb7, 0x01a3, 0xff) }, /* Fibocom FM101-GL (laptop MBIM) */ { USB_DEVICE_INTERFACE_CLASS(0x2cb7, 0x01a4, 0xff), /* Fibocom FM101-GL (laptop MBIM) */ .driver_info = RSVD(4) }, + { USB_DEVICE_INTERFACE_CLASS(0x2cb7, 0x0a04, 0xff) }, /* Fibocom FM650-CN (ECM mode) */ + { USB_DEVICE_INTERFACE_CLASS(0x2cb7, 0x0a05, 0xff) }, /* Fibocom FM650-CN (NCM mode) */ + { USB_DEVICE_INTERFACE_CLASS(0x2cb7, 0x0a06, 0xff) }, /* Fibocom FM650-CN (RNDIS mode) */ + { USB_DEVICE_INTERFACE_CLASS(0x2cb7, 0x0a07, 0xff) }, /* Fibocom FM650-CN (MBIM mode) */ { USB_DEVICE_INTERFACE_CLASS(0x2df3, 0x9d03, 0xff) }, /* LongSung M5710 */ { USB_DEVICE_INTERFACE_CLASS(0x305a, 0x1404, 0xff) }, /* GosunCn GM500 RNDIS */ { USB_DEVICE_INTERFACE_CLASS(0x305a, 0x1405, 0xff) }, /* GosunCn GM500 MBIM */ -- cgit v1.2.3 From d59cf049c8378677053703e724808836f180888e Mon Sep 17 00:00:00 2001 From: Arınç ÜNAL Date: Sat, 13 Apr 2024 16:01:39 +0300 Subject: net: dsa: mt7530: fix mirroring frames received on local port MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This switch intellectual property provides a bit on the ARL global control register which controls allowing mirroring frames which are received on the local port (monitor port). This bit is unset after reset. This ability must be enabled to fully support the port mirroring feature on this switch intellectual property. Therefore, this patch fixes the traffic not being reflected on a port, which would be configured like below: tc qdisc add dev swp0 clsact tc filter add dev swp0 ingress matchall skip_sw \ action mirred egress mirror dev swp0 As a side note, this configuration provides the hairpinning feature for a single port. Fixes: 37feab6076aa ("net: dsa: mt7530: add support for port mirroring") Signed-off-by: Arınç ÜNAL Signed-off-by: David S. Miller --- drivers/net/dsa/mt7530.c | 6 ++++++ drivers/net/dsa/mt7530.h | 4 ++++ 2 files changed, 10 insertions(+) diff --git a/drivers/net/dsa/mt7530.c b/drivers/net/dsa/mt7530.c index c0d0bce0b594..b84e1845fa02 100644 --- a/drivers/net/dsa/mt7530.c +++ b/drivers/net/dsa/mt7530.c @@ -2480,6 +2480,9 @@ mt7530_setup(struct dsa_switch *ds) PVC_EG_TAG(MT7530_VLAN_EG_CONSISTENT)); } + /* Allow mirroring frames received on the local port (monitor port). */ + mt7530_set(priv, MT753X_AGC, LOCAL_EN); + /* Setup VLAN ID 0 for VLAN-unaware bridges */ ret = mt7530_setup_vlan0(priv); if (ret) @@ -2591,6 +2594,9 @@ mt7531_setup_common(struct dsa_switch *ds) PVC_EG_TAG(MT7530_VLAN_EG_CONSISTENT)); } + /* Allow mirroring frames received on the local port (monitor port). */ + mt7530_set(priv, MT753X_AGC, LOCAL_EN); + /* Flush the FDB table */ ret = mt7530_fdb_cmd(priv, MT7530_FDB_FLUSH, NULL); if (ret < 0) diff --git a/drivers/net/dsa/mt7530.h b/drivers/net/dsa/mt7530.h index 585db03c0548..a08053390b28 100644 --- a/drivers/net/dsa/mt7530.h +++ b/drivers/net/dsa/mt7530.h @@ -32,6 +32,10 @@ enum mt753x_id { #define SYSC_REG_RSTCTRL 0x34 #define RESET_MCM BIT(2) +/* Register for ARL global control */ +#define MT753X_AGC 0xc +#define LOCAL_EN BIT(7) + /* Registers to mac forward control for unknown frames */ #define MT7530_MFC 0x10 #define BC_FFP(x) (((x) & 0xff) << 24) -- cgit v1.2.3 From 2c606d138518cc69f09c35929abc414a99e3a28f Mon Sep 17 00:00:00 2001 From: Arınç ÜNAL Date: Sat, 13 Apr 2024 16:01:40 +0300 Subject: net: dsa: mt7530: fix port mirroring for MT7988 SoC switch MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The "MT7988A Wi-Fi 7 Generation Router Platform: Datasheet (Open Version) v0.1" document shows bits 16 to 18 as the MIRROR_PORT field of the CPU forward control register. Currently, the MT7530 DSA subdriver configures bits 0 to 2 of the CPU forward control register which breaks the port mirroring feature for the MT7988 SoC switch. Fix this by using the MT7531_MIRROR_PORT_GET() and MT7531_MIRROR_PORT_SET() macros which utilise the correct bits. Fixes: 110c18bfed41 ("net: dsa: mt7530: introduce driver for MT7988 built-in switch") Signed-off-by: Arınç ÜNAL Acked-by: Daniel Golle Signed-off-by: David S. Miller --- drivers/net/dsa/mt7530.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/drivers/net/dsa/mt7530.c b/drivers/net/dsa/mt7530.c index b84e1845fa02..8090390edaf9 100644 --- a/drivers/net/dsa/mt7530.c +++ b/drivers/net/dsa/mt7530.c @@ -1883,14 +1883,16 @@ mt7530_port_vlan_del(struct dsa_switch *ds, int port, static int mt753x_mirror_port_get(unsigned int id, u32 val) { - return (id == ID_MT7531) ? MT7531_MIRROR_PORT_GET(val) : - MIRROR_PORT(val); + return (id == ID_MT7531 || id == ID_MT7988) ? + MT7531_MIRROR_PORT_GET(val) : + MIRROR_PORT(val); } static int mt753x_mirror_port_set(unsigned int id, u32 val) { - return (id == ID_MT7531) ? MT7531_MIRROR_PORT_SET(val) : - MIRROR_PORT(val); + return (id == ID_MT7531 || id == ID_MT7988) ? + MT7531_MIRROR_PORT_SET(val) : + MIRROR_PORT(val); } static int mt753x_port_mirror_add(struct dsa_switch *ds, int port, -- cgit v1.2.3 From 13c785323b36b845300b256d0e5963c3727667d7 Mon Sep 17 00:00:00 2001 From: Uwe Kleine-König Date: Wed, 17 Apr 2024 11:03:27 +0200 Subject: serial: stm32: Return IRQ_NONE in the ISR if no handling happend MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit If there is a stuck irq that the handler doesn't address, returning IRQ_HANDLED unconditionally makes it impossible for the irq core to detect the problem and disable the irq. So only return IRQ_HANDLED if an event was handled. A stuck irq is still problematic, but with this change at least it only makes the UART nonfunctional instead of occupying the (usually only) CPU by 100% and so stall the whole machine. Fixes: 48a6092fb41f ("serial: stm32-usart: Add STM32 USART Driver") Cc: stable@vger.kernel.org Signed-off-by: Uwe Kleine-König Link: https://lore.kernel.org/r/5f92603d0dfd8a5b8014b2b10a902d91e0bb881f.1713344161.git.u.kleine-koenig@pengutronix.de Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/stm32-usart.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/drivers/tty/serial/stm32-usart.c b/drivers/tty/serial/stm32-usart.c index 58d169e5c1db..d60cbac69194 100644 --- a/drivers/tty/serial/stm32-usart.c +++ b/drivers/tty/serial/stm32-usart.c @@ -861,6 +861,7 @@ static irqreturn_t stm32_usart_interrupt(int irq, void *ptr) const struct stm32_usart_offsets *ofs = &stm32_port->info->ofs; u32 sr; unsigned int size; + irqreturn_t ret = IRQ_NONE; sr = readl_relaxed(port->membase + ofs->isr); @@ -869,11 +870,14 @@ static irqreturn_t stm32_usart_interrupt(int irq, void *ptr) (sr & USART_SR_TC)) { stm32_usart_tc_interrupt_disable(port); stm32_usart_rs485_rts_disable(port); + ret = IRQ_HANDLED; } - if ((sr & USART_SR_RTOF) && ofs->icr != UNDEF_REG) + if ((sr & USART_SR_RTOF) && ofs->icr != UNDEF_REG) { writel_relaxed(USART_ICR_RTOCF, port->membase + ofs->icr); + ret = IRQ_HANDLED; + } if ((sr & USART_SR_WUF) && ofs->icr != UNDEF_REG) { /* Clear wake up flag and disable wake up interrupt */ @@ -882,6 +886,7 @@ static irqreturn_t stm32_usart_interrupt(int irq, void *ptr) stm32_usart_clr_bits(port, ofs->cr3, USART_CR3_WUFIE); if (irqd_is_wakeup_set(irq_get_irq_data(port->irq))) pm_wakeup_event(tport->tty->dev, 0); + ret = IRQ_HANDLED; } /* @@ -896,6 +901,7 @@ static irqreturn_t stm32_usart_interrupt(int irq, void *ptr) uart_unlock_and_check_sysrq(port); if (size) tty_flip_buffer_push(tport); + ret = IRQ_HANDLED; } } @@ -903,6 +909,7 @@ static irqreturn_t stm32_usart_interrupt(int irq, void *ptr) uart_port_lock(port); stm32_usart_transmit_chars(port); uart_port_unlock(port); + ret = IRQ_HANDLED; } /* Receiver timeout irq for DMA RX */ @@ -912,9 +919,10 @@ static irqreturn_t stm32_usart_interrupt(int irq, void *ptr) uart_unlock_and_check_sysrq(port); if (size) tty_flip_buffer_push(tport); + ret = IRQ_HANDLED; } - return IRQ_HANDLED; + return ret; } static void stm32_usart_set_mctrl(struct uart_port *port, unsigned int mctrl) -- cgit v1.2.3 From ea2624b5b829b8f93c0dce25721d835969b34faf Mon Sep 17 00:00:00 2001 From: Uwe Kleine-König Date: Wed, 17 Apr 2024 11:03:28 +0200 Subject: serial: stm32: Reset .throttled state in .startup() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When an UART is opened that still has .throttled set from a previous open, the RX interrupt is enabled but the irq handler doesn't consider it. This easily results in a stuck irq with the effect to occupy the CPU in a tight loop. So reset the throttle state in .startup() to ensure that RX irqs are handled. Fixes: d1ec8a2eabe9 ("serial: stm32: update throttle and unthrottle ops for dma mode") Cc: stable@vger.kernel.org Signed-off-by: Uwe Kleine-König Link: https://lore.kernel.org/r/a784f80d3414f7db723b2ec66efc56e1ad666cbf.1713344161.git.u.kleine-koenig@pengutronix.de Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/stm32-usart.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/tty/serial/stm32-usart.c b/drivers/tty/serial/stm32-usart.c index d60cbac69194..4fa5a03ebac0 100644 --- a/drivers/tty/serial/stm32-usart.c +++ b/drivers/tty/serial/stm32-usart.c @@ -1092,6 +1092,7 @@ static int stm32_usart_startup(struct uart_port *port) val |= USART_CR2_SWAP; writel_relaxed(val, port->membase + ofs->cr2); } + stm32_port->throttled = false; /* RX FIFO Flush */ if (ofs->rqr != UNDEF_REG) -- cgit v1.2.3 From e871abcda3b67d0820b4182ebe93435624e9c6a4 Mon Sep 17 00:00:00 2001 From: "Jason A. Donenfeld" Date: Wed, 17 Apr 2024 13:38:29 +0200 Subject: random: handle creditable entropy from atomic process context The entropy accounting changes a static key when the RNG has initialized, since it only ever initializes once. Static key changes, however, cannot be made from atomic context, so depending on where the last creditable entropy comes from, the static key change might need to be deferred to a worker. Previously the code used the execute_in_process_context() helper function, which accounts for whether or not the caller is in_interrupt(). However, that doesn't account for the case where the caller is actually in process context but is holding a spinlock. This turned out to be the case with input_handle_event() in drivers/input/input.c contributing entropy: [] die+0xa8/0x2fc [] bug_handler+0x44/0xec [] brk_handler+0x90/0x144 [] do_debug_exception+0xa0/0x148 [] el1_dbg+0x60/0x7c [] el1h_64_sync_handler+0x38/0x90 [] el1h_64_sync+0x64/0x6c [] __might_resched+0x1fc/0x2e8 [] __might_sleep+0x44/0x7c [] cpus_read_lock+0x1c/0xec [] static_key_enable+0x14/0x38 [] crng_set_ready+0x14/0x28 [] execute_in_process_context+0xb8/0xf8 [] _credit_init_bits+0x118/0x1dc [] add_timer_randomness+0x264/0x270 [] add_input_randomness+0x38/0x48 [] input_handle_event+0x2b8/0x490 [] input_event+0x6c/0x98 According to Guoyong, it's not really possible to refactor the various drivers to never hold a spinlock there. And in_atomic() isn't reliable. So, rather than trying to be too fancy, just punt the change in the static key to a workqueue always. There's basically no drawback of doing this, as the code already needed to account for the static key not changing immediately, and given that it's just an optimization, there's not exactly a hurry to change the static key right away, so deferal is fine. Reported-by: Guoyong Wang Cc: stable@vger.kernel.org Fixes: f5bda35fba61 ("random: use static branch for crng_ready()") Signed-off-by: Jason A. Donenfeld --- drivers/char/random.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/char/random.c b/drivers/char/random.c index 456be28ba67c..2597cb43f438 100644 --- a/drivers/char/random.c +++ b/drivers/char/random.c @@ -702,7 +702,7 @@ static void extract_entropy(void *buf, size_t len) static void __cold _credit_init_bits(size_t bits) { - static struct execute_work set_ready; + static DECLARE_WORK(set_ready, crng_set_ready); unsigned int new, orig, add; unsigned long flags; @@ -718,8 +718,8 @@ static void __cold _credit_init_bits(size_t bits) if (orig < POOL_READY_BITS && new >= POOL_READY_BITS) { crng_reseed(NULL); /* Sets crng_init to CRNG_READY under base_crng.lock. */ - if (static_key_initialized) - execute_in_process_context(crng_set_ready, &set_ready); + if (static_key_initialized && system_unbound_wq) + queue_work(system_unbound_wq, &set_ready); atomic_notifier_call_chain(&random_ready_notifier, 0, NULL); wake_up_interruptible(&crng_init_wait); kill_fasync(&fasync, SIGIO, POLL_IN); @@ -890,8 +890,8 @@ void __init random_init(void) /* * If we were initialized by the cpu or bootloader before jump labels - * are initialized, then we should enable the static branch here, where - * it's guaranteed that jump labels have been initialized. + * or workqueues are initialized, then we should enable the static + * branch here, where it's guaranteed that these have been initialized. */ if (!static_branch_likely(&crng_is_ready) && crng_init >= CRNG_READY) crng_set_ready(NULL); -- cgit v1.2.3 From 83781384a96b95e2b6403d3c8a002b2c89031770 Mon Sep 17 00:00:00 2001 From: Gerd Bayer Date: Mon, 15 Apr 2024 15:15:07 +0200 Subject: s390/ism: Properly fix receive message buffer allocation Since [1], dma_alloc_coherent() does not accept requests for GFP_COMP anymore, even on archs that may be able to fulfill this. Functionality that relied on the receive buffer being a compound page broke at that point: The SMC-D protocol, that utilizes the ism device driver, passes receive buffers to the splice processor in a struct splice_pipe_desc with a single entry list of struct pages. As the buffer is no longer a compound page, the splice processor now rejects requests to handle more than a page worth of data. Replace dma_alloc_coherent() and allocate a buffer with folio_alloc and create a DMA map for it with dma_map_page(). Since only receive buffers on ISM devices use DMA, qualify the mapping as FROM_DEVICE. Since ISM devices are available on arch s390, only, and on that arch all DMA is coherent, there is no need to introduce and export some kind of dma_sync_to_cpu() method to be called by the SMC-D protocol layer. Analogously, replace dma_free_coherent by a two step dma_unmap_page, then folio_put to free the receive buffer. [1] https://lore.kernel.org/all/20221113163535.884299-1-hch@lst.de/ Fixes: c08004eede4b ("s390/ism: don't pass bogus GFP_ flags to dma_alloc_coherent") Signed-off-by: Gerd Bayer Signed-off-by: David S. Miller --- drivers/s390/net/ism_drv.c | 37 ++++++++++++++++++++++++++++--------- 1 file changed, 28 insertions(+), 9 deletions(-) diff --git a/drivers/s390/net/ism_drv.c b/drivers/s390/net/ism_drv.c index 2c8e964425dc..43778b088ffa 100644 --- a/drivers/s390/net/ism_drv.c +++ b/drivers/s390/net/ism_drv.c @@ -292,13 +292,16 @@ out: static void ism_free_dmb(struct ism_dev *ism, struct ism_dmb *dmb) { clear_bit(dmb->sba_idx, ism->sba_bitmap); - dma_free_coherent(&ism->pdev->dev, dmb->dmb_len, - dmb->cpu_addr, dmb->dma_addr); + dma_unmap_page(&ism->pdev->dev, dmb->dma_addr, dmb->dmb_len, + DMA_FROM_DEVICE); + folio_put(virt_to_folio(dmb->cpu_addr)); } static int ism_alloc_dmb(struct ism_dev *ism, struct ism_dmb *dmb) { + struct folio *folio; unsigned long bit; + int rc; if (PAGE_ALIGN(dmb->dmb_len) > dma_get_max_seg_size(&ism->pdev->dev)) return -EINVAL; @@ -315,14 +318,30 @@ static int ism_alloc_dmb(struct ism_dev *ism, struct ism_dmb *dmb) test_and_set_bit(dmb->sba_idx, ism->sba_bitmap)) return -EINVAL; - dmb->cpu_addr = dma_alloc_coherent(&ism->pdev->dev, dmb->dmb_len, - &dmb->dma_addr, - GFP_KERNEL | __GFP_NOWARN | - __GFP_NOMEMALLOC | __GFP_NORETRY); - if (!dmb->cpu_addr) - clear_bit(dmb->sba_idx, ism->sba_bitmap); + folio = folio_alloc(GFP_KERNEL | __GFP_NOWARN | __GFP_NOMEMALLOC | + __GFP_NORETRY, get_order(dmb->dmb_len)); - return dmb->cpu_addr ? 0 : -ENOMEM; + if (!folio) { + rc = -ENOMEM; + goto out_bit; + } + + dmb->cpu_addr = folio_address(folio); + dmb->dma_addr = dma_map_page(&ism->pdev->dev, + virt_to_page(dmb->cpu_addr), 0, + dmb->dmb_len, DMA_FROM_DEVICE); + if (dma_mapping_error(&ism->pdev->dev, dmb->dma_addr)) { + rc = -ENOMEM; + goto out_free; + } + + return 0; + +out_free: + kfree(dmb->cpu_addr); +out_bit: + clear_bit(dmb->sba_idx, ism->sba_bitmap); + return rc; } int ism_register_dmb(struct ism_dev *ism, struct ism_dmb *dmb, -- cgit v1.2.3 From 652ead9b746a63e4e79d7ad66d3edf0a8a5b0c2f Mon Sep 17 00:00:00 2001 From: Maarten Lankhorst Date: Thu, 4 Apr 2024 11:03:02 +0200 Subject: drm/xe: Fix bo leak in intel_fb_bo_framebuffer_init Add a unreference bo in the error path, to prevent leaking a bo ref. Return 0 on success to clarify the success path. Signed-off-by: Maarten Lankhorst Fixes: 44e694958b95 ("drm/xe/display: Implement display support") Cc: # v6.8+ Reviewed-by: Nirmoy Das Link: https://patchwork.freedesktop.org/patch/msgid/20240404090302.68422-1-maarten.lankhorst@linux.intel.com (cherry picked from commit a2f3d731be3893e730417ae3190760fcaffdf549) Signed-off-by: Lucas De Marchi --- drivers/gpu/drm/xe/display/intel_fb_bo.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/xe/display/intel_fb_bo.c b/drivers/gpu/drm/xe/display/intel_fb_bo.c index b21da7b745a5..a9c1f9885c6b 100644 --- a/drivers/gpu/drm/xe/display/intel_fb_bo.c +++ b/drivers/gpu/drm/xe/display/intel_fb_bo.c @@ -31,7 +31,7 @@ int intel_fb_bo_framebuffer_init(struct intel_framebuffer *intel_fb, ret = ttm_bo_reserve(&bo->ttm, true, false, NULL); if (ret) - return ret; + goto err; if (!(bo->flags & XE_BO_SCANOUT_BIT)) { /* @@ -42,12 +42,16 @@ int intel_fb_bo_framebuffer_init(struct intel_framebuffer *intel_fb, */ if (XE_IOCTL_DBG(i915, !list_empty(&bo->ttm.base.gpuva.list))) { ttm_bo_unreserve(&bo->ttm); - return -EINVAL; + ret = -EINVAL; + goto err; } bo->flags |= XE_BO_SCANOUT_BIT; } ttm_bo_unreserve(&bo->ttm); + return 0; +err: + xe_bo_put(bo); return ret; } -- cgit v1.2.3 From ca7c52ac7ad384bcf299d89482c45fec7cd00da9 Mon Sep 17 00:00:00 2001 From: Matthew Auld Date: Fri, 12 Apr 2024 12:31:45 +0100 Subject: drm/xe/vm: prevent UAF with asid based lookup The asid is only erased from the xarray when the vm refcount reaches zero, however this leads to potential UAF since the xe_vm_get() only works on a vm with refcount != 0. Since the asid is allocated in the vm create ioctl, rather erase it when closing the vm, prior to dropping the potential last ref. This should also work when user closes driver fd without explicit vm destroy. Fixes: dd08ebf6c352 ("drm/xe: Introduce a new DRM driver for Intel GPUs") Closes: https://gitlab.freedesktop.org/drm/xe/kernel/-/issues/1594 Signed-off-by: Matthew Auld Cc: Matthew Brost Cc: # v6.8+ Reviewed-by: Matthew Brost Link: https://patchwork.freedesktop.org/patch/msgid/20240412113144.259426-4-matthew.auld@intel.com (cherry picked from commit 83967c57320d0d01ae512f10e79213f81e4bf594) Signed-off-by: Lucas De Marchi --- drivers/gpu/drm/xe/xe_vm.c | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/drivers/gpu/drm/xe/xe_vm.c b/drivers/gpu/drm/xe/xe_vm.c index 62d1ef8867a8..3d4c8f342e21 100644 --- a/drivers/gpu/drm/xe/xe_vm.c +++ b/drivers/gpu/drm/xe/xe_vm.c @@ -1577,6 +1577,16 @@ void xe_vm_close_and_put(struct xe_vm *vm) xe->usm.num_vm_in_fault_mode--; else if (!(vm->flags & XE_VM_FLAG_MIGRATION)) xe->usm.num_vm_in_non_fault_mode--; + + if (vm->usm.asid) { + void *lookup; + + xe_assert(xe, xe->info.has_asid); + xe_assert(xe, !(vm->flags & XE_VM_FLAG_MIGRATION)); + + lookup = xa_erase(&xe->usm.asid_to_vm, vm->usm.asid); + xe_assert(xe, lookup == vm); + } mutex_unlock(&xe->usm.lock); for_each_tile(tile, xe, id) @@ -1592,24 +1602,15 @@ static void vm_destroy_work_func(struct work_struct *w) struct xe_device *xe = vm->xe; struct xe_tile *tile; u8 id; - void *lookup; /* xe_vm_close_and_put was not called? */ xe_assert(xe, !vm->size); mutex_destroy(&vm->snap_mutex); - if (!(vm->flags & XE_VM_FLAG_MIGRATION)) { + if (!(vm->flags & XE_VM_FLAG_MIGRATION)) xe_device_mem_access_put(xe); - if (xe->info.has_asid && vm->usm.asid) { - mutex_lock(&xe->usm.lock); - lookup = xa_erase(&xe->usm.asid_to_vm, vm->usm.asid); - xe_assert(xe, lookup == vm); - mutex_unlock(&xe->usm.lock); - } - } - for_each_tile(tile, xe, id) XE_WARN_ON(vm->pt_root[id]); -- cgit v1.2.3 From 9be51470d514eb20d4ce29684cf933ef1c5fff48 Mon Sep 17 00:00:00 2001 From: John Watts Date: Wed, 17 Apr 2024 15:14:43 +1000 Subject: ASoC: sunxi: sun4i-i2s: Fix pcm_formats type specification pcm_formats should be a u64 as it is a SNDRV_PCM_FMTBIT_* not a SNDRV_PCM_FORMAT_*. Also fix a small grammar error while we're here. Reported-by: kernel test robot Closes: https://lore.kernel.org/oe-kbuild-all/202404170103.ySYwieqi-lkp@intel.com/ Signed-off-by: John Watts Link: https://lore.kernel.org/r/20240417-sunxi_s32_fix-v1-1-d82e451565c0@jookia.org Signed-off-by: Mark Brown --- sound/soc/sunxi/sun4i-i2s.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/soc/sunxi/sun4i-i2s.c b/sound/soc/sunxi/sun4i-i2s.c index 59830f2a0d30..5f8d979585b6 100644 --- a/sound/soc/sunxi/sun4i-i2s.c +++ b/sound/soc/sunxi/sun4i-i2s.c @@ -156,7 +156,7 @@ struct sun4i_i2s; /** * struct sun4i_i2s_quirks - Differences between SoC variants. * @has_reset: SoC needs reset deasserted. - * @pcm_formats: available PCM formats + * @pcm_formats: available PCM formats. * @reg_offset_txdata: offset of the tx fifo. * @sun4i_i2s_regmap: regmap config to use. * @field_clkdiv_mclk_en: regmap field to enable mclk output. @@ -176,7 +176,7 @@ struct sun4i_i2s; */ struct sun4i_i2s_quirks { bool has_reset; - snd_pcm_format_t pcm_formats; + u64 pcm_formats; unsigned int reg_offset_txdata; /* TX FIFO */ const struct regmap_config *sun4i_i2s_regmap; -- cgit v1.2.3 From f609e7b1b49e4d15cf107d2069673ee63860c398 Mon Sep 17 00:00:00 2001 From: Mario Limonciello Date: Wed, 10 Apr 2024 09:10:46 -0500 Subject: platform/x86/amd/pmc: Extend Framework 13 quirk to more BIOSes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit BIOS 03.05 still hasn't fixed the spurious IRQ1 issue. As it's still being worked on there is still a possibility that it won't need to apply to future BIOS releases. Add a quirk for BIOS 03.05 as well. Signed-off-by: Mario Limonciello Reviewed-by: Hans de Goede Link: https://lore.kernel.org/r/20240410141046.433-1-mario.limonciello@amd.com Reviewed-by: Ilpo Järvinen Signed-off-by: Ilpo Järvinen --- drivers/platform/x86/amd/pmc/pmc-quirks.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/drivers/platform/x86/amd/pmc/pmc-quirks.c b/drivers/platform/x86/amd/pmc/pmc-quirks.c index b456370166b6..b4f49720c87f 100644 --- a/drivers/platform/x86/amd/pmc/pmc-quirks.c +++ b/drivers/platform/x86/amd/pmc/pmc-quirks.c @@ -208,6 +208,15 @@ static const struct dmi_system_id fwbug_list[] = { DMI_MATCH(DMI_BIOS_VERSION, "03.03"), } }, + { + .ident = "Framework Laptop 13 (Phoenix)", + .driver_data = &quirk_spurious_8042, + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Framework"), + DMI_MATCH(DMI_PRODUCT_NAME, "Laptop 13 (AMD Ryzen 7040Series)"), + DMI_MATCH(DMI_BIOS_VERSION, "03.05"), + } + }, {} }; -- cgit v1.2.3 From ca7c4507ba87e9fc22e0ecfa819c3664b3e8287b Mon Sep 17 00:00:00 2001 From: Christian König Date: Fri, 15 Mar 2024 13:07:53 +0100 Subject: drm/amdgpu: remove invalid resource->start check v2 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The majority of those where removed in the commit aed01a68047b ("drm/amdgpu: Remove TTM resource->start visible VRAM condition v2") But this one was missed because it's working on the resource and not the BO. Since we also no longer use a fake start address for visible BOs this will now trigger invalid mapping errors. v2: also remove the unused variable Signed-off-by: Christian König Fixes: aed01a68047b ("drm/amdgpu: Remove TTM resource->start visible VRAM condition v2") CC: stable@vger.kernel.org Acked-by: Pierre-Eric Pelloux-Prayer Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c index fc418e670fda..6417cb76ccd4 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c @@ -557,7 +557,6 @@ static int amdgpu_ttm_io_mem_reserve(struct ttm_device *bdev, struct ttm_resource *mem) { struct amdgpu_device *adev = amdgpu_ttm_adev(bdev); - size_t bus_size = (size_t)mem->size; switch (mem->mem_type) { case TTM_PL_SYSTEM: @@ -568,9 +567,6 @@ static int amdgpu_ttm_io_mem_reserve(struct ttm_device *bdev, break; case TTM_PL_VRAM: mem->bus.offset = mem->start << PAGE_SHIFT; - /* check if it's visible */ - if ((mem->bus.offset + bus_size) > adev->gmc.visible_vram_size) - return -EINVAL; if (adev->mman.aper_base_kaddr && mem->placement & TTM_PL_FLAG_CONTIGUOUS) -- cgit v1.2.3 From 18921b205012568b45760753ad3146ddb9e2d4e2 Mon Sep 17 00:00:00 2001 From: Felix Kuehling Date: Wed, 10 Apr 2024 15:52:10 -0400 Subject: drm/amdkfd: Fix memory leak in create_process failure Fix memory leak due to a leaked mmget reference on an error handling code path that is triggered when attempting to create KFD processes while a GPU reset is in progress. Fixes: 0ab2d7532b05 ("drm/amdkfd: prepare per-process debug enable and disable") CC: Xiaogang Chen Signed-off-by: Felix Kuehling Tested-by: Harish Kasiviswanthan Reviewed-by: Mukul Joshi Signed-off-by: Alex Deucher Cc: stable@vger.kernel.org --- drivers/gpu/drm/amd/amdkfd/kfd_process.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_process.c b/drivers/gpu/drm/amd/amdkfd/kfd_process.c index 717a60d7a4ea..b79986412cd8 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_process.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_process.c @@ -819,9 +819,9 @@ struct kfd_process *kfd_create_process(struct task_struct *thread) mutex_lock(&kfd_processes_mutex); if (kfd_is_locked()) { - mutex_unlock(&kfd_processes_mutex); pr_debug("KFD is locked! Cannot create process"); - return ERR_PTR(-EINVAL); + process = ERR_PTR(-EINVAL); + goto out; } /* A prior open of /dev/kfd could have already created the process. */ -- cgit v1.2.3 From 91f10a3d21f2313485178d49efef8a3ba02bd8c7 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Fri, 29 Mar 2024 18:03:03 -0400 Subject: Revert "drm/amd/display: fix USB-C flag update after enc10 feature init" This reverts commit b5abd7f983e14054593dc91d6df2aa5f8cc67652. This change breaks DSC on 4k monitors at 144Hz over USB-C. Closes: https://gitlab.freedesktop.org/drm/amd/-/issues/3254 Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher Cc: Muhammad Ahmed Cc: Tom Chung Cc: Charlene Liu Cc: Hamza Mahfooz Cc: Harry Wentland Cc: stable@vger.kernel.org --- drivers/gpu/drm/amd/display/dc/dcn32/dcn32_dio_link_encoder.c | 8 +++----- drivers/gpu/drm/amd/display/dc/dcn35/dcn35_dio_link_encoder.c | 4 ++-- 2 files changed, 5 insertions(+), 7 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_dio_link_encoder.c b/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_dio_link_encoder.c index e224a028d68a..8a0460e86309 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_dio_link_encoder.c +++ b/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_dio_link_encoder.c @@ -248,14 +248,12 @@ void dcn32_link_encoder_construct( enc10->base.hpd_source = init_data->hpd_source; enc10->base.connector = init_data->connector; - enc10->base.preferred_engine = ENGINE_ID_UNKNOWN; - - enc10->base.features = *enc_features; if (enc10->base.connector.id == CONNECTOR_ID_USBC) enc10->base.features.flags.bits.DP_IS_USB_C = 1; - if (enc10->base.connector.id == CONNECTOR_ID_USBC) - enc10->base.features.flags.bits.DP_IS_USB_C = 1; + enc10->base.preferred_engine = ENGINE_ID_UNKNOWN; + + enc10->base.features = *enc_features; enc10->base.transmitter = init_data->transmitter; diff --git a/drivers/gpu/drm/amd/display/dc/dcn35/dcn35_dio_link_encoder.c b/drivers/gpu/drm/amd/display/dc/dcn35/dcn35_dio_link_encoder.c index 81e349d5835b..da94e5309fba 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn35/dcn35_dio_link_encoder.c +++ b/drivers/gpu/drm/amd/display/dc/dcn35/dcn35_dio_link_encoder.c @@ -184,6 +184,8 @@ void dcn35_link_encoder_construct( enc10->base.hpd_source = init_data->hpd_source; enc10->base.connector = init_data->connector; + if (enc10->base.connector.id == CONNECTOR_ID_USBC) + enc10->base.features.flags.bits.DP_IS_USB_C = 1; enc10->base.preferred_engine = ENGINE_ID_UNKNOWN; @@ -238,8 +240,6 @@ void dcn35_link_encoder_construct( } enc10->base.features.flags.bits.HDMI_6GB_EN = 1; - if (enc10->base.connector.id == CONNECTOR_ID_USBC) - enc10->base.features.flags.bits.DP_IS_USB_C = 1; if (bp_funcs->get_connector_speed_cap_info) result = bp_funcs->get_connector_speed_cap_info(enc10->base.ctx->dc_bios, -- cgit v1.2.3 From d111855ab7ffffc552f6a475259dc392f2319b6d Mon Sep 17 00:00:00 2001 From: Sven Schnelle Date: Mon, 15 Apr 2024 07:52:13 +0200 Subject: s390/mm: Fix NULL pointer dereference The recently added check to figure out if a fault happened on gmap ASCE dereferences the gmap pointer in lowcore without checking that it is not NULL. For all non-KVM processes the pointer is NULL, so that some value from lowcore will be read. With the current layouts of struct gmap and struct lowcore the read value (aka ASCE) is zero, so that this doesn't lead to any observable bug; at least currently. Fix this by adding the missing NULL pointer check. Fixes: 64c3431808bd ("s390/entry: compare gmap asce to determine guest/host fault") Signed-off-by: Sven Schnelle Reviewed-by: Claudio Imbrenda Reviewed-by: Heiko Carstens Signed-off-by: Alexander Gordeev --- arch/s390/kernel/entry.S | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/arch/s390/kernel/entry.S b/arch/s390/kernel/entry.S index 3dc85638bc63..6a1e0fbbaa15 100644 --- a/arch/s390/kernel/entry.S +++ b/arch/s390/kernel/entry.S @@ -340,7 +340,8 @@ SYM_CODE_START(pgm_check_handler) mvc __PT_LAST_BREAK(8,%r11),__LC_PGM_LAST_BREAK stctg %c1,%c1,__PT_CR1(%r11) #if IS_ENABLED(CONFIG_KVM) - lg %r12,__LC_GMAP + ltg %r12,__LC_GMAP + jz 5f clc __GMAP_ASCE(8,%r12), __PT_CR1(%r11) jne 5f BPENTER __SF_SIE_FLAGS(%r10),_TIF_ISOLATE_BP_GUEST -- cgit v1.2.3 From efefd4f00c967d00ad7abe092554ffbb70c1a793 Mon Sep 17 00:00:00 2001 From: Pablo Neira Ayuso Date: Wed, 17 Apr 2024 17:43:01 +0200 Subject: netfilter: nf_tables: missing iterator type in lookup walk Add missing decorator type to lookup expression and tighten WARN_ON_ONCE check in pipapo to spot earlier that this is unset. Fixes: 29b359cf6d95 ("netfilter: nft_set_pipapo: walk over current view on netlink dump") Signed-off-by: Pablo Neira Ayuso --- net/netfilter/nft_lookup.c | 1 + net/netfilter/nft_set_pipapo.c | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/net/netfilter/nft_lookup.c b/net/netfilter/nft_lookup.c index a0055f510e31..b314ca728a29 100644 --- a/net/netfilter/nft_lookup.c +++ b/net/netfilter/nft_lookup.c @@ -216,6 +216,7 @@ static int nft_lookup_validate(const struct nft_ctx *ctx, return 0; iter.genmask = nft_genmask_next(ctx->net); + iter.type = NFT_ITER_UPDATE; iter.skip = 0; iter.count = 0; iter.err = 0; diff --git a/net/netfilter/nft_set_pipapo.c b/net/netfilter/nft_set_pipapo.c index eeaf05ffba95..0f903d18bbea 100644 --- a/net/netfilter/nft_set_pipapo.c +++ b/net/netfilter/nft_set_pipapo.c @@ -2123,7 +2123,8 @@ static void nft_pipapo_walk(const struct nft_ctx *ctx, struct nft_set *set, const struct nft_pipapo_field *f; unsigned int i, r; - WARN_ON_ONCE(iter->type == NFT_ITER_UNSPEC); + WARN_ON_ONCE(iter->type != NFT_ITER_READ && + iter->type != NFT_ITER_UPDATE); rcu_read_lock(); if (iter->type == NFT_ITER_READ) -- cgit v1.2.3 From e79b47a8615d42c68aaeb68971593333667382ed Mon Sep 17 00:00:00 2001 From: Pablo Neira Ayuso Date: Wed, 17 Apr 2024 17:43:11 +0200 Subject: netfilter: nf_tables: restore set elements when delete set fails From abort path, nft_mapelem_activate() needs to restore refcounters to the original state. Currently, it uses the set->ops->walk() to iterate over these set elements. The existing set iterator skips inactive elements in the next generation, this does not work from the abort path to restore the original state since it has to skip active elements instead (not inactive ones). This patch moves the check for inactive elements to the set iterator callback, then it reverses the logic for the .activate case which needs to skip active elements. Toggle next generation bit for elements when delete set command is invoked and call nft_clear() from .activate (abort) path to restore the next generation bit. The splat below shows an object in mappings memleak: [43929.457523] ------------[ cut here ]------------ [43929.457532] WARNING: CPU: 0 PID: 1139 at include/net/netfilter/nf_tables.h:1237 nft_setelem_data_deactivate+0xe4/0xf0 [nf_tables] [...] [43929.458014] RIP: 0010:nft_setelem_data_deactivate+0xe4/0xf0 [nf_tables] [43929.458076] Code: 83 f8 01 77 ab 49 8d 7c 24 08 e8 37 5e d0 de 49 8b 6c 24 08 48 8d 7d 50 e8 e9 5c d0 de 8b 45 50 8d 50 ff 89 55 50 85 c0 75 86 <0f> 0b eb 82 0f 0b eb b3 0f 1f 40 00 90 90 90 90 90 90 90 90 90 90 [43929.458081] RSP: 0018:ffff888140f9f4b0 EFLAGS: 00010246 [43929.458086] RAX: 0000000000000000 RBX: ffff8881434f5288 RCX: dffffc0000000000 [43929.458090] RDX: 00000000ffffffff RSI: ffffffffa26d28a7 RDI: ffff88810ecc9550 [43929.458093] RBP: ffff88810ecc9500 R08: 0000000000000001 R09: ffffed10281f3e8f [43929.458096] R10: 0000000000000003 R11: ffff0000ffff0000 R12: ffff8881434f52a0 [43929.458100] R13: ffff888140f9f5f4 R14: ffff888151c7a800 R15: 0000000000000002 [43929.458103] FS: 00007f0c687c4740(0000) GS:ffff888390800000(0000) knlGS:0000000000000000 [43929.458107] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 [43929.458111] CR2: 00007f58dbe5b008 CR3: 0000000123602005 CR4: 00000000001706f0 [43929.458114] Call Trace: [43929.458118] [43929.458121] ? __warn+0x9f/0x1a0 [43929.458127] ? nft_setelem_data_deactivate+0xe4/0xf0 [nf_tables] [43929.458188] ? report_bug+0x1b1/0x1e0 [43929.458196] ? handle_bug+0x3c/0x70 [43929.458200] ? exc_invalid_op+0x17/0x40 [43929.458211] ? nft_setelem_data_deactivate+0xd7/0xf0 [nf_tables] [43929.458271] ? nft_setelem_data_deactivate+0xe4/0xf0 [nf_tables] [43929.458332] nft_mapelem_deactivate+0x24/0x30 [nf_tables] [43929.458392] nft_rhash_walk+0xdd/0x180 [nf_tables] [43929.458453] ? __pfx_nft_rhash_walk+0x10/0x10 [nf_tables] [43929.458512] ? rb_insert_color+0x2e/0x280 [43929.458520] nft_map_deactivate+0xdc/0x1e0 [nf_tables] [43929.458582] ? __pfx_nft_map_deactivate+0x10/0x10 [nf_tables] [43929.458642] ? __pfx_nft_mapelem_deactivate+0x10/0x10 [nf_tables] [43929.458701] ? __rcu_read_unlock+0x46/0x70 [43929.458709] nft_delset+0xff/0x110 [nf_tables] [43929.458769] nft_flush_table+0x16f/0x460 [nf_tables] [43929.458830] nf_tables_deltable+0x501/0x580 [nf_tables] Fixes: 628bd3e49cba ("netfilter: nf_tables: drop map element references from preparation phase") Signed-off-by: Pablo Neira Ayuso --- net/netfilter/nf_tables_api.c | 44 ++++++++++++++++++++++++++++++++++++++---- net/netfilter/nft_set_bitmap.c | 4 +--- net/netfilter/nft_set_hash.c | 8 ++------ net/netfilter/nft_set_pipapo.c | 5 +---- net/netfilter/nft_set_rbtree.c | 4 +--- 5 files changed, 45 insertions(+), 20 deletions(-) diff --git a/net/netfilter/nf_tables_api.c b/net/netfilter/nf_tables_api.c index a7a34db62ea9..d0c09f899e80 100644 --- a/net/netfilter/nf_tables_api.c +++ b/net/netfilter/nf_tables_api.c @@ -594,6 +594,12 @@ static int nft_mapelem_deactivate(const struct nft_ctx *ctx, const struct nft_set_iter *iter, struct nft_elem_priv *elem_priv) { + struct nft_set_ext *ext = nft_set_elem_ext(set, elem_priv); + + if (!nft_set_elem_active(ext, iter->genmask)) + return 0; + + nft_set_elem_change_active(ctx->net, set, ext); nft_setelem_data_deactivate(ctx->net, set, elem_priv); return 0; @@ -617,6 +623,7 @@ static void nft_map_catchall_deactivate(const struct nft_ctx *ctx, if (!nft_set_elem_active(ext, genmask)) continue; + nft_set_elem_change_active(ctx->net, set, ext); nft_setelem_data_deactivate(ctx->net, set, catchall->elem); break; } @@ -3880,6 +3887,9 @@ int nft_setelem_validate(const struct nft_ctx *ctx, struct nft_set *set, const struct nft_data *data; int err; + if (!nft_set_elem_active(ext, iter->genmask)) + return 0; + if (nft_set_ext_exists(ext, NFT_SET_EXT_FLAGS) && *nft_set_ext_flags(ext) & NFT_SET_ELEM_INTERVAL_END) return 0; @@ -3903,17 +3913,20 @@ int nft_setelem_validate(const struct nft_ctx *ctx, struct nft_set *set, int nft_set_catchall_validate(const struct nft_ctx *ctx, struct nft_set *set) { - u8 genmask = nft_genmask_next(ctx->net); + struct nft_set_iter dummy_iter = { + .genmask = nft_genmask_next(ctx->net), + }; struct nft_set_elem_catchall *catchall; + struct nft_set_ext *ext; int ret = 0; list_for_each_entry_rcu(catchall, &set->catchall_list, list) { ext = nft_set_elem_ext(set, catchall->elem); - if (!nft_set_elem_active(ext, genmask)) + if (!nft_set_elem_active(ext, dummy_iter.genmask)) continue; - ret = nft_setelem_validate(ctx, set, NULL, catchall->elem); + ret = nft_setelem_validate(ctx, set, &dummy_iter, catchall->elem); if (ret < 0) return ret; } @@ -5402,6 +5415,11 @@ static int nf_tables_bind_check_setelem(const struct nft_ctx *ctx, const struct nft_set_iter *iter, struct nft_elem_priv *elem_priv) { + const struct nft_set_ext *ext = nft_set_elem_ext(set, elem_priv); + + if (!nft_set_elem_active(ext, iter->genmask)) + return 0; + return nft_setelem_data_validate(ctx, set, elem_priv); } @@ -5494,6 +5512,13 @@ static int nft_mapelem_activate(const struct nft_ctx *ctx, const struct nft_set_iter *iter, struct nft_elem_priv *elem_priv) { + struct nft_set_ext *ext = nft_set_elem_ext(set, elem_priv); + + /* called from abort path, reverse check to undo changes. */ + if (nft_set_elem_active(ext, iter->genmask)) + return 0; + + nft_clear(ctx->net, ext); nft_setelem_data_activate(ctx->net, set, elem_priv); return 0; @@ -5511,6 +5536,7 @@ static void nft_map_catchall_activate(const struct nft_ctx *ctx, if (!nft_set_elem_active(ext, genmask)) continue; + nft_clear(ctx->net, ext); nft_setelem_data_activate(ctx->net, set, catchall->elem); break; } @@ -5785,6 +5811,9 @@ static int nf_tables_dump_setelem(const struct nft_ctx *ctx, const struct nft_set_ext *ext = nft_set_elem_ext(set, elem_priv); struct nft_set_dump_args *args; + if (!nft_set_elem_active(ext, iter->genmask)) + return 0; + if (nft_set_elem_expired(ext) || nft_set_elem_is_dead(ext)) return 0; @@ -6635,7 +6664,7 @@ static void nft_setelem_activate(struct net *net, struct nft_set *set, struct nft_set_ext *ext = nft_set_elem_ext(set, elem_priv); if (nft_setelem_is_catchall(set, elem_priv)) { - nft_set_elem_change_active(net, set, ext); + nft_clear(net, ext); } else { set->ops->activate(net, set, elem_priv); } @@ -7317,8 +7346,12 @@ static int nft_setelem_flush(const struct nft_ctx *ctx, const struct nft_set_iter *iter, struct nft_elem_priv *elem_priv) { + const struct nft_set_ext *ext = nft_set_elem_ext(set, elem_priv); struct nft_trans *trans; + if (!nft_set_elem_active(ext, iter->genmask)) + return 0; + trans = nft_trans_alloc_gfp(ctx, NFT_MSG_DELSETELEM, sizeof(struct nft_trans_elem), GFP_ATOMIC); if (!trans) @@ -10800,6 +10833,9 @@ static int nf_tables_loop_check_setelem(const struct nft_ctx *ctx, { const struct nft_set_ext *ext = nft_set_elem_ext(set, elem_priv); + if (!nft_set_elem_active(ext, iter->genmask)) + return 0; + if (nft_set_ext_exists(ext, NFT_SET_EXT_FLAGS) && *nft_set_ext_flags(ext) & NFT_SET_ELEM_INTERVAL_END) return 0; diff --git a/net/netfilter/nft_set_bitmap.c b/net/netfilter/nft_set_bitmap.c index 32df7a16835d..1caa04619dc6 100644 --- a/net/netfilter/nft_set_bitmap.c +++ b/net/netfilter/nft_set_bitmap.c @@ -172,7 +172,7 @@ static void nft_bitmap_activate(const struct net *net, nft_bitmap_location(set, nft_set_ext_key(&be->ext), &idx, &off); /* Enter 11 state. */ priv->bitmap[idx] |= (genmask << off); - nft_set_elem_change_active(net, set, &be->ext); + nft_clear(net, &be->ext); } static void nft_bitmap_flush(const struct net *net, @@ -222,8 +222,6 @@ static void nft_bitmap_walk(const struct nft_ctx *ctx, list_for_each_entry_rcu(be, &priv->list, head) { if (iter->count < iter->skip) goto cont; - if (!nft_set_elem_active(&be->ext, iter->genmask)) - goto cont; iter->err = iter->fn(ctx, set, iter, &be->priv); diff --git a/net/netfilter/nft_set_hash.c b/net/netfilter/nft_set_hash.c index 6968a3b34236..daa56dda737a 100644 --- a/net/netfilter/nft_set_hash.c +++ b/net/netfilter/nft_set_hash.c @@ -199,7 +199,7 @@ static void nft_rhash_activate(const struct net *net, const struct nft_set *set, { struct nft_rhash_elem *he = nft_elem_priv_cast(elem_priv); - nft_set_elem_change_active(net, set, &he->ext); + nft_clear(net, &he->ext); } static void nft_rhash_flush(const struct net *net, @@ -286,8 +286,6 @@ static void nft_rhash_walk(const struct nft_ctx *ctx, struct nft_set *set, if (iter->count < iter->skip) goto cont; - if (!nft_set_elem_active(&he->ext, iter->genmask)) - goto cont; iter->err = iter->fn(ctx, set, iter, &he->priv); if (iter->err < 0) @@ -599,7 +597,7 @@ static void nft_hash_activate(const struct net *net, const struct nft_set *set, { struct nft_hash_elem *he = nft_elem_priv_cast(elem_priv); - nft_set_elem_change_active(net, set, &he->ext); + nft_clear(net, &he->ext); } static void nft_hash_flush(const struct net *net, @@ -652,8 +650,6 @@ static void nft_hash_walk(const struct nft_ctx *ctx, struct nft_set *set, hlist_for_each_entry_rcu(he, &priv->table[i], node) { if (iter->count < iter->skip) goto cont; - if (!nft_set_elem_active(&he->ext, iter->genmask)) - goto cont; iter->err = iter->fn(ctx, set, iter, &he->priv); if (iter->err < 0) diff --git a/net/netfilter/nft_set_pipapo.c b/net/netfilter/nft_set_pipapo.c index 0f903d18bbea..187138afac45 100644 --- a/net/netfilter/nft_set_pipapo.c +++ b/net/netfilter/nft_set_pipapo.c @@ -1847,7 +1847,7 @@ static void nft_pipapo_activate(const struct net *net, { struct nft_pipapo_elem *e = nft_elem_priv_cast(elem_priv); - nft_set_elem_change_active(net, set, &e->ext); + nft_clear(net, &e->ext); } /** @@ -2149,9 +2149,6 @@ static void nft_pipapo_walk(const struct nft_ctx *ctx, struct nft_set *set, e = f->mt[r].e; - if (!nft_set_elem_active(&e->ext, iter->genmask)) - goto cont; - iter->err = iter->fn(ctx, set, iter, &e->priv); if (iter->err < 0) goto out; diff --git a/net/netfilter/nft_set_rbtree.c b/net/netfilter/nft_set_rbtree.c index 9944fe479e53..b7ea21327549 100644 --- a/net/netfilter/nft_set_rbtree.c +++ b/net/netfilter/nft_set_rbtree.c @@ -532,7 +532,7 @@ static void nft_rbtree_activate(const struct net *net, { struct nft_rbtree_elem *rbe = nft_elem_priv_cast(elem_priv); - nft_set_elem_change_active(net, set, &rbe->ext); + nft_clear(net, &rbe->ext); } static void nft_rbtree_flush(const struct net *net, @@ -600,8 +600,6 @@ static void nft_rbtree_walk(const struct nft_ctx *ctx, if (iter->count < iter->skip) goto cont; - if (!nft_set_elem_active(&rbe->ext, iter->genmask)) - goto cont; iter->err = iter->fn(ctx, set, iter, &rbe->priv); if (iter->err < 0) { -- cgit v1.2.3 From 6fef2d4c00b5b8561ad68dd2b68173f5c6af1e75 Mon Sep 17 00:00:00 2001 From: xinhui pan Date: Thu, 11 Apr 2024 11:11:38 +0800 Subject: drm/amdgpu: validate the parameters of bo mapping operations more clearly MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Verify the parameters of amdgpu_vm_bo_(map/replace_map/clearing_mappings) in one common place. Fixes: dc54d3d1744d ("drm/amdgpu: implement AMDGPU_VA_OP_CLEAR v2") Cc: stable@vger.kernel.org Reported-by: Vlad Stolyarov Suggested-by: Christian König Signed-off-by: xinhui pan Reviewed-by: Christian König Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c | 72 ++++++++++++++++++++++------------ 1 file changed, 46 insertions(+), 26 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c index 4299ce386322..94089069c9ad 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c @@ -1613,6 +1613,37 @@ static void amdgpu_vm_bo_insert_map(struct amdgpu_device *adev, trace_amdgpu_vm_bo_map(bo_va, mapping); } +/* Validate operation parameters to prevent potential abuse */ +static int amdgpu_vm_verify_parameters(struct amdgpu_device *adev, + struct amdgpu_bo *bo, + uint64_t saddr, + uint64_t offset, + uint64_t size) +{ + uint64_t tmp, lpfn; + + if (saddr & AMDGPU_GPU_PAGE_MASK + || offset & AMDGPU_GPU_PAGE_MASK + || size & AMDGPU_GPU_PAGE_MASK) + return -EINVAL; + + if (check_add_overflow(saddr, size, &tmp) + || check_add_overflow(offset, size, &tmp) + || size == 0 /* which also leads to end < begin */) + return -EINVAL; + + /* make sure object fit at this offset */ + if (bo && offset + size > amdgpu_bo_size(bo)) + return -EINVAL; + + /* Ensure last pfn not exceed max_pfn */ + lpfn = (saddr + size - 1) >> AMDGPU_GPU_PAGE_SHIFT; + if (lpfn >= adev->vm_manager.max_pfn) + return -EINVAL; + + return 0; +} + /** * amdgpu_vm_bo_map - map bo inside a vm * @@ -1639,21 +1670,14 @@ int amdgpu_vm_bo_map(struct amdgpu_device *adev, struct amdgpu_bo *bo = bo_va->base.bo; struct amdgpu_vm *vm = bo_va->base.vm; uint64_t eaddr; + int r; - /* validate the parameters */ - if (saddr & ~PAGE_MASK || offset & ~PAGE_MASK || size & ~PAGE_MASK) - return -EINVAL; - if (saddr + size <= saddr || offset + size <= offset) - return -EINVAL; - - /* make sure object fit at this offset */ - eaddr = saddr + size - 1; - if ((bo && offset + size > amdgpu_bo_size(bo)) || - (eaddr >= adev->vm_manager.max_pfn << AMDGPU_GPU_PAGE_SHIFT)) - return -EINVAL; + r = amdgpu_vm_verify_parameters(adev, bo, saddr, offset, size); + if (r) + return r; saddr /= AMDGPU_GPU_PAGE_SIZE; - eaddr /= AMDGPU_GPU_PAGE_SIZE; + eaddr = saddr + (size - 1) / AMDGPU_GPU_PAGE_SIZE; tmp = amdgpu_vm_it_iter_first(&vm->va, saddr, eaddr); if (tmp) { @@ -1706,17 +1730,9 @@ int amdgpu_vm_bo_replace_map(struct amdgpu_device *adev, uint64_t eaddr; int r; - /* validate the parameters */ - if (saddr & ~PAGE_MASK || offset & ~PAGE_MASK || size & ~PAGE_MASK) - return -EINVAL; - if (saddr + size <= saddr || offset + size <= offset) - return -EINVAL; - - /* make sure object fit at this offset */ - eaddr = saddr + size - 1; - if ((bo && offset + size > amdgpu_bo_size(bo)) || - (eaddr >= adev->vm_manager.max_pfn << AMDGPU_GPU_PAGE_SHIFT)) - return -EINVAL; + r = amdgpu_vm_verify_parameters(adev, bo, saddr, offset, size); + if (r) + return r; /* Allocate all the needed memory */ mapping = kmalloc(sizeof(*mapping), GFP_KERNEL); @@ -1730,7 +1746,7 @@ int amdgpu_vm_bo_replace_map(struct amdgpu_device *adev, } saddr /= AMDGPU_GPU_PAGE_SIZE; - eaddr /= AMDGPU_GPU_PAGE_SIZE; + eaddr = saddr + (size - 1) / AMDGPU_GPU_PAGE_SIZE; mapping->start = saddr; mapping->last = eaddr; @@ -1817,10 +1833,14 @@ int amdgpu_vm_bo_clear_mappings(struct amdgpu_device *adev, struct amdgpu_bo_va_mapping *before, *after, *tmp, *next; LIST_HEAD(removed); uint64_t eaddr; + int r; + + r = amdgpu_vm_verify_parameters(adev, NULL, saddr, 0, size); + if (r) + return r; - eaddr = saddr + size - 1; saddr /= AMDGPU_GPU_PAGE_SIZE; - eaddr /= AMDGPU_GPU_PAGE_SIZE; + eaddr = saddr + (size - 1) / AMDGPU_GPU_PAGE_SIZE; /* Allocate all the needed memory */ before = kzalloc(sizeof(*before), GFP_KERNEL); -- cgit v1.2.3 From a6ff969fe9cbf369e3cd0ac54261fec1122682ec Mon Sep 17 00:00:00 2001 From: Christian König Date: Thu, 4 Apr 2024 16:25:40 +0200 Subject: drm/amdgpu: fix visible VRAM handling during faults MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When we removed the hacky start code check we actually didn't took into account that *all* VRAM pages needs to be CPU accessible. Clean up the code and unify the handling into a single helper which checks if the whole resource is CPU accessible. The only place where a partial check would make sense is during eviction, but that is neglitible. Signed-off-by: Christian König Fixes: aed01a68047b ("drm/amdgpu: Remove TTM resource->start visible VRAM condition v2") Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher CC: stable@vger.kernel.org --- drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c | 2 +- drivers/gpu/drm/amd/amdgpu/amdgpu_object.c | 22 +++++------ drivers/gpu/drm/amd/amdgpu/amdgpu_object.h | 22 ----------- drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c | 61 +++++++++++++++++++----------- drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.h | 3 ++ 5 files changed, 53 insertions(+), 57 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c index 0a4b09709cfb..ec888fc6ead8 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c @@ -819,7 +819,7 @@ retry: p->bytes_moved += ctx.bytes_moved; if (!amdgpu_gmc_vram_full_visible(&adev->gmc) && - amdgpu_bo_in_cpu_visible_vram(bo)) + amdgpu_res_cpu_visible(adev, bo->tbo.resource)) p->bytes_moved_vis += ctx.bytes_moved; if (unlikely(r == -ENOMEM) && domain != bo->allowed_domains) { diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c index 010b0cb7693c..2099159a693f 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c @@ -617,8 +617,7 @@ int amdgpu_bo_create(struct amdgpu_device *adev, return r; if (!amdgpu_gmc_vram_full_visible(&adev->gmc) && - bo->tbo.resource->mem_type == TTM_PL_VRAM && - amdgpu_bo_in_cpu_visible_vram(bo)) + amdgpu_res_cpu_visible(adev, bo->tbo.resource)) amdgpu_cs_report_moved_bytes(adev, ctx.bytes_moved, ctx.bytes_moved); else @@ -1272,23 +1271,25 @@ void amdgpu_bo_move_notify(struct ttm_buffer_object *bo, bool evict) void amdgpu_bo_get_memory(struct amdgpu_bo *bo, struct amdgpu_mem_stats *stats) { + struct amdgpu_device *adev = amdgpu_ttm_adev(bo->tbo.bdev); + struct ttm_resource *res = bo->tbo.resource; uint64_t size = amdgpu_bo_size(bo); struct drm_gem_object *obj; unsigned int domain; bool shared; /* Abort if the BO doesn't currently have a backing store */ - if (!bo->tbo.resource) + if (!res) return; obj = &bo->tbo.base; shared = drm_gem_object_is_shared_for_memory_stats(obj); - domain = amdgpu_mem_type_to_domain(bo->tbo.resource->mem_type); + domain = amdgpu_mem_type_to_domain(res->mem_type); switch (domain) { case AMDGPU_GEM_DOMAIN_VRAM: stats->vram += size; - if (amdgpu_bo_in_cpu_visible_vram(bo)) + if (amdgpu_res_cpu_visible(adev, bo->tbo.resource)) stats->visible_vram += size; if (shared) stats->vram_shared += size; @@ -1389,10 +1390,7 @@ vm_fault_t amdgpu_bo_fault_reserve_notify(struct ttm_buffer_object *bo) /* Remember that this BO was accessed by the CPU */ abo->flags |= AMDGPU_GEM_CREATE_CPU_ACCESS_REQUIRED; - if (bo->resource->mem_type != TTM_PL_VRAM) - return 0; - - if (amdgpu_bo_in_cpu_visible_vram(abo)) + if (amdgpu_res_cpu_visible(adev, bo->resource)) return 0; /* Can't move a pinned BO to visible VRAM */ @@ -1415,7 +1413,7 @@ vm_fault_t amdgpu_bo_fault_reserve_notify(struct ttm_buffer_object *bo) /* this should never happen */ if (bo->resource->mem_type == TTM_PL_VRAM && - !amdgpu_bo_in_cpu_visible_vram(abo)) + !amdgpu_res_cpu_visible(adev, bo->resource)) return VM_FAULT_SIGBUS; ttm_bo_move_to_lru_tail_unlocked(bo); @@ -1579,6 +1577,7 @@ uint32_t amdgpu_bo_get_preferred_domain(struct amdgpu_device *adev, */ u64 amdgpu_bo_print_info(int id, struct amdgpu_bo *bo, struct seq_file *m) { + struct amdgpu_device *adev = amdgpu_ttm_adev(bo->tbo.bdev); struct dma_buf_attachment *attachment; struct dma_buf *dma_buf; const char *placement; @@ -1587,10 +1586,11 @@ u64 amdgpu_bo_print_info(int id, struct amdgpu_bo *bo, struct seq_file *m) if (dma_resv_trylock(bo->tbo.base.resv)) { unsigned int domain; + domain = amdgpu_mem_type_to_domain(bo->tbo.resource->mem_type); switch (domain) { case AMDGPU_GEM_DOMAIN_VRAM: - if (amdgpu_bo_in_cpu_visible_vram(bo)) + if (amdgpu_res_cpu_visible(adev, bo->tbo.resource)) placement = "VRAM VISIBLE"; else placement = "VRAM"; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_object.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_object.h index be679c42b0b8..fa03d9e4874c 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_object.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_object.h @@ -250,28 +250,6 @@ static inline u64 amdgpu_bo_mmap_offset(struct amdgpu_bo *bo) return drm_vma_node_offset_addr(&bo->tbo.base.vma_node); } -/** - * amdgpu_bo_in_cpu_visible_vram - check if BO is (partly) in visible VRAM - */ -static inline bool amdgpu_bo_in_cpu_visible_vram(struct amdgpu_bo *bo) -{ - struct amdgpu_device *adev = amdgpu_ttm_adev(bo->tbo.bdev); - struct amdgpu_res_cursor cursor; - - if (!bo->tbo.resource || bo->tbo.resource->mem_type != TTM_PL_VRAM) - return false; - - amdgpu_res_first(bo->tbo.resource, 0, amdgpu_bo_size(bo), &cursor); - while (cursor.remaining) { - if (cursor.start < adev->gmc.visible_vram_size) - return true; - - amdgpu_res_next(&cursor, cursor.size); - } - - return false; -} - /** * amdgpu_bo_explicit_sync - return whether the bo is explicitly synced */ diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c index 6417cb76ccd4..1d71729e3f6b 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c @@ -133,7 +133,7 @@ static void amdgpu_evict_flags(struct ttm_buffer_object *bo, } else if (!amdgpu_gmc_vram_full_visible(&adev->gmc) && !(abo->flags & AMDGPU_GEM_CREATE_CPU_ACCESS_REQUIRED) && - amdgpu_bo_in_cpu_visible_vram(abo)) { + amdgpu_res_cpu_visible(adev, bo->resource)) { /* Try evicting to the CPU inaccessible part of VRAM * first, but only set GTT as busy placement, so this @@ -403,40 +403,55 @@ error: return r; } -/* - * amdgpu_mem_visible - Check that memory can be accessed by ttm_bo_move_memcpy +/** + * amdgpu_res_cpu_visible - Check that resource can be accessed by CPU + * @adev: amdgpu device + * @res: the resource to check * - * Called by amdgpu_bo_move() + * Returns: true if the full resource is CPU visible, false otherwise. */ -static bool amdgpu_mem_visible(struct amdgpu_device *adev, - struct ttm_resource *mem) +bool amdgpu_res_cpu_visible(struct amdgpu_device *adev, + struct ttm_resource *res) { - u64 mem_size = (u64)mem->size; struct amdgpu_res_cursor cursor; - u64 end; - if (mem->mem_type == TTM_PL_SYSTEM || - mem->mem_type == TTM_PL_TT) + if (!res) + return false; + + if (res->mem_type == TTM_PL_SYSTEM || res->mem_type == TTM_PL_TT || + res->mem_type == AMDGPU_PL_PREEMPT) return true; - if (mem->mem_type != TTM_PL_VRAM) + + if (res->mem_type != TTM_PL_VRAM) return false; - amdgpu_res_first(mem, 0, mem_size, &cursor); - end = cursor.start + cursor.size; + amdgpu_res_first(res, 0, res->size, &cursor); while (cursor.remaining) { + if ((cursor.start + cursor.size) >= adev->gmc.visible_vram_size) + return false; amdgpu_res_next(&cursor, cursor.size); + } - if (!cursor.remaining) - break; + return true; +} - /* ttm_resource_ioremap only supports contiguous memory */ - if (end != cursor.start) - return false; +/* + * amdgpu_res_copyable - Check that memory can be accessed by ttm_bo_move_memcpy + * + * Called by amdgpu_bo_move() + */ +static bool amdgpu_res_copyable(struct amdgpu_device *adev, + struct ttm_resource *mem) +{ + if (!amdgpu_res_cpu_visible(adev, mem)) + return false; - end = cursor.start + cursor.size; - } + /* ttm_resource_ioremap only supports contiguous memory */ + if (mem->mem_type == TTM_PL_VRAM && + !(mem->placement & TTM_PL_FLAG_CONTIGUOUS)) + return false; - return end <= adev->gmc.visible_vram_size; + return true; } /* @@ -529,8 +544,8 @@ static int amdgpu_bo_move(struct ttm_buffer_object *bo, bool evict, if (r) { /* Check that all memory is CPU accessible */ - if (!amdgpu_mem_visible(adev, old_mem) || - !amdgpu_mem_visible(adev, new_mem)) { + if (!amdgpu_res_copyable(adev, old_mem) || + !amdgpu_res_copyable(adev, new_mem)) { pr_err("Move buffer fallback to memcpy unavailable\n"); return r; } diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.h index 65ec82141a8e..32cf6b6f6efd 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.h @@ -139,6 +139,9 @@ int amdgpu_vram_mgr_reserve_range(struct amdgpu_vram_mgr *mgr, int amdgpu_vram_mgr_query_page_status(struct amdgpu_vram_mgr *mgr, uint64_t start); +bool amdgpu_res_cpu_visible(struct amdgpu_device *adev, + struct ttm_resource *res); + int amdgpu_ttm_init(struct amdgpu_device *adev); void amdgpu_ttm_fini(struct amdgpu_device *adev); void amdgpu_ttm_set_buffer_funcs_status(struct amdgpu_device *adev, -- cgit v1.2.3 From 0ba753bc7e79e49556e81b0d09b2de1aa558553b Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Sun, 14 Apr 2024 22:06:08 -0400 Subject: drm/radeon: make -fstrict-flex-arrays=3 happy MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The driver parses a union where the layout up through the first array is the same, however, the array has different sizes depending on the elements in the union. Be explicit to fix the UBSAN checker. Closes: https://gitlab.freedesktop.org/drm/amd/-/issues/3323 Fixes: df8fc4e934c1 ("kbuild: Enable -fstrict-flex-arrays=3") Acked-by: Christian König Reviewed-by: Kees Cook Signed-off-by: Alex Deucher Cc: Kees Cook --- drivers/gpu/drm/radeon/radeon_atombios.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/radeon/radeon_atombios.c b/drivers/gpu/drm/radeon/radeon_atombios.c index bb1f0a3371ab..10793a433bf5 100644 --- a/drivers/gpu/drm/radeon/radeon_atombios.c +++ b/drivers/gpu/drm/radeon/radeon_atombios.c @@ -923,8 +923,12 @@ bool radeon_get_atom_connector_info_from_supported_devices_table(struct max_device = ATOM_MAX_SUPPORTED_DEVICE_INFO; for (i = 0; i < max_device; i++) { - ATOM_CONNECTOR_INFO_I2C ci = - supported_devices->info.asConnInfo[i]; + ATOM_CONNECTOR_INFO_I2C ci; + + if (frev > 1) + ci = supported_devices->info_2d1.asConnInfo[i]; + else + ci = supported_devices->info.asConnInfo[i]; bios_connectors[i].valid = false; -- cgit v1.2.3 From 781d41fed19caf900c8405064676813dc9921d32 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Mon, 8 Apr 2024 13:30:15 -0400 Subject: drm/radeon: silence UBSAN warning (v3) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Convert a variable sized array from [1] to []. v2: fix up a few more. v3: integrate comments from Kees. Reviewed-by: Kees Cook Tested-by: Jeff Johnson (v2) Acked-by: Christian König (v1) Signed-off-by: Alex Deucher Cc: keescook@chromium.org --- drivers/gpu/drm/radeon/pptable.h | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/radeon/pptable.h b/drivers/gpu/drm/radeon/pptable.h index 94947229888b..b7f22597ee95 100644 --- a/drivers/gpu/drm/radeon/pptable.h +++ b/drivers/gpu/drm/radeon/pptable.h @@ -424,7 +424,7 @@ typedef struct _ATOM_PPLIB_SUMO_CLOCK_INFO{ typedef struct _ATOM_PPLIB_STATE_V2 { //number of valid dpm levels in this state; Driver uses it to calculate the whole - //size of the state: sizeof(ATOM_PPLIB_STATE_V2) + (ucNumDPMLevels - 1) * sizeof(UCHAR) + //size of the state: struct_size(ATOM_PPLIB_STATE_V2, clockInfoIndex, ucNumDPMLevels) UCHAR ucNumDPMLevels; //a index to the array of nonClockInfos @@ -432,14 +432,14 @@ typedef struct _ATOM_PPLIB_STATE_V2 /** * Driver will read the first ucNumDPMLevels in this array */ - UCHAR clockInfoIndex[1]; + UCHAR clockInfoIndex[] __counted_by(ucNumDPMLevels); } ATOM_PPLIB_STATE_V2; typedef struct _StateArray{ //how many states we have UCHAR ucNumEntries; - ATOM_PPLIB_STATE_V2 states[1]; + ATOM_PPLIB_STATE_V2 states[] __counted_by(ucNumEntries); }StateArray; @@ -450,7 +450,7 @@ typedef struct _ClockInfoArray{ //sizeof(ATOM_PPLIB_CLOCK_INFO) UCHAR ucEntrySize; - UCHAR clockInfo[1]; + UCHAR clockInfo[] __counted_by(ucNumEntries); }ClockInfoArray; typedef struct _NonClockInfoArray{ @@ -460,7 +460,7 @@ typedef struct _NonClockInfoArray{ //sizeof(ATOM_PPLIB_NONCLOCK_INFO) UCHAR ucEntrySize; - ATOM_PPLIB_NONCLOCK_INFO nonClockInfo[1]; + ATOM_PPLIB_NONCLOCK_INFO nonClockInfo[] __counted_by(ucNumEntries); }NonClockInfoArray; typedef struct _ATOM_PPLIB_Clock_Voltage_Dependency_Record -- cgit v1.2.3 From 6376306adde5b252ee7c73572e35d13fb13f6f18 Mon Sep 17 00:00:00 2001 From: "Borislav Petkov (AMD)" Date: Mon, 15 Apr 2024 18:15:43 +0200 Subject: x86/retpolines: Enable the default thunk warning only on relevant configs The using-default-thunk warning check makes sense only with configurations which actually enable the special return thunks. Otherwise, it fires on unrelated 32-bit configs on which the special return thunks won't even work (they're 64-bit only) and, what is more, those configs even go off into the weeds when booting in the alternatives patching code, leading to a dead machine. Fixes: 4461438a8405 ("x86/retpoline: Ensure default return thunk isn't used at runtime") Reported-by: Klara Modin Reported-by: Erhard Furtner Signed-off-by: Borislav Petkov (AMD) Tested-by: Klara Modin Link: https://lore.kernel.org/r/78e0d19c-b77a-4169-a80f-2eef91f4a1d6@gmail.com Link: https://lore.kernel.org/r/20240413024956.488d474e@yea --- arch/x86/lib/retpoline.S | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/arch/x86/lib/retpoline.S b/arch/x86/lib/retpoline.S index e674ccf720b9..391059b2c6fb 100644 --- a/arch/x86/lib/retpoline.S +++ b/arch/x86/lib/retpoline.S @@ -382,8 +382,15 @@ SYM_FUNC_END(call_depth_return_thunk) SYM_CODE_START(__x86_return_thunk) UNWIND_HINT_FUNC ANNOTATE_NOENDBR +#if defined(CONFIG_MITIGATION_UNRET_ENTRY) || \ + defined(CONFIG_MITIGATION_SRSO) || \ + defined(CONFIG_MITIGATION_CALL_DEPTH_TRACKING) ALTERNATIVE __stringify(ANNOTATE_UNRET_SAFE; ret), \ "jmp warn_thunk_thunk", X86_FEATURE_ALWAYS +#else + ANNOTATE_UNRET_SAFE + ret +#endif int3 SYM_CODE_END(__x86_return_thunk) EXPORT_SYMBOL(__x86_return_thunk) -- cgit v1.2.3 From 298b871cd55a607037ac8af0011b9fdeb54c1e65 Mon Sep 17 00:00:00 2001 From: "Masami Hiramatsu (Google)" Date: Tue, 16 Apr 2024 06:44:04 +0900 Subject: bootconfig: Fix the kerneldoc of _xbc_exit() Fix the kerneldoc of _xbc_exit() which is updated to have an @early argument and the function name is changed. Link: https://lore.kernel.org/all/171321744474.599864.13532445969528690358.stgit@devnote2/ Reported-by: kernel test robot Closes: https://lore.kernel.org/oe-kbuild-all/202404150036.kPJ3HEFA-lkp@intel.com/ Fixes: 89f9a1e876b5 ("bootconfig: use memblock_free_late to free xbc memory to buddy") Signed-off-by: Masami Hiramatsu (Google) --- lib/bootconfig.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/bootconfig.c b/lib/bootconfig.c index 8841554432d5..97f8911ea339 100644 --- a/lib/bootconfig.c +++ b/lib/bootconfig.c @@ -901,7 +901,8 @@ static int __init xbc_parse_tree(void) } /** - * xbc_exit() - Clean up all parsed bootconfig + * _xbc_exit() - Clean up all parsed bootconfig + * @early: Set true if this is called before budy system is initialized. * * This clears all data structures of parsed bootconfig on memory. * If you need to reuse xbc_init() with new boot config, you can -- cgit v1.2.3 From 69ffed4b62523bbc85511f150500329d28aba356 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Wed, 17 Apr 2024 17:19:13 +0300 Subject: gpiolib: swnode: Remove wrong header inclusion The flags in the software node properties are supposed to be the GPIO lookup flags, which are provided by gpio/machine.h, as the software nodes are the kernel internal thing and doesn't need to rely to any of ABIs. Fixes: e7f9ff5dc90c ("gpiolib: add support for software nodes") Signed-off-by: Andy Shevchenko Signed-off-by: Bartosz Golaszewski --- include/linux/gpio/property.h | 1 - 1 file changed, 1 deletion(-) diff --git a/include/linux/gpio/property.h b/include/linux/gpio/property.h index 6c75c8bd44a0..1a14e239221f 100644 --- a/include/linux/gpio/property.h +++ b/include/linux/gpio/property.h @@ -2,7 +2,6 @@ #ifndef __LINUX_GPIO_PROPERTY_H #define __LINUX_GPIO_PROPERTY_H -#include /* for GPIO_* flags */ #include #define PROPERTY_ENTRY_GPIO(_name_, _chip_node_, _idx_, _flags_) \ -- cgit v1.2.3 From fa845c73497f5e9d2f6f1cf48c3aad05c2fdacb8 Mon Sep 17 00:00:00 2001 From: Kent Overstreet Date: Tue, 16 Apr 2024 19:16:45 -0400 Subject: bcachefs: Fix bch2_dev_btree_bitmap_marked_sectors() shift Fixes: 27c15ed297cb bcachefs: bch_member.btree_allocated_bitmap Signed-off-by: Kent Overstreet --- fs/bcachefs/sb-members.c | 4 ++-- fs/bcachefs/sb-members.h | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/fs/bcachefs/sb-members.c b/fs/bcachefs/sb-members.c index 522a969345e5..5b8e621ac5eb 100644 --- a/fs/bcachefs/sb-members.c +++ b/fs/bcachefs/sb-members.c @@ -463,8 +463,8 @@ static void __bch2_dev_btree_bitmap_mark(struct bch_sb_field_members_v2 *mi, uns m->btree_bitmap_shift += resize; } - for (unsigned bit = sectors >> m->btree_bitmap_shift; - bit << m->btree_bitmap_shift < end; + for (unsigned bit = start >> m->btree_bitmap_shift; + (u64) bit << m->btree_bitmap_shift < end; bit++) bitmap |= BIT_ULL(bit); diff --git a/fs/bcachefs/sb-members.h b/fs/bcachefs/sb-members.h index b27c3e4467cf..5efa64eca5f8 100644 --- a/fs/bcachefs/sb-members.h +++ b/fs/bcachefs/sb-members.h @@ -235,11 +235,11 @@ static inline bool bch2_dev_btree_bitmap_marked_sectors(struct bch_dev *ca, u64 { u64 end = start + sectors; - if (end > 64 << ca->mi.btree_bitmap_shift) + if (end > 64ULL << ca->mi.btree_bitmap_shift) return false; - for (unsigned bit = sectors >> ca->mi.btree_bitmap_shift; - bit << ca->mi.btree_bitmap_shift < end; + for (unsigned bit = start >> ca->mi.btree_bitmap_shift; + (u64) bit << ca->mi.btree_bitmap_shift < end; bit++) if (!(ca->mi.btree_allocated_bitmap & BIT_ULL(bit))) return false; -- cgit v1.2.3 From 605109ff5e43addefdf92d1cfa2a693114430024 Mon Sep 17 00:00:00 2001 From: Kent Overstreet Date: Wed, 17 Apr 2024 02:04:23 -0400 Subject: bcachefs: KEY_TYPE_error is allowed for reflink KEY_TYPE_error is left behind when we have to delete all pointers in an extent in fsck; it allows errors to be correctly returned by reads later. Signed-off-by: Kent Overstreet --- fs/bcachefs/bcachefs_format.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/fs/bcachefs/bcachefs_format.h b/fs/bcachefs/bcachefs_format.h index 085987435a5e..f7fbfccd2b1e 100644 --- a/fs/bcachefs/bcachefs_format.h +++ b/fs/bcachefs/bcachefs_format.h @@ -1504,7 +1504,8 @@ enum btree_id_flags { BIT_ULL(KEY_TYPE_stripe)) \ x(reflink, 7, BTREE_ID_EXTENTS|BTREE_ID_DATA, \ BIT_ULL(KEY_TYPE_reflink_v)| \ - BIT_ULL(KEY_TYPE_indirect_inline_data)) \ + BIT_ULL(KEY_TYPE_indirect_inline_data)| \ + BIT_ULL(KEY_TYPE_error)) \ x(subvolumes, 8, 0, \ BIT_ULL(KEY_TYPE_subvolume)) \ x(snapshots, 9, 0, \ -- cgit v1.2.3 From 719aec84b106ba3bd3639eddb2be46c510ef683a Mon Sep 17 00:00:00 2001 From: Kent Overstreet Date: Wed, 17 Apr 2024 02:17:21 -0400 Subject: bcachefs: fix leak in bch2_gc_write_reflink_key Signed-off-by: Kent Overstreet --- fs/bcachefs/btree_gc.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/fs/bcachefs/btree_gc.c b/fs/bcachefs/btree_gc.c index ecbd9598f69f..791470b0c654 100644 --- a/fs/bcachefs/btree_gc.c +++ b/fs/bcachefs/btree_gc.c @@ -1587,7 +1587,7 @@ static int bch2_gc_write_reflink_key(struct btree_trans *trans, struct bkey_i *new = bch2_bkey_make_mut_noupdate(trans, k); ret = PTR_ERR_OR_ZERO(new); if (ret) - return ret; + goto out; if (!r->refcount) new->k.type = KEY_TYPE_deleted; @@ -1595,6 +1595,7 @@ static int bch2_gc_write_reflink_key(struct btree_trans *trans, *bkey_refcount(bkey_i_to_s(new)) = cpu_to_le64(r->refcount); ret = bch2_trans_update(trans, iter, new, 0); } +out: fsck_err: printbuf_exit(&buf); return ret; -- cgit v1.2.3 From 0389c09b2fb702ca7924ddf550ce0c8af708b8be Mon Sep 17 00:00:00 2001 From: Kent Overstreet Date: Wed, 17 Apr 2024 17:27:43 -0400 Subject: bcachefs: Fix bio alloc in check_extent_checksum() if the buffer is virtually mapped it won't be a single bvec Signed-off-by: Kent Overstreet --- fs/bcachefs/backpointers.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/bcachefs/backpointers.c b/fs/bcachefs/backpointers.c index fadb1078903d..a20044201002 100644 --- a/fs/bcachefs/backpointers.c +++ b/fs/bcachefs/backpointers.c @@ -470,7 +470,7 @@ found: goto err; } - bio = bio_alloc(ca->disk_sb.bdev, 1, REQ_OP_READ, GFP_KERNEL); + bio = bio_alloc(ca->disk_sb.bdev, buf_pages(data_buf, bytes), REQ_OP_READ, GFP_KERNEL); bio->bi_iter.bi_sector = p.ptr.offset; bch2_bio_map(bio, data_buf, bytes); ret = submit_bio_wait(bio); -- cgit v1.2.3 From e5a78fdec0114266d3c47df413d2d7955807fad9 Mon Sep 17 00:00:00 2001 From: David Sterba Date: Tue, 24 Jan 2023 20:44:38 +0100 Subject: btrfs: remove colon from messages with state The message format in syslog is usually made of two parts: prefix ":" message Various tools parse the prefix up to the first ":". When there's an additional status of a btrfs filesystem like [5.199782] BTRFS info (device nvme1n1p1: state M): use zstd compression, level 9 where 'M' is for remount, there's one more ":" that does not conform to the format. Remove it. Reviewed-by: Anand Jain Signed-off-by: David Sterba --- fs/btrfs/messages.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/btrfs/messages.c b/fs/btrfs/messages.c index c96dd66fd0f7..210d9c82e2ae 100644 --- a/fs/btrfs/messages.c +++ b/fs/btrfs/messages.c @@ -7,7 +7,7 @@ #ifdef CONFIG_PRINTK -#define STATE_STRING_PREFACE ": state " +#define STATE_STRING_PREFACE " state " #define STATE_STRING_BUF_LEN (sizeof(STATE_STRING_PREFACE) + BTRFS_FS_STATE_COUNT + 1) /* -- cgit v1.2.3 From 7192833c4e55b26e8f15ef58577867a1bc808036 Mon Sep 17 00:00:00 2001 From: Naohiro Aota Date: Tue, 9 Apr 2024 23:18:52 +0900 Subject: btrfs: scrub: run relocation repair when/only needed When btrfs scrub finds an error, it reads mirrors to find correct data. If all the errors are fixed, sctx->error_bitmap is cleared for the stripe range. However, in the zoned mode, it runs relocation to repair scrub errors when the bitmap is *not* empty, which is a flipped condition. Also, it runs the relocation even if the scrub is read-only. This was missed by a fix in commit 1f2030ff6e49 ("btrfs: scrub: respect the read-only flag during repair"). The repair is only necessary when there is a repaired sector and should be done on read-write scrub. So, tweak the condition for both regular and zoned case. Fixes: 54765392a1b9 ("btrfs: scrub: introduce helper to queue a stripe for scrub") Fixes: 1f2030ff6e49 ("btrfs: scrub: respect the read-only flag during repair") CC: stable@vger.kernel.org # 6.6+ Reviewed-by: Qu Wenruo Reviewed-by: Johannes Thumshirn Signed-off-by: Naohiro Aota Signed-off-by: David Sterba --- fs/btrfs/scrub.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/fs/btrfs/scrub.c b/fs/btrfs/scrub.c index fa25004ab04e..4b22cfe9a98c 100644 --- a/fs/btrfs/scrub.c +++ b/fs/btrfs/scrub.c @@ -1012,6 +1012,7 @@ static void scrub_stripe_read_repair_worker(struct work_struct *work) struct btrfs_fs_info *fs_info = sctx->fs_info; int num_copies = btrfs_num_copies(fs_info, stripe->bg->start, stripe->bg->length); + unsigned long repaired; int mirror; int i; @@ -1078,16 +1079,15 @@ out: * Submit the repaired sectors. For zoned case, we cannot do repair * in-place, but queue the bg to be relocated. */ - if (btrfs_is_zoned(fs_info)) { - if (!bitmap_empty(&stripe->error_bitmap, stripe->nr_sectors)) + bitmap_andnot(&repaired, &stripe->init_error_bitmap, &stripe->error_bitmap, + stripe->nr_sectors); + if (!sctx->readonly && !bitmap_empty(&repaired, stripe->nr_sectors)) { + if (btrfs_is_zoned(fs_info)) { btrfs_repair_one_zone(fs_info, sctx->stripes[0].bg->start); - } else if (!sctx->readonly) { - unsigned long repaired; - - bitmap_andnot(&repaired, &stripe->init_error_bitmap, - &stripe->error_bitmap, stripe->nr_sectors); - scrub_write_sectors(sctx, stripe, repaired, false); - wait_scrub_stripe_io(stripe); + } else { + scrub_write_sectors(sctx, stripe, repaired, false); + wait_scrub_stripe_io(stripe); + } } scrub_stripe_report_errors(sctx, stripe); -- cgit v1.2.3 From 131a821a243f89be312ced9e62ccc37b2cf3846c Mon Sep 17 00:00:00 2001 From: Sweet Tea Dorminy Date: Sat, 6 Apr 2024 04:45:02 -0400 Subject: btrfs: fallback if compressed IO fails for ENOSPC In commit b4ccace878f4 ("btrfs: refactor submit_compressed_extents()"), if an async extent compressed but failed to find enough space, we changed from falling back to an uncompressed write to just failing the write altogether. The principle was that if there's not enough space to write the compressed version of the data, there can't possibly be enough space to write the larger, uncompressed version of the data. However, this isn't necessarily true: due to fragmentation, there could be enough discontiguous free blocks to write the uncompressed version, but not enough contiguous free blocks to write the smaller but unsplittable compressed version. This has occurred to an internal workload which relied on write()'s return value indicating there was space. While rare, it has happened a few times. Thus, in order to prevent early ENOSPC, re-add a fallback to uncompressed writing. Fixes: b4ccace878f4 ("btrfs: refactor submit_compressed_extents()") CC: stable@vger.kernel.org # 6.1+ Reviewed-by: Qu Wenruo Co-developed-by: Neal Gompa Signed-off-by: Neal Gompa Signed-off-by: Sweet Tea Dorminy Reviewed-by: David Sterba Signed-off-by: David Sterba --- fs/btrfs/inode.c | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index c65fe5de4022..7fed887e700c 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c @@ -1145,13 +1145,13 @@ static void submit_one_async_extent(struct async_chunk *async_chunk, 0, *alloc_hint, &ins, 1, 1); if (ret) { /* - * Here we used to try again by going back to non-compressed - * path for ENOSPC. But we can't reserve space even for - * compressed size, how could it work for uncompressed size - * which requires larger size? So here we directly go error - * path. + * We can't reserve contiguous space for the compressed size. + * Unlikely, but it's possible that we could have enough + * non-contiguous space for the uncompressed size instead. So + * fall back to uncompressed. */ - goto out_free; + submit_uncompressed_range(inode, async_extent, locked_page); + goto done; } /* Here we're doing allocation and writeback of the compressed pages */ @@ -1203,7 +1203,6 @@ done: out_free_reserve: btrfs_dec_block_group_reservations(fs_info, ins.objectid); btrfs_free_reserved_extent(fs_info, ins.objectid, ins.offset, 1); -out_free: mapping_set_error(inode->vfs_inode.i_mapping, -EIO); extent_clear_unlock_delalloc(inode, start, end, NULL, EXTENT_LOCKED | EXTENT_DELALLOC | -- cgit v1.2.3 From 86a1471d7cde792941109b93b558b5dc078b9ee9 Mon Sep 17 00:00:00 2001 From: Pablo Neira Ayuso Date: Wed, 17 Apr 2024 17:43:21 +0200 Subject: netfilter: nf_tables: fix memleak in map from abort path The delete set command does not rely on the transaction object for element removal, therefore, a combination of delete element + delete set from the abort path could result in restoring twice the refcount of the mapping. Check for inactive element in the next generation for the delete element command in the abort path, skip restoring state if next generation bit has been already cleared. This is similar to the activate logic using the set walk iterator. [ 6170.286929] ------------[ cut here ]------------ [ 6170.286939] WARNING: CPU: 6 PID: 790302 at net/netfilter/nf_tables_api.c:2086 nf_tables_chain_destroy+0x1f7/0x220 [nf_tables] [ 6170.287071] Modules linked in: [...] [ 6170.287633] CPU: 6 PID: 790302 Comm: kworker/6:2 Not tainted 6.9.0-rc3+ #365 [ 6170.287768] RIP: 0010:nf_tables_chain_destroy+0x1f7/0x220 [nf_tables] [ 6170.287886] Code: df 48 8d 7d 58 e8 69 2e 3b df 48 8b 7d 58 e8 80 1b 37 df 48 8d 7d 68 e8 57 2e 3b df 48 8b 7d 68 e8 6e 1b 37 df 48 89 ef eb c4 <0f> 0b 48 83 c4 08 5b 5d 41 5c 41 5d 41 5e 41 5f c3 cc cc cc cc 0f [ 6170.287895] RSP: 0018:ffff888134b8fd08 EFLAGS: 00010202 [ 6170.287904] RAX: 0000000000000001 RBX: ffff888125bffb28 RCX: dffffc0000000000 [ 6170.287912] RDX: 0000000000000003 RSI: ffffffffa20298ab RDI: ffff88811ebe4750 [ 6170.287919] RBP: ffff88811ebe4700 R08: ffff88838e812650 R09: fffffbfff0623a55 [ 6170.287926] R10: ffffffff8311d2af R11: 0000000000000001 R12: ffff888125bffb10 [ 6170.287933] R13: ffff888125bffb10 R14: dead000000000122 R15: dead000000000100 [ 6170.287940] FS: 0000000000000000(0000) GS:ffff888390b00000(0000) knlGS:0000000000000000 [ 6170.287948] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 [ 6170.287955] CR2: 00007fd31fc00710 CR3: 0000000133f60004 CR4: 00000000001706f0 [ 6170.287962] Call Trace: [ 6170.287967] [ 6170.287973] ? __warn+0x9f/0x1a0 [ 6170.287986] ? nf_tables_chain_destroy+0x1f7/0x220 [nf_tables] [ 6170.288092] ? report_bug+0x1b1/0x1e0 [ 6170.287986] ? nf_tables_chain_destroy+0x1f7/0x220 [nf_tables] [ 6170.288092] ? report_bug+0x1b1/0x1e0 [ 6170.288104] ? handle_bug+0x3c/0x70 [ 6170.288112] ? exc_invalid_op+0x17/0x40 [ 6170.288120] ? asm_exc_invalid_op+0x1a/0x20 [ 6170.288132] ? nf_tables_chain_destroy+0x2b/0x220 [nf_tables] [ 6170.288243] ? nf_tables_chain_destroy+0x1f7/0x220 [nf_tables] [ 6170.288366] ? nf_tables_chain_destroy+0x2b/0x220 [nf_tables] [ 6170.288483] nf_tables_trans_destroy_work+0x588/0x590 [nf_tables] Fixes: 591054469b3e ("netfilter: nf_tables: revisit chain/object refcounting from elements") Signed-off-by: Pablo Neira Ayuso --- net/netfilter/nf_tables_api.c | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/net/netfilter/nf_tables_api.c b/net/netfilter/nf_tables_api.c index d0c09f899e80..167074283ea9 100644 --- a/net/netfilter/nf_tables_api.c +++ b/net/netfilter/nf_tables_api.c @@ -7223,6 +7223,16 @@ void nft_data_hold(const struct nft_data *data, enum nft_data_types type) } } +static int nft_setelem_active_next(const struct net *net, + const struct nft_set *set, + struct nft_elem_priv *elem_priv) +{ + const struct nft_set_ext *ext = nft_set_elem_ext(set, elem_priv); + u8 genmask = nft_genmask_next(net); + + return nft_set_elem_active(ext, genmask); +} + static void nft_setelem_data_activate(const struct net *net, const struct nft_set *set, struct nft_elem_priv *elem_priv) @@ -10644,8 +10654,10 @@ static int __nf_tables_abort(struct net *net, enum nfnl_abort_action action) case NFT_MSG_DESTROYSETELEM: te = (struct nft_trans_elem *)trans->data; - nft_setelem_data_activate(net, te->set, te->elem_priv); - nft_setelem_activate(net, te->set, te->elem_priv); + if (!nft_setelem_active_next(net, te->set, te->elem_priv)) { + nft_setelem_data_activate(net, te->set, te->elem_priv); + nft_setelem_activate(net, te->set, te->elem_priv); + } if (!nft_setelem_is_catchall(te->set, te->elem_priv)) te->set->ndeact--; -- cgit v1.2.3 From 0f022d32c3eca477fbf79a205243a6123ed0fe11 Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Mon, 15 Apr 2024 18:07:28 -0300 Subject: net/sched: Fix mirred deadlock on device recursion When the mirred action is used on a classful egress qdisc and a packet is mirrored or redirected to self we hit a qdisc lock deadlock. See trace below. [..... other info removed for brevity....] [ 82.890906] [ 82.890906] ============================================ [ 82.890906] WARNING: possible recursive locking detected [ 82.890906] 6.8.0-05205-g77fadd89fe2d-dirty #213 Tainted: G W [ 82.890906] -------------------------------------------- [ 82.890906] ping/418 is trying to acquire lock: [ 82.890906] ffff888006994110 (&sch->q.lock){+.-.}-{3:3}, at: __dev_queue_xmit+0x1778/0x3550 [ 82.890906] [ 82.890906] but task is already holding lock: [ 82.890906] ffff888006994110 (&sch->q.lock){+.-.}-{3:3}, at: __dev_queue_xmit+0x1778/0x3550 [ 82.890906] [ 82.890906] other info that might help us debug this: [ 82.890906] Possible unsafe locking scenario: [ 82.890906] [ 82.890906] CPU0 [ 82.890906] ---- [ 82.890906] lock(&sch->q.lock); [ 82.890906] lock(&sch->q.lock); [ 82.890906] [ 82.890906] *** DEADLOCK *** [ 82.890906] [..... other info removed for brevity....] Example setup (eth0->eth0) to recreate tc qdisc add dev eth0 root handle 1: htb default 30 tc filter add dev eth0 handle 1: protocol ip prio 2 matchall \ action mirred egress redirect dev eth0 Another example(eth0->eth1->eth0) to recreate tc qdisc add dev eth0 root handle 1: htb default 30 tc filter add dev eth0 handle 1: protocol ip prio 2 matchall \ action mirred egress redirect dev eth1 tc qdisc add dev eth1 root handle 1: htb default 30 tc filter add dev eth1 handle 1: protocol ip prio 2 matchall \ action mirred egress redirect dev eth0 We fix this by adding an owner field (CPU id) to struct Qdisc set after root qdisc is entered. When the softirq enters it a second time, if the qdisc owner is the same CPU, the packet is dropped to break the loop. Reported-by: Mingshuai Ren Closes: https://lore.kernel.org/netdev/20240314111713.5979-1-renmingshuai@huawei.com/ Fixes: 3bcb846ca4cf ("net: get rid of spin_trylock() in net_tx_action()") Fixes: e578d9c02587 ("net: sched: use counter to break reclassify loops") Signed-off-by: Eric Dumazet Reviewed-by: Victor Nogueira Reviewed-by: Pedro Tammela Tested-by: Jamal Hadi Salim Acked-by: Jamal Hadi Salim Link: https://lore.kernel.org/r/20240415210728.36949-1-victor@mojatatu.com Signed-off-by: Jakub Kicinski --- include/net/sch_generic.h | 1 + net/core/dev.c | 6 ++++++ net/sched/sch_generic.c | 1 + 3 files changed, 8 insertions(+) diff --git a/include/net/sch_generic.h b/include/net/sch_generic.h index cefe0c4bdae3..41ca14e81d55 100644 --- a/include/net/sch_generic.h +++ b/include/net/sch_generic.h @@ -117,6 +117,7 @@ struct Qdisc { struct qdisc_skb_head q; struct gnet_stats_basic_sync bstats; struct gnet_stats_queue qstats; + int owner; unsigned long state; unsigned long state2; /* must be written under qdisc spinlock */ struct Qdisc *next_sched; diff --git a/net/core/dev.c b/net/core/dev.c index 984ff8b9d0e1..331848eca7d3 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -3775,6 +3775,10 @@ no_lock_out: return rc; } + if (unlikely(READ_ONCE(q->owner) == smp_processor_id())) { + kfree_skb_reason(skb, SKB_DROP_REASON_TC_RECLASSIFY_LOOP); + return NET_XMIT_DROP; + } /* * Heuristic to force contended enqueues to serialize on a * separate lock before trying to get qdisc main lock. @@ -3814,7 +3818,9 @@ no_lock_out: qdisc_run_end(q); rc = NET_XMIT_SUCCESS; } else { + WRITE_ONCE(q->owner, smp_processor_id()); rc = dev_qdisc_enqueue(skb, q, &to_free, txq); + WRITE_ONCE(q->owner, -1); if (qdisc_run_begin(q)) { if (unlikely(contended)) { spin_unlock(&q->busylock); diff --git a/net/sched/sch_generic.c b/net/sched/sch_generic.c index ff5336493777..4a2c763e2d11 100644 --- a/net/sched/sch_generic.c +++ b/net/sched/sch_generic.c @@ -974,6 +974,7 @@ struct Qdisc *qdisc_alloc(struct netdev_queue *dev_queue, sch->enqueue = ops->enqueue; sch->dequeue = ops->dequeue; sch->dev_queue = dev_queue; + sch->owner = -1; netdev_hold(dev, &sch->dev_tracker, GFP_KERNEL); refcount_set(&sch->refcnt, 1); -- cgit v1.2.3 From caed8eba221533123192d39cc947f45cbb1e1db5 Mon Sep 17 00:00:00 2001 From: Jakub Kicinski Date: Tue, 16 Apr 2024 08:10:48 -0700 Subject: selftests: kselftest_harness: fix Clang warning about zero-length format Apparently it's more legal to pass the format as NULL, than it is to use an empty string. Clang complains about empty formats: ./../kselftest_harness.h:1207:30: warning: format string is empty [-Wformat-zero-length] 1207 | diagnostic ? "%s" : "", diagnostic); | ^~ 1 warning generated. Reported-by: Sean Christopherson Link: https://lore.kernel.org/all/20240409224256.1581292-1-seanjc@google.com Fixes: 378193eff339 ("selftests: kselftest_harness: let PASS / FAIL provide diagnostic") Tested-by: Sean Christopherson Reviewed-by: Muhammad Usama Anjum Link: https://lore.kernel.org/r/20240416151048.1682352-1-kuba@kernel.org Signed-off-by: Jakub Kicinski --- tools/testing/selftests/kselftest.h | 10 ++++++---- tools/testing/selftests/kselftest_harness.h | 2 +- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/tools/testing/selftests/kselftest.h b/tools/testing/selftests/kselftest.h index 541bf192e30e..4eca3fd1292c 100644 --- a/tools/testing/selftests/kselftest.h +++ b/tools/testing/selftests/kselftest.h @@ -288,15 +288,17 @@ void ksft_test_result_code(int exit_code, const char *test_name, } /* Docs seem to call for double space if directive is absent */ - if (!directive[0] && msg[0]) + if (!directive[0] && msg) directive = " # "; - va_start(args, msg); printf("%s %u %s%s", tap_code, ksft_test_num(), test_name, directive); errno = saved_errno; - vprintf(msg, args); + if (msg) { + va_start(args, msg); + vprintf(msg, args); + va_end(args); + } printf("\n"); - va_end(args); } static inline int ksft_exit_pass(void) diff --git a/tools/testing/selftests/kselftest_harness.h b/tools/testing/selftests/kselftest_harness.h index 4fd735e48ee7..adb15cae79ab 100644 --- a/tools/testing/selftests/kselftest_harness.h +++ b/tools/testing/selftests/kselftest_harness.h @@ -1202,7 +1202,7 @@ void __run_test(struct __fixture_metadata *f, diagnostic = "unknown"; ksft_test_result_code(t->exit_code, test_name, - diagnostic ? "%s" : "", diagnostic); + diagnostic ? "%s" : NULL, diagnostic); } static int test_harness_run(int argc, char **argv) -- cgit v1.2.3 From d362046021ea122309da8c8e0b6850c792ca97b5 Mon Sep 17 00:00:00 2001 From: Vanillan Wang Date: Tue, 16 Apr 2024 20:07:13 +0800 Subject: net:usb:qmi_wwan: support Rolling modules Update the qmi_wwan driver support for the Rolling LTE modules. - VID:PID 33f8:0104, RW101-GL for laptop debug M.2 cards(with RMNET interface for /Linux/Chrome OS) 0x0104: RMNET, diag, at, pipe Here are the outputs of usb-devices: T: Bus=04 Lev=01 Prnt=01 Port=00 Cnt=01 Dev#= 2 Spd=5000 MxCh= 0 D: Ver= 3.20 Cls=00(>ifc ) Sub=00 Prot=00 MxPS= 9 #Cfgs= 1 P: Vendor=33f8 ProdID=0104 Rev=05.04 S: Manufacturer=Rolling Wireless S.a.r.l. S: Product=Rolling Module S: SerialNumber=ba2eb033 C: #Ifs= 6 Cfg#= 1 Atr=a0 MxPwr=896mA I: If#= 0 Alt= 0 #EPs= 2 Cls=ff(vend.) Sub=ff Prot=30 Driver=option E: Ad=01(O) Atr=02(Bulk) MxPS=1024 Ivl=0ms E: Ad=81(I) Atr=02(Bulk) MxPS=1024 Ivl=0ms I: If#= 1 Alt= 0 #EPs= 3 Cls=ff(vend.) Sub=ff Prot=40 Driver=option E: Ad=02(O) Atr=02(Bulk) MxPS=1024 Ivl=0ms E: Ad=82(I) Atr=02(Bulk) MxPS=1024 Ivl=0ms E: Ad=83(I) Atr=03(Int.) MxPS= 10 Ivl=32ms I: If#= 2 Alt= 0 #EPs= 3 Cls=ff(vend.) Sub=ff Prot=40 Driver=option E: Ad=03(O) Atr=02(Bulk) MxPS=1024 Ivl=0ms E: Ad=84(I) Atr=02(Bulk) MxPS=1024 Ivl=0ms E: Ad=85(I) Atr=03(Int.) MxPS= 10 Ivl=32ms I: If#= 3 Alt= 0 #EPs= 3 Cls=ff(vend.) Sub=00 Prot=40 Driver=option E: Ad=04(O) Atr=02(Bulk) MxPS=1024 Ivl=0ms E: Ad=86(I) Atr=02(Bulk) MxPS=1024 Ivl=0ms E: Ad=87(I) Atr=03(Int.) MxPS= 10 Ivl=32ms I: If#= 4 Alt= 0 #EPs= 3 Cls=ff(vend.) Sub=ff Prot=50 Driver=qmi_wwan E: Ad=0f(O) Atr=02(Bulk) MxPS=1024 Ivl=0ms E: Ad=88(I) Atr=03(Int.) MxPS= 8 Ivl=32ms E: Ad=8e(I) Atr=02(Bulk) MxPS=1024 Ivl=0ms I: If#= 5 Alt= 0 #EPs= 2 Cls=ff(vend.) Sub=42 Prot=01 Driver=usbfs E: Ad=05(O) Atr=02(Bulk) MxPS=1024 Ivl=0ms E: Ad=89(I) Atr=02(Bulk) MxPS=1024 Ivl=0ms Signed-off-by: Vanillan Wang Link: https://lore.kernel.org/r/20240416120713.24777-1-vanillanwang@163.com Signed-off-by: Jakub Kicinski --- drivers/net/usb/qmi_wwan.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/net/usb/qmi_wwan.c b/drivers/net/usb/qmi_wwan.c index e2e181378f41..edc34402e787 100644 --- a/drivers/net/usb/qmi_wwan.c +++ b/drivers/net/usb/qmi_wwan.c @@ -1431,6 +1431,7 @@ static const struct usb_device_id products[] = { {QMI_FIXED_INTF(0x2692, 0x9025, 4)}, /* Cellient MPL200 (rebranded Qualcomm 05c6:9025) */ {QMI_QUIRK_SET_DTR(0x1546, 0x1312, 4)}, /* u-blox LARA-R6 01B */ {QMI_QUIRK_SET_DTR(0x1546, 0x1342, 4)}, /* u-blox LARA-L6 */ + {QMI_QUIRK_SET_DTR(0x33f8, 0x0104, 4)}, /* Rolling RW101 RMNET */ /* 4. Gobi 1000 devices */ {QMI_GOBI1K_DEVICE(0x05c6, 0x9212)}, /* Acer Gobi Modem Device */ -- cgit v1.2.3 From 94667949ec3bbb2218c46ad0a0e7274c8832e494 Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Tue, 16 Apr 2024 10:23:29 +0200 Subject: net: ethernet: mtk_eth_soc: fix WED + wifi reset The WLAN + WED reset sequence relies on being able to receive interrupts from the card, in order to synchronize individual steps with the firmware. When WED is stopped, leave interrupts running and rely on the driver turning off unwanted ones. WED DMA also needs to be disabled before resetting. Fixes: f78cd9c783e0 ("net: ethernet: mtk_wed: update mtk_wed_stop") Signed-off-by: Felix Fietkau Link: https://lore.kernel.org/r/20240416082330.82564-1-nbd@nbd.name Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/mediatek/mtk_wed.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/drivers/net/ethernet/mediatek/mtk_wed.c b/drivers/net/ethernet/mediatek/mtk_wed.c index c895e265ae0e..61334a71058c 100644 --- a/drivers/net/ethernet/mediatek/mtk_wed.c +++ b/drivers/net/ethernet/mediatek/mtk_wed.c @@ -1074,13 +1074,13 @@ mtk_wed_dma_disable(struct mtk_wed_device *dev) static void mtk_wed_stop(struct mtk_wed_device *dev) { + mtk_wed_dma_disable(dev); mtk_wed_set_ext_int(dev, false); wed_w32(dev, MTK_WED_WPDMA_INT_TRIGGER, 0); wed_w32(dev, MTK_WED_WDMA_INT_TRIGGER, 0); wdma_w32(dev, MTK_WDMA_INT_MASK, 0); wdma_w32(dev, MTK_WDMA_INT_GRP2, 0); - wed_w32(dev, MTK_WED_WPDMA_INT_MASK, 0); if (!mtk_wed_get_rx_capa(dev)) return; @@ -1093,7 +1093,6 @@ static void mtk_wed_deinit(struct mtk_wed_device *dev) { mtk_wed_stop(dev); - mtk_wed_dma_disable(dev); wed_clr(dev, MTK_WED_CTRL, MTK_WED_CTRL_WDMA_INT_AGENT_EN | @@ -2605,9 +2604,6 @@ mtk_wed_irq_get(struct mtk_wed_device *dev, u32 mask) static void mtk_wed_irq_set_mask(struct mtk_wed_device *dev, u32 mask) { - if (!dev->running) - return; - mtk_wed_set_ext_int(dev, !!mask); wed_w32(dev, MTK_WED_INT_MASK, mask); } -- cgit v1.2.3 From cf16ffa17c398434a77b8a373e69287c95b60de2 Mon Sep 17 00:00:00 2001 From: Coia Prant Date: Mon, 15 Apr 2024 07:26:25 -0700 Subject: USB: serial: option: add Lonsung U8300/U9300 product Update the USB serial option driver to support Longsung U8300/U9300. For U8300 Interface 4 is used by for QMI interface in stock firmware of U8300, the router which uses U8300 modem. Interface 5 is used by for ADB interface in stock firmware of U8300, the router which uses U8300 modem. Interface mapping is: 0: unknown (Debug), 1: AT (Modem), 2: AT, 3: PPP (NDIS / Pipe), 4: QMI, 5: ADB T: Bus=05 Lev=01 Prnt=03 Port=02 Cnt=01 Dev#= 4 Spd=480 MxCh= 0 D: Ver= 2.00 Cls=00(>ifc ) Sub=00 Prot=00 MxPS=64 #Cfgs= 1 P: Vendor=1c9e ProdID=9b05 Rev=03.18 S: Manufacturer=Android S: Product=Android C: #Ifs= 6 Cfg#= 1 Atr=80 MxPwr=500mA I: If#= 0 Alt= 0 #EPs= 2 Cls=ff(vend.) Sub=ff Prot=ff Driver=option E: Ad=01(O) Atr=02(Bulk) MxPS= 512 Ivl=0ms E: Ad=81(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms I: If#= 1 Alt= 0 #EPs= 3 Cls=ff(vend.) Sub=00 Prot=00 Driver=option E: Ad=02(O) Atr=02(Bulk) MxPS= 512 Ivl=0ms E: Ad=82(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms E: Ad=83(I) Atr=03(Int.) MxPS= 10 Ivl=32ms I: If#= 2 Alt= 0 #EPs= 3 Cls=ff(vend.) Sub=00 Prot=00 Driver=option E: Ad=03(O) Atr=02(Bulk) MxPS= 512 Ivl=0ms E: Ad=84(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms E: Ad=85(I) Atr=03(Int.) MxPS= 10 Ivl=32ms I: If#= 3 Alt= 0 #EPs= 3 Cls=ff(vend.) Sub=00 Prot=00 Driver=option E: Ad=04(O) Atr=02(Bulk) MxPS= 512 Ivl=0ms E: Ad=86(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms E: Ad=87(I) Atr=03(Int.) MxPS= 10 Ivl=32ms I: If#= 4 Alt= 0 #EPs= 3 Cls=ff(vend.) Sub=ff Prot=ff Driver=qmi_wwan E: Ad=05(O) Atr=02(Bulk) MxPS= 512 Ivl=0ms E: Ad=88(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms E: Ad=89(I) Atr=03(Int.) MxPS= 8 Ivl=32ms I: If#= 5 Alt= 0 #EPs= 2 Cls=ff(vend.) Sub=42 Prot=01 Driver=(none) E: Ad=06(O) Atr=02(Bulk) MxPS= 512 Ivl=0ms E: Ad=8a(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms For U9300 Interface 1 is used by for ADB interface in stock firmware of U9300, the router which uses U9300 modem. Interface 4 is used by for QMI interface in stock firmware of U9300, the router which uses U9300 modem. Interface mapping is: 0: ADB, 1: AT (Modem), 2: AT, 3: PPP (NDIS / Pipe), 4: QMI Note: Interface 3 of some models of the U9300 series can send AT commands. T: Bus=05 Lev=01 Prnt=05 Port=04 Cnt=01 Dev#= 6 Spd=480 MxCh= 0 D: Ver= 2.00 Cls=00(>ifc ) Sub=00 Prot=00 MxPS=64 #Cfgs= 1 P: Vendor=1c9e ProdID=9b3c Rev=03.18 S: Manufacturer=Android S: Product=Android C: #Ifs= 5 Cfg#= 1 Atr=80 MxPwr=500mA I: If#= 0 Alt= 0 #EPs= 2 Cls=ff(vend.) Sub=42 Prot=01 Driver=(none) E: Ad=01(O) Atr=02(Bulk) MxPS= 512 Ivl=0ms E: Ad=81(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms I: If#= 1 Alt= 0 #EPs= 3 Cls=ff(vend.) Sub=00 Prot=00 Driver=option E: Ad=02(O) Atr=02(Bulk) MxPS= 512 Ivl=0ms E: Ad=82(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms E: Ad=83(I) Atr=03(Int.) MxPS= 10 Ivl=32ms I: If#= 2 Alt= 0 #EPs= 3 Cls=ff(vend.) Sub=00 Prot=00 Driver=option E: Ad=03(O) Atr=02(Bulk) MxPS= 512 Ivl=0ms E: Ad=84(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms E: Ad=85(I) Atr=03(Int.) MxPS= 10 Ivl=32ms I: If#= 3 Alt= 0 #EPs= 3 Cls=ff(vend.) Sub=00 Prot=00 Driver=option E: Ad=04(O) Atr=02(Bulk) MxPS= 512 Ivl=0ms E: Ad=86(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms E: Ad=87(I) Atr=03(Int.) MxPS= 10 Ivl=32ms I: If#= 4 Alt= 0 #EPs= 3 Cls=ff(vend.) Sub=ff Prot=ff Driver=qmi_wwan E: Ad=05(O) Atr=02(Bulk) MxPS= 512 Ivl=0ms E: Ad=88(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms E: Ad=89(I) Atr=03(Int.) MxPS= 8 Ivl=32ms Tested successfully using Modem Manager on U9300. Tested successfully AT commands using If=1, If=2 and If=3 on U9300. Signed-off-by: Coia Prant Reviewed-by: Lars Melin [ johan: drop product defines, trim commit message ] Cc: stable@vger.kernel.org Signed-off-by: Johan Hovold --- drivers/usb/serial/option.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c index ad0fff1e889d..8827ca3a6595 100644 --- a/drivers/usb/serial/option.c +++ b/drivers/usb/serial/option.c @@ -2068,6 +2068,10 @@ static const struct usb_device_id option_ids[] = { .driver_info = RSVD(3) }, { USB_DEVICE_INTERFACE_CLASS(LONGCHEER_VENDOR_ID, 0x9803, 0xff), .driver_info = RSVD(4) }, + { USB_DEVICE(LONGCHEER_VENDOR_ID, 0x9b05), /* Longsung U8300 */ + .driver_info = RSVD(4) | RSVD(5) }, + { USB_DEVICE(LONGCHEER_VENDOR_ID, 0x9b3c), /* Longsung U9300 */ + .driver_info = RSVD(0) | RSVD(4) }, { USB_DEVICE(LONGCHEER_VENDOR_ID, ZOOM_PRODUCT_4597) }, { USB_DEVICE(LONGCHEER_VENDOR_ID, IBALL_3_5G_CONNECT) }, { USB_DEVICE(HAIER_VENDOR_ID, HAIER_PRODUCT_CE100) }, -- cgit v1.2.3 From 311f97a4c7c22a01f8897bddf00428dfd0668e79 Mon Sep 17 00:00:00 2001 From: Vanillan Wang Date: Tue, 16 Apr 2024 18:02:55 +0800 Subject: USB: serial: option: add Rolling RW101-GL and RW135-GL support Update the USB serial option driver support for the Rolling LTE modules. - VID:PID 33f8:01a2, RW101-GL for laptop debug M.2 cards(with MBIM interface for /Linux/Chrome OS) 0x01a2: mbim, diag, at, pipe - VID:PID 33f8:01a3, RW101-GL for laptop debug M.2 cards(with MBIM interface for /Linux/Chrome OS) 0x01a3: mbim, pipe - VID:PID 33f8:01a4, RW101-GL for laptop debug M.2 cards(with MBIM interface for /Linux/Chrome OS) 0x01a4: mbim, diag, at, pipe - VID:PID 33f8:0104, RW101-GL for laptop debug M.2 cards(with RMNET interface for /Linux/Chrome OS) 0x0104: RMNET, diag, at, pipe - VID:PID 33f8:0115, RW135-GL for laptop debug M.2 cards(with MBIM interface for /Linux/Chrome OS) 0x0115: MBIM, diag, at, pipe Here are the outputs of usb-devices: T: Bus=01 Lev=01 Prnt=01 Port=02 Cnt=01 Dev#= 5 Spd=480 MxCh= 0 D: Ver= 2.01 Cls=00(>ifc ) Sub=00 Prot=00 MxPS=64 #Cfgs= 1 P: Vendor=33f8 ProdID=01a2 Rev=05.15 S: Manufacturer=Rolling Wireless S.a.r.l. S: Product=Rolling Module S: SerialNumber=12345678 C: #Ifs= 5 Cfg#= 1 Atr=a0 MxPwr=500mA I: If#= 0 Alt= 0 #EPs= 1 Cls=02(commc) Sub=0e Prot=00 Driver=cdc_mbim E: Ad=82(I) Atr=03(Int.) MxPS= 64 Ivl=32ms I: If#= 1 Alt= 1 #EPs= 2 Cls=0a(data ) Sub=00 Prot=02 Driver=cdc_mbim E: Ad=01(O) Atr=02(Bulk) MxPS= 512 Ivl=0ms E: Ad=81(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms I: If#= 2 Alt= 0 #EPs= 3 Cls=ff(vend.) Sub=ff Prot=40 Driver=option E: Ad=02(O) Atr=02(Bulk) MxPS= 512 Ivl=0ms E: Ad=83(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms E: Ad=84(I) Atr=03(Int.) MxPS= 10 Ivl=32ms I: If#= 3 Alt= 0 #EPs= 2 Cls=ff(vend.) Sub=ff Prot=30 Driver=option E: Ad=03(O) Atr=02(Bulk) MxPS= 512 Ivl=0ms E: Ad=85(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms I: If#= 4 Alt= 0 #EPs= 2 Cls=ff(vend.) Sub=00 Prot=00 Driver=option E: Ad=04(O) Atr=02(Bulk) MxPS= 512 Ivl=0ms E: Ad=86(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms T: Bus=01 Lev=01 Prnt=01 Port=02 Cnt=01 Dev#= 8 Spd=480 MxCh= 0 D: Ver= 2.01 Cls=00(>ifc ) Sub=00 Prot=00 MxPS=64 #Cfgs= 1 P: Vendor=33f8 ProdID=01a3 Rev=05.15 S: Manufacturer=Rolling Wireless S.a.r.l. S: Product=Rolling Module S: SerialNumber=12345678 C: #Ifs= 3 Cfg#= 1 Atr=a0 MxPwr=500mA I: If#= 0 Alt= 0 #EPs= 1 Cls=02(commc) Sub=0e Prot=00 Driver=cdc_mbim E: Ad=82(I) Atr=03(Int.) MxPS= 64 Ivl=32ms I: If#= 1 Alt= 1 #EPs= 2 Cls=0a(data ) Sub=00 Prot=02 Driver=cdc_mbim E: Ad=01(O) Atr=02(Bulk) MxPS= 512 Ivl=0ms E: Ad=81(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms I: If#= 2 Alt= 0 #EPs= 2 Cls=ff(vend.) Sub=00 Prot=00 Driver=option E: Ad=02(O) Atr=02(Bulk) MxPS= 512 Ivl=0ms E: Ad=83(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms T: Bus=01 Lev=01 Prnt=01 Port=02 Cnt=01 Dev#= 17 Spd=480 MxCh= 0 D: Ver= 2.01 Cls=00(>ifc ) Sub=00 Prot=00 MxPS=64 #Cfgs= 1 P: Vendor=33f8 ProdID=01a4 Rev=05.15 S: Manufacturer=Rolling Wireless S.a.r.l. S: Product=Rolling Module S: SerialNumber=12345678 C: #Ifs= 6 Cfg#= 1 Atr=a0 MxPwr=500mA I: If#= 0 Alt= 0 #EPs= 1 Cls=02(commc) Sub=0e Prot=00 Driver=cdc_mbim E: Ad=82(I) Atr=03(Int.) MxPS= 64 Ivl=32ms I: If#= 1 Alt= 1 #EPs= 2 Cls=0a(data ) Sub=00 Prot=02 Driver=cdc_mbim E: Ad=01(O) Atr=02(Bulk) MxPS= 512 Ivl=0ms E: Ad=81(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms I: If#= 2 Alt= 0 #EPs= 2 Cls=ff(vend.) Sub=ff Prot=30 Driver=option E: Ad=02(O) Atr=02(Bulk) MxPS= 512 Ivl=0ms E: Ad=83(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms I: If#= 3 Alt= 0 #EPs= 3 Cls=ff(vend.) Sub=ff Prot=40 Driver=option E: Ad=03(O) Atr=02(Bulk) MxPS= 512 Ivl=0ms E: Ad=84(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms E: Ad=85(I) Atr=03(Int.) MxPS= 10 Ivl=32ms I: If#= 4 Alt= 0 #EPs= 2 Cls=ff(vend.) Sub=42 Prot=01 Driver=usbfs E: Ad=04(O) Atr=02(Bulk) MxPS= 512 Ivl=0ms E: Ad=86(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms I: If#= 5 Alt= 0 #EPs= 2 Cls=ff(vend.) Sub=00 Prot=00 Driver=option E: Ad=05(O) Atr=02(Bulk) MxPS= 512 Ivl=0ms E: Ad=87(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms T: Bus=04 Lev=01 Prnt=01 Port=00 Cnt=01 Dev#= 2 Spd=5000 MxCh= 0 D: Ver= 3.20 Cls=00(>ifc ) Sub=00 Prot=00 MxPS= 9 #Cfgs= 1 P: Vendor=33f8 ProdID=0104 Rev=05.04 S: Manufacturer=Rolling Wireless S.a.r.l. S: Product=Rolling Module S: SerialNumber=ba2eb033 C: #Ifs= 6 Cfg#= 1 Atr=a0 MxPwr=896mA I: If#= 0 Alt= 0 #EPs= 2 Cls=ff(vend.) Sub=ff Prot=30 Driver=option E: Ad=01(O) Atr=02(Bulk) MxPS=1024 Ivl=0ms E: Ad=81(I) Atr=02(Bulk) MxPS=1024 Ivl=0ms I: If#= 1 Alt= 0 #EPs= 3 Cls=ff(vend.) Sub=ff Prot=40 Driver=option E: Ad=02(O) Atr=02(Bulk) MxPS=1024 Ivl=0ms E: Ad=82(I) Atr=02(Bulk) MxPS=1024 Ivl=0ms E: Ad=83(I) Atr=03(Int.) MxPS= 10 Ivl=32ms I: If#= 2 Alt= 0 #EPs= 3 Cls=ff(vend.) Sub=ff Prot=40 Driver=option E: Ad=03(O) Atr=02(Bulk) MxPS=1024 Ivl=0ms E: Ad=84(I) Atr=02(Bulk) MxPS=1024 Ivl=0ms E: Ad=85(I) Atr=03(Int.) MxPS= 10 Ivl=32ms I: If#= 3 Alt= 0 #EPs= 3 Cls=ff(vend.) Sub=00 Prot=40 Driver=option E: Ad=04(O) Atr=02(Bulk) MxPS=1024 Ivl=0ms E: Ad=86(I) Atr=02(Bulk) MxPS=1024 Ivl=0ms E: Ad=87(I) Atr=03(Int.) MxPS= 10 Ivl=32ms I: If#= 4 Alt= 0 #EPs= 3 Cls=ff(vend.) Sub=ff Prot=50 Driver=qmi_wwan E: Ad=0f(O) Atr=02(Bulk) MxPS=1024 Ivl=0ms E: Ad=88(I) Atr=03(Int.) MxPS= 8 Ivl=32ms E: Ad=8e(I) Atr=02(Bulk) MxPS=1024 Ivl=0ms I: If#= 5 Alt= 0 #EPs= 2 Cls=ff(vend.) Sub=42 Prot=01 Driver=usbfs E: Ad=05(O) Atr=02(Bulk) MxPS=1024 Ivl=0ms E: Ad=89(I) Atr=02(Bulk) MxPS=1024 Ivl=0ms T: Bus=01 Lev=01 Prnt=01 Port=02 Cnt=01 Dev#= 16 Spd=480 MxCh= 0 D: Ver= 2.01 Cls=00(>ifc ) Sub=00 Prot=00 MxPS=64 #Cfgs= 1 P: Vendor=33f8 ProdID=0115 Rev=05.15 S: Manufacturer=Rolling Wireless S.a.r.l. S: Product=Rolling Module S: SerialNumber=12345678 C: #Ifs= 6 Cfg#= 1 Atr=a0 MxPwr=500mA I: If#= 0 Alt= 0 #EPs= 1 Cls=02(commc) Sub=0e Prot=00 Driver=cdc_mbim E: Ad=82(I) Atr=03(Int.) MxPS= 64 Ivl=32ms I: If#= 1 Alt= 1 #EPs= 2 Cls=0a(data ) Sub=00 Prot=02 Driver=cdc_mbim E: Ad=01(O) Atr=02(Bulk) MxPS= 512 Ivl=0ms E: Ad=81(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms I: If#= 2 Alt= 0 #EPs= 2 Cls=ff(vend.) Sub=ff Prot=30 Driver=option E: Ad=02(O) Atr=02(Bulk) MxPS= 512 Ivl=0ms E: Ad=83(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms I: If#= 3 Alt= 0 #EPs= 3 Cls=ff(vend.) Sub=ff Prot=40 Driver=option E: Ad=03(O) Atr=02(Bulk) MxPS= 512 Ivl=0ms E: Ad=84(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms E: Ad=85(I) Atr=03(Int.) MxPS= 10 Ivl=32ms I: If#= 4 Alt= 0 #EPs= 2 Cls=ff(vend.) Sub=00 Prot=00 Driver=option E: Ad=04(O) Atr=02(Bulk) MxPS= 512 Ivl=0ms E: Ad=86(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms I: If#= 5 Alt= 0 #EPs= 2 Cls=ff(vend.) Sub=42 Prot=01 Driver=usbfs E: Ad=05(O) Atr=02(Bulk) MxPS= 512 Ivl=0ms E: Ad=87(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms Signed-off-by: Vanillan Wang Cc: stable@vger.kernel.org Signed-off-by: Johan Hovold --- drivers/usb/serial/option.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c index 8827ca3a6595..e22612017f66 100644 --- a/drivers/usb/serial/option.c +++ b/drivers/usb/serial/option.c @@ -2307,6 +2307,14 @@ static const struct usb_device_id option_ids[] = { { USB_DEVICE_INTERFACE_CLASS(0x305a, 0x1404, 0xff) }, /* GosunCn GM500 RNDIS */ { USB_DEVICE_INTERFACE_CLASS(0x305a, 0x1405, 0xff) }, /* GosunCn GM500 MBIM */ { USB_DEVICE_INTERFACE_CLASS(0x305a, 0x1406, 0xff) }, /* GosunCn GM500 ECM/NCM */ + { USB_DEVICE(0x33f8, 0x0104), /* Rolling RW101-GL (laptop RMNET) */ + .driver_info = RSVD(4) | RSVD(5) }, + { USB_DEVICE_INTERFACE_CLASS(0x33f8, 0x01a2, 0xff) }, /* Rolling RW101-GL (laptop MBIM) */ + { USB_DEVICE_INTERFACE_CLASS(0x33f8, 0x01a3, 0xff) }, /* Rolling RW101-GL (laptop MBIM) */ + { USB_DEVICE_INTERFACE_CLASS(0x33f8, 0x01a4, 0xff), /* Rolling RW101-GL (laptop MBIM) */ + .driver_info = RSVD(4) }, + { USB_DEVICE_INTERFACE_CLASS(0x33f8, 0x0115, 0xff), /* Rolling RW135-GL (laptop MBIM) */ + .driver_info = RSVD(5) }, { USB_DEVICE_AND_INTERFACE_INFO(OPPO_VENDOR_ID, OPPO_PRODUCT_R11, 0xff, 0xff, 0x30) }, { USB_DEVICE_AND_INTERFACE_INFO(SIERRA_VENDOR_ID, SIERRA_PRODUCT_EM9191, 0xff, 0xff, 0x30) }, { USB_DEVICE_AND_INTERFACE_INFO(SIERRA_VENDOR_ID, SIERRA_PRODUCT_EM9191, 0xff, 0xff, 0x40) }, -- cgit v1.2.3 From 32f5f73b79ffdef215e2e1bcb6ad74387c0f925c Mon Sep 17 00:00:00 2001 From: "Xin Li (Intel)" Date: Wed, 17 Apr 2024 10:47:31 -0700 Subject: x86/fred: Fix INT80 emulation for FRED Add a FRED-specific INT80 handler and document why it differs from the current one. Eventually, the common bits will be unified once FRED hw is available and it turns out that no further changes are needed but for now, keep the handlers separate for everyone's sanity's sake. [ bp: Zap duplicated commit message, massage. ] Fixes: 55617fb991df ("x86/entry: Do not allow external 0x80 interrupts") Suggested-by: H. Peter Anvin (Intel) Signed-off-by: Xin Li (Intel) Signed-off-by: Borislav Petkov (AMD) Link: https://lore.kernel.org/r/20240417174731.4189592-1-xin@zytor.com --- arch/x86/entry/common.c | 65 +++++++++++++++++++++++++++++++++++++++++++++ arch/x86/entry/entry_fred.c | 2 +- 2 files changed, 66 insertions(+), 1 deletion(-) diff --git a/arch/x86/entry/common.c b/arch/x86/entry/common.c index 6de50b80702e..51cc9c7cb9bd 100644 --- a/arch/x86/entry/common.c +++ b/arch/x86/entry/common.c @@ -255,6 +255,71 @@ __visible noinstr void do_int80_emulation(struct pt_regs *regs) instrumentation_end(); syscall_exit_to_user_mode(regs); } + +#ifdef CONFIG_X86_FRED +/* + * A FRED-specific INT80 handler is warranted for the follwing reasons: + * + * 1) As INT instructions and hardware interrupts are separate event + * types, FRED does not preclude the use of vector 0x80 for external + * interrupts. As a result, the FRED setup code does not reserve + * vector 0x80 and calling int80_is_external() is not merely + * suboptimal but actively incorrect: it could cause a system call + * to be incorrectly ignored. + * + * 2) It is called only for handling vector 0x80 of event type + * EVENT_TYPE_SWINT and will never be called to handle any external + * interrupt (event type EVENT_TYPE_EXTINT). + * + * 3) FRED has separate entry flows depending on if the event came from + * user space or kernel space, and because the kernel does not use + * INT insns, the FRED kernel entry handler fred_entry_from_kernel() + * falls through to fred_bad_type() if the event type is + * EVENT_TYPE_SWINT, i.e., INT insns. So if the kernel is handling + * an INT insn, it can only be from a user level. + * + * 4) int80_emulation() does a CLEAR_BRANCH_HISTORY. While FRED will + * likely take a different approach if it is ever needed: it + * probably belongs in either fred_intx()/ fred_other() or + * asm_fred_entrypoint_user(), depending on if this ought to be done + * for all entries from userspace or only system + * calls. + * + * 5) INT $0x80 is the fast path for 32-bit system calls under FRED. + */ +DEFINE_FREDENTRY_RAW(int80_emulation) +{ + int nr; + + enter_from_user_mode(regs); + + instrumentation_begin(); + add_random_kstack_offset(); + + /* + * FRED pushed 0 into regs::orig_ax and regs::ax contains the + * syscall number. + * + * User tracing code (ptrace or signal handlers) might assume + * that the regs::orig_ax contains a 32-bit number on invoking + * a 32-bit syscall. + * + * Establish the syscall convention by saving the 32bit truncated + * syscall number in regs::orig_ax and by invalidating regs::ax. + */ + regs->orig_ax = regs->ax & GENMASK(31, 0); + regs->ax = -ENOSYS; + + nr = syscall_32_enter(regs); + + local_irq_enable(); + nr = syscall_enter_from_user_mode_work(regs, nr); + do_syscall_32_irqs_on(regs, nr); + + instrumentation_end(); + syscall_exit_to_user_mode(regs); +} +#endif #else /* CONFIG_IA32_EMULATION */ /* Handles int $0x80 on a 32bit kernel */ diff --git a/arch/x86/entry/entry_fred.c b/arch/x86/entry/entry_fred.c index ac120cbdaaf2..9fa18b8c7f26 100644 --- a/arch/x86/entry/entry_fred.c +++ b/arch/x86/entry/entry_fred.c @@ -66,7 +66,7 @@ static noinstr void fred_intx(struct pt_regs *regs) /* INT80 */ case IA32_SYSCALL_VECTOR: if (ia32_enabled()) - return int80_emulation(regs); + return fred_int80_emulation(regs); fallthrough; #endif -- cgit v1.2.3 From a4b37f5033fa812f02f3b7bd1242393d347ba791 Mon Sep 17 00:00:00 2001 From: Hou Wenlong Date: Wed, 17 Apr 2024 19:34:25 +0800 Subject: x86/fred: Fix incorrect error code printout in fred_bad_type() regs->orig_ax has been set to -1 on entry so in the printout, fred_bad_type() should use the passed parameter error_code. Fixes: 14619d912b65 ("x86/fred: FRED entry/exit and dispatch code") Signed-off-by: Hou Wenlong Signed-off-by: Borislav Petkov (AMD) Acked-by: H. Peter Anvin (Intel) Link: https://lore.kernel.org/r/b2a8f0a41449d25240e314a2ddfbf6549511fb04.1713353612.git.houwenlong.hwl@antgroup.com --- arch/x86/entry/entry_fred.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/arch/x86/entry/entry_fred.c b/arch/x86/entry/entry_fred.c index 9fa18b8c7f26..89c1476fcdd9 100644 --- a/arch/x86/entry/entry_fred.c +++ b/arch/x86/entry/entry_fred.c @@ -28,9 +28,9 @@ static noinstr void fred_bad_type(struct pt_regs *regs, unsigned long error_code if (regs->fred_cs.sl > 0) { pr_emerg("PANIC: invalid or fatal FRED event; event type %u " "vector %u error 0x%lx aux 0x%lx at %04x:%016lx\n", - regs->fred_ss.type, regs->fred_ss.vector, regs->orig_ax, + regs->fred_ss.type, regs->fred_ss.vector, error_code, fred_event_data(regs), regs->cs, regs->ip); - die("invalid or fatal FRED event", regs, regs->orig_ax); + die("invalid or fatal FRED event", regs, error_code); panic("invalid or fatal FRED event"); } else { unsigned long flags = oops_begin(); @@ -38,10 +38,10 @@ static noinstr void fred_bad_type(struct pt_regs *regs, unsigned long error_code pr_alert("BUG: invalid or fatal FRED event; event type %u " "vector %u error 0x%lx aux 0x%lx at %04x:%016lx\n", - regs->fred_ss.type, regs->fred_ss.vector, regs->orig_ax, + regs->fred_ss.type, regs->fred_ss.vector, error_code, fred_event_data(regs), regs->cs, regs->ip); - if (__die("Invalid or fatal FRED event", regs, regs->orig_ax)) + if (__die("Invalid or fatal FRED event", regs, error_code)) sig = 0; oops_end(flags, regs, sig); -- cgit v1.2.3 From def52db470df28d6f43cacbd21137f03b9502073 Mon Sep 17 00:00:00 2001 From: Paul Barker Date: Tue, 16 Apr 2024 13:02:51 +0100 Subject: net: ravb: Count packets instead of descriptors in R-Car RX path MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The units of "work done" in the RX path should be packets instead of descriptors. Descriptors which are used by the hardware to record error conditions or are empty in the case of a DMA mapping error should not count towards our RX work budget. Also make the limit variable unsigned as it can never be negative. Fixes: c156633f1353 ("Renesas Ethernet AVB driver proper") Signed-off-by: Paul Barker Reviewed-by: Sergey Shtylyov Reviewed-by: Niklas Söderlund Signed-off-by: Paolo Abeni --- drivers/net/ethernet/renesas/ravb_main.c | 21 ++++++++------------- 1 file changed, 8 insertions(+), 13 deletions(-) diff --git a/drivers/net/ethernet/renesas/ravb_main.c b/drivers/net/ethernet/renesas/ravb_main.c index ba01c8cc3c90..7d231d011bff 100644 --- a/drivers/net/ethernet/renesas/ravb_main.c +++ b/drivers/net/ethernet/renesas/ravb_main.c @@ -892,29 +892,24 @@ static bool ravb_rx_rcar(struct net_device *ndev, int *quota, int q) struct ravb_private *priv = netdev_priv(ndev); const struct ravb_hw_info *info = priv->info; int entry = priv->cur_rx[q] % priv->num_rx_ring[q]; - int boguscnt = (priv->dirty_rx[q] + priv->num_rx_ring[q]) - - priv->cur_rx[q]; struct net_device_stats *stats = &priv->stats[q]; struct ravb_ex_rx_desc *desc; + unsigned int limit, i; struct sk_buff *skb; dma_addr_t dma_addr; struct timespec64 ts; + int rx_packets = 0; u8 desc_status; u16 pkt_len; - int limit; - boguscnt = min(boguscnt, *quota); - limit = boguscnt; + limit = priv->dirty_rx[q] + priv->num_rx_ring[q] - priv->cur_rx[q]; desc = &priv->rx_ring[q].ex_desc[entry]; - while (desc->die_dt != DT_FEMPTY) { + for (i = 0; i < limit && rx_packets < *quota && desc->die_dt != DT_FEMPTY; i++) { /* Descriptor type must be checked before all other reads */ dma_rmb(); desc_status = desc->msc; pkt_len = le16_to_cpu(desc->ds_cc) & RX_DS; - if (--boguscnt < 0) - break; - /* We use 0-byte descriptors to mark the DMA mapping errors */ if (!pkt_len) continue; @@ -960,7 +955,7 @@ static bool ravb_rx_rcar(struct net_device *ndev, int *quota, int q) if (ndev->features & NETIF_F_RXCSUM) ravb_rx_csum(skb); napi_gro_receive(&priv->napi[q], skb); - stats->rx_packets++; + rx_packets++; stats->rx_bytes += pkt_len; } @@ -995,9 +990,9 @@ static bool ravb_rx_rcar(struct net_device *ndev, int *quota, int q) desc->die_dt = DT_FEMPTY; } - *quota -= limit - (++boguscnt); - - return boguscnt <= 0; + stats->rx_packets += rx_packets; + *quota -= rx_packets; + return *quota == 0; } /* Packet receive function for Ethernet AVB */ -- cgit v1.2.3 From a892493a343494bd6bab9d098593932077ff3c43 Mon Sep 17 00:00:00 2001 From: Paul Barker Date: Tue, 16 Apr 2024 13:02:52 +0100 Subject: net: ravb: Allow RX loop to move past DMA mapping errors The RX loops in ravb_rx_gbeth() and ravb_rx_rcar() skip to the next loop iteration if a zero-length descriptor is seen (indicating a DMA mapping error). However, the current RX descriptor index `priv->cur_rx[q]` was incremented at the end of the loop and so would not be incremented when we skip to the next loop iteration. This would cause the loop to keep seeing the same zero-length descriptor instead of moving on to the next descriptor. As the loop counter `i` still increments, the loop would eventually terminate so there is no risk of being stuck here forever - but we should still fix this to avoid wasting cycles. To fix this, the RX descriptor index is incremented at the top of the loop, in the for statement itself. The assignments of `entry` and `desc` are brought into the loop to avoid the need for duplication. Fixes: d8b48911fd24 ("ravb: fix ring memory allocation") Signed-off-by: Paul Barker Reviewed-by: Sergey Shtylyov Signed-off-by: Paolo Abeni --- drivers/net/ethernet/renesas/ravb_main.c | 25 +++++++++++++------------ 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/drivers/net/ethernet/renesas/ravb_main.c b/drivers/net/ethernet/renesas/ravb_main.c index 7d231d011bff..3b870926af14 100644 --- a/drivers/net/ethernet/renesas/ravb_main.c +++ b/drivers/net/ethernet/renesas/ravb_main.c @@ -775,12 +775,15 @@ static bool ravb_rx_gbeth(struct net_device *ndev, int *quota, int q) int limit; int i; - entry = priv->cur_rx[q] % priv->num_rx_ring[q]; limit = priv->dirty_rx[q] + priv->num_rx_ring[q] - priv->cur_rx[q]; stats = &priv->stats[q]; - desc = &priv->rx_ring[q].desc[entry]; - for (i = 0; i < limit && rx_packets < *quota && desc->die_dt != DT_FEMPTY; i++) { + for (i = 0; i < limit; i++, priv->cur_rx[q]++) { + entry = priv->cur_rx[q] % priv->num_rx_ring[q]; + desc = &priv->rx_ring[q].desc[entry]; + if (rx_packets == *quota || desc->die_dt == DT_FEMPTY) + break; + /* Descriptor type must be checked before all other reads */ dma_rmb(); desc_status = desc->msc; @@ -848,9 +851,6 @@ static bool ravb_rx_gbeth(struct net_device *ndev, int *quota, int q) break; } } - - entry = (++priv->cur_rx[q]) % priv->num_rx_ring[q]; - desc = &priv->rx_ring[q].desc[entry]; } /* Refill the RX ring buffers. */ @@ -891,7 +891,6 @@ static bool ravb_rx_rcar(struct net_device *ndev, int *quota, int q) { struct ravb_private *priv = netdev_priv(ndev); const struct ravb_hw_info *info = priv->info; - int entry = priv->cur_rx[q] % priv->num_rx_ring[q]; struct net_device_stats *stats = &priv->stats[q]; struct ravb_ex_rx_desc *desc; unsigned int limit, i; @@ -901,10 +900,15 @@ static bool ravb_rx_rcar(struct net_device *ndev, int *quota, int q) int rx_packets = 0; u8 desc_status; u16 pkt_len; + int entry; limit = priv->dirty_rx[q] + priv->num_rx_ring[q] - priv->cur_rx[q]; - desc = &priv->rx_ring[q].ex_desc[entry]; - for (i = 0; i < limit && rx_packets < *quota && desc->die_dt != DT_FEMPTY; i++) { + for (i = 0; i < limit; i++, priv->cur_rx[q]++) { + entry = priv->cur_rx[q] % priv->num_rx_ring[q]; + desc = &priv->rx_ring[q].ex_desc[entry]; + if (rx_packets == *quota || desc->die_dt == DT_FEMPTY) + break; + /* Descriptor type must be checked before all other reads */ dma_rmb(); desc_status = desc->msc; @@ -958,9 +962,6 @@ static bool ravb_rx_rcar(struct net_device *ndev, int *quota, int q) rx_packets++; stats->rx_bytes += pkt_len; } - - entry = (++priv->cur_rx[q]) % priv->num_rx_ring[q]; - desc = &priv->rx_ring[q].ex_desc[entry]; } /* Refill the RX ring buffers. */ -- cgit v1.2.3 From c7c449502b51c5b5de79f97a42be750b28f6ecee Mon Sep 17 00:00:00 2001 From: Paul Barker Date: Tue, 16 Apr 2024 13:02:53 +0100 Subject: net: ravb: Fix GbEth jumbo packet RX checksum handling Sending a 7kB ping packet to the RZ/G2L in v6.9-rc2 causes the following backtrace: WARNING: CPU: 0 PID: 0 at include/linux/skbuff.h:3127 skb_trim+0x30/0x38 Hardware name: Renesas SMARC EVK based on r9a07g044l2 (DT) pc : skb_trim+0x30/0x38 lr : ravb_rx_csum_gbeth+0x40/0x90 Call trace: skb_trim+0x30/0x38 ravb_rx_gbeth+0x56c/0x5cc ravb_poll+0xa0/0x204 __napi_poll+0x38/0x17c This is caused by ravb_rx_gbeth() calling ravb_rx_csum_gbeth() with the wrong skb for a packet which spans multiple descriptors. To fix this, use the correct skb. Fixes: c2da9408579d ("ravb: Add Rx checksum offload support for GbEth") Signed-off-by: Paul Barker Reviewed-by: Sergey Shtylyov Signed-off-by: Paolo Abeni --- drivers/net/ethernet/renesas/ravb_main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/ethernet/renesas/ravb_main.c b/drivers/net/ethernet/renesas/ravb_main.c index 3b870926af14..6969cdeeb67a 100644 --- a/drivers/net/ethernet/renesas/ravb_main.c +++ b/drivers/net/ethernet/renesas/ravb_main.c @@ -843,7 +843,7 @@ static bool ravb_rx_gbeth(struct net_device *ndev, int *quota, int q) priv->rx_1st_skb->protocol = eth_type_trans(priv->rx_1st_skb, ndev); if (ndev->features & NETIF_F_RXCSUM) - ravb_rx_csum_gbeth(skb); + ravb_rx_csum_gbeth(priv->rx_1st_skb); napi_gro_receive(&priv->napi[q], priv->rx_1st_skb); rx_packets++; -- cgit v1.2.3 From 2e36c9fbc476f95a1b19e3fa0a2cdf408475ff56 Mon Sep 17 00:00:00 2001 From: Paul Barker Date: Tue, 16 Apr 2024 13:02:54 +0100 Subject: net: ravb: Fix RX byte accounting for jumbo packets The RX byte accounting for jumbo packets was changed to fix a potential use-after-free bug. However, that fix used the wrong variable and so only accounted for the number of bytes in the final descriptor, not the number of bytes in the whole packet. To fix this, we can simply update our stats with the correct number of bytes before calling napi_gro_receive(). Also rename pkt_len to desc_len in ravb_rx_gbeth() to avoid any future confusion. The variable name pkt_len is correct in ravb_rx_rcar() as that function does not handle packets spanning multiple descriptors. Fixes: 5a5a3e564de6 ("ravb: Fix potential use-after-free in ravb_rx_gbeth()") Signed-off-by: Paul Barker Reviewed-by: Sergey Shtylyov Signed-off-by: Paolo Abeni --- drivers/net/ethernet/renesas/ravb_main.c | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/drivers/net/ethernet/renesas/ravb_main.c b/drivers/net/ethernet/renesas/ravb_main.c index 6969cdeeb67a..fcb756d77681 100644 --- a/drivers/net/ethernet/renesas/ravb_main.c +++ b/drivers/net/ethernet/renesas/ravb_main.c @@ -769,7 +769,7 @@ static bool ravb_rx_gbeth(struct net_device *ndev, int *quota, int q) dma_addr_t dma_addr; int rx_packets = 0; u8 desc_status; - u16 pkt_len; + u16 desc_len; u8 die_dt; int entry; int limit; @@ -787,10 +787,10 @@ static bool ravb_rx_gbeth(struct net_device *ndev, int *quota, int q) /* Descriptor type must be checked before all other reads */ dma_rmb(); desc_status = desc->msc; - pkt_len = le16_to_cpu(desc->ds_cc) & RX_DS; + desc_len = le16_to_cpu(desc->ds_cc) & RX_DS; /* We use 0-byte descriptors to mark the DMA mapping errors */ - if (!pkt_len) + if (!desc_len) continue; if (desc_status & MSC_MC) @@ -811,25 +811,25 @@ static bool ravb_rx_gbeth(struct net_device *ndev, int *quota, int q) switch (die_dt) { case DT_FSINGLE: skb = ravb_get_skb_gbeth(ndev, entry, desc); - skb_put(skb, pkt_len); + skb_put(skb, desc_len); skb->protocol = eth_type_trans(skb, ndev); if (ndev->features & NETIF_F_RXCSUM) ravb_rx_csum_gbeth(skb); napi_gro_receive(&priv->napi[q], skb); rx_packets++; - stats->rx_bytes += pkt_len; + stats->rx_bytes += desc_len; break; case DT_FSTART: priv->rx_1st_skb = ravb_get_skb_gbeth(ndev, entry, desc); - skb_put(priv->rx_1st_skb, pkt_len); + skb_put(priv->rx_1st_skb, desc_len); break; case DT_FMID: skb = ravb_get_skb_gbeth(ndev, entry, desc); skb_copy_to_linear_data_offset(priv->rx_1st_skb, priv->rx_1st_skb->len, skb->data, - pkt_len); - skb_put(priv->rx_1st_skb, pkt_len); + desc_len); + skb_put(priv->rx_1st_skb, desc_len); dev_kfree_skb(skb); break; case DT_FEND: @@ -837,17 +837,17 @@ static bool ravb_rx_gbeth(struct net_device *ndev, int *quota, int q) skb_copy_to_linear_data_offset(priv->rx_1st_skb, priv->rx_1st_skb->len, skb->data, - pkt_len); - skb_put(priv->rx_1st_skb, pkt_len); + desc_len); + skb_put(priv->rx_1st_skb, desc_len); dev_kfree_skb(skb); priv->rx_1st_skb->protocol = eth_type_trans(priv->rx_1st_skb, ndev); if (ndev->features & NETIF_F_RXCSUM) ravb_rx_csum_gbeth(priv->rx_1st_skb); + stats->rx_bytes += priv->rx_1st_skb->len; napi_gro_receive(&priv->napi[q], priv->rx_1st_skb); rx_packets++; - stats->rx_bytes += pkt_len; break; } } -- cgit v1.2.3 From 3aadf100f93d80815685493d60cd8cab206403df Mon Sep 17 00:00:00 2001 From: "Jason A. Donenfeld" Date: Thu, 18 Apr 2024 13:45:17 +0200 Subject: Revert "vmgenid: emit uevent when VMGENID updates" This reverts commit ad6bcdad2b6724e113f191a12f859a9e8456b26d. I had nak'd it, and Greg said on the thread that it links that he wasn't going to take it either, especially since it's not his code or his tree, but then, seemingly accidentally, it got pushed up some months later, in what looks like a mistake, with no further discussion in the linked thread. So revert it, since it's clearly not intended. Fixes: ad6bcdad2b67 ("vmgenid: emit uevent when VMGENID updates") Cc: stable@vger.kernel.org Acked-by: Greg Kroah-Hartman Link: https://lore.kernel.org/r/20230531095119.11202-2-bchalios@amazon.es Signed-off-by: Jason A. Donenfeld --- drivers/virt/vmgenid.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/virt/vmgenid.c b/drivers/virt/vmgenid.c index b67a28da4702..a1c467a0e9f7 100644 --- a/drivers/virt/vmgenid.c +++ b/drivers/virt/vmgenid.c @@ -68,7 +68,6 @@ out: static void vmgenid_notify(struct acpi_device *device, u32 event) { struct vmgenid_state *state = acpi_driver_data(device); - char *envp[] = { "NEW_VMGENID=1", NULL }; u8 old_id[VMGENID_SIZE]; memcpy(old_id, state->this_id, sizeof(old_id)); @@ -76,7 +75,6 @@ static void vmgenid_notify(struct acpi_device *device, u32 event) if (!memcmp(old_id, state->this_id, sizeof(old_id))) return; add_vmfork_randomness(state->this_id, sizeof(state->this_id)); - kobject_uevent_env(&device->dev.kobj, KOBJ_CHANGE, envp); } static const struct acpi_device_id vmgenid_ids[] = { -- cgit v1.2.3 From 1607830dadeefc407e4956336d9fcd9e9defd810 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Thu, 18 Apr 2024 16:33:28 +0200 Subject: Revert "usb: cdc-wdm: close race between read and workqueue" MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This reverts commit 339f83612f3a569b194680768b22bf113c26a29d. It has been found to cause problems in a number of Chromebook devices, so revert the change until it can be brought back in a safe way. Link: https://lore.kernel.org/r/385a3519-b45d-48c5-a6fd-a3fdb6bec92f@chromium.org Reported-by:: Aleksander Morgado Fixes: 339f83612f3a ("usb: cdc-wdm: close race between read and workqueue") Cc: stable Cc: Oliver Neukum Cc: Bjørn Mork Signed-off-by: Greg Kroah-Hartman --- drivers/usb/class/cdc-wdm.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/drivers/usb/class/cdc-wdm.c b/drivers/usb/class/cdc-wdm.c index c8262e2f2917..c553decb5461 100644 --- a/drivers/usb/class/cdc-wdm.c +++ b/drivers/usb/class/cdc-wdm.c @@ -485,7 +485,6 @@ out_free_mem: static int service_outstanding_interrupt(struct wdm_device *desc) { int rv = 0; - int used; /* submit read urb only if the device is waiting for it */ if (!desc->resp_count || !--desc->resp_count) @@ -500,10 +499,7 @@ static int service_outstanding_interrupt(struct wdm_device *desc) goto out; } - used = test_and_set_bit(WDM_RESPONDING, &desc->flags); - if (used) - goto out; - + set_bit(WDM_RESPONDING, &desc->flags); spin_unlock_irq(&desc->iuspin); rv = usb_submit_urb(desc->response, GFP_KERNEL); spin_lock_irq(&desc->iuspin); -- cgit v1.2.3 From f2e0eee4703869dc5edb5302a919861566ca7797 Mon Sep 17 00:00:00 2001 From: Thinh Nguyen Date: Tue, 16 Apr 2024 01:23:07 +0000 Subject: usb: dwc3: ep0: Don't reset resource alloc flag The DWC3_EP_RESOURCE_ALLOCATED flag ensures that the resource of an endpoint is only assigned once. Unless the endpoint is reset, don't clear this flag. Otherwise we may set endpoint resource again, which prevents the driver from initiate transfer after handling a STALL or endpoint halt to the control endpoint. Cc: stable@vger.kernel.org Fixes: b311048c174d ("usb: dwc3: gadget: Rewrite endpoint allocation flow") Signed-off-by: Thinh Nguyen Link: https://lore.kernel.org/r/00122b7cc5be06abef461776e7cc9f5ebc8bc1cb.1713229786.git.Thinh.Nguyen@synopsys.com Signed-off-by: Greg Kroah-Hartman --- drivers/usb/dwc3/ep0.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/usb/dwc3/ep0.c b/drivers/usb/dwc3/ep0.c index 72bb722da2f2..d96ffbe52039 100644 --- a/drivers/usb/dwc3/ep0.c +++ b/drivers/usb/dwc3/ep0.c @@ -226,7 +226,8 @@ void dwc3_ep0_stall_and_restart(struct dwc3 *dwc) /* reinitialize physical ep1 */ dep = dwc->eps[1]; - dep->flags = DWC3_EP_ENABLED; + dep->flags &= DWC3_EP_RESOURCE_ALLOCATED; + dep->flags |= DWC3_EP_ENABLED; /* stall is always issued on EP0 */ dep = dwc->eps[0]; -- cgit v1.2.3 From 582ee2f9d268d302595db3e36b985e5cbb93284d Mon Sep 17 00:00:00 2001 From: Daniele Palmas Date: Thu, 18 Apr 2024 13:34:30 +0200 Subject: USB: serial: option: add Telit FN920C04 rmnet compositions Add the following Telit FN920C04 compositions: 0x10a0: rmnet + tty (AT/NMEA) + tty (AT) + tty (diag) T: Bus=03 Lev=01 Prnt=03 Port=06 Cnt=01 Dev#= 5 Spd=480 MxCh= 0 D: Ver= 2.01 Cls=00(>ifc ) Sub=00 Prot=00 MxPS=64 #Cfgs= 1 P: Vendor=1bc7 ProdID=10a0 Rev=05.15 S: Manufacturer=Telit Cinterion S: Product=FN920 S: SerialNumber=92c4c4d8 C: #Ifs= 4 Cfg#= 1 Atr=e0 MxPwr=500mA I: If#= 0 Alt= 0 #EPs= 3 Cls=ff(vend.) Sub=ff Prot=50 Driver=qmi_wwan E: Ad=01(O) Atr=02(Bulk) MxPS= 512 Ivl=0ms E: Ad=81(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms E: Ad=82(I) Atr=03(Int.) MxPS= 8 Ivl=32ms I: If#= 1 Alt= 0 #EPs= 3 Cls=ff(vend.) Sub=ff Prot=60 Driver=option E: Ad=02(O) Atr=02(Bulk) MxPS= 512 Ivl=0ms E: Ad=83(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms E: Ad=84(I) Atr=03(Int.) MxPS= 10 Ivl=32ms I: If#= 2 Alt= 0 #EPs= 3 Cls=ff(vend.) Sub=ff Prot=40 Driver=option E: Ad=03(O) Atr=02(Bulk) MxPS= 512 Ivl=0ms E: Ad=85(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms E: Ad=86(I) Atr=03(Int.) MxPS= 10 Ivl=32ms I: If#= 3 Alt= 0 #EPs= 2 Cls=ff(vend.) Sub=ff Prot=30 Driver=option E: Ad=04(O) Atr=02(Bulk) MxPS= 512 Ivl=0ms E: Ad=87(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms 0x10a4: rmnet + tty (AT) + tty (AT) + tty (diag) T: Bus=03 Lev=01 Prnt=03 Port=06 Cnt=01 Dev#= 8 Spd=480 MxCh= 0 D: Ver= 2.01 Cls=00(>ifc ) Sub=00 Prot=00 MxPS=64 #Cfgs= 1 P: Vendor=1bc7 ProdID=10a4 Rev=05.15 S: Manufacturer=Telit Cinterion S: Product=FN920 S: SerialNumber=92c4c4d8 C: #Ifs= 4 Cfg#= 1 Atr=e0 MxPwr=500mA I: If#= 0 Alt= 0 #EPs= 3 Cls=ff(vend.) Sub=ff Prot=50 Driver=qmi_wwan E: Ad=01(O) Atr=02(Bulk) MxPS= 512 Ivl=0ms E: Ad=81(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms E: Ad=82(I) Atr=03(Int.) MxPS= 8 Ivl=32ms I: If#= 1 Alt= 0 #EPs= 3 Cls=ff(vend.) Sub=ff Prot=40 Driver=option E: Ad=02(O) Atr=02(Bulk) MxPS= 512 Ivl=0ms E: Ad=83(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms E: Ad=84(I) Atr=03(Int.) MxPS= 10 Ivl=32ms I: If#= 2 Alt= 0 #EPs= 3 Cls=ff(vend.) Sub=ff Prot=40 Driver=option E: Ad=03(O) Atr=02(Bulk) MxPS= 512 Ivl=0ms E: Ad=85(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms E: Ad=86(I) Atr=03(Int.) MxPS= 10 Ivl=32ms I: If#= 3 Alt= 0 #EPs= 2 Cls=ff(vend.) Sub=ff Prot=30 Driver=option E: Ad=04(O) Atr=02(Bulk) MxPS= 512 Ivl=0ms E: Ad=87(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms 0x10a9: rmnet + tty (AT) + tty (diag) + DPL (data packet logging) + adb T: Bus=03 Lev=01 Prnt=03 Port=06 Cnt=01 Dev#= 9 Spd=480 MxCh= 0 D: Ver= 2.01 Cls=00(>ifc ) Sub=00 Prot=00 MxPS=64 #Cfgs= 1 P: Vendor=1bc7 ProdID=10a9 Rev=05.15 S: Manufacturer=Telit Cinterion S: Product=FN920 S: SerialNumber=92c4c4d8 C: #Ifs= 5 Cfg#= 1 Atr=e0 MxPwr=500mA I: If#= 0 Alt= 0 #EPs= 3 Cls=ff(vend.) Sub=ff Prot=50 Driver=qmi_wwan E: Ad=01(O) Atr=02(Bulk) MxPS= 512 Ivl=0ms E: Ad=81(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms E: Ad=82(I) Atr=03(Int.) MxPS= 8 Ivl=32ms I: If#= 1 Alt= 0 #EPs= 3 Cls=ff(vend.) Sub=ff Prot=40 Driver=option E: Ad=02(O) Atr=02(Bulk) MxPS= 512 Ivl=0ms E: Ad=83(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms E: Ad=84(I) Atr=03(Int.) MxPS= 10 Ivl=32ms I: If#= 2 Alt= 0 #EPs= 2 Cls=ff(vend.) Sub=ff Prot=30 Driver=option E: Ad=03(O) Atr=02(Bulk) MxPS= 512 Ivl=0ms E: Ad=85(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms I: If#= 3 Alt= 0 #EPs= 1 Cls=ff(vend.) Sub=ff Prot=80 Driver=(none) E: Ad=86(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms I: If#= 4 Alt= 0 #EPs= 2 Cls=ff(vend.) Sub=42 Prot=01 Driver=(none) E: Ad=04(O) Atr=02(Bulk) MxPS= 512 Ivl=0ms E: Ad=87(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms Signed-off-by: Daniele Palmas Cc: stable@vger.kernel.org Signed-off-by: Johan Hovold --- drivers/usb/serial/option.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c index e22612017f66..8a5846d4adf6 100644 --- a/drivers/usb/serial/option.c +++ b/drivers/usb/serial/option.c @@ -1376,6 +1376,12 @@ static const struct usb_device_id option_ids[] = { .driver_info = NCTRL(2) | RSVD(3) }, { USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x1083, 0xff), /* Telit FE990 (ECM) */ .driver_info = NCTRL(0) | RSVD(1) }, + { USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x10a0, 0xff), /* Telit FN20C04 (rmnet) */ + .driver_info = RSVD(0) | NCTRL(3) }, + { USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x10a4, 0xff), /* Telit FN20C04 (rmnet) */ + .driver_info = RSVD(0) | NCTRL(3) }, + { USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x10a9, 0xff), /* Telit FN20C04 (rmnet) */ + .driver_info = RSVD(0) | NCTRL(2) | RSVD(3) | RSVD(4) }, { USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_ME910), .driver_info = NCTRL(0) | RSVD(1) | RSVD(3) }, { USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_ME910_DUAL_MODEM), -- cgit v1.2.3 From 9543f6e26634537997b6e909c20911b7bf4876de Mon Sep 17 00:00:00 2001 From: Eric Biggers Date: Tue, 16 Apr 2024 23:04:34 -0700 Subject: x86/cpufeatures: Fix dependencies for GFNI, VAES, and VPCLMULQDQ Fix cpuid_deps[] to list the correct dependencies for GFNI, VAES, and VPCLMULQDQ. These features don't depend on AVX512, and there exist CPUs that support these features but not AVX512. GFNI actually doesn't even depend on AVX. This prevents GFNI from being unnecessarily disabled if AVX is disabled to mitigate the GDS vulnerability. This also prevents all three features from being unnecessarily disabled if AVX512VL (or its dependency AVX512F) were to be disabled, but it looks like there isn't any case where this happens anyway. Fixes: c128dbfa0f87 ("x86/cpufeatures: Enable new SSE/AVX/AVX512 CPU features") Signed-off-by: Eric Biggers Signed-off-by: Borislav Petkov (AMD) Acked-by: Dave Hansen Link: https://lore.kernel.org/r/20240417060434.47101-1-ebiggers@kernel.org --- arch/x86/kernel/cpu/cpuid-deps.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/arch/x86/kernel/cpu/cpuid-deps.c b/arch/x86/kernel/cpu/cpuid-deps.c index b7174209d855..946813d816bf 100644 --- a/arch/x86/kernel/cpu/cpuid-deps.c +++ b/arch/x86/kernel/cpu/cpuid-deps.c @@ -44,7 +44,10 @@ static const struct cpuid_dep cpuid_deps[] = { { X86_FEATURE_F16C, X86_FEATURE_XMM2, }, { X86_FEATURE_AES, X86_FEATURE_XMM2 }, { X86_FEATURE_SHA_NI, X86_FEATURE_XMM2 }, + { X86_FEATURE_GFNI, X86_FEATURE_XMM2 }, { X86_FEATURE_FMA, X86_FEATURE_AVX }, + { X86_FEATURE_VAES, X86_FEATURE_AVX }, + { X86_FEATURE_VPCLMULQDQ, X86_FEATURE_AVX }, { X86_FEATURE_AVX2, X86_FEATURE_AVX, }, { X86_FEATURE_AVX512F, X86_FEATURE_AVX, }, { X86_FEATURE_AVX512IFMA, X86_FEATURE_AVX512F }, @@ -56,9 +59,6 @@ static const struct cpuid_dep cpuid_deps[] = { { X86_FEATURE_AVX512VL, X86_FEATURE_AVX512F }, { X86_FEATURE_AVX512VBMI, X86_FEATURE_AVX512F }, { X86_FEATURE_AVX512_VBMI2, X86_FEATURE_AVX512VL }, - { X86_FEATURE_GFNI, X86_FEATURE_AVX512VL }, - { X86_FEATURE_VAES, X86_FEATURE_AVX512VL }, - { X86_FEATURE_VPCLMULQDQ, X86_FEATURE_AVX512VL }, { X86_FEATURE_AVX512_VNNI, X86_FEATURE_AVX512VL }, { X86_FEATURE_AVX512_BITALG, X86_FEATURE_AVX512VL }, { X86_FEATURE_AVX512_4VNNIW, X86_FEATURE_AVX512F }, -- cgit v1.2.3 From 752863bddacab6b5c5164b1df8c8b2e3a175ee28 Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Wed, 17 Apr 2024 16:47:43 +0200 Subject: block: propagate partition scanning errors to the BLKRRPART ioctl Commit 4601b4b130de ("block: reopen the device in blkdev_reread_part") lost the propagation of I/O errors from the low-level read of the partition table to the user space caller of the BLKRRPART. Apparently some user space relies on, so restore the propagation. This isn't exactly pretty as other block device open calls explicitly do not are about these errors, so add a new BLK_OPEN_STRICT_SCAN to opt into the error propagation. Fixes: 4601b4b130de ("block: reopen the device in blkdev_reread_part") Reported-by: Saranya Muruganandam Signed-off-by: Christoph Hellwig Reviewed-by: Chaitanya Kulkarni Reviewed-by: Shin'ichiro Kawasaki Tested-by: Shin'ichiro Kawasaki Link: https://lore.kernel.org/r/20240417144743.2277601-1-hch@lst.de Signed-off-by: Jens Axboe --- block/bdev.c | 29 +++++++++++++++++++---------- block/ioctl.c | 3 ++- include/linux/blkdev.h | 2 ++ 3 files changed, 23 insertions(+), 11 deletions(-) diff --git a/block/bdev.c b/block/bdev.c index 7a5f611c3d2e..cea51dca8753 100644 --- a/block/bdev.c +++ b/block/bdev.c @@ -652,6 +652,14 @@ static void blkdev_flush_mapping(struct block_device *bdev) bdev_write_inode(bdev); } +static void blkdev_put_whole(struct block_device *bdev) +{ + if (atomic_dec_and_test(&bdev->bd_openers)) + blkdev_flush_mapping(bdev); + if (bdev->bd_disk->fops->release) + bdev->bd_disk->fops->release(bdev->bd_disk); +} + static int blkdev_get_whole(struct block_device *bdev, blk_mode_t mode) { struct gendisk *disk = bdev->bd_disk; @@ -670,20 +678,21 @@ static int blkdev_get_whole(struct block_device *bdev, blk_mode_t mode) if (!atomic_read(&bdev->bd_openers)) set_init_blocksize(bdev); - if (test_bit(GD_NEED_PART_SCAN, &disk->state)) - bdev_disk_changed(disk, false); atomic_inc(&bdev->bd_openers); + if (test_bit(GD_NEED_PART_SCAN, &disk->state)) { + /* + * Only return scanning errors if we are called from contexts + * that explicitly want them, e.g. the BLKRRPART ioctl. + */ + ret = bdev_disk_changed(disk, false); + if (ret && (mode & BLK_OPEN_STRICT_SCAN)) { + blkdev_put_whole(bdev); + return ret; + } + } return 0; } -static void blkdev_put_whole(struct block_device *bdev) -{ - if (atomic_dec_and_test(&bdev->bd_openers)) - blkdev_flush_mapping(bdev); - if (bdev->bd_disk->fops->release) - bdev->bd_disk->fops->release(bdev->bd_disk); -} - static int blkdev_get_part(struct block_device *part, blk_mode_t mode) { struct gendisk *disk = part->bd_disk; diff --git a/block/ioctl.c b/block/ioctl.c index a9028a2c2db5..f505f9c341eb 100644 --- a/block/ioctl.c +++ b/block/ioctl.c @@ -563,7 +563,8 @@ static int blkdev_common_ioctl(struct block_device *bdev, blk_mode_t mode, return -EACCES; if (bdev_is_partition(bdev)) return -EINVAL; - return disk_scan_partitions(bdev->bd_disk, mode); + return disk_scan_partitions(bdev->bd_disk, + mode | BLK_OPEN_STRICT_SCAN); case BLKTRACESTART: case BLKTRACESTOP: case BLKTRACETEARDOWN: diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h index c3e8f7cf96be..d16320852c4b 100644 --- a/include/linux/blkdev.h +++ b/include/linux/blkdev.h @@ -128,6 +128,8 @@ typedef unsigned int __bitwise blk_mode_t; #define BLK_OPEN_WRITE_IOCTL ((__force blk_mode_t)(1 << 4)) /* open is exclusive wrt all other BLK_OPEN_WRITE opens to the device */ #define BLK_OPEN_RESTRICT_WRITES ((__force blk_mode_t)(1 << 5)) +/* return partition scanning errors */ +#define BLK_OPEN_STRICT_SCAN ((__force blk_mode_t)(1 << 6)) struct gendisk { /* -- cgit v1.2.3 From 2f7ef5bb4a2f3e481ef05fab946edb97c84f67cf Mon Sep 17 00:00:00 2001 From: Johannes Thumshirn Date: Wed, 17 Apr 2024 10:45:47 +0200 Subject: btrfs: fix information leak in btrfs_ioctl_logical_to_ino() Syzbot reported the following information leak for in btrfs_ioctl_logical_to_ino(): BUG: KMSAN: kernel-infoleak in instrument_copy_to_user include/linux/instrumented.h:114 [inline] BUG: KMSAN: kernel-infoleak in _copy_to_user+0xbc/0x110 lib/usercopy.c:40 instrument_copy_to_user include/linux/instrumented.h:114 [inline] _copy_to_user+0xbc/0x110 lib/usercopy.c:40 copy_to_user include/linux/uaccess.h:191 [inline] btrfs_ioctl_logical_to_ino+0x440/0x750 fs/btrfs/ioctl.c:3499 btrfs_ioctl+0x714/0x1260 vfs_ioctl fs/ioctl.c:51 [inline] __do_sys_ioctl fs/ioctl.c:904 [inline] __se_sys_ioctl+0x261/0x450 fs/ioctl.c:890 __x64_sys_ioctl+0x96/0xe0 fs/ioctl.c:890 x64_sys_call+0x1883/0x3b50 arch/x86/include/generated/asm/syscalls_64.h:17 do_syscall_x64 arch/x86/entry/common.c:52 [inline] do_syscall_64+0xcf/0x1e0 arch/x86/entry/common.c:83 entry_SYSCALL_64_after_hwframe+0x77/0x7f Uninit was created at: __kmalloc_large_node+0x231/0x370 mm/slub.c:3921 __do_kmalloc_node mm/slub.c:3954 [inline] __kmalloc_node+0xb07/0x1060 mm/slub.c:3973 kmalloc_node include/linux/slab.h:648 [inline] kvmalloc_node+0xc0/0x2d0 mm/util.c:634 kvmalloc include/linux/slab.h:766 [inline] init_data_container+0x49/0x1e0 fs/btrfs/backref.c:2779 btrfs_ioctl_logical_to_ino+0x17c/0x750 fs/btrfs/ioctl.c:3480 btrfs_ioctl+0x714/0x1260 vfs_ioctl fs/ioctl.c:51 [inline] __do_sys_ioctl fs/ioctl.c:904 [inline] __se_sys_ioctl+0x261/0x450 fs/ioctl.c:890 __x64_sys_ioctl+0x96/0xe0 fs/ioctl.c:890 x64_sys_call+0x1883/0x3b50 arch/x86/include/generated/asm/syscalls_64.h:17 do_syscall_x64 arch/x86/entry/common.c:52 [inline] do_syscall_64+0xcf/0x1e0 arch/x86/entry/common.c:83 entry_SYSCALL_64_after_hwframe+0x77/0x7f Bytes 40-65535 of 65536 are uninitialized Memory access of size 65536 starts at ffff888045a40000 This happens, because we're copying a 'struct btrfs_data_container' back to user-space. This btrfs_data_container is allocated in 'init_data_container()' via kvmalloc(), which does not zero-fill the memory. Fix this by using kvzalloc() which zeroes out the memory on allocation. CC: stable@vger.kernel.org # 4.14+ Reported-by: Reviewed-by: Qu Wenruo Reviewed-by: Filipe Manana Signed-off-by: Johannes Thumshirn Reviewed-by: David Sterba Signed-off-by: David Sterba --- fs/btrfs/backref.c | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/fs/btrfs/backref.c b/fs/btrfs/backref.c index c1e6a5bbeeaf..58110c968667 100644 --- a/fs/btrfs/backref.c +++ b/fs/btrfs/backref.c @@ -2776,20 +2776,14 @@ struct btrfs_data_container *init_data_container(u32 total_bytes) size_t alloc_bytes; alloc_bytes = max_t(size_t, total_bytes, sizeof(*data)); - data = kvmalloc(alloc_bytes, GFP_KERNEL); + data = kvzalloc(alloc_bytes, GFP_KERNEL); if (!data) return ERR_PTR(-ENOMEM); - if (total_bytes >= sizeof(*data)) { + if (total_bytes >= sizeof(*data)) data->bytes_left = total_bytes - sizeof(*data); - data->bytes_missing = 0; - } else { + else data->bytes_missing = sizeof(*data) - total_bytes; - data->bytes_left = 0; - } - - data->elem_cnt = 0; - data->elem_missed = 0; return data; } -- cgit v1.2.3 From fe1c6c7acce10baf9521d6dccc17268d91ee2305 Mon Sep 17 00:00:00 2001 From: Qu Wenruo Date: Tue, 9 Apr 2024 20:32:34 +0930 Subject: btrfs: fix wrong block_start calculation for btrfs_drop_extent_map_range() [BUG] During my extent_map cleanup/refactor, with extra sanity checks, extent-map-tests::test_case_7() would not pass the checks. The problem is, after btrfs_drop_extent_map_range(), the resulted extent_map has a @block_start way too large. Meanwhile my btrfs_file_extent_item based members are returning a correct @disk_bytenr/@offset combination. The extent map layout looks like this: 0 16K 32K 48K | PINNED | | Regular | The regular em at [32K, 48K) also has 32K @block_start. Then drop range [0, 36K), which should shrink the regular one to be [36K, 48K). However the @block_start is incorrect, we expect 32K + 4K, but got 52K. [CAUSE] Inside btrfs_drop_extent_map_range() function, if we hit an extent_map that covers the target range but is still beyond it, we need to split that extent map into half: |<-- drop range -->| |<----- existing extent_map --->| And if the extent map is not compressed, we need to forward extent_map::block_start by the difference between the end of drop range and the extent map start. However in that particular case, the difference is calculated using (start + len - em->start). The problem is @start can be modified if the drop range covers any pinned extent. This leads to wrong calculation, and would be caught by my later extent_map sanity checks, which checks the em::block_start against btrfs_file_extent_item::disk_bytenr + btrfs_file_extent_item::offset. This is a regression caused by commit c962098ca4af ("btrfs: fix incorrect splitting in btrfs_drop_extent_map_range"), which removed the @len update for pinned extents. [FIX] Fix it by avoiding using @start completely, and use @end - em->start instead, which @end is exclusive bytenr number. And update the test case to verify the @block_start to prevent such problem from happening. Thankfully this is not going to lead to any data corruption, as IO path does not utilize btrfs_drop_extent_map_range() with @skip_pinned set. So this fix is only here for the sake of consistency/correctness. CC: stable@vger.kernel.org # 6.5+ Fixes: c962098ca4af ("btrfs: fix incorrect splitting in btrfs_drop_extent_map_range") Reviewed-by: Filipe Manana Signed-off-by: Qu Wenruo Signed-off-by: David Sterba --- fs/btrfs/extent_map.c | 2 +- fs/btrfs/tests/extent-map-tests.c | 5 +++++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/fs/btrfs/extent_map.c b/fs/btrfs/extent_map.c index 445f7716f1e2..24a048210b15 100644 --- a/fs/btrfs/extent_map.c +++ b/fs/btrfs/extent_map.c @@ -817,7 +817,7 @@ void btrfs_drop_extent_map_range(struct btrfs_inode *inode, u64 start, u64 end, split->block_len = em->block_len; split->orig_start = em->orig_start; } else { - const u64 diff = start + len - em->start; + const u64 diff = end - em->start; split->block_len = split->len; split->block_start += diff; diff --git a/fs/btrfs/tests/extent-map-tests.c b/fs/btrfs/tests/extent-map-tests.c index 253cce7ffecf..47b5d301038e 100644 --- a/fs/btrfs/tests/extent-map-tests.c +++ b/fs/btrfs/tests/extent-map-tests.c @@ -847,6 +847,11 @@ static int test_case_7(struct btrfs_fs_info *fs_info) goto out; } + if (em->block_start != SZ_32K + SZ_4K) { + test_err("em->block_start is %llu, expected 36K", em->block_start); + goto out; + } + free_extent_map(em); read_lock(&em_tree->lock); -- cgit v1.2.3 From 56f78615bcb1c3ba58a5d9911bad3d9185cf141b Mon Sep 17 00:00:00 2001 From: Jose Ignacio Tornos Martinez Date: Wed, 17 Apr 2024 10:55:13 +0200 Subject: net: usb: ax88179_178a: avoid writing the mac address before first reading After the commit d2689b6a86b9 ("net: usb: ax88179_178a: avoid two consecutive device resets"), reset operation, in which the default mac address from the device is read, is not executed from bind operation and the random address, that is pregenerated just in case, is direclty written the first time in the device, so the default one from the device is not even read. This writing is not dangerous because is volatile and the default mac address is not missed. In order to avoid this and keep the simplification to have only one reset and reduce the delays, restore the reset from bind operation and remove the reset that is commanded from open operation. The behavior is the same but everything is ready for usbnet_probe. Tested with ASIX AX88179 USB Gigabit Ethernet devices. Restore the old behavior for the rest of possible devices because I don't have the hardware to test. cc: stable@vger.kernel.org # 6.6+ Fixes: d2689b6a86b9 ("net: usb: ax88179_178a: avoid two consecutive device resets") Reported-by: Jarkko Palviainen Signed-off-by: Jose Ignacio Tornos Martinez Link: https://lore.kernel.org/r/20240417085524.219532-1-jtornosm@redhat.com Signed-off-by: Jakub Kicinski --- drivers/net/usb/ax88179_178a.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/usb/ax88179_178a.c b/drivers/net/usb/ax88179_178a.c index a9c418890a1c..752f821a1990 100644 --- a/drivers/net/usb/ax88179_178a.c +++ b/drivers/net/usb/ax88179_178a.c @@ -1317,6 +1317,8 @@ static int ax88179_bind(struct usbnet *dev, struct usb_interface *intf) netif_set_tso_max_size(dev->net, 16384); + ax88179_reset(dev); + return 0; } @@ -1695,7 +1697,6 @@ static const struct driver_info ax88179_info = { .unbind = ax88179_unbind, .status = ax88179_status, .link_reset = ax88179_link_reset, - .reset = ax88179_reset, .stop = ax88179_stop, .flags = FLAG_ETHER | FLAG_FRAMING_AX, .rx_fixup = ax88179_rx_fixup, @@ -1708,7 +1709,6 @@ static const struct driver_info ax88178a_info = { .unbind = ax88179_unbind, .status = ax88179_status, .link_reset = ax88179_link_reset, - .reset = ax88179_reset, .stop = ax88179_stop, .flags = FLAG_ETHER | FLAG_FRAMING_AX, .rx_fixup = ax88179_rx_fixup, -- cgit v1.2.3 From c24cd679b075b0e953ea167b0aa2b2d59e4eba7f Mon Sep 17 00:00:00 2001 From: Siddharth Vadapalli Date: Wed, 17 Apr 2024 15:24:25 +0530 Subject: net: ethernet: ti: am65-cpsw-nuss: cleanup DMA Channels before using them The TX and RX DMA Channels used by the driver to exchange data with CPSW are not guaranteed to be in a clean state during driver initialization. The Bootloader could have used the same DMA Channels without cleaning them up in the event of failure. Thus, reset and disable the DMA Channels to ensure that they are in a clean state before using them. Fixes: 93a76530316a ("net: ethernet: ti: introduce am65x/j721e gigabit eth subsystem driver") Reported-by: Schuyler Patton Signed-off-by: Siddharth Vadapalli Reviewed-by: Roger Quadros Link: https://lore.kernel.org/r/20240417095425.2253876-1-s-vadapalli@ti.com Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/ti/am65-cpsw-nuss.c | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/drivers/net/ethernet/ti/am65-cpsw-nuss.c b/drivers/net/ethernet/ti/am65-cpsw-nuss.c index 2939a21ca74f..1d00e21808c1 100644 --- a/drivers/net/ethernet/ti/am65-cpsw-nuss.c +++ b/drivers/net/ethernet/ti/am65-cpsw-nuss.c @@ -2793,6 +2793,8 @@ static void am65_cpsw_unregister_devlink(struct am65_cpsw_common *common) static int am65_cpsw_nuss_register_ndevs(struct am65_cpsw_common *common) { + struct am65_cpsw_rx_chn *rx_chan = &common->rx_chns; + struct am65_cpsw_tx_chn *tx_chan = common->tx_chns; struct device *dev = common->dev; struct am65_cpsw_port *port; int ret = 0, i; @@ -2805,6 +2807,22 @@ static int am65_cpsw_nuss_register_ndevs(struct am65_cpsw_common *common) if (ret) return ret; + /* The DMA Channels are not guaranteed to be in a clean state. + * Reset and disable them to ensure that they are back to the + * clean state and ready to be used. + */ + for (i = 0; i < common->tx_ch_num; i++) { + k3_udma_glue_reset_tx_chn(tx_chan[i].tx_chn, &tx_chan[i], + am65_cpsw_nuss_tx_cleanup); + k3_udma_glue_disable_tx_chn(tx_chan[i].tx_chn); + } + + for (i = 0; i < AM65_CPSW_MAX_RX_FLOWS; i++) + k3_udma_glue_reset_rx_chn(rx_chan->rx_chn, i, rx_chan, + am65_cpsw_nuss_rx_cleanup, !!i); + + k3_udma_glue_disable_rx_chn(rx_chan->rx_chn); + ret = am65_cpsw_nuss_register_devlink(common); if (ret) return ret; -- cgit v1.2.3 From 2b504e1620376052744ebee408a84394bdaef40a Mon Sep 17 00:00:00 2001 From: Ard Biesheuvel Date: Mon, 15 Apr 2024 09:54:14 +0200 Subject: arm64/head: Drop unnecessary pre-disable-MMU workaround The Falkor erratum that results in the need for an ISB before clearing the M bit in SCTLR_ELx only applies to execution at exception level x, and so the workaround is not needed when disabling the EL1 MMU while running at EL2. Signed-off-by: Ard Biesheuvel Acked-by: Marc Zyngier Acked-by: Mark Rutland Link: https://lore.kernel.org/r/20240415075412.2347624-5-ardb+git@google.com Signed-off-by: Catalin Marinas --- arch/arm64/kernel/head.S | 2 -- 1 file changed, 2 deletions(-) diff --git a/arch/arm64/kernel/head.S b/arch/arm64/kernel/head.S index 06234c3a15f3..b8bbd72cb194 100644 --- a/arch/arm64/kernel/head.S +++ b/arch/arm64/kernel/head.S @@ -323,13 +323,11 @@ SYM_INNER_LABEL(init_el2, SYM_L_LOCAL) cbz x0, 2f /* Set a sane SCTLR_EL1, the VHE way */ - pre_disable_mmu_workaround msr_s SYS_SCTLR_EL12, x1 mov x2, #BOOT_CPU_FLAG_E2H b 3f 2: - pre_disable_mmu_workaround msr sctlr_el1, x1 mov x2, xzr 3: -- cgit v1.2.3 From 34e526cb7d46726b2ae5f83f2892d00ebb088509 Mon Sep 17 00:00:00 2001 From: Ard Biesheuvel Date: Mon, 15 Apr 2024 09:54:15 +0200 Subject: arm64/head: Disable MMU at EL2 before clearing HCR_EL2.E2H Even though the boot protocol stipulates otherwise, an exception has been made for the EFI stub, and entering the core kernel with the MMU enabled is permitted. This allows a substantial amount of cache maintenance to be elided, wich is significant when fast boot times are critical (e.g., for booting micro-VMs) Once the initial ID map has been populated, the MMU is disabled as part of the logic sequence that puts all system registers into a known state. Any code that needs to execute within the window where the MMU is off is cleaned to the PoC explicitly, which includes all of HYP text when entering at EL2. However, the current sequence of initializing the EL2 system registers is not safe: HCR_EL2 is set to its nVHE initial state before SCTLR_EL2 is reprogrammed, and this means that a VHE-to-nVHE switch may occur while the MMU is enabled. This switch causes some system registers as well as page table descriptors to be interpreted in a different way, potentially resulting in spurious exceptions relating to MMU translation. So disable the MMU explicitly first when entering in EL2 with the MMU and caches enabled. Fixes: 617861703830 ("efi: arm64: enter with MMU and caches enabled") Signed-off-by: Ard Biesheuvel Cc: # 6.3.x Acked-by: Mark Rutland Acked-by: Marc Zyngier Link: https://lore.kernel.org/r/20240415075412.2347624-6-ardb+git@google.com Signed-off-by: Catalin Marinas --- arch/arm64/kernel/head.S | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/arch/arm64/kernel/head.S b/arch/arm64/kernel/head.S index b8bbd72cb194..cb68adcabe07 100644 --- a/arch/arm64/kernel/head.S +++ b/arch/arm64/kernel/head.S @@ -289,6 +289,11 @@ SYM_INNER_LABEL(init_el2, SYM_L_LOCAL) adr_l x1, __hyp_text_end adr_l x2, dcache_clean_poc blr x2 + + mov_q x0, INIT_SCTLR_EL2_MMU_OFF + pre_disable_mmu_workaround + msr sctlr_el2, x0 + isb 0: mov_q x0, HCR_HOST_NVHE_FLAGS -- cgit v1.2.3 From ed37d240d03e84d09d4d2a771fda419da4308d17 Mon Sep 17 00:00:00 2001 From: Mohammad Shehar Yaar Tausif Date: Thu, 18 Apr 2024 22:03:24 +0530 Subject: ASoC: dt-bindings: tegra20-das: Convert to schema Convert NVIDIA Tegra20 DAS (Digital Audio Switch) binding to schema. Signed-off-by: Mohammad Shehar Yaar Tausif Reviewed-by: Krzysztof Kozlowski Link: https://lore.kernel.org/r/20240418163326.58365-1-sheharyaar48@gmail.com Signed-off-by: Mark Brown --- .../bindings/sound/nvidia,tegra20-das.txt | 12 -------- .../bindings/sound/nvidia,tegra20-das.yaml | 36 ++++++++++++++++++++++ 2 files changed, 36 insertions(+), 12 deletions(-) delete mode 100644 Documentation/devicetree/bindings/sound/nvidia,tegra20-das.txt create mode 100644 Documentation/devicetree/bindings/sound/nvidia,tegra20-das.yaml diff --git a/Documentation/devicetree/bindings/sound/nvidia,tegra20-das.txt b/Documentation/devicetree/bindings/sound/nvidia,tegra20-das.txt deleted file mode 100644 index 6de3a7ee4efb..000000000000 --- a/Documentation/devicetree/bindings/sound/nvidia,tegra20-das.txt +++ /dev/null @@ -1,12 +0,0 @@ -NVIDIA Tegra 20 DAS (Digital Audio Switch) controller - -Required properties: -- compatible : "nvidia,tegra20-das" -- reg : Should contain DAS registers location and length - -Example: - -das@70000c00 { - compatible = "nvidia,tegra20-das"; - reg = <0x70000c00 0x80>; -}; diff --git a/Documentation/devicetree/bindings/sound/nvidia,tegra20-das.yaml b/Documentation/devicetree/bindings/sound/nvidia,tegra20-das.yaml new file mode 100644 index 000000000000..44c5ce8ee6be --- /dev/null +++ b/Documentation/devicetree/bindings/sound/nvidia,tegra20-das.yaml @@ -0,0 +1,36 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/sound/nvidia,tegra20-das.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: NVIDIA Tegra 20 DAS (Digital Audio Switch) controller + +maintainers: + - Thierry Reding + - Jon Hunter + +properties: + compatible: + const: nvidia,tegra20-das + + reg: + maxItems: 1 + +required: + - compatible + - reg + +additionalProperties: false + +examples: + - | + bus { + #address-cells = <1>; + #size-cells = <1>; + das@70000c00 { + compatible = "nvidia,tegra20-das"; + reg = <0x70000c00 0x80>; + }; + }; +... -- cgit v1.2.3 From 6a94cf996f104633bfb8d260eedf96a0dbebb384 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Fri, 19 Apr 2024 08:51:47 +0200 Subject: Revert "wifi: iwlwifi: bump FW API to 90 for BZ/SC devices" Revert the API version bump, the kernel doesn't actually have all the code to deal with that version yet. Fixes: 653a90f6b226 ("wifi: iwlwifi: bump FW API to 90 for BZ/SC devices") Link: https://msgid.link/20240419085147.cd756fadab03.Ibccbb65be8e05b516cae1b9fb27a959662f9f51a@changeid Signed-off-by: Johannes Berg --- drivers/net/wireless/intel/iwlwifi/cfg/bz.c | 2 +- drivers/net/wireless/intel/iwlwifi/cfg/sc.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/intel/iwlwifi/cfg/bz.c b/drivers/net/wireless/intel/iwlwifi/cfg/bz.c index 072b0a5827d1..eca1457caa0c 100644 --- a/drivers/net/wireless/intel/iwlwifi/cfg/bz.c +++ b/drivers/net/wireless/intel/iwlwifi/cfg/bz.c @@ -10,7 +10,7 @@ #include "fw/api/txq.h" /* Highest firmware API version supported */ -#define IWL_BZ_UCODE_API_MAX 90 +#define IWL_BZ_UCODE_API_MAX 89 /* Lowest firmware API version supported */ #define IWL_BZ_UCODE_API_MIN 80 diff --git a/drivers/net/wireless/intel/iwlwifi/cfg/sc.c b/drivers/net/wireless/intel/iwlwifi/cfg/sc.c index 9b79279fd76c..dbbcb2d0968c 100644 --- a/drivers/net/wireless/intel/iwlwifi/cfg/sc.c +++ b/drivers/net/wireless/intel/iwlwifi/cfg/sc.c @@ -10,7 +10,7 @@ #include "fw/api/txq.h" /* Highest firmware API version supported */ -#define IWL_SC_UCODE_API_MAX 90 +#define IWL_SC_UCODE_API_MAX 89 /* Lowest firmware API version supported */ #define IWL_SC_UCODE_API_MIN 82 -- cgit v1.2.3 From 89884459a0b9e6ecd62a1ddfdb7708b34ee33649 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Thu, 18 Apr 2024 10:52:19 +0200 Subject: wifi: mac80211: fix idle calculation with multi-link The vif's idle state doesn't automatically go to true when any link removes the channel context, it's only idle when _all_ links no longer have a channel context. Fix that. Reviewed-by: Miriam Rachel Korenblit Link: https://msgid.link/20240418105220.90df97557702.I05d2228ce85c203b9f2d6da8538cc16dce46752a@changeid Signed-off-by: Johannes Berg --- net/mac80211/chan.c | 27 ++++++++++++++++++++++----- 1 file changed, 22 insertions(+), 5 deletions(-) diff --git a/net/mac80211/chan.c b/net/mac80211/chan.c index 80e4b9784131..ccacaed32817 100644 --- a/net/mac80211/chan.c +++ b/net/mac80211/chan.c @@ -797,6 +797,7 @@ static int ieee80211_assign_link_chanctx(struct ieee80211_link_data *link, struct ieee80211_local *local = sdata->local; struct ieee80211_chanctx_conf *conf; struct ieee80211_chanctx *curr_ctx = NULL; + bool new_idle; int ret = 0; if (WARN_ON(sdata->vif.type == NL80211_IFTYPE_NAN)) @@ -829,8 +830,6 @@ static int ieee80211_assign_link_chanctx(struct ieee80211_link_data *link, out: rcu_assign_pointer(link->conf->chanctx_conf, conf); - sdata->vif.cfg.idle = !conf; - if (curr_ctx && ieee80211_chanctx_num_assigned(local, curr_ctx) > 0) { ieee80211_recalc_chanctx_chantype(local, curr_ctx); ieee80211_recalc_smps_chanctx(local, curr_ctx); @@ -843,9 +842,27 @@ out: ieee80211_recalc_chanctx_min_def(local, new_ctx, NULL); } - if (sdata->vif.type != NL80211_IFTYPE_P2P_DEVICE && - sdata->vif.type != NL80211_IFTYPE_MONITOR) - ieee80211_vif_cfg_change_notify(sdata, BSS_CHANGED_IDLE); + if (conf) { + new_idle = false; + } else { + struct ieee80211_link_data *tmp; + + new_idle = true; + for_each_sdata_link(local, tmp) { + if (rcu_access_pointer(tmp->conf->chanctx_conf)) { + new_idle = false; + break; + } + } + } + + if (new_idle != sdata->vif.cfg.idle) { + sdata->vif.cfg.idle = new_idle; + + if (sdata->vif.type != NL80211_IFTYPE_P2P_DEVICE && + sdata->vif.type != NL80211_IFTYPE_MONITOR) + ieee80211_vif_cfg_change_notify(sdata, BSS_CHANGED_IDLE); + } ieee80211_check_fast_xmit_iface(sdata); -- cgit v1.2.3 From 645acc6f55918feacc4572dd80acbb152b2208d9 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Thu, 18 Apr 2024 10:52:20 +0200 Subject: wifi: mac80211: mlme: re-parse with correct mode When doing re-parsing in ieee80211_determine_chan_mode(), the conn->mode is changed, and the whole point of doing the parsing again was to parse as the downgraded mode. However, that didn't actually work, because the setting was copied before and never changed again. Fix that. Fixes: 310c8387c638 ("wifi: mac80211: clean up connection process") Reviewed-by: Miriam Rachel Korenblit Link: https://msgid.link/20240418105220.5e0d1fcb5622.Ib0673e0bc90033fd6d387b6a5f107c040eb907cf@changeid Signed-off-by: Johannes Berg --- net/mac80211/mlme.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index db7128f6c901..98cb475a14c8 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c @@ -616,7 +616,6 @@ ieee80211_determine_chan_mode(struct ieee80211_sub_if_data *sdata, .from_ap = true, .start = ies->data, .len = ies->len, - .mode = conn->mode, }; struct ieee802_11_elems *elems; struct ieee80211_supported_band *sband; @@ -625,6 +624,7 @@ ieee80211_determine_chan_mode(struct ieee80211_sub_if_data *sdata, int ret; again: + parse_params.mode = conn->mode; elems = ieee802_11_parse_elems_full(&parse_params); if (!elems) return ERR_PTR(-ENOMEM); -- cgit v1.2.3 From 1ac6f60aab36ae3f0520cc7ace02ad32240b8a1f Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Thu, 18 Apr 2024 10:52:21 +0200 Subject: wifi: mac80211: mlme: fix memory leak When re-parsing the elements here (with changed mode), free the original ones first to avoid leaking memory. Fixes: 310c8387c638 ("wifi: mac80211: clean up connection process") Reviewed-by: Miriam Rachel Korenblit Link: https://msgid.link/20240418105220.458421e3bbff.Icb5b84cba3ea420794cf009cf18ec3d76e434736@changeid Signed-off-by: Johannes Berg --- net/mac80211/mlme.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index 98cb475a14c8..6fa3752b740e 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c @@ -753,8 +753,10 @@ again: } /* the mode can only decrease, so this must terminate */ - if (ap_mode != conn->mode) + if (ap_mode != conn->mode) { + kfree(elems); goto again; + } mlme_link_id_dbg(sdata, link_id, "connecting with %s mode, max bandwidth %d MHz\n", -- cgit v1.2.3 From 2fb5dfe18e8255dbec4d0f8e81297de8e3490285 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Thu, 18 Apr 2024 10:52:22 +0200 Subject: wifi: mac80211: mlme: re-parse if AP mode is less than client If the AP mode ends up being determined less than the client mode, there may be different reasons for this, e.g. AP misconfiguration. If this happens in a way that causes e.g. EHT to be rejected, the elements need to be re-parsed since we'll connect as HE, but not reparsing means that we'll still think it's OK to use multi-link, so we can connect in a non-sensical configuration of advertising only HE on a secondary link. This normally won't happen for the assoc link because that reuses the mode from authentication, and if that's not EHT, multi-link association is rejected. Fix this inconsistency by parsing the elements again if the mode was different from the first parsing attempt. Print the message a bit later to avoid printing "determined AP ... to be HE" twice in cases where ieee80211_determine_ap_chan() returned a lesser mode, rather than the regulatory downgrades below changing it. Fixes: 310c8387c638 ("wifi: mac80211: clean up connection process") Reviewed-by: Miriam Rachel Korenblit Link: https://msgid.link/20240418105220.d1f25d92cfe7.Ia21eff6cdcae2f5aca13cf8e742a986af5e70f89@changeid Signed-off-by: Johannes Berg --- net/mac80211/mlme.c | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index 6fa3752b740e..502c34d52fbe 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c @@ -632,15 +632,21 @@ again: ap_mode = ieee80211_determine_ap_chan(sdata, channel, bss->vht_cap_info, elems, false, conn, &ap_chandef); - mlme_link_id_dbg(sdata, link_id, "determined AP %pM to be %s\n", - cbss->bssid, ieee80211_conn_mode_str(ap_mode)); - /* this should be impossible since parsing depends on our mode */ if (WARN_ON(ap_mode > conn->mode)) { ret = -EINVAL; goto free; } + if (conn->mode != ap_mode) { + conn->mode = ap_mode; + kfree(elems); + goto again; + } + + mlme_link_id_dbg(sdata, link_id, "determined AP %pM to be %s\n", + cbss->bssid, ieee80211_conn_mode_str(ap_mode)); + sband = sdata->local->hw.wiphy->bands[channel->band]; switch (channel->band) { @@ -691,7 +697,6 @@ again: break; } - conn->mode = ap_mode; chanreq->oper = ap_chandef; /* wider-bandwidth OFDMA is only done in EHT */ -- cgit v1.2.3 From 801ea33ae82d6a9d954074fbcf8ea9d18f1543a7 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Thu, 18 Apr 2024 10:52:23 +0200 Subject: wifi: nl80211: don't free NULL coalescing rule If the parsing fails, we can dereference a NULL pointer here. Cc: stable@vger.kernel.org Fixes: be29b99a9b51 ("cfg80211/nl80211: Add packet coalesce support") Reviewed-by: Miriam Rachel Korenblit Link: https://msgid.link/20240418105220.b328f80406e7.Id75d961050deb05b3e4e354e024866f350c68103@changeid Signed-off-by: Johannes Berg --- net/wireless/nl80211.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index b4edba6b0b7b..30ff9a470813 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c @@ -14030,6 +14030,8 @@ static int nl80211_set_coalesce(struct sk_buff *skb, struct genl_info *info) error: for (i = 0; i < new_coalesce.n_rules; i++) { tmp_rule = &new_coalesce.rules[i]; + if (!tmp_rule) + continue; for (j = 0; j < tmp_rule->n_patterns; j++) kfree(tmp_rule->patterns[j].mask); kfree(tmp_rule->patterns); -- cgit v1.2.3 From 2a4e01e5270b9fa9f6e6e0a4c24ac51a758636f9 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Thu, 18 Apr 2024 10:52:24 +0200 Subject: wifi: mac80211_hwsim: init peer measurement result If we don't get all the values here, we might pass them to cfg80211 uninitialized. Fix that, even if the input might then not make much sense. Fixes: 2af3b2a631b1 ("mac80211_hwsim: add PMSR report support via virtio") Reviewed-by: Miriam Rachel Korenblit Link: https://msgid.link/20240418105220.e1317621c1f9.If7dd447de24d7493d133284db5e9e482e4e299f8@changeid Signed-off-by: Johannes Berg --- drivers/net/wireless/virtual/mac80211_hwsim.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/virtual/mac80211_hwsim.c b/drivers/net/wireless/virtual/mac80211_hwsim.c index b55fe320633c..59e1fc0018df 100644 --- a/drivers/net/wireless/virtual/mac80211_hwsim.c +++ b/drivers/net/wireless/virtual/mac80211_hwsim.c @@ -3899,7 +3899,7 @@ static int hwsim_pmsr_report_nl(struct sk_buff *msg, struct genl_info *info) } nla_for_each_nested(peer, peers, rem) { - struct cfg80211_pmsr_result result; + struct cfg80211_pmsr_result result = {}; err = mac80211_hwsim_parse_pmsr_result(peer, &result, info); if (err) -- cgit v1.2.3 From cb55e08dba3526796e35d24a6d5db4ed6dcb8a4b Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Thu, 18 Apr 2024 10:52:25 +0200 Subject: wifi: mac80211: remove link before AP If the AP removal timer is long, we don't really want to remove the link immediately. However, we really should do it _before_ the AP removes it (which happens at or after count reaches 0), so subtract 1 from the countdown when scheduling the timer. This causes the link removal work to run just after the beacon with value 1 is received. If the counter is already zero, do it immediately. This fixes an issue where we do the removal too late and receive a beacon from the AP that's no longer associated with the MLD, but thus removed EHT and ML elements, and then we disconnect instead from the whole MLD, since one of the associated APs changed mode from EHT to HE. Fixes: 8eb8dd2ffbbb ("wifi: mac80211: Support link removal using Reconfiguration ML element") Reviewed-by: Ilan Peer Reviewed-by: Miriam Rachel Korenblit Link: https://msgid.link/20240418105220.03ac4a09fa74.Ifb8c8d38e3402721a81ce5981568f47b5c5889cb@changeid Signed-off-by: Johannes Berg --- net/mac80211/mlme.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index 502c34d52fbe..6f0880ec89da 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c @@ -5844,8 +5844,11 @@ static void ieee80211_ml_reconfiguration(struct ieee80211_sub_if_data *sdata, continue; } - link_delay = link_conf->beacon_int * - link_removal_timeout[link_id]; + if (link_removal_timeout[link_id] < 1) + link_delay = 0; + else + link_delay = link_conf->beacon_int * + (link_removal_timeout[link_id] - 1); if (!delay) delay = link_delay; -- cgit v1.2.3 From c53d8a59351e4347452e263e2e5d7446ec93da83 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Thu, 18 Apr 2024 10:52:26 +0200 Subject: wifi: mac80211: fix unaligned le16 access The AP removal timer field need not be aligned, so the code shouldn't access it directly, but use unaligned loads. Use get_unaligned_le16(), which even is shorter than the current code since it doesn't need a cast. Fixes: 8eb8dd2ffbbb ("wifi: mac80211: Support link removal using Reconfiguration ML element") Reviewed-by: Ilan Peer Reviewed-by: Miriam Rachel Korenblit Link: https://msgid.link/20240418105220.356788ba0045.I2b3cdb3644e205d5bb10322c345c0499171cf5d2@changeid Signed-off-by: Johannes Berg --- net/mac80211/mlme.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index 6f0880ec89da..3bbb216a0fc8 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c @@ -5819,7 +5819,7 @@ static void ieee80211_ml_reconfiguration(struct ieee80211_sub_if_data *sdata, */ if (control & IEEE80211_MLE_STA_RECONF_CONTROL_AP_REM_TIMER_PRESENT) - link_removal_timeout[link_id] = le16_to_cpu(*(__le16 *)pos); + link_removal_timeout[link_id] = get_unaligned_le16(pos); } removed_links &= sdata->vif.valid_links; -- cgit v1.2.3 From 7ce6ceeb77bfd9fb0b22203190bd6f57fe917b51 Mon Sep 17 00:00:00 2001 From: Cezary Rojewski Date: Fri, 19 Apr 2024 10:48:56 +0200 Subject: ASoC: Intel: avs: New IRQ handling implementation The existing code can be both improved and simplified. To make this change easier to manage, first add new implementation and then remove deadcode in a separate patch. Simplification achieved with: - reduce the amount of resources requested by the driver i.e.: IPC and CLDMA request_irq() merged into one - reduce the number of DSP ops from 2 to 1: irq_handler/thread() vs dsp_interrupt() - drop ambiguity around CLDMA interrupt, let skl.c handle that explicitly as it is the only user Signed-off-by: Cezary Rojewski Link: https://lore.kernel.org/r/20240419084857.2719593-2-cezary.rojewski@intel.com Signed-off-by: Mark Brown --- sound/soc/intel/avs/apl.c | 18 ++++++++++ sound/soc/intel/avs/avs.h | 3 ++ sound/soc/intel/avs/cldma.c | 11 +++++++ sound/soc/intel/avs/cldma.h | 1 + sound/soc/intel/avs/cnl.c | 63 +++++++++++++++++++++++++++++++++++ sound/soc/intel/avs/core.c | 80 +++++++++++++++++++++++++++++++++++++++++++++ sound/soc/intel/avs/icl.c | 1 + sound/soc/intel/avs/skl.c | 62 +++++++++++++++++++++++++++++++++++ sound/soc/intel/avs/tgl.c | 1 + 9 files changed, 240 insertions(+) diff --git a/sound/soc/intel/avs/apl.c b/sound/soc/intel/avs/apl.c index c21ecaef9eba..a186d88430b9 100644 --- a/sound/soc/intel/avs/apl.c +++ b/sound/soc/intel/avs/apl.c @@ -8,11 +8,28 @@ #include #include +#include #include "avs.h" #include "messages.h" #include "path.h" #include "topology.h" +static irqreturn_t avs_apl_dsp_interrupt(struct avs_dev *adev) +{ + u32 adspis = snd_hdac_adsp_readl(adev, AVS_ADSP_REG_ADSPIS); + irqreturn_t ret = IRQ_NONE; + + if (adspis == UINT_MAX) + return ret; + + if (adspis & AVS_ADSP_ADSPIS_IPC) { + avs_skl_ipc_interrupt(adev); + ret = IRQ_HANDLED; + } + + return ret; +} + #ifdef CONFIG_DEBUG_FS int avs_apl_enable_logs(struct avs_dev *adev, enum avs_log_enable enable, u32 aging_period, u32 fifo_full_period, unsigned long resource_mask, u32 *priorities) @@ -237,6 +254,7 @@ const struct avs_dsp_ops avs_apl_dsp_ops = { .power = avs_dsp_core_power, .reset = avs_dsp_core_reset, .stall = avs_dsp_core_stall, + .dsp_interrupt = avs_apl_dsp_interrupt, .irq_handler = avs_irq_handler, .irq_thread = avs_skl_irq_thread, .int_control = avs_dsp_interrupt_control, diff --git a/sound/soc/intel/avs/avs.h b/sound/soc/intel/avs/avs.h index eb8c03afdd23..75ae8f3addb8 100644 --- a/sound/soc/intel/avs/avs.h +++ b/sound/soc/intel/avs/avs.h @@ -46,6 +46,7 @@ struct avs_dsp_ops { int (* const power)(struct avs_dev *, u32, bool); int (* const reset)(struct avs_dev *, u32, bool); int (* const stall)(struct avs_dev *, u32, bool); + irqreturn_t (* const dsp_interrupt)(struct avs_dev *); irqreturn_t (* const irq_handler)(struct avs_dev *); irqreturn_t (* const irq_thread)(struct avs_dev *); void (* const int_control)(struct avs_dev *, bool); @@ -269,6 +270,8 @@ int avs_dsp_enable_d0ix(struct avs_dev *adev); irqreturn_t avs_skl_irq_thread(struct avs_dev *adev); irqreturn_t avs_cnl_irq_thread(struct avs_dev *adev); +void avs_skl_ipc_interrupt(struct avs_dev *adev); +irqreturn_t avs_cnl_dsp_interrupt(struct avs_dev *adev); int avs_apl_enable_logs(struct avs_dev *adev, enum avs_log_enable enable, u32 aging_period, u32 fifo_full_period, unsigned long resource_mask, u32 *priorities); int avs_icl_enable_logs(struct avs_dev *adev, enum avs_log_enable enable, u32 aging_period, diff --git a/sound/soc/intel/avs/cldma.c b/sound/soc/intel/avs/cldma.c index 585579840b64..c79b126f376d 100644 --- a/sound/soc/intel/avs/cldma.c +++ b/sound/soc/intel/avs/cldma.c @@ -270,6 +270,17 @@ static irqreturn_t cldma_irq_handler(int irq, void *dev_id) return IRQ_HANDLED; } +void hda_cldma_interrupt(struct hda_cldma *cl) +{ + /* disable CLDMA interrupt */ + snd_hdac_adsp_updatel(cl, AVS_ADSP_REG_ADSPIC, AVS_ADSP_ADSPIC_CLDMA, 0); + + cl->sd_status = snd_hdac_stream_readb(cl, SD_STS); + dev_dbg(cl->dev, "%s sd_status: 0x%08x\n", __func__, cl->sd_status); + + complete(&cl->completion); +} + int hda_cldma_init(struct hda_cldma *cl, struct hdac_bus *bus, void __iomem *dsp_ba, unsigned int buffer_size) { diff --git a/sound/soc/intel/avs/cldma.h b/sound/soc/intel/avs/cldma.h index 223d3431ab81..7d95e2747f52 100644 --- a/sound/soc/intel/avs/cldma.h +++ b/sound/soc/intel/avs/cldma.h @@ -24,6 +24,7 @@ int hda_cldma_reset(struct hda_cldma *cl); void hda_cldma_set_data(struct hda_cldma *cl, void *data, unsigned int size); void hda_cldma_setup(struct hda_cldma *cl); +void hda_cldma_interrupt(struct hda_cldma *cl); int hda_cldma_init(struct hda_cldma *cl, struct hdac_bus *bus, void __iomem *dsp_ba, unsigned int buffer_size); void hda_cldma_free(struct hda_cldma *cl); diff --git a/sound/soc/intel/avs/cnl.c b/sound/soc/intel/avs/cnl.c index 5423c29ecc4e..c021c0f51a53 100644 --- a/sound/soc/intel/avs/cnl.c +++ b/sound/soc/intel/avs/cnl.c @@ -42,10 +42,73 @@ irqreturn_t avs_cnl_irq_thread(struct avs_dev *adev) return IRQ_HANDLED; } +static void avs_cnl_ipc_interrupt(struct avs_dev *adev) +{ + const struct avs_spec *spec = adev->spec; + u32 hipc_ack, hipc_rsp; + + snd_hdac_adsp_updatel(adev, spec->hipc->ctl_offset, + AVS_ADSP_HIPCCTL_DONE | AVS_ADSP_HIPCCTL_BUSY, 0); + + hipc_ack = snd_hdac_adsp_readl(adev, spec->hipc->ack_offset); + hipc_rsp = snd_hdac_adsp_readl(adev, spec->hipc->rsp_offset); + + /* DSP acked host's request. */ + if (hipc_ack & spec->hipc->ack_done_mask) { + complete(&adev->ipc->done_completion); + + /* Tell DSP it has our attention. */ + snd_hdac_adsp_updatel(adev, spec->hipc->ack_offset, spec->hipc->ack_done_mask, + spec->hipc->ack_done_mask); + } + + /* DSP sent new response to process. */ + if (hipc_rsp & spec->hipc->rsp_busy_mask) { + union avs_reply_msg msg; + u32 hipctda; + + msg.primary = snd_hdac_adsp_readl(adev, CNL_ADSP_REG_HIPCTDR); + msg.ext.val = snd_hdac_adsp_readl(adev, CNL_ADSP_REG_HIPCTDD); + + avs_dsp_process_response(adev, msg.val); + + /* Tell DSP we accepted its message. */ + snd_hdac_adsp_updatel(adev, CNL_ADSP_REG_HIPCTDR, + CNL_ADSP_HIPCTDR_BUSY, CNL_ADSP_HIPCTDR_BUSY); + /* Ack this response. */ + snd_hdac_adsp_updatel(adev, CNL_ADSP_REG_HIPCTDA, + CNL_ADSP_HIPCTDA_DONE, CNL_ADSP_HIPCTDA_DONE); + /* HW might have been clock gated, give some time for change to propagate. */ + snd_hdac_adsp_readl_poll(adev, CNL_ADSP_REG_HIPCTDA, hipctda, + !(hipctda & CNL_ADSP_HIPCTDA_DONE), 10, 1000); + } + + snd_hdac_adsp_updatel(adev, spec->hipc->ctl_offset, + AVS_ADSP_HIPCCTL_DONE | AVS_ADSP_HIPCCTL_BUSY, + AVS_ADSP_HIPCCTL_DONE | AVS_ADSP_HIPCCTL_BUSY); +} + +irqreturn_t avs_cnl_dsp_interrupt(struct avs_dev *adev) +{ + u32 adspis = snd_hdac_adsp_readl(adev, AVS_ADSP_REG_ADSPIS); + irqreturn_t ret = IRQ_NONE; + + if (adspis == UINT_MAX) + return ret; + + if (adspis & AVS_ADSP_ADSPIS_IPC) { + avs_cnl_ipc_interrupt(adev); + ret = IRQ_HANDLED; + } + + return ret; +} + const struct avs_dsp_ops avs_cnl_dsp_ops = { .power = avs_dsp_core_power, .reset = avs_dsp_core_reset, .stall = avs_dsp_core_stall, + .dsp_interrupt = avs_cnl_dsp_interrupt, .irq_handler = avs_irq_handler, .irq_thread = avs_cnl_irq_thread, .int_control = avs_dsp_interrupt_control, diff --git a/sound/soc/intel/avs/core.c b/sound/soc/intel/avs/core.c index 76782a0f32bc..25759f4f0213 100644 --- a/sound/soc/intel/avs/core.c +++ b/sound/soc/intel/avs/core.c @@ -336,6 +336,86 @@ static irqreturn_t avs_dsp_irq_thread(int irq, void *dev_id) return avs_dsp_op(adev, irq_thread); } +static irqreturn_t avs_hda_interrupt(struct hdac_bus *bus) +{ + irqreturn_t ret = IRQ_NONE; + u32 status; + + status = snd_hdac_chip_readl(bus, INTSTS); + if (snd_hdac_bus_handle_stream_irq(bus, status, hdac_update_stream)) + ret = IRQ_HANDLED; + + spin_lock_irq(&bus->reg_lock); + /* Clear RIRB interrupt. */ + status = snd_hdac_chip_readb(bus, RIRBSTS); + if (status & RIRB_INT_MASK) { + if (status & RIRB_INT_RESPONSE) + snd_hdac_bus_update_rirb(bus); + snd_hdac_chip_writeb(bus, RIRBSTS, RIRB_INT_MASK); + ret = IRQ_HANDLED; + } + + spin_unlock_irq(&bus->reg_lock); + return ret; +} + +__maybe_unused +static irqreturn_t avs_hda_irq_handler(int irq, void *dev_id) +{ + struct hdac_bus *bus = dev_id; + u32 intsts; + + intsts = snd_hdac_chip_readl(bus, INTSTS); + if (intsts == UINT_MAX || !(intsts & AZX_INT_GLOBAL_EN)) + return IRQ_NONE; + + /* Mask GIE, unmasked in irq_thread(). */ + snd_hdac_chip_updatel(bus, INTCTL, AZX_INT_GLOBAL_EN, 0); + + return IRQ_WAKE_THREAD; +} + +__maybe_unused +static irqreturn_t avs_hda_irq_thread(int irq, void *dev_id) +{ + struct hdac_bus *bus = dev_id; + u32 status; + + status = snd_hdac_chip_readl(bus, INTSTS); + if (status & ~AZX_INT_GLOBAL_EN) + avs_hda_interrupt(bus); + + /* Unmask GIE, masked in irq_handler(). */ + snd_hdac_chip_updatel(bus, INTCTL, AZX_INT_GLOBAL_EN, AZX_INT_GLOBAL_EN); + + return IRQ_HANDLED; +} + +__maybe_unused +static irqreturn_t avs_dsp_irq_handler2(int irq, void *dev_id) +{ + struct avs_dev *adev = dev_id; + + return avs_hda_irq_handler(irq, &adev->base.core); +} + +__maybe_unused +static irqreturn_t avs_dsp_irq_thread2(int irq, void *dev_id) +{ + struct avs_dev *adev = dev_id; + struct hdac_bus *bus = &adev->base.core; + u32 status; + + status = readl(bus->ppcap + AZX_REG_PP_PPSTS); + if (status & AZX_PPCTL_PIE) + avs_dsp_op(adev, dsp_interrupt); + + /* Unmask GIE, masked in irq_handler(). */ + snd_hdac_chip_updatel(bus, INTCTL, AZX_INT_GLOBAL_EN, AZX_INT_GLOBAL_EN); + + return IRQ_HANDLED; +} + static int avs_hdac_acquire_irq(struct avs_dev *adev) { struct hdac_bus *bus = &adev->base.core; diff --git a/sound/soc/intel/avs/icl.c b/sound/soc/intel/avs/icl.c index e8b4983e03e9..c18ea41d094b 100644 --- a/sound/soc/intel/avs/icl.c +++ b/sound/soc/intel/avs/icl.c @@ -188,6 +188,7 @@ const struct avs_dsp_ops avs_icl_dsp_ops = { .power = avs_dsp_core_power, .reset = avs_dsp_core_reset, .stall = avs_dsp_core_stall, + .dsp_interrupt = avs_cnl_dsp_interrupt, .irq_handler = avs_irq_handler, .irq_thread = avs_cnl_irq_thread, .int_control = avs_dsp_interrupt_control, diff --git a/sound/soc/intel/avs/skl.c b/sound/soc/intel/avs/skl.c index d19f8953993f..25abfead9f63 100644 --- a/sound/soc/intel/avs/skl.c +++ b/sound/soc/intel/avs/skl.c @@ -10,6 +10,7 @@ #include #include #include "avs.h" +#include "cldma.h" #include "messages.h" irqreturn_t avs_skl_irq_thread(struct avs_dev *adev) @@ -37,6 +38,66 @@ irqreturn_t avs_skl_irq_thread(struct avs_dev *adev) return IRQ_HANDLED; } +void avs_skl_ipc_interrupt(struct avs_dev *adev) +{ + const struct avs_spec *spec = adev->spec; + u32 hipc_ack, hipc_rsp; + + snd_hdac_adsp_updatel(adev, spec->hipc->ctl_offset, + AVS_ADSP_HIPCCTL_DONE | AVS_ADSP_HIPCCTL_BUSY, 0); + + hipc_ack = snd_hdac_adsp_readl(adev, spec->hipc->ack_offset); + hipc_rsp = snd_hdac_adsp_readl(adev, spec->hipc->rsp_offset); + + /* DSP acked host's request. */ + if (hipc_ack & spec->hipc->ack_done_mask) { + complete(&adev->ipc->done_completion); + + /* Tell DSP it has our attention. */ + snd_hdac_adsp_updatel(adev, spec->hipc->ack_offset, spec->hipc->ack_done_mask, + spec->hipc->ack_done_mask); + } + + /* DSP sent new response to process */ + if (hipc_rsp & spec->hipc->rsp_busy_mask) { + union avs_reply_msg msg; + + msg.primary = snd_hdac_adsp_readl(adev, SKL_ADSP_REG_HIPCT); + msg.ext.val = snd_hdac_adsp_readl(adev, SKL_ADSP_REG_HIPCTE); + + avs_dsp_process_response(adev, msg.val); + + /* Tell DSP we accepted its message. */ + snd_hdac_adsp_updatel(adev, SKL_ADSP_REG_HIPCT, SKL_ADSP_HIPCT_BUSY, + SKL_ADSP_HIPCT_BUSY); + } + + snd_hdac_adsp_updatel(adev, spec->hipc->ctl_offset, + AVS_ADSP_HIPCCTL_DONE | AVS_ADSP_HIPCCTL_BUSY, + AVS_ADSP_HIPCCTL_DONE | AVS_ADSP_HIPCCTL_BUSY); +} + +static irqreturn_t avs_skl_dsp_interrupt(struct avs_dev *adev) +{ + u32 adspis = snd_hdac_adsp_readl(adev, AVS_ADSP_REG_ADSPIS); + irqreturn_t ret = IRQ_NONE; + + if (adspis == UINT_MAX) + return ret; + + if (adspis & AVS_ADSP_ADSPIS_CLDMA) { + hda_cldma_interrupt(&code_loader); + ret = IRQ_HANDLED; + } + + if (adspis & AVS_ADSP_ADSPIS_IPC) { + avs_skl_ipc_interrupt(adev); + ret = IRQ_HANDLED; + } + + return ret; +} + static int __maybe_unused avs_skl_enable_logs(struct avs_dev *adev, enum avs_log_enable enable, u32 aging_period, u32 fifo_full_period, unsigned long resource_mask, u32 *priorities) @@ -128,6 +189,7 @@ const struct avs_dsp_ops avs_skl_dsp_ops = { .power = avs_dsp_core_power, .reset = avs_dsp_core_reset, .stall = avs_dsp_core_stall, + .dsp_interrupt = avs_skl_dsp_interrupt, .irq_handler = avs_irq_handler, .irq_thread = avs_skl_irq_thread, .int_control = avs_dsp_interrupt_control, diff --git a/sound/soc/intel/avs/tgl.c b/sound/soc/intel/avs/tgl.c index 0e052e7f6bac..e3723ef38a33 100644 --- a/sound/soc/intel/avs/tgl.c +++ b/sound/soc/intel/avs/tgl.c @@ -39,6 +39,7 @@ const struct avs_dsp_ops avs_tgl_dsp_ops = { .power = avs_tgl_dsp_core_power, .reset = avs_tgl_dsp_core_reset, .stall = avs_tgl_dsp_core_stall, + .dsp_interrupt = avs_cnl_dsp_interrupt, .irq_handler = avs_irq_handler, .irq_thread = avs_cnl_irq_thread, .int_control = avs_dsp_interrupt_control, -- cgit v1.2.3 From 84049e2db59ad9b09461b6d7ec56bd3e8fe75eca Mon Sep 17 00:00:00 2001 From: Cezary Rojewski Date: Fri, 19 Apr 2024 10:48:57 +0200 Subject: ASoC: Intel: avs: Remove unused IRQ-related code Most IRQ-related code is duplicated in the driver. Switch to the new implementation and remove unused members. While the change is non-trivial, from functional perspective status quo is achieved. Signed-off-by: Cezary Rojewski Link: https://lore.kernel.org/r/20240419084857.2719593-3-cezary.rojewski@intel.com Signed-off-by: Mark Brown --- sound/soc/intel/avs/apl.c | 2 - sound/soc/intel/avs/avs.h | 5 --- sound/soc/intel/avs/cldma.c | 45 ++-------------------- sound/soc/intel/avs/cnl.c | 34 ----------------- sound/soc/intel/avs/core.c | 91 ++------------------------------------------- sound/soc/intel/avs/icl.c | 2 - sound/soc/intel/avs/ipc.c | 48 ------------------------ sound/soc/intel/avs/skl.c | 27 -------------- sound/soc/intel/avs/tgl.c | 2 - 9 files changed, 7 insertions(+), 249 deletions(-) diff --git a/sound/soc/intel/avs/apl.c b/sound/soc/intel/avs/apl.c index a186d88430b9..bf97e4e428a4 100644 --- a/sound/soc/intel/avs/apl.c +++ b/sound/soc/intel/avs/apl.c @@ -255,8 +255,6 @@ const struct avs_dsp_ops avs_apl_dsp_ops = { .reset = avs_dsp_core_reset, .stall = avs_dsp_core_stall, .dsp_interrupt = avs_apl_dsp_interrupt, - .irq_handler = avs_irq_handler, - .irq_thread = avs_skl_irq_thread, .int_control = avs_dsp_interrupt_control, .load_basefw = avs_hda_load_basefw, .load_lib = avs_hda_load_library, diff --git a/sound/soc/intel/avs/avs.h b/sound/soc/intel/avs/avs.h index 75ae8f3addb8..c905ecd0a108 100644 --- a/sound/soc/intel/avs/avs.h +++ b/sound/soc/intel/avs/avs.h @@ -47,8 +47,6 @@ struct avs_dsp_ops { int (* const reset)(struct avs_dev *, u32, bool); int (* const stall)(struct avs_dev *, u32, bool); irqreturn_t (* const dsp_interrupt)(struct avs_dev *); - irqreturn_t (* const irq_handler)(struct avs_dev *); - irqreturn_t (* const irq_thread)(struct avs_dev *); void (* const int_control)(struct avs_dev *, bool); int (* const load_basefw)(struct avs_dev *, struct firmware *); int (* const load_lib)(struct avs_dev *, struct firmware *, u32); @@ -246,7 +244,6 @@ struct avs_ipc { #define AVS_IPC_RET(ret) \ (((ret) <= 0) ? (ret) : -AVS_EIPC) -irqreturn_t avs_irq_handler(struct avs_dev *adev); void avs_dsp_process_response(struct avs_dev *adev, u64 header); int avs_dsp_send_msg_timeout(struct avs_dev *adev, struct avs_ipc_msg *request, struct avs_ipc_msg *reply, int timeout, const char *name); @@ -268,8 +265,6 @@ void avs_ipc_block(struct avs_ipc *ipc); int avs_dsp_disable_d0ix(struct avs_dev *adev); int avs_dsp_enable_d0ix(struct avs_dev *adev); -irqreturn_t avs_skl_irq_thread(struct avs_dev *adev); -irqreturn_t avs_cnl_irq_thread(struct avs_dev *adev); void avs_skl_ipc_interrupt(struct avs_dev *adev); irqreturn_t avs_cnl_dsp_interrupt(struct avs_dev *adev); int avs_apl_enable_logs(struct avs_dev *adev, enum avs_log_enable enable, u32 aging_period, diff --git a/sound/soc/intel/avs/cldma.c b/sound/soc/intel/avs/cldma.c index c79b126f376d..945ea376d031 100644 --- a/sound/soc/intel/avs/cldma.c +++ b/sound/soc/intel/avs/cldma.c @@ -248,28 +248,6 @@ void hda_cldma_setup(struct hda_cldma *cl) snd_hdac_stream_writel(cl, CL_SPBFCTL, 1); } -static irqreturn_t cldma_irq_handler(int irq, void *dev_id) -{ - struct hda_cldma *cl = dev_id; - u32 adspis; - - adspis = snd_hdac_adsp_readl(cl, AVS_ADSP_REG_ADSPIS); - if (adspis == UINT_MAX) - return IRQ_NONE; - if (!(adspis & AVS_ADSP_ADSPIS_CLDMA)) - return IRQ_NONE; - - cl->sd_status = snd_hdac_stream_readb(cl, SD_STS); - dev_warn(cl->dev, "%s sd_status: 0x%08x\n", __func__, cl->sd_status); - - /* disable CLDMA interrupt */ - snd_hdac_adsp_updatel(cl, AVS_ADSP_REG_ADSPIC, AVS_ADSP_ADSPIC_CLDMA, 0); - - complete(&cl->completion); - - return IRQ_HANDLED; -} - void hda_cldma_interrupt(struct hda_cldma *cl) { /* disable CLDMA interrupt */ @@ -284,7 +262,6 @@ void hda_cldma_interrupt(struct hda_cldma *cl) int hda_cldma_init(struct hda_cldma *cl, struct hdac_bus *bus, void __iomem *dsp_ba, unsigned int buffer_size) { - struct pci_dev *pci = to_pci_dev(bus->dev); int ret; ret = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV_SG, bus->dev, buffer_size, &cl->dmab_data); @@ -292,8 +269,10 @@ int hda_cldma_init(struct hda_cldma *cl, struct hdac_bus *bus, void __iomem *dsp return ret; ret = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, bus->dev, BDL_SIZE, &cl->dmab_bdl); - if (ret < 0) - goto alloc_err; + if (ret < 0) { + snd_dma_free_pages(&cl->dmab_data); + return ret; + } cl->dev = bus->dev; cl->bus = bus; @@ -301,27 +280,11 @@ int hda_cldma_init(struct hda_cldma *cl, struct hdac_bus *bus, void __iomem *dsp cl->buffer_size = buffer_size; cl->sd_addr = dsp_ba + AZX_CL_SD_BASE; - ret = pci_request_irq(pci, 0, cldma_irq_handler, NULL, cl, "CLDMA"); - if (ret < 0) { - dev_err(cl->dev, "Failed to request CLDMA IRQ handler: %d\n", ret); - goto req_err; - } - return 0; - -req_err: - snd_dma_free_pages(&cl->dmab_bdl); -alloc_err: - snd_dma_free_pages(&cl->dmab_data); - - return ret; } void hda_cldma_free(struct hda_cldma *cl) { - struct pci_dev *pci = to_pci_dev(cl->dev); - - pci_free_irq(pci, 0, cl); snd_dma_free_pages(&cl->dmab_data); snd_dma_free_pages(&cl->dmab_bdl); } diff --git a/sound/soc/intel/avs/cnl.c b/sound/soc/intel/avs/cnl.c index c021c0f51a53..0d03e1e03c11 100644 --- a/sound/soc/intel/avs/cnl.c +++ b/sound/soc/intel/avs/cnl.c @@ -10,38 +10,6 @@ #include "avs.h" #include "messages.h" -irqreturn_t avs_cnl_irq_thread(struct avs_dev *adev) -{ - union avs_reply_msg msg; - u32 hipctdr, hipctdd, hipctda; - - hipctdr = snd_hdac_adsp_readl(adev, CNL_ADSP_REG_HIPCTDR); - hipctdd = snd_hdac_adsp_readl(adev, CNL_ADSP_REG_HIPCTDD); - - /* Ensure DSP sent new response to process. */ - if (!(hipctdr & CNL_ADSP_HIPCTDR_BUSY)) - return IRQ_NONE; - - msg.primary = hipctdr; - msg.ext.val = hipctdd; - avs_dsp_process_response(adev, msg.val); - - /* Tell DSP we accepted its message. */ - snd_hdac_adsp_updatel(adev, CNL_ADSP_REG_HIPCTDR, - CNL_ADSP_HIPCTDR_BUSY, CNL_ADSP_HIPCTDR_BUSY); - /* Ack this response. */ - snd_hdac_adsp_updatel(adev, CNL_ADSP_REG_HIPCTDA, - CNL_ADSP_HIPCTDA_DONE, CNL_ADSP_HIPCTDA_DONE); - /* HW might have been clock gated, give some time for change to propagate. */ - snd_hdac_adsp_readl_poll(adev, CNL_ADSP_REG_HIPCTDA, hipctda, - !(hipctda & CNL_ADSP_HIPCTDA_DONE), 10, 1000); - /* Unmask busy interrupt. */ - snd_hdac_adsp_updatel(adev, CNL_ADSP_REG_HIPCCTL, - AVS_ADSP_HIPCCTL_BUSY, AVS_ADSP_HIPCCTL_BUSY); - - return IRQ_HANDLED; -} - static void avs_cnl_ipc_interrupt(struct avs_dev *adev) { const struct avs_spec *spec = adev->spec; @@ -109,8 +77,6 @@ const struct avs_dsp_ops avs_cnl_dsp_ops = { .reset = avs_dsp_core_reset, .stall = avs_dsp_core_stall, .dsp_interrupt = avs_cnl_dsp_interrupt, - .irq_handler = avs_irq_handler, - .irq_thread = avs_cnl_irq_thread, .int_control = avs_dsp_interrupt_control, .load_basefw = avs_hda_load_basefw, .load_lib = avs_hda_load_library, diff --git a/sound/soc/intel/avs/core.c b/sound/soc/intel/avs/core.c index 25759f4f0213..a059bb6888d8 100644 --- a/sound/soc/intel/avs/core.c +++ b/sound/soc/intel/avs/core.c @@ -257,85 +257,6 @@ static void hdac_update_stream(struct hdac_bus *bus, struct hdac_stream *stream) } } -static irqreturn_t hdac_bus_irq_handler(int irq, void *context) -{ - struct hdac_bus *bus = context; - u32 mask, int_enable; - u32 status; - int ret = IRQ_NONE; - - if (!pm_runtime_active(bus->dev)) - return ret; - - spin_lock(&bus->reg_lock); - - status = snd_hdac_chip_readl(bus, INTSTS); - if (status == 0 || status == UINT_MAX) { - spin_unlock(&bus->reg_lock); - return ret; - } - - /* clear rirb int */ - status = snd_hdac_chip_readb(bus, RIRBSTS); - if (status & RIRB_INT_MASK) { - if (status & RIRB_INT_RESPONSE) - snd_hdac_bus_update_rirb(bus); - snd_hdac_chip_writeb(bus, RIRBSTS, RIRB_INT_MASK); - } - - mask = (0x1 << bus->num_streams) - 1; - - status = snd_hdac_chip_readl(bus, INTSTS); - status &= mask; - if (status) { - /* Disable stream interrupts; Re-enable in bottom half */ - int_enable = snd_hdac_chip_readl(bus, INTCTL); - snd_hdac_chip_writel(bus, INTCTL, (int_enable & (~mask))); - ret = IRQ_WAKE_THREAD; - } else { - ret = IRQ_HANDLED; - } - - spin_unlock(&bus->reg_lock); - return ret; -} - -static irqreturn_t hdac_bus_irq_thread(int irq, void *context) -{ - struct hdac_bus *bus = context; - u32 status; - u32 int_enable; - u32 mask; - unsigned long flags; - - status = snd_hdac_chip_readl(bus, INTSTS); - - snd_hdac_bus_handle_stream_irq(bus, status, hdac_update_stream); - - /* Re-enable stream interrupts */ - mask = (0x1 << bus->num_streams) - 1; - spin_lock_irqsave(&bus->reg_lock, flags); - int_enable = snd_hdac_chip_readl(bus, INTCTL); - snd_hdac_chip_writel(bus, INTCTL, (int_enable | mask)); - spin_unlock_irqrestore(&bus->reg_lock, flags); - - return IRQ_HANDLED; -} - -static irqreturn_t avs_dsp_irq_handler(int irq, void *dev_id) -{ - struct avs_dev *adev = dev_id; - - return avs_dsp_op(adev, irq_handler); -} - -static irqreturn_t avs_dsp_irq_thread(int irq, void *dev_id) -{ - struct avs_dev *adev = dev_id; - - return avs_dsp_op(adev, irq_thread); -} - static irqreturn_t avs_hda_interrupt(struct hdac_bus *bus) { irqreturn_t ret = IRQ_NONE; @@ -359,7 +280,6 @@ static irqreturn_t avs_hda_interrupt(struct hdac_bus *bus) return ret; } -__maybe_unused static irqreturn_t avs_hda_irq_handler(int irq, void *dev_id) { struct hdac_bus *bus = dev_id; @@ -375,7 +295,6 @@ static irqreturn_t avs_hda_irq_handler(int irq, void *dev_id) return IRQ_WAKE_THREAD; } -__maybe_unused static irqreturn_t avs_hda_irq_thread(int irq, void *dev_id) { struct hdac_bus *bus = dev_id; @@ -391,16 +310,14 @@ static irqreturn_t avs_hda_irq_thread(int irq, void *dev_id) return IRQ_HANDLED; } -__maybe_unused -static irqreturn_t avs_dsp_irq_handler2(int irq, void *dev_id) +static irqreturn_t avs_dsp_irq_handler(int irq, void *dev_id) { struct avs_dev *adev = dev_id; return avs_hda_irq_handler(irq, &adev->base.core); } -__maybe_unused -static irqreturn_t avs_dsp_irq_thread2(int irq, void *dev_id) +static irqreturn_t avs_dsp_irq_thread(int irq, void *dev_id) { struct avs_dev *adev = dev_id; struct hdac_bus *bus = &adev->base.core; @@ -429,7 +346,7 @@ static int avs_hdac_acquire_irq(struct avs_dev *adev) return ret; } - ret = pci_request_irq(pci, 0, hdac_bus_irq_handler, hdac_bus_irq_thread, bus, + ret = pci_request_irq(pci, 0, avs_hda_irq_handler, avs_hda_irq_thread, bus, KBUILD_MODNAME); if (ret < 0) { dev_err(adev->dev, "Failed to request stream IRQ handler: %d\n", ret); @@ -610,8 +527,6 @@ static void avs_pci_shutdown(struct pci_dev *pci) snd_hdac_bus_stop_chip(bus); snd_hdac_display_power(bus, HDA_CODEC_IDX_CONTROLLER, false); - if (avs_platattr_test(adev, CLDMA)) - pci_free_irq(pci, 0, &code_loader); pci_free_irq(pci, 0, adev); pci_free_irq(pci, 0, bus); pci_free_irq_vectors(pci); diff --git a/sound/soc/intel/avs/icl.c b/sound/soc/intel/avs/icl.c index c18ea41d094b..e0880acf8050 100644 --- a/sound/soc/intel/avs/icl.c +++ b/sound/soc/intel/avs/icl.c @@ -189,8 +189,6 @@ const struct avs_dsp_ops avs_icl_dsp_ops = { .reset = avs_dsp_core_reset, .stall = avs_dsp_core_stall, .dsp_interrupt = avs_cnl_dsp_interrupt, - .irq_handler = avs_irq_handler, - .irq_thread = avs_cnl_irq_thread, .int_control = avs_dsp_interrupt_control, .load_basefw = avs_icl_load_basefw, .load_lib = avs_hda_load_library, diff --git a/sound/soc/intel/avs/ipc.c b/sound/soc/intel/avs/ipc.c index ad0e535b3c2e..f9b302215c37 100644 --- a/sound/soc/intel/avs/ipc.c +++ b/sound/soc/intel/avs/ipc.c @@ -301,54 +301,6 @@ void avs_dsp_process_response(struct avs_dev *adev, u64 header) complete(&ipc->busy_completion); } -irqreturn_t avs_irq_handler(struct avs_dev *adev) -{ - struct avs_ipc *ipc = adev->ipc; - const struct avs_spec *const spec = adev->spec; - u32 adspis, hipc_rsp, hipc_ack; - irqreturn_t ret = IRQ_NONE; - - adspis = snd_hdac_adsp_readl(adev, AVS_ADSP_REG_ADSPIS); - if (adspis == UINT_MAX || !(adspis & AVS_ADSP_ADSPIS_IPC)) - return ret; - - hipc_ack = snd_hdac_adsp_readl(adev, spec->hipc->ack_offset); - hipc_rsp = snd_hdac_adsp_readl(adev, spec->hipc->rsp_offset); - - /* DSP acked host's request */ - if (hipc_ack & spec->hipc->ack_done_mask) { - /* - * As an extra precaution, mask done interrupt. Code executed - * due to complete() found below does not assume any masking. - */ - snd_hdac_adsp_updatel(adev, spec->hipc->ctl_offset, - AVS_ADSP_HIPCCTL_DONE, 0); - - complete(&ipc->done_completion); - - /* tell DSP it has our attention */ - snd_hdac_adsp_updatel(adev, spec->hipc->ack_offset, - spec->hipc->ack_done_mask, - spec->hipc->ack_done_mask); - /* unmask done interrupt */ - snd_hdac_adsp_updatel(adev, spec->hipc->ctl_offset, - AVS_ADSP_HIPCCTL_DONE, - AVS_ADSP_HIPCCTL_DONE); - ret = IRQ_HANDLED; - } - - /* DSP sent new response to process */ - if (hipc_rsp & spec->hipc->rsp_busy_mask) { - /* mask busy interrupt */ - snd_hdac_adsp_updatel(adev, spec->hipc->ctl_offset, - AVS_ADSP_HIPCCTL_BUSY, 0); - - ret = IRQ_WAKE_THREAD; - } - - return ret; -} - static bool avs_ipc_is_busy(struct avs_ipc *ipc) { struct avs_dev *adev = to_avs_dev(ipc->dev); diff --git a/sound/soc/intel/avs/skl.c b/sound/soc/intel/avs/skl.c index 25abfead9f63..fceed353449a 100644 --- a/sound/soc/intel/avs/skl.c +++ b/sound/soc/intel/avs/skl.c @@ -13,31 +13,6 @@ #include "cldma.h" #include "messages.h" -irqreturn_t avs_skl_irq_thread(struct avs_dev *adev) -{ - union avs_reply_msg msg; - u32 hipct, hipcte; - - hipct = snd_hdac_adsp_readl(adev, SKL_ADSP_REG_HIPCT); - hipcte = snd_hdac_adsp_readl(adev, SKL_ADSP_REG_HIPCTE); - - /* Ensure DSP sent new response to process. */ - if (!(hipct & SKL_ADSP_HIPCT_BUSY)) - return IRQ_NONE; - - msg.primary = hipct; - msg.ext.val = hipcte; - avs_dsp_process_response(adev, msg.val); - - /* Tell DSP we accepted its message. */ - snd_hdac_adsp_updatel(adev, SKL_ADSP_REG_HIPCT, SKL_ADSP_HIPCT_BUSY, SKL_ADSP_HIPCT_BUSY); - /* Unmask busy interrupt. */ - snd_hdac_adsp_updatel(adev, SKL_ADSP_REG_HIPCCTL, AVS_ADSP_HIPCCTL_BUSY, - AVS_ADSP_HIPCCTL_BUSY); - - return IRQ_HANDLED; -} - void avs_skl_ipc_interrupt(struct avs_dev *adev) { const struct avs_spec *spec = adev->spec; @@ -190,8 +165,6 @@ const struct avs_dsp_ops avs_skl_dsp_ops = { .reset = avs_dsp_core_reset, .stall = avs_dsp_core_stall, .dsp_interrupt = avs_skl_dsp_interrupt, - .irq_handler = avs_irq_handler, - .irq_thread = avs_skl_irq_thread, .int_control = avs_dsp_interrupt_control, .load_basefw = avs_cldma_load_basefw, .load_lib = avs_cldma_load_library, diff --git a/sound/soc/intel/avs/tgl.c b/sound/soc/intel/avs/tgl.c index e3723ef38a33..b985a8299b72 100644 --- a/sound/soc/intel/avs/tgl.c +++ b/sound/soc/intel/avs/tgl.c @@ -40,8 +40,6 @@ const struct avs_dsp_ops avs_tgl_dsp_ops = { .reset = avs_tgl_dsp_core_reset, .stall = avs_tgl_dsp_core_stall, .dsp_interrupt = avs_cnl_dsp_interrupt, - .irq_handler = avs_irq_handler, - .irq_thread = avs_cnl_irq_thread, .int_control = avs_dsp_interrupt_control, .load_basefw = avs_icl_load_basefw, .load_lib = avs_hda_load_library, -- cgit v1.2.3 From 69197dfc64007b5292cc960581548f41ccd44828 Mon Sep 17 00:00:00 2001 From: Duanqiang Wen Date: Thu, 18 Apr 2024 10:15:56 +0800 Subject: net: libwx: fix alloc msix vectors failed driver needs queue msix vectors and one misc irq vector, but only queue vectors need irq affinity. when num_online_cpus is less than chip max msix vectors, driver will acquire (num_online_cpus + 1) vecotrs, and call pci_alloc_irq_vectors_affinity functions with affinity params without setting pre_vectors or post_vectors, it will cause return error code -ENOSPC. Misc irq vector is vector 0, driver need to set affinity params .pre_vectors = 1. Fixes: 3f703186113f ("net: libwx: Add irq flow functions") Signed-off-by: Duanqiang Wen Signed-off-by: David S. Miller --- drivers/net/ethernet/wangxun/libwx/wx_lib.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/ethernet/wangxun/libwx/wx_lib.c b/drivers/net/ethernet/wangxun/libwx/wx_lib.c index 6dff2c85682d..6fae161cbcb8 100644 --- a/drivers/net/ethernet/wangxun/libwx/wx_lib.c +++ b/drivers/net/ethernet/wangxun/libwx/wx_lib.c @@ -1598,7 +1598,7 @@ static void wx_set_num_queues(struct wx *wx) */ static int wx_acquire_msix_vectors(struct wx *wx) { - struct irq_affinity affd = {0, }; + struct irq_affinity affd = { .pre_vectors = 1 }; int nvecs, i; /* We start by asking for one vector per queue pair */ -- cgit v1.2.3 From f58f45c1e5b92975e91754f5407250085a6ae7cf Mon Sep 17 00:00:00 2001 From: David Bauer Date: Thu, 18 Apr 2024 15:29:08 +0200 Subject: vxlan: drop packets from invalid src-address The VXLAN driver currently does not check if the inner layer2 source-address is valid. In case source-address snooping/learning is enabled, a entry in the FDB for the invalid address is created with the layer3 address of the tunnel endpoint. If the frame happens to have a non-unicast address set, all this non-unicast traffic is subsequently not flooded to the tunnel network but sent to the learnt host in the FDB. To make matters worse, this FDB entry does not expire. Apply the same filtering for packets as it is done for bridges. This not only drops these invalid packets but avoids them from being learnt into the FDB. Fixes: d342894c5d2f ("vxlan: virtual extensible lan") Suggested-by: Ido Schimmel Signed-off-by: David Bauer Signed-off-by: David S. Miller --- drivers/net/vxlan/vxlan_core.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/net/vxlan/vxlan_core.c b/drivers/net/vxlan/vxlan_core.c index 3495591a5c29..ba319fc21957 100644 --- a/drivers/net/vxlan/vxlan_core.c +++ b/drivers/net/vxlan/vxlan_core.c @@ -1615,6 +1615,10 @@ static bool vxlan_set_mac(struct vxlan_dev *vxlan, if (ether_addr_equal(eth_hdr(skb)->h_source, vxlan->dev->dev_addr)) return false; + /* Ignore packets from invalid src-address */ + if (!is_valid_ether_addr(eth_hdr(skb)->h_source)) + return false; + /* Get address from the outer IP header */ if (vxlan_get_sk_family(vs) == AF_INET) { saddr.sin.sin_addr.s_addr = ip_hdr(skb)->saddr; -- cgit v1.2.3 From b552f63cd43735048bbe9bfbb7a9dcfce166fbdd Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Mon, 15 Apr 2024 21:02:12 +0200 Subject: thermal/debugfs: Add missing count increment to thermal_debug_tz_trip_up() The count field in struct trip_stats, representing the number of times the zone temperature was above the trip point, needs to be incremented in thermal_debug_tz_trip_up(), for two reasons. First, if a trip point is crossed on the way up for the first time, thermal_debug_update_temp() called from update_temperature() does not see it because it has not been added to trips_crossed[] array in the thermal zone's struct tz_debugfs object yet. Therefore, when thermal_debug_tz_trip_up() is called after that, the trip point's count value is 0, and the attempt to divide by it during the average temperature computation leads to a divide error which causes the kernel to crash. Setting the count to 1 before the division by incrementing it fixes this problem. Second, if a trip point is crossed on the way up, but it has been crossed on the way up already before, its count value needs to be incremented to make a record of the fact that the zone temperature is above the trip now. Without doing that, if the mitigations applied after crossing the trip cause the zone temperature to drop below its threshold, the count will not be updated for this episode at all and the average temperature in the trip statistics record will be somewhat higher than it should be. Fixes: 7ef01f228c9f ("thermal/debugfs: Add thermal debugfs information for mitigation episodes") Cc :6.8+ # 6.8+ Signed-off-by: Rafael J. Wysocki --- drivers/thermal/thermal_debugfs.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/thermal/thermal_debugfs.c b/drivers/thermal/thermal_debugfs.c index c617e8b9f0dd..d78d54ae2605 100644 --- a/drivers/thermal/thermal_debugfs.c +++ b/drivers/thermal/thermal_debugfs.c @@ -616,6 +616,7 @@ void thermal_debug_tz_trip_up(struct thermal_zone_device *tz, tze->trip_stats[trip_id].timestamp = now; tze->trip_stats[trip_id].max = max(tze->trip_stats[trip_id].max, temperature); tze->trip_stats[trip_id].min = min(tze->trip_stats[trip_id].min, temperature); + tze->trip_stats[trip_id].count++; tze->trip_stats[trip_id].avg = tze->trip_stats[trip_id].avg + (temperature - tze->trip_stats[trip_id].avg) / tze->trip_stats[trip_id].count; -- cgit v1.2.3 From 01bc4fda9ea0a6b52f12326486f07a4910666cf6 Mon Sep 17 00:00:00 2001 From: Li Nan Date: Fri, 19 Apr 2024 17:32:57 +0800 Subject: blk-iocost: do not WARN if iocg was already offlined In iocg_pay_debt(), warn is triggered if 'active_list' is empty, which is intended to confirm iocg is active when it has debt. However, warn can be triggered during a blkcg or disk removal, if iocg_waitq_timer_fn() is run at that time: WARNING: CPU: 0 PID: 2344971 at block/blk-iocost.c:1402 iocg_pay_debt+0x14c/0x190 Call trace: iocg_pay_debt+0x14c/0x190 iocg_kick_waitq+0x438/0x4c0 iocg_waitq_timer_fn+0xd8/0x130 __run_hrtimer+0x144/0x45c __hrtimer_run_queues+0x16c/0x244 hrtimer_interrupt+0x2cc/0x7b0 The warn in this situation is meaningless. Since this iocg is being removed, the state of the 'active_list' is irrelevant, and 'waitq_timer' is canceled after removing 'active_list' in ioc_pd_free(), which ensures iocg is freed after iocg_waitq_timer_fn() returns. Therefore, add the check if iocg was already offlined to avoid warn when removing a blkcg or disk. Signed-off-by: Li Nan Reviewed-by: Yu Kuai Acked-by: Tejun Heo Link: https://lore.kernel.org/r/20240419093257.3004211-1-linan666@huaweicloud.com Signed-off-by: Jens Axboe --- block/blk-iocost.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/block/blk-iocost.c b/block/blk-iocost.c index baa20c85799d..690ca99dfaca 100644 --- a/block/blk-iocost.c +++ b/block/blk-iocost.c @@ -1439,8 +1439,11 @@ static void iocg_pay_debt(struct ioc_gq *iocg, u64 abs_vpay, lockdep_assert_held(&iocg->ioc->lock); lockdep_assert_held(&iocg->waitq.lock); - /* make sure that nobody messed with @iocg */ - WARN_ON_ONCE(list_empty(&iocg->active_list)); + /* + * make sure that nobody messed with @iocg. Check iocg->pd.online + * to avoid warn when removing blkcg or disk. + */ + WARN_ON_ONCE(list_empty(&iocg->active_list) && iocg->pd.online); WARN_ON_ONCE(iocg->inuse > 1); iocg->abs_vdebt -= min(abs_vpay, iocg->abs_vdebt); -- cgit v1.2.3 From 50449ca66cc5a8cbc64749cf4b9f3d3fc5f4b457 Mon Sep 17 00:00:00 2001 From: Yaxiong Tian Date: Wed, 17 Apr 2024 10:52:48 +0800 Subject: arm64: hibernate: Fix level3 translation fault in swsusp_save() On arm64 machines, swsusp_save() faults if it attempts to access MEMBLOCK_NOMAP memory ranges. This can be reproduced in QEMU using UEFI when booting with rodata=off debug_pagealloc=off and CONFIG_KFENCE=n: Unable to handle kernel paging request at virtual address ffffff8000000000 Mem abort info: ESR = 0x0000000096000007 EC = 0x25: DABT (current EL), IL = 32 bits SET = 0, FnV = 0 EA = 0, S1PTW = 0 FSC = 0x07: level 3 translation fault Data abort info: ISV = 0, ISS = 0x00000007, ISS2 = 0x00000000 CM = 0, WnR = 0, TnD = 0, TagAccess = 0 GCS = 0, Overlay = 0, DirtyBit = 0, Xs = 0 swapper pgtable: 4k pages, 39-bit VAs, pgdp=00000000eeb0b000 [ffffff8000000000] pgd=180000217fff9803, p4d=180000217fff9803, pud=180000217fff9803, pmd=180000217fff8803, pte=0000000000000000 Internal error: Oops: 0000000096000007 [#1] SMP Internal error: Oops: 0000000096000007 [#1] SMP Modules linked in: xt_multiport ipt_REJECT nf_reject_ipv4 xt_conntrack nf_conntrack nf_defrag_ipv6 nf_defrag_ipv4 libcrc32c iptable_filter bpfilter rfkill at803x snd_hda_codec_hdmi snd_hda_intel snd_intel_dspcfg dwmac_generic stmmac_platform snd_hda_codec stmmac joydev pcs_xpcs snd_hda_core phylink ppdev lp parport ramoops reed_solomon ip_tables x_tables nls_iso8859_1 vfat multipath linear amdgpu amdxcp drm_exec gpu_sched drm_buddy hid_generic usbhid hid radeon video drm_suballoc_helper drm_ttm_helper ttm i2c_algo_bit drm_display_helper cec drm_kms_helper drm CPU: 0 PID: 3663 Comm: systemd-sleep Not tainted 6.6.2+ #76 Source Version: 4e22ed63a0a48e7a7cff9b98b7806d8d4add7dc0 Hardware name: Greatwall GW-XXXXXX-XXX/GW-XXXXXX-XXX, BIOS KunLun BIOS V4.0 01/19/2021 pstate: 600003c5 (nZCv DAIF -PAN -UAO -TCO -DIT -SSBS BTYPE=--) pc : swsusp_save+0x280/0x538 lr : swsusp_save+0x280/0x538 sp : ffffffa034a3fa40 x29: ffffffa034a3fa40 x28: ffffff8000001000 x27: 0000000000000000 x26: ffffff8001400000 x25: ffffffc08113e248 x24: 0000000000000000 x23: 0000000000080000 x22: ffffffc08113e280 x21: 00000000000c69f2 x20: ffffff8000000000 x19: ffffffc081ae2500 x18: 0000000000000000 x17: 6666662074736420 x16: 3030303030303030 x15: 3038666666666666 x14: 0000000000000b69 x13: ffffff9f89088530 x12: 00000000ffffffea x11: 00000000ffff7fff x10: 00000000ffff7fff x9 : ffffffc08193f0d0 x8 : 00000000000bffe8 x7 : c0000000ffff7fff x6 : 0000000000000001 x5 : ffffffa0fff09dc8 x4 : 0000000000000000 x3 : 0000000000000027 x2 : 0000000000000000 x1 : 0000000000000000 x0 : 000000000000004e Call trace: swsusp_save+0x280/0x538 swsusp_arch_suspend+0x148/0x190 hibernation_snapshot+0x240/0x39c hibernate+0xc4/0x378 state_store+0xf0/0x10c kobj_attr_store+0x14/0x24 The reason is swsusp_save() -> copy_data_pages() -> page_is_saveable() -> kernel_page_present() assuming that a page is always present when can_set_direct_map() is false (all of rodata_full, debug_pagealloc_enabled() and arm64_kfence_can_set_direct_map() false), irrespective of the MEMBLOCK_NOMAP ranges. Such MEMBLOCK_NOMAP regions should not be saved during hibernation. This problem was introduced by changes to the pfn_valid() logic in commit a7d9f306ba70 ("arm64: drop pfn_valid_within() and simplify pfn_valid()"). Similar to other architectures, drop the !can_set_direct_map() check in kernel_page_present() so that page_is_savable() skips such pages. Fixes: a7d9f306ba70 ("arm64: drop pfn_valid_within() and simplify pfn_valid()") Cc: # 5.14.x Suggested-by: Mike Rapoport Suggested-by: Catalin Marinas Co-developed-by: xiongxin Signed-off-by: xiongxin Signed-off-by: Yaxiong Tian Acked-by: Mike Rapoport (IBM) Link: https://lore.kernel.org/r/20240417025248.386622-1-tianyaxiong@kylinos.cn [catalin.marinas@arm.com: rework commit message] Signed-off-by: Catalin Marinas --- arch/arm64/mm/pageattr.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/arch/arm64/mm/pageattr.c b/arch/arm64/mm/pageattr.c index 0c4e3ecf989d..0e270a1c51e6 100644 --- a/arch/arm64/mm/pageattr.c +++ b/arch/arm64/mm/pageattr.c @@ -219,9 +219,6 @@ bool kernel_page_present(struct page *page) pte_t *ptep; unsigned long addr = (unsigned long)page_address(page); - if (!can_set_direct_map()) - return true; - pgdp = pgd_offset_k(addr); if (pgd_none(READ_ONCE(*pgdp))) return false; -- cgit v1.2.3 From dad80c6bff770d25f67ec25fe011730e4a463008 Mon Sep 17 00:00:00 2001 From: David Howells Date: Thu, 4 Apr 2024 16:05:19 +0100 Subject: cifs: Fix reacquisition of volume cookie on still-live connection During mount, cifs_mount_get_tcon() gets a tcon resource connection record and then attaches an fscache volume cookie to it. However, it does this irrespective of whether or not the tcon returned from cifs_get_tcon() is a new record or one that's already in use. This leads to a warning about a volume cookie collision and a leaked volume cookie because tcon->fscache gets reset. Fix this be adding a mutex and a "we've already tried this" flag and only doing it once for the lifetime of the tcon. [!] Note: Looking at cifs_mount_get_tcon(), a more general solution may actually be required. Reacquiring the volume cookie isn't the only thing that function does: it also partially reinitialises the tcon record without any locking - which may cause live filesystem ops already using the tcon through a previous mount to malfunction. This can be reproduced simply by something like: mount //example.com/test /xfstest.test -o user=shares,pass=xxx,fsc mount //example.com/test /mnt -o user=shares,pass=xxx,fsc Fixes: 70431bfd825d ("cifs: Support fscache indexing rewrite") Signed-off-by: David Howells Acked-by: Paulo Alcantara (Red Hat) cc: Shyam Prasad N cc: linux-cifs@vger.kernel.org cc: linux-fsdevel@vger.kernel.org Signed-off-by: Steve French --- fs/smb/client/cifsglob.h | 2 ++ fs/smb/client/fscache.c | 13 +++++++++++++ fs/smb/client/misc.c | 3 +++ 3 files changed, 18 insertions(+) diff --git a/fs/smb/client/cifsglob.h b/fs/smb/client/cifsglob.h index d6669ce4ae87..fc09d1c0ee07 100644 --- a/fs/smb/client/cifsglob.h +++ b/fs/smb/client/cifsglob.h @@ -1276,7 +1276,9 @@ struct cifs_tcon { __u32 max_cached_dirs; #ifdef CONFIG_CIFS_FSCACHE u64 resource_id; /* server resource id */ + bool fscache_acquired; /* T if we've tried acquiring a cookie */ struct fscache_volume *fscache; /* cookie for share */ + struct mutex fscache_lock; /* Prevent regetting a cookie */ #endif struct list_head pending_opens; /* list of incomplete opens */ struct cached_fids *cfids; diff --git a/fs/smb/client/fscache.c b/fs/smb/client/fscache.c index 340efce8f052..113bde8f1e61 100644 --- a/fs/smb/client/fscache.c +++ b/fs/smb/client/fscache.c @@ -43,12 +43,23 @@ int cifs_fscache_get_super_cookie(struct cifs_tcon *tcon) char *key; int ret = -ENOMEM; + if (tcon->fscache_acquired) + return 0; + + mutex_lock(&tcon->fscache_lock); + if (tcon->fscache_acquired) { + mutex_unlock(&tcon->fscache_lock); + return 0; + } + tcon->fscache_acquired = true; + tcon->fscache = NULL; switch (sa->sa_family) { case AF_INET: case AF_INET6: break; default: + mutex_unlock(&tcon->fscache_lock); cifs_dbg(VFS, "Unknown network family '%d'\n", sa->sa_family); return -EINVAL; } @@ -57,6 +68,7 @@ int cifs_fscache_get_super_cookie(struct cifs_tcon *tcon) sharename = extract_sharename(tcon->tree_name); if (IS_ERR(sharename)) { + mutex_unlock(&tcon->fscache_lock); cifs_dbg(FYI, "%s: couldn't extract sharename\n", __func__); return PTR_ERR(sharename); } @@ -90,6 +102,7 @@ out_2: kfree(key); out: kfree(sharename); + mutex_unlock(&tcon->fscache_lock); return ret; } diff --git a/fs/smb/client/misc.c b/fs/smb/client/misc.c index 7d15a1969b81..ad44f8d66b37 100644 --- a/fs/smb/client/misc.c +++ b/fs/smb/client/misc.c @@ -139,6 +139,9 @@ tcon_info_alloc(bool dir_leases_enabled) atomic_set(&ret_buf->num_local_opens, 0); atomic_set(&ret_buf->num_remote_opens, 0); ret_buf->stats_from_time = ktime_get_real_seconds(); +#ifdef CONFIG_CIFS_FSCACHE + mutex_init(&ret_buf->fscache_lock); +#endif return ret_buf; } -- cgit v1.2.3 From afc23febd51c7e24361e3a9c09f3e892eb0a41ea Mon Sep 17 00:00:00 2001 From: David Howells Date: Thu, 4 Apr 2024 13:51:36 +0100 Subject: cifs: Add tracing for the cifs_tcon struct refcounting Add tracing for the refcounting/lifecycle of the cifs_tcon struct, marking different events with different labels and giving each tcon its own debug ID so that the tracelines corresponding to individual tcons can be distinguished. This can be enabled with: echo 1 >/sys/kernel/debug/tracing/events/cifs/smb3_tcon_ref/enable Signed-off-by: David Howells Acked-by: Paulo Alcantara (Red Hat) cc: Shyam Prasad N cc: linux-cifs@vger.kernel.org cc: linux-fsdevel@vger.kernel.org Signed-off-by: Steve French --- fs/smb/client/cifsfs.c | 2 + fs/smb/client/cifsglob.h | 1 + fs/smb/client/cifsproto.h | 9 ++--- fs/smb/client/connect.c | 21 +++++----- fs/smb/client/fscache.c | 7 ++++ fs/smb/client/misc.c | 10 +++-- fs/smb/client/smb2misc.c | 10 +++-- fs/smb/client/smb2ops.c | 7 +++- fs/smb/client/smb2pdu.c | 8 ++-- fs/smb/client/smb2transport.c | 2 + fs/smb/client/trace.h | 92 ++++++++++++++++++++++++++++++++++++++++++- 11 files changed, 143 insertions(+), 26 deletions(-) diff --git a/fs/smb/client/cifsfs.c b/fs/smb/client/cifsfs.c index d41eedbff674..30781789dfd9 100644 --- a/fs/smb/client/cifsfs.c +++ b/fs/smb/client/cifsfs.c @@ -739,6 +739,8 @@ static void cifs_umount_begin(struct super_block *sb) spin_lock(&cifs_tcp_ses_lock); spin_lock(&tcon->tc_lock); + trace_smb3_tcon_ref(tcon->debug_id, tcon->tc_count, + netfs_trace_tcon_ref_see_umount); if ((tcon->tc_count > 1) || (tcon->status == TID_EXITING)) { /* we have other mounts to same share or we have already tried to umount this and woken up diff --git a/fs/smb/client/cifsglob.h b/fs/smb/client/cifsglob.h index fc09d1c0ee07..6ff35570db81 100644 --- a/fs/smb/client/cifsglob.h +++ b/fs/smb/client/cifsglob.h @@ -1190,6 +1190,7 @@ struct cifs_fattr { */ struct cifs_tcon { struct list_head tcon_list; + int debug_id; /* Debugging for tracing */ int tc_count; struct list_head rlist; /* reconnect list */ spinlock_t tc_lock; /* protect anything here that is not protected */ diff --git a/fs/smb/client/cifsproto.h b/fs/smb/client/cifsproto.h index 8e0a348f1f66..fbc358c09da3 100644 --- a/fs/smb/client/cifsproto.h +++ b/fs/smb/client/cifsproto.h @@ -303,7 +303,7 @@ cifs_get_tcp_session(struct smb3_fs_context *ctx, struct TCP_Server_Info *primary_server); extern void cifs_put_tcp_session(struct TCP_Server_Info *server, int from_reconnect); -extern void cifs_put_tcon(struct cifs_tcon *tcon); +extern void cifs_put_tcon(struct cifs_tcon *tcon, enum smb3_tcon_ref_trace trace); extern void cifs_release_automount_timer(void); @@ -530,8 +530,9 @@ extern int CIFSSMBLogoff(const unsigned int xid, struct cifs_ses *ses); extern struct cifs_ses *sesInfoAlloc(void); extern void sesInfoFree(struct cifs_ses *); -extern struct cifs_tcon *tcon_info_alloc(bool dir_leases_enabled); -extern void tconInfoFree(struct cifs_tcon *); +extern struct cifs_tcon *tcon_info_alloc(bool dir_leases_enabled, + enum smb3_tcon_ref_trace trace); +extern void tconInfoFree(struct cifs_tcon *tcon, enum smb3_tcon_ref_trace trace); extern int cifs_sign_rqst(struct smb_rqst *rqst, struct TCP_Server_Info *server, __u32 *pexpected_response_sequence_number); @@ -721,8 +722,6 @@ static inline int cifs_create_options(struct cifs_sb_info *cifs_sb, int options) return options; } -struct super_block *cifs_get_tcon_super(struct cifs_tcon *tcon); -void cifs_put_tcon_super(struct super_block *sb); int cifs_wait_for_server_reconnect(struct TCP_Server_Info *server, bool retry); /* Put references of @ses and its children */ diff --git a/fs/smb/client/connect.c b/fs/smb/client/connect.c index 4e35970681bf..7a16e12f5da8 100644 --- a/fs/smb/client/connect.c +++ b/fs/smb/client/connect.c @@ -1943,7 +1943,7 @@ cifs_setup_ipc(struct cifs_ses *ses, struct smb3_fs_context *ctx) } /* no need to setup directory caching on IPC share, so pass in false */ - tcon = tcon_info_alloc(false); + tcon = tcon_info_alloc(false, netfs_trace_tcon_ref_new_ipc); if (tcon == NULL) return -ENOMEM; @@ -1960,7 +1960,7 @@ cifs_setup_ipc(struct cifs_ses *ses, struct smb3_fs_context *ctx) if (rc) { cifs_server_dbg(VFS, "failed to connect to IPC (rc=%d)\n", rc); - tconInfoFree(tcon); + tconInfoFree(tcon, netfs_trace_tcon_ref_free_ipc_fail); goto out; } @@ -2043,7 +2043,7 @@ void __cifs_put_smb_ses(struct cifs_ses *ses) * files on session close, as specified in MS-SMB2 3.3.5.6 Receiving an * SMB2 LOGOFF Request. */ - tconInfoFree(tcon); + tconInfoFree(tcon, netfs_trace_tcon_ref_free_ipc); if (do_logoff) { xid = get_xid(); rc = server->ops->logoff(xid, ses); @@ -2432,6 +2432,8 @@ cifs_find_tcon(struct cifs_ses *ses, struct smb3_fs_context *ctx) continue; } ++tcon->tc_count; + trace_smb3_tcon_ref(tcon->debug_id, tcon->tc_count, + netfs_trace_tcon_ref_get_find); spin_unlock(&tcon->tc_lock); spin_unlock(&cifs_tcp_ses_lock); return tcon; @@ -2441,7 +2443,7 @@ cifs_find_tcon(struct cifs_ses *ses, struct smb3_fs_context *ctx) } void -cifs_put_tcon(struct cifs_tcon *tcon) +cifs_put_tcon(struct cifs_tcon *tcon, enum smb3_tcon_ref_trace trace) { unsigned int xid; struct cifs_ses *ses; @@ -2457,6 +2459,7 @@ cifs_put_tcon(struct cifs_tcon *tcon) cifs_dbg(FYI, "%s: tc_count=%d\n", __func__, tcon->tc_count); spin_lock(&cifs_tcp_ses_lock); spin_lock(&tcon->tc_lock); + trace_smb3_tcon_ref(tcon->debug_id, tcon->tc_count - 1, trace); if (--tcon->tc_count > 0) { spin_unlock(&tcon->tc_lock); spin_unlock(&cifs_tcp_ses_lock); @@ -2493,7 +2496,7 @@ cifs_put_tcon(struct cifs_tcon *tcon) _free_xid(xid); cifs_fscache_release_super_cookie(tcon); - tconInfoFree(tcon); + tconInfoFree(tcon, netfs_trace_tcon_ref_free); cifs_put_smb_ses(ses); } @@ -2547,7 +2550,7 @@ cifs_get_tcon(struct cifs_ses *ses, struct smb3_fs_context *ctx) nohandlecache = ctx->nohandlecache; else nohandlecache = true; - tcon = tcon_info_alloc(!nohandlecache); + tcon = tcon_info_alloc(!nohandlecache, netfs_trace_tcon_ref_new); if (tcon == NULL) { rc = -ENOMEM; goto out_fail; @@ -2737,7 +2740,7 @@ cifs_get_tcon(struct cifs_ses *ses, struct smb3_fs_context *ctx) return tcon; out_fail: - tconInfoFree(tcon); + tconInfoFree(tcon, netfs_trace_tcon_ref_free_fail); return ERR_PTR(rc); } @@ -2754,7 +2757,7 @@ cifs_put_tlink(struct tcon_link *tlink) } if (!IS_ERR(tlink_tcon(tlink))) - cifs_put_tcon(tlink_tcon(tlink)); + cifs_put_tcon(tlink_tcon(tlink), netfs_trace_tcon_ref_put_tlink); kfree(tlink); } @@ -3319,7 +3322,7 @@ void cifs_mount_put_conns(struct cifs_mount_ctx *mnt_ctx) int rc = 0; if (mnt_ctx->tcon) - cifs_put_tcon(mnt_ctx->tcon); + cifs_put_tcon(mnt_ctx->tcon, netfs_trace_tcon_ref_put_mnt_ctx); else if (mnt_ctx->ses) cifs_put_smb_ses(mnt_ctx->ses); else if (mnt_ctx->server) diff --git a/fs/smb/client/fscache.c b/fs/smb/client/fscache.c index 113bde8f1e61..1a895e6243ee 100644 --- a/fs/smb/client/fscache.c +++ b/fs/smb/client/fscache.c @@ -94,6 +94,11 @@ int cifs_fscache_get_super_cookie(struct cifs_tcon *tcon) } pr_err("Cache volume key already in use (%s)\n", key); vcookie = NULL; + trace_smb3_tcon_ref(tcon->debug_id, tcon->tc_count, + netfs_trace_tcon_ref_see_fscache_collision); + } else { + trace_smb3_tcon_ref(tcon->debug_id, tcon->tc_count, + netfs_trace_tcon_ref_see_fscache_okay); } tcon->fscache = vcookie; @@ -115,6 +120,8 @@ void cifs_fscache_release_super_cookie(struct cifs_tcon *tcon) cifs_fscache_fill_volume_coherency(tcon, &cd); fscache_relinquish_volume(tcon->fscache, &cd, false); tcon->fscache = NULL; + trace_smb3_tcon_ref(tcon->debug_id, tcon->tc_count, + netfs_trace_tcon_ref_see_fscache_relinq); } void cifs_fscache_get_inode_cookie(struct inode *inode) diff --git a/fs/smb/client/misc.c b/fs/smb/client/misc.c index ad44f8d66b37..07c468ddb88a 100644 --- a/fs/smb/client/misc.c +++ b/fs/smb/client/misc.c @@ -111,9 +111,10 @@ sesInfoFree(struct cifs_ses *buf_to_free) } struct cifs_tcon * -tcon_info_alloc(bool dir_leases_enabled) +tcon_info_alloc(bool dir_leases_enabled, enum smb3_tcon_ref_trace trace) { struct cifs_tcon *ret_buf; + static atomic_t tcon_debug_id; ret_buf = kzalloc(sizeof(*ret_buf), GFP_KERNEL); if (!ret_buf) @@ -130,7 +131,8 @@ tcon_info_alloc(bool dir_leases_enabled) atomic_inc(&tconInfoAllocCount); ret_buf->status = TID_NEW; - ++ret_buf->tc_count; + ret_buf->debug_id = atomic_inc_return(&tcon_debug_id); + ret_buf->tc_count = 1; spin_lock_init(&ret_buf->tc_lock); INIT_LIST_HEAD(&ret_buf->openFileList); INIT_LIST_HEAD(&ret_buf->tcon_list); @@ -142,17 +144,19 @@ tcon_info_alloc(bool dir_leases_enabled) #ifdef CONFIG_CIFS_FSCACHE mutex_init(&ret_buf->fscache_lock); #endif + trace_smb3_tcon_ref(ret_buf->debug_id, ret_buf->tc_count, trace); return ret_buf; } void -tconInfoFree(struct cifs_tcon *tcon) +tconInfoFree(struct cifs_tcon *tcon, enum smb3_tcon_ref_trace trace) { if (tcon == NULL) { cifs_dbg(FYI, "Null buffer passed to tconInfoFree\n"); return; } + trace_smb3_tcon_ref(tcon->debug_id, tcon->tc_count, trace); free_cached_dirs(tcon->cfids); atomic_dec(&tconInfoAllocCount); kfree(tcon->nativeFileSystem); diff --git a/fs/smb/client/smb2misc.c b/fs/smb/client/smb2misc.c index cc72be5a93a9..677ef6f99a5b 100644 --- a/fs/smb/client/smb2misc.c +++ b/fs/smb/client/smb2misc.c @@ -767,7 +767,7 @@ smb2_cancelled_close_fid(struct work_struct *work) if (rc) cifs_tcon_dbg(VFS, "Close cancelled mid failed rc:%d\n", rc); - cifs_put_tcon(tcon); + cifs_put_tcon(tcon, netfs_trace_tcon_ref_put_cancelled_close_fid); kfree(cancelled); } @@ -811,6 +811,8 @@ smb2_handle_cancelled_close(struct cifs_tcon *tcon, __u64 persistent_fid, if (tcon->tc_count <= 0) { struct TCP_Server_Info *server = NULL; + trace_smb3_tcon_ref(tcon->debug_id, tcon->tc_count, + netfs_trace_tcon_ref_see_cancelled_close); WARN_ONCE(tcon->tc_count < 0, "tcon refcount is negative"); spin_unlock(&cifs_tcp_ses_lock); @@ -823,12 +825,14 @@ smb2_handle_cancelled_close(struct cifs_tcon *tcon, __u64 persistent_fid, return 0; } tcon->tc_count++; + trace_smb3_tcon_ref(tcon->debug_id, tcon->tc_count, + netfs_trace_tcon_ref_get_cancelled_close); spin_unlock(&cifs_tcp_ses_lock); rc = __smb2_handle_cancelled_cmd(tcon, SMB2_CLOSE_HE, 0, persistent_fid, volatile_fid); if (rc) - cifs_put_tcon(tcon); + cifs_put_tcon(tcon, netfs_trace_tcon_ref_put_cancelled_close); return rc; } @@ -856,7 +860,7 @@ smb2_handle_cancelled_mid(struct mid_q_entry *mid, struct TCP_Server_Info *serve rsp->PersistentFileId, rsp->VolatileFileId); if (rc) - cifs_put_tcon(tcon); + cifs_put_tcon(tcon, netfs_trace_tcon_ref_put_cancelled_mid); return rc; } diff --git a/fs/smb/client/smb2ops.c b/fs/smb/client/smb2ops.c index 78c94d0350fe..28f0b7d19d53 100644 --- a/fs/smb/client/smb2ops.c +++ b/fs/smb/client/smb2ops.c @@ -2915,8 +2915,11 @@ smb2_get_dfs_refer(const unsigned int xid, struct cifs_ses *ses, tcon = list_first_entry_or_null(&ses->tcon_list, struct cifs_tcon, tcon_list); - if (tcon) + if (tcon) { tcon->tc_count++; + trace_smb3_tcon_ref(tcon->debug_id, tcon->tc_count, + netfs_trace_tcon_ref_get_dfs_refer); + } spin_unlock(&cifs_tcp_ses_lock); } @@ -2980,6 +2983,8 @@ smb2_get_dfs_refer(const unsigned int xid, struct cifs_ses *ses, /* ipc tcons are not refcounted */ spin_lock(&cifs_tcp_ses_lock); tcon->tc_count--; + trace_smb3_tcon_ref(tcon->debug_id, tcon->tc_count, + netfs_trace_tcon_ref_dec_dfs_refer); /* tc_count can never go negative */ WARN_ON(tcon->tc_count < 0); spin_unlock(&cifs_tcp_ses_lock); diff --git a/fs/smb/client/smb2pdu.c b/fs/smb/client/smb2pdu.c index 86c647a947cc..a5efce03cb58 100644 --- a/fs/smb/client/smb2pdu.c +++ b/fs/smb/client/smb2pdu.c @@ -4138,6 +4138,8 @@ void smb2_reconnect_server(struct work_struct *work) list_for_each_entry(tcon, &ses->tcon_list, tcon_list) { if (tcon->need_reconnect || tcon->need_reopen_files) { tcon->tc_count++; + trace_smb3_tcon_ref(tcon->debug_id, tcon->tc_count, + netfs_trace_tcon_ref_get_reconnect_server); list_add_tail(&tcon->rlist, &tmp_list); tcon_selected = true; } @@ -4176,14 +4178,14 @@ void smb2_reconnect_server(struct work_struct *work) if (tcon->ipc) cifs_put_smb_ses(tcon->ses); else - cifs_put_tcon(tcon); + cifs_put_tcon(tcon, netfs_trace_tcon_ref_put_reconnect_server); } if (!ses_exist) goto done; /* allocate a dummy tcon struct used for reconnect */ - tcon = tcon_info_alloc(false); + tcon = tcon_info_alloc(false, netfs_trace_tcon_ref_new_reconnect_server); if (!tcon) { resched = true; list_for_each_entry_safe(ses, ses2, &tmp_ses_list, rlist) { @@ -4206,7 +4208,7 @@ void smb2_reconnect_server(struct work_struct *work) list_del_init(&ses->rlist); cifs_put_smb_ses(ses); } - tconInfoFree(tcon); + tconInfoFree(tcon, netfs_trace_tcon_ref_free_reconnect_server); done: cifs_dbg(FYI, "Reconnecting tcons and channels finished\n"); diff --git a/fs/smb/client/smb2transport.c b/fs/smb/client/smb2transport.c index 1d6e54f7879e..02135a605305 100644 --- a/fs/smb/client/smb2transport.c +++ b/fs/smb/client/smb2transport.c @@ -189,6 +189,8 @@ smb2_find_smb_sess_tcon_unlocked(struct cifs_ses *ses, __u32 tid) if (tcon->tid != tid) continue; ++tcon->tc_count; + trace_smb3_tcon_ref(tcon->debug_id, tcon->tc_count, + netfs_trace_tcon_ref_get_find_sess_tcon); return tcon; } diff --git a/fs/smb/client/trace.h b/fs/smb/client/trace.h index 5e83cb9da902..604e52876cd2 100644 --- a/fs/smb/client/trace.h +++ b/fs/smb/client/trace.h @@ -3,6 +3,9 @@ * Copyright (C) 2018, Microsoft Corporation. * * Author(s): Steve French + * + * Please use this 3-part article as a reference for writing new tracepoints: + * https://lwn.net/Articles/379903/ */ #undef TRACE_SYSTEM #define TRACE_SYSTEM cifs @@ -15,9 +18,70 @@ #include /* - * Please use this 3-part article as a reference for writing new tracepoints: - * https://lwn.net/Articles/379903/ + * Specify enums for tracing information. + */ +#define smb3_tcon_ref_traces \ + EM(netfs_trace_tcon_ref_dec_dfs_refer, "DEC DfsRef") \ + EM(netfs_trace_tcon_ref_free, "FRE ") \ + EM(netfs_trace_tcon_ref_free_fail, "FRE Fail ") \ + EM(netfs_trace_tcon_ref_free_ipc, "FRE Ipc ") \ + EM(netfs_trace_tcon_ref_free_ipc_fail, "FRE Ipc-F ") \ + EM(netfs_trace_tcon_ref_free_reconnect_server, "FRE Reconn") \ + EM(netfs_trace_tcon_ref_get_cancelled_close, "GET Cn-Cls") \ + EM(netfs_trace_tcon_ref_get_dfs_refer, "GET DfsRef") \ + EM(netfs_trace_tcon_ref_get_find, "GET Find ") \ + EM(netfs_trace_tcon_ref_get_find_sess_tcon, "GET FndSes") \ + EM(netfs_trace_tcon_ref_get_reconnect_server, "GET Reconn") \ + EM(netfs_trace_tcon_ref_new, "NEW ") \ + EM(netfs_trace_tcon_ref_new_ipc, "NEW Ipc ") \ + EM(netfs_trace_tcon_ref_new_reconnect_server, "NEW Reconn") \ + EM(netfs_trace_tcon_ref_put_cancelled_close, "PUT Cn-Cls") \ + EM(netfs_trace_tcon_ref_put_cancelled_close_fid, "PUT Cn-Fid") \ + EM(netfs_trace_tcon_ref_put_cancelled_mid, "PUT Cn-Mid") \ + EM(netfs_trace_tcon_ref_put_mnt_ctx, "PUT MntCtx") \ + EM(netfs_trace_tcon_ref_put_reconnect_server, "PUT Reconn") \ + EM(netfs_trace_tcon_ref_put_tlink, "PUT Tlink ") \ + EM(netfs_trace_tcon_ref_see_cancelled_close, "SEE Cn-Cls") \ + EM(netfs_trace_tcon_ref_see_fscache_collision, "SEE FV-CO!") \ + EM(netfs_trace_tcon_ref_see_fscache_okay, "SEE FV-Ok ") \ + EM(netfs_trace_tcon_ref_see_fscache_relinq, "SEE FV-Rlq") \ + E_(netfs_trace_tcon_ref_see_umount, "SEE Umount") + +#undef EM +#undef E_ + +/* + * Define those tracing enums. + */ +#ifndef __SMB3_DECLARE_TRACE_ENUMS_ONCE_ONLY +#define __SMB3_DECLARE_TRACE_ENUMS_ONCE_ONLY + +#define EM(a, b) a, +#define E_(a, b) a + +enum smb3_tcon_ref_trace { smb3_tcon_ref_traces } __mode(byte); + +#undef EM +#undef E_ +#endif + +/* + * Export enum symbols via userspace. + */ +#define EM(a, b) TRACE_DEFINE_ENUM(a); +#define E_(a, b) TRACE_DEFINE_ENUM(a); + +smb3_tcon_ref_traces; + +#undef EM +#undef E_ + +/* + * Now redefine the EM() and E_() macros to map the enums to the strings that + * will be printed in the output. */ +#define EM(a, b) { a, b }, +#define E_(a, b) { a, b } /* For logging errors in read or write */ DECLARE_EVENT_CLASS(smb3_rw_err_class, @@ -1125,6 +1189,30 @@ DEFINE_SMB3_CREDIT_EVENT(waitff_credits); DEFINE_SMB3_CREDIT_EVENT(overflow_credits); DEFINE_SMB3_CREDIT_EVENT(set_credits); + +TRACE_EVENT(smb3_tcon_ref, + TP_PROTO(unsigned int tcon_debug_id, int ref, + enum smb3_tcon_ref_trace trace), + TP_ARGS(tcon_debug_id, ref, trace), + TP_STRUCT__entry( + __field(unsigned int, tcon) + __field(int, ref) + __field(enum smb3_tcon_ref_trace, trace) + ), + TP_fast_assign( + __entry->tcon = tcon_debug_id; + __entry->ref = ref; + __entry->trace = trace; + ), + TP_printk("TC=%08x %s r=%u", + __entry->tcon, + __print_symbolic(__entry->trace, smb3_tcon_ref_traces), + __entry->ref) + ); + + +#undef EM +#undef E_ #endif /* _CIFS_TRACE_H */ #undef TRACE_INCLUDE_PATH -- cgit v1.2.3 From 18d86965e31f9be4d477da0744a7cdc9815858de Mon Sep 17 00:00:00 2001 From: Paulo Alcantara Date: Fri, 19 Apr 2024 12:05:07 -0300 Subject: smb: client: fix rename(2) regression against samba After commit 2c7d399e551c ("smb: client: reuse file lease key in compound operations") the client started reusing lease keys for rename, unlink and set path size operations to prevent it from breaking its own leases and thus causing unnecessary lease breaks to same connection. The implementation relies on positive dentries and cifsInodeInfo::lease_granted to decide whether reusing lease keys for the compound requests. cifsInodeInfo::lease_granted was introduced by commit 0ab95c2510b6 ("Defer close only when lease is enabled.") to indicate whether lease caching is granted for a specific file, but that can only happen until file is open, so cifsInodeInfo::lease_granted was left uninitialised in ->alloc_inode and then client started sending random lease keys for files that hadn't any leases. This fixes the following test case against samba: mount.cifs //srv/share /mnt/1 -o ...,nosharesock mount.cifs //srv/share /mnt/2 -o ...,nosharesock touch /mnt/1/foo; tail -f /mnt/1/foo & pid=$! mv /mnt/2/foo /mnt/2/bar # fails with -EIO kill $pid Fixes: 0ab95c2510b6 ("Defer close only when lease is enabled.") Signed-off-by: Paulo Alcantara (Red Hat) Signed-off-by: Steve French --- fs/smb/client/cifsfs.c | 1 + 1 file changed, 1 insertion(+) diff --git a/fs/smb/client/cifsfs.c b/fs/smb/client/cifsfs.c index 30781789dfd9..39277c37185c 100644 --- a/fs/smb/client/cifsfs.c +++ b/fs/smb/client/cifsfs.c @@ -389,6 +389,7 @@ cifs_alloc_inode(struct super_block *sb) * server, can not assume caching of file data or metadata. */ cifs_set_oplock_level(cifs_inode, 0); + cifs_inode->lease_granted = false; cifs_inode->flags = 0; spin_lock_init(&cifs_inode->writers_lock); cifs_inode->writers = 0; -- cgit v1.2.3 From c119f4ede3fa90a9463f50831761c28f989bfb20 Mon Sep 17 00:00:00 2001 From: Namjae Jeon Date: Thu, 11 Apr 2024 23:02:15 +0900 Subject: ksmbd: fix slab-out-of-bounds in smb2_allocate_rsp_buf If ->ProtocolId is SMB2_TRANSFORM_PROTO_NUM, smb2 request size validation could be skipped. if request size is smaller than sizeof(struct smb2_query_info_req), slab-out-of-bounds read can happen in smb2_allocate_rsp_buf(). This patch allocate response buffer after decrypting transform request. smb3_decrypt_req() will validate transform request size and avoid slab-out-of-bound in smb2_allocate_rsp_buf(). Reported-by: Norbert Szetei Cc: stable@vger.kernel.org Signed-off-by: Namjae Jeon Signed-off-by: Steve French --- fs/smb/server/server.c | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/fs/smb/server/server.c b/fs/smb/server/server.c index c0788188aa82..c67fbc8d6683 100644 --- a/fs/smb/server/server.c +++ b/fs/smb/server/server.c @@ -167,20 +167,17 @@ static void __handle_ksmbd_work(struct ksmbd_work *work, int rc; bool is_chained = false; - if (conn->ops->allocate_rsp_buf(work)) - return; - if (conn->ops->is_transform_hdr && conn->ops->is_transform_hdr(work->request_buf)) { rc = conn->ops->decrypt_req(work); - if (rc < 0) { - conn->ops->set_rsp_status(work, STATUS_DATA_ERROR); - goto send; - } - + if (rc < 0) + return; work->encrypted = true; } + if (conn->ops->allocate_rsp_buf(work)) + return; + rc = conn->ops->init_rsp_hdr(work); if (rc) { /* either uid or tid is not correct */ -- cgit v1.2.3 From 17cf0c2794bdb6f39671265aa18aea5c22ee8c4a Mon Sep 17 00:00:00 2001 From: Namjae Jeon Date: Fri, 12 Apr 2024 09:45:00 +0900 Subject: ksmbd: validate request buffer size in smb2_allocate_rsp_buf() The response buffer should be allocated in smb2_allocate_rsp_buf before validating request. But the fields in payload as well as smb2 header is used in smb2_allocate_rsp_buf(). This patch add simple buffer size validation to avoid potencial out-of-bounds in request buffer. Cc: stable@vger.kernel.org Signed-off-by: Namjae Jeon Signed-off-by: Steve French --- fs/smb/server/smb2pdu.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/fs/smb/server/smb2pdu.c b/fs/smb/server/smb2pdu.c index 5723bbf372d7..ee4b2875a021 100644 --- a/fs/smb/server/smb2pdu.c +++ b/fs/smb/server/smb2pdu.c @@ -535,6 +535,10 @@ int smb2_allocate_rsp_buf(struct ksmbd_work *work) if (cmd == SMB2_QUERY_INFO_HE) { struct smb2_query_info_req *req; + if (get_rfc1002_len(work->request_buf) < + offsetof(struct smb2_query_info_req, OutputBufferLength)) + return -EINVAL; + req = smb2_get_msg(work->request_buf); if ((req->InfoType == SMB2_O_INFO_FILE && (req->FileInfoClass == FILE_FULL_EA_INFORMATION || -- cgit v1.2.3 From 4973b04d3ea577db80c501c5f14e68ec69fe1794 Mon Sep 17 00:00:00 2001 From: Marios Makassikis Date: Mon, 15 Apr 2024 15:12:48 +0200 Subject: ksmbd: clear RENAME_NOREPLACE before calling vfs_rename File overwrite case is explicitly handled, so it is not necessary to pass RENAME_NOREPLACE to vfs_rename. Clearing the flag fixes rename operations when the share is a ntfs-3g mount. The latter uses an older version of fuse with no support for flags in the ->rename op. Cc: stable@vger.kernel.org Signed-off-by: Marios Makassikis Acked-by: Namjae Jeon Signed-off-by: Steve French --- fs/smb/server/vfs.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/fs/smb/server/vfs.c b/fs/smb/server/vfs.c index 22f0f3db3ac9..51b1b0bed616 100644 --- a/fs/smb/server/vfs.c +++ b/fs/smb/server/vfs.c @@ -754,10 +754,15 @@ retry: goto out4; } + /* + * explicitly handle file overwrite case, for compatibility with + * filesystems that may not support rename flags (e.g: fuse) + */ if ((flags & RENAME_NOREPLACE) && d_is_positive(new_dentry)) { err = -EEXIST; goto out4; } + flags &= ~(RENAME_NOREPLACE); if (old_child == trap) { err = -EINVAL; -- cgit v1.2.3 From 0268a7cc7fdc47d90b6c18859de7718d5059f6f1 Mon Sep 17 00:00:00 2001 From: Namjae Jeon Date: Fri, 19 Apr 2024 23:46:34 +0900 Subject: ksmbd: common: use struct_group_attr instead of struct_group for network_open_info 4byte padding cause the connection issue with the applications of MacOS. smb2_close response size increases by 4 bytes by padding, And the smb client of MacOS check it and stop the connection. This patch use struct_group_attr instead of struct_group for network_open_info to use __packed to avoid padding. Fixes: 0015eb6e1238 ("smb: client, common: fix fortify warnings") Cc: stable@vger.kernel.org Signed-off-by: Namjae Jeon Signed-off-by: Steve French --- fs/smb/common/smb2pdu.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/smb/common/smb2pdu.h b/fs/smb/common/smb2pdu.h index 1b594307c9d5..202ff9128156 100644 --- a/fs/smb/common/smb2pdu.h +++ b/fs/smb/common/smb2pdu.h @@ -711,7 +711,7 @@ struct smb2_close_rsp { __le16 StructureSize; /* 60 */ __le16 Flags; __le32 Reserved; - struct_group(network_open_info, + struct_group_attr(network_open_info, __packed, __le64 CreationTime; __le64 LastAccessTime; __le64 LastWriteTime; -- cgit v1.2.3 From e9d8c2f95ab8acaf3f4d4a53682a4afa3c263692 Mon Sep 17 00:00:00 2001 From: Namjae Jeon Date: Sat, 20 Apr 2024 09:17:58 +0900 Subject: ksmbd: add continuous availability share parameter If capabilities of the share is not SMB2_SHARE_CAP_CONTINUOUS_AVAILABILITY, ksmbd should not grant a persistent handle to the client. This patch add continuous availability share parameter to control it. Signed-off-by: Namjae Jeon Signed-off-by: Steve French --- fs/smb/server/ksmbd_netlink.h | 35 ++++++++++++++++++----------------- fs/smb/server/smb2pdu.c | 11 +++++++++-- 2 files changed, 27 insertions(+), 19 deletions(-) diff --git a/fs/smb/server/ksmbd_netlink.h b/fs/smb/server/ksmbd_netlink.h index 686b321c5a8b..f4e55199938d 100644 --- a/fs/smb/server/ksmbd_netlink.h +++ b/fs/smb/server/ksmbd_netlink.h @@ -340,23 +340,24 @@ enum KSMBD_TREE_CONN_STATUS { /* * Share config flags. */ -#define KSMBD_SHARE_FLAG_INVALID (0) -#define KSMBD_SHARE_FLAG_AVAILABLE BIT(0) -#define KSMBD_SHARE_FLAG_BROWSEABLE BIT(1) -#define KSMBD_SHARE_FLAG_WRITEABLE BIT(2) -#define KSMBD_SHARE_FLAG_READONLY BIT(3) -#define KSMBD_SHARE_FLAG_GUEST_OK BIT(4) -#define KSMBD_SHARE_FLAG_GUEST_ONLY BIT(5) -#define KSMBD_SHARE_FLAG_STORE_DOS_ATTRS BIT(6) -#define KSMBD_SHARE_FLAG_OPLOCKS BIT(7) -#define KSMBD_SHARE_FLAG_PIPE BIT(8) -#define KSMBD_SHARE_FLAG_HIDE_DOT_FILES BIT(9) -#define KSMBD_SHARE_FLAG_INHERIT_OWNER BIT(10) -#define KSMBD_SHARE_FLAG_STREAMS BIT(11) -#define KSMBD_SHARE_FLAG_FOLLOW_SYMLINKS BIT(12) -#define KSMBD_SHARE_FLAG_ACL_XATTR BIT(13) -#define KSMBD_SHARE_FLAG_UPDATE BIT(14) -#define KSMBD_SHARE_FLAG_CROSSMNT BIT(15) +#define KSMBD_SHARE_FLAG_INVALID (0) +#define KSMBD_SHARE_FLAG_AVAILABLE BIT(0) +#define KSMBD_SHARE_FLAG_BROWSEABLE BIT(1) +#define KSMBD_SHARE_FLAG_WRITEABLE BIT(2) +#define KSMBD_SHARE_FLAG_READONLY BIT(3) +#define KSMBD_SHARE_FLAG_GUEST_OK BIT(4) +#define KSMBD_SHARE_FLAG_GUEST_ONLY BIT(5) +#define KSMBD_SHARE_FLAG_STORE_DOS_ATTRS BIT(6) +#define KSMBD_SHARE_FLAG_OPLOCKS BIT(7) +#define KSMBD_SHARE_FLAG_PIPE BIT(8) +#define KSMBD_SHARE_FLAG_HIDE_DOT_FILES BIT(9) +#define KSMBD_SHARE_FLAG_INHERIT_OWNER BIT(10) +#define KSMBD_SHARE_FLAG_STREAMS BIT(11) +#define KSMBD_SHARE_FLAG_FOLLOW_SYMLINKS BIT(12) +#define KSMBD_SHARE_FLAG_ACL_XATTR BIT(13) +#define KSMBD_SHARE_FLAG_UPDATE BIT(14) +#define KSMBD_SHARE_FLAG_CROSSMNT BIT(15) +#define KSMBD_SHARE_FLAG_CONTINUOUS_AVAILABILITY BIT(16) /* * Tree connect request flags. diff --git a/fs/smb/server/smb2pdu.c b/fs/smb/server/smb2pdu.c index ee4b2875a021..355824151c2d 100644 --- a/fs/smb/server/smb2pdu.c +++ b/fs/smb/server/smb2pdu.c @@ -1988,7 +1988,12 @@ int smb2_tree_connect(struct ksmbd_work *work) write_unlock(&sess->tree_conns_lock); rsp->StructureSize = cpu_to_le16(16); out_err1: - rsp->Capabilities = 0; + if (server_conf.flags & KSMBD_GLOBAL_FLAG_DURABLE_HANDLE && + test_share_config_flag(share, + KSMBD_SHARE_FLAG_CONTINUOUS_AVAILABILITY)) + rsp->Capabilities = SMB2_SHARE_CAP_CONTINUOUS_AVAILABILITY; + else + rsp->Capabilities = 0; rsp->Reserved = 0; /* default manual caching */ rsp->ShareFlags = SMB2_SHAREFLAG_MANUAL_CACHING; @@ -3502,7 +3507,9 @@ int smb2_open(struct ksmbd_work *work) memcpy(fp->client_guid, conn->ClientGUID, SMB2_CLIENT_GUID_SIZE); if (dh_info.type == DURABLE_REQ_V2 || dh_info.type == DURABLE_REQ) { - if (dh_info.type == DURABLE_REQ_V2 && dh_info.persistent) + if (dh_info.type == DURABLE_REQ_V2 && dh_info.persistent && + test_share_config_flag(work->tcon->share_conf, + KSMBD_SHARE_FLAG_CONTINUOUS_AVAILABILITY)) fp->is_persistent = true; else fp->is_durable = true; -- cgit v1.2.3 From 680d11f6e5427b6af1321932286722d24a8b16c1 Mon Sep 17 00:00:00 2001 From: Yick Xie Date: Fri, 19 Apr 2024 01:06:10 +0800 Subject: udp: preserve the connected status if only UDP cmsg If "udp_cmsg_send()" returned 0 (i.e. only UDP cmsg), "connected" should not be set to 0. Otherwise it stops the connected socket from using the cached route. Fixes: 2e8de8576343 ("udp: add gso segment cmsg") Signed-off-by: Yick Xie Cc: stable@vger.kernel.org Reviewed-by: Willem de Bruijn Link: https://lore.kernel.org/r/20240418170610.867084-1-yick.xie@gmail.com Signed-off-by: Jakub Kicinski --- net/ipv4/udp.c | 5 +++-- net/ipv6/udp.c | 5 +++-- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c index c02bf011d4a6..420905be5f30 100644 --- a/net/ipv4/udp.c +++ b/net/ipv4/udp.c @@ -1123,16 +1123,17 @@ int udp_sendmsg(struct sock *sk, struct msghdr *msg, size_t len) if (msg->msg_controllen) { err = udp_cmsg_send(sk, msg, &ipc.gso_size); - if (err > 0) + if (err > 0) { err = ip_cmsg_send(sk, msg, &ipc, sk->sk_family == AF_INET6); + connected = 0; + } if (unlikely(err < 0)) { kfree(ipc.opt); return err; } if (ipc.opt) free = 1; - connected = 0; } if (!ipc.opt) { struct ip_options_rcu *inet_opt; diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c index 8b1dd7f51249..1a4cccdd40c9 100644 --- a/net/ipv6/udp.c +++ b/net/ipv6/udp.c @@ -1474,9 +1474,11 @@ do_udp_sendmsg: ipc6.opt = opt; err = udp_cmsg_send(sk, msg, &ipc6.gso_size); - if (err > 0) + if (err > 0) { err = ip6_datagram_send_ctl(sock_net(sk), sk, msg, fl6, &ipc6); + connected = false; + } if (err < 0) { fl6_sock_release(flowlabel); return err; @@ -1488,7 +1490,6 @@ do_udp_sendmsg: } if (!(opt->opt_nflen|opt->opt_flen)) opt = NULL; - connected = false; } if (!opt) { opt = txopt_get(np); -- cgit v1.2.3 From 9f898fc2c31fbf0ac5ecd289f528a716464cb005 Mon Sep 17 00:00:00 2001 From: Justin Chen Date: Thu, 18 Apr 2024 11:05:41 -0700 Subject: net: bcmasp: fix memory leak when bringing down interface When bringing down the TX rings we flush the rings but forget to reclaimed the flushed packets. This leads to a memory leak since we do not free the dma mapped buffers. This also leads to tx control block corruption when bringing down the interface for power management. Fixes: 490cb412007d ("net: bcmasp: Add support for ASP2.0 Ethernet controller") Signed-off-by: Justin Chen Acked-by: Florian Fainelli Reviewed-by: Simon Horman Link: https://lore.kernel.org/r/20240418180541.2271719-1-justin.chen@broadcom.com Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/broadcom/asp2/bcmasp_intf.c | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/drivers/net/ethernet/broadcom/asp2/bcmasp_intf.c b/drivers/net/ethernet/broadcom/asp2/bcmasp_intf.c index 72ea97c5d5d4..82768b0e9026 100644 --- a/drivers/net/ethernet/broadcom/asp2/bcmasp_intf.c +++ b/drivers/net/ethernet/broadcom/asp2/bcmasp_intf.c @@ -436,10 +436,8 @@ static void umac_init(struct bcmasp_intf *intf) umac_wl(intf, 0x800, UMC_RX_MAX_PKT_SZ); } -static int bcmasp_tx_poll(struct napi_struct *napi, int budget) +static int bcmasp_tx_reclaim(struct bcmasp_intf *intf) { - struct bcmasp_intf *intf = - container_of(napi, struct bcmasp_intf, tx_napi); struct bcmasp_intf_stats64 *stats = &intf->stats64; struct device *kdev = &intf->parent->pdev->dev; unsigned long read, released = 0; @@ -482,10 +480,16 @@ static int bcmasp_tx_poll(struct napi_struct *napi, int budget) DESC_RING_COUNT); } - /* Ensure all descriptors have been written to DRAM for the hardware - * to see updated contents. - */ - wmb(); + return released; +} + +static int bcmasp_tx_poll(struct napi_struct *napi, int budget) +{ + struct bcmasp_intf *intf = + container_of(napi, struct bcmasp_intf, tx_napi); + int released = 0; + + released = bcmasp_tx_reclaim(intf); napi_complete(&intf->tx_napi); @@ -797,6 +801,7 @@ static void bcmasp_init_tx(struct bcmasp_intf *intf) intf->tx_spb_dma_read = intf->tx_spb_dma_addr; intf->tx_spb_index = 0; intf->tx_spb_clean_index = 0; + memset(intf->tx_cbs, 0, sizeof(struct bcmasp_tx_cb) * DESC_RING_COUNT); /* Make sure channels are disabled */ tx_spb_ctrl_wl(intf, 0x0, TX_SPB_CTRL_ENABLE); @@ -885,6 +890,8 @@ static void bcmasp_netif_deinit(struct net_device *dev) } while (timeout-- > 0); tx_spb_dma_wl(intf, 0x0, TX_SPB_DMA_FIFO_CTRL); + bcmasp_tx_reclaim(intf); + umac_enable_set(intf, UMC_CMD_TX_EN, 0); phy_stop(dev->phydev); -- cgit v1.2.3 From 976c44af48141cd8595601c0af2a19a43c5b228b Mon Sep 17 00:00:00 2001 From: Ido Schimmel Date: Thu, 18 Apr 2024 15:46:06 +0200 Subject: mlxsw: core: Unregister EMAD trap using FORWARD action The device's manual (PRM - Programmer's Reference Manual) classifies the trap that is used to deliver EMAD responses as an "event trap". Among other things, it means that the only actions that can be associated with the trap are TRAP and FORWARD (NOP). Currently, during driver de-initialization the driver unregisters the trap by setting its action to DISCARD, which violates the above guideline. Future firmware versions will prevent such misuses by returning an error. This does not prevent the driver from working, but an error will be printed to the kernel log during module removal / devlink reload: mlxsw_spectrum 0000:03:00.0: Reg cmd access status failed (status=7(bad parameter)) mlxsw_spectrum 0000:03:00.0: Reg cmd access failed (reg_id=7003(hpkt),type=write) Suppress the error message by aligning the driver to the manual and use a FORWARD (NOP) action when unregistering the trap. Fixes: 4ec14b7634b2 ("mlxsw: Add interface to access registers and process events") Cc: Jiri Pirko Cc: Amit Cohen Signed-off-by: Ido Schimmel Reviewed-by: Petr Machata Reviewed-by: Simon Horman Signed-off-by: Petr Machata Link: https://lore.kernel.org/r/753a89e14008fde08cb4a2c1e5f537b81d8eb2d6.1713446092.git.petrm@nvidia.com Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/mellanox/mlxsw/core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/ethernet/mellanox/mlxsw/core.c b/drivers/net/ethernet/mellanox/mlxsw/core.c index e4d7739bd7c8..4a79c0d7e7ad 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/core.c +++ b/drivers/net/ethernet/mellanox/mlxsw/core.c @@ -849,7 +849,7 @@ free_skb: static const struct mlxsw_listener mlxsw_emad_rx_listener = MLXSW_RXL(mlxsw_emad_rx_listener_func, ETHEMAD, TRAP_TO_CPU, false, - EMAD, DISCARD); + EMAD, FORWARD); static int mlxsw_emad_tlv_enable(struct mlxsw_core *mlxsw_core) { -- cgit v1.2.3 From 7e2050a8366315aeaf0316b3d362e67cf58f3ea8 Mon Sep 17 00:00:00 2001 From: Ido Schimmel Date: Thu, 18 Apr 2024 15:46:07 +0200 Subject: mlxsw: core_env: Fix driver initialization with old firmware The driver queries the Management Capabilities Mask (MCAM) register during initialization to understand if it can read up to 128 bytes from transceiver modules. However, not all firmware versions support this register, leading to the driver failing to load. Fix by treating an error in the register query as an indication that the feature is not supported. Fixes: 1f4aea1f72da ("mlxsw: core_env: Read transceiver module EEPROM in 128 bytes chunks") Reported-by: Tim 'mithro' Ansell Signed-off-by: Ido Schimmel Reviewed-by: Petr Machata Signed-off-by: Petr Machata Reviewed-by: Simon Horman Link: https://lore.kernel.org/r/0afa8b2e8bac178f5f88211344429176dcc72281.1713446092.git.petrm@nvidia.com Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/mellanox/mlxsw/core_env.c | 20 ++++++-------------- 1 file changed, 6 insertions(+), 14 deletions(-) diff --git a/drivers/net/ethernet/mellanox/mlxsw/core_env.c b/drivers/net/ethernet/mellanox/mlxsw/core_env.c index 53b150b7ae4e..6c06b0592760 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/core_env.c +++ b/drivers/net/ethernet/mellanox/mlxsw/core_env.c @@ -1357,24 +1357,20 @@ static struct mlxsw_linecards_event_ops mlxsw_env_event_ops = { .got_inactive = mlxsw_env_got_inactive, }; -static int mlxsw_env_max_module_eeprom_len_query(struct mlxsw_env *mlxsw_env) +static void mlxsw_env_max_module_eeprom_len_query(struct mlxsw_env *mlxsw_env) { char mcam_pl[MLXSW_REG_MCAM_LEN]; - bool mcia_128b_supported; + bool mcia_128b_supported = false; int err; mlxsw_reg_mcam_pack(mcam_pl, MLXSW_REG_MCAM_FEATURE_GROUP_ENHANCED_FEATURES); err = mlxsw_reg_query(mlxsw_env->core, MLXSW_REG(mcam), mcam_pl); - if (err) - return err; - - mlxsw_reg_mcam_unpack(mcam_pl, MLXSW_REG_MCAM_MCIA_128B, - &mcia_128b_supported); + if (!err) + mlxsw_reg_mcam_unpack(mcam_pl, MLXSW_REG_MCAM_MCIA_128B, + &mcia_128b_supported); mlxsw_env->max_eeprom_len = mcia_128b_supported ? 128 : 48; - - return 0; } int mlxsw_env_init(struct mlxsw_core *mlxsw_core, @@ -1445,15 +1441,11 @@ int mlxsw_env_init(struct mlxsw_core *mlxsw_core, if (err) goto err_type_set; - err = mlxsw_env_max_module_eeprom_len_query(env); - if (err) - goto err_eeprom_len_query; - + mlxsw_env_max_module_eeprom_len_query(env); env->line_cards[0]->active = true; return 0; -err_eeprom_len_query: err_type_set: mlxsw_env_module_event_disable(env, 0); err_mlxsw_env_module_event_enable: -- cgit v1.2.3 From 773501d01e6bc3f2557882a25679392d982d5f3e Mon Sep 17 00:00:00 2001 From: Ido Schimmel Date: Thu, 18 Apr 2024 15:46:08 +0200 Subject: mlxsw: pci: Fix driver initialization with old firmware The driver queries the Management Capabilities Mask (MCAM) register during initialization to understand if a new and deeper reset flow is supported. However, not all firmware versions support this register, leading to the driver failing to load. Fix by treating an error in the register query as an indication that the feature is not supported. Fixes: f257c73e5356 ("mlxsw: pci: Add support for new reset flow") Reported-by: Tim 'mithro' Ansell Signed-off-by: Ido Schimmel Reviewed-by: Petr Machata Reviewed-by: Simon Horman Reviewed-by: Kalesh AP Signed-off-by: Petr Machata Link: https://lore.kernel.org/r/ee968c49d53bac96a4c66d1b09ebbd097d81aca5.1713446092.git.petrm@nvidia.com Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/mellanox/mlxsw/pci.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/drivers/net/ethernet/mellanox/mlxsw/pci.c b/drivers/net/ethernet/mellanox/mlxsw/pci.c index af99bf17eb36..f42a1b1c9368 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/pci.c +++ b/drivers/net/ethernet/mellanox/mlxsw/pci.c @@ -1530,7 +1530,7 @@ mlxsw_pci_reset(struct mlxsw_pci *mlxsw_pci, const struct pci_device_id *id) { struct pci_dev *pdev = mlxsw_pci->pdev; char mcam_pl[MLXSW_REG_MCAM_LEN]; - bool pci_reset_supported; + bool pci_reset_supported = false; u32 sys_status; int err; @@ -1548,11 +1548,9 @@ mlxsw_pci_reset(struct mlxsw_pci *mlxsw_pci, const struct pci_device_id *id) mlxsw_reg_mcam_pack(mcam_pl, MLXSW_REG_MCAM_FEATURE_GROUP_ENHANCED_FEATURES); err = mlxsw_reg_query(mlxsw_pci->core, MLXSW_REG(mcam), mcam_pl); - if (err) - return err; - - mlxsw_reg_mcam_unpack(mcam_pl, MLXSW_REG_MCAM_PCI_RESET, - &pci_reset_supported); + if (!err) + mlxsw_reg_mcam_unpack(mcam_pl, MLXSW_REG_MCAM_PCI_RESET, + &pci_reset_supported); if (pci_reset_supported) { pci_dbg(pdev, "Starting PCI reset flow\n"); -- cgit v1.2.3 From fcdbc1d7a4b638e5d5668de461f320386f3002aa Mon Sep 17 00:00:00 2001 From: Kent Overstreet Date: Wed, 17 Apr 2024 15:19:50 -0400 Subject: bcachefs: Check for journal entries overruning end of sb clean section Fix a missing bounds check in superblock validation. Note that we don't yet have repair code for this case - repair code for individual items is generally low priority, since the whole superblock is checksummed, validated prior to write, and we have backups. Reported-by: lei lu Signed-off-by: Kent Overstreet --- fs/bcachefs/sb-clean.c | 8 ++++++++ fs/bcachefs/sb-errors_types.h | 3 ++- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/fs/bcachefs/sb-clean.c b/fs/bcachefs/sb-clean.c index 5980ba2563fe..35ca3f138de6 100644 --- a/fs/bcachefs/sb-clean.c +++ b/fs/bcachefs/sb-clean.c @@ -29,6 +29,14 @@ int bch2_sb_clean_validate_late(struct bch_fs *c, struct bch_sb_field_clean *cle for (entry = clean->start; entry < (struct jset_entry *) vstruct_end(&clean->field); entry = vstruct_next(entry)) { + if (vstruct_end(entry) > vstruct_end(&clean->field)) { + bch_err(c, "journal entry (u64s %u) overran end of superblock clean section (u64s %u) by %zu", + le16_to_cpu(entry->u64s), le32_to_cpu(clean->field.u64s), + (u64 *) vstruct_end(entry) - (u64 *) vstruct_end(&clean->field)); + bch2_sb_error_count(c, BCH_FSCK_ERR_sb_clean_entry_overrun); + return -BCH_ERR_fsck_repair_unimplemented; + } + ret = bch2_journal_entry_validate(c, NULL, entry, le16_to_cpu(c->disk_sb.sb->version), BCH_SB_BIG_ENDIAN(c->disk_sb.sb), diff --git a/fs/bcachefs/sb-errors_types.h b/fs/bcachefs/sb-errors_types.h index 4ca6e7b0d8aa..06c7a644f4a4 100644 --- a/fs/bcachefs/sb-errors_types.h +++ b/fs/bcachefs/sb-errors_types.h @@ -271,7 +271,8 @@ x(btree_root_unreadable_and_scan_found_nothing, 263) \ x(snapshot_node_missing, 264) \ x(dup_backpointer_to_bad_csum_extent, 265) \ - x(btree_bitmap_not_marked, 266) + x(btree_bitmap_not_marked, 266) \ + x(sb_clean_entry_overrun, 267) enum bch_sb_error_id { #define x(t, n) BCH_FSCK_ERR_##t = n, -- cgit v1.2.3 From ec438ac59d7a8bd7e76d3e1201d55071be484626 Mon Sep 17 00:00:00 2001 From: Kent Overstreet Date: Sat, 20 Apr 2024 00:31:32 -0400 Subject: bcachefs: Fix missing call to bch2_fs_allocator_background_exit() Signed-off-by: Kent Overstreet --- fs/bcachefs/super.c | 1 + 1 file changed, 1 insertion(+) diff --git a/fs/bcachefs/super.c b/fs/bcachefs/super.c index 8daf80a38d60..88e214c609bb 100644 --- a/fs/bcachefs/super.c +++ b/fs/bcachefs/super.c @@ -544,6 +544,7 @@ static void __bch2_fs_free(struct bch_fs *c) bch2_find_btree_nodes_exit(&c->found_btree_nodes); bch2_free_pending_node_rewrites(c); + bch2_fs_allocator_background_exit(c); bch2_fs_sb_errors_exit(c); bch2_fs_counters_exit(c); bch2_fs_snapshots_exit(c); -- cgit v1.2.3 From 366c5cec9ce473f68925d703a07cac56e1d16956 Mon Sep 17 00:00:00 2001 From: James Bottomley Date: Sat, 20 Apr 2024 08:34:09 -0400 Subject: MAINTAINERS: update to working email address jejb@linux.ibm.com no longer works. Signed-off-by: James Bottomley --- MAINTAINERS | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/MAINTAINERS b/MAINTAINERS index c23fda1aa1f0..e5121ff5e60e 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -11995,7 +11995,7 @@ F: include/keys/encrypted-type.h F: security/keys/encrypted-keys/ KEYS-TRUSTED -M: James Bottomley +M: James Bottomley M: Jarkko Sakkinen M: Mimi Zohar L: linux-integrity@vger.kernel.org @@ -19669,7 +19669,7 @@ F: drivers/scsi/sg.c F: include/scsi/sg.h SCSI SUBSYSTEM -M: "James E.J. Bottomley" +M: "James E.J. Bottomley" M: "Martin K. Petersen" L: linux-scsi@vger.kernel.org S: Maintained -- cgit v1.2.3 From 32cf5a4eda464d76d553ee3f1b06c4d33d796c52 Mon Sep 17 00:00:00 2001 From: Chuck Lever Date: Fri, 19 Apr 2024 11:51:12 -0400 Subject: Revert "svcrdma: Add Write chunk WRs to the RPC's Send WR chain" Performance regression reported with NFS/RDMA using Omnipath, bisected to commit e084ee673c77 ("svcrdma: Add Write chunk WRs to the RPC's Send WR chain"). Tracing on the server reports: nfsd-7771 [060] 1758.891809: svcrdma_sq_post_err: cq.id=205 cid=226 sc_sq_avail=13643/851 status=-12 sq_post_err reports ENOMEM, and the rdma->sc_sq_avail (13643) is larger than rdma->sc_sq_depth (851). The number of available Send Queue entries is always supposed to be smaller than the Send Queue depth. That seems like a Send Queue accounting bug in svcrdma. As it's getting to be late in the 6.9-rc cycle, revert this commit. It can be revisited in a subsequent kernel release. Link: https://bugzilla.kernel.org/show_bug.cgi?id=218743 Fixes: e084ee673c77 ("svcrdma: Add Write chunk WRs to the RPC's Send WR chain") Signed-off-by: Chuck Lever --- include/linux/sunrpc/svc_rdma.h | 13 ++---- net/sunrpc/xprtrdma/svc_rdma_rw.c | 86 +++++++++-------------------------- net/sunrpc/xprtrdma/svc_rdma_sendto.c | 5 +- 3 files changed, 26 insertions(+), 78 deletions(-) diff --git a/include/linux/sunrpc/svc_rdma.h b/include/linux/sunrpc/svc_rdma.h index 24cd199dd6f3..d33bab33099a 100644 --- a/include/linux/sunrpc/svc_rdma.h +++ b/include/linux/sunrpc/svc_rdma.h @@ -210,7 +210,6 @@ struct svc_rdma_recv_ctxt { */ struct svc_rdma_write_info { struct svcxprt_rdma *wi_rdma; - struct list_head wi_list; const struct svc_rdma_chunk *wi_chunk; @@ -239,10 +238,7 @@ struct svc_rdma_send_ctxt { struct ib_cqe sc_cqe; struct xdr_buf sc_hdrbuf; struct xdr_stream sc_stream; - - struct list_head sc_write_info_list; struct svc_rdma_write_info sc_reply_info; - void *sc_xprt_buf; int sc_page_count; int sc_cur_sge_no; @@ -274,14 +270,11 @@ extern void svc_rdma_cc_init(struct svcxprt_rdma *rdma, extern void svc_rdma_cc_release(struct svcxprt_rdma *rdma, struct svc_rdma_chunk_ctxt *cc, enum dma_data_direction dir); -extern void svc_rdma_write_chunk_release(struct svcxprt_rdma *rdma, - struct svc_rdma_send_ctxt *ctxt); extern void svc_rdma_reply_chunk_release(struct svcxprt_rdma *rdma, struct svc_rdma_send_ctxt *ctxt); -extern int svc_rdma_prepare_write_list(struct svcxprt_rdma *rdma, - const struct svc_rdma_pcl *write_pcl, - struct svc_rdma_send_ctxt *sctxt, - const struct xdr_buf *xdr); +extern int svc_rdma_send_write_list(struct svcxprt_rdma *rdma, + const struct svc_rdma_recv_ctxt *rctxt, + const struct xdr_buf *xdr); extern int svc_rdma_prepare_reply_chunk(struct svcxprt_rdma *rdma, const struct svc_rdma_pcl *write_pcl, const struct svc_rdma_pcl *reply_pcl, diff --git a/net/sunrpc/xprtrdma/svc_rdma_rw.c b/net/sunrpc/xprtrdma/svc_rdma_rw.c index f2a100c4c81f..40797114d50a 100644 --- a/net/sunrpc/xprtrdma/svc_rdma_rw.c +++ b/net/sunrpc/xprtrdma/svc_rdma_rw.c @@ -230,28 +230,6 @@ static void svc_rdma_write_info_free(struct svc_rdma_write_info *info) queue_work(svcrdma_wq, &info->wi_work); } -/** - * svc_rdma_write_chunk_release - Release Write chunk I/O resources - * @rdma: controlling transport - * @ctxt: Send context that is being released - */ -void svc_rdma_write_chunk_release(struct svcxprt_rdma *rdma, - struct svc_rdma_send_ctxt *ctxt) -{ - struct svc_rdma_write_info *info; - struct svc_rdma_chunk_ctxt *cc; - - while (!list_empty(&ctxt->sc_write_info_list)) { - info = list_first_entry(&ctxt->sc_write_info_list, - struct svc_rdma_write_info, wi_list); - list_del(&info->wi_list); - - cc = &info->wi_cc; - svc_rdma_wake_send_waiters(rdma, cc->cc_sqecount); - svc_rdma_write_info_free(info); - } -} - /** * svc_rdma_reply_chunk_release - Release Reply chunk I/O resources * @rdma: controlling transport @@ -308,11 +286,13 @@ static void svc_rdma_write_done(struct ib_cq *cq, struct ib_wc *wc) struct ib_cqe *cqe = wc->wr_cqe; struct svc_rdma_chunk_ctxt *cc = container_of(cqe, struct svc_rdma_chunk_ctxt, cc_cqe); + struct svc_rdma_write_info *info = + container_of(cc, struct svc_rdma_write_info, wi_cc); switch (wc->status) { case IB_WC_SUCCESS: trace_svcrdma_wc_write(&cc->cc_cid); - return; + break; case IB_WC_WR_FLUSH_ERR: trace_svcrdma_wc_write_flush(wc, &cc->cc_cid); break; @@ -320,11 +300,12 @@ static void svc_rdma_write_done(struct ib_cq *cq, struct ib_wc *wc) trace_svcrdma_wc_write_err(wc, &cc->cc_cid); } - /* The RDMA Write has flushed, so the client won't get - * some of the outgoing RPC message. Signal the loss - * to the client by closing the connection. - */ - svc_xprt_deferred_close(&rdma->sc_xprt); + svc_rdma_wake_send_waiters(rdma, cc->cc_sqecount); + + if (unlikely(wc->status != IB_WC_SUCCESS)) + svc_xprt_deferred_close(&rdma->sc_xprt); + + svc_rdma_write_info_free(info); } /** @@ -620,19 +601,13 @@ static int svc_rdma_xb_write(const struct xdr_buf *xdr, void *data) return xdr->len; } -/* Link Write WRs for @chunk onto @sctxt's WR chain. - */ -static int svc_rdma_prepare_write_chunk(struct svcxprt_rdma *rdma, - struct svc_rdma_send_ctxt *sctxt, - const struct svc_rdma_chunk *chunk, - const struct xdr_buf *xdr) +static int svc_rdma_send_write_chunk(struct svcxprt_rdma *rdma, + const struct svc_rdma_chunk *chunk, + const struct xdr_buf *xdr) { struct svc_rdma_write_info *info; struct svc_rdma_chunk_ctxt *cc; - struct ib_send_wr *first_wr; struct xdr_buf payload; - struct list_head *pos; - struct ib_cqe *cqe; int ret; if (xdr_buf_subsegment(xdr, &payload, chunk->ch_position, @@ -648,25 +623,10 @@ static int svc_rdma_prepare_write_chunk(struct svcxprt_rdma *rdma, if (ret != payload.len) goto out_err; - ret = -EINVAL; - if (unlikely(cc->cc_sqecount > rdma->sc_sq_depth)) - goto out_err; - - first_wr = sctxt->sc_wr_chain; - cqe = &cc->cc_cqe; - list_for_each(pos, &cc->cc_rwctxts) { - struct svc_rdma_rw_ctxt *rwc; - - rwc = list_entry(pos, struct svc_rdma_rw_ctxt, rw_list); - first_wr = rdma_rw_ctx_wrs(&rwc->rw_ctx, rdma->sc_qp, - rdma->sc_port_num, cqe, first_wr); - cqe = NULL; - } - sctxt->sc_wr_chain = first_wr; - sctxt->sc_sqecount += cc->cc_sqecount; - list_add(&info->wi_list, &sctxt->sc_write_info_list); - trace_svcrdma_post_write_chunk(&cc->cc_cid, cc->cc_sqecount); + ret = svc_rdma_post_chunk_ctxt(rdma, cc); + if (ret < 0) + goto out_err; return 0; out_err: @@ -675,27 +635,25 @@ out_err: } /** - * svc_rdma_prepare_write_list - Construct WR chain for sending Write list + * svc_rdma_send_write_list - Send all chunks on the Write list * @rdma: controlling RDMA transport - * @write_pcl: Write list provisioned by the client - * @sctxt: Send WR resources + * @rctxt: Write list provisioned by the client * @xdr: xdr_buf containing an RPC Reply message * * Returns zero on success, or a negative errno if one or more * Write chunks could not be sent. */ -int svc_rdma_prepare_write_list(struct svcxprt_rdma *rdma, - const struct svc_rdma_pcl *write_pcl, - struct svc_rdma_send_ctxt *sctxt, - const struct xdr_buf *xdr) +int svc_rdma_send_write_list(struct svcxprt_rdma *rdma, + const struct svc_rdma_recv_ctxt *rctxt, + const struct xdr_buf *xdr) { struct svc_rdma_chunk *chunk; int ret; - pcl_for_each_chunk(chunk, write_pcl) { + pcl_for_each_chunk(chunk, &rctxt->rc_write_pcl) { if (!chunk->ch_payload_length) break; - ret = svc_rdma_prepare_write_chunk(rdma, sctxt, chunk, xdr); + ret = svc_rdma_send_write_chunk(rdma, chunk, xdr); if (ret < 0) return ret; } diff --git a/net/sunrpc/xprtrdma/svc_rdma_sendto.c b/net/sunrpc/xprtrdma/svc_rdma_sendto.c index dfca39abd16c..bb5436b719e0 100644 --- a/net/sunrpc/xprtrdma/svc_rdma_sendto.c +++ b/net/sunrpc/xprtrdma/svc_rdma_sendto.c @@ -142,7 +142,6 @@ svc_rdma_send_ctxt_alloc(struct svcxprt_rdma *rdma) ctxt->sc_send_wr.sg_list = ctxt->sc_sges; ctxt->sc_send_wr.send_flags = IB_SEND_SIGNALED; ctxt->sc_cqe.done = svc_rdma_wc_send; - INIT_LIST_HEAD(&ctxt->sc_write_info_list); ctxt->sc_xprt_buf = buffer; xdr_buf_init(&ctxt->sc_hdrbuf, ctxt->sc_xprt_buf, rdma->sc_max_req_size); @@ -228,7 +227,6 @@ static void svc_rdma_send_ctxt_release(struct svcxprt_rdma *rdma, struct ib_device *device = rdma->sc_cm_id->device; unsigned int i; - svc_rdma_write_chunk_release(rdma, ctxt); svc_rdma_reply_chunk_release(rdma, ctxt); if (ctxt->sc_page_count) @@ -1015,8 +1013,7 @@ int svc_rdma_sendto(struct svc_rqst *rqstp) if (!p) goto put_ctxt; - ret = svc_rdma_prepare_write_list(rdma, &rctxt->rc_write_pcl, sctxt, - &rqstp->rq_res); + ret = svc_rdma_send_write_list(rdma, rctxt, &rqstp->rq_res); if (ret < 0) goto put_ctxt; -- cgit v1.2.3 From 6e4d9bd110e293513c3c2a3ff2dfa0a0735699e0 Mon Sep 17 00:00:00 2001 From: Kent Overstreet Date: Sat, 20 Apr 2024 15:13:20 -0400 Subject: bcachefs: bkey_cached.btree_trans_barrier_seq needs to be a ulong this stores the SRCU sequence number, which we use to check if an SRCU barrier has elapsed; this is a partial fix for the key cache shrinker not actually freeing. Signed-off-by: Kent Overstreet --- fs/bcachefs/btree_types.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/bcachefs/btree_types.h b/fs/bcachefs/btree_types.h index e0c982a4195c..c69b233c41bb 100644 --- a/fs/bcachefs/btree_types.h +++ b/fs/bcachefs/btree_types.h @@ -321,9 +321,9 @@ struct bkey_cached { struct btree_bkey_cached_common c; unsigned long flags; + unsigned long btree_trans_barrier_seq; u16 u64s; bool valid; - u32 btree_trans_barrier_seq; struct bkey_cached_key key; struct rhash_head hash; -- cgit v1.2.3 From adfe9357c39e251ffe22ceaa1edb4b7662ed76e6 Mon Sep 17 00:00:00 2001 From: Kent Overstreet Date: Sat, 20 Apr 2024 15:35:40 -0400 Subject: bcachefs: Tweak btree key cache shrinker so it actually frees Freeing key cache items is a multi stage process; we need to wait for an SRCU grace period to elapse, and we handle this ourselves - partially to avoid callback overhead, but primarily so that when allocating we can first allocate from the freed items waiting for an SRCU grace period. Previously, the shrinker was counting the items on the 'waiting for SRCU grace period' lists as items being scanned, but this meant that too many items waiting for an SRCU grace period could prevent it from doing any work at all. After this, we're seeing that items skipped due to the accessed bit are the main cause of the shrinker not making any progress, and we actually want the key cache shrinker to run quite aggressively because reclaimed items will still generally be found (more compactly) in the btree node cache - so we also tweak the shrinker to not count those against nr_to_scan. Signed-off-by: Kent Overstreet --- fs/bcachefs/btree_key_cache.c | 19 ++++--------------- 1 file changed, 4 insertions(+), 15 deletions(-) diff --git a/fs/bcachefs/btree_key_cache.c b/fs/bcachefs/btree_key_cache.c index 88a3582a3275..e8c1c530cd95 100644 --- a/fs/bcachefs/btree_key_cache.c +++ b/fs/bcachefs/btree_key_cache.c @@ -842,8 +842,6 @@ static unsigned long bch2_btree_key_cache_scan(struct shrinker *shrink, * Newest freed entries are at the end of the list - once we hit one * that's too new to be freed, we can bail out: */ - scanned += bc->nr_freed_nonpcpu; - list_for_each_entry_safe(ck, t, &bc->freed_nonpcpu, list) { if (!poll_state_synchronize_srcu(&c->btree_trans_barrier, ck->btree_trans_barrier_seq)) @@ -857,11 +855,6 @@ static unsigned long bch2_btree_key_cache_scan(struct shrinker *shrink, bc->nr_freed_nonpcpu--; } - if (scanned >= nr) - goto out; - - scanned += bc->nr_freed_pcpu; - list_for_each_entry_safe(ck, t, &bc->freed_pcpu, list) { if (!poll_state_synchronize_srcu(&c->btree_trans_barrier, ck->btree_trans_barrier_seq)) @@ -875,9 +868,6 @@ static unsigned long bch2_btree_key_cache_scan(struct shrinker *shrink, bc->nr_freed_pcpu--; } - if (scanned >= nr) - goto out; - rcu_read_lock(); tbl = rht_dereference_rcu(bc->table.tbl, &bc->table); if (bc->shrink_iter >= tbl->size) @@ -893,12 +883,12 @@ static unsigned long bch2_btree_key_cache_scan(struct shrinker *shrink, next = rht_dereference_bucket_rcu(pos->next, tbl, bc->shrink_iter); ck = container_of(pos, struct bkey_cached, hash); - if (test_bit(BKEY_CACHED_DIRTY, &ck->flags)) + if (test_bit(BKEY_CACHED_DIRTY, &ck->flags)) { goto next; - - if (test_bit(BKEY_CACHED_ACCESSED, &ck->flags)) + } else if (test_bit(BKEY_CACHED_ACCESSED, &ck->flags)) { clear_bit(BKEY_CACHED_ACCESSED, &ck->flags); - else if (bkey_cached_lock_for_evict(ck)) { + goto next; + } else if (bkey_cached_lock_for_evict(ck)) { bkey_cached_evict(bc, ck); bkey_cached_free(bc, ck); } @@ -916,7 +906,6 @@ next: } while (scanned < nr && bc->shrink_iter != start); rcu_read_unlock(); -out: memalloc_nofs_restore(flags); srcu_read_unlock(&c->btree_trans_barrier, srcu_idx); mutex_unlock(&bc->lock); -- cgit v1.2.3 From 467d2528d64e8fcf784850ac94f665efae2af149 Mon Sep 17 00:00:00 2001 From: Seven Lee Date: Mon, 15 Apr 2024 15:06:47 +0800 Subject: ASoC: dt-bindings: nau8821: Add delay control for ADC Change the original fixed delay to the assignment from the property. It will make it more flexible to different platforms to avoid pop noise at the beginning of recording. Signed-off-by: Seven Lee Reviewed-by: Rob Herring (Arm) Link: https://lore.kernel.org/r/20240415070649.3496487-2-wtli@nuvoton.com Signed-off-by: Mark Brown --- Documentation/devicetree/bindings/sound/nuvoton,nau8821.yaml | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/Documentation/devicetree/bindings/sound/nuvoton,nau8821.yaml b/Documentation/devicetree/bindings/sound/nuvoton,nau8821.yaml index 054b53954ac3..9f44168efb3e 100644 --- a/Documentation/devicetree/bindings/sound/nuvoton,nau8821.yaml +++ b/Documentation/devicetree/bindings/sound/nuvoton,nau8821.yaml @@ -103,6 +103,12 @@ properties: just limited to the left adc for design demand. type: boolean + nuvoton,adc-delay-ms: + description: Delay (in ms) to make input path stable and avoid pop noise. + minimum: 125 + maximum: 500 + default: 125 + '#sound-dai-cells': const: 0 @@ -136,6 +142,7 @@ examples: nuvoton,jack-eject-debounce = <0>; nuvoton,dmic-clk-threshold = <3072000>; nuvoton,dmic-slew-rate = <0>; + nuvoton,adc-delay-ms = <125>; #sound-dai-cells = <0>; }; }; -- cgit v1.2.3 From b37fdd42c00904afa11d9a8eb80e098429b894b3 Mon Sep 17 00:00:00 2001 From: Seven Lee Date: Mon, 15 Apr 2024 15:06:48 +0800 Subject: ASoC: nau8821: Add delay control for ADC Change the original fixed delay to the assignment from the property. It will make it more flexible to different platforms to avoid pop noise at the beginning of recording. Signed-off-by: Seven Lee Link: https://lore.kernel.org/r/20240415070649.3496487-3-wtli@nuvoton.com Signed-off-by: Mark Brown --- sound/soc/codecs/nau8821.c | 11 +++++++++-- sound/soc/codecs/nau8821.h | 1 + 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/sound/soc/codecs/nau8821.c b/sound/soc/codecs/nau8821.c index 012e347e6391..fec669e00a10 100644 --- a/sound/soc/codecs/nau8821.c +++ b/sound/soc/codecs/nau8821.c @@ -511,7 +511,7 @@ static int nau8821_left_adc_event(struct snd_soc_dapm_widget *w, switch (event) { case SND_SOC_DAPM_POST_PMU: - msleep(125); + msleep(nau8821->adc_delay); regmap_update_bits(nau8821->regmap, NAU8821_R01_ENA_CTRL, NAU8821_EN_ADCL, NAU8821_EN_ADCL); break; @@ -535,7 +535,7 @@ static int nau8821_right_adc_event(struct snd_soc_dapm_widget *w, switch (event) { case SND_SOC_DAPM_POST_PMU: - msleep(125); + msleep(nau8821->adc_delay); regmap_update_bits(nau8821->regmap, NAU8821_R01_ENA_CTRL, NAU8821_EN_ADCR, NAU8821_EN_ADCR); break; @@ -1697,6 +1697,7 @@ static void nau8821_print_device_properties(struct nau8821 *nau8821) dev_dbg(dev, "dmic-clk-threshold: %d\n", nau8821->dmic_clk_threshold); dev_dbg(dev, "key_enable: %d\n", nau8821->key_enable); + dev_dbg(dev, "adc-delay-ms: %d\n", nau8821->adc_delay); } static int nau8821_read_device_properties(struct device *dev, @@ -1742,6 +1743,12 @@ static int nau8821_read_device_properties(struct device *dev, &nau8821->dmic_slew_rate); if (ret) nau8821->dmic_slew_rate = 0; + ret = device_property_read_u32(dev, "nuvoton,adc-delay-ms", + &nau8821->adc_delay); + if (ret) + nau8821->adc_delay = 125; + if (nau8821->adc_delay < 125 || nau8821->adc_delay > 500) + dev_warn(dev, "Please set the suitable delay time!\n"); return 0; } diff --git a/sound/soc/codecs/nau8821.h b/sound/soc/codecs/nau8821.h index 62eaad130b2e..f0935ffafcbe 100644 --- a/sound/soc/codecs/nau8821.h +++ b/sound/soc/codecs/nau8821.h @@ -577,6 +577,7 @@ struct nau8821 { int dmic_clk_threshold; int dmic_slew_rate; int key_enable; + int adc_delay; }; int nau8821_enable_jack_detect(struct snd_soc_component *component, -- cgit v1.2.3 From ad8ba241bc93536a2c8af150b237c5be8fafe942 Mon Sep 17 00:00:00 2001 From: Seven Lee Date: Mon, 15 Apr 2024 15:06:49 +0800 Subject: ASoC: nau8821: Remove redundant ADC controls Remove redundant left/right adc channel enable controls. Signed-off-by: Seven Lee Link: https://lore.kernel.org/r/20240415070649.3496487-4-wtli@nuvoton.com Signed-off-by: Mark Brown --- sound/soc/codecs/nau8821.c | 8 -------- 1 file changed, 8 deletions(-) diff --git a/sound/soc/codecs/nau8821.c b/sound/soc/codecs/nau8821.c index fec669e00a10..6818bbd1d3c7 100644 --- a/sound/soc/codecs/nau8821.c +++ b/sound/soc/codecs/nau8821.c @@ -512,12 +512,8 @@ static int nau8821_left_adc_event(struct snd_soc_dapm_widget *w, switch (event) { case SND_SOC_DAPM_POST_PMU: msleep(nau8821->adc_delay); - regmap_update_bits(nau8821->regmap, NAU8821_R01_ENA_CTRL, - NAU8821_EN_ADCL, NAU8821_EN_ADCL); break; case SND_SOC_DAPM_POST_PMD: - regmap_update_bits(nau8821->regmap, - NAU8821_R01_ENA_CTRL, NAU8821_EN_ADCL, 0); break; default: return -EINVAL; @@ -536,12 +532,8 @@ static int nau8821_right_adc_event(struct snd_soc_dapm_widget *w, switch (event) { case SND_SOC_DAPM_POST_PMU: msleep(nau8821->adc_delay); - regmap_update_bits(nau8821->regmap, NAU8821_R01_ENA_CTRL, - NAU8821_EN_ADCR, NAU8821_EN_ADCR); break; case SND_SOC_DAPM_POST_PMD: - regmap_update_bits(nau8821->regmap, - NAU8821_R01_ENA_CTRL, NAU8821_EN_ADCR, 0); break; default: return -EINVAL; -- cgit v1.2.3 From cbd9eed87107bb6d6e537e79aeea65399898ca41 Mon Sep 17 00:00:00 2001 From: Luca Ceresoli Date: Tue, 16 Apr 2024 08:00:24 +0200 Subject: ASoC: dapm: debugfs: add component to route lines debugfs entries for DAPM widgets have the following form: Left ADC: Off in 1 out 0 - R2(0x2) mask 0x2 stream Left HiFi Capture inactive out "static" "Capture" in "static" "Left PGA" Lines with the "in" and "out" prefixes describe routes from/to other widgets presenting the path name and the connected widget name. This is ambiguous in case of cards having multiple widgets with the same name in different components. For example the STM32MP157A-DK1 board (arch/arm/boot/dts/st/stm32mp15xx-dkx.dtsi) has a "Capture" widget in both the "cs42l51.0-004a" and the "hdmi-audio-codec.1.auto" components. Avoid the ambiguity by adding the component name to the "in" and "out" lines. Add the new field at the end to minimize backward compatibility issues. The existing vizdapm tool continues working after this change. The output becomes: Left ADC: Off in 1 out 0 - R2(0x2) mask 0x2 stream Left HiFi Capture inactive out "static" "Capture" "cs42l51.0-004a" in "static" "Left PGA" "cs42l51.0-004a" Signed-off-by: Luca Ceresoli Reviewed-by: Alexandre Belloni Link: https://lore.kernel.org/r/20240416-vizdapm-ng-v1-1-5d33c0b57bc5@bootlin.com Signed-off-by: Mark Brown --- sound/soc/soc-dapm.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c index ad8ba8fbbaee..eb9535764693 100644 --- a/sound/soc/soc-dapm.c +++ b/sound/soc/soc-dapm.c @@ -2104,6 +2104,7 @@ static ssize_t dapm_widget_power_read_file(struct file *file, int in, out; ssize_t ret; struct snd_soc_dapm_path *p = NULL; + const char *c_name; buf = kmalloc(PAGE_SIZE, GFP_KERNEL); if (!buf) @@ -2145,11 +2146,13 @@ static ssize_t dapm_widget_power_read_file(struct file *file, if (!p->connect) continue; + c_name = p->node[rdir]->dapm->component ? + p->node[rdir]->dapm->component->name : NULL; ret += scnprintf(buf + ret, PAGE_SIZE - ret, - " %s \"%s\" \"%s\"\n", + " %s \"%s\" \"%s\" \"%s\"\n", (rdir == SND_SOC_DAPM_DIR_IN) ? "in" : "out", p->name ? p->name : "static", - p->node[rdir]->name); + p->node[rdir]->name, c_name); } } -- cgit v1.2.3 From 5b1047dcf80b35bafcacbd10b57342d1a96139c0 Mon Sep 17 00:00:00 2001 From: Luca Ceresoli Date: Tue, 16 Apr 2024 08:00:25 +0200 Subject: ASoC: dapm: debugfs: show the widget type To make the widget debugfs files more informative, add a line showing the widget type string. Keeping backward compatibility is nice to have being debugfs, and ease of parsing by both humans and software is also good. To maximize both with a reasonable effort add a new line without thouching the already complex format of the first line. The syntax is meant to be a key/value pair. The existing vizdapm tool continues working after this change, ignoring the new line. The new format is: Left ADC: Off in 1 out 0 - R2(0x2) mask 0x2 stream Left HiFi Capture inactive widget-type adc out "static" "Capture" "cs42l51.0-004a" in "static" "Left PGA" "cs42l51.0-004a" Signed-off-by: Luca Ceresoli Reviewed-by: Alexandre Belloni Link: https://lore.kernel.org/r/20240416-vizdapm-ng-v1-2-5d33c0b57bc5@bootlin.com Signed-off-by: Mark Brown --- sound/soc/soc-dapm.c | 47 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 47 insertions(+) diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c index eb9535764693..16dad4a45443 100644 --- a/sound/soc/soc-dapm.c +++ b/sound/soc/soc-dapm.c @@ -2094,6 +2094,48 @@ static int dapm_power_widgets(struct snd_soc_card *card, int event) } #ifdef CONFIG_DEBUG_FS + +static const char * const snd_soc_dapm_type_name[] = { + [snd_soc_dapm_input] = "input", + [snd_soc_dapm_output] = "output", + [snd_soc_dapm_mux] = "mux", + [snd_soc_dapm_demux] = "demux", + [snd_soc_dapm_mixer] = "mixer", + [snd_soc_dapm_mixer_named_ctl] = "mixer_named_ctl", + [snd_soc_dapm_pga] = "pga", + [snd_soc_dapm_out_drv] = "out_drv", + [snd_soc_dapm_adc] = "adc", + [snd_soc_dapm_dac] = "dac", + [snd_soc_dapm_micbias] = "micbias", + [snd_soc_dapm_mic] = "mic", + [snd_soc_dapm_hp] = "hp", + [snd_soc_dapm_spk] = "spk", + [snd_soc_dapm_line] = "line", + [snd_soc_dapm_switch] = "switch", + [snd_soc_dapm_vmid] = "vmid", + [snd_soc_dapm_pre] = "pre", + [snd_soc_dapm_post] = "post", + [snd_soc_dapm_supply] = "supply", + [snd_soc_dapm_pinctrl] = "pinctrl", + [snd_soc_dapm_regulator_supply] = "regulator_supply", + [snd_soc_dapm_clock_supply] = "clock_supply", + [snd_soc_dapm_aif_in] = "aif_in", + [snd_soc_dapm_aif_out] = "aif_out", + [snd_soc_dapm_siggen] = "siggen", + [snd_soc_dapm_sink] = "sink", + [snd_soc_dapm_dai_in] = "dai_in", + [snd_soc_dapm_dai_out] = "dai_out", + [snd_soc_dapm_dai_link] = "dai_link", + [snd_soc_dapm_kcontrol] = "kcontrol", + [snd_soc_dapm_buffer] = "buffer", + [snd_soc_dapm_scheduler] = "scheduler", + [snd_soc_dapm_effect] = "effect", + [snd_soc_dapm_src] = "src", + [snd_soc_dapm_asrc] = "asrc", + [snd_soc_dapm_encoder] = "encoder", + [snd_soc_dapm_decoder] = "decoder", +}; + static ssize_t dapm_widget_power_read_file(struct file *file, char __user *user_buf, size_t count, loff_t *ppos) @@ -2106,6 +2148,8 @@ static ssize_t dapm_widget_power_read_file(struct file *file, struct snd_soc_dapm_path *p = NULL; const char *c_name; + BUILD_BUG_ON(ARRAY_SIZE(snd_soc_dapm_type_name) != SND_SOC_DAPM_TYPE_COUNT); + buf = kmalloc(PAGE_SIZE, GFP_KERNEL); if (!buf) return -ENOMEM; @@ -2137,6 +2181,9 @@ static ssize_t dapm_widget_power_read_file(struct file *file, w->sname, w->active ? "active" : "inactive"); + ret += scnprintf(buf + ret, PAGE_SIZE - ret, " widget-type %s\n", + snd_soc_dapm_type_name[w->id]); + snd_soc_dapm_for_each_direction(dir) { rdir = SND_SOC_DAPM_DIR_REVERSE(dir); snd_soc_dapm_widget_for_each_path(w, dir, p) { -- cgit v1.2.3 From e7bb43898bcf54da7ffb4819a04c8428f7db24db Mon Sep 17 00:00:00 2001 From: Luca Ceresoli Date: Tue, 16 Apr 2024 08:00:26 +0200 Subject: ASoC: dapm-graph: new tool to visualize DAPM state Add a tool to generate a picture of the current DAPM state for a sound card. dapm-graph is inspired by vizdapm which used to be published on a Wolfson Micro git repository now disappeared, and has a few forks around: https://github.com/mihais/asoc-tools https://github.com/alexandrebelloni/asoc-tools dapm-graph is a full reimplementation with several improvements while still being a self-contained shell script: Improvements to rendered output: - shows the entire card, not one component hierarchy only - each component is rendered in a separate box - shows widget on/off status based on widget information alone (the original vizdapm propagates the "on" green colour to the first input widget) - use bold line and gray background and not only green/red line to show on/off status (for the color blind) Improvements for embedded system developers: - remote mode: get state of remote device (possibly with minimal rootfs) via SSH, but parsing locally for faster operation - compatible with BusyBox shell, not only bash Usability improvements: - flexible command line (uses getopts for parsing) - detailed help text - flag to enable detailed debug logging - graphviz output format detected from file extension, not hard coded - a self-contained shell script Usage is designed to be simple: dapm-grpah -c CARD - get state from debugfs for CARD dapm-grpah -c CARD -r REMOTE_TARGET - same, but remotely via SSH dapm-grpah -d STATE_DIR - from a local copy of the debugfs tree for a card Signed-off-by: Luca Ceresoli Reviewed-by: Alexandre Belloni Link: https://lore.kernel.org/r/20240416-vizdapm-ng-v1-3-5d33c0b57bc5@bootlin.com Signed-off-by: Mark Brown --- MAINTAINERS | 6 + tools/sound/dapm-graph | 303 +++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 309 insertions(+) create mode 100755 tools/sound/dapm-graph diff --git a/MAINTAINERS b/MAINTAINERS index a7d0dd91ac19..aa3b455588e1 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -20669,6 +20669,12 @@ F: include/trace/events/sof*.h F: include/uapi/sound/asoc.h F: sound/soc/ +SOUND - SOC LAYER / dapm-graph +M: Luca Ceresoli +L: linux-sound@vger.kernel.org +S: Maintained +F: tools/sound/dapm-graph + SOUND - SOUND OPEN FIRMWARE (SOF) DRIVERS M: Pierre-Louis Bossart M: Liam Girdwood diff --git a/tools/sound/dapm-graph b/tools/sound/dapm-graph new file mode 100755 index 000000000000..57d78f6df041 --- /dev/null +++ b/tools/sound/dapm-graph @@ -0,0 +1,303 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# +# Generate a graph of the current DAPM state for an audio card +# +# Copyright 2024 Bootlin +# Author: Luca Ceresoli + +set -eu + +STYLE_NODE_ON="shape=box,style=bold,color=green4" +STYLE_NODE_OFF="shape=box,style=filled,color=gray30,fillcolor=gray95" + +# Print usage and exit +# +# $1 = exit return value +# $2 = error string (required if $1 != 0) +usage() +{ + if [ "${1}" -ne 0 ]; then + echo "${2}" >&2 + fi + + echo " +Generate a graph of the current DAPM state for an audio card. + +The DAPM state can be obtained via debugfs for a card on the local host or +a remote target, or from a local copy of the debugfs tree for the card. + +Usage: + $(basename $0) [options] -c CARD - Local sound card + $(basename $0) [options] -c CARD -r REMOTE_TARGET - Card on remote system + $(basename $0) [options] -d STATE_DIR - Local directory + +Options: + -c CARD Sound card to get DAPM state of + -r REMOTE_TARGET Get DAPM state from REMOTE_TARGET via SSH and SCP + instead of using a local sound card + -d STATE_DIR Get DAPM state from a local copy of a debugfs tree + -o OUT_FILE Output file (default: dapm.dot) + -D Show verbose debugging info + -h Print this help and exit + +The output format is implied by the extension of OUT_FILE: + + * Use the .dot extension to generate a text graph representation in + graphviz dot syntax. + * Any other extension is assumed to be a format supported by graphviz for + rendering, e.g. 'png', 'svg', and will produce both the .dot file and a + picture from it. This requires the 'dot' program from the graphviz + package. +" + + exit ${1} +} + +# Connect to a remote target via SSH, collect all DAPM files from debufs +# into a tarball and get the tarball via SCP into $3/dapm.tar +# +# $1 = target as used by ssh and scp, e.g. "root@192.168.1.1" +# $2 = sound card name +# $3 = temp dir path (present on the host, created on the target) +# $4 = local directory to extract the tarball into +# +# Requires an ssh+scp server, find and tar+gz on the target +# +# Note: the tarball is needed because plain 'scp -r' from debugfs would +# copy only empty files +grab_remote_files() +{ + echo "Collecting DAPM state from ${1}" + dbg_echo "Collected DAPM state in ${3}" + + ssh "${1}" " +set -eu && +cd \"/sys/kernel/debug/asoc/${2}\" && +find * -type d -exec mkdir -p ${3}/dapm-tree/{} \; && +find * -type f -exec cp \"{}\" \"${3}/dapm-tree/{}\" \; && +cd ${3}/dapm-tree && +tar cf ${3}/dapm.tar ." + scp -q "${1}:${3}/dapm.tar" "${3}" + + mkdir -p "${4}" + tar xf "${tmp_dir}/dapm.tar" -C "${4}" +} + +# Parse a widget file and generate graph description in graphviz dot format +# +# Skips any file named "bias_level". +# +# $1 = temporary work dir +# $2 = component name +# $3 = widget filename +process_dapm_widget() +{ + local tmp_dir="${1}" + local c_name="${2}" + local w_file="${3}" + local dot_file="${tmp_dir}/main.dot" + local links_file="${tmp_dir}/links.dot" + + local w_name="$(basename "${w_file}")" + local w_tag="${c_name}_${w_name}" + + if [ "${w_name}" = "bias_level" ]; then + return 0 + fi + + dbg_echo " + Widget: ${w_name}" + + cat "${w_file}" | ( + read line + + if echo "${line}" | grep -q ': On ' + then local node_style="${STYLE_NODE_ON}" + else local node_style="${STYLE_NODE_OFF}" + fi + + local w_type="" + while read line; do + # Collect widget type if present + if echo "${line}" | grep -q '^widget-type '; then + local w_type_raw="$(echo "$line" | cut -d ' ' -f 2)" + dbg_echo " - Widget type: ${w_type_raw}" + + # Note: escaping '\n' is tricky to get working with both + # bash and busybox ash, so use a '%' here and replace it + # later + local w_type="%n[${w_type_raw}]" + fi + + # Collect any links. We could use "in" links or "out" links, + # let's use "in" links + if echo "${line}" | grep -q '^in '; then + local w_src=$(echo "$line" | + awk -F\" '{print $6 "_" $4}' | + sed 's/^(null)_/ROOT_/') + dbg_echo " - Input route from: ${w_src}" + echo " \"${w_src}\" -> \"$w_tag\"" >> "${links_file}" + fi + done + + echo " \"${w_tag}\" [label=\"${w_name}${w_type}\",${node_style}]" | + tr '%' '\\' >> "${dot_file}" + ) +} + +# Parse the DAPM tree for a sound card component and generate graph +# description in graphviz dot format +# +# $1 = temporary work dir +# $2 = component directory +# $3 = forced component name (extracted for path if empty) +process_dapm_component() +{ + local tmp_dir="${1}" + local c_dir="${2}" + local c_name="${3}" + local dot_file="${tmp_dir}/main.dot" + local links_file="${tmp_dir}/links.dot" + + if [ -z "${c_name}" ]; then + # Extract directory name into component name: + # "./cs42l51.0-004a/dapm" -> "cs42l51.0-004a" + c_name="$(basename $(dirname "${c_dir}"))" + fi + + dbg_echo " * Component: ${c_name}" + + echo "" >> "${dot_file}" + echo " subgraph \"${c_name}\" {" >> "${dot_file}" + echo " cluster = true" >> "${dot_file}" + echo " label = \"${c_name}\"" >> "${dot_file}" + echo " color=dodgerblue" >> "${dot_file}" + + # Create empty file to ensure it will exist in all cases + >"${links_file}" + + # Iterate over widgets in the component dir + for w_file in ${c_dir}/*; do + process_dapm_widget "${tmp_dir}" "${c_name}" "${w_file}" + done + + echo " }" >> "${dot_file}" + + cat "${links_file}" >> "${dot_file}" +} + +# Parse the DAPM tree for a sound card and generate graph description in +# graphviz dot format +# +# $1 = temporary work dir +# $2 = directory tree with DAPM state (either in debugfs or a mirror) +process_dapm_tree() +{ + local tmp_dir="${1}" + local dapm_dir="${2}" + local dot_file="${tmp_dir}/main.dot" + + echo "digraph G {" > "${dot_file}" + echo " fontname=\"sans-serif\"" >> "${dot_file}" + echo " node [fontname=\"sans-serif\"]" >> "${dot_file}" + + + # Process root directory (no component) + process_dapm_component "${tmp_dir}" "${dapm_dir}/dapm" "ROOT" + + # Iterate over components + for c_dir in "${dapm_dir}"/*/dapm + do + process_dapm_component "${tmp_dir}" "${c_dir}" "" + done + + echo "}" >> "${dot_file}" +} + +main() +{ + # Parse command line + local out_file="dapm.dot" + local card_name="" + local remote_target="" + local dapm_tree="" + local dbg_on="" + while getopts "c:r:d:o:Dh" arg; do + case $arg in + c) card_name="${OPTARG}" ;; + r) remote_target="${OPTARG}" ;; + d) dapm_tree="${OPTARG}" ;; + o) out_file="${OPTARG}" ;; + D) dbg_on="1" ;; + h) usage 0 ;; + *) usage 1 ;; + esac + done + shift $(($OPTIND - 1)) + + if [ -n "${dapm_tree}" ]; then + if [ -n "${card_name}${remote_target}" ]; then + usage 1 "Cannot use -c and -r with -d" + fi + echo "Using local tree: ${dapm_tree}" + elif [ -n "${remote_target}" ]; then + if [ -z "${card_name}" ]; then + usage 1 "-r requires -c" + fi + echo "Using card ${card_name} from remote target ${remote_target}" + elif [ -n "${card_name}" ]; then + echo "Using local card: ${card_name}" + else + usage 1 "Please choose mode using -c, -r or -d" + fi + + # Define logging function + if [ "${dbg_on}" ]; then + dbg_echo() { + echo "$*" >&2 + } + else + dbg_echo() { + : + } + fi + + # Filename must have a dot in order the infer the format from the + # extension + if ! echo "${out_file}" | grep -qE '\.'; then + echo "Missing extension in output filename ${out_file}" >&2 + usage + exit 1 + fi + + local out_fmt="${out_file##*.}" + local dot_file="${out_file%.*}.dot" + + dbg_echo "dot file: $dot_file" + dbg_echo "Output file: $out_file" + dbg_echo "Output format: $out_fmt" + + tmp_dir="$(mktemp -d /tmp/$(basename $0).XXXXXX)" + trap "{ rm -fr ${tmp_dir}; }" INT TERM EXIT + + if [ -z "${dapm_tree}" ] + then + dapm_tree="/sys/kernel/debug/asoc/${card_name}" + fi + if [ -n "${remote_target}" ]; then + dapm_tree="${tmp_dir}/dapm-tree" + grab_remote_files "${remote_target}" "${card_name}" "${tmp_dir}" "${dapm_tree}" + fi + # In all cases now ${dapm_tree} contains the DAPM state + + process_dapm_tree "${tmp_dir}" "${dapm_tree}" + cp "${tmp_dir}/main.dot" "${dot_file}" + + if [ "${out_file}" != "${dot_file}" ]; then + dot -T"${out_fmt}" "${dot_file}" -o "${out_file}" + fi + + echo "Generated file ${out_file}" +} + +main "${@}" -- cgit v1.2.3 From 85ab365f7cdf2b2a713823a93e7e5e94f0529627 Mon Sep 17 00:00:00 2001 From: Kent Overstreet Date: Fri, 19 Apr 2024 21:54:32 -0400 Subject: bcachefs: Fix deadlock in journal write path bch2_journal_write() was incorrectly waiting on earlier journal writes synchronously; this usually worked because most of the time we'd be running in the context of a thread that did a journal_buf_put(), but sometimes we'd be running out of the same workqueue that completes those prior journal writes. Additionally, this makes sure to punt to a workqueue before submitting preflushes - we really don't want to be calling submit_bio() in the main transaction commit path. Signed-off-by: Kent Overstreet --- fs/bcachefs/journal_io.c | 60 +++++++++++++++++++++++++++++++++--------------- 1 file changed, 42 insertions(+), 18 deletions(-) diff --git a/fs/bcachefs/journal_io.c b/fs/bcachefs/journal_io.c index 9aa28b52ab92..eb1f9d6f5a19 100644 --- a/fs/bcachefs/journal_io.c +++ b/fs/bcachefs/journal_io.c @@ -1723,7 +1723,7 @@ static void journal_write_endio(struct bio *bio) percpu_ref_put(&ca->io_ref); } -static CLOSURE_CALLBACK(do_journal_write) +static CLOSURE_CALLBACK(journal_write_submit) { closure_type(w, struct journal_buf, io); struct journal *j = container_of(w, struct journal, buf[w->idx]); @@ -1768,6 +1768,44 @@ static CLOSURE_CALLBACK(do_journal_write) continue_at(cl, journal_write_done, j->wq); } +static CLOSURE_CALLBACK(journal_write_preflush) +{ + closure_type(w, struct journal_buf, io); + struct journal *j = container_of(w, struct journal, buf[w->idx]); + struct bch_fs *c = container_of(j, struct bch_fs, journal); + + if (j->seq_ondisk + 1 != le64_to_cpu(w->data->seq)) { + spin_lock(&j->lock); + closure_wait(&j->async_wait, cl); + spin_unlock(&j->lock); + + continue_at(cl, journal_write_preflush, j->wq); + return; + } + + if (w->separate_flush) { + for_each_rw_member(c, ca) { + percpu_ref_get(&ca->io_ref); + + struct journal_device *ja = &ca->journal; + struct bio *bio = &ja->bio[w->idx]->bio; + bio_reset(bio, ca->disk_sb.bdev, + REQ_OP_WRITE|REQ_SYNC|REQ_META|REQ_PREFLUSH); + bio->bi_end_io = journal_write_endio; + bio->bi_private = ca; + closure_bio_submit(bio, cl); + } + + continue_at(cl, journal_write_submit, j->wq); + } else { + /* + * no need to punt to another work item if we're not waiting on + * preflushes + */ + journal_write_submit(&cl->work); + } +} + static int bch2_journal_write_prep(struct journal *j, struct journal_buf *w) { struct bch_fs *c = container_of(j, struct bch_fs, journal); @@ -2033,23 +2071,9 @@ CLOSURE_CALLBACK(bch2_journal_write) goto err; if (!JSET_NO_FLUSH(w->data)) - closure_wait_event(&j->async_wait, j->seq_ondisk + 1 == le64_to_cpu(w->data->seq)); - - if (!JSET_NO_FLUSH(w->data) && w->separate_flush) { - for_each_rw_member(c, ca) { - percpu_ref_get(&ca->io_ref); - - struct journal_device *ja = &ca->journal; - struct bio *bio = &ja->bio[w->idx]->bio; - bio_reset(bio, ca->disk_sb.bdev, - REQ_OP_WRITE|REQ_SYNC|REQ_META|REQ_PREFLUSH); - bio->bi_end_io = journal_write_endio; - bio->bi_private = ca; - closure_bio_submit(bio, cl); - } - } - - continue_at(cl, do_journal_write, j->wq); + continue_at(cl, journal_write_preflush, j->wq); + else + continue_at(cl, journal_write_submit, j->wq); return; no_io: continue_at(cl, journal_write_done, j->wq); -- cgit v1.2.3 From 0e42f381193d7f9b47922f1c4308e7729a45ba13 Mon Sep 17 00:00:00 2001 From: Kent Overstreet Date: Sat, 20 Apr 2024 22:26:47 -0400 Subject: bcachefs: Fix inode early destruction path discard_new_inode() is the wrong interface to use when we need to free an inode that was never inserted into the inode hash table; we can bypass the whole iput() -> evict() path and replace it with __destroy_inode(); kmem_cache_free() - this fixes a WARN_ON() about I_NEW. Signed-off-by: Kent Overstreet --- fs/bcachefs/fs.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/fs/bcachefs/fs.c b/fs/bcachefs/fs.c index b5ea9fa1259d..fce690007edf 100644 --- a/fs/bcachefs/fs.c +++ b/fs/bcachefs/fs.c @@ -188,7 +188,8 @@ static struct bch_inode_info *bch2_inode_insert(struct bch_fs *c, struct bch_ino BUG_ON(!old); if (unlikely(old != inode)) { - discard_new_inode(&inode->v); + __destroy_inode(&inode->v); + kmem_cache_free(bch2_inode_cache, inode); inode = old; } else { mutex_lock(&c->vfs_inodes_lock); @@ -225,8 +226,10 @@ static struct bch_inode_info *bch2_new_inode(struct btree_trans *trans) if (unlikely(!inode)) { int ret = drop_locks_do(trans, (inode = to_bch_ei(new_inode(c->vfs_sb))) ? 0 : -ENOMEM); - if (ret && inode) - discard_new_inode(&inode->v); + if (ret && inode) { + __destroy_inode(&inode->v); + kmem_cache_free(bch2_inode_cache, inode); + } if (ret) return ERR_PTR(ret); } -- cgit v1.2.3 From 1324eafd37aa5c5b970c1b48a857acc81f0685c8 Mon Sep 17 00:00:00 2001 From: Shenghao Ding Date: Sun, 7 Apr 2024 17:18:42 +0800 Subject: ASoc: PCM6240: Create PCM6240 Family driver code PCM6240 driver implements a flexible and configurable setting for register and filter coefficients, to one, two or even multiple PCM6240 Family Audio chips. Signed-off-by: Shenghao Ding Link: https://lore.kernel.org/r/20240407091846.1299-2-shenghao-ding@ti.com Signed-off-by: Mark Brown --- sound/soc/codecs/pcm6240.c | 2217 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 2217 insertions(+) create mode 100644 sound/soc/codecs/pcm6240.c diff --git a/sound/soc/codecs/pcm6240.c b/sound/soc/codecs/pcm6240.c new file mode 100644 index 000000000000..93d592dbee66 --- /dev/null +++ b/sound/soc/codecs/pcm6240.c @@ -0,0 +1,2217 @@ +// SPDX-License-Identifier: GPL-2.0 +// +// ALSA SoC Texas Instruments PCM6240 Family Audio ADC/DAC Device +// +// Copyright (C) 2022 - 2024 Texas Instruments Incorporated +// https://www.ti.com +// +// The PCM6240 driver implements a flexible and configurable +// algo coefficient setting for one, two, or even multiple +// PCM6240 Family chips. +// +// Author: Shenghao Ding +// + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "pcm6240.h" + +static const struct i2c_device_id pcmdevice_i2c_id[] = { + { "adc3120", ADC3120 }, + { "adc5120", ADC5120 }, + { "adc6120", ADC6120 }, + { "dix4192", DIX4192 }, + { "pcm1690", PCM1690 }, + { "pcm3120", PCM3120 }, + { "pcm3140", PCM3140 }, + { "pcm5120", PCM5120 }, + { "pcm5140", PCM5140 }, + { "pcm6120", PCM6120 }, + { "pcm6140", PCM6140 }, + { "pcm6240", PCM6240 }, + { "pcm6260", PCM6260 }, + { "pcm9211", PCM9211 }, + { "pcmd3140", PCMD3140 }, + { "pcmd3180", PCMD3180 }, + { "pcmd512x", PCMD512X }, + { "taa5212", TAA5212 }, + { "taa5412", TAA5412 }, + { "tad5212", TAD5212 }, + { "tad5412", TAD5412 }, + {} +}; +MODULE_DEVICE_TABLE(i2c, pcmdevice_i2c_id); + +static const char *const pcmdev_ctrl_name[] = { + "%s i2c%d Dev%d Ch%d Ana Volume", + "%s i2c%d Dev%d Ch%d Digi Volume", + "%s i2c%d Dev%d Ch%d Fine Volume", +}; + +static const char *const pcmdev_ctrl_name_with_prefix[] = { + "%s Dev%d Ch%d Ana Volume", + "%s Dev%d Ch%d Digi Volume", + "%s Dev%d Ch%d Fine Volume", +}; + +static const struct pcmdevice_mixer_control adc5120_analog_gain_ctl[] = { + { + .shift = 1, + .reg = ADC5120_REG_CH1_ANALOG_GAIN, + .max = 0x54, + .invert = 0, + }, + { + .shift = 1, + .reg = ADC5120_REG_CH2_ANALOG_GAIN, + .max = 0x54, + .invert = 0, + } +}; + +static const struct pcmdevice_mixer_control adc5120_digi_gain_ctl[] = { + { + .shift = 0, + .reg = ADC5120_REG_CH1_DIGITAL_GAIN, + .max = 0xff, + .invert = 0, + }, + { + .shift = 0, + .reg = ADC5120_REG_CH2_DIGITAL_GAIN, + .max = 0xff, + .invert = 0, + } +}; + +static const struct pcmdevice_mixer_control pcm1690_digi_gain_ctl[] = { + { + .shift = 0, + .reg = PCM1690_REG_CH1_DIGITAL_GAIN, + .max = 0xff, + .invert = 0, + }, + { + .shift = 0, + .reg = PCM1690_REG_CH2_DIGITAL_GAIN, + .max = 0xff, + .invert = 0, + }, + { + .shift = 0, + .reg = PCM1690_REG_CH3_DIGITAL_GAIN, + .max = 0xff, + .invert = 0, + }, + { + .shift = 0, + .reg = PCM1690_REG_CH4_DIGITAL_GAIN, + .max = 0xff, + .invert = 0, + }, + { + .shift = 0, + .reg = PCM1690_REG_CH5_DIGITAL_GAIN, + .max = 0xff, + .invert = 0, + }, + { + .shift = 0, + .reg = PCM1690_REG_CH6_DIGITAL_GAIN, + .max = 0xff, + .invert = 0, + }, + { + .shift = 0, + .reg = PCM1690_REG_CH7_DIGITAL_GAIN, + .max = 0xff, + .invert = 0, + }, + { + .shift = 0, + .reg = PCM1690_REG_CH8_DIGITAL_GAIN, + .max = 0xff, + .invert = 0, + } +}; + +static const struct pcmdevice_mixer_control pcm6240_analog_gain_ctl[] = { + { + .shift = 2, + .reg = PCM6240_REG_CH1_ANALOG_GAIN, + .max = 0x42, + .invert = 0, + }, + { + .shift = 2, + .reg = PCM6240_REG_CH2_ANALOG_GAIN, + .max = 0x42, + .invert = 0, + }, + { + .shift = 2, + .reg = PCM6240_REG_CH3_ANALOG_GAIN, + .max = 0x42, + .invert = 0, + }, + { + .shift = 2, + .reg = PCM6240_REG_CH4_ANALOG_GAIN, + .max = 0x42, + .invert = 0, + } +}; + +static const struct pcmdevice_mixer_control pcm6240_digi_gain_ctl[] = { + { + .shift = 0, + .reg = PCM6240_REG_CH1_DIGITAL_GAIN, + .max = 0xff, + .invert = 0, + }, + { + .shift = 0, + .reg = PCM6240_REG_CH2_DIGITAL_GAIN, + .max = 0xff, + .invert = 0, + }, + { + .shift = 0, + .reg = PCM6240_REG_CH3_DIGITAL_GAIN, + .max = 0xff, + .invert = 0, + }, + { + .shift = 0, + .reg = PCM6240_REG_CH4_DIGITAL_GAIN, + .max = 0xff, + .invert = 0, + } +}; + +static const struct pcmdevice_mixer_control pcm6260_analog_gain_ctl[] = { + { + .shift = 2, + .reg = PCM6260_REG_CH1_ANALOG_GAIN, + .max = 0x42, + .invert = 0, + }, + { + .shift = 2, + .reg = PCM6260_REG_CH2_ANALOG_GAIN, + .max = 0x42, + .invert = 0, + }, + { + .shift = 2, + .reg = PCM6260_REG_CH3_ANALOG_GAIN, + .max = 0x42, + .invert = 0, + }, + { + .shift = 2, + .reg = PCM6260_REG_CH4_ANALOG_GAIN, + .max = 0x42, + .invert = 0, + }, + { + .shift = 2, + .reg = PCM6260_REG_CH5_ANALOG_GAIN, + .max = 0x42, + .invert = 0, + }, + { + .shift = 2, + .reg = PCM6260_REG_CH6_ANALOG_GAIN, + .max = 0x42, + .invert = 0, + } +}; + +static const struct pcmdevice_mixer_control pcm6260_digi_gain_ctl[] = { + { + .shift = 0, + .reg = PCM6260_REG_CH1_DIGITAL_GAIN, + .max = 0xff, + .invert = 0, + }, + { + .shift = 0, + .reg = PCM6260_REG_CH2_DIGITAL_GAIN, + .max = 0xff, + .invert = 0, + }, + { + .shift = 0, + .reg = PCM6260_REG_CH3_DIGITAL_GAIN, + .max = 0xff, + .invert = 0, + }, + { + .shift = 0, + .reg = PCM6260_REG_CH4_DIGITAL_GAIN, + .max = 0xff, + .invert = 0, + }, + { + .shift = 0, + .reg = PCM6260_REG_CH5_DIGITAL_GAIN, + .max = 0xff, + .invert = 0, + }, + { + .shift = 0, + .reg = PCM6260_REG_CH6_DIGITAL_GAIN, + .max = 0xff, + .invert = 0, + } +}; + +static const struct pcmdevice_mixer_control pcm9211_digi_gain_ctl[] = { + { + .shift = 0, + .reg = PCM9211_REG_CH1_DIGITAL_GAIN, + .max = 0xff, + .invert = 0, + }, + { + .shift = 0, + .reg = PCM9211_REG_CH2_DIGITAL_GAIN, + .max = 0xff, + .invert = 0, + } +}; + +static const struct pcmdevice_mixer_control pcmd3140_digi_gain_ctl[] = { + { + .shift = 0, + .reg = PCMD3140_REG_CH1_DIGITAL_GAIN, + .max = 0xff, + .invert = 0, + }, + { + .shift = 0, + .reg = PCMD3140_REG_CH2_DIGITAL_GAIN, + .max = 0xff, + .invert = 0, + }, + { + .shift = 0, + .reg = PCMD3140_REG_CH3_DIGITAL_GAIN, + .max = 0xff, + .invert = 0, + }, + { + .shift = 0, + .reg = PCMD3140_REG_CH4_DIGITAL_GAIN, + .max = 0xff, + .invert = 0, + } +}; + +static const struct pcmdevice_mixer_control pcmd3140_fine_gain_ctl[] = { + { + .shift = 4, + .reg = PCMD3140_REG_CH1_FINE_GAIN, + .max = 0xf, + .invert = 0, + }, + { + .shift = 4, + .reg = PCMD3140_REG_CH2_FINE_GAIN, + .max = 0xf, + .invert = 0, + }, + { + .shift = 4, + .reg = PCMD3140_REG_CH3_FINE_GAIN, + .max = 0xf, + .invert = 0, + }, + { + .shift = 4, + .reg = PCMD3140_REG_CH4_FINE_GAIN, + .max = 0xf, + .invert = 0, + } +}; + +static const struct pcmdevice_mixer_control pcmd3180_digi_gain_ctl[] = { + { + .shift = 0, + .reg = PCMD3180_REG_CH1_DIGITAL_GAIN, + .max = 0xff, + .invert = 0, + }, + { + .shift = 0, + .reg = PCMD3180_REG_CH2_DIGITAL_GAIN, + .max = 0xff, + .invert = 0, + }, + { + .shift = 0, + .reg = PCMD3180_REG_CH3_DIGITAL_GAIN, + .max = 0xff, + .invert = 0, + }, + { + .shift = 0, + .reg = PCMD3180_REG_CH4_DIGITAL_GAIN, + .max = 0xff, + .invert = 0, + }, + { + .shift = 0, + .reg = PCMD3180_REG_CH5_DIGITAL_GAIN, + .max = 0xff, + .invert = 0, + }, + { + .shift = 0, + .reg = PCMD3180_REG_CH6_DIGITAL_GAIN, + .max = 0xff, + .invert = 0, + }, + { + .shift = 0, + .reg = PCMD3180_REG_CH7_DIGITAL_GAIN, + .max = 0xff, + .invert = 0, + }, + { + .shift = 0, + .reg = PCMD3180_REG_CH8_DIGITAL_GAIN, + .max = 0xff, + .invert = 0, + } +}; + +static const struct pcmdevice_mixer_control pcmd3180_fine_gain_ctl[] = { + { + .shift = 4, + .reg = PCMD3180_REG_CH1_FINE_GAIN, + .max = 0xf, + .invert = 0, + }, + { + .shift = 4, + .reg = PCMD3180_REG_CH2_FINE_GAIN, + .max = 0xf, + .invert = 0, + }, + { + .shift = 4, + .reg = PCMD3180_REG_CH3_FINE_GAIN, + .max = 0xf, + .invert = 0, + }, + { + .shift = 4, + .reg = PCMD3180_REG_CH4_FINE_GAIN, + .max = 0xf, + .invert = 0, + }, + { + .shift = 4, + .reg = PCMD3180_REG_CH5_FINE_GAIN, + .max = 0xf, + .invert = 0, + }, + { + .shift = 4, + .reg = PCMD3180_REG_CH6_FINE_GAIN, + .max = 0xf, + .invert = 0, + }, + { + .shift = 4, + .reg = PCMD3180_REG_CH7_FINE_GAIN, + .max = 0xf, + .invert = 0, + }, + { + .shift = 4, + .reg = PCMD3180_REG_CH8_FINE_GAIN, + .max = 0xf, + .invert = 0, + } +}; + +static const struct pcmdevice_mixer_control taa5412_digi_vol_ctl[] = { + { + .shift = 0, + .reg = TAA5412_REG_CH1_DIGITAL_VOLUME, + .max = 0xff, + .invert = 0, + }, + { + .shift = 0, + .reg = TAA5412_REG_CH2_DIGITAL_VOLUME, + .max = 0xff, + .invert = 0, + }, + { + .shift = 0, + .reg = TAA5412_REG_CH3_DIGITAL_VOLUME, + .max = 0xff, + .invert = 0, + }, + { + .shift = 0, + .reg = TAA5412_REG_CH4_DIGITAL_VOLUME, + .max = 0xff, + .invert = 0, + } +}; + +static const struct pcmdevice_mixer_control taa5412_fine_gain_ctl[] = { + { + .shift = 4, + .reg = TAA5412_REG_CH1_FINE_GAIN, + .max = 0xf, + .invert = 0, + }, + { + .shift = 4, + .reg = TAA5412_REG_CH2_FINE_GAIN, + .max = 0xf, + .invert = 0, + }, + { + .shift = 4, + .reg = TAA5412_REG_CH3_FINE_GAIN, + .max = 0xf, + .invert = 4, + }, + { + .shift = 0, + .reg = TAA5412_REG_CH4_FINE_GAIN, + .max = 0xf, + .invert = 4, + } +}; + +static const DECLARE_TLV_DB_MINMAX_MUTE(pcmd3140_dig_gain_tlv, + -10000, 2700); +static const DECLARE_TLV_DB_MINMAX_MUTE(pcm1690_fine_dig_gain_tlv, + -12750, 0); +static const DECLARE_TLV_DB_MINMAX_MUTE(pcm1690_dig_gain_tlv, + -25500, 0); +static const DECLARE_TLV_DB_MINMAX_MUTE(pcm9211_dig_gain_tlv, + -11450, 2000); +static const DECLARE_TLV_DB_MINMAX_MUTE(adc5120_fgain_tlv, + -10050, 2700); +static const DECLARE_TLV_DB_LINEAR(adc5120_chgain_tlv, 0, 4200); +static const DECLARE_TLV_DB_MINMAX_MUTE(pcm6260_fgain_tlv, + -10000, 2700); +static const DECLARE_TLV_DB_LINEAR(pcm6260_chgain_tlv, 0, 4200); +static const DECLARE_TLV_DB_MINMAX_MUTE(taa5412_dig_vol_tlv, + -8050, 4700); +static const DECLARE_TLV_DB_LINEAR(taa5412_fine_gain_tlv, + -80, 70); + +static int pcmdev_change_dev(struct pcmdevice_priv *pcm_priv, + unsigned short dev_no) +{ + struct i2c_client *client = (struct i2c_client *)pcm_priv->client; + struct regmap *map = pcm_priv->regmap; + int ret; + + if (client->addr == pcm_priv->addr[dev_no]) + return 0; + + client->addr = pcm_priv->addr[dev_no]; + /* All pcmdevices share the same regmap, clear the page + * inside regmap once switching to another pcmdevice. + * Register 0 at any pages inside pcmdevice is the same + * one for page-switching. + */ + ret = regmap_write(map, PCMDEVICE_PAGE_SELECT, 0); + if (ret < 0) + dev_err(pcm_priv->dev, "%s: err = %d\n", __func__, ret); + + return ret; +} + +static int pcmdev_dev_read(struct pcmdevice_priv *pcm_dev, + unsigned int dev_no, unsigned int reg, unsigned int *val) +{ + struct regmap *map = pcm_dev->regmap; + int ret; + + if (dev_no >= pcm_dev->ndev) { + dev_err(pcm_dev->dev, "%s: no such channel(%d)\n", __func__, + dev_no); + return -EINVAL; + } + + ret = pcmdev_change_dev(pcm_dev, dev_no); + if (ret < 0) { + dev_err(pcm_dev->dev, "%s: chg dev err = %d\n", __func__, ret); + return ret; + } + + ret = regmap_read(map, reg, val); + if (ret < 0) + dev_err(pcm_dev->dev, "%s: err = %d\n", __func__, ret); + + return ret; +} + +static int pcmdev_dev_update_bits(struct pcmdevice_priv *pcm_dev, + unsigned int dev_no, unsigned int reg, unsigned int mask, + unsigned int value) +{ + struct regmap *map = pcm_dev->regmap; + int ret; + + if (dev_no >= pcm_dev->ndev) { + dev_err(pcm_dev->dev, "%s: no such channel(%d)\n", __func__, + dev_no); + return -EINVAL; + } + + ret = pcmdev_change_dev(pcm_dev, dev_no); + if (ret < 0) { + dev_err(pcm_dev->dev, "%s: chg dev err = %d\n", __func__, ret); + return ret; + } + + ret = regmap_update_bits(map, reg, mask, value); + if (ret < 0) + dev_err(pcm_dev->dev, "%s: update_bits err=%d\n", + __func__, ret); + + return ret; +} + +static int pcmdev_get_volsw(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol, int vol_ctrl_type) +{ + struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); + struct pcmdevice_priv *pcm_dev = + snd_soc_component_get_drvdata(component); + struct pcmdevice_mixer_control *mc = + (struct pcmdevice_mixer_control *)kcontrol->private_value; + int max = mc->max, ret; + unsigned int mask = BIT(fls(max)) - 1; + unsigned int dev_no = mc->dev_no; + unsigned int shift = mc->shift; + unsigned int reg = mc->reg; + unsigned int val; + + mutex_lock(&pcm_dev->codec_lock); + + if (pcm_dev->chip_id == PCM1690) { + ret = pcmdev_dev_read(pcm_dev, dev_no, PCM1690_REG_MODE_CTRL, + &val); + if (ret) { + dev_err(pcm_dev->dev, "%s: read mode err=%d\n", + __func__, ret); + goto out; + } + val &= PCM1690_REG_MODE_CTRL_DAMS_MSK; + /* Set to wide-range mode, before using vol ctrl. */ + if (!val && vol_ctrl_type == PCMDEV_PCM1690_VOL_CTRL) { + ucontrol->value.integer.value[0] = -25500; + goto out; + } + /* Set to fine mode, before using fine vol ctrl. */ + if (val && vol_ctrl_type == PCMDEV_PCM1690_FINE_VOL_CTRL) { + ucontrol->value.integer.value[0] = -12750; + goto out; + } + } + + ret = pcmdev_dev_read(pcm_dev, dev_no, reg, &val); + if (ret) { + dev_err(pcm_dev->dev, "%s: read err=%d\n", + __func__, ret); + goto out; + } + + val = (val >> shift) & mask; + val = (val > max) ? max : val; + val = mc->invert ? max - val : val; + ucontrol->value.integer.value[0] = val; +out: + mutex_unlock(&pcm_dev->codec_lock); + return ret; +} + +static int pcmdevice_get_volsw(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + return pcmdev_get_volsw(kcontrol, ucontrol, PCMDEV_GENERIC_VOL_CTRL); +} + +static int pcm1690_get_volsw(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + return pcmdev_get_volsw(kcontrol, ucontrol, PCMDEV_PCM1690_VOL_CTRL); +} + +static int pcm1690_get_finevolsw(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + return pcmdev_get_volsw(kcontrol, ucontrol, + PCMDEV_PCM1690_FINE_VOL_CTRL); +} + +static int pcmdev_put_volsw(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol, int vol_ctrl_type) +{ + struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); + struct pcmdevice_priv *pcm_dev = + snd_soc_component_get_drvdata(component); + struct pcmdevice_mixer_control *mc = + (struct pcmdevice_mixer_control *)kcontrol->private_value; + int max = mc->max, rc; + unsigned int mask = BIT(fls(max)) - 1; + unsigned int dev_no = mc->dev_no; + unsigned int shift = mc->shift; + unsigned int val, val_mask; + unsigned int reg = mc->reg; + + mutex_lock(&pcm_dev->codec_lock); + val = ucontrol->value.integer.value[0] & mask; + val = (val > max) ? max : val; + val = mc->invert ? max - val : val; + val_mask = mask << shift; + val = val << shift; + + switch (vol_ctrl_type) { + case PCMDEV_PCM1690_VOL_CTRL: + val_mask |= PCM1690_REG_MODE_CTRL_DAMS_MSK; + val |= PCM1690_REG_MODE_CTRL_DAMS_WIDE_RANGE; + break; + case PCMDEV_PCM1690_FINE_VOL_CTRL: + val_mask |= PCM1690_REG_MODE_CTRL_DAMS_MSK; + val |= PCM1690_REG_MODE_CTRL_DAMS_FINE_STEP; + break; + } + + rc = pcmdev_dev_update_bits(pcm_dev, dev_no, reg, val_mask, val); + if (rc < 0) + dev_err(pcm_dev->dev, "%s: update_bits err = %d\n", + __func__, rc); + else + rc = 1; + mutex_unlock(&pcm_dev->codec_lock); + return rc; +} + +static int pcmdevice_put_volsw(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + return pcmdev_put_volsw(kcontrol, ucontrol, PCMDEV_GENERIC_VOL_CTRL); +} + +static int pcm1690_put_volsw(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + return pcmdev_put_volsw(kcontrol, ucontrol, PCMDEV_PCM1690_VOL_CTRL); +} + +static int pcm1690_put_finevolsw(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + return pcmdev_put_volsw(kcontrol, ucontrol, + PCMDEV_PCM1690_FINE_VOL_CTRL); +} + +static const struct pcmdev_ctrl_info pcmdev_gain_ctl_info[][2] = { + // ADC3120 + { + { + .gain = adc5120_chgain_tlv, + .pcmdev_ctrl = adc5120_analog_gain_ctl, + .ctrl_array_size = ARRAY_SIZE(adc5120_analog_gain_ctl), + .get = pcmdevice_get_volsw, + .put = pcmdevice_put_volsw, + .pcmdev_ctrl_name_id = 0, + }, + { + .gain = adc5120_fgain_tlv, + .pcmdev_ctrl = adc5120_digi_gain_ctl, + .ctrl_array_size = ARRAY_SIZE(adc5120_digi_gain_ctl), + .get = pcmdevice_get_volsw, + .put = pcmdevice_put_volsw, + .pcmdev_ctrl_name_id = 1, + }, + }, + // ADC5120 + { + { + .gain = adc5120_chgain_tlv, + .pcmdev_ctrl = adc5120_analog_gain_ctl, + .ctrl_array_size = ARRAY_SIZE(adc5120_analog_gain_ctl), + .get = pcmdevice_get_volsw, + .put = pcmdevice_put_volsw, + .pcmdev_ctrl_name_id = 0, + }, + { + .gain = adc5120_fgain_tlv, + .pcmdev_ctrl = adc5120_digi_gain_ctl, + .ctrl_array_size = ARRAY_SIZE(adc5120_digi_gain_ctl), + .get = pcmdevice_get_volsw, + .put = pcmdevice_put_volsw, + .pcmdev_ctrl_name_id = 1, + }, + }, + // ADC6120 + { + { + .gain = adc5120_chgain_tlv, + .pcmdev_ctrl = adc5120_analog_gain_ctl, + .ctrl_array_size = ARRAY_SIZE(adc5120_analog_gain_ctl), + .get = pcmdevice_get_volsw, + .put = pcmdevice_put_volsw, + .pcmdev_ctrl_name_id = 0, + }, + { + .gain = adc5120_fgain_tlv, + .pcmdev_ctrl = adc5120_digi_gain_ctl, + .ctrl_array_size = ARRAY_SIZE(adc5120_digi_gain_ctl), + .get = pcmdevice_get_volsw, + .put = pcmdevice_put_volsw, + .pcmdev_ctrl_name_id = 1, + }, + }, + // DIX4192 + { + { + .ctrl_array_size = 0, + }, + { + .ctrl_array_size = 0, + }, + }, + // PCM1690 + { + { + .gain = pcm1690_fine_dig_gain_tlv, + .pcmdev_ctrl = pcm1690_digi_gain_ctl, + .ctrl_array_size = ARRAY_SIZE(pcm1690_digi_gain_ctl), + .get = pcm1690_get_volsw, + .put = pcm1690_put_volsw, + .pcmdev_ctrl_name_id = 1, + }, + { + .gain = pcm1690_dig_gain_tlv, + .pcmdev_ctrl = pcm1690_digi_gain_ctl, + .ctrl_array_size = ARRAY_SIZE(pcm1690_digi_gain_ctl), + .get = pcm1690_get_finevolsw, + .put = pcm1690_put_finevolsw, + .pcmdev_ctrl_name_id = 2, + }, + }, + // PCM3120 + { + { + .gain = adc5120_chgain_tlv, + .pcmdev_ctrl = adc5120_analog_gain_ctl, + .ctrl_array_size = ARRAY_SIZE(adc5120_analog_gain_ctl), + .get = pcmdevice_get_volsw, + .put = pcmdevice_put_volsw, + .pcmdev_ctrl_name_id = 0, + }, + { + .gain = adc5120_fgain_tlv, + .pcmdev_ctrl = adc5120_digi_gain_ctl, + .ctrl_array_size = ARRAY_SIZE(adc5120_digi_gain_ctl), + .get = pcmdevice_get_volsw, + .put = pcmdevice_put_volsw, + .pcmdev_ctrl_name_id = 1, + }, + }, + // PCM3140 + { + { + .gain = pcm6260_chgain_tlv, + .pcmdev_ctrl = pcm6240_analog_gain_ctl, + .ctrl_array_size = ARRAY_SIZE(pcm6240_analog_gain_ctl), + .get = pcmdevice_get_volsw, + .put = pcmdevice_put_volsw, + .pcmdev_ctrl_name_id = 0, + }, + { + .gain = pcm6260_fgain_tlv, + .pcmdev_ctrl = pcm6240_digi_gain_ctl, + .ctrl_array_size = ARRAY_SIZE(pcm6240_digi_gain_ctl), + .get = pcmdevice_get_volsw, + .put = pcmdevice_put_volsw, + .pcmdev_ctrl_name_id = 1, + }, + }, + // PCM5120 + { + { + .gain = adc5120_chgain_tlv, + .pcmdev_ctrl = adc5120_analog_gain_ctl, + .ctrl_array_size = ARRAY_SIZE(adc5120_analog_gain_ctl), + .get = pcmdevice_get_volsw, + .put = pcmdevice_put_volsw, + .pcmdev_ctrl_name_id = 0, + }, + { + .gain = adc5120_fgain_tlv, + .pcmdev_ctrl = adc5120_digi_gain_ctl, + .ctrl_array_size = ARRAY_SIZE(adc5120_digi_gain_ctl), + .get = pcmdevice_get_volsw, + .put = pcmdevice_put_volsw, + .pcmdev_ctrl_name_id = 1, + }, + }, + // PCM5140 + { + { + .gain = pcm6260_chgain_tlv, + .pcmdev_ctrl = pcm6240_analog_gain_ctl, + .ctrl_array_size = ARRAY_SIZE(pcm6240_analog_gain_ctl), + .get = pcmdevice_get_volsw, + .put = pcmdevice_put_volsw, + .pcmdev_ctrl_name_id = 0, + }, + { + .gain = pcm6260_fgain_tlv, + .pcmdev_ctrl = pcm6240_digi_gain_ctl, + .ctrl_array_size = ARRAY_SIZE(pcm6240_digi_gain_ctl), + .get = pcmdevice_get_volsw, + .put = pcmdevice_put_volsw, + .pcmdev_ctrl_name_id = 1, + }, + }, + // PCM6120 + { + { + .gain = adc5120_chgain_tlv, + .pcmdev_ctrl = adc5120_analog_gain_ctl, + .ctrl_array_size = ARRAY_SIZE(adc5120_analog_gain_ctl), + .get = pcmdevice_get_volsw, + .put = pcmdevice_put_volsw, + .pcmdev_ctrl_name_id = 0, + }, + { + .gain = adc5120_fgain_tlv, + .pcmdev_ctrl = adc5120_digi_gain_ctl, + .ctrl_array_size = ARRAY_SIZE(adc5120_digi_gain_ctl), + .get = pcmdevice_get_volsw, + .put = pcmdevice_put_volsw, + .pcmdev_ctrl_name_id = 1, + }, + }, + // PCM6140 + { + { + .gain = pcm6260_chgain_tlv, + .pcmdev_ctrl = pcm6240_analog_gain_ctl, + .ctrl_array_size = ARRAY_SIZE(pcm6240_analog_gain_ctl), + .get = pcmdevice_get_volsw, + .put = pcmdevice_put_volsw, + .pcmdev_ctrl_name_id = 0, + }, + { + .gain = pcm6260_fgain_tlv, + .pcmdev_ctrl = pcm6240_digi_gain_ctl, + .ctrl_array_size = ARRAY_SIZE(pcm6240_digi_gain_ctl), + .get = pcmdevice_get_volsw, + .put = pcmdevice_put_volsw, + .pcmdev_ctrl_name_id = 1, + }, + }, + // PCM6240 + { + { + .gain = pcm6260_chgain_tlv, + .pcmdev_ctrl = pcm6240_analog_gain_ctl, + .ctrl_array_size = ARRAY_SIZE(pcm6240_analog_gain_ctl), + .get = pcmdevice_get_volsw, + .put = pcmdevice_put_volsw, + .pcmdev_ctrl_name_id = 0, + }, + { + .gain = pcm6260_fgain_tlv, + .pcmdev_ctrl = pcm6240_digi_gain_ctl, + .ctrl_array_size = ARRAY_SIZE(pcm6240_digi_gain_ctl), + .get = pcmdevice_get_volsw, + .put = pcmdevice_put_volsw, + .pcmdev_ctrl_name_id = 1, + }, + }, + // PCM6260 + { + { + .gain = pcm6260_chgain_tlv, + .pcmdev_ctrl = pcm6260_analog_gain_ctl, + .ctrl_array_size = ARRAY_SIZE(pcm6260_analog_gain_ctl), + .get = pcmdevice_get_volsw, + .put = pcmdevice_put_volsw, + .pcmdev_ctrl_name_id = 0, + }, + { + .gain = pcm6260_fgain_tlv, + .pcmdev_ctrl = pcm6260_digi_gain_ctl, + .ctrl_array_size = ARRAY_SIZE(pcm6260_digi_gain_ctl), + .get = pcmdevice_get_volsw, + .put = pcmdevice_put_volsw, + .pcmdev_ctrl_name_id = 1, + }, + }, + // PCM9211 + { + { + .ctrl_array_size = 0, + }, + { + .gain = pcm9211_dig_gain_tlv, + .pcmdev_ctrl = pcm9211_digi_gain_ctl, + .ctrl_array_size = ARRAY_SIZE(pcm9211_digi_gain_ctl), + .get = pcmdevice_get_volsw, + .put = pcmdevice_put_volsw, + .pcmdev_ctrl_name_id = 1, + }, + + }, + // PCMD3140 + { + { + .gain = taa5412_fine_gain_tlv, + .pcmdev_ctrl = pcmd3140_fine_gain_ctl, + .ctrl_array_size = ARRAY_SIZE(pcmd3140_fine_gain_ctl), + .get = pcmdevice_get_volsw, + .put = pcmdevice_put_volsw, + .pcmdev_ctrl_name_id = 2, + }, + { + .gain = pcmd3140_dig_gain_tlv, + .pcmdev_ctrl = pcmd3140_digi_gain_ctl, + .ctrl_array_size = ARRAY_SIZE(pcmd3140_digi_gain_ctl), + .get = pcmdevice_get_volsw, + .put = pcmdevice_put_volsw, + .pcmdev_ctrl_name_id = 1, + }, + }, + // PCMD3180 + { + { + .gain = taa5412_fine_gain_tlv, + .pcmdev_ctrl = pcmd3180_fine_gain_ctl, + .ctrl_array_size = ARRAY_SIZE(pcmd3180_fine_gain_ctl), + .get = pcmdevice_get_volsw, + .put = pcmdevice_put_volsw, + .pcmdev_ctrl_name_id = 2, + }, + { + .gain = pcmd3140_dig_gain_tlv, + .pcmdev_ctrl = pcmd3180_digi_gain_ctl, + .ctrl_array_size = ARRAY_SIZE(pcmd3180_digi_gain_ctl), + .get = pcmdevice_get_volsw, + .put = pcmdevice_put_volsw, + .pcmdev_ctrl_name_id = 1, + }, + }, + // PCMD512X + { + { + .ctrl_array_size = 0, + }, + { + .ctrl_array_size = 0, + }, + }, + // TAA5212 + { + { + .gain = taa5412_fine_gain_tlv, + .pcmdev_ctrl = taa5412_fine_gain_ctl, + .ctrl_array_size = ARRAY_SIZE(taa5412_fine_gain_ctl), + .get = pcmdevice_get_volsw, + .put = pcmdevice_put_volsw, + .pcmdev_ctrl_name_id = 2, + }, + { + .gain = taa5412_dig_vol_tlv, + .pcmdev_ctrl = taa5412_digi_vol_ctl, + .ctrl_array_size = ARRAY_SIZE(taa5412_digi_vol_ctl), + .get = pcmdevice_get_volsw, + .put = pcmdevice_put_volsw, + .pcmdev_ctrl_name_id = 1, + }, + }, + // TAA5412 + { + { + .gain = taa5412_fine_gain_tlv, + .pcmdev_ctrl = taa5412_fine_gain_ctl, + .ctrl_array_size = ARRAY_SIZE(taa5412_fine_gain_ctl), + .get = pcmdevice_get_volsw, + .put = pcmdevice_put_volsw, + .pcmdev_ctrl_name_id = 2, + }, + { + .gain = taa5412_dig_vol_tlv, + .pcmdev_ctrl = taa5412_digi_vol_ctl, + .ctrl_array_size = ARRAY_SIZE(taa5412_digi_vol_ctl), + .get = pcmdevice_get_volsw, + .put = pcmdevice_put_volsw, + .pcmdev_ctrl_name_id = 1, + }, + }, + // TAD5212 + { + { + .ctrl_array_size = 0, + }, + { + .ctrl_array_size = 0, + }, + }, + // TAD5412 + { + { + .ctrl_array_size = 0, + }, + { + .ctrl_array_size = 0, + }, + }, +}; + +static int pcmdev_dev_bulk_write(struct pcmdevice_priv *pcm_dev, + unsigned int dev_no, unsigned int reg, unsigned char *data, + unsigned int len) +{ + struct regmap *map = pcm_dev->regmap; + int ret; + + if (dev_no >= pcm_dev->ndev) { + dev_err(pcm_dev->dev, "%s: no such channel(%d)\n", __func__, + dev_no); + return -EINVAL; + } + + ret = pcmdev_change_dev(pcm_dev, dev_no); + if (ret < 0) { + dev_err(pcm_dev->dev, "%s: chg dev err = %d\n", __func__, ret); + return ret; + } + + ret = regmap_bulk_write(map, reg, data, len); + if (ret < 0) + dev_err(pcm_dev->dev, "%s: bulk_write err = %d\n", __func__, + ret); + + return ret; +} + +static int pcmdev_dev_write(struct pcmdevice_priv *pcm_dev, + unsigned int dev_no, unsigned int reg, unsigned int value) +{ + struct regmap *map = pcm_dev->regmap; + int ret; + + if (dev_no >= pcm_dev->ndev) { + dev_err(pcm_dev->dev, "%s: no such channel(%d)\n", __func__, + dev_no); + return -EINVAL; + } + + ret = pcmdev_change_dev(pcm_dev, dev_no); + if (ret < 0) { + dev_err(pcm_dev->dev, "%s: chg dev err = %d\n", __func__, ret); + return ret; + } + + ret = regmap_write(map, reg, value); + if (ret < 0) + dev_err(pcm_dev->dev, "%s: err = %d\n", __func__, ret); + + return ret; +} + +static int pcmdevice_info_profile( + struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_info *uinfo) +{ + struct snd_soc_component *codec + = snd_soc_kcontrol_component(kcontrol); + struct pcmdevice_priv *pcm_dev = + snd_soc_component_get_drvdata(codec); + + uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; + uinfo->count = 1; + uinfo->value.integer.min = 0; + uinfo->value.integer.max = max(0, pcm_dev->regbin.ncfgs - 1); + + return 0; +} + +static int pcmdevice_get_profile_id( + struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_component *codec + = snd_soc_kcontrol_component(kcontrol); + struct pcmdevice_priv *pcm_dev = + snd_soc_component_get_drvdata(codec); + + ucontrol->value.integer.value[0] = pcm_dev->cur_conf; + + return 0; +} + +static int pcmdevice_set_profile_id( + struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_component *codec + = snd_soc_kcontrol_component(kcontrol); + struct pcmdevice_priv *pcm_dev = + snd_soc_component_get_drvdata(codec); + int nr_profile = ucontrol->value.integer.value[0]; + int max = pcm_dev->regbin.ncfgs - 1; + int ret = 0; + + nr_profile = clamp(nr_profile, 0, max); + + if (pcm_dev->cur_conf != nr_profile) { + pcm_dev->cur_conf = nr_profile; + ret = 1; + } + + return ret; +} + +static int pcmdevice_info_volsw(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_info *uinfo) +{ + struct pcmdevice_mixer_control *mc = + (struct pcmdevice_mixer_control *)kcontrol->private_value; + + uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; + uinfo->count = 1; + uinfo->value.integer.min = 0; + uinfo->value.integer.max = mc->max; + return 0; +} + +static void pcm9211_sw_rst(struct pcmdevice_priv *pcm_dev) +{ + int ret, i; + + for (i = 0; i < pcm_dev->ndev; i++) { + ret = pcmdev_dev_update_bits(pcm_dev, i, + PCM9211_REG_SW_CTRL, PCM9211_REG_SW_CTRL_MRST_MSK, + PCM9211_REG_SW_CTRL_MRST); + if (ret < 0) + dev_err(pcm_dev->dev, "%s: dev %d swreset fail %d\n", + __func__, i, ret); + } +} + +static void pcmdevice_sw_rst(struct pcmdevice_priv *pcm_dev) +{ + int ret, i; + + for (i = 0; i < pcm_dev->ndev; i++) { + ret = pcmdev_dev_write(pcm_dev, i, PCMDEVICE_REG_SWRESET, + PCMDEVICE_REG_SWRESET_RESET); + if (ret < 0) + dev_err(pcm_dev->dev, "%s: dev %d swreset fail %d\n", + __func__, i, ret); + } +} + +static struct pcmdevice_config_info *pcmdevice_add_config(void *ctxt, + const unsigned char *config_data, unsigned int config_size, + int *status) +{ + struct pcmdevice_priv *pcm_dev = (struct pcmdevice_priv *)ctxt; + struct pcmdevice_config_info *cfg_info; + struct pcmdevice_block_data **bk_da; + unsigned int config_offset = 0, i; + + cfg_info = kzalloc(sizeof(struct pcmdevice_config_info), GFP_KERNEL); + if (!cfg_info) { + *status = -ENOMEM; + goto out; + } + + if (pcm_dev->regbin.fw_hdr.binary_version_num >= 0x105) { + if (config_offset + 64 > (int)config_size) { + *status = -EINVAL; + dev_err(pcm_dev->dev, + "%s: cfg_name out of boundary\n", __func__); + goto out; + } + memcpy(cfg_info->cfg_name, &config_data[config_offset], 64); + config_offset += 64; + } + + if (config_offset + 4 > config_size) { + *status = -EINVAL; + dev_err(pcm_dev->dev, "%s: nblocks out of boundary\n", + __func__); + goto out; + } + cfg_info->nblocks = + get_unaligned_be32(&config_data[config_offset]); + config_offset += 4; + + bk_da = cfg_info->blk_data = kcalloc(cfg_info->nblocks, + sizeof(struct pcmdevice_block_data *), GFP_KERNEL); + if (!bk_da) { + *status = -ENOMEM; + goto out; + } + cfg_info->real_nblocks = 0; + for (i = 0; i < cfg_info->nblocks; i++) { + if (config_offset + 12 > config_size) { + *status = -EINVAL; + dev_err(pcm_dev->dev, + "%s: out of boundary i = %d nblocks = %u\n", + __func__, i, cfg_info->nblocks); + break; + } + bk_da[i] = kzalloc(sizeof(struct pcmdevice_block_data), + GFP_KERNEL); + if (!bk_da[i]) { + *status = -ENOMEM; + break; + } + bk_da[i]->dev_idx = config_data[config_offset]; + config_offset++; + + bk_da[i]->block_type = config_data[config_offset]; + config_offset++; + + if (bk_da[i]->block_type == PCMDEVICE_BIN_BLK_PRE_POWER_UP) { + if (bk_da[i]->dev_idx == 0) + cfg_info->active_dev = + (1 << pcm_dev->ndev) - 1; + else + cfg_info->active_dev = + 1 << (bk_da[i]->dev_idx - 1); + } + + bk_da[i]->yram_checksum = + get_unaligned_be16(&config_data[config_offset]); + config_offset += 2; + bk_da[i]->block_size = + get_unaligned_be32(&config_data[config_offset]); + config_offset += 4; + + bk_da[i]->n_subblks = + get_unaligned_be32(&config_data[config_offset]); + + config_offset += 4; + + if (config_offset + bk_da[i]->block_size > config_size) { + *status = -EINVAL; + dev_err(pcm_dev->dev, + "%s: out of boundary: i = %d blks = %u\n", + __func__, i, cfg_info->nblocks); + break; + } + + bk_da[i]->regdata = kmemdup(&config_data[config_offset], + bk_da[i]->block_size, GFP_KERNEL); + if (!bk_da[i]->regdata) { + *status = -ENOMEM; + goto out; + } + config_offset += bk_da[i]->block_size; + cfg_info->real_nblocks += 1; + } +out: + return cfg_info; +} + +static int pcmdev_gain_ctrl_add(struct pcmdevice_priv *pcm_dev, + int dev_no, int ctl_id) +{ + struct i2c_adapter *adap = pcm_dev->client->adapter; + struct snd_soc_component *comp = pcm_dev->component; + struct pcmdevice_mixer_control *pcmdev_ctrl; + struct snd_kcontrol_new *pcmdev_controls; + int ret, mix_index = 0, name_id, chn; + unsigned int id = pcm_dev->chip_id; + const int nr_chn = + pcmdev_gain_ctl_info[id][ctl_id].ctrl_array_size; + const char *ctrl_name; + char *name; + + if (!nr_chn) { + dev_dbg(pcm_dev->dev, "%s: no gain ctrl for %s\n", __func__, + pcm_dev->dev_name); + return 0; + } + + pcmdev_controls = devm_kzalloc(pcm_dev->dev, + nr_chn * sizeof(struct snd_kcontrol_new), GFP_KERNEL); + if (!pcmdev_controls) + return -ENOMEM; + + name_id = pcmdev_gain_ctl_info[id][ctl_id].pcmdev_ctrl_name_id; + + if (comp->name_prefix) + ctrl_name = pcmdev_ctrl_name_with_prefix[name_id]; + else + ctrl_name = pcmdev_ctrl_name[name_id]; + + for (chn = 1; chn <= nr_chn; chn++) { + name = devm_kzalloc(pcm_dev->dev, + SNDRV_CTL_ELEM_ID_NAME_MAXLEN, GFP_KERNEL); + if (!name) { + ret = -ENOMEM; + goto out; + } + if (comp->name_prefix) + scnprintf(name, SNDRV_CTL_ELEM_ID_NAME_MAXLEN, + ctrl_name, comp->name_prefix, dev_no, chn); + else + scnprintf(name, SNDRV_CTL_ELEM_ID_NAME_MAXLEN, + ctrl_name, pcm_dev->upper_dev_name, adap->nr, + dev_no, chn); + pcmdev_controls[mix_index].tlv.p = + pcmdev_gain_ctl_info[id][ctl_id].gain; + pcmdev_ctrl = devm_kmemdup(pcm_dev->dev, + &pcmdev_gain_ctl_info[id][ctl_id].pcmdev_ctrl[chn - 1], + sizeof(*pcmdev_ctrl), GFP_KERNEL); + if (!pcmdev_ctrl) { + ret = -ENOMEM; + goto out; + } + pcmdev_ctrl->dev_no = dev_no; + pcmdev_controls[mix_index].private_value = + (unsigned long)pcmdev_ctrl; + pcmdev_controls[mix_index].name = name; + pcmdev_controls[mix_index].access = + SNDRV_CTL_ELEM_ACCESS_TLV_READ | + SNDRV_CTL_ELEM_ACCESS_READWRITE; + pcmdev_controls[mix_index].iface = + SNDRV_CTL_ELEM_IFACE_MIXER; + pcmdev_controls[mix_index].info = pcmdevice_info_volsw; + pcmdev_controls[mix_index].get = + pcmdev_gain_ctl_info[id][ctl_id].get; + pcmdev_controls[mix_index].put = + pcmdev_gain_ctl_info[id][ctl_id].put; + mix_index++; + } + + ret = snd_soc_add_component_controls(comp, pcmdev_controls, mix_index); + if (ret) + dev_err(pcm_dev->dev, "%s: add_controls err = %d\n", + __func__, ret); +out: + return ret; +} + +static int pcmdev_profile_ctrl_add(struct pcmdevice_priv *pcm_dev) +{ + struct snd_soc_component *comp = pcm_dev->component; + struct i2c_adapter *adap = pcm_dev->client->adapter; + struct snd_kcontrol_new *pcmdev_ctrl; + char *name; + int ret; + + pcmdev_ctrl = devm_kzalloc(pcm_dev->dev, + sizeof(struct snd_kcontrol_new), GFP_KERNEL); + if (!pcmdev_ctrl) + return -ENOMEM; + + /* Create a mixer item for selecting the active profile */ + name = devm_kzalloc(pcm_dev->dev, SNDRV_CTL_ELEM_ID_NAME_MAXLEN, + GFP_KERNEL); + if (!name) + return -ENOMEM; + + if (comp->name_prefix) + scnprintf(name, SNDRV_CTL_ELEM_ID_NAME_MAXLEN, + "%s Profile id", comp->name_prefix); + else + scnprintf(name, SNDRV_CTL_ELEM_ID_NAME_MAXLEN, + "%s i2c%d Profile id", pcm_dev->upper_dev_name, + adap->nr); + pcmdev_ctrl->name = name; + pcmdev_ctrl->iface = SNDRV_CTL_ELEM_IFACE_MIXER; + pcmdev_ctrl->info = pcmdevice_info_profile; + pcmdev_ctrl->get = pcmdevice_get_profile_id; + pcmdev_ctrl->put = pcmdevice_set_profile_id; + + ret = snd_soc_add_component_controls(comp, pcmdev_ctrl, 1); + if (ret) + dev_err(pcm_dev->dev, "%s: add_controls err = %d\n", + __func__, ret); + + return ret; +} + +static void pcmdevice_config_info_remove(void *ctxt) +{ + struct pcmdevice_priv *pcm_dev = (struct pcmdevice_priv *) ctxt; + struct pcmdevice_regbin *regbin = &(pcm_dev->regbin); + struct pcmdevice_config_info **cfg_info = regbin->cfg_info; + int i, j; + + if (!cfg_info) + return; + for (i = 0; i < regbin->ncfgs; i++) { + if (!cfg_info[i]) + continue; + if (cfg_info[i]->blk_data) { + for (j = 0; j < (int)cfg_info[i]->real_nblocks; j++) { + if (!cfg_info[i]->blk_data[j]) + continue; + kfree(cfg_info[i]->blk_data[j]->regdata); + kfree(cfg_info[i]->blk_data[j]); + } + kfree(cfg_info[i]->blk_data); + } + kfree(cfg_info[i]); + } + kfree(cfg_info); +} + +static int pcmdev_regbin_ready(const struct firmware *fmw, void *ctxt) +{ + struct pcmdevice_config_info **cfg_info; + struct pcmdevice_priv *pcm_dev = ctxt; + struct pcmdevice_regbin_hdr *fw_hdr; + struct pcmdevice_regbin *regbin; + unsigned int total_config_sz = 0; + int offset = 0, ret = 0, i; + unsigned char *buf; + + regbin = &(pcm_dev->regbin); + fw_hdr = &(regbin->fw_hdr); + if (!fmw || !fmw->data) { + dev_err(pcm_dev->dev, "%s: failed to read %s\n", + __func__, pcm_dev->bin_name); + pcm_dev->fw_state = PCMDEVICE_FW_LOAD_FAILED; + ret = -EINVAL; + goto out; + } + buf = (unsigned char *)fmw->data; + + fw_hdr->img_sz = get_unaligned_be32(&buf[offset]); + offset += 4; + if (fw_hdr->img_sz != fmw->size) { + dev_err(pcm_dev->dev, "%s: file size(%d) not match %u", + __func__, (int)fmw->size, fw_hdr->img_sz); + pcm_dev->fw_state = PCMDEVICE_FW_LOAD_FAILED; + ret = -EINVAL; + goto out; + } + + fw_hdr->checksum = get_unaligned_be32(&buf[offset]); + offset += 4; + fw_hdr->binary_version_num = get_unaligned_be32(&buf[offset]); + if (fw_hdr->binary_version_num < 0x103) { + dev_err(pcm_dev->dev, "%s: bin version 0x%04x is out of date", + __func__, fw_hdr->binary_version_num); + pcm_dev->fw_state = PCMDEVICE_FW_LOAD_FAILED; + ret = -EINVAL; + goto out; + } + offset += 4; + fw_hdr->drv_fw_version = get_unaligned_be32(&buf[offset]); + offset += 8; + fw_hdr->plat_type = buf[offset]; + offset += 1; + fw_hdr->dev_family = buf[offset]; + offset += 1; + fw_hdr->reserve = buf[offset]; + offset += 1; + fw_hdr->ndev = buf[offset]; + offset += 1; + if (fw_hdr->ndev != pcm_dev->ndev) { + dev_err(pcm_dev->dev, "%s: invalid ndev(%u)\n", __func__, + fw_hdr->ndev); + pcm_dev->fw_state = PCMDEVICE_FW_LOAD_FAILED; + ret = -EINVAL; + goto out; + } + + if (offset + PCMDEVICE_MAX_REGBIN_DEVICES > fw_hdr->img_sz) { + dev_err(pcm_dev->dev, "%s: devs out of boundary!\n", __func__); + pcm_dev->fw_state = PCMDEVICE_FW_LOAD_FAILED; + ret = -EINVAL; + goto out; + } + + for (i = 0; i < PCMDEVICE_MAX_REGBIN_DEVICES; i++, offset++) + fw_hdr->devs[i] = buf[offset]; + + fw_hdr->nconfig = get_unaligned_be32(&buf[offset]); + offset += 4; + + for (i = 0; i < PCMDEVICE_CONFIG_SUM; i++) { + fw_hdr->config_size[i] = get_unaligned_be32(&buf[offset]); + offset += 4; + total_config_sz += fw_hdr->config_size[i]; + } + + if (fw_hdr->img_sz - total_config_sz != (unsigned int)offset) { + dev_err(pcm_dev->dev, "%s: bin file error!\n", __func__); + pcm_dev->fw_state = PCMDEVICE_FW_LOAD_FAILED; + ret = -EINVAL; + goto out; + } + cfg_info = kcalloc(fw_hdr->nconfig, sizeof(*cfg_info), GFP_KERNEL); + if (!cfg_info) { + pcm_dev->fw_state = PCMDEVICE_FW_LOAD_FAILED; + ret = -ENOMEM; + goto out; + } + regbin->cfg_info = cfg_info; + regbin->ncfgs = 0; + for (i = 0; i < (int)fw_hdr->nconfig; i++) { + cfg_info[i] = pcmdevice_add_config(ctxt, &buf[offset], + fw_hdr->config_size[i], &ret); + if (ret) { + /* In case the bin file is partially destroyed. */ + if (regbin->ncfgs == 0) + pcm_dev->fw_state = PCMDEVICE_FW_LOAD_FAILED; + break; + } + offset += (int)fw_hdr->config_size[i]; + regbin->ncfgs += 1; + } + +out: + if (pcm_dev->fw_state == PCMDEVICE_FW_LOAD_FAILED) { + dev_err(pcm_dev->dev, + "%s: remove config due to fw load error!\n", __func__); + pcmdevice_config_info_remove(pcm_dev); + } + + return ret; +} + +static int pcmdevice_comp_probe(struct snd_soc_component *comp) +{ + struct pcmdevice_priv *pcm_dev = snd_soc_component_get_drvdata(comp); + struct i2c_adapter *adap = pcm_dev->client->adapter; + const struct firmware *fw_entry = NULL; + int ret, i, j; + + mutex_lock(&pcm_dev->codec_lock); + + pcm_dev->component = comp; + + for (i = 0; i < pcm_dev->ndev; i++) { + for (j = 0; j < 2; j++) { + ret = pcmdev_gain_ctrl_add(pcm_dev, i, j); + if (ret < 0) + goto out; + } + } + + if (comp->name_prefix) { + /* There's name_prefix defined in DTS. Bin file name will be + * name_prefix.bin stores the firmware including register + * setting and params for different filters inside chips, it + * must be copied into firmware folder. The same types of + * pcmdevices sitting on the same i2c bus will be aggregated as + * one single codec, all of them share the same bin file. + */ + scnprintf(pcm_dev->bin_name, PCMDEVICE_BIN_FILENAME_LEN, + "%s.bin", comp->name_prefix); + } else { + /* There's NO name_prefix defined in DTS. Bin file name will be + * device-name[defined in pcmdevice_i2c_id]-i2c-bus_id + * [0,1,...,N]-sum[1,...,4]dev.bin stores the firmware + * including register setting and params for different filters + * inside chips, it must be copied into firmware folder. The + * same types of pcmdevices sitting on the same i2c bus will be + * aggregated as one single codec, all of them share the same + * bin file. + */ + scnprintf(pcm_dev->bin_name, PCMDEVICE_BIN_FILENAME_LEN, + "%s-i2c-%d-%udev.bin", pcm_dev->dev_name, adap->nr, + pcm_dev->ndev); + } + + ret = request_firmware(&fw_entry, pcm_dev->bin_name, pcm_dev->dev); + if (ret) { + dev_err(pcm_dev->dev, "%s: request %s err = %d\n", __func__, + pcm_dev->bin_name, ret); + goto out; + } + + ret = pcmdev_regbin_ready(fw_entry, pcm_dev); + if (ret) { + dev_err(pcm_dev->dev, "%s: %s parse err = %d\n", __func__, + pcm_dev->bin_name, ret); + goto out; + } + ret = pcmdev_profile_ctrl_add(pcm_dev); +out: + if (fw_entry) + release_firmware(fw_entry); + + mutex_unlock(&pcm_dev->codec_lock); + return ret; +} + + +static void pcmdevice_comp_remove(struct snd_soc_component *codec) +{ + struct pcmdevice_priv *pcm_dev = snd_soc_component_get_drvdata(codec); + + if (!pcm_dev) + return; + mutex_lock(&pcm_dev->codec_lock); + pcmdevice_config_info_remove(pcm_dev); + mutex_unlock(&pcm_dev->codec_lock); +} + +static const struct snd_soc_dapm_widget pcmdevice_dapm_widgets[] = { + SND_SOC_DAPM_AIF_IN("ASI", "ASI Playback", 0, SND_SOC_NOPM, 0, 0), + SND_SOC_DAPM_AIF_OUT("ASI1 OUT", "ASI1 Capture", + 0, SND_SOC_NOPM, 0, 0), + SND_SOC_DAPM_OUTPUT("OUT"), + SND_SOC_DAPM_INPUT("MIC"), +}; + +static const struct snd_soc_dapm_route pcmdevice_audio_map[] = { + {"OUT", NULL, "ASI"}, + {"ASI1 OUT", NULL, "MIC"}, +}; + +static const struct snd_soc_component_driver + soc_codec_driver_pcmdevice = { + .probe = pcmdevice_comp_probe, + .remove = pcmdevice_comp_remove, + .dapm_widgets = pcmdevice_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(pcmdevice_dapm_widgets), + .dapm_routes = pcmdevice_audio_map, + .num_dapm_routes = ARRAY_SIZE(pcmdevice_audio_map), + .suspend_bias_off = 1, + .idle_bias_on = 0, + .use_pmdown_time = 1, + .endianness = 1, +}; + +static int pcmdev_single_byte_wr(struct pcmdevice_priv *pcm_dev, + unsigned char *data, int devn, int sublocksize) +{ + unsigned short len = get_unaligned_be16(&data[2]); + int offset = 2; + int i, ret; + + offset += 2; + if (offset + 4 * len > sublocksize) { + dev_err(pcm_dev->dev, "%s: dev-%d byt wr out of boundary\n", + __func__, devn); + return -EINVAL; + } + + for (i = 0; i < len; i++) { + ret = pcmdev_dev_write(pcm_dev, devn, + PCMDEVICE_REG(data[offset + 1], data[offset + 2]), + data[offset + 3]); + /* skip this error for next operation or next devices */ + if (ret < 0) + dev_err(pcm_dev->dev, "%s: dev-%d single write err\n", + __func__, devn); + + offset += 4; + } + + return offset; +} + +static int pcmdev_burst_wr(struct pcmdevice_priv *pcm_dev, + unsigned char *data, int devn, int sublocksize) +{ + unsigned short len = get_unaligned_be16(&data[2]); + int offset = 2; + int ret; + + offset += 2; + if (offset + 4 + len > sublocksize) { + dev_err(pcm_dev->dev, "%s: dev-%d burst Out of boundary\n", + __func__, devn); + return -EINVAL; + } + if (len % 4) { + dev_err(pcm_dev->dev, "%s: dev-%d bst-len(%u) not div by 4\n", + __func__, devn, len); + return -EINVAL; + } + ret = pcmdev_dev_bulk_write(pcm_dev, devn, + PCMDEVICE_REG(data[offset + 1], data[offset + 2]), + &(data[offset + 4]), len); + /* skip this error for next devices */ + if (ret < 0) + dev_err(pcm_dev->dev, "%s: dev-%d bulk_write err = %d\n", + __func__, devn, ret); + + offset += (len + 4); + + return offset; +} + +static int pcmdev_delay(struct pcmdevice_priv *pcm_dev, + unsigned char *data, int devn, int sublocksize) +{ + unsigned int delay_time = 0; + int offset = 2; + + if (offset + 2 > sublocksize) { + dev_err(pcm_dev->dev, "%s: dev-%d deley out of boundary\n", + __func__, devn); + return -EINVAL; + } + delay_time = get_unaligned_be16(&data[2]) * 1000; + usleep_range(delay_time, delay_time + 50); + offset += 2; + + return offset; +} + +static int pcmdev_bits_wr(struct pcmdevice_priv *pcm_dev, + unsigned char *data, int devn, int sublocksize) +{ + int offset = 2; + int ret; + + if (offset + 6 > sublocksize) { + dev_err(pcm_dev->dev, "%s: dev-%d bit write out of memory\n", + __func__, devn); + return -EINVAL; + } + ret = pcmdev_dev_update_bits(pcm_dev, devn, + PCMDEVICE_REG(data[offset + 3], data[offset + 4]), + data[offset + 1], data[offset + 5]); + /* skip this error for next devices */ + if (ret < 0) + dev_err(pcm_dev->dev, "%s: dev-%d update_bits err = %d\n", + __func__, devn, ret); + + offset += 6; + + return offset; +} + +static int pcmdevice_process_block(void *ctxt, unsigned char *data, + unsigned char dev_idx, int sublocksize) +{ + struct pcmdevice_priv *pcm_dev = (struct pcmdevice_priv *)ctxt; + int devn, dev_end, ret = 0; + unsigned char subblk_typ = data[1]; + + if (dev_idx) { + devn = dev_idx - 1; + dev_end = dev_idx; + } else { + devn = 0; + dev_end = pcm_dev->ndev; + } + + /* loop in case of several devices sharing the same sub-block */ + for (; devn < dev_end; devn++) { + switch (subblk_typ) { + case PCMDEVICE_CMD_SING_W: + ret = pcmdev_single_byte_wr(pcm_dev, data, devn, sublocksize); + break; + case PCMDEVICE_CMD_BURST: + ret = pcmdev_burst_wr(pcm_dev, data, devn, sublocksize); + break; + case PCMDEVICE_CMD_DELAY: + ret = pcmdev_delay(pcm_dev, data, devn, sublocksize); + break; + case PCMDEVICE_CMD_FIELD_W: + ret = pcmdev_bits_wr(pcm_dev, data, devn, sublocksize); + break; + default: + break; + } + /* + * In case of sub-block error, break the loop for the rest of + * devices. + */ + if (ret < 0) + break; + } + + return ret; +} + +static void pcmdevice_select_cfg_blk(void *ctxt, int conf_no, + unsigned char block_type) +{ + struct pcmdevice_priv *pcm_dev = (struct pcmdevice_priv *)ctxt; + struct pcmdevice_regbin *regbin = &(pcm_dev->regbin); + struct pcmdevice_config_info **cfg_info = regbin->cfg_info; + struct pcmdevice_block_data **blk_data; + int j, k; + + if (conf_no >= regbin->ncfgs || conf_no < 0 || NULL == cfg_info) { + dev_err(pcm_dev->dev, "%s: conf_no should be less than %u\n", + __func__, regbin->ncfgs); + goto out; + } + blk_data = cfg_info[conf_no]->blk_data; + + for (j = 0; j < (int)cfg_info[conf_no]->real_nblocks; j++) { + unsigned int length = 0, ret; + + if (block_type > 5 || block_type < 2) { + dev_err(pcm_dev->dev, + "%s: block_type should be out of range\n", + __func__); + goto out; + } + if (block_type != blk_data[j]->block_type) + continue; + + for (k = 0; k < (int)blk_data[j]->n_subblks; k++) { + ret = pcmdevice_process_block(pcm_dev, + blk_data[j]->regdata + length, + blk_data[j]->dev_idx, + blk_data[j]->block_size - length); + length += ret; + if (blk_data[j]->block_size < length) { + dev_err(pcm_dev->dev, + "%s: %u %u out of boundary\n", + __func__, length, + blk_data[j]->block_size); + break; + } + } + if (length != blk_data[j]->block_size) + dev_err(pcm_dev->dev, "%s: %u %u size is not same\n", + __func__, length, blk_data[j]->block_size); + } + +out: + return; +} + +static int pcmdevice_mute(struct snd_soc_dai *dai, int mute, int stream) +{ + struct snd_soc_component *codec = dai->component; + struct pcmdevice_priv *pcm_dev = snd_soc_component_get_drvdata(codec); + unsigned char block_type; + + if (pcm_dev->fw_state == PCMDEVICE_FW_LOAD_FAILED) { + dev_err(pcm_dev->dev, "%s: bin file not loaded\n", __func__); + return -EINVAL; + } + + if (mute) + block_type = PCMDEVICE_BIN_BLK_PRE_SHUTDOWN; + else + block_type = PCMDEVICE_BIN_BLK_PRE_POWER_UP; + + mutex_lock(&pcm_dev->codec_lock); + pcmdevice_select_cfg_blk(pcm_dev, pcm_dev->cur_conf, block_type); + mutex_unlock(&pcm_dev->codec_lock); + return 0; +} + +static int pcmdevice_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params, struct snd_soc_dai *dai) +{ + struct pcmdevice_priv *pcm_dev = snd_soc_dai_get_drvdata(dai); + unsigned int fsrate; + unsigned int slot_width; + int bclk_rate; + int ret = 0; + + fsrate = params_rate(params); + switch (fsrate) { + case 48000: + break; + case 44100: + break; + default: + dev_err(pcm_dev->dev, "%s: incorrect sample rate = %u\n", + __func__, fsrate); + ret = -EINVAL; + goto out; + } + + slot_width = params_width(params); + switch (slot_width) { + case 16: + break; + case 20: + break; + case 24: + break; + case 32: + break; + default: + dev_err(pcm_dev->dev, "%s: incorrect slot width = %u\n", + __func__, slot_width); + ret = -EINVAL; + goto out; + } + + bclk_rate = snd_soc_params_to_bclk(params); + if (bclk_rate < 0) { + dev_err(pcm_dev->dev, "%s: incorrect bclk rate = %d\n", + __func__, bclk_rate); + ret = bclk_rate; + } + +out: + return ret; +} + +static const struct snd_soc_dai_ops pcmdevice_dai_ops = { + .mute_stream = pcmdevice_mute, + .hw_params = pcmdevice_hw_params, +}; + +static struct snd_soc_dai_driver pcmdevice_dai_driver[] = { + { + .name = "pcmdevice-codec", + .capture = { + .stream_name = "Capture", + .channels_min = 2, + .channels_max = PCMDEVICE_MAX_CHANNELS, + .rates = PCMDEVICE_RATES, + .formats = PCMDEVICE_FORMATS, + }, + .playback = { + .stream_name = "Playback", + .channels_min = 2, + .channels_max = PCMDEVICE_MAX_CHANNELS, + .rates = PCMDEVICE_RATES, + .formats = PCMDEVICE_FORMATS, + }, + .ops = &pcmdevice_dai_ops, + .symmetric_rate = 1, + } +}; + +#ifdef CONFIG_OF +static const struct of_device_id pcmdevice_of_match[] = { + { .compatible = "ti,adc3120" }, + { .compatible = "ti,adc5120" }, + { .compatible = "ti,adc6120" }, + { .compatible = "ti,dix4192" }, + { .compatible = "ti,pcm1690" }, + { .compatible = "ti,pcm3120" }, + { .compatible = "ti,pcm3140" }, + { .compatible = "ti,pcm5120" }, + { .compatible = "ti,pcm5140" }, + { .compatible = "ti,pcm6120" }, + { .compatible = "ti,pcm6140" }, + { .compatible = "ti,pcm6240" }, + { .compatible = "ti,pcm6260" }, + { .compatible = "ti,pcm9211" }, + { .compatible = "ti,pcmd3140" }, + { .compatible = "ti,pcmd3180" }, + { .compatible = "ti,pcmd512x" }, + { .compatible = "ti,taa5212" }, + { .compatible = "ti,taa5412" }, + { .compatible = "ti,tad5212" }, + { .compatible = "ti,tad5412" }, + {}, +}; +MODULE_DEVICE_TABLE(of, pcmdevice_of_match); +#endif + +static const struct regmap_range_cfg pcmdevice_ranges[] = { + { + .range_min = 0, + .range_max = 256 * 128, + .selector_reg = PCMDEVICE_PAGE_SELECT, + .selector_mask = 0xff, + .selector_shift = 0, + .window_start = 0, + .window_len = 128, + }, +}; + +static const struct regmap_config pcmdevice_i2c_regmap = { + .reg_bits = 8, + .val_bits = 8, + .cache_type = REGCACHE_MAPLE, + .ranges = pcmdevice_ranges, + .num_ranges = ARRAY_SIZE(pcmdevice_ranges), + .max_register = 256 * 128, +}; + +static void pcmdevice_remove(struct pcmdevice_priv *pcm_dev) +{ + if (gpio_is_valid(pcm_dev->irq_info.gpio)) { + gpio_free(pcm_dev->irq_info.gpio); + free_irq(pcm_dev->irq_info.nmb, pcm_dev); + } + mutex_destroy(&pcm_dev->codec_lock); +} + +static char *str_to_upper(char *str) +{ + char *orig = str; + + if (!str) + return NULL; + + while (*str) { + *str = toupper(*str); + str++; + } + + return orig; +} + +static int pcmdevice_i2c_probe(struct i2c_client *i2c) +{ + const struct i2c_device_id *id = i2c_match_id(pcmdevice_i2c_id, i2c); + struct pcmdevice_priv *pcm_dev; + struct device_node *np; + unsigned int dev_addrs[PCMDEVICE_MAX_I2C_DEVICES]; + int ret = 0, i = 0, ndev = 0; +#ifdef CONFIG_OF + const __be32 *reg, *reg_end; + int len, sw, aw; +#endif + + pcm_dev = devm_kzalloc(&i2c->dev, sizeof(*pcm_dev), GFP_KERNEL); + if (!pcm_dev) { + ret = -ENOMEM; + goto out; + } + + pcm_dev->chip_id = (id != NULL) ? id->driver_data : 0; + + pcm_dev->dev = &i2c->dev; + pcm_dev->client = i2c; + + if (pcm_dev->chip_id >= MAX_DEVICE) + pcm_dev->chip_id = 0; + + strscpy(pcm_dev->dev_name, pcmdevice_i2c_id[pcm_dev->chip_id].name, + sizeof(pcm_dev->dev_name)); + + strscpy(pcm_dev->upper_dev_name, + pcmdevice_i2c_id[pcm_dev->chip_id].name, + sizeof(pcm_dev->upper_dev_name)); + + str_to_upper(pcm_dev->upper_dev_name); + + pcm_dev->regmap = devm_regmap_init_i2c(i2c, &pcmdevice_i2c_regmap); + if (IS_ERR(pcm_dev->regmap)) { + ret = PTR_ERR(pcm_dev->regmap); + dev_err(&i2c->dev, "%s: failed to allocate register map: %d\n", + __func__, ret); + goto out; + } + + i2c_set_clientdata(i2c, pcm_dev); + mutex_init(&pcm_dev->codec_lock); + np = pcm_dev->dev->of_node; +#ifdef CONFIG_OF + aw = of_n_addr_cells(np); + sw = of_n_size_cells(np); + if (sw == 0) { + reg = (const __be32 *)of_get_property(np, + "reg", &len); + reg_end = reg + len/sizeof(*reg); + ndev = 0; + do { + dev_addrs[ndev] = of_read_number(reg, aw); + reg += aw; + ndev++; + } while (reg < reg_end); + } else { + ndev = 1; + dev_addrs[0] = i2c->addr; + } +#else + ndev = 1; + dev_addrs[0] = i2c->addr; +#endif + pcm_dev->irq_info.gpio = of_irq_get(np, 0); + + for (i = 0; i < ndev; i++) + pcm_dev->addr[i] = dev_addrs[i]; + + pcm_dev->ndev = ndev; + + pcm_dev->hw_rst = devm_gpiod_get_optional(&i2c->dev, + "reset-gpios", GPIOD_OUT_HIGH); + /* No reset GPIO, no side-effect */ + if (IS_ERR(pcm_dev->hw_rst)) { + if (pcm_dev->chip_id == PCM9211 || pcm_dev->chip_id == PCM1690) + pcm9211_sw_rst(pcm_dev); + else + pcmdevice_sw_rst(pcm_dev); + } else { + gpiod_set_value_cansleep(pcm_dev->hw_rst, 0); + usleep_range(500, 1000); + gpiod_set_value_cansleep(pcm_dev->hw_rst, 1); + } + + if (pcm_dev->chip_id == PCM1690) + goto skip_interrupt; + if (gpio_is_valid(pcm_dev->irq_info.gpio)) { + dev_dbg(pcm_dev->dev, "irq-gpio = %d", pcm_dev->irq_info.gpio); + + ret = gpio_request(pcm_dev->irq_info.gpio, "PCMDEV-IRQ"); + if (!ret) { + int gpio = pcm_dev->irq_info.gpio; + + gpio_direction_input(gpio); + pcm_dev->irq_info.nmb = gpio_to_irq(gpio); + + } else + dev_err(pcm_dev->dev, "%s: GPIO %d request error\n", + __func__, pcm_dev->irq_info.gpio); + } else + dev_err(pcm_dev->dev, "Looking up irq-gpio failed %d\n", + pcm_dev->irq_info.gpio); + +skip_interrupt: + ret = devm_snd_soc_register_component(&i2c->dev, + &soc_codec_driver_pcmdevice, pcmdevice_dai_driver, + ARRAY_SIZE(pcmdevice_dai_driver)); + if (ret < 0) + dev_err(&i2c->dev, "probe register comp failed %d\n", ret); + +out: + if (ret < 0) + pcmdevice_remove(pcm_dev); + return ret; +} + +static void pcmdevice_i2c_remove(struct i2c_client *i2c) +{ + struct pcmdevice_priv *pcm_dev = i2c_get_clientdata(i2c); + + pcmdevice_remove(pcm_dev); +} + +static struct i2c_driver pcmdevice_i2c_driver = { + .driver = { + .name = "pcmdevice-codec", + .of_match_table = of_match_ptr(pcmdevice_of_match), + }, + .probe = pcmdevice_i2c_probe, + .remove = pcmdevice_i2c_remove, + .id_table = pcmdevice_i2c_id, +}; +module_i2c_driver(pcmdevice_i2c_driver); + +MODULE_AUTHOR("Shenghao Ding "); +MODULE_DESCRIPTION("ASoC PCM6240 Family Audio ADC/DAC Driver"); +MODULE_LICENSE("GPL"); -- cgit v1.2.3 From d537f7b52d71110a98cd7230cce1b56ae7c8ea71 Mon Sep 17 00:00:00 2001 From: Shenghao Ding Date: Sun, 7 Apr 2024 17:18:43 +0800 Subject: ASoc: PCM6240: Create header file for PCM6240 Family driver code PCM6240 driver implements a flexible and configurable setting for register and filter coefficients, to one, two or even multiple PCM6240 Family Audio chips. Signed-off-by: Shenghao Ding Link: https://lore.kernel.org/r/20240407091846.1299-3-shenghao-ding@ti.com Signed-off-by: Mark Brown --- sound/soc/codecs/pcm6240.h | 252 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 252 insertions(+) create mode 100644 sound/soc/codecs/pcm6240.h diff --git a/sound/soc/codecs/pcm6240.h b/sound/soc/codecs/pcm6240.h new file mode 100644 index 000000000000..1e125bb97286 --- /dev/null +++ b/sound/soc/codecs/pcm6240.h @@ -0,0 +1,252 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +// +// ALSA SoC Texas Instruments PCM6240 Family Audio ADC/DAC/Router +// +// Copyright (C) 2022 - 2024 Texas Instruments Incorporated +// https://www.ti.com +// +// The PCM6240 driver implements a flexible and configurable +// algo coefficient setting for one, two, or even multiple +// PCM6240 Family Audio chips. +// +// Author: Shenghao Ding +// + +#ifndef __PCM6240_H__ +#define __PCM6240_H__ + +enum pcm_device { + ADC3120, + ADC5120, + ADC6120, + DIX4192, + PCM1690, + PCM3120, + PCM3140, + PCM5120, + PCM5140, + PCM6120, + PCM6140, + PCM6240, + PCM6260, + PCM9211, + PCMD3140, + PCMD3180, + PCMD512X, + TAA5212, + TAA5412, + TAD5212, + TAD5412, + MAX_DEVICE, +}; + +#define PCMDEV_GENERIC_VOL_CTRL 0x0 +#define PCMDEV_PCM1690_VOL_CTRL 0x1 +#define PCMDEV_PCM1690_FINE_VOL_CTRL 0x2 + +/* Maximum number of I2C addresses */ +#define PCMDEVICE_MAX_I2C_DEVICES 4 +/* Maximum number defined in REGBIN protocol */ +#define PCMDEVICE_MAX_REGBIN_DEVICES 8 +#define PCMDEVICE_CONFIG_SUM 64 +#define PCMDEVICE_BIN_FILENAME_LEN 64 + +#define PCMDEVICE_RATES (SNDRV_PCM_RATE_44100 | \ + SNDRV_PCM_RATE_48000) +#define PCMDEVICE_MAX_CHANNELS 8 +#define PCMDEVICE_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | \ + SNDRV_PCM_FMTBIT_S20_3LE | \ + SNDRV_PCM_FMTBIT_S24_3LE | \ + SNDRV_PCM_FMTBIT_S24_LE | \ + SNDRV_PCM_FMTBIT_S32_LE) + +/* PAGE Control Register (available in page0 of each book) */ +#define PCMDEVICE_PAGE_SELECT 0x00 +#define PCMDEVICE_REG(page, reg) ((page * 128) + reg) +#define PCMDEVICE_REG_SWRESET PCMDEVICE_REG(0X0, 0x01) +#define PCMDEVICE_REG_SWRESET_RESET BIT(0) + +#define ADC5120_REG_CH1_ANALOG_GAIN PCMDEVICE_REG(0X0, 0x3d) +#define ADC5120_REG_CH1_DIGITAL_GAIN PCMDEVICE_REG(0X0, 0x3e) +#define ADC5120_REG_CH2_ANALOG_GAIN PCMDEVICE_REG(0X0, 0x42) +#define ADC5120_REG_CH2_DIGITAL_GAIN PCMDEVICE_REG(0X0, 0x43) + +#define PCM1690_REG_MODE_CTRL PCMDEVICE_REG(0X0, 0x46) +#define PCM1690_REG_MODE_CTRL_DAMS_MSK BIT(7) +#define PCM1690_REG_MODE_CTRL_DAMS_FINE_STEP 0x0 +#define PCM1690_REG_MODE_CTRL_DAMS_WIDE_RANGE 0x80 + +#define PCM1690_REG_CH1_DIGITAL_GAIN PCMDEVICE_REG(0X0, 0x48) +#define PCM1690_REG_CH2_DIGITAL_GAIN PCMDEVICE_REG(0X0, 0x49) +#define PCM1690_REG_CH3_DIGITAL_GAIN PCMDEVICE_REG(0X0, 0x4a) +#define PCM1690_REG_CH4_DIGITAL_GAIN PCMDEVICE_REG(0X0, 0x4b) +#define PCM1690_REG_CH5_DIGITAL_GAIN PCMDEVICE_REG(0X0, 0x4c) +#define PCM1690_REG_CH6_DIGITAL_GAIN PCMDEVICE_REG(0X0, 0x4d) +#define PCM1690_REG_CH7_DIGITAL_GAIN PCMDEVICE_REG(0X0, 0x4e) +#define PCM1690_REG_CH8_DIGITAL_GAIN PCMDEVICE_REG(0X0, 0x4f) + +#define PCM6240_REG_CH1_ANALOG_GAIN PCMDEVICE_REG(0X0, 0x3d) +#define PCM6240_REG_CH1_DIGITAL_GAIN PCMDEVICE_REG(0X0, 0x3e) +#define PCM6240_REG_CH2_ANALOG_GAIN PCMDEVICE_REG(0X0, 0x42) +#define PCM6240_REG_CH2_DIGITAL_GAIN PCMDEVICE_REG(0X0, 0x43) +#define PCM6240_REG_CH3_ANALOG_GAIN PCMDEVICE_REG(0X0, 0x47) +#define PCM6240_REG_CH3_DIGITAL_GAIN PCMDEVICE_REG(0X0, 0x48) +#define PCM6240_REG_CH4_ANALOG_GAIN PCMDEVICE_REG(0X0, 0x4c) +#define PCM6240_REG_CH4_DIGITAL_GAIN PCMDEVICE_REG(0X0, 0x4d) + +#define PCM6260_REG_CH1_ANALOG_GAIN PCMDEVICE_REG(0X0, 0x3d) +#define PCM6260_REG_CH1_DIGITAL_GAIN PCMDEVICE_REG(0X0, 0x3e) +#define PCM6260_REG_CH2_ANALOG_GAIN PCMDEVICE_REG(0X0, 0x42) +#define PCM6260_REG_CH2_DIGITAL_GAIN PCMDEVICE_REG(0X0, 0x43) +#define PCM6260_REG_CH3_ANALOG_GAIN PCMDEVICE_REG(0X0, 0x47) +#define PCM6260_REG_CH3_DIGITAL_GAIN PCMDEVICE_REG(0X0, 0x48) +#define PCM6260_REG_CH4_ANALOG_GAIN PCMDEVICE_REG(0X0, 0x4c) +#define PCM6260_REG_CH4_DIGITAL_GAIN PCMDEVICE_REG(0X0, 0x4d) +#define PCM6260_REG_CH5_ANALOG_GAIN PCMDEVICE_REG(0X0, 0x51) +#define PCM6260_REG_CH5_DIGITAL_GAIN PCMDEVICE_REG(0X0, 0x52) +#define PCM6260_REG_CH6_ANALOG_GAIN PCMDEVICE_REG(0X0, 0x56) +#define PCM6260_REG_CH6_DIGITAL_GAIN PCMDEVICE_REG(0X0, 0x57) + +#define PCM9211_REG_SW_CTRL PCMDEVICE_REG(0X0, 0x40) +#define PCM9211_REG_SW_CTRL_MRST_MSK BIT(7) +#define PCM9211_REG_SW_CTRL_MRST 0x0 + +#define PCM9211_REG_CH1_DIGITAL_GAIN PCMDEVICE_REG(0X0, 0x46) +#define PCM9211_REG_CH2_DIGITAL_GAIN PCMDEVICE_REG(0X0, 0x47) + +#define PCMD3140_REG_CH1_DIGITAL_GAIN PCMDEVICE_REG(0X0, 0x3E) +#define PCMD3140_REG_CH2_DIGITAL_GAIN PCMDEVICE_REG(0X0, 0x43) +#define PCMD3140_REG_CH3_DIGITAL_GAIN PCMDEVICE_REG(0X0, 0x48) +#define PCMD3140_REG_CH4_DIGITAL_GAIN PCMDEVICE_REG(0X0, 0x4D) + +#define PCMD3140_REG_CH1_FINE_GAIN PCMDEVICE_REG(0X0, 0x3F) +#define PCMD3140_REG_CH2_FINE_GAIN PCMDEVICE_REG(0X0, 0x44) +#define PCMD3140_REG_CH3_FINE_GAIN PCMDEVICE_REG(0X0, 0x49) +#define PCMD3140_REG_CH4_FINE_GAIN PCMDEVICE_REG(0X0, 0x4E) + +#define PCMD3180_REG_CH1_DIGITAL_GAIN PCMDEVICE_REG(0X0, 0x3E) +#define PCMD3180_REG_CH2_DIGITAL_GAIN PCMDEVICE_REG(0X0, 0x43) +#define PCMD3180_REG_CH3_DIGITAL_GAIN PCMDEVICE_REG(0X0, 0x48) +#define PCMD3180_REG_CH4_DIGITAL_GAIN PCMDEVICE_REG(0X0, 0x4D) +#define PCMD3180_REG_CH5_DIGITAL_GAIN PCMDEVICE_REG(0X0, 0x52) +#define PCMD3180_REG_CH6_DIGITAL_GAIN PCMDEVICE_REG(0X0, 0x57) +#define PCMD3180_REG_CH7_DIGITAL_GAIN PCMDEVICE_REG(0X0, 0x5C) +#define PCMD3180_REG_CH8_DIGITAL_GAIN PCMDEVICE_REG(0X0, 0x61) + +#define PCMD3180_REG_CH1_FINE_GAIN PCMDEVICE_REG(0X0, 0x3F) +#define PCMD3180_REG_CH2_FINE_GAIN PCMDEVICE_REG(0X0, 0x44) +#define PCMD3180_REG_CH3_FINE_GAIN PCMDEVICE_REG(0X0, 0x49) +#define PCMD3180_REG_CH4_FINE_GAIN PCMDEVICE_REG(0X0, 0x4E) +#define PCMD3180_REG_CH5_FINE_GAIN PCMDEVICE_REG(0X0, 0x53) +#define PCMD3180_REG_CH6_FINE_GAIN PCMDEVICE_REG(0X0, 0x58) +#define PCMD3180_REG_CH7_FINE_GAIN PCMDEVICE_REG(0X0, 0x5D) +#define PCMD3180_REG_CH8_FINE_GAIN PCMDEVICE_REG(0X0, 0x62) + +#define TAA5412_REG_CH1_DIGITAL_VOLUME PCMDEVICE_REG(0X0, 0x52) +#define TAA5412_REG_CH2_DIGITAL_VOLUME PCMDEVICE_REG(0X0, 0x57) +#define TAA5412_REG_CH3_DIGITAL_VOLUME PCMDEVICE_REG(0X0, 0x5B) +#define TAA5412_REG_CH4_DIGITAL_VOLUME PCMDEVICE_REG(0X0, 0x5F) + +#define TAA5412_REG_CH1_FINE_GAIN PCMDEVICE_REG(0X0, 0x53) +#define TAA5412_REG_CH2_FINE_GAIN PCMDEVICE_REG(0X0, 0x58) +#define TAA5412_REG_CH3_FINE_GAIN PCMDEVICE_REG(0X0, 0x5C) +#define TAA5412_REG_CH4_FINE_GAIN PCMDEVICE_REG(0X0, 0x60) + +#define PCMDEVICE_CMD_SING_W 0x1 +#define PCMDEVICE_CMD_BURST 0x2 +#define PCMDEVICE_CMD_DELAY 0x3 +#define PCMDEVICE_CMD_FIELD_W 0x4 + +enum pcmdevice_bin_blk_type { + PCMDEVICE_BIN_BLK_COEFF = 1, + PCMDEVICE_BIN_BLK_POST_POWER_UP, + PCMDEVICE_BIN_BLK_PRE_SHUTDOWN, + PCMDEVICE_BIN_BLK_PRE_POWER_UP, + PCMDEVICE_BIN_BLK_POST_SHUTDOWN +}; + +enum pcmdevice_fw_state { + PCMDEVICE_FW_LOAD_OK = 0, + PCMDEVICE_FW_LOAD_FAILED +}; + +struct pcmdevice_regbin_hdr { + unsigned int img_sz; + unsigned int checksum; + unsigned int binary_version_num; + unsigned int drv_fw_version; + unsigned int timestamp; + unsigned char plat_type; + unsigned char dev_family; + unsigned char reserve; + unsigned char ndev; + unsigned char devs[PCMDEVICE_MAX_REGBIN_DEVICES]; + unsigned int nconfig; + unsigned int config_size[PCMDEVICE_CONFIG_SUM]; +}; + +struct pcmdevice_block_data { + unsigned char dev_idx; + unsigned char block_type; + unsigned short yram_checksum; + unsigned int block_size; + unsigned int n_subblks; + unsigned char *regdata; +}; + +struct pcmdevice_config_info { + char cfg_name[64]; + unsigned int nblocks; + unsigned int real_nblocks; + unsigned char active_dev; + struct pcmdevice_block_data **blk_data; +}; + +struct pcmdevice_regbin { + struct pcmdevice_regbin_hdr fw_hdr; + int ncfgs; + struct pcmdevice_config_info **cfg_info; +}; + +struct pcmdevice_irqinfo { + int gpio; + int nmb; +}; + +struct pcmdevice_priv { + struct snd_soc_component *component; + struct i2c_client *client; + struct device *dev; + struct mutex codec_lock; + struct gpio_desc *hw_rst; + struct regmap *regmap; + struct pcmdevice_regbin regbin; + struct pcmdevice_irqinfo irq_info; + unsigned int addr[PCMDEVICE_MAX_I2C_DEVICES]; + unsigned int chip_id; + int cur_conf; + int fw_state; + int ndev; + unsigned char bin_name[PCMDEVICE_BIN_FILENAME_LEN]; + /* used for kcontrol name */ + unsigned char upper_dev_name[I2C_NAME_SIZE]; + unsigned char dev_name[I2C_NAME_SIZE]; +}; + +/* mixer control */ +struct pcmdevice_mixer_control { + int max; + int reg; + unsigned int dev_no; + unsigned int shift; + unsigned int invert; +}; +struct pcmdev_ctrl_info { + const unsigned int *gain; + const struct pcmdevice_mixer_control *pcmdev_ctrl; + unsigned int ctrl_array_size; + snd_kcontrol_get_t *get; + snd_kcontrol_put_t *put; + int pcmdev_ctrl_name_id; +}; +#endif /* __PCM6240_H__ */ -- cgit v1.2.3 From 6bb1b70690766367e166b8ff59f4b5f9739f7964 Mon Sep 17 00:00:00 2001 From: Shenghao Ding Date: Sun, 7 Apr 2024 17:18:44 +0800 Subject: ASoc: PCM6240: Add compile item for PCM6240 Family driver PCM6240 driver implements a flexible and configurable setting for register and filter coefficients, to one, two or even multiple PCM6240 Family Audio chips. Signed-off-by: Shenghao Ding Link: https://lore.kernel.org/r/20240407091846.1299-4-shenghao-ding@ti.com Signed-off-by: Mark Brown --- sound/soc/codecs/Kconfig | 10 ++++++++++ sound/soc/codecs/Makefile | 2 ++ 2 files changed, 12 insertions(+) diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig index 995eab954dd5..4afc43d3f71f 100644 --- a/sound/soc/codecs/Kconfig +++ b/sound/soc/codecs/Kconfig @@ -179,6 +179,7 @@ config SND_SOC_ALL_CODECS imply SND_SOC_PCM5102A imply SND_SOC_PCM512x_I2C imply SND_SOC_PCM512x_SPI + imply SND_SOC_PCM6240 imply SND_SOC_PEB2466 imply SND_SOC_RK3308 imply SND_SOC_RK3328 @@ -1424,6 +1425,15 @@ config SND_SOC_PCM512x_SPI select SND_SOC_PCM512x select REGMAP_SPI +config SND_SOC_PCM6240 + tristate "Texas Instruments PCM6240 Family Audio chips based on I2C" + depends on I2C + help + Enable support for Texas Instruments PCM6240 Family Audio chips. + Note the PCM6240 driver implements a flexible and configurable + setting for register and filter coefficients, to one, two or + even multiple PCM6240 Family Audio chips. + config SND_SOC_PEB2466 tristate "Infineon PEB2466 quad PCM codec" depends on SPI diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile index 9ba24fb870b1..cddb16cd6a4c 100644 --- a/sound/soc/codecs/Makefile +++ b/sound/soc/codecs/Makefile @@ -204,6 +204,7 @@ snd-soc-pcm5102a-objs := pcm5102a.o snd-soc-pcm512x-objs := pcm512x.o snd-soc-pcm512x-i2c-objs := pcm512x-i2c.o snd-soc-pcm512x-spi-objs := pcm512x-spi.o +snd-soc-pcm6240-objs := pcm6240.o snd-soc-peb2466-objs := peb2466.o snd-soc-rk3308-objs := rk3308_codec.o snd-soc-rk3328-objs := rk3328_codec.o @@ -595,6 +596,7 @@ obj-$(CONFIG_SND_SOC_PCM5102A) += snd-soc-pcm5102a.o obj-$(CONFIG_SND_SOC_PCM512x) += snd-soc-pcm512x.o obj-$(CONFIG_SND_SOC_PCM512x_I2C) += snd-soc-pcm512x-i2c.o obj-$(CONFIG_SND_SOC_PCM512x_SPI) += snd-soc-pcm512x-spi.o +obj-$(CONFIG_SND_SOC_PCM6240) += snd-soc-pcm6240.o obj-$(CONFIG_SND_SOC_PEB2466) += snd-soc-peb2466.o obj-$(CONFIG_SND_SOC_RK3308) += snd-soc-rk3308.o obj-$(CONFIG_SND_SOC_RK3328) += snd-soc-rk3328.o -- cgit v1.2.3 From cee56a8e9cf89fd690e18eb2e6f09d3f8a6442fb Mon Sep 17 00:00:00 2001 From: Shenghao Ding Date: Sun, 7 Apr 2024 17:18:45 +0800 Subject: ASoc: dt-bindings: PCM6240: Add initial DT binding PCM6240 family chips are popular among audio customers, in spite of only a portion of the functionality of codec, such as ADC or DAC, and so on, for different Specifications, range from Personal Electric to Automotive Electric, even some professional fields. Yet their audio performance is far superior to the codec's, and cost is lower than codec, and much easier to program than codec. Reviewed-by: Rob Herring Signed-off-by: Shenghao Ding Link: https://lore.kernel.org/r/20240407091846.1299-5-shenghao-ding@ti.com Signed-off-by: Mark Brown --- .../devicetree/bindings/sound/ti,pcm6240.yaml | 177 +++++++++++++++++++++ 1 file changed, 177 insertions(+) create mode 100644 Documentation/devicetree/bindings/sound/ti,pcm6240.yaml diff --git a/Documentation/devicetree/bindings/sound/ti,pcm6240.yaml b/Documentation/devicetree/bindings/sound/ti,pcm6240.yaml new file mode 100644 index 000000000000..dd5b08e3d7a1 --- /dev/null +++ b/Documentation/devicetree/bindings/sound/ti,pcm6240.yaml @@ -0,0 +1,177 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +# Copyright (C) 2022 - 2024 Texas Instruments Incorporated +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/sound/ti,pcm6240.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Texas Instruments PCM6240 Family Audio ADC/DAC + +maintainers: + - Shenghao Ding + +description: | + The PCM6240 Family is a big family of Audio ADC/DAC for + different Specifications, range from Personal Electric + to Automotive Electric, even some professional fields. + + Specifications about the audio chip can be found at: + https://www.ti.com/lit/gpn/tlv320adc3120 + https://www.ti.com/lit/gpn/tlv320adc5120 + https://www.ti.com/lit/gpn/tlv320adc6120 + https://www.ti.com/lit/gpn/dix4192 + https://www.ti.com/lit/gpn/pcm1690 + https://www.ti.com/lit/gpn/pcm3120-q1 + https://www.ti.com/lit/gpn/pcm3140-q1 + https://www.ti.com/lit/gpn/pcm5120-q1 + https://www.ti.com/lit/gpn/pcm6120-q1 + https://www.ti.com/lit/gpn/pcm6260-q1 + https://www.ti.com/lit/gpn/pcm9211 + https://www.ti.com/lit/gpn/pcmd3140 + https://www.ti.com/lit/gpn/pcmd3180 + https://www.ti.com/lit/gpn/taa5212 + https://www.ti.com/lit/gpn/tad5212 + +properties: + compatible: + description: | + ti,adc3120: Stereo-channel, 768-kHz, Burr-Brown™ audio analog-to- + digital converter (ADC) with 106-dB SNR. + + ti,adc5120: 2-Channel, 768-kHz, Burr-Brown™ Audio ADC with 120-dB SNR. + + ti,adc6120: Stereo-channel, 768-kHz, Burr-Brown™ audio analog-to- + digital converter (ADC) with 123-dB SNR. + + ti,dix4192: 216-kHz digital audio converter with Quad-Channel In + and One-Channel Out. + + ti,pcm1690: Automotive Catalog 113dB SNR 8-Channel Audio DAC with + Differential Outputs. + + ti,pcm3120: Automotive, stereo, 106-dB SNR, 768-kHz, low-power + software-controlled audio ADC. + + ti,pcm3140: Automotive, Quad-Channel, 768-kHz, Burr-Brown™ Audio ADC + with 106-dB SNR. + + ti,pcm5120: Automotive, stereo, 120-dB SNR, 768-kHz, low-power + software-controlled audio ADC. + + ti,pcm5140: Automotive, Quad-Channel, 768-kHz, Burr-Brown™ Audio ADC + with 120-dB SNR. + + ti,pcm6120: Automotive, stereo, 123-dB SNR, 768-kHz, low-power + software-controlled audio ADC. + + ti,pcm6140: Automotive, Quad-Channel, 768-kHz, Burr-Brown™ Audio ADC + with 123-dB SNR. + + ti,pcm6240: Automotive 4-ch audio ADC with integrated programmable mic + bias, boost and input diagnostics. + + ti,pcm6260: Automotive 6-ch audio ADC with integrated programmable mic + bias, boost and input diagnostics. + + ti,pcm9211: 216-kHz digital audio converter With Stereo ADC and + Routing. + + ti,pcmd3140: Four-channel PDM-input to TDM or I2S output converter. + + ti,pcmd3180: Eight-channel pulse-density-modulation input to TDM or + I2S output converter. + + ti,taa5212: Low-power high-performance stereo audio ADC with 118-dB + dynamic range. + + ti,tad5212: Low-power stereo audio DAC with 120-dB dynamic range. + oneOf: + - items: + - enum: + - ti,adc3120 + - ti,adc5120 + - ti,pcm3120 + - ti,pcm5120 + - ti,pcm6120 + - const: ti,adc6120 + - items: + - enum: + - ti,pcmd512x + - ti,pcm9211 + - ti,taa5212 + - ti,tad5212 + - const: ti,adc6120 + - items: + - enum: + - ti,pcm3140 + - ti,pcm5140 + - ti,dix4192 + - ti,pcm6140 + - ti,pcm6260 + - const: ti,pcm6240 + - items: + - enum: + - ti,pcmd3140 + - ti,pcmd3180 + - ti,pcm1690 + - ti,taa5412 + - ti,tad5412 + - const: ti,pcm6240 + - enum: + - ti,adc6120 + - ti,pcm6240 + + reg: + description: + I2C address, in multiple pcmdevices case, all the i2c address + aggregate as one Audio Device to support multiple audio slots. + minItems: 1 + maxItems: 4 + + reset-gpios: + maxItems: 1 + + interrupts: + maxItems: 1 + description: + Invalid only for ti,pcm1690 because of no INT pin. + + '#sound-dai-cells': + const: 0 + +required: + - compatible + - reg + +allOf: + - $ref: dai-common.yaml# + - if: + properties: + compatible: + contains: + enum: + - ti,pcm1690 + then: + properties: + interrupts: false + +additionalProperties: false + +examples: + - | + #include + i2c { + /* example for two devices with interrupt support */ + #address-cells = <1>; + #size-cells = <0>; + pcm6240: audio-codec@48 { + compatible = "ti,pcm6240"; + reg = <0x48>, /* primary-device */ + <0x4b>; /* secondary-device */ + #sound-dai-cells = <0>; + reset-gpios = <&gpio1 10 GPIO_ACTIVE_HIGH>; + interrupt-parent = <&gpio1>; + interrupts = <15>; + }; + }; +... -- cgit v1.2.3 From f5d20b253d1a51aadb8881d899caaaa989217e89 Mon Sep 17 00:00:00 2001 From: Amadeusz Sławiński Date: Fri, 19 Apr 2024 10:43:07 +0200 Subject: ASoC: Intel: avs: Switch to ACPI NHLT MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Now that NHLT support in ACPI framework was introduced, migrate avs driver to new API. Signed-off-by: Amadeusz Sławiński Signed-off-by: Cezary Rojewski Link: https://lore.kernel.org/r/20240419084307.2718881-3-cezary.rojewski@intel.com Signed-off-by: Mark Brown --- sound/soc/intel/Kconfig | 1 + sound/soc/intel/avs/avs.h | 1 - sound/soc/intel/avs/board_selection.c | 7 +++---- sound/soc/intel/avs/core.c | 10 ++++------ sound/soc/intel/avs/path.c | 32 ++++++++++++++++---------------- 5 files changed, 24 insertions(+), 27 deletions(-) diff --git a/sound/soc/intel/Kconfig b/sound/soc/intel/Kconfig index 4b9e498e3303..38b61dfd1487 100644 --- a/sound/soc/intel/Kconfig +++ b/sound/soc/intel/Kconfig @@ -214,6 +214,7 @@ config SND_SOC_INTEL_AVS depends on X86 || COMPILE_TEST depends on PCI depends on COMMON_CLK + select ACPI_NHLT if ACPI select SND_SOC_ACPI if ACPI select SND_SOC_TOPOLOGY select SND_SOC_HDA diff --git a/sound/soc/intel/avs/avs.h b/sound/soc/intel/avs/avs.h index f80f79415344..900786eb81e4 100644 --- a/sound/soc/intel/avs/avs.h +++ b/sound/soc/intel/avs/avs.h @@ -151,7 +151,6 @@ struct avs_dev { struct completion fw_ready; struct work_struct probe_work; - struct nhlt_acpi_table *nhlt; struct list_head comp_list; struct mutex comp_list_mutex; struct list_head path_list; diff --git a/sound/soc/intel/avs/board_selection.c b/sound/soc/intel/avs/board_selection.c index 8360ce557401..290ea314ace8 100644 --- a/sound/soc/intel/avs/board_selection.c +++ b/sound/soc/intel/avs/board_selection.c @@ -10,10 +10,10 @@ #include #include #include +#include #include #include #include -#include #include #include #include "avs.h" @@ -434,8 +434,7 @@ static int avs_register_dmic_board(struct avs_dev *adev) struct snd_soc_acpi_mach mach = {{0}}; int ret; - if (!adev->nhlt || - !intel_nhlt_has_endpoint_type(adev->nhlt, NHLT_LINK_DMIC)) { + if (!acpi_nhlt_find_endpoint(ACPI_NHLT_LINKTYPE_PDM, -1, -1, -1)) { dev_dbg(adev->dev, "no DMIC endpoints present\n"); return 0; } @@ -523,7 +522,7 @@ static int avs_register_i2s_boards(struct avs_dev *adev) struct snd_soc_acpi_mach *mach; int ret; - if (!adev->nhlt || !intel_nhlt_has_endpoint_type(adev->nhlt, NHLT_LINK_SSP)) { + if (!acpi_nhlt_find_endpoint(ACPI_NHLT_LINKTYPE_SSP, -1, -1, -1)) { dev_dbg(adev->dev, "no I2S endpoints present\n"); return 0; } diff --git a/sound/soc/intel/avs/core.c b/sound/soc/intel/avs/core.c index d7f8940099ce..a61ce42b426c 100644 --- a/sound/soc/intel/avs/core.c +++ b/sound/soc/intel/avs/core.c @@ -14,15 +14,16 @@ // foundation of this driver // +#include #include #include +#include #include #include #include #include #include #include -#include #include "../../codecs/hda.h" #include "avs.h" #include "cldma.h" @@ -214,9 +215,7 @@ static void avs_hda_probe_work(struct work_struct *work) if (ret < 0) return; - adev->nhlt = intel_nhlt_init(adev->dev); - if (!adev->nhlt) - dev_info(bus->dev, "platform has no NHLT\n"); + acpi_nhlt_get_gbl_table(); avs_debugfs_init(adev); avs_register_all_boards(adev); @@ -549,8 +548,7 @@ static void avs_pci_remove(struct pci_dev *pci) avs_unregister_all_boards(adev); avs_debugfs_exit(adev); - if (adev->nhlt) - intel_nhlt_free(adev->nhlt); + acpi_nhlt_put_gbl_table(); if (avs_platattr_test(adev, CLDMA)) hda_cldma_free(&code_loader); diff --git a/sound/soc/intel/avs/path.c b/sound/soc/intel/avs/path.c index e785fc2a7008..531a086642be 100644 --- a/sound/soc/intel/avs/path.c +++ b/sound/soc/intel/avs/path.c @@ -6,7 +6,8 @@ // Amadeusz Slawinski // -#include +#include +#include #include #include #include "avs.h" @@ -143,10 +144,10 @@ static bool avs_dma_type_is_input(u32 dma_type) static int avs_copier_create(struct avs_dev *adev, struct avs_path_module *mod) { - struct nhlt_acpi_table *nhlt = adev->nhlt; struct avs_tplg_module *t = mod->template; struct avs_copier_cfg *cfg; - struct nhlt_specific_cfg *ep_blob; + struct acpi_nhlt_format_config *ep_blob; + struct acpi_nhlt_endpoint *ep; union avs_connector_node_id node_id = {0}; size_t cfg_size, data_size = 0; void *data = NULL; @@ -174,18 +175,18 @@ static int avs_copier_create(struct avs_dev *adev, struct avs_path_module *mod) else fmt = t->cfg_ext->copier.out_fmt; - ep_blob = intel_nhlt_get_endpoint_blob(adev->dev, - nhlt, t->cfg_ext->copier.vindex.i2s.instance, - NHLT_LINK_SSP, fmt->valid_bit_depth, fmt->bit_depth, - fmt->num_channels, fmt->sampling_freq, direction, - NHLT_DEVICE_I2S); + ep = acpi_nhlt_find_endpoint(ACPI_NHLT_LINKTYPE_SSP, + ACPI_NHLT_DEVICETYPE_CODEC, direction, + t->cfg_ext->copier.vindex.i2s.instance); + ep_blob = acpi_nhlt_endpoint_find_fmtcfg(ep, fmt->num_channels, fmt->sampling_freq, + fmt->valid_bit_depth, fmt->bit_depth); if (!ep_blob) { dev_err(adev->dev, "no I2S ep_blob found\n"); return -ENOENT; } - data = ep_blob->caps; - data_size = ep_blob->size; + data = ep_blob->config.capabilities; + data_size = ep_blob->config.capabilities_size; /* I2S gateway's vindex is statically assigned in topology */ node_id.vindex = t->cfg_ext->copier.vindex.val; @@ -199,17 +200,16 @@ static int avs_copier_create(struct avs_dev *adev, struct avs_path_module *mod) else fmt = t->in_fmt; - ep_blob = intel_nhlt_get_endpoint_blob(adev->dev, nhlt, 0, - NHLT_LINK_DMIC, fmt->valid_bit_depth, - fmt->bit_depth, fmt->num_channels, - fmt->sampling_freq, direction, NHLT_DEVICE_DMIC); + ep = acpi_nhlt_find_endpoint(ACPI_NHLT_LINKTYPE_PDM, -1, direction, 0); + ep_blob = acpi_nhlt_endpoint_find_fmtcfg(ep, fmt->num_channels, fmt->sampling_freq, + fmt->valid_bit_depth, fmt->bit_depth); if (!ep_blob) { dev_err(adev->dev, "no DMIC ep_blob found\n"); return -ENOENT; } - data = ep_blob->caps; - data_size = ep_blob->size; + data = ep_blob->config.capabilities; + data_size = ep_blob->config.capabilities_size; /* DMIC gateway's vindex is statically assigned in topology */ node_id.vindex = t->cfg_ext->copier.vindex.val; -- cgit v1.2.3 From ed30a4a51bb196781c8058073ea720133a65596f Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Sun, 21 Apr 2024 12:35:54 -0700 Subject: Linux 6.9-rc5 --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 59d8a7f95d0a..43b10f3d438c 100644 --- a/Makefile +++ b/Makefile @@ -2,7 +2,7 @@ VERSION = 6 PATCHLEVEL = 9 SUBLEVEL = 0 -EXTRAVERSION = -rc4 +EXTRAVERSION = -rc5 NAME = Hurr durr I'ma ninja sloth # *DOCUMENTATION* -- cgit v1.2.3 From e858beeddfa3a400844c0e22d2118b3b52f1ea5e Mon Sep 17 00:00:00 2001 From: Kent Overstreet Date: Sun, 21 Apr 2024 23:32:18 -0400 Subject: bcachefs: If we run merges at a lower watermark, they must be nonblocking Fix another deadlock related to the merge path; previously, we switched to always running merges at a lower watermark (because they are noncritical); but when we run at a lower watermark we also need to run nonblocking or we've introduced a new deadlock. Signed-off-by: Kent Overstreet Reported-and-tested-by: s@m-h.ug --- fs/bcachefs/btree_update_interior.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/fs/bcachefs/btree_update_interior.c b/fs/bcachefs/btree_update_interior.c index 6030c396754f..b4efd8cc4d1a 100644 --- a/fs/bcachefs/btree_update_interior.c +++ b/fs/bcachefs/btree_update_interior.c @@ -1960,7 +1960,11 @@ int __bch2_foreground_maybe_merge(struct btree_trans *trans, if ((flags & BCH_WATERMARK_MASK) == BCH_WATERMARK_interior_updates) return 0; - flags &= ~BCH_WATERMARK_MASK; + if ((flags & BCH_WATERMARK_MASK) <= BCH_WATERMARK_reclaim) { + flags &= ~BCH_WATERMARK_MASK; + flags |= BCH_WATERMARK_btree; + flags |= BCH_TRANS_COMMIT_journal_reclaim; + } b = trans->paths[path].l[level].b; -- cgit v1.2.3 From 91112fc6212a9be6f3be636d885df9c17395e1a4 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Sat, 20 Apr 2024 15:44:36 +0200 Subject: wifi: iwlwifi: mvm: fix link ID management On older (pre-MLD API) devices, we started also calling iwl_mvm_set_link_mapping()/iwl_mvm_unset_link_mapping(), but of course not also iwl_mvm_remove_link(). Since the link ID was only released in iwl_mvm_remove_link() this causes us to run out of FW link IDs very quickly. Fix it by releasing the link ID correctly. Fixes: a8b5d4809b50 ("wifi: iwlwifi: mvm: Configure the link mapping for non-MLD FW") Link: https://msgid.link/20240420154435.dce72db5d5e3.Ic40b454b24f1c7b380a1eedf67455d9cf2f58541@changeid Signed-off-by: Johannes Berg --- drivers/net/wireless/intel/iwlwifi/mvm/link.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/link.c b/drivers/net/wireless/intel/iwlwifi/mvm/link.c index 9f69e04594e4..fe5bba8561d0 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/link.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/link.c @@ -279,6 +279,7 @@ int iwl_mvm_unset_link_mapping(struct iwl_mvm *mvm, struct ieee80211_vif *vif, RCU_INIT_POINTER(mvm->link_id_to_link_conf[link_info->fw_link_id], NULL); + iwl_mvm_release_fw_link_id(mvm, link_info->fw_link_id); return 0; } @@ -296,7 +297,6 @@ int iwl_mvm_remove_link(struct iwl_mvm *mvm, struct ieee80211_vif *vif, return 0; cmd.link_id = cpu_to_le32(link_info->fw_link_id); - iwl_mvm_release_fw_link_id(mvm, link_info->fw_link_id); link_info->fw_link_id = IWL_MVM_FW_LINK_ID_INVALID; cmd.spec_link_id = link_conf->link_id; cmd.phy_id = cpu_to_le32(FW_CTXT_INVALID); -- cgit v1.2.3 From 0b8fe5bd73249dc20be2e88a12041f8920797b59 Mon Sep 17 00:00:00 2001 From: Daniele Palmas Date: Thu, 18 Apr 2024 13:12:07 +0200 Subject: net: usb: qmi_wwan: add Telit FN920C04 compositions Add the following Telit FN920C04 compositions: 0x10a0: rmnet + tty (AT/NMEA) + tty (AT) + tty (diag) T: Bus=03 Lev=01 Prnt=03 Port=06 Cnt=01 Dev#= 5 Spd=480 MxCh= 0 D: Ver= 2.01 Cls=00(>ifc ) Sub=00 Prot=00 MxPS=64 #Cfgs= 1 P: Vendor=1bc7 ProdID=10a0 Rev=05.15 S: Manufacturer=Telit Cinterion S: Product=FN920 S: SerialNumber=92c4c4d8 C: #Ifs= 4 Cfg#= 1 Atr=e0 MxPwr=500mA I: If#= 0 Alt= 0 #EPs= 3 Cls=ff(vend.) Sub=ff Prot=50 Driver=qmi_wwan E: Ad=01(O) Atr=02(Bulk) MxPS= 512 Ivl=0ms E: Ad=81(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms E: Ad=82(I) Atr=03(Int.) MxPS= 8 Ivl=32ms I: If#= 1 Alt= 0 #EPs= 3 Cls=ff(vend.) Sub=ff Prot=60 Driver=option E: Ad=02(O) Atr=02(Bulk) MxPS= 512 Ivl=0ms E: Ad=83(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms E: Ad=84(I) Atr=03(Int.) MxPS= 10 Ivl=32ms I: If#= 2 Alt= 0 #EPs= 3 Cls=ff(vend.) Sub=ff Prot=40 Driver=option E: Ad=03(O) Atr=02(Bulk) MxPS= 512 Ivl=0ms E: Ad=85(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms E: Ad=86(I) Atr=03(Int.) MxPS= 10 Ivl=32ms I: If#= 3 Alt= 0 #EPs= 2 Cls=ff(vend.) Sub=ff Prot=30 Driver=option E: Ad=04(O) Atr=02(Bulk) MxPS= 512 Ivl=0ms E: Ad=87(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms 0x10a4: rmnet + tty (AT) + tty (AT) + tty (diag) T: Bus=03 Lev=01 Prnt=03 Port=06 Cnt=01 Dev#= 8 Spd=480 MxCh= 0 D: Ver= 2.01 Cls=00(>ifc ) Sub=00 Prot=00 MxPS=64 #Cfgs= 1 P: Vendor=1bc7 ProdID=10a4 Rev=05.15 S: Manufacturer=Telit Cinterion S: Product=FN920 S: SerialNumber=92c4c4d8 C: #Ifs= 4 Cfg#= 1 Atr=e0 MxPwr=500mA I: If#= 0 Alt= 0 #EPs= 3 Cls=ff(vend.) Sub=ff Prot=50 Driver=qmi_wwan E: Ad=01(O) Atr=02(Bulk) MxPS= 512 Ivl=0ms E: Ad=81(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms E: Ad=82(I) Atr=03(Int.) MxPS= 8 Ivl=32ms I: If#= 1 Alt= 0 #EPs= 3 Cls=ff(vend.) Sub=ff Prot=40 Driver=option E: Ad=02(O) Atr=02(Bulk) MxPS= 512 Ivl=0ms E: Ad=83(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms E: Ad=84(I) Atr=03(Int.) MxPS= 10 Ivl=32ms I: If#= 2 Alt= 0 #EPs= 3 Cls=ff(vend.) Sub=ff Prot=40 Driver=option E: Ad=03(O) Atr=02(Bulk) MxPS= 512 Ivl=0ms E: Ad=85(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms E: Ad=86(I) Atr=03(Int.) MxPS= 10 Ivl=32ms I: If#= 3 Alt= 0 #EPs= 2 Cls=ff(vend.) Sub=ff Prot=30 Driver=option E: Ad=04(O) Atr=02(Bulk) MxPS= 512 Ivl=0ms E: Ad=87(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms 0x10a9: rmnet + tty (AT) + tty (diag) + DPL (data packet logging) + adb T: Bus=03 Lev=01 Prnt=03 Port=06 Cnt=01 Dev#= 9 Spd=480 MxCh= 0 D: Ver= 2.01 Cls=00(>ifc ) Sub=00 Prot=00 MxPS=64 #Cfgs= 1 P: Vendor=1bc7 ProdID=10a9 Rev=05.15 S: Manufacturer=Telit Cinterion S: Product=FN920 S: SerialNumber=92c4c4d8 C: #Ifs= 5 Cfg#= 1 Atr=e0 MxPwr=500mA I: If#= 0 Alt= 0 #EPs= 3 Cls=ff(vend.) Sub=ff Prot=50 Driver=qmi_wwan E: Ad=01(O) Atr=02(Bulk) MxPS= 512 Ivl=0ms E: Ad=81(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms E: Ad=82(I) Atr=03(Int.) MxPS= 8 Ivl=32ms I: If#= 1 Alt= 0 #EPs= 3 Cls=ff(vend.) Sub=ff Prot=40 Driver=option E: Ad=02(O) Atr=02(Bulk) MxPS= 512 Ivl=0ms E: Ad=83(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms E: Ad=84(I) Atr=03(Int.) MxPS= 10 Ivl=32ms I: If#= 2 Alt= 0 #EPs= 2 Cls=ff(vend.) Sub=ff Prot=30 Driver=option E: Ad=03(O) Atr=02(Bulk) MxPS= 512 Ivl=0ms E: Ad=85(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms I: If#= 3 Alt= 0 #EPs= 1 Cls=ff(vend.) Sub=ff Prot=80 Driver=(none) E: Ad=86(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms I: If#= 4 Alt= 0 #EPs= 2 Cls=ff(vend.) Sub=42 Prot=01 Driver=(none) E: Ad=04(O) Atr=02(Bulk) MxPS= 512 Ivl=0ms E: Ad=87(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms Signed-off-by: Daniele Palmas Signed-off-by: David S. Miller --- drivers/net/usb/qmi_wwan.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/net/usb/qmi_wwan.c b/drivers/net/usb/qmi_wwan.c index edc34402e787..a5469cf5cf67 100644 --- a/drivers/net/usb/qmi_wwan.c +++ b/drivers/net/usb/qmi_wwan.c @@ -1368,6 +1368,9 @@ static const struct usb_device_id products[] = { {QMI_QUIRK_SET_DTR(0x1bc7, 0x1060, 2)}, /* Telit LN920 */ {QMI_QUIRK_SET_DTR(0x1bc7, 0x1070, 2)}, /* Telit FN990 */ {QMI_QUIRK_SET_DTR(0x1bc7, 0x1080, 2)}, /* Telit FE990 */ + {QMI_QUIRK_SET_DTR(0x1bc7, 0x10a0, 0)}, /* Telit FN920C04 */ + {QMI_QUIRK_SET_DTR(0x1bc7, 0x10a4, 0)}, /* Telit FN920C04 */ + {QMI_QUIRK_SET_DTR(0x1bc7, 0x10a9, 0)}, /* Telit FN920C04 */ {QMI_FIXED_INTF(0x1bc7, 0x1100, 3)}, /* Telit ME910 */ {QMI_FIXED_INTF(0x1bc7, 0x1101, 3)}, /* Telit ME910 dual modem */ {QMI_FIXED_INTF(0x1bc7, 0x1200, 5)}, /* Telit LE920 */ -- cgit v1.2.3 From c58e88d49097bd12dfcfef4f075b43f5d5830941 Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Sat, 20 Apr 2024 07:01:16 +0000 Subject: icmp: prevent possible NULL dereferences from icmp_build_probe() First problem is a double call to __in_dev_get_rcu(), because the second one could return NULL. if (__in_dev_get_rcu(dev) && __in_dev_get_rcu(dev)->ifa_list) Second problem is a read from dev->ip6_ptr with no NULL check: if (!list_empty(&rcu_dereference(dev->ip6_ptr)->addr_list)) Use the correct RCU API to fix these. v2: add missing include Fixes: d329ea5bd884 ("icmp: add response to RFC 8335 PROBE messages") Signed-off-by: Eric Dumazet Cc: Andreas Roeseler Reviewed-by: David Ahern Signed-off-by: David S. Miller --- net/ipv4/icmp.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/net/ipv4/icmp.c b/net/ipv4/icmp.c index e63a3bf99617..437e782b9663 100644 --- a/net/ipv4/icmp.c +++ b/net/ipv4/icmp.c @@ -92,6 +92,7 @@ #include #include #include +#include /* * Build xmit assembly blocks @@ -1032,6 +1033,8 @@ bool icmp_build_probe(struct sk_buff *skb, struct icmphdr *icmphdr) struct icmp_ext_hdr *ext_hdr, _ext_hdr; struct icmp_ext_echo_iio *iio, _iio; struct net *net = dev_net(skb->dev); + struct inet6_dev *in6_dev; + struct in_device *in_dev; struct net_device *dev; char buff[IFNAMSIZ]; u16 ident_len; @@ -1115,10 +1118,15 @@ bool icmp_build_probe(struct sk_buff *skb, struct icmphdr *icmphdr) /* Fill bits in reply message */ if (dev->flags & IFF_UP) status |= ICMP_EXT_ECHOREPLY_ACTIVE; - if (__in_dev_get_rcu(dev) && __in_dev_get_rcu(dev)->ifa_list) + + in_dev = __in_dev_get_rcu(dev); + if (in_dev && rcu_access_pointer(in_dev->ifa_list)) status |= ICMP_EXT_ECHOREPLY_IPV4; - if (!list_empty(&rcu_dereference(dev->ip6_ptr)->addr_list)) + + in6_dev = __in6_dev_get(dev); + if (in6_dev && !list_empty(&in6_dev->addr_list)) status |= ICMP_EXT_ECHOREPLY_IPV6; + dev_put(dev); icmphdr->un.echo.sequence |= htons(status); return true; -- cgit v1.2.3 From 70dcdf5f8c41ce2379d48d497db10af4a09ea075 Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Sun, 21 Apr 2024 14:44:58 -0500 Subject: mailmap: add entries for Alex Elder Define my kernel.org address to be the canonical one, and add mailmap entries for the various addresses (including typos) that have been used over the years. Signed-off-by: Alex Elder Signed-off-by: David S. Miller --- .mailmap | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/.mailmap b/.mailmap index 8284692f9610..f932ce611898 100644 --- a/.mailmap +++ b/.mailmap @@ -38,6 +38,16 @@ Alexei Starovoitov Alexei Starovoitov Alexei Starovoitov Alexey Makhalov +Alex Elder +Alex Elder +Alex Elder +Alex Elder +Alex Elder +Alex Elder +Alex Elder +Alex Elder +Alex Elder +Alex Elder Alex Hung Alex Shi Alex Shi -- cgit v1.2.3 From 4fd1edcdf13c0d234543ecf502092be65c5177db Mon Sep 17 00:00:00 2001 From: Hangbin Liu Date: Fri, 19 Apr 2024 16:02:00 +0800 Subject: bridge/br_netlink.c: no need to return void function br_info_notify is a void function. There is no need to return. Fixes: b6d0425b816e ("bridge: cfm: Netlink Notifications.") Signed-off-by: Hangbin Liu Acked-by: Nikolay Aleksandrov Signed-off-by: David S. Miller --- net/bridge/br_netlink.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/bridge/br_netlink.c b/net/bridge/br_netlink.c index 2cf4fc756263..f17dbac7d828 100644 --- a/net/bridge/br_netlink.c +++ b/net/bridge/br_netlink.c @@ -667,7 +667,7 @@ void br_ifinfo_notify(int event, const struct net_bridge *br, { u32 filter = RTEXT_FILTER_BRVLAN_COMPRESSED; - return br_info_notify(event, br, port, filter); + br_info_notify(event, br, port, filter); } /* -- cgit v1.2.3 From 7474b1c82be3780692d537d331f9aa7fc1e5a368 Mon Sep 17 00:00:00 2001 From: Vikas Gupta Date: Fri, 19 Apr 2024 11:34:47 -0700 Subject: bnxt_en: refactor reset close code Introduce bnxt_fw_fatal_close() API which can be used to stop data path and disable device when firmware is in fatal state. Signed-off-by: Vikas Gupta Signed-off-by: Michael Chan Signed-off-by: David S. Miller --- drivers/net/ethernet/broadcom/bnxt/bnxt.c | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.c b/drivers/net/ethernet/broadcom/bnxt/bnxt.c index 57e61f963167..c852f87c842f 100644 --- a/drivers/net/ethernet/broadcom/bnxt/bnxt.c +++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.c @@ -13037,6 +13037,16 @@ static void bnxt_rx_ring_reset(struct bnxt *bp) bnxt_rtnl_unlock_sp(bp); } +static void bnxt_fw_fatal_close(struct bnxt *bp) +{ + bnxt_tx_disable(bp); + bnxt_disable_napi(bp); + bnxt_disable_int_sync(bp); + bnxt_free_irq(bp); + bnxt_clear_int_mode(bp); + pci_disable_device(bp->pdev); +} + static void bnxt_fw_reset_close(struct bnxt *bp) { bnxt_ulp_stop(bp); @@ -13050,12 +13060,7 @@ static void bnxt_fw_reset_close(struct bnxt *bp) pci_read_config_word(bp->pdev, PCI_SUBSYSTEM_ID, &val); if (val == 0xffff) bp->fw_reset_min_dsecs = 0; - bnxt_tx_disable(bp); - bnxt_disable_napi(bp); - bnxt_disable_int_sync(bp); - bnxt_free_irq(bp); - bnxt_clear_int_mode(bp); - pci_disable_device(bp->pdev); + bnxt_fw_fatal_close(bp); } __bnxt_close_nic(bp, true, false); bnxt_vf_reps_free(bp); -- cgit v1.2.3 From a1acdc226baec331512f815d6ac9dd6f8435cc7f Mon Sep 17 00:00:00 2001 From: Vikas Gupta Date: Fri, 19 Apr 2024 11:34:48 -0700 Subject: bnxt_en: Fix the PCI-AER routines We do not support two simultaneous recoveries so check for reset flag, BNXT_STATE_IN_FW_RESET, and do not proceed with AER further. When the pci channel state is pci_channel_io_frozen, the PCIe link can not be trusted so we disable the traffic immediately and stop BAR access by calling bnxt_fw_fatal_close(). BAR access after AER fatal error can cause an NMI. Fixes: f75d9a0aa967 ("bnxt_en: Re-write PCI BARs after PCI fatal error.") Signed-off-by: Vikas Gupta Signed-off-by: Michael Chan Signed-off-by: David S. Miller --- drivers/net/ethernet/broadcom/bnxt/bnxt.c | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.c b/drivers/net/ethernet/broadcom/bnxt/bnxt.c index c852f87c842f..86c1c30c70d5 100644 --- a/drivers/net/ethernet/broadcom/bnxt/bnxt.c +++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.c @@ -15378,6 +15378,7 @@ static pci_ers_result_t bnxt_io_error_detected(struct pci_dev *pdev, { struct net_device *netdev = pci_get_drvdata(pdev); struct bnxt *bp = netdev_priv(netdev); + bool abort = false; netdev_info(netdev, "PCI I/O error detected\n"); @@ -15386,16 +15387,27 @@ static pci_ers_result_t bnxt_io_error_detected(struct pci_dev *pdev, bnxt_ulp_stop(bp); - if (state == pci_channel_io_perm_failure) { + if (test_and_set_bit(BNXT_STATE_IN_FW_RESET, &bp->state)) { + netdev_err(bp->dev, "Firmware reset already in progress\n"); + abort = true; + } + + if (abort || state == pci_channel_io_perm_failure) { rtnl_unlock(); return PCI_ERS_RESULT_DISCONNECT; } - if (state == pci_channel_io_frozen) + /* Link is not reliable anymore if state is pci_channel_io_frozen + * so we disable bus master to prevent any potential bad DMAs before + * freeing kernel memory. + */ + if (state == pci_channel_io_frozen) { set_bit(BNXT_STATE_PCI_CHANNEL_IO_FROZEN, &bp->state); + bnxt_fw_fatal_close(bp); + } if (netif_running(netdev)) - bnxt_close(netdev); + __bnxt_close_nic(bp, true, true); if (pci_is_enabled(pdev)) pci_disable_device(pdev); @@ -15479,6 +15491,7 @@ static pci_ers_result_t bnxt_io_slot_reset(struct pci_dev *pdev) } reset_exit: + clear_bit(BNXT_STATE_IN_FW_RESET, &bp->state); bnxt_clear_reservations(bp, true); rtnl_unlock(); -- cgit v1.2.3 From 41e54045b741daf61e03c82d442227af3d12111f Mon Sep 17 00:00:00 2001 From: Michael Chan Date: Fri, 19 Apr 2024 11:34:49 -0700 Subject: bnxt_en: Fix error recovery for 5760X (P7) chips During error recovery, such as AER fatal error slot reset, we call bnxt_try_map_fw_health_reg() to try to get access to the health register to determine the firmware state. Fix bnxt_try_map_fw_health_reg() to recognize the P7 chip correctly and set up the health register. This fixes this type of AER slot reset failure: bnxt_en 0000:04:00.0: AER: PCIe Bus Error: severity=Uncorrectable (Fatal), type=Inaccessible, (Unregistered Agent ID) bnxt_en 0000:04:00.0 enp4s0f0np0: PCI I/O error detected bnxt_en 0000:04:00.0 bnxt_re0: Handle device suspend call bnxt_en 0000:04:00.1 enp4s0f1np1: PCI I/O error detected bnxt_en 0000:04:00.1 bnxt_re1: Handle device suspend call pcieport 0000:00:02.0: AER: Root Port link has been reset (0) bnxt_en 0000:04:00.0 enp4s0f0np0: PCI Slot Reset bnxt_en 0000:04:00.0: enabling device (0000 -> 0002) bnxt_en 0000:04:00.0: Firmware not ready bnxt_en 0000:04:00.1 enp4s0f1np1: PCI Slot Reset bnxt_en 0000:04:00.1: enabling device (0000 -> 0002) bnxt_en 0000:04:00.1: Firmware not ready pcieport 0000:00:02.0: AER: device recovery failed Fixes: a432a45bdba4 ("bnxt_en: Define basic P7 macros") Signed-off-by: Michael Chan Signed-off-by: David S. Miller --- drivers/net/ethernet/broadcom/bnxt/bnxt.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.c b/drivers/net/ethernet/broadcom/bnxt/bnxt.c index 86c1c30c70d5..ed04a90a4fdd 100644 --- a/drivers/net/ethernet/broadcom/bnxt/bnxt.c +++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.c @@ -9089,7 +9089,7 @@ static void bnxt_try_map_fw_health_reg(struct bnxt *bp) BNXT_FW_HEALTH_WIN_BASE + BNXT_GRC_REG_CHIP_NUM); } - if (!BNXT_CHIP_P5(bp)) + if (!BNXT_CHIP_P5_PLUS(bp)) return; status_loc = BNXT_GRC_REG_STATUS_P5 | -- cgit v1.2.3 From d05dcfdf5e1659b2949d13060284eff3888b644e Mon Sep 17 00:00:00 2001 From: Eric Van Hensbergen Date: Mon, 15 Apr 2024 20:24:37 +0000 Subject: fs/9p: mitigate inode collisions Detect and mitigate inode collsions that now occur since we fixed 9p generating duplicate inode structures. Underlying cause of these appears to be a race condition between reuse of inode numbers in underlying file system and cleanup of inode numbers in the client. Enabling caching makes this much more likely to happen as it increases cleanup latency due to writebacks. Reported-by: Kent Overstreet Signed-off-by: Eric Van Hensbergen --- fs/9p/v9fs.h | 11 ++++++----- fs/9p/vfs_inode.c | 37 +++++++++++++++++++++++++++++-------- fs/9p/vfs_inode_dotl.c | 28 ++++++++++++++++++++-------- fs/9p/vfs_super.c | 2 +- 4 files changed, 56 insertions(+), 22 deletions(-) diff --git a/fs/9p/v9fs.h b/fs/9p/v9fs.h index 9defa12208f9..1775fcc7f0e8 100644 --- a/fs/9p/v9fs.h +++ b/fs/9p/v9fs.h @@ -179,13 +179,14 @@ extern int v9fs_vfs_rename(struct mnt_idmap *idmap, struct inode *old_dir, struct dentry *old_dentry, struct inode *new_dir, struct dentry *new_dentry, unsigned int flags); -extern struct inode *v9fs_fid_iget(struct super_block *sb, struct p9_fid *fid); +extern struct inode *v9fs_fid_iget(struct super_block *sb, struct p9_fid *fid, + bool new); extern const struct inode_operations v9fs_dir_inode_operations_dotl; extern const struct inode_operations v9fs_file_inode_operations_dotl; extern const struct inode_operations v9fs_symlink_inode_operations_dotl; extern const struct netfs_request_ops v9fs_req_ops; extern struct inode *v9fs_fid_iget_dotl(struct super_block *sb, - struct p9_fid *fid); + struct p9_fid *fid, bool new); /* other default globals */ #define V9FS_PORT 564 @@ -224,12 +225,12 @@ static inline int v9fs_proto_dotl(struct v9fs_session_info *v9ses) */ static inline struct inode * v9fs_get_inode_from_fid(struct v9fs_session_info *v9ses, struct p9_fid *fid, - struct super_block *sb) + struct super_block *sb, bool new) { if (v9fs_proto_dotl(v9ses)) - return v9fs_fid_iget_dotl(sb, fid); + return v9fs_fid_iget_dotl(sb, fid, new); else - return v9fs_fid_iget(sb, fid); + return v9fs_fid_iget(sb, fid, new); } #endif diff --git a/fs/9p/vfs_inode.c b/fs/9p/vfs_inode.c index 47bd77199e20..7a3308d77606 100644 --- a/fs/9p/vfs_inode.c +++ b/fs/9p/vfs_inode.c @@ -364,7 +364,8 @@ void v9fs_evict_inode(struct inode *inode) clear_inode(inode); } -struct inode *v9fs_fid_iget(struct super_block *sb, struct p9_fid *fid) +struct inode * +v9fs_fid_iget(struct super_block *sb, struct p9_fid *fid, bool new) { dev_t rdev; int retval; @@ -376,8 +377,18 @@ struct inode *v9fs_fid_iget(struct super_block *sb, struct p9_fid *fid) inode = iget_locked(sb, QID2INO(&fid->qid)); if (unlikely(!inode)) return ERR_PTR(-ENOMEM); - if (!(inode->i_state & I_NEW)) - return inode; + if (!(inode->i_state & I_NEW)) { + if (!new) { + goto done; + } else { + p9_debug(P9_DEBUG_VFS, "WARNING: Inode collision %ld\n", + inode->i_ino); + iput(inode); + remove_inode_hash(inode); + inode = iget_locked(sb, QID2INO(&fid->qid)); + WARN_ON(!(inode->i_state & I_NEW)); + } + } /* * initialize the inode with the stat info @@ -401,11 +412,11 @@ struct inode *v9fs_fid_iget(struct super_block *sb, struct p9_fid *fid) v9fs_set_netfs_context(inode); v9fs_cache_inode_get_cookie(inode); unlock_new_inode(inode); +done: return inode; error: iget_failed(inode); return ERR_PTR(retval); - } /** @@ -437,8 +448,15 @@ static int v9fs_at_to_dotl_flags(int flags) */ static void v9fs_dec_count(struct inode *inode) { - if (!S_ISDIR(inode->i_mode) || inode->i_nlink > 2) - drop_nlink(inode); + if (!S_ISDIR(inode->i_mode) || inode->i_nlink > 2) { + if (inode->i_nlink) { + drop_nlink(inode); + } else { + p9_debug(P9_DEBUG_VFS, + "WARNING: unexpected i_nlink zero %d inode %ld\n", + inode->i_nlink, inode->i_ino); + } + } } /** @@ -489,6 +507,9 @@ static int v9fs_remove(struct inode *dir, struct dentry *dentry, int flags) } else v9fs_dec_count(inode); + if (inode->i_nlink <= 0) /* no more refs unhash it */ + remove_inode_hash(inode); + v9fs_invalidate_inode_attr(inode); v9fs_invalidate_inode_attr(dir); @@ -554,7 +575,7 @@ v9fs_create(struct v9fs_session_info *v9ses, struct inode *dir, /* * instantiate inode and assign the unopened fid to the dentry */ - inode = v9fs_get_inode_from_fid(v9ses, fid, dir->i_sb); + inode = v9fs_get_inode_from_fid(v9ses, fid, dir->i_sb, true); if (IS_ERR(inode)) { err = PTR_ERR(inode); p9_debug(P9_DEBUG_VFS, @@ -683,7 +704,7 @@ struct dentry *v9fs_vfs_lookup(struct inode *dir, struct dentry *dentry, else if (IS_ERR(fid)) inode = ERR_CAST(fid); else - inode = v9fs_get_inode_from_fid(v9ses, fid, dir->i_sb); + inode = v9fs_get_inode_from_fid(v9ses, fid, dir->i_sb, false); /* * If we had a rename on the server and a parallel lookup * for the new name, then make sure we instantiate with diff --git a/fs/9p/vfs_inode_dotl.c b/fs/9p/vfs_inode_dotl.c index 55dde186041a..c61b97bd13b9 100644 --- a/fs/9p/vfs_inode_dotl.c +++ b/fs/9p/vfs_inode_dotl.c @@ -52,7 +52,10 @@ static kgid_t v9fs_get_fsgid_for_create(struct inode *dir_inode) return current_fsgid(); } -struct inode *v9fs_fid_iget_dotl(struct super_block *sb, struct p9_fid *fid) + + +struct inode * +v9fs_fid_iget_dotl(struct super_block *sb, struct p9_fid *fid, bool new) { int retval; struct inode *inode; @@ -62,8 +65,18 @@ struct inode *v9fs_fid_iget_dotl(struct super_block *sb, struct p9_fid *fid) inode = iget_locked(sb, QID2INO(&fid->qid)); if (unlikely(!inode)) return ERR_PTR(-ENOMEM); - if (!(inode->i_state & I_NEW)) - return inode; + if (!(inode->i_state & I_NEW)) { + if (!new) { + goto done; + } else { /* deal with race condition in inode number reuse */ + p9_debug(P9_DEBUG_ERROR, "WARNING: Inode collision %lx\n", + inode->i_ino); + iput(inode); + remove_inode_hash(inode); + inode = iget_locked(sb, QID2INO(&fid->qid)); + WARN_ON(!(inode->i_state & I_NEW)); + } + } /* * initialize the inode with the stat info @@ -90,12 +103,11 @@ struct inode *v9fs_fid_iget_dotl(struct super_block *sb, struct p9_fid *fid) goto error; unlock_new_inode(inode); - +done: return inode; error: iget_failed(inode); return ERR_PTR(retval); - } struct dotl_openflag_map { @@ -247,7 +259,7 @@ v9fs_vfs_atomic_open_dotl(struct inode *dir, struct dentry *dentry, p9_debug(P9_DEBUG_VFS, "p9_client_walk failed %d\n", err); goto out; } - inode = v9fs_fid_iget_dotl(dir->i_sb, fid); + inode = v9fs_fid_iget_dotl(dir->i_sb, fid, true); if (IS_ERR(inode)) { err = PTR_ERR(inode); p9_debug(P9_DEBUG_VFS, "inode creation failed %d\n", err); @@ -340,7 +352,7 @@ static int v9fs_vfs_mkdir_dotl(struct mnt_idmap *idmap, } /* instantiate inode and assign the unopened fid to the dentry */ - inode = v9fs_fid_iget_dotl(dir->i_sb, fid); + inode = v9fs_fid_iget_dotl(dir->i_sb, fid, true); if (IS_ERR(inode)) { err = PTR_ERR(inode); p9_debug(P9_DEBUG_VFS, "inode creation failed %d\n", @@ -776,7 +788,7 @@ v9fs_vfs_mknod_dotl(struct mnt_idmap *idmap, struct inode *dir, err); goto error; } - inode = v9fs_fid_iget_dotl(dir->i_sb, fid); + inode = v9fs_fid_iget_dotl(dir->i_sb, fid, true); if (IS_ERR(inode)) { err = PTR_ERR(inode); p9_debug(P9_DEBUG_VFS, "inode creation failed %d\n", diff --git a/fs/9p/vfs_super.c b/fs/9p/vfs_super.c index 55e67e36ae68..f52fdf42945c 100644 --- a/fs/9p/vfs_super.c +++ b/fs/9p/vfs_super.c @@ -139,7 +139,7 @@ static struct dentry *v9fs_mount(struct file_system_type *fs_type, int flags, else sb->s_d_op = &v9fs_dentry_operations; - inode = v9fs_get_inode_from_fid(v9ses, fid, sb); + inode = v9fs_get_inode_from_fid(v9ses, fid, sb, true); if (IS_ERR(inode)) { retval = PTR_ERR(inode); goto release_sb; -- cgit v1.2.3 From 77d8aa79ecfb209308e0644c02f655122b31def7 Mon Sep 17 00:00:00 2001 From: Takayuki Nagata Date: Mon, 15 Apr 2024 16:47:49 +0900 Subject: cifs: reinstate original behavior again for forceuid/forcegid forceuid/forcegid should be enabled by default when uid=/gid= options are specified, but commit 24e0a1eff9e2 ("cifs: switch to new mount api") changed the behavior. Due to the change, a mounted share does not show intentional uid/gid for files and directories even though uid=/gid= options are specified since forceuid/forcegid are not enabled. This patch reinstates original behavior that overrides uid/gid with specified uid/gid by the options. Fixes: 24e0a1eff9e2 ("cifs: switch to new mount api") Signed-off-by: Takayuki Nagata Acked-by: Paulo Alcantara (Red Hat) Acked-by: Ronnie Sahlberg Acked-by: Tom Talpey Signed-off-by: Steve French --- fs/smb/client/fs_context.c | 12 ++++++++++++ fs/smb/client/fs_context.h | 2 ++ 2 files changed, 14 insertions(+) diff --git a/fs/smb/client/fs_context.c b/fs/smb/client/fs_context.c index 6c727d8c31e8..3bbac925d076 100644 --- a/fs/smb/client/fs_context.c +++ b/fs/smb/client/fs_context.c @@ -748,6 +748,16 @@ static int smb3_fs_context_validate(struct fs_context *fc) /* set the port that we got earlier */ cifs_set_port((struct sockaddr *)&ctx->dstaddr, ctx->port); + if (ctx->uid_specified && !ctx->forceuid_specified) { + ctx->override_uid = 1; + pr_notice("enabling forceuid mount option implicitly because uid= option is specified\n"); + } + + if (ctx->gid_specified && !ctx->forcegid_specified) { + ctx->override_gid = 1; + pr_notice("enabling forcegid mount option implicitly because gid= option is specified\n"); + } + if (ctx->override_uid && !ctx->uid_specified) { ctx->override_uid = 0; pr_notice("ignoring forceuid mount option specified with no uid= option\n"); @@ -1019,12 +1029,14 @@ static int smb3_fs_context_parse_param(struct fs_context *fc, ctx->override_uid = 0; else ctx->override_uid = 1; + ctx->forceuid_specified = true; break; case Opt_forcegid: if (result.negated) ctx->override_gid = 0; else ctx->override_gid = 1; + ctx->forcegid_specified = true; break; case Opt_perm: if (result.negated) diff --git a/fs/smb/client/fs_context.h b/fs/smb/client/fs_context.h index a947bddeba27..cf577ec0dd0a 100644 --- a/fs/smb/client/fs_context.h +++ b/fs/smb/client/fs_context.h @@ -165,6 +165,8 @@ enum cifs_param { }; struct smb3_fs_context { + bool forceuid_specified; + bool forcegid_specified; bool uid_specified; bool cruid_specified; bool gid_specified; -- cgit v1.2.3 From 05d92ee782eeb7b939bdd0189e6efcab9195bf95 Mon Sep 17 00:00:00 2001 From: Jarred White Date: Mon, 8 Apr 2024 22:23:09 -0700 Subject: ACPI: CPPC: Fix bit_offset shift in MASK_VAL() macro Commit 2f4a4d63a193 ("ACPI: CPPC: Use access_width over bit_width for system memory accesses") neglected to properly wrap the bit_offset shift when it comes to applying the mask. This may cause incorrect values to be read and may cause the cpufreq module not be loaded. [ 11.059751] cpu_capacity: CPU0 missing/invalid highest performance. [ 11.066005] cpu_capacity: partial information: fallback to 1024 for all CPUs Also, corrected the bitmask generation in GENMASK (extra bit being added). Fixes: 2f4a4d63a193 ("ACPI: CPPC: Use access_width over bit_width for system memory accesses") Signed-off-by: Jarred White Cc: 5.15+ # 5.15+ Reviewed-by: Vanshidhar Konda Signed-off-by: Rafael J. Wysocki --- drivers/acpi/cppc_acpi.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/acpi/cppc_acpi.c b/drivers/acpi/cppc_acpi.c index 4bfbe55553f4..00a30ca35e78 100644 --- a/drivers/acpi/cppc_acpi.c +++ b/drivers/acpi/cppc_acpi.c @@ -170,8 +170,8 @@ show_cppc_data(cppc_get_perf_ctrs, cppc_perf_fb_ctrs, wraparound_time); #define GET_BIT_WIDTH(reg) ((reg)->access_width ? (8 << ((reg)->access_width - 1)) : (reg)->bit_width) /* Shift and apply the mask for CPC reads/writes */ -#define MASK_VAL(reg, val) ((val) >> ((reg)->bit_offset & \ - GENMASK(((reg)->bit_width), 0))) +#define MASK_VAL(reg, val) (((val) >> (reg)->bit_offset) & \ + GENMASK(((reg)->bit_width) - 1, 0)) static ssize_t show_feedback_ctrs(struct kobject *kobj, struct kobj_attribute *attr, char *buf) -- cgit v1.2.3 From f489c948028b69cea235d9c0de1cc10eeb26a172 Mon Sep 17 00:00:00 2001 From: Vanshidhar Konda Date: Thu, 11 Apr 2024 16:18:44 -0700 Subject: ACPI: CPPC: Fix access width used for PCC registers commit 2f4a4d63a193 ("ACPI: CPPC: Use access_width over bit_width for system memory accesses") modified cpc_read()/cpc_write() to use access_width to read CPC registers. However, for PCC registers the access width field in the ACPI register macro specifies the PCC subspace ID. For non-zero PCC subspace ID it is incorrectly treated as access width. This causes errors when reading from PCC registers in the CPPC driver. For PCC registers, base the size of read/write on the bit width field. The debug message in cpc_read()/cpc_write() is updated to print relevant information for the address space type used to read the register. Fixes: 2f4a4d63a193 ("ACPI: CPPC: Use access_width over bit_width for system memory accesses") Signed-off-by: Vanshidhar Konda Tested-by: Jarred White Reviewed-by: Jarred White Reviewed-by: Easwar Hariharan Cc: 5.15+ # 5.15+ Signed-off-by: Rafael J. Wysocki --- drivers/acpi/cppc_acpi.c | 53 +++++++++++++++++++++++++++++++++--------------- 1 file changed, 37 insertions(+), 16 deletions(-) diff --git a/drivers/acpi/cppc_acpi.c b/drivers/acpi/cppc_acpi.c index 00a30ca35e78..a40b6f3946ef 100644 --- a/drivers/acpi/cppc_acpi.c +++ b/drivers/acpi/cppc_acpi.c @@ -1002,14 +1002,14 @@ static int cpc_read(int cpu, struct cpc_register_resource *reg_res, u64 *val) } *val = 0; + size = GET_BIT_WIDTH(reg); if (reg->space_id == ACPI_ADR_SPACE_SYSTEM_IO) { - u32 width = GET_BIT_WIDTH(reg); u32 val_u32; acpi_status status; status = acpi_os_read_port((acpi_io_address)reg->address, - &val_u32, width); + &val_u32, size); if (ACPI_FAILURE(status)) { pr_debug("Error: Failed to read SystemIO port %llx\n", reg->address); @@ -1018,17 +1018,22 @@ static int cpc_read(int cpu, struct cpc_register_resource *reg_res, u64 *val) *val = val_u32; return 0; - } else if (reg->space_id == ACPI_ADR_SPACE_PLATFORM_COMM && pcc_ss_id >= 0) + } else if (reg->space_id == ACPI_ADR_SPACE_PLATFORM_COMM && pcc_ss_id >= 0) { + /* + * For registers in PCC space, the register size is determined + * by the bit width field; the access size is used to indicate + * the PCC subspace id. + */ + size = reg->bit_width; vaddr = GET_PCC_VADDR(reg->address, pcc_ss_id); + } else if (reg->space_id == ACPI_ADR_SPACE_SYSTEM_MEMORY) vaddr = reg_res->sys_mem_vaddr; else if (reg->space_id == ACPI_ADR_SPACE_FIXED_HARDWARE) return cpc_read_ffh(cpu, reg, val); else return acpi_os_read_memory((acpi_physical_address)reg->address, - val, reg->bit_width); - - size = GET_BIT_WIDTH(reg); + val, size); switch (size) { case 8: @@ -1044,8 +1049,13 @@ static int cpc_read(int cpu, struct cpc_register_resource *reg_res, u64 *val) *val = readq_relaxed(vaddr); break; default: - pr_debug("Error: Cannot read %u bit width from PCC for ss: %d\n", - reg->bit_width, pcc_ss_id); + if (reg->space_id == ACPI_ADR_SPACE_SYSTEM_MEMORY) { + pr_debug("Error: Cannot read %u bit width from system memory: 0x%llx\n", + size, reg->address); + } else if (reg->space_id == ACPI_ADR_SPACE_PLATFORM_COMM) { + pr_debug("Error: Cannot read %u bit width from PCC for ss: %d\n", + size, pcc_ss_id); + } return -EFAULT; } @@ -1063,12 +1073,13 @@ static int cpc_write(int cpu, struct cpc_register_resource *reg_res, u64 val) int pcc_ss_id = per_cpu(cpu_pcc_subspace_idx, cpu); struct cpc_reg *reg = ®_res->cpc_entry.reg; + size = GET_BIT_WIDTH(reg); + if (reg->space_id == ACPI_ADR_SPACE_SYSTEM_IO) { - u32 width = GET_BIT_WIDTH(reg); acpi_status status; status = acpi_os_write_port((acpi_io_address)reg->address, - (u32)val, width); + (u32)val, size); if (ACPI_FAILURE(status)) { pr_debug("Error: Failed to write SystemIO port %llx\n", reg->address); @@ -1076,17 +1087,22 @@ static int cpc_write(int cpu, struct cpc_register_resource *reg_res, u64 val) } return 0; - } else if (reg->space_id == ACPI_ADR_SPACE_PLATFORM_COMM && pcc_ss_id >= 0) + } else if (reg->space_id == ACPI_ADR_SPACE_PLATFORM_COMM && pcc_ss_id >= 0) { + /* + * For registers in PCC space, the register size is determined + * by the bit width field; the access size is used to indicate + * the PCC subspace id. + */ + size = reg->bit_width; vaddr = GET_PCC_VADDR(reg->address, pcc_ss_id); + } else if (reg->space_id == ACPI_ADR_SPACE_SYSTEM_MEMORY) vaddr = reg_res->sys_mem_vaddr; else if (reg->space_id == ACPI_ADR_SPACE_FIXED_HARDWARE) return cpc_write_ffh(cpu, reg, val); else return acpi_os_write_memory((acpi_physical_address)reg->address, - val, reg->bit_width); - - size = GET_BIT_WIDTH(reg); + val, size); if (reg->space_id == ACPI_ADR_SPACE_SYSTEM_MEMORY) val = MASK_VAL(reg, val); @@ -1105,8 +1121,13 @@ static int cpc_write(int cpu, struct cpc_register_resource *reg_res, u64 val) writeq_relaxed(val, vaddr); break; default: - pr_debug("Error: Cannot write %u bit width to PCC for ss: %d\n", - reg->bit_width, pcc_ss_id); + if (reg->space_id == ACPI_ADR_SPACE_SYSTEM_MEMORY) { + pr_debug("Error: Cannot write %u bit width to system memory: 0x%llx\n", + size, reg->address); + } else if (reg->space_id == ACPI_ADR_SPACE_PLATFORM_COMM) { + pr_debug("Error: Cannot write %u bit width to PCC for ss: %d\n", + size, pcc_ss_id); + } ret_val = -EFAULT; break; } -- cgit v1.2.3 From a4e3899065ffa87d49dc20e8c17501edbc189692 Mon Sep 17 00:00:00 2001 From: Matthias Schiffer Date: Wed, 17 Apr 2024 12:37:37 +0200 Subject: net: dsa: mv88e6xx: fix supported_interfaces setup in mv88e6250_phylink_get_caps() With the recent PHYLINK changes requiring supported_interfaces to be set, MV88E6250 family switches like the 88E6020 fail to probe - cmode is never initialized on these devices, so mv88e6250_phylink_get_caps() does not set any supported_interfaces flags. Instead of a cmode, on 88E6250 we have a read-only port mode value that encodes similar information. There is no reason to bother mapping port mode to the cmodes of other switch models; instead we introduce a mv88e6250_setup_supported_interfaces() that is called directly from mv88e6250_phylink_get_caps(). Fixes: de5c9bf40c45 ("net: phylink: require supported_interfaces to be filled") Signed-off-by: Matthias Schiffer Link: https://lore.kernel.org/r/20240417103737.166651-1-matthias.schiffer@ew.tq-group.com Signed-off-by: Jakub Kicinski --- drivers/net/dsa/mv88e6xxx/chip.c | 56 +++++++++++++++++++++++++++++++++++++--- drivers/net/dsa/mv88e6xxx/port.h | 23 ++++++++++++++--- 2 files changed, 71 insertions(+), 8 deletions(-) diff --git a/drivers/net/dsa/mv88e6xxx/chip.c b/drivers/net/dsa/mv88e6xxx/chip.c index c95787cb9086..59b5dd0e2f41 100644 --- a/drivers/net/dsa/mv88e6xxx/chip.c +++ b/drivers/net/dsa/mv88e6xxx/chip.c @@ -566,13 +566,61 @@ static void mv88e6xxx_translate_cmode(u8 cmode, unsigned long *supported) phy_interface_set_rgmii(supported); } -static void mv88e6250_phylink_get_caps(struct mv88e6xxx_chip *chip, int port, - struct phylink_config *config) +static void +mv88e6250_setup_supported_interfaces(struct mv88e6xxx_chip *chip, int port, + struct phylink_config *config) { unsigned long *supported = config->supported_interfaces; + int err; + u16 reg; - /* Translate the default cmode */ - mv88e6xxx_translate_cmode(chip->ports[port].cmode, supported); + err = mv88e6xxx_port_read(chip, port, MV88E6XXX_PORT_STS, ®); + if (err) { + dev_err(chip->dev, "p%d: failed to read port status\n", port); + return; + } + + switch (reg & MV88E6250_PORT_STS_PORTMODE_MASK) { + case MV88E6250_PORT_STS_PORTMODE_MII_10_HALF_PHY: + case MV88E6250_PORT_STS_PORTMODE_MII_100_HALF_PHY: + case MV88E6250_PORT_STS_PORTMODE_MII_10_FULL_PHY: + case MV88E6250_PORT_STS_PORTMODE_MII_100_FULL_PHY: + __set_bit(PHY_INTERFACE_MODE_REVMII, supported); + break; + + case MV88E6250_PORT_STS_PORTMODE_MII_HALF: + case MV88E6250_PORT_STS_PORTMODE_MII_FULL: + __set_bit(PHY_INTERFACE_MODE_MII, supported); + break; + + case MV88E6250_PORT_STS_PORTMODE_MII_DUAL_100_RMII_FULL_PHY: + case MV88E6250_PORT_STS_PORTMODE_MII_200_RMII_FULL_PHY: + case MV88E6250_PORT_STS_PORTMODE_MII_10_100_RMII_HALF_PHY: + case MV88E6250_PORT_STS_PORTMODE_MII_10_100_RMII_FULL_PHY: + __set_bit(PHY_INTERFACE_MODE_REVRMII, supported); + break; + + case MV88E6250_PORT_STS_PORTMODE_MII_DUAL_100_RMII_FULL: + case MV88E6250_PORT_STS_PORTMODE_MII_10_100_RMII_FULL: + __set_bit(PHY_INTERFACE_MODE_RMII, supported); + break; + + case MV88E6250_PORT_STS_PORTMODE_MII_100_RGMII: + __set_bit(PHY_INTERFACE_MODE_RGMII, supported); + break; + + default: + dev_err(chip->dev, + "p%d: invalid port mode in status register: %04x\n", + port, reg); + } +} + +static void mv88e6250_phylink_get_caps(struct mv88e6xxx_chip *chip, int port, + struct phylink_config *config) +{ + if (!mv88e6xxx_phy_is_internal(chip, port)) + mv88e6250_setup_supported_interfaces(chip, port, config); config->mac_capabilities = MAC_SYM_PAUSE | MAC_10 | MAC_100; } diff --git a/drivers/net/dsa/mv88e6xxx/port.h b/drivers/net/dsa/mv88e6xxx/port.h index 86deeb347cbc..ddadeb9bfdae 100644 --- a/drivers/net/dsa/mv88e6xxx/port.h +++ b/drivers/net/dsa/mv88e6xxx/port.h @@ -25,10 +25,25 @@ #define MV88E6250_PORT_STS_PORTMODE_PHY_100_HALF 0x0900 #define MV88E6250_PORT_STS_PORTMODE_PHY_10_FULL 0x0a00 #define MV88E6250_PORT_STS_PORTMODE_PHY_100_FULL 0x0b00 -#define MV88E6250_PORT_STS_PORTMODE_MII_10_HALF 0x0c00 -#define MV88E6250_PORT_STS_PORTMODE_MII_100_HALF 0x0d00 -#define MV88E6250_PORT_STS_PORTMODE_MII_10_FULL 0x0e00 -#define MV88E6250_PORT_STS_PORTMODE_MII_100_FULL 0x0f00 +/* - Modes with PHY suffix use output instead of input clock + * - Modes without RMII or RGMII use MII + * - Modes without speed do not have a fixed speed specified in the manual + * ("DC to x MHz" - variable clock support?) + */ +#define MV88E6250_PORT_STS_PORTMODE_MII_DISABLED 0x0000 +#define MV88E6250_PORT_STS_PORTMODE_MII_100_RGMII 0x0100 +#define MV88E6250_PORT_STS_PORTMODE_MII_DUAL_100_RMII_FULL_PHY 0x0200 +#define MV88E6250_PORT_STS_PORTMODE_MII_200_RMII_FULL_PHY 0x0400 +#define MV88E6250_PORT_STS_PORTMODE_MII_DUAL_100_RMII_FULL 0x0600 +#define MV88E6250_PORT_STS_PORTMODE_MII_10_100_RMII_FULL 0x0700 +#define MV88E6250_PORT_STS_PORTMODE_MII_HALF 0x0800 +#define MV88E6250_PORT_STS_PORTMODE_MII_10_100_RMII_HALF_PHY 0x0900 +#define MV88E6250_PORT_STS_PORTMODE_MII_FULL 0x0a00 +#define MV88E6250_PORT_STS_PORTMODE_MII_10_100_RMII_FULL_PHY 0x0b00 +#define MV88E6250_PORT_STS_PORTMODE_MII_10_HALF_PHY 0x0c00 +#define MV88E6250_PORT_STS_PORTMODE_MII_100_HALF_PHY 0x0d00 +#define MV88E6250_PORT_STS_PORTMODE_MII_10_FULL_PHY 0x0e00 +#define MV88E6250_PORT_STS_PORTMODE_MII_100_FULL_PHY 0x0f00 #define MV88E6XXX_PORT_STS_LINK 0x0800 #define MV88E6XXX_PORT_STS_DUPLEX 0x0400 #define MV88E6XXX_PORT_STS_SPEED_MASK 0x0300 -- cgit v1.2.3 From 98a821546b3919a10a58faa12ebe5e9a55cd638e Mon Sep 17 00:00:00 2001 From: Zhu Lingshan Date: Mon, 15 Apr 2024 19:10:47 +0800 Subject: vDPA: code clean for vhost_vdpa uapi This commit cleans up the uapi for vhost_vdpa by better naming some of the enums which report blk information to user space, and they are not in any official releases yet. Fixes: 1ac61ddfee93 ("vDPA: report virtio-blk flush info to user space") Fixes: ae1374b7f72c ("vDPA: report virtio-block read-only info to user space") Fixes: 330b8aea6924 ("vDPA: report virtio-block max segment size to user space") Signed-off-by: Zhu Lingshan Message-Id: <20240415111047.1047774-1-lingshan.zhu@intel.com> Signed-off-by: Michael S. Tsirkin --- drivers/vdpa/vdpa.c | 6 +++--- include/uapi/linux/vdpa.h | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/vdpa/vdpa.c b/drivers/vdpa/vdpa.c index b246067e074b..6cb96a1e8b7d 100644 --- a/drivers/vdpa/vdpa.c +++ b/drivers/vdpa/vdpa.c @@ -967,7 +967,7 @@ vdpa_dev_blk_seg_size_config_fill(struct sk_buff *msg, u64 features, val_u32 = __virtio32_to_cpu(true, config->size_max); - return nla_put_u32(msg, VDPA_ATTR_DEV_BLK_CFG_SEG_SIZE, val_u32); + return nla_put_u32(msg, VDPA_ATTR_DEV_BLK_CFG_SIZE_MAX, val_u32); } /* fill the block size*/ @@ -1089,7 +1089,7 @@ static int vdpa_dev_blk_ro_config_fill(struct sk_buff *msg, u64 features) u8 ro; ro = ((features & BIT_ULL(VIRTIO_BLK_F_RO)) == 0) ? 0 : 1; - if (nla_put_u8(msg, VDPA_ATTR_DEV_BLK_CFG_READ_ONLY, ro)) + if (nla_put_u8(msg, VDPA_ATTR_DEV_BLK_READ_ONLY, ro)) return -EMSGSIZE; return 0; @@ -1100,7 +1100,7 @@ static int vdpa_dev_blk_flush_config_fill(struct sk_buff *msg, u64 features) u8 flush; flush = ((features & BIT_ULL(VIRTIO_BLK_F_FLUSH)) == 0) ? 0 : 1; - if (nla_put_u8(msg, VDPA_ATTR_DEV_BLK_CFG_FLUSH, flush)) + if (nla_put_u8(msg, VDPA_ATTR_DEV_BLK_FLUSH, flush)) return -EMSGSIZE; return 0; diff --git a/include/uapi/linux/vdpa.h b/include/uapi/linux/vdpa.h index 43c51698195c..842bf1201ac4 100644 --- a/include/uapi/linux/vdpa.h +++ b/include/uapi/linux/vdpa.h @@ -57,7 +57,7 @@ enum vdpa_attr { VDPA_ATTR_DEV_FEATURES, /* u64 */ VDPA_ATTR_DEV_BLK_CFG_CAPACITY, /* u64 */ - VDPA_ATTR_DEV_BLK_CFG_SEG_SIZE, /* u32 */ + VDPA_ATTR_DEV_BLK_CFG_SIZE_MAX, /* u32 */ VDPA_ATTR_DEV_BLK_CFG_BLK_SIZE, /* u32 */ VDPA_ATTR_DEV_BLK_CFG_SEG_MAX, /* u32 */ VDPA_ATTR_DEV_BLK_CFG_NUM_QUEUES, /* u16 */ @@ -70,8 +70,8 @@ enum vdpa_attr { VDPA_ATTR_DEV_BLK_CFG_DISCARD_SEC_ALIGN,/* u32 */ VDPA_ATTR_DEV_BLK_CFG_MAX_WRITE_ZEROES_SEC, /* u32 */ VDPA_ATTR_DEV_BLK_CFG_MAX_WRITE_ZEROES_SEG, /* u32 */ - VDPA_ATTR_DEV_BLK_CFG_READ_ONLY, /* u8 */ - VDPA_ATTR_DEV_BLK_CFG_FLUSH, /* u8 */ + VDPA_ATTR_DEV_BLK_READ_ONLY, /* u8 */ + VDPA_ATTR_DEV_BLK_FLUSH, /* u8 */ /* new attributes must be added above here */ VDPA_ATTR_MAX, -- cgit v1.2.3 From 97ec32b583bb08f72146eee2c1a1918e05760f8c Mon Sep 17 00:00:00 2001 From: David Christensen Date: Thu, 18 Apr 2024 15:55:17 -0400 Subject: MAINTAINERS: eth: mark IBM eHEA as an Orphan Current maintainer Douglas Miller has left IBM and no replacement has been assigned for the driver. The eHEA hardware was last used on IBM POWER7 systems, the last of which reached end-of-support at the end of 2020. Signed-off-by: David Christensen Reviewed-by: Pradeep Satyanarayana Acked-by: Michael Ellerman (powerpc) Link: https://lore.kernel.org/r/20240418195517.528577-1-drc@linux.ibm.com Signed-off-by: Jakub Kicinski --- MAINTAINERS | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/MAINTAINERS b/MAINTAINERS index c23fda1aa1f0..2d5acd6d98c4 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -7829,9 +7829,8 @@ W: http://aeschi.ch.eu.org/efs/ F: fs/efs/ EHEA (IBM pSeries eHEA 10Gb ethernet adapter) DRIVER -M: Douglas Miller L: netdev@vger.kernel.org -S: Maintained +S: Orphan F: drivers/net/ethernet/ibm/ehea/ ELM327 CAN NETWORK DRIVER -- cgit v1.2.3 From 6bea4f03c6a4e973ef369e15aac88f37981db49e Mon Sep 17 00:00:00 2001 From: Paul Geurts Date: Thu, 18 Apr 2024 21:25:38 +0200 Subject: NFC: trf7970a: disable all regulators on removal During module probe, regulator 'vin' and 'vdd-io' are used and enabled, but the vdd-io regulator overwrites the 'vin' regulator pointer. During remove, only the vdd-io is disabled, as the vin regulator pointer is not available anymore. When regulator_put() is called during resource cleanup a kernel warning is given, as the regulator is still enabled. Store the two regulators in separate pointers and disable both the regulators on module remove. Fixes: 49d22c70aaf0 ("NFC: trf7970a: Add device tree option of 1.8 Volt IO voltage") Signed-off-by: Paul Geurts Reviewed-by: Krzysztof Kozlowski Link: https://lore.kernel.org/r/DB7PR09MB26847A4EBF88D9EDFEB1DA0F950E2@DB7PR09MB2684.eurprd09.prod.outlook.com Signed-off-by: Jakub Kicinski --- drivers/nfc/trf7970a.c | 42 +++++++++++++++++++++++------------------- 1 file changed, 23 insertions(+), 19 deletions(-) diff --git a/drivers/nfc/trf7970a.c b/drivers/nfc/trf7970a.c index 7eb17f46a815..9e1a34e23af2 100644 --- a/drivers/nfc/trf7970a.c +++ b/drivers/nfc/trf7970a.c @@ -424,7 +424,8 @@ struct trf7970a { enum trf7970a_state state; struct device *dev; struct spi_device *spi; - struct regulator *regulator; + struct regulator *vin_regulator; + struct regulator *vddio_regulator; struct nfc_digital_dev *ddev; u32 quirks; bool is_initiator; @@ -1883,7 +1884,7 @@ static int trf7970a_power_up(struct trf7970a *trf) if (trf->state != TRF7970A_ST_PWR_OFF) return 0; - ret = regulator_enable(trf->regulator); + ret = regulator_enable(trf->vin_regulator); if (ret) { dev_err(trf->dev, "%s - Can't enable VIN: %d\n", __func__, ret); return ret; @@ -1926,7 +1927,7 @@ static int trf7970a_power_down(struct trf7970a *trf) if (trf->en2_gpiod && !(trf->quirks & TRF7970A_QUIRK_EN2_MUST_STAY_LOW)) gpiod_set_value_cansleep(trf->en2_gpiod, 0); - ret = regulator_disable(trf->regulator); + ret = regulator_disable(trf->vin_regulator); if (ret) dev_err(trf->dev, "%s - Can't disable VIN: %d\n", __func__, ret); @@ -2065,37 +2066,37 @@ static int trf7970a_probe(struct spi_device *spi) mutex_init(&trf->lock); INIT_DELAYED_WORK(&trf->timeout_work, trf7970a_timeout_work_handler); - trf->regulator = devm_regulator_get(&spi->dev, "vin"); - if (IS_ERR(trf->regulator)) { - ret = PTR_ERR(trf->regulator); + trf->vin_regulator = devm_regulator_get(&spi->dev, "vin"); + if (IS_ERR(trf->vin_regulator)) { + ret = PTR_ERR(trf->vin_regulator); dev_err(trf->dev, "Can't get VIN regulator: %d\n", ret); goto err_destroy_lock; } - ret = regulator_enable(trf->regulator); + ret = regulator_enable(trf->vin_regulator); if (ret) { dev_err(trf->dev, "Can't enable VIN: %d\n", ret); goto err_destroy_lock; } - uvolts = regulator_get_voltage(trf->regulator); + uvolts = regulator_get_voltage(trf->vin_regulator); if (uvolts > 4000000) trf->chip_status_ctrl = TRF7970A_CHIP_STATUS_VRS5_3; - trf->regulator = devm_regulator_get(&spi->dev, "vdd-io"); - if (IS_ERR(trf->regulator)) { - ret = PTR_ERR(trf->regulator); + trf->vddio_regulator = devm_regulator_get(&spi->dev, "vdd-io"); + if (IS_ERR(trf->vddio_regulator)) { + ret = PTR_ERR(trf->vddio_regulator); dev_err(trf->dev, "Can't get VDD_IO regulator: %d\n", ret); - goto err_destroy_lock; + goto err_disable_vin_regulator; } - ret = regulator_enable(trf->regulator); + ret = regulator_enable(trf->vddio_regulator); if (ret) { dev_err(trf->dev, "Can't enable VDD_IO: %d\n", ret); - goto err_destroy_lock; + goto err_disable_vin_regulator; } - if (regulator_get_voltage(trf->regulator) == 1800000) { + if (regulator_get_voltage(trf->vddio_regulator) == 1800000) { trf->io_ctrl = TRF7970A_REG_IO_CTRL_IO_LOW; dev_dbg(trf->dev, "trf7970a config vdd_io to 1.8V\n"); } @@ -2108,7 +2109,7 @@ static int trf7970a_probe(struct spi_device *spi) if (!trf->ddev) { dev_err(trf->dev, "Can't allocate NFC digital device\n"); ret = -ENOMEM; - goto err_disable_regulator; + goto err_disable_vddio_regulator; } nfc_digital_set_parent_dev(trf->ddev, trf->dev); @@ -2137,8 +2138,10 @@ err_shutdown: trf7970a_shutdown(trf); err_free_ddev: nfc_digital_free_device(trf->ddev); -err_disable_regulator: - regulator_disable(trf->regulator); +err_disable_vddio_regulator: + regulator_disable(trf->vddio_regulator); +err_disable_vin_regulator: + regulator_disable(trf->vin_regulator); err_destroy_lock: mutex_destroy(&trf->lock); return ret; @@ -2157,7 +2160,8 @@ static void trf7970a_remove(struct spi_device *spi) nfc_digital_unregister_device(trf->ddev); nfc_digital_free_device(trf->ddev); - regulator_disable(trf->regulator); + regulator_disable(trf->vddio_regulator); + regulator_disable(trf->vin_regulator); mutex_destroy(&trf->lock); } -- cgit v1.2.3 From 3249c68e3cdacc2da8fe811a54f8db43df124c0e Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Mon, 22 Apr 2024 18:15:13 +0300 Subject: ASoC: soc.h: Don't use "proxy" headers Update header inclusions to follow IWYU (Include What You Use) principle. Signed-off-by: Andy Shevchenko Link: https://lore.kernel.org/r/20240422151513.2052167-1-andriy.shevchenko@linux.intel.com Signed-off-by: Mark Brown --- include/sound/soc.h | 30 ++++++++++++++++++++---------- 1 file changed, 20 insertions(+), 10 deletions(-) diff --git a/include/sound/soc.h b/include/sound/soc.h index 0376f7e4c15d..2a1b6c198547 100644 --- a/include/sound/soc.h +++ b/include/sound/soc.h @@ -11,20 +11,30 @@ #define __LINUX_SND_SOC_H #include +#include +#include +#include +#include +#include +#include +#include +#include #include -#include #include -#include #include -#include -#include -#include -#include -#include -#include + +#include #include #include -#include +#include +#include + +struct module; +struct platform_device; + +/* For the current users of sound/soc.h to avoid build issues */ +#include +#include /* * Convenience kcontrol builders @@ -412,7 +422,6 @@ #define SOC_ENUM_SINGLE_VIRT_DECL(name, xtexts) \ const struct soc_enum name = SOC_ENUM_SINGLE_VIRT(ARRAY_SIZE(xtexts), xtexts) -struct device_node; struct snd_jack; struct snd_soc_card; struct snd_soc_pcm_stream; @@ -427,6 +436,7 @@ struct soc_enum; struct snd_soc_jack; struct snd_soc_jack_zone; struct snd_soc_jack_pin; + #include #include #include -- cgit v1.2.3 From ab371a026a1a4ad81817d82ba433c19934082894 Mon Sep 17 00:00:00 2001 From: Kartik Agarwala Date: Sun, 21 Apr 2024 09:01:31 +0530 Subject: ASoC: dt-bindings: mt2701-wm8960: Convert to dtschema Convert mt2701-wm890 bindings from text to dtschema. This is used by MediaTek mt7623a/n SoC. Signed-off-by: Kartik Agarwala Reviewed-by: Rob Herring (Arm) Link: https://lore.kernel.org/r/20240421033129.13076-1-agarwala.kartik@gmail.com Signed-off-by: Mark Brown --- .../bindings/sound/mediatek,mt2701-wm8960.yaml | 54 ++++++++++++++++++++++ .../devicetree/bindings/sound/mt2701-wm8960.txt | 24 ---------- 2 files changed, 54 insertions(+), 24 deletions(-) create mode 100644 Documentation/devicetree/bindings/sound/mediatek,mt2701-wm8960.yaml delete mode 100644 Documentation/devicetree/bindings/sound/mt2701-wm8960.txt diff --git a/Documentation/devicetree/bindings/sound/mediatek,mt2701-wm8960.yaml b/Documentation/devicetree/bindings/sound/mediatek,mt2701-wm8960.yaml new file mode 100644 index 000000000000..cf985461a995 --- /dev/null +++ b/Documentation/devicetree/bindings/sound/mediatek,mt2701-wm8960.yaml @@ -0,0 +1,54 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/sound/mediatek,mt2701-wm8960.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: MediaTek MT2701 with WM8960 CODEC + +maintainers: + - Kartik Agarwala + +properties: + compatible: + const: mediatek,mt2701-wm8960-machine + + mediatek,platform: + $ref: /schemas/types.yaml#/definitions/phandle + description: The phandle of MT2701 ASoC platform. + + audio-routing: + $ref: /schemas/types.yaml#/definitions/non-unique-string-array + description: + A list of the connections between audio components. Each entry is a + pair of strings, the first being the connection's sink, the second + being the connection's source. + + mediatek,audio-codec: + $ref: /schemas/types.yaml#/definitions/phandle + description: The phandle of the WM8960 audio codec. + +unevaluatedProperties: false + +required: + - compatible + - mediatek,platform + - audio-routing + - mediatek,audio-codec + - pinctrl-names + - pinctrl-0 + +examples: + - | + sound { + compatible = "mediatek,mt2701-wm8960-machine"; + mediatek,platform = <&afe>; + audio-routing = + "Headphone", "HP_L", + "Headphone", "HP_R", + "LINPUT1", "AMIC", + "RINPUT1", "AMIC"; + mediatek,audio-codec = <&wm8960>; + pinctrl-names = "default"; + pinctrl-0 = <&aud_pins_default>; + }; diff --git a/Documentation/devicetree/bindings/sound/mt2701-wm8960.txt b/Documentation/devicetree/bindings/sound/mt2701-wm8960.txt deleted file mode 100644 index 809b609ea9d0..000000000000 --- a/Documentation/devicetree/bindings/sound/mt2701-wm8960.txt +++ /dev/null @@ -1,24 +0,0 @@ -MT2701 with WM8960 CODEC - -Required properties: -- compatible: "mediatek,mt2701-wm8960-machine" -- mediatek,platform: the phandle of MT2701 ASoC platform -- audio-routing: a list of the connections between audio -- mediatek,audio-codec: the phandles of wm8960 codec -- pinctrl-names: Should contain only one value - "default" -- pinctrl-0: Should specify pin control groups used for this controller. - -Example: - - sound:sound { - compatible = "mediatek,mt2701-wm8960-machine"; - mediatek,platform = <&afe>; - audio-routing = - "Headphone", "HP_L", - "Headphone", "HP_R", - "LINPUT1", "AMIC", - "RINPUT1", "AMIC"; - mediatek,audio-codec = <&wm8960>; - pinctrl-names = "default"; - pinctrl-0 = <&aud_pins_default>; - }; -- cgit v1.2.3 From 181d58cfe90f6a2ad53f6811d318fbc7149df8c1 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Wed, 17 Apr 2024 12:52:34 +0300 Subject: ASoC: cs35l41: Delete unnecessary condition in cs35l41_pcm_hw_params() This code returns -EINVAL if "i" is out of bounds a few lines earlier. Delete this unnecessary check and pull the code in a tab. Signed-off-by: Dan Carpenter Link: https://lore.kernel.org/r/1ee32bfb-6f6c-4b61-887b-6f655abbfc47@moroto.mountain Signed-off-by: Mark Brown --- sound/soc/codecs/cs35l41.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/sound/soc/codecs/cs35l41.c b/sound/soc/codecs/cs35l41.c index dfb4ce53491b..00258ac2bea6 100644 --- a/sound/soc/codecs/cs35l41.c +++ b/sound/soc/codecs/cs35l41.c @@ -772,10 +772,9 @@ static int cs35l41_pcm_hw_params(struct snd_pcm_substream *substream, asp_wl = params_width(params); - if (i < ARRAY_SIZE(cs35l41_fs_rates)) - regmap_update_bits(cs35l41->regmap, CS35L41_GLOBAL_CLK_CTRL, - CS35L41_GLOBAL_FS_MASK, - cs35l41_fs_rates[i].fs_cfg << CS35L41_GLOBAL_FS_SHIFT); + regmap_update_bits(cs35l41->regmap, CS35L41_GLOBAL_CLK_CTRL, + CS35L41_GLOBAL_FS_MASK, + cs35l41_fs_rates[i].fs_cfg << CS35L41_GLOBAL_FS_SHIFT); if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { regmap_update_bits(cs35l41->regmap, CS35L41_SP_FORMAT, -- cgit v1.2.3 From 467324bcfe1a31ec65d0cf4aa59421d6b7a7d52b Mon Sep 17 00:00:00 2001 From: Duoming Zhou Date: Fri, 19 Apr 2024 10:04:56 +0800 Subject: ax25: Fix netdev refcount issue The dev_tracker is added to ax25_cb in ax25_bind(). When the ax25 device is detaching, the dev_tracker of ax25_cb should be deallocated in ax25_kill_by_device() instead of the dev_tracker of ax25_dev. The log reported by ref_tracker is shown below: [ 80.884935] ref_tracker: reference already released. [ 80.885150] ref_tracker: allocated in: [ 80.885349] ax25_dev_device_up+0x105/0x540 [ 80.885730] ax25_device_event+0xa4/0x420 [ 80.885730] notifier_call_chain+0xc9/0x1e0 [ 80.885730] __dev_notify_flags+0x138/0x280 [ 80.885730] dev_change_flags+0xd7/0x180 [ 80.885730] dev_ifsioc+0x6a9/0xa30 [ 80.885730] dev_ioctl+0x4d8/0xd90 [ 80.885730] sock_do_ioctl+0x1c2/0x2d0 [ 80.885730] sock_ioctl+0x38b/0x4f0 [ 80.885730] __se_sys_ioctl+0xad/0xf0 [ 80.885730] do_syscall_64+0xc4/0x1b0 [ 80.885730] entry_SYSCALL_64_after_hwframe+0x67/0x6f [ 80.885730] ref_tracker: freed in: [ 80.885730] ax25_device_event+0x272/0x420 [ 80.885730] notifier_call_chain+0xc9/0x1e0 [ 80.885730] dev_close_many+0x272/0x370 [ 80.885730] unregister_netdevice_many_notify+0x3b5/0x1180 [ 80.885730] unregister_netdev+0xcf/0x120 [ 80.885730] sixpack_close+0x11f/0x1b0 [ 80.885730] tty_ldisc_kill+0xcb/0x190 [ 80.885730] tty_ldisc_hangup+0x338/0x3d0 [ 80.885730] __tty_hangup+0x504/0x740 [ 80.885730] tty_release+0x46e/0xd80 [ 80.885730] __fput+0x37f/0x770 [ 80.885730] __x64_sys_close+0x7b/0xb0 [ 80.885730] do_syscall_64+0xc4/0x1b0 [ 80.885730] entry_SYSCALL_64_after_hwframe+0x67/0x6f [ 80.893739] ------------[ cut here ]------------ [ 80.894030] WARNING: CPU: 2 PID: 140 at lib/ref_tracker.c:255 ref_tracker_free+0x47b/0x6b0 [ 80.894297] Modules linked in: [ 80.894929] CPU: 2 PID: 140 Comm: ax25_conn_rel_6 Not tainted 6.9.0-rc4-g8cd26fd90c1a #11 [ 80.895190] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS rel-1.14.0-0-g155821a1990b-prebuilt.qem4 [ 80.895514] RIP: 0010:ref_tracker_free+0x47b/0x6b0 [ 80.895808] Code: 83 c5 18 4c 89 eb 48 c1 eb 03 8a 04 13 84 c0 0f 85 df 01 00 00 41 83 7d 00 00 75 4b 4c 89 ff 9 [ 80.896171] RSP: 0018:ffff888009edf8c0 EFLAGS: 00000286 [ 80.896339] RAX: 1ffff1100141ac00 RBX: 1ffff1100149463b RCX: dffffc0000000000 [ 80.896502] RDX: 0000000000000001 RSI: 0000000000000246 RDI: ffff88800a0d6518 [ 80.896925] RBP: ffff888009edf9b0 R08: ffff88806d3288d3 R09: 1ffff1100da6511a [ 80.897212] R10: dffffc0000000000 R11: ffffed100da6511b R12: ffff88800a4a31d4 [ 80.897859] R13: ffff88800a4a31d8 R14: dffffc0000000000 R15: ffff88800a0d6518 [ 80.898279] FS: 00007fd88b7fe700(0000) GS:ffff88806d300000(0000) knlGS:0000000000000000 [ 80.899436] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 [ 80.900181] CR2: 00007fd88c001d48 CR3: 000000000993e000 CR4: 00000000000006f0 ... [ 80.935774] ref_tracker: sp%d@000000000bb9df3d has 1/1 users at [ 80.935774] ax25_bind+0x424/0x4e0 [ 80.935774] __sys_bind+0x1d9/0x270 [ 80.935774] __x64_sys_bind+0x75/0x80 [ 80.935774] do_syscall_64+0xc4/0x1b0 [ 80.935774] entry_SYSCALL_64_after_hwframe+0x67/0x6f Change ax25_dev->dev_tracker to the dev_tracker of ax25_cb in order to mitigate the bug. Fixes: feef318c855a ("ax25: fix UAF bugs of net_device caused by rebinding operation") Signed-off-by: Duoming Zhou Link: https://lore.kernel.org/r/20240419020456.29826-1-duoming@zju.edu.cn Signed-off-by: Paolo Abeni --- net/ax25/af_ax25.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/ax25/af_ax25.c b/net/ax25/af_ax25.c index 558e158c98d0..9169efb2f43a 100644 --- a/net/ax25/af_ax25.c +++ b/net/ax25/af_ax25.c @@ -103,7 +103,7 @@ again: s->ax25_dev = NULL; if (sk->sk_socket) { netdev_put(ax25_dev->dev, - &ax25_dev->dev_tracker); + &s->dev_tracker); ax25_dev_put(ax25_dev); } ax25_cb_del(s); -- cgit v1.2.3 From a44f2eb106a46f2275a79de54ce0ea63e4f3d8c8 Mon Sep 17 00:00:00 2001 From: Jakub Kicinski Date: Fri, 19 Apr 2024 19:08:26 -0700 Subject: tools: ynl: don't ignore errors in NLMSG_DONE messages NLMSG_DONE contains an error code, it has to be extracted. Prior to this change all dumps will end in success, and in case of failure the result is silently truncated. Fixes: e4b48ed460d3 ("tools: ynl: add a completely generic client") Signed-off-by: Jakub Kicinski Reviewed-by: Donald Hunter Link: https://lore.kernel.org/r/20240420020827.3288615-1-kuba@kernel.org Signed-off-by: Paolo Abeni --- tools/net/ynl/lib/ynl.py | 1 + 1 file changed, 1 insertion(+) diff --git a/tools/net/ynl/lib/ynl.py b/tools/net/ynl/lib/ynl.py index 5fa7957f6e0f..25810e18b0a7 100644 --- a/tools/net/ynl/lib/ynl.py +++ b/tools/net/ynl/lib/ynl.py @@ -182,6 +182,7 @@ class NlMsg: self.done = 1 extack_off = 20 elif self.nl_type == Netlink.NLMSG_DONE: + self.error = struct.unpack("i", self.raw[0:4])[0] self.done = 1 extack_off = 4 -- cgit v1.2.3 From 68301ef471b63f25d6e6144a0820fea52257a34a Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Tue, 23 Apr 2024 21:19:36 +0200 Subject: ACPI: PM: s2idle: Evaluate all Low-Power S0 Idle _DSM functions Commit 073237281a50 ("ACPI: PM: s2idle: Enable Low-Power S0 Idle MSFT UUID for non-AMD systems") attempted to avoid evaluating the same Low- Power S0 Idle _DSM functions for different UUIDs, but that turns out to be a mistake, because some systems in the field are adversely affected by it. Address this by allowing all Low-Power S0 Idle _DSM functions to be evaluated, but still print the message regarding duplication of Low- Power S0 Idle _DSM function sets for different UUIDs. Fixes: 073237281a50 ("ACPI: PM: s2idle: Enable Low-Power S0 Idle MSFT UUID for non-AMD systems") Closes: https://bugzilla.kernel.org/show_bug.cgi?id=218750 Reported-and-tested-by: Mark Pearson Suggested-by: Mario Limonciello Signed-off-by: Rafael J. Wysocki Reviewed-by: Mario Limonciello --- drivers/acpi/x86/s2idle.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/drivers/acpi/x86/s2idle.c b/drivers/acpi/x86/s2idle.c index cd84af23f7ea..dd0b40b9bbe8 100644 --- a/drivers/acpi/x86/s2idle.c +++ b/drivers/acpi/x86/s2idle.c @@ -492,16 +492,14 @@ static int lps0_device_attach(struct acpi_device *adev, unsigned int func_mask; /* - * Avoid evaluating the same _DSM function for two - * different UUIDs and prioritize the MSFT one. + * Log a message if the _DSM function sets for two + * different UUIDs overlap. */ func_mask = lps0_dsm_func_mask & lps0_dsm_func_mask_microsoft; - if (func_mask) { + if (func_mask) acpi_handle_info(adev->handle, "Duplicate LPS0 _DSM functions (mask: 0x%x)\n", func_mask); - lps0_dsm_func_mask &= ~func_mask; - } } } -- cgit v1.2.3 From 9c8ecb9308d8013ff9ac9d36fdd8ae746033b93c Mon Sep 17 00:00:00 2001 From: Chuck Lever Date: Tue, 23 Apr 2024 17:48:43 -0400 Subject: Revert "NFSD: Reschedule CB operations when backchannel rpc_clnt is shut down" The reverted commit attempted to enable NFSD to retransmit pending callback operations if an NFS client disconnects, but unintentionally introduces a hazardous behavior regression if the client becomes permanently unreachable while callback operations are still pending. A disconnect can occur due to network partition or if the NFS server needs to force the NFS client to retransmit (for example, if a GSS window under-run occurs). Reverting the commit will make NFSD behave the same as it did in v6.8 and before. Pending callback operations are permanently lost if the client connection is terminated before the client receives them. For some callback operations, this loss is not harmful. However, for CB_RECALL, the loss means a delegation might be revoked unnecessarily. For CB_OFFLOAD, pending COPY operations will never complete unless the NFS client subsequently sends an OFFLOAD_STATUS operation, which the Linux NFS client does not currently implement. These issues still need to be addressed somehow. Reported-by: Dai Ngo Link: https://bugzilla.kernel.org/show_bug.cgi?id=218735 Signed-off-by: Chuck Lever --- fs/nfsd/nfs4callback.c | 20 ++------------------ 1 file changed, 2 insertions(+), 18 deletions(-) diff --git a/fs/nfsd/nfs4callback.c b/fs/nfsd/nfs4callback.c index e440f72b9d4e..d153af81f406 100644 --- a/fs/nfsd/nfs4callback.c +++ b/fs/nfsd/nfs4callback.c @@ -986,14 +986,6 @@ static bool nfsd4_queue_cb(struct nfsd4_callback *cb) return queue_delayed_work(callback_wq, &cb->cb_work, 0); } -static void nfsd4_queue_cb_delayed(struct nfsd4_callback *cb, - unsigned long msecs) -{ - trace_nfsd_cb_queue(cb->cb_clp, cb); - queue_delayed_work(callback_wq, &cb->cb_work, - msecs_to_jiffies(msecs)); -} - static void nfsd41_cb_inflight_begin(struct nfs4_client *clp) { atomic_inc(&clp->cl_cb_inflight); @@ -1502,16 +1494,8 @@ nfsd4_run_cb_work(struct work_struct *work) clnt = clp->cl_cb_client; if (!clnt) { - if (test_bit(NFSD4_CLIENT_CB_KILL, &clp->cl_flags)) - nfsd41_destroy_cb(cb); - else { - /* - * XXX: Ideally, we could wait for the client to - * reconnect, but I haven't figured out how - * to do that yet. - */ - nfsd4_queue_cb_delayed(cb, 25); - } + /* Callback channel broken, or client killed; give up: */ + nfsd41_destroy_cb(cb); return; } -- cgit v1.2.3 From 8ddb7142c8ab37371c6fd167a8aded97922c6268 Mon Sep 17 00:00:00 2001 From: Chuck Lever Date: Tue, 23 Apr 2024 17:52:24 -0400 Subject: Revert "NFSD: Convert the callback workqueue to use delayed_work" This commit was a pre-requisite for commit c1ccfcf1a9bf ("NFSD: Reschedule CB operations when backchannel rpc_clnt is shut down"), which has already been reverted. Signed-off-by: Chuck Lever --- fs/nfsd/nfs4callback.c | 6 +++--- fs/nfsd/state.h | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/fs/nfsd/nfs4callback.c b/fs/nfsd/nfs4callback.c index d153af81f406..6aff46701aa1 100644 --- a/fs/nfsd/nfs4callback.c +++ b/fs/nfsd/nfs4callback.c @@ -983,7 +983,7 @@ static struct workqueue_struct *callback_wq; static bool nfsd4_queue_cb(struct nfsd4_callback *cb) { trace_nfsd_cb_queue(cb->cb_clp, cb); - return queue_delayed_work(callback_wq, &cb->cb_work, 0); + return queue_work(callback_wq, &cb->cb_work); } static void nfsd41_cb_inflight_begin(struct nfs4_client *clp) @@ -1482,7 +1482,7 @@ static void nfsd4_run_cb_work(struct work_struct *work) { struct nfsd4_callback *cb = - container_of(work, struct nfsd4_callback, cb_work.work); + container_of(work, struct nfsd4_callback, cb_work); struct nfs4_client *clp = cb->cb_clp; struct rpc_clnt *clnt; int flags; @@ -1528,7 +1528,7 @@ void nfsd4_init_cb(struct nfsd4_callback *cb, struct nfs4_client *clp, cb->cb_msg.rpc_argp = cb; cb->cb_msg.rpc_resp = cb; cb->cb_ops = ops; - INIT_DELAYED_WORK(&cb->cb_work, nfsd4_run_cb_work); + INIT_WORK(&cb->cb_work, nfsd4_run_cb_work); cb->cb_status = 0; cb->cb_need_restart = false; cb->cb_holds_slot = false; diff --git a/fs/nfsd/state.h b/fs/nfsd/state.h index 01c6f3445646..2ed0fcf879fd 100644 --- a/fs/nfsd/state.h +++ b/fs/nfsd/state.h @@ -68,7 +68,7 @@ struct nfsd4_callback { struct nfs4_client *cb_clp; struct rpc_message cb_msg; const struct nfsd4_callback_ops *cb_ops; - struct delayed_work cb_work; + struct work_struct cb_work; int cb_seq_status; int cb_status; bool cb_need_restart; -- cgit v1.2.3 From 701a22fd9ffaa409bbd45c2936870341b3ad9fdb Mon Sep 17 00:00:00 2001 From: Mohammad Shehar Yaar Tausif Date: Tue, 23 Apr 2024 17:27:47 +0530 Subject: ASoC: dt-bindings: tegra20-ac97: convert to dt schema Convert NVIDIA Tegra20 AC97 binding to DT schema. Change -gpio to -gpios in schema as "gpio" suffix is deprecated. Signed-off-by: Mohammad Shehar Yaar Tausif Reviewed-by: Krzysztof Kozlowski Link: https://lore.kernel.org/r/20240423115749.15786-1-sheharyaar48@gmail.com Signed-off-by: Mark Brown --- .../bindings/sound/nvidia,tegra20-ac97.txt | 36 ---------- .../bindings/sound/nvidia,tegra20-ac97.yaml | 82 ++++++++++++++++++++++ 2 files changed, 82 insertions(+), 36 deletions(-) delete mode 100644 Documentation/devicetree/bindings/sound/nvidia,tegra20-ac97.txt create mode 100644 Documentation/devicetree/bindings/sound/nvidia,tegra20-ac97.yaml diff --git a/Documentation/devicetree/bindings/sound/nvidia,tegra20-ac97.txt b/Documentation/devicetree/bindings/sound/nvidia,tegra20-ac97.txt deleted file mode 100644 index eaf00102d92c..000000000000 --- a/Documentation/devicetree/bindings/sound/nvidia,tegra20-ac97.txt +++ /dev/null @@ -1,36 +0,0 @@ -NVIDIA Tegra 20 AC97 controller - -Required properties: -- compatible : "nvidia,tegra20-ac97" -- reg : Should contain AC97 controller registers location and length -- interrupts : Should contain AC97 interrupt -- resets : Must contain an entry for each entry in reset-names. - See ../reset/reset.txt for details. -- reset-names : Must include the following entries: - - ac97 -- dmas : Must contain an entry for each entry in clock-names. - See ../dma/dma.txt for details. -- dma-names : Must include the following entries: - - rx - - tx -- clocks : Must contain one entry, for the module clock. - See ../clocks/clock-bindings.txt for details. -- nvidia,codec-reset-gpio : The Tegra GPIO controller's phandle and the number - of the GPIO used to reset the external AC97 codec -- nvidia,codec-sync-gpio : The Tegra GPIO controller's phandle and the number - of the GPIO corresponding with the AC97 DAP _FS line - -Example: - -ac97@70002000 { - compatible = "nvidia,tegra20-ac97"; - reg = <0x70002000 0x200>; - interrupts = <0 81 0x04>; - nvidia,codec-reset-gpio = <&gpio 170 0>; - nvidia,codec-sync-gpio = <&gpio 120 0>; - clocks = <&tegra_car 3>; - resets = <&tegra_car 3>; - reset-names = "ac97"; - dmas = <&apbdma 12>, <&apbdma 12>; - dma-names = "rx", "tx"; -}; diff --git a/Documentation/devicetree/bindings/sound/nvidia,tegra20-ac97.yaml b/Documentation/devicetree/bindings/sound/nvidia,tegra20-ac97.yaml new file mode 100644 index 000000000000..4ea0a303d995 --- /dev/null +++ b/Documentation/devicetree/bindings/sound/nvidia,tegra20-ac97.yaml @@ -0,0 +1,82 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/sound/nvidia,tegra20-ac97.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: NVIDIA Tegra20 AC97 controller + +maintainers: + - Thierry Reding + - Jon Hunter + +properties: + compatible: + const: nvidia,tegra20-ac97 + + reg: + maxItems: 1 + + resets: + maxItems: 1 + + reset-names: + const: ac97 + + interrupts: + maxItems: 1 + + clocks: + maxItems: 1 + + dmas: + maxItems: 2 + + dma-names: + items: + - const: rx + - const: tx + + nvidia,codec-reset-gpios: + description: Reset pin of external AC97 codec + maxItems: 1 + + nvidia,codec-sync-gpios: + description: AC97 DAP _FS line + maxItems: 1 + +required: + - compatible + - reg + - resets + - reset-names + - interrupts + - clocks + - dmas + - dma-names + - nvidia,codec-reset-gpios + - nvidia,codec-sync-gpios + +additionalProperties: false + +examples: + - | + #include + #include + #include + #include + #include + + ac97@70002000 { + compatible = "nvidia,tegra20-ac97"; + reg = <0x70002000 0x200>; + resets = <&tegra_car 3>; + reset-names = "ac97"; + interrupts = ; + clocks = <&tegra_car 3>; + dmas = <&apbdma 12>, <&apbdma 12>; + dma-names = "rx", "tx"; + nvidia,codec-reset-gpios = <&gpio TEGRA_GPIO(V, 2) GPIO_ACTIVE_HIGH>; + nvidia,codec-sync-gpios = <&gpio TEGRA_GPIO(P, 0) GPIO_ACTIVE_HIGH>; + }; +... -- cgit v1.2.3 From fe2a84133724ef56d2c99f2be5d0e06c4b8395c1 Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Tue, 23 Apr 2024 08:44:28 +0100 Subject: ASoc: PCM6240: Fix spelling mistake: "deley" -> "delay" There is a spelling mistake in a dev_err message. Fix it. Signed-off-by: Colin Ian King Link: https://lore.kernel.org/r/20240423074428.1313777-1-colin.i.king@gmail.com Signed-off-by: Mark Brown --- sound/soc/codecs/pcm6240.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/codecs/pcm6240.c b/sound/soc/codecs/pcm6240.c index 93d592dbee66..86e126783a1d 100644 --- a/sound/soc/codecs/pcm6240.c +++ b/sound/soc/codecs/pcm6240.c @@ -1772,7 +1772,7 @@ static int pcmdev_delay(struct pcmdevice_priv *pcm_dev, int offset = 2; if (offset + 2 > sublocksize) { - dev_err(pcm_dev->dev, "%s: dev-%d deley out of boundary\n", + dev_err(pcm_dev->dev, "%s: dev-%d delay out of boundary\n", __func__, devn); return -EINVAL; } -- cgit v1.2.3 From 466c8c46b4ba763435b2a787b7824d9f0fd3e76e Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Tue, 23 Apr 2024 14:19:26 +0200 Subject: ASoC: dt-bindings: renesas: Fix R-Car Gen4 SoC-specific compatibles make dtbs_check: arch/arm64/boot/dts/renesas/r8a779g0-white-hawk.dtb: sound@ec5a0000: compatible: 'oneOf' conditional failed, one must be fixed: ['renesas,rcar_sound-r8a779g0', 'renesas,rcar_sound-gen4'] is too short ... 'renesas,rcar_sound-r8a779h0' was expected The list of SoC-specific compatible values for R-Car Gen4 SoCs is mutually-exclusive, just like for other R-Car SoC generations, so it should use an enum. Fixes: d6e792ed7dd022a1 ("ASoC: dt-bindings: renesas: add R8A779H0 V4M") Signed-off-by: Geert Uytterhoeven Reviewed-by: Krzysztof Kozlowski Link: https://lore.kernel.org/r/b3a6cf12c46b23a501b0d54c6892b969e2a55145.1713874657.git.geert+renesas@glider.be Signed-off-by: Mark Brown --- Documentation/devicetree/bindings/sound/renesas,rsnd.yaml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/Documentation/devicetree/bindings/sound/renesas,rsnd.yaml b/Documentation/devicetree/bindings/sound/renesas,rsnd.yaml index b3da278cf141..07ec6247d9de 100644 --- a/Documentation/devicetree/bindings/sound/renesas,rsnd.yaml +++ b/Documentation/devicetree/bindings/sound/renesas,rsnd.yaml @@ -48,8 +48,9 @@ properties: - const: renesas,rcar_sound-gen3 # for Gen4 SoC - items: - - const: renesas,rcar_sound-r8a779g0 # R-Car V4H - - const: renesas,rcar_sound-r8a779h0 # R-Car V4M + - enum: + - renesas,rcar_sound-r8a779g0 # R-Car V4H + - renesas,rcar_sound-r8a779h0 # R-Car V4M - const: renesas,rcar_sound-gen4 # for Generic - enum: -- cgit v1.2.3 From 3584718cf2ec7e79b6814f2596dcf398c5fb2eca Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Sun, 21 Apr 2024 17:52:48 +0000 Subject: net: fix sk_memory_allocated_{add|sub} vs softirqs Jonathan Heathcote reported a regression caused by blamed commit on aarch64 architecture. x86 happens to have irq-safe __this_cpu_add_return() and __this_cpu_sub(), but this is not generic. I think my confusion came from "struct sock" argument, because these helpers are called with a locked socket. But the memory accounting is per-proto (and per-cpu after the blamed commit). We might cleanup these helpers later to directly accept a "struct proto *proto" argument. Switch to this_cpu_add_return() and this_cpu_xchg() operations, and get rid of preempt_disable()/preempt_enable() pairs. Fast path becomes a bit faster as a result :) Many thanks to Jonathan Heathcote for his awesome report and investigations. Fixes: 3cd3399dd7a8 ("net: implement per-cpu reserves for memory_allocated") Reported-by: Jonathan Heathcote Closes: https://lore.kernel.org/netdev/VI1PR01MB42407D7947B2EA448F1E04EFD10D2@VI1PR01MB4240.eurprd01.prod.exchangelabs.com/ Signed-off-by: Eric Dumazet Acked-by: Soheil Hassas Yeganeh Reviewed-by: Shakeel Butt Link: https://lore.kernel.org/r/20240421175248.1692552-1-edumazet@google.com Signed-off-by: Jakub Kicinski --- include/net/sock.h | 38 ++++++++++++++++++++------------------ 1 file changed, 20 insertions(+), 18 deletions(-) diff --git a/include/net/sock.h b/include/net/sock.h index f57bfd8a2ad2..b4b553df7870 100644 --- a/include/net/sock.h +++ b/include/net/sock.h @@ -1410,32 +1410,34 @@ sk_memory_allocated(const struct sock *sk) #define SK_MEMORY_PCPU_RESERVE (1 << (20 - PAGE_SHIFT)) extern int sysctl_mem_pcpu_rsv; +static inline void proto_memory_pcpu_drain(struct proto *proto) +{ + int val = this_cpu_xchg(*proto->per_cpu_fw_alloc, 0); + + if (val) + atomic_long_add(val, proto->memory_allocated); +} + static inline void -sk_memory_allocated_add(struct sock *sk, int amt) +sk_memory_allocated_add(const struct sock *sk, int val) { - int local_reserve; + struct proto *proto = sk->sk_prot; - preempt_disable(); - local_reserve = __this_cpu_add_return(*sk->sk_prot->per_cpu_fw_alloc, amt); - if (local_reserve >= READ_ONCE(sysctl_mem_pcpu_rsv)) { - __this_cpu_sub(*sk->sk_prot->per_cpu_fw_alloc, local_reserve); - atomic_long_add(local_reserve, sk->sk_prot->memory_allocated); - } - preempt_enable(); + val = this_cpu_add_return(*proto->per_cpu_fw_alloc, val); + + if (unlikely(val >= READ_ONCE(sysctl_mem_pcpu_rsv))) + proto_memory_pcpu_drain(proto); } static inline void -sk_memory_allocated_sub(struct sock *sk, int amt) +sk_memory_allocated_sub(const struct sock *sk, int val) { - int local_reserve; + struct proto *proto = sk->sk_prot; - preempt_disable(); - local_reserve = __this_cpu_sub_return(*sk->sk_prot->per_cpu_fw_alloc, amt); - if (local_reserve <= -READ_ONCE(sysctl_mem_pcpu_rsv)) { - __this_cpu_sub(*sk->sk_prot->per_cpu_fw_alloc, local_reserve); - atomic_long_add(local_reserve, sk->sk_prot->memory_allocated); - } - preempt_enable(); + val = this_cpu_sub_return(*proto->per_cpu_fw_alloc, val); + + if (unlikely(val <= -READ_ONCE(sysctl_mem_pcpu_rsv))) + proto_memory_pcpu_drain(proto); } #define SK_ALLOC_PERCPU_COUNTER_BATCH 16 -- cgit v1.2.3 From 58a4c9b1e5a3e53c9148e80b90e1e43897ce77d1 Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Sun, 21 Apr 2024 18:43:26 +0000 Subject: ipv4: check for NULL idev in ip_route_use_hint() syzbot was able to trigger a NULL deref in fib_validate_source() in an old tree [1]. It appears the bug exists in latest trees. All calls to __in_dev_get_rcu() must be checked for a NULL result. [1] general protection fault, probably for non-canonical address 0xdffffc0000000000: 0000 [#1] SMP KASAN KASAN: null-ptr-deref in range [0x0000000000000000-0x0000000000000007] CPU: 2 PID: 3257 Comm: syz-executor.3 Not tainted 5.10.0-syzkaller #0 Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS 1.16.3-debian-1.16.3-2~bpo12+1 04/01/2014 RIP: 0010:fib_validate_source+0xbf/0x15a0 net/ipv4/fib_frontend.c:425 Code: 18 f2 f2 f2 f2 42 c7 44 20 23 f3 f3 f3 f3 48 89 44 24 78 42 c6 44 20 27 f3 e8 5d 88 48 fc 4c 89 e8 48 c1 e8 03 48 89 44 24 18 <42> 80 3c 20 00 74 08 4c 89 ef e8 d2 15 98 fc 48 89 5c 24 10 41 bf RSP: 0018:ffffc900015fee40 EFLAGS: 00010246 RAX: 0000000000000000 RBX: ffff88800f7a4000 RCX: ffff88800f4f90c0 RDX: 0000000000000000 RSI: 0000000004001eac RDI: ffff8880160c64c0 RBP: ffffc900015ff060 R08: 0000000000000000 R09: ffff88800f7a4000 R10: 0000000000000002 R11: ffff88800f4f90c0 R12: dffffc0000000000 R13: 0000000000000000 R14: 0000000000000000 R15: ffff88800f7a4000 FS: 00007f938acfe6c0(0000) GS:ffff888058c00000(0000) knlGS:0000000000000000 CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 CR2: 00007f938acddd58 CR3: 000000001248e000 CR4: 0000000000352ef0 DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400 Call Trace: ip_route_use_hint+0x410/0x9b0 net/ipv4/route.c:2231 ip_rcv_finish_core+0x2c4/0x1a30 net/ipv4/ip_input.c:327 ip_list_rcv_finish net/ipv4/ip_input.c:612 [inline] ip_sublist_rcv+0x3ed/0xe50 net/ipv4/ip_input.c:638 ip_list_rcv+0x422/0x470 net/ipv4/ip_input.c:673 __netif_receive_skb_list_ptype net/core/dev.c:5572 [inline] __netif_receive_skb_list_core+0x6b1/0x890 net/core/dev.c:5620 __netif_receive_skb_list net/core/dev.c:5672 [inline] netif_receive_skb_list_internal+0x9f9/0xdc0 net/core/dev.c:5764 netif_receive_skb_list+0x55/0x3e0 net/core/dev.c:5816 xdp_recv_frames net/bpf/test_run.c:257 [inline] xdp_test_run_batch net/bpf/test_run.c:335 [inline] bpf_test_run_xdp_live+0x1818/0x1d00 net/bpf/test_run.c:363 bpf_prog_test_run_xdp+0x81f/0x1170 net/bpf/test_run.c:1376 bpf_prog_test_run+0x349/0x3c0 kernel/bpf/syscall.c:3736 __sys_bpf+0x45c/0x710 kernel/bpf/syscall.c:5115 __do_sys_bpf kernel/bpf/syscall.c:5201 [inline] __se_sys_bpf kernel/bpf/syscall.c:5199 [inline] __x64_sys_bpf+0x7c/0x90 kernel/bpf/syscall.c:5199 Fixes: 02b24941619f ("ipv4: use dst hint for ipv4 list receive") Reported-by: syzbot Signed-off-by: Eric Dumazet Acked-by: Paolo Abeni Link: https://lore.kernel.org/r/20240421184326.1704930-1-edumazet@google.com Signed-off-by: Jakub Kicinski --- net/ipv4/route.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/net/ipv4/route.c b/net/ipv4/route.c index d36ace160d42..b814fdab19f7 100644 --- a/net/ipv4/route.c +++ b/net/ipv4/route.c @@ -2166,6 +2166,9 @@ int ip_route_use_hint(struct sk_buff *skb, __be32 daddr, __be32 saddr, int err = -EINVAL; u32 tag = 0; + if (!in_dev) + return -EINVAL; + if (ipv4_is_multicast(saddr) || ipv4_is_lbcast(saddr)) goto martian_source; -- cgit v1.2.3 From 4ce62d5b2f7aecd4900e7d6115588ad7f9acccca Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Sun, 21 Apr 2024 19:38:28 +0000 Subject: net: usb: ax88179_178a: stop lying about skb->truesize Some usb drivers try to set small skb->truesize and break core networking stacks. In this patch, I removed one of the skb->truesize overide. I also replaced one skb_clone() by an allocation of a fresh and small skb, to get minimally sized skbs, like we did in commit 1e2c61172342 ("net: cdc_ncm: reduce skb truesize in rx path") Fixes: f8ebb3ac881b ("net: usb: ax88179_178a: Fix packet receiving") Reported-by: shironeko Closes: https://lore.kernel.org/netdev/c110f41a0d2776b525930f213ca9715c@tesaguri.club/ Signed-off-by: Eric Dumazet Cc: Jose Alonso Reviewed-by: Simon Horman Link: https://lore.kernel.org/r/20240421193828.1966195-1-edumazet@google.com Signed-off-by: Jakub Kicinski --- drivers/net/usb/ax88179_178a.c | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/drivers/net/usb/ax88179_178a.c b/drivers/net/usb/ax88179_178a.c index 752f821a1990..df9d767cb524 100644 --- a/drivers/net/usb/ax88179_178a.c +++ b/drivers/net/usb/ax88179_178a.c @@ -1456,21 +1456,16 @@ static int ax88179_rx_fixup(struct usbnet *dev, struct sk_buff *skb) /* Skip IP alignment pseudo header */ skb_pull(skb, 2); - skb->truesize = SKB_TRUESIZE(pkt_len_plus_padd); ax88179_rx_checksum(skb, pkt_hdr); return 1; } - ax_skb = skb_clone(skb, GFP_ATOMIC); + ax_skb = netdev_alloc_skb_ip_align(dev->net, pkt_len); if (!ax_skb) return 0; - skb_trim(ax_skb, pkt_len); + skb_put(ax_skb, pkt_len); + memcpy(ax_skb->data, skb->data + 2, pkt_len); - /* Skip IP alignment pseudo header */ - skb_pull(ax_skb, 2); - - skb->truesize = pkt_len_plus_padd + - SKB_DATA_ALIGN(sizeof(struct sk_buff)); ax88179_rx_checksum(ax_skb, pkt_hdr); usbnet_skb_return(dev, ax_skb); -- cgit v1.2.3 From 80e679b352c3ce5158f3f778cfb77eb767e586fb Mon Sep 17 00:00:00 2001 From: Hyunwoo Kim Date: Mon, 22 Apr 2024 05:33:40 -0400 Subject: tcp: Fix Use-After-Free in tcp_ao_connect_init Since call_rcu, which is called in the hlist_for_each_entry_rcu traversal of tcp_ao_connect_init, is not part of the RCU read critical section, it is possible that the RCU grace period will pass during the traversal and the key will be free. To prevent this, it should be changed to hlist_for_each_entry_safe. Fixes: 7c2ffaf21bd6 ("net/tcp: Calculate TCP-AO traffic keys") Signed-off-by: Hyunwoo Kim Reviewed-by: Eric Dumazet Acked-by: Dmitry Safonov <0x7f454c46@gmail.com> Link: https://lore.kernel.org/r/ZiYu9NJ/ClR8uSkH@v4bel-B760M-AORUS-ELITE-AX Signed-off-by: Jakub Kicinski --- net/ipv4/tcp_ao.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/net/ipv4/tcp_ao.c b/net/ipv4/tcp_ao.c index 3afeeb68e8a7..781b67a52571 100644 --- a/net/ipv4/tcp_ao.c +++ b/net/ipv4/tcp_ao.c @@ -1068,6 +1068,7 @@ void tcp_ao_connect_init(struct sock *sk) { struct tcp_sock *tp = tcp_sk(sk); struct tcp_ao_info *ao_info; + struct hlist_node *next; union tcp_ao_addr *addr; struct tcp_ao_key *key; int family, l3index; @@ -1090,7 +1091,7 @@ void tcp_ao_connect_init(struct sock *sk) l3index = l3mdev_master_ifindex_by_index(sock_net(sk), sk->sk_bound_dev_if); - hlist_for_each_entry_rcu(key, &ao_info->head, node) { + hlist_for_each_entry_safe(key, next, &ao_info->head, node) { if (!tcp_ao_key_cmp(key, l3index, addr, key->prefixlen, family, -1, -1)) continue; -- cgit v1.2.3 From f2a904107ee2b647bb7794a1a82b67740d7c8a64 Mon Sep 17 00:00:00 2001 From: Hyunwoo Kim Date: Mon, 22 Apr 2024 05:39:30 -0400 Subject: net: gtp: Fix Use-After-Free in gtp_dellink Since call_rcu, which is called in the hlist_for_each_entry_rcu traversal of gtp_dellink, is not part of the RCU read critical section, it is possible that the RCU grace period will pass during the traversal and the key will be free. To prevent this, it should be changed to hlist_for_each_entry_safe. Fixes: 94dc550a5062 ("gtp: fix an use-after-free in ipv4_pdp_find()") Signed-off-by: Hyunwoo Kim Reviewed-by: Eric Dumazet Signed-off-by: David S. Miller --- drivers/net/gtp.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/net/gtp.c b/drivers/net/gtp.c index ba4704c2c640..e62d6cbdf9bc 100644 --- a/drivers/net/gtp.c +++ b/drivers/net/gtp.c @@ -1098,11 +1098,12 @@ out_hashtable: static void gtp_dellink(struct net_device *dev, struct list_head *head) { struct gtp_dev *gtp = netdev_priv(dev); + struct hlist_node *next; struct pdp_ctx *pctx; int i; for (i = 0; i < gtp->hash_size; i++) - hlist_for_each_entry_rcu(pctx, >p->tid_hash[i], hlist_tid) + hlist_for_each_entry_safe(pctx, next, >p->tid_hash[i], hlist_tid) pdp_context_delete(pctx); list_del_rcu(>p->list); -- cgit v1.2.3 From 5b5f724b05c550e10693a53a81cadca901aefd16 Mon Sep 17 00:00:00 2001 From: Daniel Golle Date: Sun, 21 Apr 2024 01:08:31 +0100 Subject: net: phy: mediatek-ge-soc: follow netdev LED trigger semantics Only blink if the link is up on a LED which is programmed to also indicate link-status. Otherwise, if both LEDs are in use to indicate different speeds, the resulting blinking being inverted on LEDs which aren't switched on at a specific speed is quite counter-intuitive. Also make sure that state left behind by reset or the bootloader is recognized correctly including the half-duplex and full-duplex bits as well as the (unsupported by Linux netdev trigger semantics) link-down bit. Fixes: c66937b0f8db ("net: phy: mediatek-ge-soc: support PHY LEDs") Signed-off-by: Daniel Golle Signed-off-by: David S. Miller --- drivers/net/phy/mediatek-ge-soc.c | 43 +++++++++++++++++++++++---------------- 1 file changed, 26 insertions(+), 17 deletions(-) diff --git a/drivers/net/phy/mediatek-ge-soc.c b/drivers/net/phy/mediatek-ge-soc.c index 0f3a1538a8b8..f4f9412d0cd7 100644 --- a/drivers/net/phy/mediatek-ge-soc.c +++ b/drivers/net/phy/mediatek-ge-soc.c @@ -216,6 +216,9 @@ #define MTK_PHY_LED_ON_LINK1000 BIT(0) #define MTK_PHY_LED_ON_LINK100 BIT(1) #define MTK_PHY_LED_ON_LINK10 BIT(2) +#define MTK_PHY_LED_ON_LINK (MTK_PHY_LED_ON_LINK10 |\ + MTK_PHY_LED_ON_LINK100 |\ + MTK_PHY_LED_ON_LINK1000) #define MTK_PHY_LED_ON_LINKDOWN BIT(3) #define MTK_PHY_LED_ON_FDX BIT(4) /* Full duplex */ #define MTK_PHY_LED_ON_HDX BIT(5) /* Half duplex */ @@ -231,6 +234,12 @@ #define MTK_PHY_LED_BLINK_100RX BIT(3) #define MTK_PHY_LED_BLINK_10TX BIT(4) #define MTK_PHY_LED_BLINK_10RX BIT(5) +#define MTK_PHY_LED_BLINK_RX (MTK_PHY_LED_BLINK_10RX |\ + MTK_PHY_LED_BLINK_100RX |\ + MTK_PHY_LED_BLINK_1000RX) +#define MTK_PHY_LED_BLINK_TX (MTK_PHY_LED_BLINK_10TX |\ + MTK_PHY_LED_BLINK_100TX |\ + MTK_PHY_LED_BLINK_1000TX) #define MTK_PHY_LED_BLINK_COLLISION BIT(6) #define MTK_PHY_LED_BLINK_RX_CRC_ERR BIT(7) #define MTK_PHY_LED_BLINK_RX_IDLE_ERR BIT(8) @@ -1247,11 +1256,9 @@ static int mt798x_phy_led_hw_control_get(struct phy_device *phydev, u8 index, if (blink < 0) return -EIO; - if ((on & (MTK_PHY_LED_ON_LINK1000 | MTK_PHY_LED_ON_LINK100 | - MTK_PHY_LED_ON_LINK10)) || - (blink & (MTK_PHY_LED_BLINK_1000RX | MTK_PHY_LED_BLINK_100RX | - MTK_PHY_LED_BLINK_10RX | MTK_PHY_LED_BLINK_1000TX | - MTK_PHY_LED_BLINK_100TX | MTK_PHY_LED_BLINK_10TX))) + if ((on & (MTK_PHY_LED_ON_LINK | MTK_PHY_LED_ON_FDX | MTK_PHY_LED_ON_HDX | + MTK_PHY_LED_ON_LINKDOWN)) || + (blink & (MTK_PHY_LED_BLINK_RX | MTK_PHY_LED_BLINK_TX))) set_bit(bit_netdev, &priv->led_state); else clear_bit(bit_netdev, &priv->led_state); @@ -1269,7 +1276,7 @@ static int mt798x_phy_led_hw_control_get(struct phy_device *phydev, u8 index, if (!rules) return 0; - if (on & (MTK_PHY_LED_ON_LINK1000 | MTK_PHY_LED_ON_LINK100 | MTK_PHY_LED_ON_LINK10)) + if (on & MTK_PHY_LED_ON_LINK) *rules |= BIT(TRIGGER_NETDEV_LINK); if (on & MTK_PHY_LED_ON_LINK10) @@ -1287,10 +1294,10 @@ static int mt798x_phy_led_hw_control_get(struct phy_device *phydev, u8 index, if (on & MTK_PHY_LED_ON_HDX) *rules |= BIT(TRIGGER_NETDEV_HALF_DUPLEX); - if (blink & (MTK_PHY_LED_BLINK_1000RX | MTK_PHY_LED_BLINK_100RX | MTK_PHY_LED_BLINK_10RX)) + if (blink & MTK_PHY_LED_BLINK_RX) *rules |= BIT(TRIGGER_NETDEV_RX); - if (blink & (MTK_PHY_LED_BLINK_1000TX | MTK_PHY_LED_BLINK_100TX | MTK_PHY_LED_BLINK_10TX)) + if (blink & MTK_PHY_LED_BLINK_TX) *rules |= BIT(TRIGGER_NETDEV_TX); return 0; @@ -1323,15 +1330,19 @@ static int mt798x_phy_led_hw_control_set(struct phy_device *phydev, u8 index, on |= MTK_PHY_LED_ON_LINK1000; if (rules & BIT(TRIGGER_NETDEV_RX)) { - blink |= MTK_PHY_LED_BLINK_10RX | - MTK_PHY_LED_BLINK_100RX | - MTK_PHY_LED_BLINK_1000RX; + blink |= (on & MTK_PHY_LED_ON_LINK) ? + (((on & MTK_PHY_LED_ON_LINK10) ? MTK_PHY_LED_BLINK_10RX : 0) | + ((on & MTK_PHY_LED_ON_LINK100) ? MTK_PHY_LED_BLINK_100RX : 0) | + ((on & MTK_PHY_LED_ON_LINK1000) ? MTK_PHY_LED_BLINK_1000RX : 0)) : + MTK_PHY_LED_BLINK_RX; } if (rules & BIT(TRIGGER_NETDEV_TX)) { - blink |= MTK_PHY_LED_BLINK_10TX | - MTK_PHY_LED_BLINK_100TX | - MTK_PHY_LED_BLINK_1000TX; + blink |= (on & MTK_PHY_LED_ON_LINK) ? + (((on & MTK_PHY_LED_ON_LINK10) ? MTK_PHY_LED_BLINK_10TX : 0) | + ((on & MTK_PHY_LED_ON_LINK100) ? MTK_PHY_LED_BLINK_100TX : 0) | + ((on & MTK_PHY_LED_ON_LINK1000) ? MTK_PHY_LED_BLINK_1000TX : 0)) : + MTK_PHY_LED_BLINK_TX; } if (blink || on) @@ -1344,9 +1355,7 @@ static int mt798x_phy_led_hw_control_set(struct phy_device *phydev, u8 index, MTK_PHY_LED0_ON_CTRL, MTK_PHY_LED_ON_FDX | MTK_PHY_LED_ON_HDX | - MTK_PHY_LED_ON_LINK10 | - MTK_PHY_LED_ON_LINK100 | - MTK_PHY_LED_ON_LINK1000, + MTK_PHY_LED_ON_LINK, on); if (ret) -- cgit v1.2.3 From 9bf4e919ccad613b3596eebf1ff37b05b6405307 Mon Sep 17 00:00:00 2001 From: Nathan Chancellor Date: Mon, 1 Apr 2024 11:24:17 -0700 Subject: Bluetooth: Fix type of len in {l2cap,sco}_sock_getsockopt_old() After an innocuous optimization change in LLVM main (19.0.0), x86_64 allmodconfig (which enables CONFIG_KCSAN / -fsanitize=thread) fails to build due to the checks in check_copy_size(): In file included from net/bluetooth/sco.c:27: In file included from include/linux/module.h:13: In file included from include/linux/stat.h:19: In file included from include/linux/time.h:60: In file included from include/linux/time32.h:13: In file included from include/linux/timex.h:67: In file included from arch/x86/include/asm/timex.h:6: In file included from arch/x86/include/asm/tsc.h:10: In file included from arch/x86/include/asm/msr.h:15: In file included from include/linux/percpu.h:7: In file included from include/linux/smp.h:118: include/linux/thread_info.h:244:4: error: call to '__bad_copy_from' declared with 'error' attribute: copy source size is too small 244 | __bad_copy_from(); | ^ The same exact error occurs in l2cap_sock.c. The copy_to_user() statements that are failing come from l2cap_sock_getsockopt_old() and sco_sock_getsockopt_old(). This does not occur with GCC with or without KCSAN or Clang without KCSAN enabled. len is defined as an 'int' because it is assigned from '__user int *optlen'. However, it is clamped against the result of sizeof(), which has a type of 'size_t' ('unsigned long' for 64-bit platforms). This is done with min_t() because min() requires compatible types, which results in both len and the result of sizeof() being casted to 'unsigned int', meaning len changes signs and the result of sizeof() is truncated. From there, len is passed to copy_to_user(), which has a third parameter type of 'unsigned long', so it is widened and changes signs again. This excessive casting in combination with the KCSAN instrumentation causes LLVM to fail to eliminate the __bad_copy_from() call, failing the build. The official recommendation from LLVM developers is to consistently use long types for all size variables to avoid the unnecessary casting in the first place. Change the type of len to size_t in both l2cap_sock_getsockopt_old() and sco_sock_getsockopt_old(). This clears up the error while allowing min_t() to be replaced with min(), resulting in simpler code with no casts and fewer implicit conversions. While len is a different type than optlen now, it should result in no functional change because the result of sizeof() will clamp all values of optlen in the same manner as before. Cc: stable@vger.kernel.org Closes: https://github.com/ClangBuiltLinux/linux/issues/2007 Link: https://github.com/llvm/llvm-project/issues/85647 Signed-off-by: Nathan Chancellor Reviewed-by: Justin Stitt Signed-off-by: Luiz Augusto von Dentz --- net/bluetooth/l2cap_sock.c | 7 ++++--- net/bluetooth/sco.c | 7 ++++--- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/net/bluetooth/l2cap_sock.c b/net/bluetooth/l2cap_sock.c index e7d810b23082..5cc83f906c12 100644 --- a/net/bluetooth/l2cap_sock.c +++ b/net/bluetooth/l2cap_sock.c @@ -439,7 +439,8 @@ static int l2cap_sock_getsockopt_old(struct socket *sock, int optname, struct l2cap_chan *chan = l2cap_pi(sk)->chan; struct l2cap_options opts; struct l2cap_conninfo cinfo; - int len, err = 0; + int err = 0; + size_t len; u32 opt; BT_DBG("sk %p", sk); @@ -486,7 +487,7 @@ static int l2cap_sock_getsockopt_old(struct socket *sock, int optname, BT_DBG("mode 0x%2.2x", chan->mode); - len = min_t(unsigned int, len, sizeof(opts)); + len = min(len, sizeof(opts)); if (copy_to_user(optval, (char *) &opts, len)) err = -EFAULT; @@ -536,7 +537,7 @@ static int l2cap_sock_getsockopt_old(struct socket *sock, int optname, cinfo.hci_handle = chan->conn->hcon->handle; memcpy(cinfo.dev_class, chan->conn->hcon->dev_class, 3); - len = min_t(unsigned int, len, sizeof(cinfo)); + len = min(len, sizeof(cinfo)); if (copy_to_user(optval, (char *) &cinfo, len)) err = -EFAULT; diff --git a/net/bluetooth/sco.c b/net/bluetooth/sco.c index 368e026f4d15..5d03c5440b06 100644 --- a/net/bluetooth/sco.c +++ b/net/bluetooth/sco.c @@ -964,7 +964,8 @@ static int sco_sock_getsockopt_old(struct socket *sock, int optname, struct sock *sk = sock->sk; struct sco_options opts; struct sco_conninfo cinfo; - int len, err = 0; + int err = 0; + size_t len; BT_DBG("sk %p", sk); @@ -986,7 +987,7 @@ static int sco_sock_getsockopt_old(struct socket *sock, int optname, BT_DBG("mtu %u", opts.mtu); - len = min_t(unsigned int, len, sizeof(opts)); + len = min(len, sizeof(opts)); if (copy_to_user(optval, (char *)&opts, len)) err = -EFAULT; @@ -1004,7 +1005,7 @@ static int sco_sock_getsockopt_old(struct socket *sock, int optname, cinfo.hci_handle = sco_pi(sk)->conn->hcon->handle; memcpy(cinfo.dev_class, sco_pi(sk)->conn->hcon->dev_class, 3); - len = min_t(unsigned int, len, sizeof(cinfo)); + len = min(len, sizeof(cinfo)); if (copy_to_user(optval, (char *)&cinfo, len)) err = -EFAULT; -- cgit v1.2.3 From 2e7ed5f5e69b6fe93dd3c6b651d041e0a7a456d1 Mon Sep 17 00:00:00 2001 From: Luiz Augusto von Dentz Date: Fri, 5 Apr 2024 16:40:33 -0400 Subject: Bluetooth: hci_sync: Use advertised PHYs on hci_le_ext_create_conn_sync The extended advertising reports do report the PHYs so this store then in hci_conn so it can be later used in hci_le_ext_create_conn_sync to narrow the PHYs to be scanned since the controller will also perform a scan having a smaller set of PHYs shall reduce the time it takes to find and connect peers. Fixes: 288c90224eec ("Bluetooth: Enable all supported LE PHY by default") Signed-off-by: Luiz Augusto von Dentz --- include/net/bluetooth/hci_core.h | 4 +++- net/bluetooth/hci_conn.c | 6 ++++-- net/bluetooth/hci_event.c | 20 ++++++++++++-------- net/bluetooth/hci_sync.c | 9 ++++++--- net/bluetooth/l2cap_core.c | 2 +- 5 files changed, 26 insertions(+), 15 deletions(-) diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h index 56fb42df44a3..02af7d7013da 100644 --- a/include/net/bluetooth/hci_core.h +++ b/include/net/bluetooth/hci_core.h @@ -738,6 +738,8 @@ struct hci_conn { __u8 le_per_adv_data[HCI_MAX_PER_AD_TOT_LEN]; __u16 le_per_adv_data_len; __u16 le_per_adv_data_offset; + __u8 le_adv_phy; + __u8 le_adv_sec_phy; __u8 le_tx_phy; __u8 le_rx_phy; __s8 rssi; @@ -1512,7 +1514,7 @@ struct hci_conn *hci_connect_le_scan(struct hci_dev *hdev, bdaddr_t *dst, enum conn_reasons conn_reason); struct hci_conn *hci_connect_le(struct hci_dev *hdev, bdaddr_t *dst, u8 dst_type, bool dst_resolved, u8 sec_level, - u16 conn_timeout, u8 role); + u16 conn_timeout, u8 role, u8 phy, u8 sec_phy); void hci_connect_le_scan_cleanup(struct hci_conn *conn, u8 status); struct hci_conn *hci_connect_acl(struct hci_dev *hdev, bdaddr_t *dst, u8 sec_level, u8 auth_type, diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c index 3ad74f76983b..05346250f719 100644 --- a/net/bluetooth/hci_conn.c +++ b/net/bluetooth/hci_conn.c @@ -1263,7 +1263,7 @@ u8 hci_conn_set_handle(struct hci_conn *conn, u16 handle) struct hci_conn *hci_connect_le(struct hci_dev *hdev, bdaddr_t *dst, u8 dst_type, bool dst_resolved, u8 sec_level, - u16 conn_timeout, u8 role) + u16 conn_timeout, u8 role, u8 phy, u8 sec_phy) { struct hci_conn *conn; struct smp_irk *irk; @@ -1326,6 +1326,8 @@ struct hci_conn *hci_connect_le(struct hci_dev *hdev, bdaddr_t *dst, conn->dst_type = dst_type; conn->sec_level = BT_SECURITY_LOW; conn->conn_timeout = conn_timeout; + conn->le_adv_phy = phy; + conn->le_adv_sec_phy = sec_phy; err = hci_connect_le_sync(hdev, conn); if (err) { @@ -2273,7 +2275,7 @@ struct hci_conn *hci_connect_cis(struct hci_dev *hdev, bdaddr_t *dst, le = hci_connect_le(hdev, dst, dst_type, false, BT_SECURITY_LOW, HCI_LE_CONN_TIMEOUT, - HCI_ROLE_SLAVE); + HCI_ROLE_SLAVE, 0, 0); else le = hci_connect_le_scan(hdev, dst, dst_type, BT_SECURITY_LOW, diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c index a8b8cfebe018..4d70402e295f 100644 --- a/net/bluetooth/hci_event.c +++ b/net/bluetooth/hci_event.c @@ -6038,7 +6038,7 @@ static void hci_le_conn_update_complete_evt(struct hci_dev *hdev, void *data, static struct hci_conn *check_pending_le_conn(struct hci_dev *hdev, bdaddr_t *addr, u8 addr_type, bool addr_resolved, - u8 adv_type) + u8 adv_type, u8 phy, u8 sec_phy) { struct hci_conn *conn; struct hci_conn_params *params; @@ -6093,7 +6093,7 @@ static struct hci_conn *check_pending_le_conn(struct hci_dev *hdev, conn = hci_connect_le(hdev, addr, addr_type, addr_resolved, BT_SECURITY_LOW, hdev->def_le_autoconnect_timeout, - HCI_ROLE_MASTER); + HCI_ROLE_MASTER, phy, sec_phy); if (!IS_ERR(conn)) { /* If HCI_AUTO_CONN_EXPLICIT is set, conn is already owned * by higher layer that tried to connect, if no then @@ -6128,8 +6128,9 @@ static struct hci_conn *check_pending_le_conn(struct hci_dev *hdev, static void process_adv_report(struct hci_dev *hdev, u8 type, bdaddr_t *bdaddr, u8 bdaddr_type, bdaddr_t *direct_addr, - u8 direct_addr_type, s8 rssi, u8 *data, u8 len, - bool ext_adv, bool ctl_time, u64 instant) + u8 direct_addr_type, u8 phy, u8 sec_phy, s8 rssi, + u8 *data, u8 len, bool ext_adv, bool ctl_time, + u64 instant) { struct discovery_state *d = &hdev->discovery; struct smp_irk *irk; @@ -6217,7 +6218,7 @@ static void process_adv_report(struct hci_dev *hdev, u8 type, bdaddr_t *bdaddr, * for advertising reports) and is already verified to be RPA above. */ conn = check_pending_le_conn(hdev, bdaddr, bdaddr_type, bdaddr_resolved, - type); + type, phy, sec_phy); if (!ext_adv && conn && type == LE_ADV_IND && len <= max_adv_len(hdev)) { /* Store report for later inclusion by @@ -6363,7 +6364,8 @@ static void hci_le_adv_report_evt(struct hci_dev *hdev, void *data, if (info->length <= max_adv_len(hdev)) { rssi = info->data[info->length]; process_adv_report(hdev, info->type, &info->bdaddr, - info->bdaddr_type, NULL, 0, rssi, + info->bdaddr_type, NULL, 0, + HCI_ADV_PHY_1M, 0, rssi, info->data, info->length, false, false, instant); } else { @@ -6448,6 +6450,8 @@ static void hci_le_ext_adv_report_evt(struct hci_dev *hdev, void *data, if (legacy_evt_type != LE_ADV_INVALID) { process_adv_report(hdev, legacy_evt_type, &info->bdaddr, info->bdaddr_type, NULL, 0, + info->primary_phy, + info->secondary_phy, info->rssi, info->data, info->length, !(evt_type & LE_EXT_ADV_LEGACY_PDU), false, instant); @@ -6730,8 +6734,8 @@ static void hci_le_direct_adv_report_evt(struct hci_dev *hdev, void *data, process_adv_report(hdev, info->type, &info->bdaddr, info->bdaddr_type, &info->direct_addr, - info->direct_addr_type, info->rssi, NULL, 0, - false, false, instant); + info->direct_addr_type, HCI_ADV_PHY_1M, 0, + info->rssi, NULL, 0, false, false, instant); } hci_dev_unlock(hdev); diff --git a/net/bluetooth/hci_sync.c b/net/bluetooth/hci_sync.c index c5d8799046cc..4c707eb64e6f 100644 --- a/net/bluetooth/hci_sync.c +++ b/net/bluetooth/hci_sync.c @@ -6346,7 +6346,8 @@ static int hci_le_ext_create_conn_sync(struct hci_dev *hdev, plen = sizeof(*cp); - if (scan_1m(hdev)) { + if (scan_1m(hdev) && (conn->le_adv_phy == HCI_ADV_PHY_1M || + conn->le_adv_sec_phy == HCI_ADV_PHY_1M)) { cp->phys |= LE_SCAN_PHY_1M; set_ext_conn_params(conn, p); @@ -6354,7 +6355,8 @@ static int hci_le_ext_create_conn_sync(struct hci_dev *hdev, plen += sizeof(*p); } - if (scan_2m(hdev)) { + if (scan_2m(hdev) && (conn->le_adv_phy == HCI_ADV_PHY_2M || + conn->le_adv_sec_phy == HCI_ADV_PHY_2M)) { cp->phys |= LE_SCAN_PHY_2M; set_ext_conn_params(conn, p); @@ -6362,7 +6364,8 @@ static int hci_le_ext_create_conn_sync(struct hci_dev *hdev, plen += sizeof(*p); } - if (scan_coded(hdev)) { + if (scan_coded(hdev) && (conn->le_adv_phy == HCI_ADV_PHY_CODED || + conn->le_adv_sec_phy == HCI_ADV_PHY_CODED)) { cp->phys |= LE_SCAN_PHY_CODED; set_ext_conn_params(conn, p); diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c index dc0897408793..84fc70862d78 100644 --- a/net/bluetooth/l2cap_core.c +++ b/net/bluetooth/l2cap_core.c @@ -7018,7 +7018,7 @@ int l2cap_chan_connect(struct l2cap_chan *chan, __le16 psm, u16 cid, if (hci_dev_test_flag(hdev, HCI_ADVERTISING)) hcon = hci_connect_le(hdev, dst, dst_type, false, chan->sec_level, timeout, - HCI_ROLE_SLAVE); + HCI_ROLE_SLAVE, 0, 0); else hcon = hci_connect_le_scan(hdev, dst, dst_type, chan->sec_level, timeout, -- cgit v1.2.3 From d1a5a7eede2977da3d2002d5ea3b519019cc1a98 Mon Sep 17 00:00:00 2001 From: WangYuli Date: Fri, 29 Mar 2024 10:34:39 +0800 Subject: Bluetooth: btusb: Add Realtek RTL8852BE support ID 0x0bda:0x4853 Add the support ID(0x0bda, 0x4853) to usb_device_id table for Realtek RTL8852BE. Without this change the device utilizes an obsolete version of the firmware that is encoded in it rather than the updated Realtek firmware and config files from the firmware directory. The latter files implement many new features. The device table is as follows: T: Bus=03 Lev=01 Prnt=01 Port=09 Cnt=03 Dev#= 4 Spd=12 MxCh= 0 D: Ver= 1.00 Cls=e0(wlcon) Sub=01 Prot=01 MxPS=64 #Cfgs= 1 P: Vendor=0bda ProdID=4853 Rev= 0.00 S: Manufacturer=Realtek S: Product=Bluetooth Radio S: SerialNumber=00e04c000001 C:* #Ifs= 2 Cfg#= 1 Atr=e0 MxPwr=500mA I:* If#= 0 Alt= 0 #EPs= 3 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb E: Ad=81(I) Atr=03(Int.) MxPS= 16 Ivl=1ms E: Ad=02(O) Atr=02(Bulk) MxPS= 64 Ivl=0ms E: Ad=82(I) Atr=02(Bulk) MxPS= 64 Ivl=0ms I:* If#= 1 Alt= 0 #EPs= 2 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb E: Ad=03(O) Atr=01(Isoc) MxPS= 0 Ivl=1ms E: Ad=83(I) Atr=01(Isoc) MxPS= 0 Ivl=1ms I: If#= 1 Alt= 1 #EPs= 2 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb E: Ad=03(O) Atr=01(Isoc) MxPS= 9 Ivl=1ms E: Ad=83(I) Atr=01(Isoc) MxPS= 9 Ivl=1ms I: If#= 1 Alt= 2 #EPs= 2 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb E: Ad=03(O) Atr=01(Isoc) MxPS= 17 Ivl=1ms E: Ad=83(I) Atr=01(Isoc) MxPS= 17 Ivl=1ms I: If#= 1 Alt= 3 #EPs= 2 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb E: Ad=03(O) Atr=01(Isoc) MxPS= 25 Ivl=1ms E: Ad=83(I) Atr=01(Isoc) MxPS= 25 Ivl=1ms I: If#= 1 Alt= 4 #EPs= 2 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb E: Ad=03(O) Atr=01(Isoc) MxPS= 33 Ivl=1ms E: Ad=83(I) Atr=01(Isoc) MxPS= 33 Ivl=1ms I: If#= 1 Alt= 5 #EPs= 2 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb E: Ad=03(O) Atr=01(Isoc) MxPS= 49 Ivl=1ms E: Ad=83(I) Atr=01(Isoc) MxPS= 49 Ivl=1ms Cc: stable@vger.kernel.org Signed-off-by: Larry Finger Signed-off-by: WangYuli Signed-off-by: Luiz Augusto von Dentz --- drivers/bluetooth/btusb.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c index 06e915b57283..d9c621d15fee 100644 --- a/drivers/bluetooth/btusb.c +++ b/drivers/bluetooth/btusb.c @@ -542,6 +542,8 @@ static const struct usb_device_id quirks_table[] = { /* Realtek 8852BE Bluetooth devices */ { USB_DEVICE(0x0cb8, 0xc559), .driver_info = BTUSB_REALTEK | BTUSB_WIDEBAND_SPEECH }, + { USB_DEVICE(0x0bda, 0x4853), .driver_info = BTUSB_REALTEK | + BTUSB_WIDEBAND_SPEECH }, { USB_DEVICE(0x0bda, 0x887b), .driver_info = BTUSB_REALTEK | BTUSB_WIDEBAND_SPEECH }, { USB_DEVICE(0x0bda, 0xb85b), .driver_info = BTUSB_REALTEK | -- cgit v1.2.3 From b23d98d46d2858dcc0fd016caff165cbdc24e70a Mon Sep 17 00:00:00 2001 From: Zijun Hu Date: Mon, 25 Mar 2024 16:11:49 +0800 Subject: Bluetooth: btusb: Fix triggering coredump implementation for QCA btusb_coredump_qca() uses __hci_cmd_sync() to send a vendor-specific command to trigger firmware coredump, but the command does not have any event as its sync response, so it is not suitable to use __hci_cmd_sync(), fixed by using __hci_cmd_send(). Fixes: 20981ce2d5a5 ("Bluetooth: btusb: Add WCN6855 devcoredump support") Signed-off-by: Zijun Hu Signed-off-by: Luiz Augusto von Dentz --- drivers/bluetooth/btusb.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c index d9c621d15fee..e3946f7b736e 100644 --- a/drivers/bluetooth/btusb.c +++ b/drivers/bluetooth/btusb.c @@ -3482,13 +3482,12 @@ static void btusb_dump_hdr_qca(struct hci_dev *hdev, struct sk_buff *skb) static void btusb_coredump_qca(struct hci_dev *hdev) { + int err; static const u8 param[] = { 0x26 }; - struct sk_buff *skb; - skb = __hci_cmd_sync(hdev, 0xfc0c, 1, param, HCI_CMD_TIMEOUT); - if (IS_ERR(skb)) - bt_dev_err(hdev, "%s: triggle crash failed (%ld)", __func__, PTR_ERR(skb)); - kfree_skb(skb); + err = __hci_cmd_send(hdev, 0xfc0c, 1, param); + if (err < 0) + bt_dev_err(hdev, "%s: triggle crash failed (%d)", __func__, err); } /* -- cgit v1.2.3 From a9a830a676a9a93c5020f5c61236166931fa4266 Mon Sep 17 00:00:00 2001 From: Luiz Augusto von Dentz Date: Mon, 15 Apr 2024 13:41:01 -0400 Subject: Bluetooth: hci_event: Fix sending HCI_OP_READ_ENC_KEY_SIZE The code shall always check if HCI_QUIRK_BROKEN_READ_ENC_KEY_SIZE has been set before attempting to use HCI_OP_READ_ENC_KEY_SIZE. Fixes: c569242cd492 ("Bluetooth: hci_event: set the conn encrypted before conn establishes") Signed-off-by: Luiz Augusto von Dentz --- include/net/bluetooth/hci_core.h | 4 ++++ net/bluetooth/hci_event.c | 5 ++--- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h index 02af7d7013da..e8f581f3f3ce 100644 --- a/include/net/bluetooth/hci_core.h +++ b/include/net/bluetooth/hci_core.h @@ -1907,6 +1907,10 @@ void hci_conn_del_sysfs(struct hci_conn *conn); #define privacy_mode_capable(dev) (use_ll_privacy(dev) && \ (hdev->commands[39] & 0x04)) +#define read_key_size_capable(dev) \ + ((dev)->commands[20] & 0x10 && \ + !test_bit(HCI_QUIRK_BROKEN_READ_ENC_KEY_SIZE, &hdev->quirks)) + /* Use enhanced synchronous connection if command is supported and its quirk * has not been set. */ diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c index 4d70402e295f..4a27e4a17a67 100644 --- a/net/bluetooth/hci_event.c +++ b/net/bluetooth/hci_event.c @@ -3218,7 +3218,7 @@ static void hci_conn_complete_evt(struct hci_dev *hdev, void *data, if (key) { set_bit(HCI_CONN_ENCRYPT, &conn->flags); - if (!(hdev->commands[20] & 0x10)) { + if (!read_key_size_capable(hdev)) { conn->enc_key_size = HCI_LINK_KEY_SIZE; } else { cp.handle = cpu_to_le16(conn->handle); @@ -3666,8 +3666,7 @@ static void hci_encrypt_change_evt(struct hci_dev *hdev, void *data, * controller really supports it. If it doesn't, assume * the default size (16). */ - if (!(hdev->commands[20] & 0x10) || - test_bit(HCI_QUIRK_BROKEN_READ_ENC_KEY_SIZE, &hdev->quirks)) { + if (!read_key_size_capable(hdev)) { conn->enc_key_size = HCI_LINK_KEY_SIZE; goto notify; } -- cgit v1.2.3 From 32868e126c78876a8a5ddfcb6ac8cb2fffcf4d27 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Tue, 16 Apr 2024 11:15:09 +0200 Subject: Bluetooth: qca: fix invalid device address check Qualcomm Bluetooth controllers may not have been provisioned with a valid device address and instead end up using the default address 00:00:00:00:5a:ad. This was previously believed to be due to lack of persistent storage for the address but it may also be due to integrators opting to not use the on-chip OTP memory and instead store the address elsewhere (e.g. in storage managed by secure world firmware). According to Qualcomm, at least WCN6750, WCN6855 and WCN7850 have on-chip OTP storage for the address. As the device type alone cannot be used to determine when the address is valid, instead read back the address during setup() and only set the HCI_QUIRK_USE_BDADDR_PROPERTY flag when needed. This specifically makes sure that controllers that have been provisioned with an address do not start as unconfigured. Reported-by: Janaki Ramaiah Thota Link: https://lore.kernel.org/r/124a7d54-5a18-4be7-9a76-a12017f6cce5@quicinc.com/ Fixes: 5971752de44c ("Bluetooth: hci_qca: Set HCI_QUIRK_USE_BDADDR_PROPERTY for wcn3990") Fixes: e668eb1e1578 ("Bluetooth: hci_core: Don't stop BT if the BD address missing in dts") Fixes: 6945795bc81a ("Bluetooth: fix use-bdaddr-property quirk") Cc: stable@vger.kernel.org # 6.5 Cc: Matthias Kaehlcke Signed-off-by: Johan Hovold Reported-by: Janaki Ramaiah Thota Signed-off-by: Luiz Augusto von Dentz --- drivers/bluetooth/btqca.c | 38 ++++++++++++++++++++++++++++++++++++++ drivers/bluetooth/hci_qca.c | 2 -- 2 files changed, 38 insertions(+), 2 deletions(-) diff --git a/drivers/bluetooth/btqca.c b/drivers/bluetooth/btqca.c index 19cfc342fc7b..216826c31ee3 100644 --- a/drivers/bluetooth/btqca.c +++ b/drivers/bluetooth/btqca.c @@ -15,6 +15,8 @@ #define VERSION "0.1" +#define QCA_BDADDR_DEFAULT (&(bdaddr_t) {{ 0xad, 0x5a, 0x00, 0x00, 0x00, 0x00 }}) + int qca_read_soc_version(struct hci_dev *hdev, struct qca_btsoc_version *ver, enum qca_btsoc_type soc_type) { @@ -612,6 +614,38 @@ int qca_set_bdaddr_rome(struct hci_dev *hdev, const bdaddr_t *bdaddr) } EXPORT_SYMBOL_GPL(qca_set_bdaddr_rome); +static int qca_check_bdaddr(struct hci_dev *hdev) +{ + struct hci_rp_read_bd_addr *bda; + struct sk_buff *skb; + int err; + + if (bacmp(&hdev->public_addr, BDADDR_ANY)) + return 0; + + skb = __hci_cmd_sync(hdev, HCI_OP_READ_BD_ADDR, 0, NULL, + HCI_INIT_TIMEOUT); + if (IS_ERR(skb)) { + err = PTR_ERR(skb); + bt_dev_err(hdev, "Failed to read device address (%d)", err); + return err; + } + + if (skb->len != sizeof(*bda)) { + bt_dev_err(hdev, "Device address length mismatch"); + kfree_skb(skb); + return -EIO; + } + + bda = (struct hci_rp_read_bd_addr *)skb->data; + if (!bacmp(&bda->bdaddr, QCA_BDADDR_DEFAULT)) + set_bit(HCI_QUIRK_USE_BDADDR_PROPERTY, &hdev->quirks); + + kfree_skb(skb); + + return 0; +} + static void qca_generate_hsp_nvm_name(char *fwname, size_t max_size, struct qca_btsoc_version ver, u8 rom_ver, u16 bid) { @@ -818,6 +852,10 @@ int qca_uart_setup(struct hci_dev *hdev, uint8_t baudrate, break; } + err = qca_check_bdaddr(hdev); + if (err) + return err; + bt_dev_info(hdev, "QCA setup on UART is completed"); return 0; diff --git a/drivers/bluetooth/hci_qca.c b/drivers/bluetooth/hci_qca.c index ecbc52eaf101..92fa20f5ac7d 100644 --- a/drivers/bluetooth/hci_qca.c +++ b/drivers/bluetooth/hci_qca.c @@ -1905,8 +1905,6 @@ retry: case QCA_WCN6750: case QCA_WCN6855: case QCA_WCN7850: - set_bit(HCI_QUIRK_USE_BDADDR_PROPERTY, &hdev->quirks); - qcadev = serdev_device_get_drvdata(hu->serdev); if (qcadev->bdaddr_property_broken) set_bit(HCI_QUIRK_BDADDR_PROPERTY_BROKEN, &hdev->quirks); -- cgit v1.2.3 From 6eb5fcc416f127f220b9177a5c9ae751cac1cda8 Mon Sep 17 00:00:00 2001 From: Luiz Augusto von Dentz Date: Tue, 16 Apr 2024 15:34:45 -0400 Subject: Bluetooth: MGMT: Fix failing to MGMT_OP_ADD_UUID/MGMT_OP_REMOVE_UUID These commands don't require the adapter to be up and running so don't use hci_cmd_sync_queue which would check that flag, instead use hci_cmd_sync_submit which would ensure mgmt_class_complete is set properly regardless if any command was actually run or not. Link: https://github.com/bluez/bluez/issues/809 Fixes: d883a4669a1d ("Bluetooth: hci_sync: Only allow hci_cmd_sync_queue if running") Signed-off-by: Luiz Augusto von Dentz --- net/bluetooth/mgmt.c | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c index 32ed6e9245a3..657abd9bcc87 100644 --- a/net/bluetooth/mgmt.c +++ b/net/bluetooth/mgmt.c @@ -2623,7 +2623,11 @@ static int add_uuid(struct sock *sk, struct hci_dev *hdev, void *data, u16 len) goto failed; } - err = hci_cmd_sync_queue(hdev, add_uuid_sync, cmd, mgmt_class_complete); + /* MGMT_OP_ADD_UUID don't require adapter the UP/Running so use + * hci_cmd_sync_submit instead of hci_cmd_sync_queue. + */ + err = hci_cmd_sync_submit(hdev, add_uuid_sync, cmd, + mgmt_class_complete); if (err < 0) { mgmt_pending_free(cmd); goto failed; @@ -2717,8 +2721,11 @@ update_class: goto unlock; } - err = hci_cmd_sync_queue(hdev, remove_uuid_sync, cmd, - mgmt_class_complete); + /* MGMT_OP_REMOVE_UUID don't require adapter the UP/Running so use + * hci_cmd_sync_submit instead of hci_cmd_sync_queue. + */ + err = hci_cmd_sync_submit(hdev, remove_uuid_sync, cmd, + mgmt_class_complete); if (err < 0) mgmt_pending_free(cmd); @@ -2784,8 +2791,11 @@ static int set_dev_class(struct sock *sk, struct hci_dev *hdev, void *data, goto unlock; } - err = hci_cmd_sync_queue(hdev, set_class_sync, cmd, - mgmt_class_complete); + /* MGMT_OP_SET_DEV_CLASS don't require adapter the UP/Running so use + * hci_cmd_sync_submit instead of hci_cmd_sync_queue. + */ + err = hci_cmd_sync_submit(hdev, set_class_sync, cmd, + mgmt_class_complete); if (err < 0) mgmt_pending_free(cmd); -- cgit v1.2.3 From 18bdb386a1a30e7a3d7732a98e45e69cf6b5710d Mon Sep 17 00:00:00 2001 From: Sean Wang Date: Wed, 17 Apr 2024 16:27:38 -0700 Subject: Bluetooth: btusb: mediatek: Fix double free of skb in coredump hci_devcd_append() would free the skb on error so the caller don't have to free it again otherwise it would cause the double free of skb. Fixes: 0b7015132878 ("Bluetooth: btusb: mediatek: add MediaTek devcoredump support") Reported-by : Dan Carpenter Signed-off-by: Sean Wang Signed-off-by: Luiz Augusto von Dentz --- drivers/bluetooth/btmtk.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/drivers/bluetooth/btmtk.c b/drivers/bluetooth/btmtk.c index ac8ebccd3507..812fd2a8f853 100644 --- a/drivers/bluetooth/btmtk.c +++ b/drivers/bluetooth/btmtk.c @@ -380,8 +380,10 @@ int btmtk_process_coredump(struct hci_dev *hdev, struct sk_buff *skb) switch (data->cd_info.state) { case HCI_DEVCOREDUMP_IDLE: err = hci_devcd_init(hdev, MTK_COREDUMP_SIZE); - if (err < 0) + if (err < 0) { + kfree_skb(skb); break; + } data->cd_info.cnt = 0; /* It is supposed coredump can be done within 5 seconds */ @@ -407,9 +409,6 @@ int btmtk_process_coredump(struct hci_dev *hdev, struct sk_buff *skb) break; } - if (err < 0) - kfree_skb(skb); - return err; } EXPORT_SYMBOL_GPL(btmtk_process_coredump); -- cgit v1.2.3 From 73e87c0a49fda31d7b589edccf4c72e924411371 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Mon, 22 Apr 2024 15:57:47 +0200 Subject: Bluetooth: qca: fix NULL-deref on non-serdev suspend Qualcomm ROME controllers can be registered from the Bluetooth line discipline and in this case the HCI UART serdev pointer is NULL. Add the missing sanity check to prevent a NULL-pointer dereference when wakeup() is called for a non-serdev controller during suspend. Just return true for now to restore the original behaviour and address the crash with pre-6.2 kernels, which do not have commit e9b3e5b8c657 ("Bluetooth: hci_qca: only assign wakeup with serial port support") that causes the crash to happen already at setup() time. Fixes: c1a74160eaf1 ("Bluetooth: hci_qca: Add device_may_wakeup support") Cc: stable@vger.kernel.org # 5.13 Signed-off-by: Johan Hovold Signed-off-by: Luiz Augusto von Dentz --- drivers/bluetooth/hci_qca.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/bluetooth/hci_qca.c b/drivers/bluetooth/hci_qca.c index 92fa20f5ac7d..94c85f4fbf3b 100644 --- a/drivers/bluetooth/hci_qca.c +++ b/drivers/bluetooth/hci_qca.c @@ -1672,6 +1672,9 @@ static bool qca_wakeup(struct hci_dev *hdev) struct hci_uart *hu = hci_get_drvdata(hdev); bool wakeup; + if (!hu->serdev) + return true; + /* BT SoC attached through the serial bus is handled by the serdev driver. * So we need to use the device handle of the serdev driver to get the * status of device may wakeup. -- cgit v1.2.3 From 7ddb9de6af0f1c71147785b12fd7c8ec3f06cc86 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Mon, 22 Apr 2024 15:57:48 +0200 Subject: Bluetooth: qca: fix NULL-deref on non-serdev setup Qualcomm ROME controllers can be registered from the Bluetooth line discipline and in this case the HCI UART serdev pointer is NULL. Add the missing sanity check to prevent a NULL-pointer dereference when setup() is called for a non-serdev controller. Fixes: e9b3e5b8c657 ("Bluetooth: hci_qca: only assign wakeup with serial port support") Cc: stable@vger.kernel.org # 6.2 Cc: Zhengping Jiang Signed-off-by: Johan Hovold Signed-off-by: Luiz Augusto von Dentz --- drivers/bluetooth/hci_qca.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/bluetooth/hci_qca.c b/drivers/bluetooth/hci_qca.c index 94c85f4fbf3b..b621a0a40ea4 100644 --- a/drivers/bluetooth/hci_qca.c +++ b/drivers/bluetooth/hci_qca.c @@ -1958,8 +1958,10 @@ retry: qca_debugfs_init(hdev); hu->hdev->hw_error = qca_hw_error; hu->hdev->cmd_timeout = qca_cmd_timeout; - if (device_can_wakeup(hu->serdev->ctrl->dev.parent)) - hu->hdev->wakeup = qca_wakeup; + if (hu->serdev) { + if (device_can_wakeup(hu->serdev->ctrl->dev.parent)) + hu->hdev->wakeup = qca_wakeup; + } } else if (ret == -ENOENT) { /* No patch/nvm-config found, run with original fw/config */ set_bit(QCA_ROM_FW, &qca->flags); -- cgit v1.2.3 From 88cd6e6b2d327faa13e4505b07f1e380e51b21ff Mon Sep 17 00:00:00 2001 From: Chun-Yi Lee Date: Wed, 24 Apr 2024 21:59:03 +0800 Subject: Bluetooth: hci_sync: Using hci_cmd_sync_submit when removing Adv Monitor Since the d883a4669a1de be introduced in v6.4, bluetooth daemon got the following failed message of MGMT_OP_REMOVE_ADV_MONITOR command when controller is power-off: bluetoothd[20976]: src/adapter.c:reset_adv_monitors_complete() Failed to reset Adv Monitors: Failed> Normally this situation is happened when the bluetoothd deamon be started manually after system booting. Which means that bluetoothd received MGMT_EV_INDEX_ADDED event after kernel runs hci_power_off(). Base on doc/mgmt-api.txt, the MGMT_OP_REMOVE_ADV_MONITOR command can be used when the controller is not powered. This patch changes the code in remove_adv_monitor() to use hci_cmd_sync_submit() instead of hci_cmd_sync_queue(). Fixes: d883a4669a1de ("Bluetooth: hci_sync: Only allow hci_cmd_sync_queue if running") Cc: Luiz Augusto von Dentz Cc: Manish Mandlik Cc: Archie Pusaka Cc: Miao-chen Chou Signed-off-by: Chun-Yi Lee Signed-off-by: Luiz Augusto von Dentz --- net/bluetooth/mgmt.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c index 657abd9bcc87..965f621ef865 100644 --- a/net/bluetooth/mgmt.c +++ b/net/bluetooth/mgmt.c @@ -5485,8 +5485,8 @@ static int remove_adv_monitor(struct sock *sk, struct hci_dev *hdev, goto unlock; } - err = hci_cmd_sync_queue(hdev, mgmt_remove_adv_monitor_sync, cmd, - mgmt_remove_adv_monitor_complete); + err = hci_cmd_sync_submit(hdev, mgmt_remove_adv_monitor_sync, cmd, + mgmt_remove_adv_monitor_complete); if (err) { mgmt_pending_remove(cmd); -- cgit v1.2.3 From 3d05fc82237aa97162d0d7dc300b55bb34e91d02 Mon Sep 17 00:00:00 2001 From: Bartosz Golaszewski Date: Wed, 24 Apr 2024 14:29:32 +0200 Subject: Bluetooth: qca: set power_ctrl_enabled on NULL returned by gpiod_get_optional() Any return value from gpiod_get_optional() other than a pointer to a GPIO descriptor or a NULL-pointer is an error and the driver should abort probing. That being said: commit 56d074d26c58 ("Bluetooth: hci_qca: don't use IS_ERR_OR_NULL() with gpiod_get_optional()") no longer sets power_ctrl_enabled on NULL-pointer returned by devm_gpiod_get_optional(). Restore this behavior but bail-out on errors. While at it: also bail-out on error returned when trying to get the "swctrl" GPIO. Reported-by: Wren Turkal Reported-by: Zijun Hu Closes: https://lore.kernel.org/linux-bluetooth/1713449192-25926-2-git-send-email-quic_zijuhu@quicinc.com/ Fixes: 56d074d26c58 ("Bluetooth: hci_qca: don't use IS_ERR_OR_NULL() with gpiod_get_optional()") Reviewed-by: Krzysztof Kozlowski Signed-off-by: Bartosz Golaszewski Tested-by: Wren Turkal" Reported-by: Wren Turkal Reported-by: Zijun Hu Reviewed-by: Krzysztof Kozlowski Reviewed-by: Krzysztof Kozlowski Signed-off-by: Luiz Augusto von Dentz --- drivers/bluetooth/hci_qca.c | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/drivers/bluetooth/hci_qca.c b/drivers/bluetooth/hci_qca.c index b621a0a40ea4..0c9c9ee56592 100644 --- a/drivers/bluetooth/hci_qca.c +++ b/drivers/bluetooth/hci_qca.c @@ -2332,16 +2332,21 @@ static int qca_serdev_probe(struct serdev_device *serdev) (data->soc_type == QCA_WCN6750 || data->soc_type == QCA_WCN6855)) { dev_err(&serdev->dev, "failed to acquire BT_EN gpio\n"); - power_ctrl_enabled = false; + return PTR_ERR(qcadev->bt_en); } + if (!qcadev->bt_en) + power_ctrl_enabled = false; + qcadev->sw_ctrl = devm_gpiod_get_optional(&serdev->dev, "swctrl", GPIOD_IN); if (IS_ERR(qcadev->sw_ctrl) && (data->soc_type == QCA_WCN6750 || data->soc_type == QCA_WCN6855 || - data->soc_type == QCA_WCN7850)) - dev_warn(&serdev->dev, "failed to acquire SW_CTRL gpio\n"); + data->soc_type == QCA_WCN7850)) { + dev_err(&serdev->dev, "failed to acquire SW_CTRL gpio\n"); + return PTR_ERR(qcadev->sw_ctrl); + } qcadev->susclk = devm_clk_get_optional(&serdev->dev, NULL); if (IS_ERR(qcadev->susclk)) { @@ -2360,10 +2365,13 @@ static int qca_serdev_probe(struct serdev_device *serdev) qcadev->bt_en = devm_gpiod_get_optional(&serdev->dev, "enable", GPIOD_OUT_LOW); if (IS_ERR(qcadev->bt_en)) { - dev_warn(&serdev->dev, "failed to acquire enable gpio\n"); - power_ctrl_enabled = false; + dev_err(&serdev->dev, "failed to acquire enable gpio\n"); + return PTR_ERR(qcadev->bt_en); } + if (!qcadev->bt_en) + power_ctrl_enabled = false; + qcadev->susclk = devm_clk_get_optional(&serdev->dev, NULL); if (IS_ERR(qcadev->susclk)) { dev_warn(&serdev->dev, "failed to acquire clk\n"); -- cgit v1.2.3 From e10d3ba4d434ed172914617ed8d74bd411421193 Mon Sep 17 00:00:00 2001 From: Ismael Luceno Date: Sun, 21 Apr 2024 16:22:32 +0200 Subject: ipvs: Fix checksumming on GSO of SCTP packets It was observed in the wild that pairs of consecutive packets would leave the IPVS with the same wrong checksum, and the issue only went away when disabling GSO. IPVS needs to avoid computing the SCTP checksum when using GSO. Fixes: 90017accff61 ("sctp: Add GSO support") Co-developed-by: Firo Yang Signed-off-by: Ismael Luceno Tested-by: Andreas Taschner Acked-by: Julian Anastasov Signed-off-by: Pablo Neira Ayuso --- net/netfilter/ipvs/ip_vs_proto_sctp.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/net/netfilter/ipvs/ip_vs_proto_sctp.c b/net/netfilter/ipvs/ip_vs_proto_sctp.c index a0921adc31a9..1e689c714127 100644 --- a/net/netfilter/ipvs/ip_vs_proto_sctp.c +++ b/net/netfilter/ipvs/ip_vs_proto_sctp.c @@ -126,7 +126,8 @@ sctp_snat_handler(struct sk_buff *skb, struct ip_vs_protocol *pp, if (sctph->source != cp->vport || payload_csum || skb->ip_summed == CHECKSUM_PARTIAL) { sctph->source = cp->vport; - sctp_nat_csum(skb, sctph, sctphoff); + if (!skb_is_gso(skb) || !skb_is_gso_sctp(skb)) + sctp_nat_csum(skb, sctph, sctphoff); } else { skb->ip_summed = CHECKSUM_UNNECESSARY; } @@ -174,7 +175,8 @@ sctp_dnat_handler(struct sk_buff *skb, struct ip_vs_protocol *pp, (skb->ip_summed == CHECKSUM_PARTIAL && !(skb_dst(skb)->dev->features & NETIF_F_SCTP_CRC))) { sctph->dest = cp->dport; - sctp_nat_csum(skb, sctph, sctphoff); + if (!skb_is_gso(skb) || !skb_is_gso_sctp(skb)) + sctp_nat_csum(skb, sctph, sctphoff); } else if (skb->ip_summed != CHECKSUM_PARTIAL) { skb->ip_summed = CHECKSUM_UNNECESSARY; } -- cgit v1.2.3 From 5ea7b72d4fac2fdbc0425cd8f2ea33abe95235b2 Mon Sep 17 00:00:00 2001 From: Hyunwoo Kim Date: Mon, 22 Apr 2024 05:37:17 -0400 Subject: net: openvswitch: Fix Use-After-Free in ovs_ct_exit Since kfree_rcu, which is called in the hlist_for_each_entry_rcu traversal of ovs_ct_limit_exit, is not part of the RCU read critical section, it is possible that the RCU grace period will pass during the traversal and the key will be free. To prevent this, it should be changed to hlist_for_each_entry_safe. Fixes: 11efd5cb04a1 ("openvswitch: Support conntrack zone limit") Signed-off-by: Hyunwoo Kim Reviewed-by: Eric Dumazet Reviewed-by: Aaron Conole Link: https://lore.kernel.org/r/ZiYvzQN/Ry5oeFQW@v4bel-B760M-AORUS-ELITE-AX Signed-off-by: Jakub Kicinski --- net/openvswitch/conntrack.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/net/openvswitch/conntrack.c b/net/openvswitch/conntrack.c index 74b63cdb5992..2928c142a2dd 100644 --- a/net/openvswitch/conntrack.c +++ b/net/openvswitch/conntrack.c @@ -1593,9 +1593,9 @@ static void ovs_ct_limit_exit(struct net *net, struct ovs_net *ovs_net) for (i = 0; i < CT_LIMIT_HASH_BUCKETS; ++i) { struct hlist_head *head = &info->limits[i]; struct ovs_ct_limit *ct_limit; + struct hlist_node *next; - hlist_for_each_entry_rcu(ct_limit, head, hlist_node, - lockdep_ovsl_is_held()) + hlist_for_each_entry_safe(ct_limit, next, head, hlist_node) kfree_rcu(ct_limit, rcu); } kfree(info->limits); -- cgit v1.2.3 From 627f9c1bb882765a84aa78015abbacd783d429be Mon Sep 17 00:00:00 2001 From: Ido Schimmel Date: Mon, 22 Apr 2024 17:25:54 +0200 Subject: mlxsw: spectrum_acl_tcam: Fix race in region ID allocation Region identifiers can be allocated both when user space tries to insert a new tc filter and when filters are migrated from one region to another as part of the rehash delayed work. There is no lock protecting the bitmap from which these identifiers are allocated from, which is racy and leads to bad parameter errors from the device's firmware. Fix by converting the bitmap to IDA which handles its own locking. For consistency, do the same for the group identifiers that are part of the same structure. Fixes: 2bffc5322fd8 ("mlxsw: spectrum_acl: Don't take mutex in mlxsw_sp_acl_tcam_vregion_rehash_work()") Reported-by: Amit Cohen Signed-off-by: Ido Schimmel Tested-by: Alexander Zubkov Reviewed-by: Petr Machata Signed-off-by: Petr Machata Reviewed-by: Simon Horman Link: https://lore.kernel.org/r/ce494b7940cadfe84f3e18da7785b51ef5f776e3.1713797103.git.petrm@nvidia.com Signed-off-by: Jakub Kicinski --- .../ethernet/mellanox/mlxsw/spectrum_acl_tcam.c | 61 ++++++++++------------ .../ethernet/mellanox/mlxsw/spectrum_acl_tcam.h | 5 +- 2 files changed, 30 insertions(+), 36 deletions(-) diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.c index f20052776b3f..b6a4652a6475 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.c @@ -10,6 +10,7 @@ #include #include #include +#include #include #include @@ -58,41 +59,43 @@ int mlxsw_sp_acl_tcam_priority_get(struct mlxsw_sp *mlxsw_sp, static int mlxsw_sp_acl_tcam_region_id_get(struct mlxsw_sp_acl_tcam *tcam, u16 *p_id) { - u16 id; + int id; - id = find_first_zero_bit(tcam->used_regions, tcam->max_regions); - if (id < tcam->max_regions) { - __set_bit(id, tcam->used_regions); - *p_id = id; - return 0; - } - return -ENOBUFS; + id = ida_alloc_max(&tcam->used_regions, tcam->max_regions - 1, + GFP_KERNEL); + if (id < 0) + return id; + + *p_id = id; + + return 0; } static void mlxsw_sp_acl_tcam_region_id_put(struct mlxsw_sp_acl_tcam *tcam, u16 id) { - __clear_bit(id, tcam->used_regions); + ida_free(&tcam->used_regions, id); } static int mlxsw_sp_acl_tcam_group_id_get(struct mlxsw_sp_acl_tcam *tcam, u16 *p_id) { - u16 id; + int id; - id = find_first_zero_bit(tcam->used_groups, tcam->max_groups); - if (id < tcam->max_groups) { - __set_bit(id, tcam->used_groups); - *p_id = id; - return 0; - } - return -ENOBUFS; + id = ida_alloc_max(&tcam->used_groups, tcam->max_groups - 1, + GFP_KERNEL); + if (id < 0) + return id; + + *p_id = id; + + return 0; } static void mlxsw_sp_acl_tcam_group_id_put(struct mlxsw_sp_acl_tcam *tcam, u16 id) { - __clear_bit(id, tcam->used_groups); + ida_free(&tcam->used_groups, id); } struct mlxsw_sp_acl_tcam_pattern { @@ -1549,19 +1552,11 @@ int mlxsw_sp_acl_tcam_init(struct mlxsw_sp *mlxsw_sp, if (max_tcam_regions < max_regions) max_regions = max_tcam_regions; - tcam->used_regions = bitmap_zalloc(max_regions, GFP_KERNEL); - if (!tcam->used_regions) { - err = -ENOMEM; - goto err_alloc_used_regions; - } + ida_init(&tcam->used_regions); tcam->max_regions = max_regions; max_groups = MLXSW_CORE_RES_GET(mlxsw_sp->core, ACL_MAX_GROUPS); - tcam->used_groups = bitmap_zalloc(max_groups, GFP_KERNEL); - if (!tcam->used_groups) { - err = -ENOMEM; - goto err_alloc_used_groups; - } + ida_init(&tcam->used_groups); tcam->max_groups = max_groups; tcam->max_group_size = MLXSW_CORE_RES_GET(mlxsw_sp->core, ACL_MAX_GROUP_SIZE); @@ -1575,10 +1570,8 @@ int mlxsw_sp_acl_tcam_init(struct mlxsw_sp *mlxsw_sp, return 0; err_tcam_init: - bitmap_free(tcam->used_groups); -err_alloc_used_groups: - bitmap_free(tcam->used_regions); -err_alloc_used_regions: + ida_destroy(&tcam->used_groups); + ida_destroy(&tcam->used_regions); mlxsw_sp_acl_tcam_rehash_params_unregister(mlxsw_sp); err_rehash_params_register: mutex_destroy(&tcam->lock); @@ -1591,8 +1584,8 @@ void mlxsw_sp_acl_tcam_fini(struct mlxsw_sp *mlxsw_sp, const struct mlxsw_sp_acl_tcam_ops *ops = mlxsw_sp->acl_tcam_ops; ops->fini(mlxsw_sp, tcam->priv); - bitmap_free(tcam->used_groups); - bitmap_free(tcam->used_regions); + ida_destroy(&tcam->used_groups); + ida_destroy(&tcam->used_regions); mlxsw_sp_acl_tcam_rehash_params_unregister(mlxsw_sp); mutex_destroy(&tcam->lock); } diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.h b/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.h index 462bf448497d..79a1d8606512 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.h +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.h @@ -6,15 +6,16 @@ #include #include +#include #include "reg.h" #include "spectrum.h" #include "core_acl_flex_keys.h" struct mlxsw_sp_acl_tcam { - unsigned long *used_regions; /* bit array */ + struct ida used_regions; unsigned int max_regions; - unsigned long *used_groups; /* bit array */ + struct ida used_groups; unsigned int max_groups; unsigned int max_group_size; struct mutex lock; /* guards vregion list */ -- cgit v1.2.3 From d90cfe20562407d9f080d24123078d666d730707 Mon Sep 17 00:00:00 2001 From: Ido Schimmel Date: Mon, 22 Apr 2024 17:25:55 +0200 Subject: mlxsw: spectrum_acl_tcam: Fix race during rehash delayed work The purpose of the rehash delayed work is to reduce the number of masks (eRPs) used by an ACL region as the eRP bank is a global and limited resource. This is done in three steps: 1. Creating a new set of masks and a new ACL region which will use the new masks and to which the existing filters will be migrated to. The new region is assigned to 'vregion->region' and the region from which the filters are migrated from is assigned to 'vregion->region2'. 2. Migrating all the filters from the old region to the new region. 3. Destroying the old region and setting 'vregion->region2' to NULL. Only the second steps is performed under the 'vregion->lock' mutex although its comments says that among other things it "Protects consistency of region, region2 pointers". This is problematic as the first step can race with filter insertion from user space that uses 'vregion->region', but under the mutex. Fix by holding the mutex across the entirety of the delayed work and not only during the second step. Fixes: 2bffc5322fd8 ("mlxsw: spectrum_acl: Don't take mutex in mlxsw_sp_acl_tcam_vregion_rehash_work()") Signed-off-by: Ido Schimmel Tested-by: Alexander Zubkov Reviewed-by: Petr Machata Signed-off-by: Petr Machata Reviewed-by: Simon Horman Link: https://lore.kernel.org/r/1ec1d54edf2bad0a369e6b4fa030aba64e1f124b.1713797103.git.petrm@nvidia.com Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.c index b6a4652a6475..9c0c728bb42d 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.c @@ -718,7 +718,9 @@ static void mlxsw_sp_acl_tcam_vregion_rehash_work(struct work_struct *work) rehash.dw.work); int credits = MLXSW_SP_ACL_TCAM_VREGION_REHASH_CREDITS; + mutex_lock(&vregion->lock); mlxsw_sp_acl_tcam_vregion_rehash(vregion->mlxsw_sp, vregion, &credits); + mutex_unlock(&vregion->lock); if (credits < 0) /* Rehash gone out of credits so it was interrupted. * Schedule the work as soon as possible to continue. @@ -1323,7 +1325,6 @@ mlxsw_sp_acl_tcam_vregion_migrate(struct mlxsw_sp *mlxsw_sp, int err, err2; trace_mlxsw_sp_acl_tcam_vregion_migrate(mlxsw_sp, vregion); - mutex_lock(&vregion->lock); err = mlxsw_sp_acl_tcam_vchunk_migrate_all(mlxsw_sp, vregion, ctx, credits); if (err) { @@ -1343,7 +1344,6 @@ mlxsw_sp_acl_tcam_vregion_migrate(struct mlxsw_sp *mlxsw_sp, /* Let the rollback to be continued later on. */ } } - mutex_unlock(&vregion->lock); trace_mlxsw_sp_acl_tcam_vregion_migrate_end(mlxsw_sp, vregion); return err; } -- cgit v1.2.3 From 79b5b4b18bc85b19d3a518483f9abbbe6d7b3ba4 Mon Sep 17 00:00:00 2001 From: Ido Schimmel Date: Mon, 22 Apr 2024 17:25:56 +0200 Subject: mlxsw: spectrum_acl_tcam: Fix possible use-after-free during activity update The rule activity update delayed work periodically traverses the list of configured rules and queries their activity from the device. As part of this task it accesses the entry pointed by 'ventry->entry', but this entry can be changed concurrently by the rehash delayed work, leading to a use-after-free [1]. Fix by closing the race and perform the activity query under the 'vregion->lock' mutex. [1] BUG: KASAN: slab-use-after-free in mlxsw_sp_acl_tcam_flower_rule_activity_get+0x121/0x140 Read of size 8 at addr ffff8881054ed808 by task kworker/0:18/181 CPU: 0 PID: 181 Comm: kworker/0:18 Not tainted 6.9.0-rc2-custom-00781-gd5ab772d32f7 #2 Hardware name: Mellanox Technologies Ltd. MSN3700/VMOD0005, BIOS 5.11 01/06/2019 Workqueue: mlxsw_core mlxsw_sp_acl_rule_activity_update_work Call Trace: dump_stack_lvl+0xc6/0x120 print_report+0xce/0x670 kasan_report+0xd7/0x110 mlxsw_sp_acl_tcam_flower_rule_activity_get+0x121/0x140 mlxsw_sp_acl_rule_activity_update_work+0x219/0x400 process_one_work+0x8eb/0x19b0 worker_thread+0x6c9/0xf70 kthread+0x2c9/0x3b0 ret_from_fork+0x4d/0x80 ret_from_fork_asm+0x1a/0x30 Allocated by task 1039: kasan_save_stack+0x33/0x60 kasan_save_track+0x14/0x30 __kasan_kmalloc+0x8f/0xa0 __kmalloc+0x19c/0x360 mlxsw_sp_acl_tcam_entry_create+0x7b/0x1f0 mlxsw_sp_acl_tcam_vchunk_migrate_all+0x30d/0xb50 mlxsw_sp_acl_tcam_vregion_rehash_work+0x157/0x1300 process_one_work+0x8eb/0x19b0 worker_thread+0x6c9/0xf70 kthread+0x2c9/0x3b0 ret_from_fork+0x4d/0x80 ret_from_fork_asm+0x1a/0x30 Freed by task 1039: kasan_save_stack+0x33/0x60 kasan_save_track+0x14/0x30 kasan_save_free_info+0x3b/0x60 poison_slab_object+0x102/0x170 __kasan_slab_free+0x14/0x30 kfree+0xc1/0x290 mlxsw_sp_acl_tcam_vchunk_migrate_all+0x3d7/0xb50 mlxsw_sp_acl_tcam_vregion_rehash_work+0x157/0x1300 process_one_work+0x8eb/0x19b0 worker_thread+0x6c9/0xf70 kthread+0x2c9/0x3b0 ret_from_fork+0x4d/0x80 ret_from_fork_asm+0x1a/0x30 Fixes: 2bffc5322fd8 ("mlxsw: spectrum_acl: Don't take mutex in mlxsw_sp_acl_tcam_vregion_rehash_work()") Signed-off-by: Ido Schimmel Tested-by: Alexander Zubkov Reviewed-by: Petr Machata Signed-off-by: Petr Machata Reviewed-by: Simon Horman Link: https://lore.kernel.org/r/1fcce0a60b231ebeb2515d91022284ba7b4ffe7a.1713797103.git.petrm@nvidia.com Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.c index 9c0c728bb42d..7e69225c057d 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.c @@ -1159,8 +1159,14 @@ mlxsw_sp_acl_tcam_ventry_activity_get(struct mlxsw_sp *mlxsw_sp, struct mlxsw_sp_acl_tcam_ventry *ventry, bool *activity) { - return mlxsw_sp_acl_tcam_entry_activity_get(mlxsw_sp, - ventry->entry, activity); + struct mlxsw_sp_acl_tcam_vregion *vregion = ventry->vchunk->vregion; + int err; + + mutex_lock(&vregion->lock); + err = mlxsw_sp_acl_tcam_entry_activity_get(mlxsw_sp, ventry->entry, + activity); + mutex_unlock(&vregion->lock); + return err; } static int -- cgit v1.2.3 From 54225988889931467a9b55fdbef534079b665519 Mon Sep 17 00:00:00 2001 From: Ido Schimmel Date: Mon, 22 Apr 2024 17:25:57 +0200 Subject: mlxsw: spectrum_acl_tcam: Fix possible use-after-free during rehash The rehash delayed work migrates filters from one region to another according to the number of available credits. The migrated from region is destroyed at the end of the work if the number of credits is non-negative as the assumption is that this is indicative of migration being complete. This assumption is incorrect as a non-negative number of credits can also be the result of a failed migration. The destruction of a region that still has filters referencing it can result in a use-after-free [1]. Fix by not destroying the region if migration failed. [1] BUG: KASAN: slab-use-after-free in mlxsw_sp_acl_ctcam_region_entry_remove+0x21d/0x230 Read of size 8 at addr ffff8881735319e8 by task kworker/0:31/3858 CPU: 0 PID: 3858 Comm: kworker/0:31 Tainted: G W 6.9.0-rc2-custom-00782-gf2275c2157d8 #5 Hardware name: Mellanox Technologies Ltd. MSN3700/VMOD0005, BIOS 5.11 01/06/2019 Workqueue: mlxsw_core mlxsw_sp_acl_tcam_vregion_rehash_work Call Trace: dump_stack_lvl+0xc6/0x120 print_report+0xce/0x670 kasan_report+0xd7/0x110 mlxsw_sp_acl_ctcam_region_entry_remove+0x21d/0x230 mlxsw_sp_acl_ctcam_entry_del+0x2e/0x70 mlxsw_sp_acl_atcam_entry_del+0x81/0x210 mlxsw_sp_acl_tcam_vchunk_migrate_all+0x3cd/0xb50 mlxsw_sp_acl_tcam_vregion_rehash_work+0x157/0x1300 process_one_work+0x8eb/0x19b0 worker_thread+0x6c9/0xf70 kthread+0x2c9/0x3b0 ret_from_fork+0x4d/0x80 ret_from_fork_asm+0x1a/0x30 Allocated by task 174: kasan_save_stack+0x33/0x60 kasan_save_track+0x14/0x30 __kasan_kmalloc+0x8f/0xa0 __kmalloc+0x19c/0x360 mlxsw_sp_acl_tcam_region_create+0xdf/0x9c0 mlxsw_sp_acl_tcam_vregion_rehash_work+0x954/0x1300 process_one_work+0x8eb/0x19b0 worker_thread+0x6c9/0xf70 kthread+0x2c9/0x3b0 ret_from_fork+0x4d/0x80 ret_from_fork_asm+0x1a/0x30 Freed by task 7: kasan_save_stack+0x33/0x60 kasan_save_track+0x14/0x30 kasan_save_free_info+0x3b/0x60 poison_slab_object+0x102/0x170 __kasan_slab_free+0x14/0x30 kfree+0xc1/0x290 mlxsw_sp_acl_tcam_region_destroy+0x272/0x310 mlxsw_sp_acl_tcam_vregion_rehash_work+0x731/0x1300 process_one_work+0x8eb/0x19b0 worker_thread+0x6c9/0xf70 kthread+0x2c9/0x3b0 ret_from_fork+0x4d/0x80 ret_from_fork_asm+0x1a/0x30 Fixes: c9c9af91f1d9 ("mlxsw: spectrum_acl: Allow to interrupt/continue rehash work") Signed-off-by: Ido Schimmel Tested-by: Alexander Zubkov Reviewed-by: Petr Machata Signed-off-by: Petr Machata Reviewed-by: Simon Horman Link: https://lore.kernel.org/r/3e412b5659ec2310c5c615760dfe5eac18dd7ebd.1713797103.git.petrm@nvidia.com Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.c index 7e69225c057d..1ff0b2c7c11d 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.c @@ -1451,6 +1451,7 @@ mlxsw_sp_acl_tcam_vregion_rehash(struct mlxsw_sp *mlxsw_sp, ctx, credits); if (err) { dev_err(mlxsw_sp->bus_info->dev, "Failed to migrate vregion\n"); + return; } if (*credits >= 0) -- cgit v1.2.3 From 5bcf925587e9b5d36420d572a0b4d131c90fb306 Mon Sep 17 00:00:00 2001 From: Ido Schimmel Date: Mon, 22 Apr 2024 17:25:58 +0200 Subject: mlxsw: spectrum_acl_tcam: Rate limit error message In the rare cases when the device resources are exhausted it is likely that the rehash delayed work will fail. An error message will be printed whenever this happens which can be overwhelming considering the fact that the work is per-region and that there can be hundreds of regions. Fix by rate limiting the error message. Fixes: e5e7962ee5c2 ("mlxsw: spectrum_acl: Implement region migration according to hints") Signed-off-by: Ido Schimmel Tested-by: Alexander Zubkov Reviewed-by: Petr Machata Signed-off-by: Petr Machata Reviewed-by: Simon Horman Link: https://lore.kernel.org/r/c510763b2ebd25e7990d80183feff91cde593145.1713797103.git.petrm@nvidia.com Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.c index 1ff0b2c7c11d..568ae7092fe0 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.c @@ -1450,7 +1450,7 @@ mlxsw_sp_acl_tcam_vregion_rehash(struct mlxsw_sp *mlxsw_sp, err = mlxsw_sp_acl_tcam_vregion_migrate(mlxsw_sp, vregion, ctx, credits); if (err) { - dev_err(mlxsw_sp->bus_info->dev, "Failed to migrate vregion\n"); + dev_err_ratelimited(mlxsw_sp->bus_info->dev, "Failed to migrate vregion\n"); return; } -- cgit v1.2.3 From 8ca3f7a7b61393804c46f170743c3b839df13977 Mon Sep 17 00:00:00 2001 From: Ido Schimmel Date: Mon, 22 Apr 2024 17:25:59 +0200 Subject: mlxsw: spectrum_acl_tcam: Fix memory leak during rehash The rehash delayed work migrates filters from one region to another. This is done by iterating over all chunks (all the filters with the same priority) in the region and in each chunk iterating over all the filters. If the migration fails, the code tries to migrate the filters back to the old region. However, the rollback itself can also fail in which case another migration will be erroneously performed. Besides the fact that this ping pong is not a very good idea, it also creates a problem. Each virtual chunk references two chunks: The currently used one ('vchunk->chunk') and a backup ('vchunk->chunk2'). During migration the first holds the chunk we want to migrate filters to and the second holds the chunk we are migrating filters from. The code currently assumes - but does not verify - that the backup chunk does not exist (NULL) if the currently used chunk does not reference the target region. This assumption breaks when we are trying to rollback a rollback, resulting in the backup chunk being overwritten and leaked [1]. Fix by not rolling back a failed rollback and add a warning to avoid future cases. [1] WARNING: CPU: 5 PID: 1063 at lib/parman.c:291 parman_destroy+0x17/0x20 Modules linked in: CPU: 5 PID: 1063 Comm: kworker/5:11 Tainted: G W 6.9.0-rc2-custom-00784-gc6a05c468a0b #14 Hardware name: Mellanox Technologies Ltd. MSN3700/VMOD0005, BIOS 5.11 01/06/2019 Workqueue: mlxsw_core mlxsw_sp_acl_tcam_vregion_rehash_work RIP: 0010:parman_destroy+0x17/0x20 [...] Call Trace: mlxsw_sp_acl_atcam_region_fini+0x19/0x60 mlxsw_sp_acl_tcam_region_destroy+0x49/0xf0 mlxsw_sp_acl_tcam_vregion_rehash_work+0x1f1/0x470 process_one_work+0x151/0x370 worker_thread+0x2cb/0x3e0 kthread+0xd0/0x100 ret_from_fork+0x34/0x50 ret_from_fork_asm+0x1a/0x30 Fixes: 843500518509 ("mlxsw: spectrum_acl: Do rollback as another call to mlxsw_sp_acl_tcam_vchunk_migrate_all()") Signed-off-by: Ido Schimmel Tested-by: Alexander Zubkov Reviewed-by: Petr Machata Signed-off-by: Petr Machata Reviewed-by: Simon Horman Link: https://lore.kernel.org/r/d5edd4f4503934186ae5cfe268503b16345b4e0f.1713797103.git.petrm@nvidia.com Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.c index 568ae7092fe0..0902eb7651e1 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.c @@ -1200,6 +1200,8 @@ mlxsw_sp_acl_tcam_vchunk_migrate_start(struct mlxsw_sp *mlxsw_sp, { struct mlxsw_sp_acl_tcam_chunk *new_chunk; + WARN_ON(vchunk->chunk2); + new_chunk = mlxsw_sp_acl_tcam_chunk_create(mlxsw_sp, vchunk, region); if (IS_ERR(new_chunk)) return PTR_ERR(new_chunk); @@ -1334,6 +1336,8 @@ mlxsw_sp_acl_tcam_vregion_migrate(struct mlxsw_sp *mlxsw_sp, err = mlxsw_sp_acl_tcam_vchunk_migrate_all(mlxsw_sp, vregion, ctx, credits); if (err) { + if (ctx->this_is_rollback) + return err; /* In case migration was not successful, we need to swap * so the original region pointer is assigned again * to vregion->region. -- cgit v1.2.3 From 743edc8547a92b6192aa1f1b6bb78233fa21dc9b Mon Sep 17 00:00:00 2001 From: Ido Schimmel Date: Mon, 22 Apr 2024 17:26:00 +0200 Subject: mlxsw: spectrum_acl_tcam: Fix warning during rehash As previously explained, the rehash delayed work migrates filters from one region to another. This is done by iterating over all chunks (all the filters with the same priority) in the region and in each chunk iterating over all the filters. When the work runs out of credits it stores the current chunk and entry as markers in the per-work context so that it would know where to resume the migration from the next time the work is scheduled. Upon error, the chunk marker is reset to NULL, but without resetting the entry markers despite being relative to it. This can result in migration being resumed from an entry that does not belong to the chunk being migrated. In turn, this will eventually lead to a chunk being iterated over as if it is an entry. Because of how the two structures happen to be defined, this does not lead to KASAN splats, but to warnings such as [1]. Fix by creating a helper that resets all the markers and call it from all the places the currently only reset the chunk marker. For good measures also call it when starting a completely new rehash. Add a warning to avoid future cases. [1] WARNING: CPU: 7 PID: 1076 at drivers/net/ethernet/mellanox/mlxsw/core_acl_flex_keys.c:407 mlxsw_afk_encode+0x242/0x2f0 Modules linked in: CPU: 7 PID: 1076 Comm: kworker/7:24 Tainted: G W 6.9.0-rc3-custom-00880-g29e61d91b77b #29 Hardware name: Mellanox Technologies Ltd. MSN3700/VMOD0005, BIOS 5.11 01/06/2019 Workqueue: mlxsw_core mlxsw_sp_acl_tcam_vregion_rehash_work RIP: 0010:mlxsw_afk_encode+0x242/0x2f0 [...] Call Trace: mlxsw_sp_acl_atcam_entry_add+0xd9/0x3c0 mlxsw_sp_acl_tcam_entry_create+0x5e/0xa0 mlxsw_sp_acl_tcam_vchunk_migrate_all+0x109/0x290 mlxsw_sp_acl_tcam_vregion_rehash_work+0x6c/0x470 process_one_work+0x151/0x370 worker_thread+0x2cb/0x3e0 kthread+0xd0/0x100 ret_from_fork+0x34/0x50 Fixes: 6f9579d4e302 ("mlxsw: spectrum_acl: Remember where to continue rehash migration") Signed-off-by: Ido Schimmel Tested-by: Alexander Zubkov Reviewed-by: Petr Machata Signed-off-by: Petr Machata Reviewed-by: Simon Horman Link: https://lore.kernel.org/r/cc17eed86b41dd829d39b07906fec074a9ce580e.1713797103.git.petrm@nvidia.com Signed-off-by: Jakub Kicinski --- .../net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.c | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.c index 0902eb7651e1..e8c607886621 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.c @@ -730,6 +730,17 @@ static void mlxsw_sp_acl_tcam_vregion_rehash_work(struct work_struct *work) mlxsw_sp_acl_tcam_vregion_rehash_work_schedule(vregion); } +static void +mlxsw_sp_acl_tcam_rehash_ctx_vchunk_reset(struct mlxsw_sp_acl_tcam_rehash_ctx *ctx) +{ + /* The entry markers are relative to the current chunk and therefore + * needs to be reset together with the chunk marker. + */ + ctx->current_vchunk = NULL; + ctx->start_ventry = NULL; + ctx->stop_ventry = NULL; +} + static void mlxsw_sp_acl_tcam_rehash_ctx_vchunk_changed(struct mlxsw_sp_acl_tcam_vchunk *vchunk) { @@ -752,7 +763,7 @@ mlxsw_sp_acl_tcam_rehash_ctx_vregion_changed(struct mlxsw_sp_acl_tcam_vregion *v * the current chunk pointer to make sure all chunks * are properly migrated. */ - vregion->rehash.ctx.current_vchunk = NULL; + mlxsw_sp_acl_tcam_rehash_ctx_vchunk_reset(&vregion->rehash.ctx); } static struct mlxsw_sp_acl_tcam_vregion * @@ -1220,7 +1231,7 @@ mlxsw_sp_acl_tcam_vchunk_migrate_end(struct mlxsw_sp *mlxsw_sp, { mlxsw_sp_acl_tcam_chunk_destroy(mlxsw_sp, vchunk->chunk2); vchunk->chunk2 = NULL; - ctx->current_vchunk = NULL; + mlxsw_sp_acl_tcam_rehash_ctx_vchunk_reset(ctx); } static int @@ -1252,6 +1263,8 @@ mlxsw_sp_acl_tcam_vchunk_migrate_one(struct mlxsw_sp *mlxsw_sp, ventry = list_first_entry(&vchunk->ventry_list, typeof(*ventry), list); + WARN_ON(ventry->vchunk != vchunk); + list_for_each_entry_from(ventry, &vchunk->ventry_list, list) { /* During rollback, once we reach the ventry that failed * to migrate, we are done. @@ -1343,7 +1356,7 @@ mlxsw_sp_acl_tcam_vregion_migrate(struct mlxsw_sp *mlxsw_sp, * to vregion->region. */ swap(vregion->region, vregion->region2); - ctx->current_vchunk = NULL; + mlxsw_sp_acl_tcam_rehash_ctx_vchunk_reset(ctx); ctx->this_is_rollback = true; err2 = mlxsw_sp_acl_tcam_vchunk_migrate_all(mlxsw_sp, vregion, ctx, credits); @@ -1402,6 +1415,7 @@ mlxsw_sp_acl_tcam_vregion_rehash_start(struct mlxsw_sp *mlxsw_sp, ctx->hints_priv = hints_priv; ctx->this_is_rollback = false; + mlxsw_sp_acl_tcam_rehash_ctx_vchunk_reset(ctx); return 0; -- cgit v1.2.3 From b377add0f0117409c418ddd6504bd682ebe0bf79 Mon Sep 17 00:00:00 2001 From: Ido Schimmel Date: Mon, 22 Apr 2024 17:26:01 +0200 Subject: mlxsw: spectrum_acl_tcam: Fix incorrect list API usage Both the function that migrates all the chunks within a region and the function that migrates all the entries within a chunk call list_first_entry() on the respective lists without checking that the lists are not empty. This is incorrect usage of the API, which leads to the following warning [1]. Fix by returning if the lists are empty as there is nothing to migrate in this case. [1] WARNING: CPU: 0 PID: 6437 at drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.c:1266 mlxsw_sp_acl_tcam_vchunk_migrate_all+0x1f1/0> Modules linked in: CPU: 0 PID: 6437 Comm: kworker/0:37 Not tainted 6.9.0-rc3-custom-00883-g94a65f079ef6 #39 Hardware name: Mellanox Technologies Ltd. MSN3700/VMOD0005, BIOS 5.11 01/06/2019 Workqueue: mlxsw_core mlxsw_sp_acl_tcam_vregion_rehash_work RIP: 0010:mlxsw_sp_acl_tcam_vchunk_migrate_all+0x1f1/0x2c0 [...] Call Trace: mlxsw_sp_acl_tcam_vregion_rehash_work+0x6c/0x4a0 process_one_work+0x151/0x370 worker_thread+0x2cb/0x3e0 kthread+0xd0/0x100 ret_from_fork+0x34/0x50 ret_from_fork_asm+0x1a/0x30 Fixes: 6f9579d4e302 ("mlxsw: spectrum_acl: Remember where to continue rehash migration") Signed-off-by: Ido Schimmel Tested-by: Alexander Zubkov Reviewed-by: Petr Machata Signed-off-by: Petr Machata Reviewed-by: Simon Horman Link: https://lore.kernel.org/r/4628e9a22d1d84818e28310abbbc498e7bc31bc9.1713797103.git.petrm@nvidia.com Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.c index e8c607886621..89a5ebc3463f 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.c @@ -1254,6 +1254,9 @@ mlxsw_sp_acl_tcam_vchunk_migrate_one(struct mlxsw_sp *mlxsw_sp, return 0; } + if (list_empty(&vchunk->ventry_list)) + goto out; + /* If the migration got interrupted, we have the ventry to start from * stored in context. */ @@ -1305,6 +1308,7 @@ mlxsw_sp_acl_tcam_vchunk_migrate_one(struct mlxsw_sp *mlxsw_sp, } } +out: mlxsw_sp_acl_tcam_vchunk_migrate_end(mlxsw_sp, vchunk, ctx); return 0; } @@ -1318,6 +1322,9 @@ mlxsw_sp_acl_tcam_vchunk_migrate_all(struct mlxsw_sp *mlxsw_sp, struct mlxsw_sp_acl_tcam_vchunk *vchunk; int err; + if (list_empty(&vregion->vchunk_list)) + return 0; + /* If the migration got interrupted, we have the vchunk * we are working on stored in context. */ -- cgit v1.2.3 From fb4e2b70a7194b209fc7320bbf33b375f7114bd5 Mon Sep 17 00:00:00 2001 From: Ido Schimmel Date: Mon, 22 Apr 2024 17:26:02 +0200 Subject: mlxsw: spectrum_acl_tcam: Fix memory leak when canceling rehash work The rehash delayed work is rescheduled with a delay if the number of credits at end of the work is not negative as supposedly it means that the migration ended. Otherwise, it is rescheduled immediately. After "mlxsw: spectrum_acl_tcam: Fix possible use-after-free during rehash" the above is no longer accurate as a non-negative number of credits is no longer indicative of the migration being done. It can also happen if the work encountered an error in which case the migration will resume the next time the work is scheduled. The significance of the above is that it is possible for the work to be pending and associated with hints that were allocated when the migration started. This leads to the hints being leaked [1] when the work is canceled while pending as part of ACL region dismantle. Fix by freeing the hints if hints are associated with a work that was canceled while pending. Blame the original commit since the reliance on not having a pending work associated with hints is fragile. [1] unreferenced object 0xffff88810e7c3000 (size 256): comm "kworker/0:16", pid 176, jiffies 4295460353 hex dump (first 32 bytes): 00 30 95 11 81 88 ff ff 61 00 00 00 00 00 00 80 .0......a....... 00 00 61 00 40 00 00 00 00 00 00 00 04 00 00 00 ..a.@........... backtrace (crc 2544ddb9): [<00000000cf8cfab3>] kmalloc_trace+0x23f/0x2a0 [<000000004d9a1ad9>] objagg_hints_get+0x42/0x390 [<000000000b143cf3>] mlxsw_sp_acl_erp_rehash_hints_get+0xca/0x400 [<0000000059bdb60a>] mlxsw_sp_acl_tcam_vregion_rehash_work+0x868/0x1160 [<00000000e81fd734>] process_one_work+0x59c/0xf20 [<00000000ceee9e81>] worker_thread+0x799/0x12c0 [<00000000bda6fe39>] kthread+0x246/0x300 [<0000000070056d23>] ret_from_fork+0x34/0x70 [<00000000dea2b93e>] ret_from_fork_asm+0x1a/0x30 Fixes: c9c9af91f1d9 ("mlxsw: spectrum_acl: Allow to interrupt/continue rehash work") Signed-off-by: Ido Schimmel Tested-by: Alexander Zubkov Signed-off-by: Petr Machata Reviewed-by: Simon Horman Link: https://lore.kernel.org/r/0cc12ebb07c4d4c41a1265ee2c28b392ff997a86.1713797103.git.petrm@nvidia.com Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.c index 89a5ebc3463f..92a406f02eae 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_tcam.c @@ -836,10 +836,14 @@ mlxsw_sp_acl_tcam_vregion_destroy(struct mlxsw_sp *mlxsw_sp, struct mlxsw_sp_acl_tcam *tcam = vregion->tcam; if (vgroup->vregion_rehash_enabled && ops->region_rehash_hints_get) { + struct mlxsw_sp_acl_tcam_rehash_ctx *ctx = &vregion->rehash.ctx; + mutex_lock(&tcam->lock); list_del(&vregion->tlist); mutex_unlock(&tcam->lock); - cancel_delayed_work_sync(&vregion->rehash.dw); + if (cancel_delayed_work_sync(&vregion->rehash.dw) && + ctx->hints_priv) + ops->region_rehash_hints_put(ctx->hints_priv); } mlxsw_sp_acl_tcam_vgroup_vregion_detach(mlxsw_sp, vregion); if (vregion->region2) -- cgit v1.2.3 From 8d6bf83f6740ba52a59e25dad360e1e87ef47666 Mon Sep 17 00:00:00 2001 From: Duanqiang Wen Date: Mon, 22 Apr 2024 16:41:08 +0800 Subject: Revert "net: txgbe: fix i2c dev name cannot match clkdev" This reverts commit c644920ce9220d83e070f575a4df711741c07f07. when register i2c dev, txgbe shorten "i2c_designware" to "i2c_dw", will cause this i2c dev can't match platfom driver i2c_designware_platform. Signed-off-by: Duanqiang Wen Reviewed-by: Jacob Keller Link: https://lore.kernel.org/r/20240422084109.3201-1-duanqiangwen@net-swift.com Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/wangxun/txgbe/txgbe_phy.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/drivers/net/ethernet/wangxun/txgbe/txgbe_phy.c b/drivers/net/ethernet/wangxun/txgbe/txgbe_phy.c index 2fa511227eac..5b5d5e4310d1 100644 --- a/drivers/net/ethernet/wangxun/txgbe/txgbe_phy.c +++ b/drivers/net/ethernet/wangxun/txgbe/txgbe_phy.c @@ -20,8 +20,6 @@ #include "txgbe_phy.h" #include "txgbe_hw.h" -#define TXGBE_I2C_CLK_DEV_NAME "i2c_dw" - static int txgbe_swnodes_register(struct txgbe *txgbe) { struct txgbe_nodes *nodes = &txgbe->nodes; @@ -573,8 +571,8 @@ static int txgbe_clock_register(struct txgbe *txgbe) char clk_name[32]; struct clk *clk; - snprintf(clk_name, sizeof(clk_name), "%s.%d", - TXGBE_I2C_CLK_DEV_NAME, pci_dev_id(pdev)); + snprintf(clk_name, sizeof(clk_name), "i2c_dw.%d", + pci_dev_id(pdev)); clk = clk_register_fixed_rate(NULL, clk_name, NULL, 0, 156250000); if (IS_ERR(clk)) @@ -636,7 +634,7 @@ static int txgbe_i2c_register(struct txgbe *txgbe) info.parent = &pdev->dev; info.fwnode = software_node_fwnode(txgbe->nodes.group[SWNODE_I2C]); - info.name = TXGBE_I2C_CLK_DEV_NAME; + info.name = "i2c_designware"; info.id = pci_dev_id(pdev); info.res = &DEFINE_RES_IRQ(pdev->irq); -- cgit v1.2.3 From edd2d250fb3bb5d70419ae82c1f9dbb9684dffd3 Mon Sep 17 00:00:00 2001 From: Duanqiang Wen Date: Mon, 22 Apr 2024 16:41:09 +0800 Subject: Revert "net: txgbe: fix clk_name exceed MAX_DEV_ID limits" This reverts commit e30cef001da259e8df354b813015d0e5acc08740. commit 99f4570cfba1 ("clkdev: Update clkdev id usage to allow for longer names") can fix clk_name exceed MAX_DEV_ID limits, so this commit is meaningless. Signed-off-by: Duanqiang Wen Reviewed-by: Jacob Keller Link: https://lore.kernel.org/r/20240422084109.3201-2-duanqiangwen@net-swift.com Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/wangxun/txgbe/txgbe_phy.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/ethernet/wangxun/txgbe/txgbe_phy.c b/drivers/net/ethernet/wangxun/txgbe/txgbe_phy.c index 5b5d5e4310d1..93295916b1d2 100644 --- a/drivers/net/ethernet/wangxun/txgbe/txgbe_phy.c +++ b/drivers/net/ethernet/wangxun/txgbe/txgbe_phy.c @@ -571,7 +571,7 @@ static int txgbe_clock_register(struct txgbe *txgbe) char clk_name[32]; struct clk *clk; - snprintf(clk_name, sizeof(clk_name), "i2c_dw.%d", + snprintf(clk_name, sizeof(clk_name), "i2c_designware.%d", pci_dev_id(pdev)); clk = clk_register_fixed_rate(NULL, clk_name, NULL, 0, 156250000); -- cgit v1.2.3 From c04d1b9ecce565455652ac3c6b17043cd475cf47 Mon Sep 17 00:00:00 2001 From: Lukas Wunner Date: Mon, 22 Apr 2024 13:45:02 -0700 Subject: igc: Fix LED-related deadlock on driver unbind MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Roman reports a deadlock on unplug of a Thunderbolt docking station containing an Intel I225 Ethernet adapter. The root cause is that led_classdev's for LEDs on the adapter are registered such that they're device-managed by the netdev. That results in recursive acquisition of the rtnl_lock() mutex on unplug: When the driver calls unregister_netdev(), it acquires rtnl_lock(), then frees the device-managed resources. Upon unregistering the LEDs, netdev_trig_deactivate() invokes unregister_netdevice_notifier(), which tries to acquire rtnl_lock() again. Avoid by using non-device-managed LED registration. Stack trace for posterity: schedule+0x6e/0xf0 schedule_preempt_disabled+0x15/0x20 __mutex_lock+0x2a0/0x750 unregister_netdevice_notifier+0x40/0x150 netdev_trig_deactivate+0x1f/0x60 [ledtrig_netdev] led_trigger_set+0x102/0x330 led_classdev_unregister+0x4b/0x110 release_nodes+0x3d/0xb0 devres_release_all+0x8b/0xc0 device_del+0x34f/0x3c0 unregister_netdevice_many_notify+0x80b/0xaf0 unregister_netdev+0x7c/0xd0 igc_remove+0xd8/0x1e0 [igc] pci_device_remove+0x3f/0xb0 Fixes: ea578703b03d ("igc: Add support for LEDs on i225/i226") Reported-by: Roman Lozko Closes: https://lore.kernel.org/r/CAEhC_B=ksywxCG_+aQqXUrGEgKq+4mqnSV8EBHOKbC3-Obj9+Q@mail.gmail.com/ Reported-by: "Marek Marczykowski-Górecki" Closes: https://lore.kernel.org/r/ZhRD3cOtz5i-61PB@mail-itl/ Signed-off-by: Kurt Kanzenbach Signed-off-by: Lukas Wunner Cc: Heiner Kallweit Reviewed-by: Simon Horman Reviewed-by: Kurt Kanzenbach Tested-by: Kurt Kanzenbach # Intel i225 Tested-by: Naama Meir Signed-off-by: Tony Nguyen Link: https://lore.kernel.org/r/20240422204503.225448-1-anthony.l.nguyen@intel.com Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/intel/igc/igc.h | 2 ++ drivers/net/ethernet/intel/igc/igc_leds.c | 38 ++++++++++++++++++++++++------- drivers/net/ethernet/intel/igc/igc_main.c | 3 +++ 3 files changed, 35 insertions(+), 8 deletions(-) diff --git a/drivers/net/ethernet/intel/igc/igc.h b/drivers/net/ethernet/intel/igc/igc.h index 90316dc58630..6bc56c7c181e 100644 --- a/drivers/net/ethernet/intel/igc/igc.h +++ b/drivers/net/ethernet/intel/igc/igc.h @@ -298,6 +298,7 @@ struct igc_adapter { /* LEDs */ struct mutex led_mutex; + struct igc_led_classdev *leds; }; void igc_up(struct igc_adapter *adapter); @@ -723,6 +724,7 @@ void igc_ptp_read(struct igc_adapter *adapter, struct timespec64 *ts); void igc_ptp_tx_tstamp_event(struct igc_adapter *adapter); int igc_led_setup(struct igc_adapter *adapter); +void igc_led_free(struct igc_adapter *adapter); #define igc_rx_pg_size(_ring) (PAGE_SIZE << igc_rx_pg_order(_ring)) diff --git a/drivers/net/ethernet/intel/igc/igc_leds.c b/drivers/net/ethernet/intel/igc/igc_leds.c index bf240c5daf86..3929b25b6ae6 100644 --- a/drivers/net/ethernet/intel/igc/igc_leds.c +++ b/drivers/net/ethernet/intel/igc/igc_leds.c @@ -236,8 +236,8 @@ static void igc_led_get_name(struct igc_adapter *adapter, int index, char *buf, pci_dev_id(adapter->pdev), index); } -static void igc_setup_ldev(struct igc_led_classdev *ldev, - struct net_device *netdev, int index) +static int igc_setup_ldev(struct igc_led_classdev *ldev, + struct net_device *netdev, int index) { struct igc_adapter *adapter = netdev_priv(netdev); struct led_classdev *led_cdev = &ldev->led; @@ -257,24 +257,46 @@ static void igc_setup_ldev(struct igc_led_classdev *ldev, led_cdev->hw_control_get = igc_led_hw_control_get; led_cdev->hw_control_get_device = igc_led_hw_control_get_device; - devm_led_classdev_register(&netdev->dev, led_cdev); + return led_classdev_register(&netdev->dev, led_cdev); } int igc_led_setup(struct igc_adapter *adapter) { struct net_device *netdev = adapter->netdev; - struct device *dev = &netdev->dev; struct igc_led_classdev *leds; - int i; + int i, err; mutex_init(&adapter->led_mutex); - leds = devm_kcalloc(dev, IGC_NUM_LEDS, sizeof(*leds), GFP_KERNEL); + leds = kcalloc(IGC_NUM_LEDS, sizeof(*leds), GFP_KERNEL); if (!leds) return -ENOMEM; - for (i = 0; i < IGC_NUM_LEDS; i++) - igc_setup_ldev(leds + i, netdev, i); + for (i = 0; i < IGC_NUM_LEDS; i++) { + err = igc_setup_ldev(leds + i, netdev, i); + if (err) + goto err; + } + + adapter->leds = leds; return 0; + +err: + for (i--; i >= 0; i--) + led_classdev_unregister(&((leds + i)->led)); + + kfree(leds); + return err; +} + +void igc_led_free(struct igc_adapter *adapter) +{ + struct igc_led_classdev *leds = adapter->leds; + int i; + + for (i = 0; i < IGC_NUM_LEDS; i++) + led_classdev_unregister(&((leds + i)->led)); + + kfree(leds); } diff --git a/drivers/net/ethernet/intel/igc/igc_main.c b/drivers/net/ethernet/intel/igc/igc_main.c index 35ad40a803cb..4d975d620a8e 100644 --- a/drivers/net/ethernet/intel/igc/igc_main.c +++ b/drivers/net/ethernet/intel/igc/igc_main.c @@ -7021,6 +7021,9 @@ static void igc_remove(struct pci_dev *pdev) cancel_work_sync(&adapter->watchdog_task); hrtimer_cancel(&adapter->hrtimer); + if (IS_ENABLED(CONFIG_IGC_LEDS)) + igc_led_free(adapter); + /* Release control of h/w to f/w. If f/w is AMT enabled, this * would have already happened in close and is redundant. */ -- cgit v1.2.3 From 730117730709992c9f6535dd7b47638ee561ec45 Mon Sep 17 00:00:00 2001 From: Jakub Kicinski Date: Tue, 23 Apr 2024 17:21:48 -0700 Subject: eth: bnxt: fix counting packets discarded due to OOM and netpoll I added OOM and netpoll discard counters, naively assuming that the cpr pointer is pointing to a common completion ring. Turns out that is usually *a* completion ring but not *the* completion ring which bnapi->cp_ring points to. bnapi->cp_ring is where the stats are read from, so we end up reporting 0 thru ethtool -S and qstat even though the drop events have happened. Make 100% sure we're recording statistics in the correct structure. Fixes: 907fd4a294db ("bnxt: count discards due to memory allocation errors") Reviewed-by: Michael Chan Link: https://lore.kernel.org/r/20240424002148.3937059-1-kuba@kernel.org Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/broadcom/bnxt/bnxt.c | 44 +++++++++++++------------------ 1 file changed, 18 insertions(+), 26 deletions(-) diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.c b/drivers/net/ethernet/broadcom/bnxt/bnxt.c index ed04a90a4fdd..2c2ee79c4d77 100644 --- a/drivers/net/ethernet/broadcom/bnxt/bnxt.c +++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.c @@ -1778,7 +1778,7 @@ static inline struct sk_buff *bnxt_tpa_end(struct bnxt *bp, skb = bnxt_copy_skb(bnapi, data_ptr, len, mapping); if (!skb) { bnxt_abort_tpa(cpr, idx, agg_bufs); - cpr->sw_stats.rx.rx_oom_discards += 1; + cpr->bnapi->cp_ring.sw_stats.rx.rx_oom_discards += 1; return NULL; } } else { @@ -1788,7 +1788,7 @@ static inline struct sk_buff *bnxt_tpa_end(struct bnxt *bp, new_data = __bnxt_alloc_rx_frag(bp, &new_mapping, GFP_ATOMIC); if (!new_data) { bnxt_abort_tpa(cpr, idx, agg_bufs); - cpr->sw_stats.rx.rx_oom_discards += 1; + cpr->bnapi->cp_ring.sw_stats.rx.rx_oom_discards += 1; return NULL; } @@ -1804,7 +1804,7 @@ static inline struct sk_buff *bnxt_tpa_end(struct bnxt *bp, if (!skb) { skb_free_frag(data); bnxt_abort_tpa(cpr, idx, agg_bufs); - cpr->sw_stats.rx.rx_oom_discards += 1; + cpr->bnapi->cp_ring.sw_stats.rx.rx_oom_discards += 1; return NULL; } skb_reserve(skb, bp->rx_offset); @@ -1815,7 +1815,7 @@ static inline struct sk_buff *bnxt_tpa_end(struct bnxt *bp, skb = bnxt_rx_agg_pages_skb(bp, cpr, skb, idx, agg_bufs, true); if (!skb) { /* Page reuse already handled by bnxt_rx_pages(). */ - cpr->sw_stats.rx.rx_oom_discards += 1; + cpr->bnapi->cp_ring.sw_stats.rx.rx_oom_discards += 1; return NULL; } } @@ -2094,11 +2094,8 @@ static int bnxt_rx_pkt(struct bnxt *bp, struct bnxt_cp_ring_info *cpr, u32 frag_len = bnxt_rx_agg_pages_xdp(bp, cpr, &xdp, cp_cons, agg_bufs, false); - if (!frag_len) { - cpr->sw_stats.rx.rx_oom_discards += 1; - rc = -ENOMEM; - goto next_rx; - } + if (!frag_len) + goto oom_next_rx; } xdp_active = true; } @@ -2121,9 +2118,7 @@ static int bnxt_rx_pkt(struct bnxt *bp, struct bnxt_cp_ring_info *cpr, else bnxt_xdp_buff_frags_free(rxr, &xdp); } - cpr->sw_stats.rx.rx_oom_discards += 1; - rc = -ENOMEM; - goto next_rx; + goto oom_next_rx; } } else { u32 payload; @@ -2134,29 +2129,21 @@ static int bnxt_rx_pkt(struct bnxt *bp, struct bnxt_cp_ring_info *cpr, payload = 0; skb = bp->rx_skb_func(bp, rxr, cons, data, data_ptr, dma_addr, payload | len); - if (!skb) { - cpr->sw_stats.rx.rx_oom_discards += 1; - rc = -ENOMEM; - goto next_rx; - } + if (!skb) + goto oom_next_rx; } if (agg_bufs) { if (!xdp_active) { skb = bnxt_rx_agg_pages_skb(bp, cpr, skb, cp_cons, agg_bufs, false); - if (!skb) { - cpr->sw_stats.rx.rx_oom_discards += 1; - rc = -ENOMEM; - goto next_rx; - } + if (!skb) + goto oom_next_rx; } else { skb = bnxt_xdp_build_skb(bp, skb, agg_bufs, rxr->page_pool, &xdp, rxcmp1); if (!skb) { /* we should be able to free the old skb here */ bnxt_xdp_buff_frags_free(rxr, &xdp); - cpr->sw_stats.rx.rx_oom_discards += 1; - rc = -ENOMEM; - goto next_rx; + goto oom_next_rx; } } } @@ -2234,6 +2221,11 @@ next_rx_no_prod_no_len: *raw_cons = tmp_raw_cons; return rc; + +oom_next_rx: + cpr->bnapi->cp_ring.sw_stats.rx.rx_oom_discards += 1; + rc = -ENOMEM; + goto next_rx; } /* In netpoll mode, if we are using a combined completion ring, we need to @@ -2280,7 +2272,7 @@ static int bnxt_force_rx_discard(struct bnxt *bp, } rc = bnxt_rx_pkt(bp, cpr, raw_cons, event); if (rc && rc != -EBUSY) - cpr->sw_stats.rx.rx_netpoll_discards += 1; + cpr->bnapi->cp_ring.sw_stats.rx.rx_netpoll_discards += 1; return rc; } -- cgit v1.2.3 From 8e30abc9ace4f0add4cd761dfdbfaebae5632dd2 Mon Sep 17 00:00:00 2001 From: Pablo Neira Ayuso Date: Wed, 24 Apr 2024 20:45:01 +0200 Subject: netfilter: nf_tables: honor table dormant flag from netdev release event path Check for table dormant flag otherwise netdev release event path tries to unregister an already unregistered hook. [524854.857999] ------------[ cut here ]------------ [524854.858010] WARNING: CPU: 0 PID: 3386599 at net/netfilter/core.c:501 __nf_unregister_net_hook+0x21a/0x260 [...] [524854.858848] CPU: 0 PID: 3386599 Comm: kworker/u32:2 Not tainted 6.9.0-rc3+ #365 [524854.858869] Workqueue: netns cleanup_net [524854.858886] RIP: 0010:__nf_unregister_net_hook+0x21a/0x260 [524854.858903] Code: 24 e8 aa 73 83 ff 48 63 43 1c 83 f8 01 0f 85 3d ff ff ff e8 98 d1 f0 ff 48 8b 3c 24 e8 8f 73 83 ff 48 63 43 1c e9 26 ff ff ff <0f> 0b 48 83 c4 18 48 c7 c7 00 68 e9 82 5b 5d 41 5c 41 5d 41 5e 41 [524854.858914] RSP: 0018:ffff8881e36d79e0 EFLAGS: 00010246 [524854.858926] RAX: 0000000000000000 RBX: ffff8881339ae790 RCX: ffffffff81ba524a [524854.858936] RDX: dffffc0000000000 RSI: 0000000000000008 RDI: ffff8881c8a16438 [524854.858945] RBP: ffff8881c8a16438 R08: 0000000000000001 R09: ffffed103c6daf34 [524854.858954] R10: ffff8881e36d79a7 R11: 0000000000000000 R12: 0000000000000005 [524854.858962] R13: ffff8881c8a16000 R14: 0000000000000000 R15: ffff8881351b5a00 [524854.858971] FS: 0000000000000000(0000) GS:ffff888390800000(0000) knlGS:0000000000000000 [524854.858982] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 [524854.858991] CR2: 00007fc9be0f16f4 CR3: 00000001437cc004 CR4: 00000000001706f0 [524854.859000] Call Trace: [524854.859006] [524854.859013] ? __warn+0x9f/0x1a0 [524854.859027] ? __nf_unregister_net_hook+0x21a/0x260 [524854.859044] ? report_bug+0x1b1/0x1e0 [524854.859060] ? handle_bug+0x3c/0x70 [524854.859071] ? exc_invalid_op+0x17/0x40 [524854.859083] ? asm_exc_invalid_op+0x1a/0x20 [524854.859100] ? __nf_unregister_net_hook+0x6a/0x260 [524854.859116] ? __nf_unregister_net_hook+0x21a/0x260 [524854.859135] nf_tables_netdev_event+0x337/0x390 [nf_tables] [524854.859304] ? __pfx_nf_tables_netdev_event+0x10/0x10 [nf_tables] [524854.859461] ? packet_notifier+0xb3/0x360 [524854.859476] ? _raw_spin_unlock_irqrestore+0x11/0x40 [524854.859489] ? dcbnl_netdevice_event+0x35/0x140 [524854.859507] ? __pfx_nf_tables_netdev_event+0x10/0x10 [nf_tables] [524854.859661] notifier_call_chain+0x7d/0x140 [524854.859677] unregister_netdevice_many_notify+0x5e1/0xae0 Fixes: d54725cd11a5 ("netfilter: nf_tables: support for multiple devices per netdev hook") Signed-off-by: Pablo Neira Ayuso --- net/netfilter/nft_chain_filter.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/net/netfilter/nft_chain_filter.c b/net/netfilter/nft_chain_filter.c index 274b6f7e6bb5..d170758a1eb5 100644 --- a/net/netfilter/nft_chain_filter.c +++ b/net/netfilter/nft_chain_filter.c @@ -338,7 +338,9 @@ static void nft_netdev_event(unsigned long event, struct net_device *dev, return; if (n > 1) { - nf_unregister_net_hook(ctx->net, &found->ops); + if (!(ctx->chain->table->flags & NFT_TABLE_F_DORMANT)) + nf_unregister_net_hook(ctx->net, &found->ops); + list_del_rcu(&found->list); kfree_rcu(found, rcu); return; -- cgit v1.2.3 From 6c9cd59dbcb09a2122b5ce0dfc07c74e6fc00dc0 Mon Sep 17 00:00:00 2001 From: MD Danish Anwar Date: Tue, 23 Apr 2024 14:18:28 +0530 Subject: net: phy: dp83869: Fix MII mode failure The DP83869 driver sets the MII bit (needed for PHY to work in MII mode) only if the op-mode is either DP83869_100M_MEDIA_CONVERT or DP83869_RGMII_100_BASE. Some drivers i.e. ICSSG support MII mode with op-mode as DP83869_RGMII_COPPER_ETHERNET for which the MII bit is not set in dp83869 driver. As a result MII mode on ICSSG doesn't work and below log is seen. TI DP83869 300b2400.mdio:0f: selected op-mode is not valid with MII mode icssg-prueth icssg1-eth: couldn't connect to phy ethernet-phy@0 icssg-prueth icssg1-eth: can't phy connect port MII0 Fix this by setting MII bit for DP83869_RGMII_COPPER_ETHERNET op-mode as well. Fixes: 94e86ef1b801 ("net: phy: dp83869: support mii mode when rgmii strap cfg is used") Signed-off-by: MD Danish Anwar Reviewed-by: Ravi Gunasekaran Signed-off-by: David S. Miller --- drivers/net/phy/dp83869.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/net/phy/dp83869.c b/drivers/net/phy/dp83869.c index fa8c6fdcf301..d7aaefb5226b 100644 --- a/drivers/net/phy/dp83869.c +++ b/drivers/net/phy/dp83869.c @@ -695,7 +695,8 @@ static int dp83869_configure_mode(struct phy_device *phydev, phy_ctrl_val = dp83869->mode; if (phydev->interface == PHY_INTERFACE_MODE_MII) { if (dp83869->mode == DP83869_100M_MEDIA_CONVERT || - dp83869->mode == DP83869_RGMII_100_BASE) { + dp83869->mode == DP83869_RGMII_100_BASE || + dp83869->mode == DP83869_RGMII_COPPER_ETHERNET) { phy_ctrl_val |= DP83869_OP_MODE_MII; } else { phydev_err(phydev, "selected op-mode is not valid with MII mode\n"); -- cgit v1.2.3 From 475747a19316b08e856c666a20503e73d7ed67ed Mon Sep 17 00:00:00 2001 From: Rahul Rameshbabu Date: Tue, 23 Apr 2024 11:13:02 -0700 Subject: macsec: Enable devices to advertise whether they update sk_buff md_dst during offloads Cannot know whether a Rx skb missing md_dst is intended for MACsec or not without knowing whether the device is able to update this field during an offload. Assume that an offload to a MACsec device cannot support updating md_dst by default. Capable devices can advertise that they do indicate that an skb is related to a MACsec offloaded packet using the md_dst. Cc: Sabrina Dubroca Cc: stable@vger.kernel.org Fixes: 860ead89b851 ("net/macsec: Add MACsec skb_metadata_dst Rx Data path support") Signed-off-by: Rahul Rameshbabu Reviewed-by: Benjamin Poirier Reviewed-by: Cosmin Ratiu Reviewed-by: Sabrina Dubroca Link: https://lore.kernel.org/r/20240423181319.115860-2-rrameshbabu@nvidia.com Signed-off-by: Jakub Kicinski --- include/net/macsec.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/include/net/macsec.h b/include/net/macsec.h index dbd22180cc5c..de216cbc6b05 100644 --- a/include/net/macsec.h +++ b/include/net/macsec.h @@ -321,6 +321,7 @@ struct macsec_context { * for the TX tag * @needed_tailroom: number of bytes reserved at the end of the sk_buff for the * TX tag + * @rx_uses_md_dst: whether MACsec device offload supports sk_buff md_dst */ struct macsec_ops { /* Device wide */ @@ -352,6 +353,7 @@ struct macsec_ops { struct sk_buff *skb); unsigned int needed_headroom; unsigned int needed_tailroom; + bool rx_uses_md_dst; }; void macsec_pn_wrapped(struct macsec_secy *secy, struct macsec_tx_sa *tx_sa); -- cgit v1.2.3 From 6e159fd653d7ebf6290358e0330a0cb8a75cf73b Mon Sep 17 00:00:00 2001 From: Rahul Rameshbabu Date: Tue, 23 Apr 2024 11:13:03 -0700 Subject: ethernet: Add helper for assigning packet type when dest address does not match device address Enable reuse of logic in eth_type_trans for determining packet type. Suggested-by: Sabrina Dubroca Cc: stable@vger.kernel.org Signed-off-by: Rahul Rameshbabu Reviewed-by: Sabrina Dubroca Link: https://lore.kernel.org/r/20240423181319.115860-3-rrameshbabu@nvidia.com Signed-off-by: Jakub Kicinski --- include/linux/etherdevice.h | 25 +++++++++++++++++++++++++ net/ethernet/eth.c | 12 +----------- 2 files changed, 26 insertions(+), 11 deletions(-) diff --git a/include/linux/etherdevice.h b/include/linux/etherdevice.h index 224645f17c33..297231854ada 100644 --- a/include/linux/etherdevice.h +++ b/include/linux/etherdevice.h @@ -607,6 +607,31 @@ static inline void eth_hw_addr_gen(struct net_device *dev, const u8 *base_addr, eth_hw_addr_set(dev, addr); } +/** + * eth_skb_pkt_type - Assign packet type if destination address does not match + * @skb: Assigned a packet type if address does not match @dev address + * @dev: Network device used to compare packet address against + * + * If the destination MAC address of the packet does not match the network + * device address, assign an appropriate packet type. + */ +static inline void eth_skb_pkt_type(struct sk_buff *skb, + const struct net_device *dev) +{ + const struct ethhdr *eth = eth_hdr(skb); + + if (unlikely(!ether_addr_equal_64bits(eth->h_dest, dev->dev_addr))) { + if (unlikely(is_multicast_ether_addr_64bits(eth->h_dest))) { + if (ether_addr_equal_64bits(eth->h_dest, dev->broadcast)) + skb->pkt_type = PACKET_BROADCAST; + else + skb->pkt_type = PACKET_MULTICAST; + } else { + skb->pkt_type = PACKET_OTHERHOST; + } + } +} + /** * eth_skb_pad - Pad buffer to mininum number of octets for Ethernet frame * @skb: Buffer to pad diff --git a/net/ethernet/eth.c b/net/ethernet/eth.c index 2edc8b796a4e..049c3adeb850 100644 --- a/net/ethernet/eth.c +++ b/net/ethernet/eth.c @@ -164,17 +164,7 @@ __be16 eth_type_trans(struct sk_buff *skb, struct net_device *dev) eth = (struct ethhdr *)skb->data; skb_pull_inline(skb, ETH_HLEN); - if (unlikely(!ether_addr_equal_64bits(eth->h_dest, - dev->dev_addr))) { - if (unlikely(is_multicast_ether_addr_64bits(eth->h_dest))) { - if (ether_addr_equal_64bits(eth->h_dest, dev->broadcast)) - skb->pkt_type = PACKET_BROADCAST; - else - skb->pkt_type = PACKET_MULTICAST; - } else { - skb->pkt_type = PACKET_OTHERHOST; - } - } + eth_skb_pkt_type(skb, dev); /* * Some variants of DSA tagging don't have an ethertype field -- cgit v1.2.3 From 642c984dd0e37dbaec9f87bd1211e5fac1f142bf Mon Sep 17 00:00:00 2001 From: Rahul Rameshbabu Date: Tue, 23 Apr 2024 11:13:04 -0700 Subject: macsec: Detect if Rx skb is macsec-related for offloading devices that update md_dst Can now correctly identify where the packets should be delivered by using md_dst or its absence on devices that provide it. This detection is not possible without device drivers that update md_dst. A fallback pattern should be used for supporting such device drivers. This fallback mode causes multicast messages to be cloned to both the non-macsec and macsec ports, independent of whether the multicast message received was encrypted over MACsec or not. Other non-macsec traffic may also fail to be handled correctly for devices in promiscuous mode. Link: https://lore.kernel.org/netdev/ZULRxX9eIbFiVi7v@hog/ Cc: Sabrina Dubroca Cc: stable@vger.kernel.org Fixes: 860ead89b851 ("net/macsec: Add MACsec skb_metadata_dst Rx Data path support") Signed-off-by: Rahul Rameshbabu Reviewed-by: Benjamin Poirier Reviewed-by: Cosmin Ratiu Reviewed-by: Sabrina Dubroca Link: https://lore.kernel.org/r/20240423181319.115860-4-rrameshbabu@nvidia.com Signed-off-by: Jakub Kicinski --- drivers/net/macsec.c | 46 ++++++++++++++++++++++++++++++++++++---------- 1 file changed, 36 insertions(+), 10 deletions(-) diff --git a/drivers/net/macsec.c b/drivers/net/macsec.c index 0206b84284ab..ff016c11b4a0 100644 --- a/drivers/net/macsec.c +++ b/drivers/net/macsec.c @@ -999,10 +999,12 @@ static enum rx_handler_result handle_not_macsec(struct sk_buff *skb) struct metadata_dst *md_dst; struct macsec_rxh_data *rxd; struct macsec_dev *macsec; + bool is_macsec_md_dst; rcu_read_lock(); rxd = macsec_data_rcu(skb->dev); md_dst = skb_metadata_dst(skb); + is_macsec_md_dst = md_dst && md_dst->type == METADATA_MACSEC; list_for_each_entry_rcu(macsec, &rxd->secys, secys) { struct sk_buff *nskb; @@ -1013,14 +1015,42 @@ static enum rx_handler_result handle_not_macsec(struct sk_buff *skb) * the SecTAG, so we have to deduce which port to deliver to. */ if (macsec_is_offloaded(macsec) && netif_running(ndev)) { - struct macsec_rx_sc *rx_sc = NULL; + const struct macsec_ops *ops; - if (md_dst && md_dst->type == METADATA_MACSEC) - rx_sc = find_rx_sc(&macsec->secy, md_dst->u.macsec_info.sci); + ops = macsec_get_ops(macsec, NULL); - if (md_dst && md_dst->type == METADATA_MACSEC && !rx_sc) + if (ops->rx_uses_md_dst && !is_macsec_md_dst) continue; + if (is_macsec_md_dst) { + struct macsec_rx_sc *rx_sc; + + /* All drivers that implement MACsec offload + * support using skb metadata destinations must + * indicate that they do so. + */ + DEBUG_NET_WARN_ON_ONCE(!ops->rx_uses_md_dst); + rx_sc = find_rx_sc(&macsec->secy, + md_dst->u.macsec_info.sci); + if (!rx_sc) + continue; + /* device indicated macsec offload occurred */ + skb->dev = ndev; + skb->pkt_type = PACKET_HOST; + eth_skb_pkt_type(skb, ndev); + ret = RX_HANDLER_ANOTHER; + goto out; + } + + /* This datapath is insecure because it is unable to + * enforce isolation of broadcast/multicast traffic and + * unicast traffic with promiscuous mode on the macsec + * netdev. Since the core stack has no mechanism to + * check that the hardware did indeed receive MACsec + * traffic, it is possible that the response handling + * done by the MACsec port was to a plaintext packet. + * This violates the MACsec protocol standard. + */ if (ether_addr_equal_64bits(hdr->h_dest, ndev->dev_addr)) { /* exact match, divert skb to this port */ @@ -1036,14 +1066,10 @@ static enum rx_handler_result handle_not_macsec(struct sk_buff *skb) break; nskb->dev = ndev; - if (ether_addr_equal_64bits(hdr->h_dest, - ndev->broadcast)) - nskb->pkt_type = PACKET_BROADCAST; - else - nskb->pkt_type = PACKET_MULTICAST; + eth_skb_pkt_type(nskb, ndev); __netif_rx(nskb); - } else if (rx_sc || ndev->flags & IFF_PROMISC) { + } else if (ndev->flags & IFF_PROMISC) { skb->dev = ndev; skb->pkt_type = PACKET_HOST; ret = RX_HANDLER_ANOTHER; -- cgit v1.2.3 From 39d26a8f2efcb8b5665fe7d54a7dba306a8f1dff Mon Sep 17 00:00:00 2001 From: Rahul Rameshbabu Date: Tue, 23 Apr 2024 11:13:05 -0700 Subject: net/mlx5e: Advertise mlx5 ethernet driver updates sk_buff md_dst for MACsec mlx5 Rx flow steering and CQE handling enable the driver to be able to update an skb's md_dst attribute as MACsec when MACsec traffic arrives when a device is configured for offloading. Advertise this to the core stack to take advantage of this capability. Cc: stable@vger.kernel.org Fixes: b7c9400cbc48 ("net/mlx5e: Implement MACsec Rx data path using MACsec skb_metadata_dst") Signed-off-by: Rahul Rameshbabu Reviewed-by: Benjamin Poirier Reviewed-by: Cosmin Ratiu Reviewed-by: Sabrina Dubroca Link: https://lore.kernel.org/r/20240423181319.115860-5-rrameshbabu@nvidia.com Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/mellanox/mlx5/core/en_accel/macsec.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/macsec.c b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/macsec.c index b2cabd6ab86c..cc9bcc420032 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/macsec.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/macsec.c @@ -1640,6 +1640,7 @@ static const struct macsec_ops macsec_offload_ops = { .mdo_add_secy = mlx5e_macsec_add_secy, .mdo_upd_secy = mlx5e_macsec_upd_secy, .mdo_del_secy = mlx5e_macsec_del_secy, + .rx_uses_md_dst = true, }; bool mlx5e_macsec_handle_tx_skb(struct mlx5e_macsec *macsec, struct sk_buff *skb) -- cgit v1.2.3 From 4dcd0e83ea1d1df9b2e0174a6d3e795b3477d64e Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Tue, 23 Apr 2024 19:15:22 +0300 Subject: net: ti: icssg-prueth: Fix signedness bug in prueth_init_rx_chns() The rx_chn->irq[] array is unsigned int but it should be signed for the error handling to work. Also if k3_udma_glue_rx_get_irq() returns zero then we should return -ENXIO instead of success. Fixes: 128d5874c082 ("net: ti: icssg-prueth: Add ICSSG ethernet driver") Signed-off-by: Dan Carpenter Reviewed-by: Roger Quadros Reviewed-by: MD Danish Anwar Link: https://lore.kernel.org/r/05282415-e7f4-42f3-99f8-32fde8f30936@moroto.mountain Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/ti/icssg/icssg_prueth.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/drivers/net/ethernet/ti/icssg/icssg_prueth.c b/drivers/net/ethernet/ti/icssg/icssg_prueth.c index cf7b73f8f450..b69af69a1ccd 100644 --- a/drivers/net/ethernet/ti/icssg/icssg_prueth.c +++ b/drivers/net/ethernet/ti/icssg/icssg_prueth.c @@ -421,12 +421,14 @@ static int prueth_init_rx_chns(struct prueth_emac *emac, if (!i) fdqring_id = k3_udma_glue_rx_flow_get_fdq_id(rx_chn->rx_chn, i); - rx_chn->irq[i] = k3_udma_glue_rx_get_irq(rx_chn->rx_chn, i); - if (rx_chn->irq[i] <= 0) { - ret = rx_chn->irq[i]; + ret = k3_udma_glue_rx_get_irq(rx_chn->rx_chn, i); + if (ret <= 0) { + if (!ret) + ret = -ENXIO; netdev_err(ndev, "Failed to get rx dma irq"); goto fail; } + rx_chn->irq[i] = ret; } return 0; -- cgit v1.2.3 From 2cc7d150550cc981aceedf008f5459193282425c Mon Sep 17 00:00:00 2001 From: Sindhu Devale Date: Tue, 23 Apr 2024 11:27:17 -0700 Subject: i40e: Do not use WQ_MEM_RECLAIM flag for workqueue Issue reported by customer during SRIOV testing, call trace: When both i40e and the i40iw driver are loaded, a warning in check_flush_dependency is being triggered. This seems to be because of the i40e driver workqueue is allocated with the WQ_MEM_RECLAIM flag, and the i40iw one is not. Similar error was encountered on ice too and it was fixed by removing the flag. Do the same for i40e too. [Feb 9 09:08] ------------[ cut here ]------------ [ +0.000004] workqueue: WQ_MEM_RECLAIM i40e:i40e_service_task [i40e] is flushing !WQ_MEM_RECLAIM infiniband:0x0 [ +0.000060] WARNING: CPU: 0 PID: 937 at kernel/workqueue.c:2966 check_flush_dependency+0x10b/0x120 [ +0.000007] Modules linked in: snd_seq_dummy snd_hrtimer snd_seq snd_timer snd_seq_device snd soundcore nls_utf8 cifs cifs_arc4 nls_ucs2_utils rdma_cm iw_cm ib_cm cifs_md4 dns_resolver netfs qrtr rfkill sunrpc vfat fat intel_rapl_msr intel_rapl_common irdma intel_uncore_frequency intel_uncore_frequency_common ice ipmi_ssif isst_if_common skx_edac nfit libnvdimm x86_pkg_temp_thermal intel_powerclamp gnss coretemp ib_uverbs rapl intel_cstate ib_core iTCO_wdt iTCO_vendor_support acpi_ipmi mei_me ipmi_si intel_uncore ioatdma i2c_i801 joydev pcspkr mei ipmi_devintf lpc_ich intel_pch_thermal i2c_smbus ipmi_msghandler acpi_power_meter acpi_pad xfs libcrc32c ast sd_mod drm_shmem_helper t10_pi drm_kms_helper sg ixgbe drm i40e ahci crct10dif_pclmul libahci crc32_pclmul igb crc32c_intel libata ghash_clmulni_intel i2c_algo_bit mdio dca wmi dm_mirror dm_region_hash dm_log dm_mod fuse [ +0.000050] CPU: 0 PID: 937 Comm: kworker/0:3 Kdump: loaded Not tainted 6.8.0-rc2-Feb-net_dev-Qiueue-00279-gbd43c5687e05 #1 [ +0.000003] Hardware name: Intel Corporation S2600BPB/S2600BPB, BIOS SE5C620.86B.02.01.0013.121520200651 12/15/2020 [ +0.000001] Workqueue: i40e i40e_service_task [i40e] [ +0.000024] RIP: 0010:check_flush_dependency+0x10b/0x120 [ +0.000003] Code: ff 49 8b 54 24 18 48 8d 8b b0 00 00 00 49 89 e8 48 81 c6 b0 00 00 00 48 c7 c7 b0 97 fa 9f c6 05 8a cc 1f 02 01 e8 35 b3 fd ff <0f> 0b e9 10 ff ff ff 80 3d 78 cc 1f 02 00 75 94 e9 46 ff ff ff 90 [ +0.000002] RSP: 0018:ffffbd294976bcf8 EFLAGS: 00010282 [ +0.000002] RAX: 0000000000000000 RBX: ffff94d4c483c000 RCX: 0000000000000027 [ +0.000001] RDX: ffff94d47f620bc8 RSI: 0000000000000001 RDI: ffff94d47f620bc0 [ +0.000001] RBP: 0000000000000000 R08: 0000000000000000 R09: 00000000ffff7fff [ +0.000001] R10: ffffbd294976bb98 R11: ffffffffa0be65e8 R12: ffff94c5451ea180 [ +0.000001] R13: ffff94c5ab5e8000 R14: ffff94c5c20b6e05 R15: ffff94c5f1330ab0 [ +0.000001] FS: 0000000000000000(0000) GS:ffff94d47f600000(0000) knlGS:0000000000000000 [ +0.000002] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 [ +0.000001] CR2: 00007f9e6f1fca70 CR3: 0000000038e20004 CR4: 00000000007706f0 [ +0.000000] DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 [ +0.000001] DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400 [ +0.000001] PKRU: 55555554 [ +0.000001] Call Trace: [ +0.000001] [ +0.000002] ? __warn+0x80/0x130 [ +0.000003] ? check_flush_dependency+0x10b/0x120 [ +0.000002] ? report_bug+0x195/0x1a0 [ +0.000005] ? handle_bug+0x3c/0x70 [ +0.000003] ? exc_invalid_op+0x14/0x70 [ +0.000002] ? asm_exc_invalid_op+0x16/0x20 [ +0.000006] ? check_flush_dependency+0x10b/0x120 [ +0.000002] ? check_flush_dependency+0x10b/0x120 [ +0.000002] __flush_workqueue+0x126/0x3f0 [ +0.000015] ib_cache_cleanup_one+0x1c/0xe0 [ib_core] [ +0.000056] __ib_unregister_device+0x6a/0xb0 [ib_core] [ +0.000023] ib_unregister_device_and_put+0x34/0x50 [ib_core] [ +0.000020] i40iw_close+0x4b/0x90 [irdma] [ +0.000022] i40e_notify_client_of_netdev_close+0x54/0xc0 [i40e] [ +0.000035] i40e_service_task+0x126/0x190 [i40e] [ +0.000024] process_one_work+0x174/0x340 [ +0.000003] worker_thread+0x27e/0x390 [ +0.000001] ? __pfx_worker_thread+0x10/0x10 [ +0.000002] kthread+0xdf/0x110 [ +0.000002] ? __pfx_kthread+0x10/0x10 [ +0.000002] ret_from_fork+0x2d/0x50 [ +0.000003] ? __pfx_kthread+0x10/0x10 [ +0.000001] ret_from_fork_asm+0x1b/0x30 [ +0.000004] [ +0.000001] ---[ end trace 0000000000000000 ]--- Fixes: 4d5957cbdecd ("i40e: remove WQ_UNBOUND and the task limit of our workqueue") Signed-off-by: Sindhu Devale Reviewed-by: Arkadiusz Kubalewski Reviewed-by: Mateusz Polchlopek Signed-off-by: Aleksandr Loktionov Tested-by: Robert Ganzynkowicz Signed-off-by: Tony Nguyen Link: https://lore.kernel.org/r/20240423182723.740401-2-anthony.l.nguyen@intel.com Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/intel/i40e/i40e_main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c index 48b9ddb2b1b3..1792491d8d2d 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_main.c +++ b/drivers/net/ethernet/intel/i40e/i40e_main.c @@ -16650,7 +16650,7 @@ static int __init i40e_init_module(void) * since we need to be able to guarantee forward progress even under * memory pressure. */ - i40e_wq = alloc_workqueue("%s", WQ_MEM_RECLAIM, 0, i40e_driver_name); + i40e_wq = alloc_workqueue("%s", 0, 0, i40e_driver_name); if (!i40e_wq) { pr_err("%s: Failed to create workqueue\n", i40e_driver_name); return -ENOMEM; -- cgit v1.2.3 From ef3c313119ea448c22da10366faa26b5b4b1a18e Mon Sep 17 00:00:00 2001 From: Erwan Velu Date: Tue, 23 Apr 2024 11:27:18 -0700 Subject: i40e: Report MFS in decimal base instead of hex If the MFS is set below the default (0x2600), a warning message is reported like the following : MFS for port 1 has been set below the default: 600 This message is a bit confusing as the number shown here (600) is in fact an hexa number: 0x600 = 1536 Without any explicit "0x" prefix, this message is read like the MFS is set to 600 bytes. MFS, as per MTUs, are usually expressed in decimal base. This commit reports both current and default MFS values in decimal so it's less confusing for end-users. A typical warning message looks like the following : MFS for port 1 (1536) has been set below the default (9728) Signed-off-by: Erwan Velu Reviewed-by: Simon Horman Tested-by: Tony Brelinski Signed-off-by: Tony Nguyen Fixes: 3a2c6ced90e1 ("i40e: Add a check to see if MFS is set") Link: https://lore.kernel.org/r/20240423182723.740401-3-anthony.l.nguyen@intel.com Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/intel/i40e/i40e_main.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c index 1792491d8d2d..ffb9f9f15c52 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_main.c +++ b/drivers/net/ethernet/intel/i40e/i40e_main.c @@ -16107,8 +16107,8 @@ static int i40e_probe(struct pci_dev *pdev, const struct pci_device_id *ent) val = FIELD_GET(I40E_PRTGL_SAH_MFS_MASK, rd32(&pf->hw, I40E_PRTGL_SAH)); if (val < MAX_FRAME_SIZE_DEFAULT) - dev_warn(&pdev->dev, "MFS for port %x has been set below the default: %x\n", - pf->hw.port, val); + dev_warn(&pdev->dev, "MFS for port %x (%d) has been set below the default (%d)\n", + pf->hw.port, val, MAX_FRAME_SIZE_DEFAULT); /* Add a filter to drop all Flow control frames from any VSI from being * transmitted. By doing so we stop a malicious VF from sending out -- cgit v1.2.3 From 54976cf58d6168b8d15cebb395069f23b2f34b31 Mon Sep 17 00:00:00 2001 From: Sudheer Mogilappagari Date: Tue, 23 Apr 2024 11:27:19 -0700 Subject: iavf: Fix TC config comparison with existing adapter TC config Same number of TCs doesn't imply that underlying TC configs are same. The config could be different due to difference in number of queues in each TC. Add utility function to determine if TC configs are same. Fixes: d5b33d024496 ("i40evf: add ndo_setup_tc callback to i40evf") Signed-off-by: Sudheer Mogilappagari Tested-by: Mineri Bhange (A Contingent Worker at Intel) Signed-off-by: Tony Nguyen Link: https://lore.kernel.org/r/20240423182723.740401-4-anthony.l.nguyen@intel.com Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/intel/iavf/iavf_main.c | 30 ++++++++++++++++++++++++++++- 1 file changed, 29 insertions(+), 1 deletion(-) diff --git a/drivers/net/ethernet/intel/iavf/iavf_main.c b/drivers/net/ethernet/intel/iavf/iavf_main.c index ef2440f3abf8..166832a4213a 100644 --- a/drivers/net/ethernet/intel/iavf/iavf_main.c +++ b/drivers/net/ethernet/intel/iavf/iavf_main.c @@ -3502,6 +3502,34 @@ static void iavf_del_all_cloud_filters(struct iavf_adapter *adapter) spin_unlock_bh(&adapter->cloud_filter_list_lock); } +/** + * iavf_is_tc_config_same - Compare the mqprio TC config with the + * TC config already configured on this adapter. + * @adapter: board private structure + * @mqprio_qopt: TC config received from kernel. + * + * This function compares the TC config received from the kernel + * with the config already configured on the adapter. + * + * Return: True if configuration is same, false otherwise. + **/ +static bool iavf_is_tc_config_same(struct iavf_adapter *adapter, + struct tc_mqprio_qopt *mqprio_qopt) +{ + struct virtchnl_channel_info *ch = &adapter->ch_config.ch_info[0]; + int i; + + if (adapter->num_tc != mqprio_qopt->num_tc) + return false; + + for (i = 0; i < adapter->num_tc; i++) { + if (ch[i].count != mqprio_qopt->count[i] || + ch[i].offset != mqprio_qopt->offset[i]) + return false; + } + return true; +} + /** * __iavf_setup_tc - configure multiple traffic classes * @netdev: network interface device structure @@ -3559,7 +3587,7 @@ static int __iavf_setup_tc(struct net_device *netdev, void *type_data) if (ret) return ret; /* Return if same TC config is requested */ - if (adapter->num_tc == num_tc) + if (iavf_is_tc_config_same(adapter, &mqprio_qopt->qopt)) return 0; adapter->num_tc = num_tc; -- cgit v1.2.3 From 96fdd1f6b4ed72a741fb0eb705c0e13049b8721f Mon Sep 17 00:00:00 2001 From: Jacob Keller Date: Tue, 23 Apr 2024 11:27:20 -0700 Subject: ice: fix LAG and VF lock dependency in ice_reset_vf() 9f74a3dfcf83 ("ice: Fix VF Reset paths when interface in a failed over aggregate"), the ice driver has acquired the LAG mutex in ice_reset_vf(). The commit placed this lock acquisition just prior to the acquisition of the VF configuration lock. If ice_reset_vf() acquires the configuration lock via the ICE_VF_RESET_LOCK flag, this could deadlock with ice_vc_cfg_qs_msg() because it always acquires the locks in the order of the VF configuration lock and then the LAG mutex. Lockdep reports this violation almost immediately on creating and then removing 2 VF: ====================================================== WARNING: possible circular locking dependency detected 6.8.0-rc6 #54 Tainted: G W O ------------------------------------------------------ kworker/60:3/6771 is trying to acquire lock: ff40d43e099380a0 (&vf->cfg_lock){+.+.}-{3:3}, at: ice_reset_vf+0x22f/0x4d0 [ice] but task is already holding lock: ff40d43ea1961210 (&pf->lag_mutex){+.+.}-{3:3}, at: ice_reset_vf+0xb7/0x4d0 [ice] which lock already depends on the new lock. the existing dependency chain (in reverse order) is: -> #1 (&pf->lag_mutex){+.+.}-{3:3}: __lock_acquire+0x4f8/0xb40 lock_acquire+0xd4/0x2d0 __mutex_lock+0x9b/0xbf0 ice_vc_cfg_qs_msg+0x45/0x690 [ice] ice_vc_process_vf_msg+0x4f5/0x870 [ice] __ice_clean_ctrlq+0x2b5/0x600 [ice] ice_service_task+0x2c9/0x480 [ice] process_one_work+0x1e9/0x4d0 worker_thread+0x1e1/0x3d0 kthread+0x104/0x140 ret_from_fork+0x31/0x50 ret_from_fork_asm+0x1b/0x30 -> #0 (&vf->cfg_lock){+.+.}-{3:3}: check_prev_add+0xe2/0xc50 validate_chain+0x558/0x800 __lock_acquire+0x4f8/0xb40 lock_acquire+0xd4/0x2d0 __mutex_lock+0x9b/0xbf0 ice_reset_vf+0x22f/0x4d0 [ice] ice_process_vflr_event+0x98/0xd0 [ice] ice_service_task+0x1cc/0x480 [ice] process_one_work+0x1e9/0x4d0 worker_thread+0x1e1/0x3d0 kthread+0x104/0x140 ret_from_fork+0x31/0x50 ret_from_fork_asm+0x1b/0x30 other info that might help us debug this: Possible unsafe locking scenario: CPU0 CPU1 ---- ---- lock(&pf->lag_mutex); lock(&vf->cfg_lock); lock(&pf->lag_mutex); lock(&vf->cfg_lock); *** DEADLOCK *** 4 locks held by kworker/60:3/6771: #0: ff40d43e05428b38 ((wq_completion)ice){+.+.}-{0:0}, at: process_one_work+0x176/0x4d0 #1: ff50d06e05197e58 ((work_completion)(&pf->serv_task)){+.+.}-{0:0}, at: process_one_work+0x176/0x4d0 #2: ff40d43ea1960e50 (&pf->vfs.table_lock){+.+.}-{3:3}, at: ice_process_vflr_event+0x48/0xd0 [ice] #3: ff40d43ea1961210 (&pf->lag_mutex){+.+.}-{3:3}, at: ice_reset_vf+0xb7/0x4d0 [ice] stack backtrace: CPU: 60 PID: 6771 Comm: kworker/60:3 Tainted: G W O 6.8.0-rc6 #54 Hardware name: Workqueue: ice ice_service_task [ice] Call Trace: dump_stack_lvl+0x4a/0x80 check_noncircular+0x12d/0x150 check_prev_add+0xe2/0xc50 ? save_trace+0x59/0x230 ? add_chain_cache+0x109/0x450 validate_chain+0x558/0x800 __lock_acquire+0x4f8/0xb40 ? lockdep_hardirqs_on+0x7d/0x100 lock_acquire+0xd4/0x2d0 ? ice_reset_vf+0x22f/0x4d0 [ice] ? lock_is_held_type+0xc7/0x120 __mutex_lock+0x9b/0xbf0 ? ice_reset_vf+0x22f/0x4d0 [ice] ? ice_reset_vf+0x22f/0x4d0 [ice] ? rcu_is_watching+0x11/0x50 ? ice_reset_vf+0x22f/0x4d0 [ice] ice_reset_vf+0x22f/0x4d0 [ice] ? process_one_work+0x176/0x4d0 ice_process_vflr_event+0x98/0xd0 [ice] ice_service_task+0x1cc/0x480 [ice] process_one_work+0x1e9/0x4d0 worker_thread+0x1e1/0x3d0 ? __pfx_worker_thread+0x10/0x10 kthread+0x104/0x140 ? __pfx_kthread+0x10/0x10 ret_from_fork+0x31/0x50 ? __pfx_kthread+0x10/0x10 ret_from_fork_asm+0x1b/0x30 To avoid deadlock, we must acquire the LAG mutex only after acquiring the VF configuration lock. Fix the ice_reset_vf() to acquire the LAG mutex only after we either acquire or check that the VF configuration lock is held. Fixes: 9f74a3dfcf83 ("ice: Fix VF Reset paths when interface in a failed over aggregate") Signed-off-by: Jacob Keller Reviewed-by: Dave Ertman Reviewed-by: Mateusz Polchlopek Tested-by: Przemek Kitszel Tested-by: Rafal Romanowski Signed-off-by: Tony Nguyen Link: https://lore.kernel.org/r/20240423182723.740401-5-anthony.l.nguyen@intel.com Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/intel/ice/ice_vf_lib.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/drivers/net/ethernet/intel/ice/ice_vf_lib.c b/drivers/net/ethernet/intel/ice/ice_vf_lib.c index 21d26e19338a..d10a4be965b5 100644 --- a/drivers/net/ethernet/intel/ice/ice_vf_lib.c +++ b/drivers/net/ethernet/intel/ice/ice_vf_lib.c @@ -856,6 +856,11 @@ int ice_reset_vf(struct ice_vf *vf, u32 flags) return 0; } + if (flags & ICE_VF_RESET_LOCK) + mutex_lock(&vf->cfg_lock); + else + lockdep_assert_held(&vf->cfg_lock); + lag = pf->lag; mutex_lock(&pf->lag_mutex); if (lag && lag->bonded && lag->primary) { @@ -867,11 +872,6 @@ int ice_reset_vf(struct ice_vf *vf, u32 flags) act_prt = ICE_LAG_INVALID_PORT; } - if (flags & ICE_VF_RESET_LOCK) - mutex_lock(&vf->cfg_lock); - else - lockdep_assert_held(&vf->cfg_lock); - if (ice_is_vf_disabled(vf)) { vsi = ice_get_vf_vsi(vf); if (!vsi) { @@ -956,14 +956,14 @@ int ice_reset_vf(struct ice_vf *vf, u32 flags) ice_mbx_clear_malvf(&vf->mbx_info); out_unlock: - if (flags & ICE_VF_RESET_LOCK) - mutex_unlock(&vf->cfg_lock); - if (lag && lag->bonded && lag->primary && act_prt != ICE_LAG_INVALID_PORT) ice_lag_move_vf_nodes_cfg(lag, pri_prt, act_prt); mutex_unlock(&pf->lag_mutex); + if (flags & ICE_VF_RESET_LOCK) + mutex_unlock(&vf->cfg_lock); + return err; } -- cgit v1.2.3 From 1b9e743e923b256e353a9a644195372285e5a6c0 Mon Sep 17 00:00:00 2001 From: Jason Reeder Date: Wed, 24 Apr 2024 12:46:26 +0530 Subject: net: ethernet: ti: am65-cpts: Fix PTPv1 message type on TX packets The CPTS, by design, captures the messageType (Sync, Delay_Req, etc.) field from the second nibble of the PTP header which is defined in the PTPv2 (1588-2008) specification. In the PTPv1 (1588-2002) specification the first two bytes of the PTP header are defined as the versionType which is always 0x0001. This means that any PTPv1 packets that are tagged for TX timestamping by the CPTS will have their messageType set to 0x0 which corresponds to a Sync message type. This causes issues when a PTPv1 stack is expecting a Delay_Req (messageType: 0x1) timestamp that never appears. Fix this by checking if the ptp_class of the timestamped TX packet is PTP_CLASS_V1 and then matching the PTP sequence ID to the stored sequence ID in the skb->cb data structure. If the sequence IDs match and the packet is of type PTPv1 then there is a chance that the messageType has been incorrectly stored by the CPTS so overwrite the messageType stored by the CPTS with the messageType from the skb->cb data structure. This allows the PTPv1 stack to receive TX timestamps for Delay_Req packets which are necessary to lock onto a PTP Leader. Signed-off-by: Jason Reeder Signed-off-by: Ravi Gunasekaran Tested-by: Ed Trexel Fixes: f6bd59526ca5 ("net: ethernet: ti: introduce am654 common platform time sync driver") Link: https://lore.kernel.org/r/20240424071626.32558-1-r-gunasekaran@ti.com Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/ti/am65-cpts.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/net/ethernet/ti/am65-cpts.c b/drivers/net/ethernet/ti/am65-cpts.c index c66618d91c28..f89716b1cfb6 100644 --- a/drivers/net/ethernet/ti/am65-cpts.c +++ b/drivers/net/ethernet/ti/am65-cpts.c @@ -784,6 +784,11 @@ static bool am65_cpts_match_tx_ts(struct am65_cpts *cpts, struct am65_cpts_skb_cb_data *skb_cb = (struct am65_cpts_skb_cb_data *)skb->cb; + if ((ptp_classify_raw(skb) & PTP_CLASS_V1) && + ((mtype_seqid & AM65_CPTS_EVENT_1_SEQUENCE_ID_MASK) == + (skb_cb->skb_mtype_seqid & AM65_CPTS_EVENT_1_SEQUENCE_ID_MASK))) + mtype_seqid = skb_cb->skb_mtype_seqid; + if (mtype_seqid == skb_cb->skb_mtype_seqid) { u64 ns = event->timestamp; -- cgit v1.2.3 From 6e965eba43e9724f3e603d7b7cc83e53b23d155e Mon Sep 17 00:00:00 2001 From: Su Hui Date: Wed, 24 Apr 2024 10:27:25 +0800 Subject: octeontx2-af: fix the double free in rvu_npc_freemem() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Clang static checker(scan-build) warning: drivers/net/ethernet/marvell/octeontx2/af/rvu_npc.c:line 2184, column 2 Attempt to free released memory. npc_mcam_rsrcs_deinit() has released 'mcam->counters.bmap'. Deleted this redundant kfree() to fix this double free problem. Fixes: dd7842878633 ("octeontx2-af: Add new devlink param to configure maximum usable NIX block LFs") Signed-off-by: Su Hui Reviewed-by: Geetha sowjanya Reviewed-by: Kalesh AP Reviewed-by: Hariprasad Kelam Link: https://lore.kernel.org/r/20240424022724.144587-1-suhui@nfschina.com Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/marvell/octeontx2/af/rvu_npc.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/net/ethernet/marvell/octeontx2/af/rvu_npc.c b/drivers/net/ethernet/marvell/octeontx2/af/rvu_npc.c index be709f83f331..e8b73b9d75e3 100644 --- a/drivers/net/ethernet/marvell/octeontx2/af/rvu_npc.c +++ b/drivers/net/ethernet/marvell/octeontx2/af/rvu_npc.c @@ -2181,7 +2181,6 @@ void rvu_npc_freemem(struct rvu *rvu) kfree(pkind->rsrc.bmap); npc_mcam_rsrcs_deinit(rvu); - kfree(mcam->counters.bmap); if (rvu->kpu_prfl_addr) iounmap(rvu->kpu_prfl_addr); else -- cgit v1.2.3 From 0c81ea5a8e231fa120e3f76aa9ea99fa3950cc59 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Wed, 24 Apr 2024 09:45:21 +0200 Subject: net: ravb: Fix registered interrupt names MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit As interrupts are now requested from ravb_probe(), before calling register_netdev(), ndev->name still contains the template "eth%d", leading to funny names in /proc/interrupts. E.g. on R-Car E3: 89: 0 0 GICv2 93 Level eth%d:ch22:multi 90: 0 3 GICv2 95 Level eth%d:ch24:emac 91: 0 23484 GICv2 71 Level eth%d:ch0:rx_be 92: 0 0 GICv2 72 Level eth%d:ch1:rx_nc 93: 0 13735 GICv2 89 Level eth%d:ch18:tx_be 94: 0 0 GICv2 90 Level eth%d:ch19:tx_nc Worse, on platforms with multiple RAVB instances (e.g. R-Car V4H), all interrupts have similar names. Fix this by using the device name instead, like is done in several other drivers: 89: 0 0 GICv2 93 Level e6800000.ethernet:ch22:multi 90: 0 1 GICv2 95 Level e6800000.ethernet:ch24:emac 91: 0 28578 GICv2 71 Level e6800000.ethernet:ch0:rx_be 92: 0 0 GICv2 72 Level e6800000.ethernet:ch1:rx_nc 93: 0 14044 GICv2 89 Level e6800000.ethernet:ch18:tx_be 94: 0 0 GICv2 90 Level e6800000.ethernet:ch19:tx_nc Rename the local variable dev_name, as it shadows the dev_name() function, and pre-initialize it, to simplify the code. Fixes: 32f012b8c01ca9fd ("net: ravb: Move getting/requesting IRQs in the probe() method") Signed-off-by: Geert Uytterhoeven Reviewed-by: Niklas Söderlund Reviewed-by: Sergey Shtylyov Reviewed-by: Claudiu Beznea Tested-by: Claudiu Beznea # on RZ/G3S Link: https://lore.kernel.org/r/cde67b68adf115b3cf0b44c32334ae00b2fbb321.1713944647.git.geert+renesas@glider.be Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/renesas/ravb_main.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/drivers/net/ethernet/renesas/ravb_main.c b/drivers/net/ethernet/renesas/ravb_main.c index fcb756d77681..9b1f639f64a1 100644 --- a/drivers/net/ethernet/renesas/ravb_main.c +++ b/drivers/net/ethernet/renesas/ravb_main.c @@ -2722,19 +2722,18 @@ static int ravb_setup_irq(struct ravb_private *priv, const char *irq_name, struct platform_device *pdev = priv->pdev; struct net_device *ndev = priv->ndev; struct device *dev = &pdev->dev; - const char *dev_name; + const char *devname = dev_name(dev); unsigned long flags; int error, irq_num; if (irq_name) { - dev_name = devm_kasprintf(dev, GFP_KERNEL, "%s:%s", ndev->name, ch); - if (!dev_name) + devname = devm_kasprintf(dev, GFP_KERNEL, "%s:%s", devname, ch); + if (!devname) return -ENOMEM; irq_num = platform_get_irq_byname(pdev, irq_name); flags = 0; } else { - dev_name = ndev->name; irq_num = platform_get_irq(pdev, 0); flags = IRQF_SHARED; } @@ -2744,9 +2743,9 @@ static int ravb_setup_irq(struct ravb_private *priv, const char *irq_name, if (irq) *irq = irq_num; - error = devm_request_irq(dev, irq_num, handler, flags, dev_name, ndev); + error = devm_request_irq(dev, irq_num, handler, flags, devname, ndev); if (error) - netdev_err(ndev, "cannot request IRQ %s\n", dev_name); + netdev_err(ndev, "cannot request IRQ %s\n", devname); return error; } -- cgit v1.2.3 From 38d7b94e81d068b8d8c8392f421cfd2c3bbfd1a6 Mon Sep 17 00:00:00 2001 From: Arkadiusz Kubalewski Date: Wed, 24 Apr 2024 12:16:36 +0200 Subject: dpll: fix dpll_pin_on_pin_register() for multiple parent pins In scenario where pin is registered with multiple parent pins via dpll_pin_on_pin_register(..), all belonging to the same dpll device. A second call to dpll_pin_on_pin_unregister(..) would cause a call trace, as it tries to use already released registration resources (due to fix introduced in b446631f355e). In this scenario pin was registered twice, so resources are not yet expected to be release until each registered pin/pin pair is unregistered. Currently, the following crash/call trace is produced when ice driver is removed on the system with installed E810T NIC which includes dpll device: WARNING: CPU: 51 PID: 9155 at drivers/dpll/dpll_core.c:809 dpll_pin_ops+0x20/0x30 RIP: 0010:dpll_pin_ops+0x20/0x30 Call Trace: ? __warn+0x7f/0x130 ? dpll_pin_ops+0x20/0x30 dpll_msg_add_pin_freq+0x37/0x1d0 dpll_cmd_pin_get_one+0x1c0/0x400 ? __nlmsg_put+0x63/0x80 dpll_pin_event_send+0x93/0x140 dpll_pin_on_pin_unregister+0x3f/0x100 ice_dpll_deinit_pins+0xa1/0x230 [ice] ice_remove+0xf1/0x210 [ice] Fix by adding a parent pointer as a cookie when creating a registration, also when searching for it. For the regular pins pass NULL, this allows to create separated registration for each parent the pin is registered with. Fixes: b446631f355e ("dpll: fix dpll_xa_ref_*_del() for multiple registrations") Signed-off-by: Arkadiusz Kubalewski Reviewed-by: Jiri Pirko Link: https://lore.kernel.org/r/20240424101636.1491424-1-arkadiusz.kubalewski@intel.com Signed-off-by: Jakub Kicinski --- drivers/dpll/dpll_core.c | 58 +++++++++++++++++++++++++++--------------------- 1 file changed, 33 insertions(+), 25 deletions(-) diff --git a/drivers/dpll/dpll_core.c b/drivers/dpll/dpll_core.c index 64eaca80d736..d0f6693ca142 100644 --- a/drivers/dpll/dpll_core.c +++ b/drivers/dpll/dpll_core.c @@ -42,6 +42,7 @@ struct dpll_pin_registration { struct list_head list; const struct dpll_pin_ops *ops; void *priv; + void *cookie; }; struct dpll_device *dpll_device_get_by_id(int id) @@ -54,12 +55,14 @@ struct dpll_device *dpll_device_get_by_id(int id) static struct dpll_pin_registration * dpll_pin_registration_find(struct dpll_pin_ref *ref, - const struct dpll_pin_ops *ops, void *priv) + const struct dpll_pin_ops *ops, void *priv, + void *cookie) { struct dpll_pin_registration *reg; list_for_each_entry(reg, &ref->registration_list, list) { - if (reg->ops == ops && reg->priv == priv) + if (reg->ops == ops && reg->priv == priv && + reg->cookie == cookie) return reg; } return NULL; @@ -67,7 +70,8 @@ dpll_pin_registration_find(struct dpll_pin_ref *ref, static int dpll_xa_ref_pin_add(struct xarray *xa_pins, struct dpll_pin *pin, - const struct dpll_pin_ops *ops, void *priv) + const struct dpll_pin_ops *ops, void *priv, + void *cookie) { struct dpll_pin_registration *reg; struct dpll_pin_ref *ref; @@ -78,7 +82,7 @@ dpll_xa_ref_pin_add(struct xarray *xa_pins, struct dpll_pin *pin, xa_for_each(xa_pins, i, ref) { if (ref->pin != pin) continue; - reg = dpll_pin_registration_find(ref, ops, priv); + reg = dpll_pin_registration_find(ref, ops, priv, cookie); if (reg) { refcount_inc(&ref->refcount); return 0; @@ -111,6 +115,7 @@ dpll_xa_ref_pin_add(struct xarray *xa_pins, struct dpll_pin *pin, } reg->ops = ops; reg->priv = priv; + reg->cookie = cookie; if (ref_exists) refcount_inc(&ref->refcount); list_add_tail(®->list, &ref->registration_list); @@ -119,7 +124,8 @@ dpll_xa_ref_pin_add(struct xarray *xa_pins, struct dpll_pin *pin, } static int dpll_xa_ref_pin_del(struct xarray *xa_pins, struct dpll_pin *pin, - const struct dpll_pin_ops *ops, void *priv) + const struct dpll_pin_ops *ops, void *priv, + void *cookie) { struct dpll_pin_registration *reg; struct dpll_pin_ref *ref; @@ -128,7 +134,7 @@ static int dpll_xa_ref_pin_del(struct xarray *xa_pins, struct dpll_pin *pin, xa_for_each(xa_pins, i, ref) { if (ref->pin != pin) continue; - reg = dpll_pin_registration_find(ref, ops, priv); + reg = dpll_pin_registration_find(ref, ops, priv, cookie); if (WARN_ON(!reg)) return -EINVAL; list_del(®->list); @@ -146,7 +152,7 @@ static int dpll_xa_ref_pin_del(struct xarray *xa_pins, struct dpll_pin *pin, static int dpll_xa_ref_dpll_add(struct xarray *xa_dplls, struct dpll_device *dpll, - const struct dpll_pin_ops *ops, void *priv) + const struct dpll_pin_ops *ops, void *priv, void *cookie) { struct dpll_pin_registration *reg; struct dpll_pin_ref *ref; @@ -157,7 +163,7 @@ dpll_xa_ref_dpll_add(struct xarray *xa_dplls, struct dpll_device *dpll, xa_for_each(xa_dplls, i, ref) { if (ref->dpll != dpll) continue; - reg = dpll_pin_registration_find(ref, ops, priv); + reg = dpll_pin_registration_find(ref, ops, priv, cookie); if (reg) { refcount_inc(&ref->refcount); return 0; @@ -190,6 +196,7 @@ dpll_xa_ref_dpll_add(struct xarray *xa_dplls, struct dpll_device *dpll, } reg->ops = ops; reg->priv = priv; + reg->cookie = cookie; if (ref_exists) refcount_inc(&ref->refcount); list_add_tail(®->list, &ref->registration_list); @@ -199,7 +206,7 @@ dpll_xa_ref_dpll_add(struct xarray *xa_dplls, struct dpll_device *dpll, static void dpll_xa_ref_dpll_del(struct xarray *xa_dplls, struct dpll_device *dpll, - const struct dpll_pin_ops *ops, void *priv) + const struct dpll_pin_ops *ops, void *priv, void *cookie) { struct dpll_pin_registration *reg; struct dpll_pin_ref *ref; @@ -208,7 +215,7 @@ dpll_xa_ref_dpll_del(struct xarray *xa_dplls, struct dpll_device *dpll, xa_for_each(xa_dplls, i, ref) { if (ref->dpll != dpll) continue; - reg = dpll_pin_registration_find(ref, ops, priv); + reg = dpll_pin_registration_find(ref, ops, priv, cookie); if (WARN_ON(!reg)) return; list_del(®->list); @@ -594,14 +601,14 @@ EXPORT_SYMBOL_GPL(dpll_pin_put); static int __dpll_pin_register(struct dpll_device *dpll, struct dpll_pin *pin, - const struct dpll_pin_ops *ops, void *priv) + const struct dpll_pin_ops *ops, void *priv, void *cookie) { int ret; - ret = dpll_xa_ref_pin_add(&dpll->pin_refs, pin, ops, priv); + ret = dpll_xa_ref_pin_add(&dpll->pin_refs, pin, ops, priv, cookie); if (ret) return ret; - ret = dpll_xa_ref_dpll_add(&pin->dpll_refs, dpll, ops, priv); + ret = dpll_xa_ref_dpll_add(&pin->dpll_refs, dpll, ops, priv, cookie); if (ret) goto ref_pin_del; xa_set_mark(&dpll_pin_xa, pin->id, DPLL_REGISTERED); @@ -610,7 +617,7 @@ __dpll_pin_register(struct dpll_device *dpll, struct dpll_pin *pin, return ret; ref_pin_del: - dpll_xa_ref_pin_del(&dpll->pin_refs, pin, ops, priv); + dpll_xa_ref_pin_del(&dpll->pin_refs, pin, ops, priv, cookie); return ret; } @@ -642,7 +649,7 @@ dpll_pin_register(struct dpll_device *dpll, struct dpll_pin *pin, dpll->clock_id == pin->clock_id))) ret = -EINVAL; else - ret = __dpll_pin_register(dpll, pin, ops, priv); + ret = __dpll_pin_register(dpll, pin, ops, priv, NULL); mutex_unlock(&dpll_lock); return ret; @@ -651,11 +658,11 @@ EXPORT_SYMBOL_GPL(dpll_pin_register); static void __dpll_pin_unregister(struct dpll_device *dpll, struct dpll_pin *pin, - const struct dpll_pin_ops *ops, void *priv) + const struct dpll_pin_ops *ops, void *priv, void *cookie) { ASSERT_DPLL_PIN_REGISTERED(pin); - dpll_xa_ref_pin_del(&dpll->pin_refs, pin, ops, priv); - dpll_xa_ref_dpll_del(&pin->dpll_refs, dpll, ops, priv); + dpll_xa_ref_pin_del(&dpll->pin_refs, pin, ops, priv, cookie); + dpll_xa_ref_dpll_del(&pin->dpll_refs, dpll, ops, priv, cookie); if (xa_empty(&pin->dpll_refs)) xa_clear_mark(&dpll_pin_xa, pin->id, DPLL_REGISTERED); } @@ -680,7 +687,7 @@ void dpll_pin_unregister(struct dpll_device *dpll, struct dpll_pin *pin, mutex_lock(&dpll_lock); dpll_pin_delete_ntf(pin); - __dpll_pin_unregister(dpll, pin, ops, priv); + __dpll_pin_unregister(dpll, pin, ops, priv, NULL); mutex_unlock(&dpll_lock); } EXPORT_SYMBOL_GPL(dpll_pin_unregister); @@ -716,12 +723,12 @@ int dpll_pin_on_pin_register(struct dpll_pin *parent, struct dpll_pin *pin, return -EINVAL; mutex_lock(&dpll_lock); - ret = dpll_xa_ref_pin_add(&pin->parent_refs, parent, ops, priv); + ret = dpll_xa_ref_pin_add(&pin->parent_refs, parent, ops, priv, pin); if (ret) goto unlock; refcount_inc(&pin->refcount); xa_for_each(&parent->dpll_refs, i, ref) { - ret = __dpll_pin_register(ref->dpll, pin, ops, priv); + ret = __dpll_pin_register(ref->dpll, pin, ops, priv, parent); if (ret) { stop = i; goto dpll_unregister; @@ -735,11 +742,12 @@ int dpll_pin_on_pin_register(struct dpll_pin *parent, struct dpll_pin *pin, dpll_unregister: xa_for_each(&parent->dpll_refs, i, ref) if (i < stop) { - __dpll_pin_unregister(ref->dpll, pin, ops, priv); + __dpll_pin_unregister(ref->dpll, pin, ops, priv, + parent); dpll_pin_delete_ntf(pin); } refcount_dec(&pin->refcount); - dpll_xa_ref_pin_del(&pin->parent_refs, parent, ops, priv); + dpll_xa_ref_pin_del(&pin->parent_refs, parent, ops, priv, pin); unlock: mutex_unlock(&dpll_lock); return ret; @@ -764,10 +772,10 @@ void dpll_pin_on_pin_unregister(struct dpll_pin *parent, struct dpll_pin *pin, mutex_lock(&dpll_lock); dpll_pin_delete_ntf(pin); - dpll_xa_ref_pin_del(&pin->parent_refs, parent, ops, priv); + dpll_xa_ref_pin_del(&pin->parent_refs, parent, ops, priv, pin); refcount_dec(&pin->refcount); xa_for_each(&pin->dpll_refs, i, ref) - __dpll_pin_unregister(ref->dpll, pin, ops, priv); + __dpll_pin_unregister(ref->dpll, pin, ops, priv, parent); mutex_unlock(&dpll_lock); } EXPORT_SYMBOL_GPL(dpll_pin_on_pin_unregister); -- cgit v1.2.3 From 0844370f8945086eb9335739d10205dcea8d707b Mon Sep 17 00:00:00 2001 From: Sabrina Dubroca Date: Wed, 24 Apr 2024 12:25:47 +0200 Subject: tls: fix lockless read of strp->msg_ready in ->poll tls_sk_poll is called without locking the socket, and needs to read strp->msg_ready (via tls_strp_msg_ready). Convert msg_ready to a bool and use READ_ONCE/WRITE_ONCE where needed. The remaining reads are only performed when the socket is locked. Fixes: 121dca784fc0 ("tls: suppress wakeups unless we have a full record") Signed-off-by: Sabrina Dubroca Link: https://lore.kernel.org/r/0b7ee062319037cf86af6b317b3d72f7bfcd2e97.1713797701.git.sd@queasysnail.net Signed-off-by: Jakub Kicinski --- include/net/tls.h | 3 ++- net/tls/tls.h | 2 +- net/tls/tls_strp.c | 6 +++--- 3 files changed, 6 insertions(+), 5 deletions(-) diff --git a/include/net/tls.h b/include/net/tls.h index 340ad43971e4..33f657d3c051 100644 --- a/include/net/tls.h +++ b/include/net/tls.h @@ -111,7 +111,8 @@ struct tls_strparser { u32 stopped : 1; u32 copy_mode : 1; u32 mixed_decrypted : 1; - u32 msg_ready : 1; + + bool msg_ready; struct strp_msg stm; diff --git a/net/tls/tls.h b/net/tls/tls.h index 762f424ff2d5..e5e47452308a 100644 --- a/net/tls/tls.h +++ b/net/tls/tls.h @@ -215,7 +215,7 @@ static inline struct sk_buff *tls_strp_msg(struct tls_sw_context_rx *ctx) static inline bool tls_strp_msg_ready(struct tls_sw_context_rx *ctx) { - return ctx->strp.msg_ready; + return READ_ONCE(ctx->strp.msg_ready); } static inline bool tls_strp_msg_mixed_decrypted(struct tls_sw_context_rx *ctx) diff --git a/net/tls/tls_strp.c b/net/tls/tls_strp.c index ca1e0e198ceb..5df08d848b5c 100644 --- a/net/tls/tls_strp.c +++ b/net/tls/tls_strp.c @@ -360,7 +360,7 @@ static int tls_strp_copyin(read_descriptor_t *desc, struct sk_buff *in_skb, if (strp->stm.full_len && strp->stm.full_len == skb->len) { desc->count = 0; - strp->msg_ready = 1; + WRITE_ONCE(strp->msg_ready, 1); tls_rx_msg_ready(strp); } @@ -528,7 +528,7 @@ static int tls_strp_read_sock(struct tls_strparser *strp) if (!tls_strp_check_queue_ok(strp)) return tls_strp_read_copy(strp, false); - strp->msg_ready = 1; + WRITE_ONCE(strp->msg_ready, 1); tls_rx_msg_ready(strp); return 0; @@ -580,7 +580,7 @@ void tls_strp_msg_done(struct tls_strparser *strp) else tls_strp_flush_anchor_copy(strp); - strp->msg_ready = 0; + WRITE_ONCE(strp->msg_ready, 0); memset(&strp->stm, 0, sizeof(strp->stm)); tls_strp_check_rcv(strp); -- cgit v1.2.3 From e3eb7dd47bd4806f00e104eb6da092c435f9fb21 Mon Sep 17 00:00:00 2001 From: Peter Münster Date: Wed, 24 Apr 2024 15:51:52 +0200 Subject: net: b44: set pause params only when interface is up MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit b44_free_rings() accesses b44::rx_buffers (and ::tx_buffers) unconditionally, but b44::rx_buffers is only valid when the device is up (they get allocated in b44_open(), and deallocated again in b44_close()), any other time these are just a NULL pointers. So if you try to change the pause params while the network interface is disabled/administratively down, everything explodes (which likely netifd tries to do). Link: https://github.com/openwrt/openwrt/issues/13789 Fixes: 1da177e4c3f4 (Linux-2.6.12-rc2) Cc: stable@vger.kernel.org Reported-by: Peter Münster Suggested-by: Jonas Gorski Signed-off-by: Vaclav Svoboda Tested-by: Peter Münster Reviewed-by: Andrew Lunn Signed-off-by: Peter Münster Reviewed-by: Michael Chan Link: https://lore.kernel.org/r/87y192oolj.fsf@a16n.net Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/broadcom/b44.c | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/drivers/net/ethernet/broadcom/b44.c b/drivers/net/ethernet/broadcom/b44.c index 3e4fb3c3e834..1be6d14030bc 100644 --- a/drivers/net/ethernet/broadcom/b44.c +++ b/drivers/net/ethernet/broadcom/b44.c @@ -2009,12 +2009,14 @@ static int b44_set_pauseparam(struct net_device *dev, bp->flags |= B44_FLAG_TX_PAUSE; else bp->flags &= ~B44_FLAG_TX_PAUSE; - if (bp->flags & B44_FLAG_PAUSE_AUTO) { - b44_halt(bp); - b44_init_rings(bp); - b44_init_hw(bp, B44_FULL_RESET); - } else { - __b44_set_flow_ctrl(bp, bp->flags); + if (netif_running(dev)) { + if (bp->flags & B44_FLAG_PAUSE_AUTO) { + b44_halt(bp); + b44_init_rings(bp); + b44_init_hw(bp, B44_FULL_RESET); + } else { + __b44_set_flow_ctrl(bp, bp->flags); + } } spin_unlock_irq(&bp->lock); -- cgit v1.2.3 From 1971d13ffa84a551d29a81fdf5b5ec5be166ac83 Mon Sep 17 00:00:00 2001 From: Kuniyuki Iwashima Date: Wed, 24 Apr 2024 10:04:43 -0700 Subject: af_unix: Suppress false-positive lockdep splat for spin_lock() in __unix_gc(). syzbot reported a lockdep splat regarding unix_gc_lock and unix_state_lock(). One is called from recvmsg() for a connected socket, and another is called from GC for TCP_LISTEN socket. So, the splat is false-positive. Let's add a dedicated lock class for the latter to suppress the splat. Note that this change is not necessary for net-next.git as the issue is only applied to the old GC impl. [0]: WARNING: possible circular locking dependency detected 6.9.0-rc5-syzkaller-00007-g4d2008430ce8 #0 Not tainted ----------------------------------------------------- kworker/u8:1/11 is trying to acquire lock: ffff88807cea4e70 (&u->lock){+.+.}-{2:2}, at: spin_lock include/linux/spinlock.h:351 [inline] ffff88807cea4e70 (&u->lock){+.+.}-{2:2}, at: __unix_gc+0x40e/0xf70 net/unix/garbage.c:302 but task is already holding lock: ffffffff8f6ab638 (unix_gc_lock){+.+.}-{2:2}, at: spin_lock include/linux/spinlock.h:351 [inline] ffffffff8f6ab638 (unix_gc_lock){+.+.}-{2:2}, at: __unix_gc+0x117/0xf70 net/unix/garbage.c:261 which lock already depends on the new lock. the existing dependency chain (in reverse order) is: -> #1 (unix_gc_lock){+.+.}-{2:2}: lock_acquire+0x1ed/0x550 kernel/locking/lockdep.c:5754 __raw_spin_lock include/linux/spinlock_api_smp.h:133 [inline] _raw_spin_lock+0x2e/0x40 kernel/locking/spinlock.c:154 spin_lock include/linux/spinlock.h:351 [inline] unix_notinflight+0x13d/0x390 net/unix/garbage.c:140 unix_detach_fds net/unix/af_unix.c:1819 [inline] unix_destruct_scm+0x221/0x350 net/unix/af_unix.c:1876 skb_release_head_state+0x100/0x250 net/core/skbuff.c:1188 skb_release_all net/core/skbuff.c:1200 [inline] __kfree_skb net/core/skbuff.c:1216 [inline] kfree_skb_reason+0x16d/0x3b0 net/core/skbuff.c:1252 kfree_skb include/linux/skbuff.h:1262 [inline] manage_oob net/unix/af_unix.c:2672 [inline] unix_stream_read_generic+0x1125/0x2700 net/unix/af_unix.c:2749 unix_stream_splice_read+0x239/0x320 net/unix/af_unix.c:2981 do_splice_read fs/splice.c:985 [inline] splice_file_to_pipe+0x299/0x500 fs/splice.c:1295 do_splice+0xf2d/0x1880 fs/splice.c:1379 __do_splice fs/splice.c:1436 [inline] __do_sys_splice fs/splice.c:1652 [inline] __se_sys_splice+0x331/0x4a0 fs/splice.c:1634 do_syscall_x64 arch/x86/entry/common.c:52 [inline] do_syscall_64+0xf5/0x240 arch/x86/entry/common.c:83 entry_SYSCALL_64_after_hwframe+0x77/0x7f -> #0 (&u->lock){+.+.}-{2:2}: check_prev_add kernel/locking/lockdep.c:3134 [inline] check_prevs_add kernel/locking/lockdep.c:3253 [inline] validate_chain+0x18cb/0x58e0 kernel/locking/lockdep.c:3869 __lock_acquire+0x1346/0x1fd0 kernel/locking/lockdep.c:5137 lock_acquire+0x1ed/0x550 kernel/locking/lockdep.c:5754 __raw_spin_lock include/linux/spinlock_api_smp.h:133 [inline] _raw_spin_lock+0x2e/0x40 kernel/locking/spinlock.c:154 spin_lock include/linux/spinlock.h:351 [inline] __unix_gc+0x40e/0xf70 net/unix/garbage.c:302 process_one_work kernel/workqueue.c:3254 [inline] process_scheduled_works+0xa10/0x17c0 kernel/workqueue.c:3335 worker_thread+0x86d/0xd70 kernel/workqueue.c:3416 kthread+0x2f0/0x390 kernel/kthread.c:388 ret_from_fork+0x4b/0x80 arch/x86/kernel/process.c:147 ret_from_fork_asm+0x1a/0x30 arch/x86/entry/entry_64.S:244 other info that might help us debug this: Possible unsafe locking scenario: CPU0 CPU1 ---- ---- lock(unix_gc_lock); lock(&u->lock); lock(unix_gc_lock); lock(&u->lock); *** DEADLOCK *** 3 locks held by kworker/u8:1/11: #0: ffff888015089148 ((wq_completion)events_unbound){+.+.}-{0:0}, at: process_one_work kernel/workqueue.c:3229 [inline] #0: ffff888015089148 ((wq_completion)events_unbound){+.+.}-{0:0}, at: process_scheduled_works+0x8e0/0x17c0 kernel/workqueue.c:3335 #1: ffffc90000107d00 (unix_gc_work){+.+.}-{0:0}, at: process_one_work kernel/workqueue.c:3230 [inline] #1: ffffc90000107d00 (unix_gc_work){+.+.}-{0:0}, at: process_scheduled_works+0x91b/0x17c0 kernel/workqueue.c:3335 #2: ffffffff8f6ab638 (unix_gc_lock){+.+.}-{2:2}, at: spin_lock include/linux/spinlock.h:351 [inline] #2: ffffffff8f6ab638 (unix_gc_lock){+.+.}-{2:2}, at: __unix_gc+0x117/0xf70 net/unix/garbage.c:261 stack backtrace: CPU: 0 PID: 11 Comm: kworker/u8:1 Not tainted 6.9.0-rc5-syzkaller-00007-g4d2008430ce8 #0 Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 03/27/2024 Workqueue: events_unbound __unix_gc Call Trace: __dump_stack lib/dump_stack.c:88 [inline] dump_stack_lvl+0x241/0x360 lib/dump_stack.c:114 check_noncircular+0x36a/0x4a0 kernel/locking/lockdep.c:2187 check_prev_add kernel/locking/lockdep.c:3134 [inline] check_prevs_add kernel/locking/lockdep.c:3253 [inline] validate_chain+0x18cb/0x58e0 kernel/locking/lockdep.c:3869 __lock_acquire+0x1346/0x1fd0 kernel/locking/lockdep.c:5137 lock_acquire+0x1ed/0x550 kernel/locking/lockdep.c:5754 __raw_spin_lock include/linux/spinlock_api_smp.h:133 [inline] _raw_spin_lock+0x2e/0x40 kernel/locking/spinlock.c:154 spin_lock include/linux/spinlock.h:351 [inline] __unix_gc+0x40e/0xf70 net/unix/garbage.c:302 process_one_work kernel/workqueue.c:3254 [inline] process_scheduled_works+0xa10/0x17c0 kernel/workqueue.c:3335 worker_thread+0x86d/0xd70 kernel/workqueue.c:3416 kthread+0x2f0/0x390 kernel/kthread.c:388 ret_from_fork+0x4b/0x80 arch/x86/kernel/process.c:147 ret_from_fork_asm+0x1a/0x30 arch/x86/entry/entry_64.S:244 Fixes: 47d8ac011fe1 ("af_unix: Fix garbage collector racing against connect()") Reported-and-tested-by: syzbot+fa379358c28cc87cc307@syzkaller.appspotmail.com Closes: https://syzkaller.appspot.com/bug?extid=fa379358c28cc87cc307 Signed-off-by: Kuniyuki Iwashima Link: https://lore.kernel.org/r/20240424170443.9832-1-kuniyu@amazon.com Signed-off-by: Jakub Kicinski --- include/net/af_unix.h | 3 +++ net/unix/garbage.c | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/include/net/af_unix.h b/include/net/af_unix.h index 627ea8e2d915..3dee0b2721aa 100644 --- a/include/net/af_unix.h +++ b/include/net/af_unix.h @@ -85,6 +85,9 @@ enum unix_socket_lock_class { U_LOCK_NORMAL, U_LOCK_SECOND, /* for double locking, see unix_state_double_lock(). */ U_LOCK_DIAG, /* used while dumping icons, see sk_diag_dump_icons(). */ + U_LOCK_GC_LISTENER, /* used for listening socket while determining gc + * candidates to close a small race window. + */ }; static inline void unix_state_lock_nested(struct sock *sk, diff --git a/net/unix/garbage.c b/net/unix/garbage.c index 6433a414acf8..0104be9d4704 100644 --- a/net/unix/garbage.c +++ b/net/unix/garbage.c @@ -299,7 +299,7 @@ static void __unix_gc(struct work_struct *work) __set_bit(UNIX_GC_MAYBE_CYCLE, &u->gc_flags); if (sk->sk_state == TCP_LISTEN) { - unix_state_lock(sk); + unix_state_lock_nested(sk, U_LOCK_GC_LISTENER); unix_state_unlock(sk); } } -- cgit v1.2.3 From 2da01ca3674c6e90dbeeda02168849e2ec877edc Mon Sep 17 00:00:00 2001 From: Shengjiu Wang Date: Thu, 25 Apr 2024 14:35:06 +0800 Subject: ASoC: dt-bindings: fsl,ssi: Convert to YAML Convert the fsl,ssi binding to YAML. Add below compatible strings which were not listed in document: fsl,imx50-ssi fsl,imx53-ssi fsl,imx25-ssi fsl,imx27-ssi fsl,imx6q-ssi fsl,imx6sl-ssi fsl,imx6sx-ssi Add below fsl,mode strings which were not listed. i2s-slave i2s-master lj-slave lj-master rj-slave rj-master Add 'ac97-gpios' property which were not listed. Then dtbs_check can pass. And remove the 'codec' description which should be in the 'codec' binding doc. Signed-off-by: Shengjiu Wang Reviewed-by: Rob Herring (Arm) Link: https://lore.kernel.org/r/1714026906-16723-1-git-send-email-shengjiu.wang@nxp.com Signed-off-by: Mark Brown --- .../devicetree/bindings/sound/fsl,ssi.txt | 87 --------- .../devicetree/bindings/sound/fsl,ssi.yaml | 194 +++++++++++++++++++++ 2 files changed, 194 insertions(+), 87 deletions(-) delete mode 100644 Documentation/devicetree/bindings/sound/fsl,ssi.txt create mode 100644 Documentation/devicetree/bindings/sound/fsl,ssi.yaml diff --git a/Documentation/devicetree/bindings/sound/fsl,ssi.txt b/Documentation/devicetree/bindings/sound/fsl,ssi.txt deleted file mode 100644 index 7e15a85cecd2..000000000000 --- a/Documentation/devicetree/bindings/sound/fsl,ssi.txt +++ /dev/null @@ -1,87 +0,0 @@ -Freescale Synchronous Serial Interface - -The SSI is a serial device that communicates with audio codecs. It can -be programmed in AC97, I2S, left-justified, or right-justified modes. - -Required properties: -- compatible: Compatible list, should contain one of the following - compatibles: - fsl,mpc8610-ssi - fsl,imx51-ssi - fsl,imx35-ssi - fsl,imx21-ssi -- cell-index: The SSI, <0> = SSI1, <1> = SSI2, and so on. -- reg: Offset and length of the register set for the device. -- interrupts: where a is the interrupt number and b is a - field that represents an encoding of the sense and - level information for the interrupt. This should be - encoded based on the information in section 2) - depending on the type of interrupt controller you - have. -- fsl,fifo-depth: The number of elements in the transmit and receive FIFOs. - This number is the maximum allowed value for SFCSR[TFWM0]. - - clocks: "ipg" - Required clock for the SSI unit - "baud" - Required clock for SSI master mode. Otherwise this - clock is not used - -Required are also ac97 link bindings if ac97 is used. See -Documentation/devicetree/bindings/sound/soc-ac97link.txt for the necessary -bindings. - -Optional properties: -- codec-handle: Phandle to a 'codec' node that defines an audio - codec connected to this SSI. This node is typically - a child of an I2C or other control node. -- fsl,fiq-stream-filter: Bool property. Disabled DMA and use FIQ instead to - filter the codec stream. This is necessary for some boards - where an incompatible codec is connected to this SSI, e.g. - on pca100 and pcm043. -- dmas: Generic dma devicetree binding as described in - Documentation/devicetree/bindings/dma/dma.txt. -- dma-names: Two dmas have to be defined, "tx" and "rx", if fsl,imx-fiq - is not defined. -- fsl,mode: The operating mode for the AC97 interface only. - "ac97-slave" - AC97 mode, SSI is clock slave - "ac97-master" - AC97 mode, SSI is clock master -- fsl,ssi-asynchronous: - If specified, the SSI is to be programmed in asynchronous - mode. In this mode, pins SRCK, STCK, SRFS, and STFS must - all be connected to valid signals. In synchronous mode, - SRCK and SRFS are ignored. Asynchronous mode allows - playback and capture to use different sample sizes and - sample rates. Some drivers may require that SRCK and STCK - be connected together, and SRFS and STFS be connected - together. This would still allow different sample sizes, - but not different sample rates. -- fsl,playback-dma: Phandle to a node for the DMA channel to use for - playback of audio. This is typically dictated by SOC - design. See the notes below. - Only used on Power Architecture. -- fsl,capture-dma: Phandle to a node for the DMA channel to use for - capture (recording) of audio. This is typically dictated - by SOC design. See the notes below. - Only used on Power Architecture. - -Child 'codec' node required properties: -- compatible: Compatible list, contains the name of the codec - -Child 'codec' node optional properties: -- clock-frequency: The frequency of the input clock, which typically comes - from an on-board dedicated oscillator. - -Notes on fsl,playback-dma and fsl,capture-dma: - -On SOCs that have an SSI, specific DMA channels are hard-wired for playback -and capture. On the MPC8610, for example, SSI1 must use DMA channel 0 for -playback and DMA channel 1 for capture. SSI2 must use DMA channel 2 for -playback and DMA channel 3 for capture. The developer can choose which -DMA controller to use, but the channels themselves are hard-wired. The -purpose of these two properties is to represent this hardware design. - -The device tree nodes for the DMA channels that are referenced by -"fsl,playback-dma" and "fsl,capture-dma" must be marked as compatible with -"fsl,ssi-dma-channel". The SOC-specific compatible string (e.g. -"fsl,mpc8610-dma-channel") can remain. If these nodes are left as -"fsl,elo-dma-channel" or "fsl,eloplus-dma-channel", then the generic Elo DMA -drivers (fsldma) will attempt to use them, and it will conflict with the -sound drivers. diff --git a/Documentation/devicetree/bindings/sound/fsl,ssi.yaml b/Documentation/devicetree/bindings/sound/fsl,ssi.yaml new file mode 100644 index 000000000000..4ab10cd3b520 --- /dev/null +++ b/Documentation/devicetree/bindings/sound/fsl,ssi.yaml @@ -0,0 +1,194 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/sound/fsl,ssi.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Freescale Synchronous Serial Interface + +maintainers: + - Shengjiu Wang + +description: + Notes on fsl,playback-dma and fsl,capture-dma + On SOCs that have an SSI, specific DMA channels are hard-wired for playback + and capture. On the MPC8610, for example, SSI1 must use DMA channel 0 for + playback and DMA channel 1 for capture. SSI2 must use DMA channel 2 for + playback and DMA channel 3 for capture. The developer can choose which + DMA controller to use, but the channels themselves are hard-wired. The + purpose of these two properties is to represent this hardware design. + + The device tree nodes for the DMA channels that are referenced by + "fsl,playback-dma" and "fsl,capture-dma" must be marked as compatible with + "fsl,ssi-dma-channel". The SOC-specific compatible string (e.g. + "fsl,mpc8610-dma-channel") can remain. If these nodes are left as + "fsl,elo-dma-channel" or "fsl,eloplus-dma-channel", then the generic Elo DMA + drivers (fsldma) will attempt to use them, and it will conflict with the + sound drivers. + +properties: + compatible: + oneOf: + - items: + - enum: + - fsl,imx50-ssi + - fsl,imx53-ssi + - const: fsl,imx51-ssi + - const: fsl,imx21-ssi + - items: + - enum: + - fsl,imx25-ssi + - fsl,imx27-ssi + - fsl,imx35-ssi + - fsl,imx51-ssi + - const: fsl,imx21-ssi + - items: + - enum: + - fsl,imx6q-ssi + - fsl,imx6sl-ssi + - fsl,imx6sx-ssi + - const: fsl,imx51-ssi + - items: + - const: fsl,imx21-ssi + - items: + - const: fsl,mpc8610-ssi + + reg: + maxItems: 1 + + interrupts: + maxItems: 1 + + clocks: + items: + - description: The ipg clock for register access + - description: clock for SSI master mode + minItems: 1 + + clock-names: + items: + - const: ipg + - const: baud + minItems: 1 + + dmas: + oneOf: + - items: + - description: DMA controller phandle and request line for RX + - description: DMA controller phandle and request line for TX + - items: + - description: DMA controller phandle and request line for RX0 + - description: DMA controller phandle and request line for TX0 + - description: DMA controller phandle and request line for RX1 + - description: DMA controller phandle and request line for TX1 + + dma-names: + oneOf: + - items: + - const: rx + - const: tx + - items: + - const: rx0 + - const: tx0 + - const: rx1 + - const: tx1 + + "#sound-dai-cells": + const: 0 + description: optional, some dts node didn't add it. + + cell-index: + $ref: /schemas/types.yaml#/definitions/uint32 + enum: [0, 1, 2] + description: The SSI index + + ac97-gpios: + $ref: /schemas/types.yaml#/definitions/phandle-array + description: Please refer to soc-ac97link.txt + + codec-handle: + $ref: /schemas/types.yaml#/definitions/phandle + description: + Phandle to a 'codec' node that defines an audio + codec connected to this SSI. This node is typically + a child of an I2C or other control node. + + fsl,fifo-depth: + $ref: /schemas/types.yaml#/definitions/uint32 + description: + The number of elements in the transmit and receive FIFOs. + This number is the maximum allowed value for SFCSR[TFWM0]. + enum: [8, 15] + + fsl,fiq-stream-filter: + type: boolean + description: + Disabled DMA and use FIQ instead to filter the codec stream. + This is necessary for some boards where an incompatible codec + is connected to this SSI, e.g. on pca100 and pcm043. + + fsl,mode: + $ref: /schemas/types.yaml#/definitions/string + enum: [ ac97-slave, ac97-master, i2s-slave, i2s-master, + lj-slave, lj-master, rj-slave, rj-master ] + description: | + "ac97-slave" - AC97 mode, SSI is clock slave + "ac97-master" - AC97 mode, SSI is clock master + "i2s-slave" - I2S mode, SSI is clock slave + "i2s-master" - I2S mode, SSI is clock master + "lj-slave" - Left justified mode, SSI is clock slave + "lj-master" - Left justified mode, SSI is clock master + "rj-slave" - Right justified mode, SSI is clock slave + "rj-master" - Right justified mode, SSI is clock master + + fsl,ssi-asynchronous: + type: boolean + description: If specified, the SSI is to be programmed in asynchronous + mode. In this mode, pins SRCK, STCK, SRFS, and STFS must + all be connected to valid signals. In synchronous mode, + SRCK and SRFS are ignored. Asynchronous mode allows + playback and capture to use different sample sizes and + sample rates. Some drivers may require that SRCK and STCK + be connected together, and SRFS and STFS be connected + together. This would still allow different sample sizes, + but not different sample rates. + + fsl,playback-dma: + $ref: /schemas/types.yaml#/definitions/phandle + description: Phandle to a node for the DMA channel to use for + playback of audio. This is typically dictated by SOC + design. Only used on Power Architecture. + + fsl,capture-dma: + $ref: /schemas/types.yaml#/definitions/phandle + description: Phandle to a node for the DMA channel to use for + capture (recording) of audio. This is typically dictated + by SOC design. Only used on Power Architecture. + +required: + - compatible + - reg + - interrupts + - fsl,fifo-depth + +allOf: + - $ref: dai-common.yaml# + +unevaluatedProperties: false + +examples: + - | + #include + #include + ssi@2028000 { + compatible = "fsl,imx6q-ssi", "fsl,imx51-ssi"; + reg = <0x02028000 0x4000>; + interrupts = ; + clocks = <&clks IMX6QDL_CLK_SSI1_IPG>, + <&clks IMX6QDL_CLK_SSI1>; + clock-names = "ipg", "baud"; + dmas = <&sdma 37 1 0>, <&sdma 38 1 0>; + dma-names = "rx", "tx"; + #sound-dai-cells = <0>; + fsl,fifo-depth = <15>; + }; -- cgit v1.2.3 From d2d377fc22d23fd38188ea90b051584069a299a2 Mon Sep 17 00:00:00 2001 From: Brent Lu Date: Fri, 26 Apr 2024 10:25:07 -0500 Subject: ASoC: Intel: nau8825/rt5682: move speaker widget to common modules Two machine drivers sof_rt5682 and sof_nau8825 always register two speaker widgets 'Left Spk' and 'Right Spk' regardless the actual number of speakers. Move the widget registration to speaker common modules to avoid useless speaker widgets for 1 or 4 speaker boards. Reviewed-by: Bard Liao Signed-off-by: Brent Lu Signed-off-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20240426152529.38345-2-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/intel/boards/sof_maxim_common.c | 66 ++++++++++++++++++-- sound/soc/intel/boards/sof_nau8825.c | 4 -- sound/soc/intel/boards/sof_realtek_common.c | 93 ++++++++++++++++++++++++++++- sound/soc/intel/boards/sof_rt5682.c | 32 ++++++++-- 4 files changed, 180 insertions(+), 15 deletions(-) diff --git a/sound/soc/intel/boards/sof_maxim_common.c b/sound/soc/intel/boards/sof_maxim_common.c index cf2974718271..53c7392bf3dd 100644 --- a/sound/soc/intel/boards/sof_maxim_common.c +++ b/sound/soc/intel/boards/sof_maxim_common.c @@ -12,6 +12,20 @@ #include #include "sof_maxim_common.h" +/* + * Common structures and functions + */ +static const struct snd_kcontrol_new maxim_2spk_kcontrols[] = { + SOC_DAPM_PIN_SWITCH("Left Spk"), + SOC_DAPM_PIN_SWITCH("Right Spk"), + +}; + +static const struct snd_soc_dapm_widget maxim_2spk_widgets[] = { + SND_SOC_DAPM_SPK("Left Spk", NULL), + SND_SOC_DAPM_SPK("Right Spk", NULL), +}; + /* helper function to get the number of specific codec */ static unsigned int get_num_codecs(const char *hid) { @@ -135,12 +149,40 @@ EXPORT_SYMBOL_NS(max_98373_ops, SND_SOC_INTEL_SOF_MAXIM_COMMON); int max_98373_spk_codec_init(struct snd_soc_pcm_runtime *rtd) { struct snd_soc_card *card = rtd->card; + unsigned int num_codecs = get_num_codecs(MAX_98373_ACPI_HID); int ret; - ret = snd_soc_dapm_add_routes(&card->dapm, max_98373_dapm_routes, - ARRAY_SIZE(max_98373_dapm_routes)); - if (ret) - dev_err(rtd->dev, "Speaker map addition failed: %d\n", ret); + switch (num_codecs) { + case 2: + ret = snd_soc_dapm_new_controls(&card->dapm, maxim_2spk_widgets, + ARRAY_SIZE(maxim_2spk_widgets)); + if (ret) { + dev_err(rtd->dev, "fail to add max98373 widgets, ret %d\n", + ret); + return ret; + } + + ret = snd_soc_add_card_controls(card, maxim_2spk_kcontrols, + ARRAY_SIZE(maxim_2spk_kcontrols)); + if (ret) { + dev_err(rtd->dev, "fail to add max98373 kcontrols, ret %d\n", + ret); + return ret; + } + + ret = snd_soc_dapm_add_routes(&card->dapm, max_98373_dapm_routes, + ARRAY_SIZE(max_98373_dapm_routes)); + if (ret) { + dev_err(rtd->dev, "fail to add max98373 routes, ret %d\n", + ret); + return ret; + } + break; + default: + dev_err(rtd->dev, "max98373: invalid num_codecs %d\n", num_codecs); + return -EINVAL; + } + return ret; } EXPORT_SYMBOL_NS(max_98373_spk_codec_init, SND_SOC_INTEL_SOF_MAXIM_COMMON); @@ -287,6 +329,22 @@ static int max_98390_init(struct snd_soc_pcm_runtime *rtd) fallthrough; case 2: /* add regular speakers dapm route */ + ret = snd_soc_dapm_new_controls(&card->dapm, maxim_2spk_widgets, + ARRAY_SIZE(maxim_2spk_widgets)); + if (ret) { + dev_err(rtd->dev, "fail to add max98390 woofer widgets, ret %d\n", + ret); + return ret; + } + + ret = snd_soc_add_card_controls(card, maxim_2spk_kcontrols, + ARRAY_SIZE(maxim_2spk_kcontrols)); + if (ret) { + dev_err(rtd->dev, "fail to add max98390 woofer kcontrols, ret %d\n", + ret); + return ret; + } + ret = snd_soc_dapm_add_routes(&card->dapm, max_98390_dapm_routes, ARRAY_SIZE(max_98390_dapm_routes)); if (ret) { diff --git a/sound/soc/intel/boards/sof_nau8825.c b/sound/soc/intel/boards/sof_nau8825.c index fe5f9e8dd652..dd4dc4ec4255 100644 --- a/sound/soc/intel/boards/sof_nau8825.c +++ b/sound/soc/intel/boards/sof_nau8825.c @@ -140,15 +140,11 @@ static int sof_card_late_probe(struct snd_soc_card *card) static const struct snd_kcontrol_new sof_controls[] = { SOC_DAPM_PIN_SWITCH("Headphone Jack"), SOC_DAPM_PIN_SWITCH("Headset Mic"), - SOC_DAPM_PIN_SWITCH("Left Spk"), - SOC_DAPM_PIN_SWITCH("Right Spk"), }; static const struct snd_soc_dapm_widget sof_widgets[] = { SND_SOC_DAPM_HP("Headphone Jack", NULL), SND_SOC_DAPM_MIC("Headset Mic", NULL), - SND_SOC_DAPM_SPK("Left Spk", NULL), - SND_SOC_DAPM_SPK("Right Spk", NULL), }; static const struct snd_soc_dapm_route sof_map[] = { diff --git a/sound/soc/intel/boards/sof_realtek_common.c b/sound/soc/intel/boards/sof_realtek_common.c index 20d094c52d28..cb1c21d822f6 100644 --- a/sound/soc/intel/boards/sof_realtek_common.c +++ b/sound/soc/intel/boards/sof_realtek_common.c @@ -21,6 +21,17 @@ /* * Common structures and functions */ +static const struct snd_kcontrol_new realtek_2spk_kcontrols[] = { + SOC_DAPM_PIN_SWITCH("Left Spk"), + SOC_DAPM_PIN_SWITCH("Right Spk"), + +}; + +static const struct snd_soc_dapm_widget realtek_2spk_widgets[] = { + SND_SOC_DAPM_SPK("Left Spk", NULL), + SND_SOC_DAPM_SPK("Right Spk", NULL), +}; + static const struct snd_kcontrol_new realtek_4spk_kcontrols[] = { SOC_DAPM_PIN_SWITCH("WL Ext Spk"), SOC_DAPM_PIN_SWITCH("WR Ext Spk"), @@ -181,6 +192,22 @@ static int rt1011_init(struct snd_soc_pcm_runtime *rtd) switch (num_codecs) { case 2: if (!soc_intel_is_cml()) { + ret = snd_soc_dapm_new_controls(&card->dapm, realtek_2spk_widgets, + ARRAY_SIZE(realtek_2spk_widgets)); + if (ret) { + dev_err(rtd->dev, "fail to add rt1011 widgets, ret %d\n", + ret); + return ret; + } + + ret = snd_soc_add_card_controls(card, realtek_2spk_kcontrols, + ARRAY_SIZE(realtek_2spk_kcontrols)); + if (ret) { + dev_err(rtd->dev, "fail to add rt1011 kcontrols, ret %d\n", + ret); + return ret; + } + ret = snd_soc_dapm_add_routes(&card->dapm, speaker_map_lr, ARRAY_SIZE(speaker_map_lr)); if (ret) { @@ -357,6 +384,20 @@ static int rt1015p_init(struct snd_soc_pcm_runtime *rtd) struct snd_soc_card *card = rtd->card; int ret; + ret = snd_soc_dapm_new_controls(&card->dapm, realtek_2spk_widgets, + ARRAY_SIZE(realtek_2spk_widgets)); + if (ret) { + dev_err(rtd->dev, "fail to add rt1015p widgets, ret %d\n", ret); + return ret; + } + + ret = snd_soc_add_card_controls(card, realtek_2spk_kcontrols, + ARRAY_SIZE(realtek_2spk_kcontrols)); + if (ret) { + dev_err(rtd->dev, "fail to add rt1015p kcontrols, ret %d\n", ret); + return ret; + } + if (rt1015p_get_num_codecs() == 1) ret = snd_soc_dapm_add_routes(&card->dapm, rt1015p_1dev_dapm_routes, ARRAY_SIZE(rt1015p_1dev_dapm_routes)); @@ -486,8 +527,42 @@ static struct snd_soc_dai_link_component rt1015_components[] = { static int speaker_codec_init_lr(struct snd_soc_pcm_runtime *rtd) { - return snd_soc_dapm_add_routes(&rtd->card->dapm, speaker_map_lr, - ARRAY_SIZE(speaker_map_lr)); + struct snd_soc_card *card = rtd->card; + unsigned int num_codecs = get_num_codecs(RT1015_ACPI_HID); + int ret; + + switch (num_codecs) { + case 2: + ret = snd_soc_dapm_new_controls(&card->dapm, realtek_2spk_widgets, + ARRAY_SIZE(realtek_2spk_widgets)); + if (ret) { + dev_err(rtd->dev, "fail to add rt1015 widgets, ret %d\n", + ret); + return ret; + } + + ret = snd_soc_add_card_controls(card, realtek_2spk_kcontrols, + ARRAY_SIZE(realtek_2spk_kcontrols)); + if (ret) { + dev_err(rtd->dev, "fail to add rt1015 kcontrols, ret %d\n", + ret); + return ret; + } + + ret = snd_soc_dapm_add_routes(&rtd->card->dapm, speaker_map_lr, + ARRAY_SIZE(speaker_map_lr)); + if (ret) { + dev_err(rtd->dev, "fail to add rt1015 routes, ret %d\n", + ret); + return ret; + } + break; + default: + dev_err(rtd->dev, "rt1015: invalid num_codecs %d\n", num_codecs); + return -EINVAL; + } + + return ret; } void sof_rt1015_codec_conf(struct snd_soc_card *card) @@ -624,6 +699,20 @@ static int rt1019p_init(struct snd_soc_pcm_runtime *rtd) struct snd_soc_card *card = rtd->card; int ret; + ret = snd_soc_dapm_new_controls(&card->dapm, realtek_2spk_widgets, + ARRAY_SIZE(realtek_2spk_widgets)); + if (ret) { + dev_err(rtd->dev, "fail to add rt1019p widgets, ret %d\n", ret); + return ret; + } + + ret = snd_soc_add_card_controls(card, realtek_2spk_kcontrols, + ARRAY_SIZE(realtek_2spk_kcontrols)); + if (ret) { + dev_err(rtd->dev, "fail to add rt1019p kcontrols, ret %d\n", ret); + return ret; + } + ret = snd_soc_dapm_add_routes(&card->dapm, rt1019p_dapm_routes, ARRAY_SIZE(rt1019p_dapm_routes)); if (ret) { diff --git a/sound/soc/intel/boards/sof_rt5682.c b/sound/soc/intel/boards/sof_rt5682.c index 062012de3de2..1e70ce469650 100644 --- a/sound/soc/intel/boards/sof_rt5682.c +++ b/sound/soc/intel/boards/sof_rt5682.c @@ -431,16 +431,11 @@ static int sof_card_late_probe(struct snd_soc_card *card) static const struct snd_kcontrol_new sof_controls[] = { SOC_DAPM_PIN_SWITCH("Headphone Jack"), SOC_DAPM_PIN_SWITCH("Headset Mic"), - SOC_DAPM_PIN_SWITCH("Left Spk"), - SOC_DAPM_PIN_SWITCH("Right Spk"), - }; static const struct snd_soc_dapm_widget sof_widgets[] = { SND_SOC_DAPM_HP("Headphone Jack", NULL), SND_SOC_DAPM_MIC("Headset Mic", NULL), - SND_SOC_DAPM_SPK("Left Spk", NULL), - SND_SOC_DAPM_SPK("Right Spk", NULL), }; static const struct snd_soc_dapm_route sof_map[] = { @@ -452,6 +447,17 @@ static const struct snd_soc_dapm_route sof_map[] = { { "IN1P", NULL, "Headset Mic" }, }; +static const struct snd_kcontrol_new rt5650_spk_kcontrols[] = { + SOC_DAPM_PIN_SWITCH("Left Spk"), + SOC_DAPM_PIN_SWITCH("Right Spk"), + +}; + +static const struct snd_soc_dapm_widget rt5650_spk_widgets[] = { + SND_SOC_DAPM_SPK("Left Spk", NULL), + SND_SOC_DAPM_SPK("Right Spk", NULL), +}; + static const struct snd_soc_dapm_route rt5650_spk_dapm_routes[] = { /* speaker */ { "Left Spk", NULL, "SPOL" }, @@ -463,6 +469,22 @@ static int rt5650_spk_init(struct snd_soc_pcm_runtime *rtd) struct snd_soc_card *card = rtd->card; int ret; + ret = snd_soc_dapm_new_controls(&card->dapm, rt5650_spk_widgets, + ARRAY_SIZE(rt5650_spk_widgets)); + if (ret) { + dev_err(rtd->dev, "fail to add rt5650 spk widgets, ret %d\n", + ret); + return ret; + } + + ret = snd_soc_add_card_controls(card, rt5650_spk_kcontrols, + ARRAY_SIZE(rt5650_spk_kcontrols)); + if (ret) { + dev_err(rtd->dev, "fail to add rt5650 spk kcontrols, ret %d\n", + ret); + return ret; + } + ret = snd_soc_dapm_add_routes(&card->dapm, rt5650_spk_dapm_routes, ARRAY_SIZE(rt5650_spk_dapm_routes)); if (ret) -- cgit v1.2.3 From 3b3ed4752600b6462c184edc3284dcc277891aa6 Mon Sep 17 00:00:00 2001 From: Brent Lu Date: Fri, 26 Apr 2024 10:25:08 -0500 Subject: ASoC: Intel: sof_maxim_common: support MAX98390 on cml boards Add support for 2xMAX98390 speaker amplifier running in I2S mode for existing cml boards. Reviewed-by: Bard Liao Signed-off-by: Brent Lu Signed-off-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20240426152529.38345-3-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/intel/boards/sof_maxim_common.c | 42 +++++++++++++++++++++++++------ 1 file changed, 35 insertions(+), 7 deletions(-) diff --git a/sound/soc/intel/boards/sof_maxim_common.c b/sound/soc/intel/boards/sof_maxim_common.c index 53c7392bf3dd..bb12aab15ad5 100644 --- a/sound/soc/intel/boards/sof_maxim_common.c +++ b/sound/soc/intel/boards/sof_maxim_common.c @@ -10,6 +10,7 @@ #include #include #include +#include "../common/soc-intel-quirks.h" #include "sof_maxim_common.h" /* @@ -219,6 +220,17 @@ static const struct snd_soc_dapm_route max_98390_tt_dapm_routes[] = { { "TR Spk", NULL, "Tweeter Right BE_OUT" }, }; +static struct snd_soc_codec_conf max_98390_cml_codec_conf[] = { + { + .dlc = COMP_CODEC_CONF(MAX_98390_DEV0_NAME), + .name_prefix = "Left", + }, + { + .dlc = COMP_CODEC_CONF(MAX_98390_DEV1_NAME), + .name_prefix = "Right", + }, +}; + static struct snd_soc_codec_conf max_98390_codec_conf[] = { { .dlc = COMP_CODEC_CONF(MAX_98390_DEV0_NAME), @@ -271,6 +283,7 @@ static int max_98390_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream); + struct snd_soc_dai_link *dai_link = rtd->dai_link; struct snd_soc_dai *codec_dai; int i, ret; @@ -280,13 +293,24 @@ static int max_98390_hw_params(struct snd_pcm_substream *substream, return -ENODEV; } - ret = snd_soc_dai_set_tdm_slot(codec_dai, max_98390_tdm_mask[i].tx, - max_98390_tdm_mask[i].rx, 4, - params_width(params)); - if (ret < 0) { - dev_err(codec_dai->dev, "fail to set tdm slot, ret %d\n", - ret); - return ret; + switch (dai_link->dai_fmt & SND_SOC_DAIFMT_FORMAT_MASK) { + case SND_SOC_DAIFMT_DSP_A: + case SND_SOC_DAIFMT_DSP_B: + /* 4-slot TDM */ + ret = snd_soc_dai_set_tdm_slot(codec_dai, + max_98390_tdm_mask[i].tx, + max_98390_tdm_mask[i].rx, + 4, + params_width(params)); + if (ret < 0) { + dev_err(codec_dai->dev, "fail to set tdm slot, ret %d\n", + ret); + return ret; + } + break; + default: + dev_dbg(codec_dai->dev, "codec is in I2S mode\n"); + break; } } return 0; @@ -395,6 +419,10 @@ void max_98390_set_codec_conf(struct device *dev, struct snd_soc_card *card) switch (num_codecs) { case 2: + if (soc_intel_is_cml()) + card->codec_conf = max_98390_cml_codec_conf; + + fallthrough; case 4: card->num_configs = num_codecs; break; -- cgit v1.2.3 From b7654a7e217704694ed3e484f0a3c415f8678896 Mon Sep 17 00:00:00 2001 From: Brent Lu Date: Fri, 26 Apr 2024 10:25:09 -0500 Subject: ASoC: Intel: sof_da7219: support MAX98390 Add support to Maxim MAX98390 speaker amplifier. Reviewed-by: Bard Liao Signed-off-by: Brent Lu Signed-off-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20240426152529.38345-4-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/intel/boards/Kconfig | 1 + sound/soc/intel/boards/sof_da7219.c | 6 ++++++ 2 files changed, 7 insertions(+) diff --git a/sound/soc/intel/boards/Kconfig b/sound/soc/intel/boards/Kconfig index 0ad7b0a1e237..e300af4d6b9f 100644 --- a/sound/soc/intel/boards/Kconfig +++ b/sound/soc/intel/boards/Kconfig @@ -614,6 +614,7 @@ config SND_SOC_INTEL_SOF_DA7219_MACH select SND_SOC_DA7219 select SND_SOC_MAX98357A select SND_SOC_MAX98373_I2C + select SND_SOC_MAX98390 select SND_SOC_DMIC select SND_SOC_INTEL_SOF_BOARD_HELPERS select SND_SOC_INTEL_SOF_MAXIM_COMMON diff --git a/sound/soc/intel/boards/sof_da7219.c b/sound/soc/intel/boards/sof_da7219.c index cbbce07ec5f7..de5b0a8b5b8c 100644 --- a/sound/soc/intel/boards/sof_da7219.c +++ b/sound/soc/intel/boards/sof_da7219.c @@ -281,6 +281,9 @@ sof_card_dai_links_create(struct device *dev, struct snd_soc_card *card, return -EINVAL; } break; + case CODEC_MAX98390: + max_98390_dai_link(dev, ctx->amp_link); + break; default: dev_err(dev, "invalid amp type %d\n", ctx->amp_type); return -EINVAL; @@ -352,6 +355,9 @@ static int audio_probe(struct platform_device *pdev) case CODEC_MAX98373: max_98373_set_codec_conf(&card_da7219); break; + case CODEC_MAX98390: + max_98390_set_codec_conf(&pdev->dev, &card_da7219); + break; case CODEC_MAX98360A: case CODEC_NONE: /* no codec conf required */ -- cgit v1.2.3 From a0cf86d813d22d80046d83e9b36c1c2308903956 Mon Sep 17 00:00:00 2001 From: Brent Lu Date: Fri, 26 Apr 2024 10:25:10 -0500 Subject: ASoC: Intel: sof_da7219: add cml_da7219_def for cml boards Add the board config cml_da7219_def to da7219 machine driver for all cml boards using default SSP port allocation (headphone codec on SSP0, speaker amplifiers on SSP1). Reviewed-by: Bard Liao Signed-off-by: Brent Lu Signed-off-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20240426152529.38345-5-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/intel/boards/sof_da7219.c | 24 +++++++++++++++++++++--- 1 file changed, 21 insertions(+), 3 deletions(-) diff --git a/sound/soc/intel/boards/sof_da7219.c b/sound/soc/intel/boards/sof_da7219.c index de5b0a8b5b8c..69555eee7c7a 100644 --- a/sound/soc/intel/boards/sof_da7219.c +++ b/sound/soc/intel/boards/sof_da7219.c @@ -19,8 +19,9 @@ #include "sof_maxim_common.h" /* Driver-specific board quirks: from bit 0 to 7 */ -#define SOF_DA7219_JSL_BOARD BIT(0) -#define SOF_DA7219_MCLK_EN BIT(1) +#define SOF_DA7219_CML_BOARD BIT(0) +#define SOF_DA7219_JSL_BOARD BIT(1) +#define SOF_DA7219_MCLK_EN BIT(2) #define DIALOG_CODEC_DAI "da7219-hifi" @@ -292,6 +293,14 @@ sof_card_dai_links_create(struct device *dev, struct snd_soc_card *card, return 0; } +#define CML_LINK_ORDER SOF_LINK_ORDER(SOF_LINK_AMP, \ + SOF_LINK_CODEC, \ + SOF_LINK_DMIC01, \ + SOF_LINK_IDISP_HDMI, \ + SOF_LINK_DMIC16K, \ + SOF_LINK_NONE, \ + SOF_LINK_NONE) + #define JSL_LINK_ORDER SOF_LINK_ORDER(SOF_LINK_AMP, \ SOF_LINK_CODEC, \ SOF_LINK_DMIC01, \ @@ -320,7 +329,10 @@ static int audio_probe(struct platform_device *pdev) if (mach->mach_params.codec_mask & IDISP_CODEC_MASK) ctx->hdmi.idisp_codec = true; - if (board_quirk & SOF_DA7219_JSL_BOARD) { + if (board_quirk & SOF_DA7219_CML_BOARD) { + /* overwrite the DAI link order for CML boards */ + ctx->link_order_overwrite = CML_LINK_ORDER; + } else if (board_quirk & SOF_DA7219_JSL_BOARD) { ctx->da7219.is_jsl_board = true; /* overwrite the DAI link order for JSL boards */ @@ -380,6 +392,12 @@ static int audio_probe(struct platform_device *pdev) } static const struct platform_device_id board_ids[] = { + { + .name = "cml_da7219_def", + .driver_data = (kernel_ulong_t)(SOF_DA7219_CML_BOARD | + SOF_SSP_PORT_CODEC(0) | + SOF_SSP_PORT_AMP(1)), + }, { .name = "jsl_da7219_def", .driver_data = (kernel_ulong_t)(SOF_DA7219_JSL_BOARD | -- cgit v1.2.3 From 5a2bc761fab23e47ef20a847476d504548dfb417 Mon Sep 17 00:00:00 2001 From: Brent Lu Date: Fri, 26 Apr 2024 10:25:11 -0500 Subject: ASoC: Intel: sof_da7219: support MAX98390 on cml boards For cml boards, MAX98390 speaker amplifier is supported by machine driver bxt_da7219_max98357a with sound card name cml_max98390_da7219. Use same name for backward compatibility with existing devices on market. Reviewed-by: Bard Liao Signed-off-by: Brent Lu Signed-off-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20240426152529.38345-6-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/intel/boards/sof_da7219.c | 33 ++++++++++++++++++++++++++++----- 1 file changed, 28 insertions(+), 5 deletions(-) diff --git a/sound/soc/intel/boards/sof_da7219.c b/sound/soc/intel/boards/sof_da7219.c index 69555eee7c7a..0abb71a10a72 100644 --- a/sound/soc/intel/boards/sof_da7219.c +++ b/sound/soc/intel/boards/sof_da7219.c @@ -313,6 +313,7 @@ static int audio_probe(struct platform_device *pdev) { struct snd_soc_acpi_mach *mach = pdev->dev.platform_data; struct sof_card_private *ctx; + char *card_name; unsigned long board_quirk = 0; int ret; @@ -332,6 +333,21 @@ static int audio_probe(struct platform_device *pdev) if (board_quirk & SOF_DA7219_CML_BOARD) { /* overwrite the DAI link order for CML boards */ ctx->link_order_overwrite = CML_LINK_ORDER; + + /* backward-compatible with existing devices */ + switch (ctx->amp_type) { + case CODEC_MAX98390: + card_name = devm_kstrdup(&pdev->dev, + "cml_max98390_da7219", + GFP_KERNEL); + if (!card_name) + return -ENOMEM; + + card_da7219.name = card_name; + break; + default: + break; + } } else if (board_quirk & SOF_DA7219_JSL_BOARD) { ctx->da7219.is_jsl_board = true; @@ -341,13 +357,20 @@ static int audio_probe(struct platform_device *pdev) /* backward-compatible with existing devices */ switch (ctx->amp_type) { case CODEC_MAX98360A: - card_da7219.name = devm_kstrdup(&pdev->dev, - "da7219max98360a", - GFP_KERNEL); + card_name = devm_kstrdup(&pdev->dev, "da7219max98360a", + GFP_KERNEL); + if (!card_name) + return -ENOMEM; + + card_da7219.name = card_name; break; case CODEC_MAX98373: - card_da7219.name = devm_kstrdup(&pdev->dev, "da7219max", - GFP_KERNEL); + card_name = devm_kstrdup(&pdev->dev, "da7219max", + GFP_KERNEL); + if (!card_name) + return -ENOMEM; + + card_da7219.name = card_name; break; default: break; -- cgit v1.2.3 From 12e5fe68d0bb079cc5228d09280c1d82a61f0d18 Mon Sep 17 00:00:00 2001 From: Brent Lu Date: Fri, 26 Apr 2024 10:25:12 -0500 Subject: ASoC: Intel: bxt_da7219_max98357a: remove MAX98390 support Remove MAX98390 support and use sof_da7219 machine driver instead for existing cml boards with MAX98390 speaker amplifier. Reviewed-by: Bard Liao Signed-off-by: Brent Lu Signed-off-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20240426152529.38345-7-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/intel/boards/Kconfig | 6 +- sound/soc/intel/boards/bxt_da7219_max98357a.c | 109 +--------------------- sound/soc/intel/common/soc-acpi-intel-cml-match.c | 2 +- 3 files changed, 6 insertions(+), 111 deletions(-) diff --git a/sound/soc/intel/boards/Kconfig b/sound/soc/intel/boards/Kconfig index e300af4d6b9f..44cf1a8df510 100644 --- a/sound/soc/intel/boards/Kconfig +++ b/sound/soc/intel/boards/Kconfig @@ -301,7 +301,6 @@ config SND_SOC_INTEL_DA7219_MAX98357A_GENERIC tristate select SND_SOC_DA7219 select SND_SOC_MAX98357A - select SND_SOC_MAX98390 select SND_SOC_DMIC select SND_SOC_HDAC_HDMI select SND_SOC_INTEL_HDA_DSP_COMMON @@ -313,14 +312,14 @@ config SND_SOC_INTEL_BXT_DA7219_MAX98357A_COMMON if SND_SOC_INTEL_APL config SND_SOC_INTEL_BXT_DA7219_MAX98357A_MACH - tristate "Broxton with DA7219 and MAX98357A/MAX98390 in I2S Mode" + tristate "Broxton with DA7219 and MAX98357A in I2S Mode" depends on I2C && ACPI depends on MFD_INTEL_LPSS || COMPILE_TEST depends on SND_HDA_CODEC_HDMI select SND_SOC_INTEL_BXT_DA7219_MAX98357A_COMMON help This adds support for ASoC machine driver for Broxton-P platforms - with DA7219 + MAX98357A/MAX98390 I2S audio codec. + with DA7219 + MAX98357A I2S audio codec. Say Y or m if you have such a device. This is a recommended option. If unsure select "N". @@ -587,6 +586,7 @@ config SND_SOC_INTEL_CML_LP_DA7219_MAX98357A_MACH depends on I2C && ACPI depends on MFD_INTEL_LPSS || COMPILE_TEST select SND_SOC_INTEL_BXT_DA7219_MAX98357A_COMMON + imply SND_SOC_INTEL_SOF_DA7219_MACH help This adds support for ASoC machine driver for Cometlake platforms with DA7219 + MAX98357A I2S audio codec. diff --git a/sound/soc/intel/boards/bxt_da7219_max98357a.c b/sound/soc/intel/boards/bxt_da7219_max98357a.c index 3fe3f38c6cb6..9f167c828d1c 100644 --- a/sound/soc/intel/boards/bxt_da7219_max98357a.c +++ b/sound/soc/intel/boards/bxt_da7219_max98357a.c @@ -24,14 +24,9 @@ #define BXT_DIALOG_CODEC_DAI "da7219-hifi" #define BXT_MAXIM_CODEC_DAI "HiFi" -#define MAX98390_DEV0_NAME "i2c-MX98390:00" -#define MAX98390_DEV1_NAME "i2c-MX98390:01" #define DUAL_CHANNEL 2 #define QUAD_CHANNEL 4 -#define SPKAMP_MAX98357A 1 -#define SPKAMP_MAX98390 2 - static struct snd_soc_jack broxton_headset; static struct snd_soc_jack broxton_hdmi[3]; @@ -44,7 +39,6 @@ struct bxt_hdmi_pcm { struct bxt_card_private { struct list_head hdmi_pcm_list; bool common_hdmi_codec_drv; - int spkamp; }; enum { @@ -91,17 +85,9 @@ static const struct snd_kcontrol_new broxton_controls[] = { SOC_DAPM_PIN_SWITCH("Headphone Jack"), SOC_DAPM_PIN_SWITCH("Headset Mic"), SOC_DAPM_PIN_SWITCH("Line Out"), -}; - -static const struct snd_kcontrol_new max98357a_controls[] = { SOC_DAPM_PIN_SWITCH("Spk"), }; -static const struct snd_kcontrol_new max98390_controls[] = { - SOC_DAPM_PIN_SWITCH("Left Spk"), - SOC_DAPM_PIN_SWITCH("Right Spk"), -}; - static const struct snd_soc_dapm_widget broxton_widgets[] = { SND_SOC_DAPM_HP("Headphone Jack", NULL), SND_SOC_DAPM_MIC("Headset Mic", NULL), @@ -112,17 +98,9 @@ static const struct snd_soc_dapm_widget broxton_widgets[] = { SND_SOC_DAPM_SPK("HDMI3", NULL), SND_SOC_DAPM_SUPPLY("Platform Clock", SND_SOC_NOPM, 0, 0, platform_clock_control, SND_SOC_DAPM_POST_PMD|SND_SOC_DAPM_PRE_PMU), -}; - -static const struct snd_soc_dapm_widget max98357a_widgets[] = { SND_SOC_DAPM_SPK("Spk", NULL), }; -static const struct snd_soc_dapm_widget max98390_widgets[] = { - SND_SOC_DAPM_SPK("Left Spk", NULL), - SND_SOC_DAPM_SPK("Right Spk", NULL), -}; - static const struct snd_soc_dapm_route audio_map[] = { /* HP jack connectors - unknown if we have jack detection */ {"Headphone Jack", NULL, "HPL"}, @@ -153,19 +131,11 @@ static const struct snd_soc_dapm_route audio_map[] = { { "Headphone Jack", NULL, "Platform Clock" }, { "Headset Mic", NULL, "Platform Clock" }, { "Line Out", NULL, "Platform Clock" }, -}; -static const struct snd_soc_dapm_route max98357a_routes[] = { /* speaker */ {"Spk", NULL, "Speaker"}, }; -static const struct snd_soc_dapm_route max98390_routes[] = { - /* Speaker */ - {"Left Spk", NULL, "Left BE_OUT"}, - {"Right Spk", NULL, "Right BE_OUT"}, -}; - static const struct snd_soc_dapm_route broxton_map[] = { {"HiFi Playback", NULL, "ssp5 Tx"}, {"ssp5 Tx", NULL, "codec0_out"}, @@ -453,10 +423,6 @@ SND_SOC_DAILINK_DEF(ssp5_pin, SND_SOC_DAILINK_DEF(ssp5_codec, DAILINK_COMP_ARRAY(COMP_CODEC("MX98357A:00", BXT_MAXIM_CODEC_DAI))); -SND_SOC_DAILINK_DEF(max98390_codec, - DAILINK_COMP_ARRAY( - /* Left */ COMP_CODEC(MAX98390_DEV0_NAME, "max98390-aif1"), - /* Right */ COMP_CODEC(MAX98390_DEV1_NAME, "max98390-aif1"))); SND_SOC_DAILINK_DEF(ssp1_pin, DAILINK_COMP_ARRAY(COMP_CPU("SSP1 Pin"))); @@ -654,69 +620,15 @@ static struct snd_soc_dai_link broxton_dais[] = { }, }; -static struct snd_soc_codec_conf max98390_codec_confs[] = { - { - .dlc = COMP_CODEC_CONF(MAX98390_DEV0_NAME), - .name_prefix = "Left", - }, - { - .dlc = COMP_CODEC_CONF(MAX98390_DEV1_NAME), - .name_prefix = "Right", - }, -}; - #define NAME_SIZE 32 static int bxt_card_late_probe(struct snd_soc_card *card) { struct bxt_card_private *ctx = snd_soc_card_get_drvdata(card); struct bxt_hdmi_pcm *pcm; struct snd_soc_component *component = NULL; - const struct snd_kcontrol_new *controls; - const struct snd_soc_dapm_widget *widgets; - const struct snd_soc_dapm_route *routes; - int num_controls, num_widgets, num_routes, err, i = 0; + int err, i = 0; char jack_name[NAME_SIZE]; - switch (ctx->spkamp) { - case SPKAMP_MAX98357A: - controls = max98357a_controls; - num_controls = ARRAY_SIZE(max98357a_controls); - widgets = max98357a_widgets; - num_widgets = ARRAY_SIZE(max98357a_widgets); - routes = max98357a_routes; - num_routes = ARRAY_SIZE(max98357a_routes); - break; - case SPKAMP_MAX98390: - controls = max98390_controls; - num_controls = ARRAY_SIZE(max98390_controls); - widgets = max98390_widgets; - num_widgets = ARRAY_SIZE(max98390_widgets); - routes = max98390_routes; - num_routes = ARRAY_SIZE(max98390_routes); - break; - default: - dev_err(card->dev, "Invalid speaker amplifier %d\n", ctx->spkamp); - return -EINVAL; - } - - err = snd_soc_dapm_new_controls(&card->dapm, widgets, num_widgets); - if (err) { - dev_err(card->dev, "Fail to new widgets\n"); - return err; - } - - err = snd_soc_add_card_controls(card, controls, num_controls); - if (err) { - dev_err(card->dev, "Fail to add controls\n"); - return err; - } - - err = snd_soc_dapm_add_routes(&card->dapm, routes, num_routes); - if (err) { - dev_err(card->dev, "Fail to add routes\n"); - return err; - } - if (soc_intel_is_glk()) snd_soc_dapm_add_routes(&card->dapm, gemini_map, ARRAY_SIZE(gemini_map)); @@ -785,11 +697,6 @@ static int broxton_audio_probe(struct platform_device *pdev) INIT_LIST_HEAD(&ctx->hdmi_pcm_list); - if (acpi_dev_present("MX98390", NULL, -1)) - ctx->spkamp = SPKAMP_MAX98390; - else - ctx->spkamp = SPKAMP_MAX98357A; - broxton_audio_card.dev = &pdev->dev; snd_soc_card_set_drvdata(&broxton_audio_card, ctx); if (soc_intel_is_glk()) { @@ -817,13 +724,7 @@ static int broxton_audio_probe(struct platform_device *pdev) } else if (soc_intel_is_cml()) { unsigned int i; - if (ctx->spkamp == SPKAMP_MAX98390) { - broxton_audio_card.name = "cml_max98390_da7219"; - - broxton_audio_card.codec_conf = max98390_codec_confs; - broxton_audio_card.num_configs = ARRAY_SIZE(max98390_codec_confs); - } else - broxton_audio_card.name = "cmlda7219max"; + broxton_audio_card.name = "cmlda7219max"; for (i = 0; i < ARRAY_SIZE(broxton_dais); i++) { if (!broxton_dais[i].codecs->dai_name) @@ -834,12 +735,6 @@ static int broxton_audio_probe(struct platform_device *pdev) BXT_MAXIM_CODEC_DAI)) { broxton_dais[i].name = "SSP1-Codec"; broxton_dais[i].cpus->dai_name = "SSP1 Pin"; - - if (ctx->spkamp == SPKAMP_MAX98390) { - broxton_dais[i].codecs = max98390_codec; - broxton_dais[i].num_codecs = ARRAY_SIZE(max98390_codec); - broxton_dais[i].dpcm_capture = 1; - } } /* DIALOG_CODEC is connected to SSP0 */ else if (!strcmp(broxton_dais[i].codecs->dai_name, diff --git a/sound/soc/intel/common/soc-acpi-intel-cml-match.c b/sound/soc/intel/common/soc-acpi-intel-cml-match.c index 160bfa0e5ef5..4217dbb716dc 100644 --- a/sound/soc/intel/common/soc-acpi-intel-cml-match.c +++ b/sound/soc/intel/common/soc-acpi-intel-cml-match.c @@ -75,7 +75,7 @@ struct snd_soc_acpi_mach snd_soc_acpi_intel_cml_machines[] = { }, { .id = "DLGS7219", - .drv_name = "cml_da7219_mx98357a", + .drv_name = "cml_da7219_def", .machine_quirk = snd_soc_acpi_codec_list, .quirk_data = &max98390_spk_codecs, .sof_tplg_filename = "sof-cml-da7219-max98390.tplg", -- cgit v1.2.3 From 5b093b0b47efefbb928c4d3a5e982bbeaefda44c Mon Sep 17 00:00:00 2001 From: Bard Liao Date: Fri, 26 Apr 2024 10:25:13 -0500 Subject: ASoC: Intel: sof_rt5682: add missing MAX98357A config sof_rt5682 supports MAX98357A/MAX98360A amp. Select SND_SOC_MAX98357A as needed. Reviewed-by: Ranjani Sridharan Signed-off-by: Bard Liao Signed-off-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20240426152529.38345-8-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/intel/boards/Kconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/sound/soc/intel/boards/Kconfig b/sound/soc/intel/boards/Kconfig index 44cf1a8df510..a61c3d0435c4 100644 --- a/sound/soc/intel/boards/Kconfig +++ b/sound/soc/intel/boards/Kconfig @@ -486,6 +486,7 @@ config SND_SOC_INTEL_SOF_RT5682_MACH depends on ((SND_HDA_CODEC_HDMI && SND_SOC_SOF_HDA_AUDIO_CODEC) &&\ (MFD_INTEL_LPSS || COMPILE_TEST)) ||\ (SND_SOC_SOF_BAYTRAIL && (X86_INTEL_LPSS || COMPILE_TEST)) + select SND_SOC_MAX98357A select SND_SOC_MAX98373_I2C select SND_SOC_MAX98390 select SND_SOC_RT1011 -- cgit v1.2.3 From 7873252c0e44ef5c0e04cf3c7c25f5e2c5180272 Mon Sep 17 00:00:00 2001 From: Brent Lu Date: Fri, 26 Apr 2024 10:25:14 -0500 Subject: ASoC: Intel: sof_da7219: support MAX98357A Add support to Maxim MAX98357A speaker amplifier. Reviewed-by: Bard Liao Signed-off-by: Brent Lu Signed-off-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20240426152529.38345-9-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/intel/boards/sof_da7219.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/sound/soc/intel/boards/sof_da7219.c b/sound/soc/intel/boards/sof_da7219.c index 0abb71a10a72..610b5a8e0860 100644 --- a/sound/soc/intel/boards/sof_da7219.c +++ b/sound/soc/intel/boards/sof_da7219.c @@ -267,6 +267,9 @@ sof_card_dai_links_create(struct device *dev, struct snd_soc_card *card, /* codec-specific fields for speaker amplifier */ switch (ctx->amp_type) { + case CODEC_MAX98357A: + max_98357a_dai_link(ctx->amp_link); + break; case CODEC_MAX98360A: max_98360a_dai_link(ctx->amp_link); break; @@ -393,6 +396,7 @@ static int audio_probe(struct platform_device *pdev) case CODEC_MAX98390: max_98390_set_codec_conf(&pdev->dev, &card_da7219); break; + case CODEC_MAX98357A: case CODEC_MAX98360A: case CODEC_NONE: /* no codec conf required */ -- cgit v1.2.3 From e895d16f4e8f0e5d90d7188e8fd9c507a97fb8b7 Mon Sep 17 00:00:00 2001 From: Brent Lu Date: Fri, 26 Apr 2024 10:25:15 -0500 Subject: ASoC: Intel: sof_da7219: support MAX98357A on cml boards For cml boards, MAX98357A speaker amplifier is supported by machine driver bxt_da7219_max98357a with sound card name cmlda7219max. Use same name for backward compatibility with existing devices on market. Reviewed-by: Bard Liao Signed-off-by: Brent Lu Signed-off-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20240426152529.38345-10-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/intel/boards/sof_da7219.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/sound/soc/intel/boards/sof_da7219.c b/sound/soc/intel/boards/sof_da7219.c index 610b5a8e0860..ecb1d4b25ea6 100644 --- a/sound/soc/intel/boards/sof_da7219.c +++ b/sound/soc/intel/boards/sof_da7219.c @@ -339,6 +339,14 @@ static int audio_probe(struct platform_device *pdev) /* backward-compatible with existing devices */ switch (ctx->amp_type) { + case CODEC_MAX98357A: + card_name = devm_kstrdup(&pdev->dev, "cmlda7219max", + GFP_KERNEL); + if (!card_name) + return -ENOMEM; + + card_da7219.name = card_name; + break; case CODEC_MAX98390: card_name = devm_kstrdup(&pdev->dev, "cml_max98390_da7219", -- cgit v1.2.3 From 35ca48662cdf0749a2b9931d625690967fbce032 Mon Sep 17 00:00:00 2001 From: Brent Lu Date: Fri, 26 Apr 2024 10:25:16 -0500 Subject: ASoC: Intel: bxt_da7219_max98357a: remove cml support Remove cml platform support and use sof_da7219 machine driver instead for existing cml boards with MAX98357A speaker amplifier. Reviewed-by: Bard Liao Signed-off-by: Brent Lu Signed-off-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20240426152529.38345-11-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/intel/boards/Kconfig | 6 ++--- sound/soc/intel/boards/bxt_da7219_max98357a.c | 28 +---------------------- sound/soc/intel/common/soc-acpi-intel-cml-match.c | 2 +- 3 files changed, 4 insertions(+), 32 deletions(-) diff --git a/sound/soc/intel/boards/Kconfig b/sound/soc/intel/boards/Kconfig index a61c3d0435c4..134512a7d3b8 100644 --- a/sound/soc/intel/boards/Kconfig +++ b/sound/soc/intel/boards/Kconfig @@ -584,13 +584,11 @@ if (SND_SOC_SOF_COMETLAKE && SND_SOC_SOF_HDA_LINK) config SND_SOC_INTEL_CML_LP_DA7219_MAX98357A_MACH tristate "CML_LP with DA7219 and MAX98357A in I2S Mode" - depends on I2C && ACPI - depends on MFD_INTEL_LPSS || COMPILE_TEST - select SND_SOC_INTEL_BXT_DA7219_MAX98357A_COMMON imply SND_SOC_INTEL_SOF_DA7219_MACH help This adds support for ASoC machine driver for Cometlake platforms - with DA7219 + MAX98357A I2S audio codec. + with DA7219 + MAX98357A I2S audio codec. This option is deprecated + and please use SND_SOC_INTEL_SOF_DA7219_MACH instead. Say Y or m if you have such a device. This is a recommended option. If unsure select "N". diff --git a/sound/soc/intel/boards/bxt_da7219_max98357a.c b/sound/soc/intel/boards/bxt_da7219_max98357a.c index 9f167c828d1c..45fe1d7b8865 100644 --- a/sound/soc/intel/boards/bxt_da7219_max98357a.c +++ b/sound/soc/intel/boards/bxt_da7219_max98357a.c @@ -201,10 +201,7 @@ static int broxton_da7219_codec_init(struct snd_soc_pcm_runtime *rtd) int clk_freq; /* Configure sysclk for codec */ - if (soc_intel_is_cml()) - clk_freq = 24000000; - else - clk_freq = 19200000; + clk_freq = 19200000; ret = snd_soc_dai_set_sysclk(codec_dai, DA7219_CLKSRC_MCLK, clk_freq, SND_SOC_CLOCK_IN); @@ -721,28 +718,6 @@ static int broxton_audio_probe(struct platform_device *pdev) broxton_dais[i].cpus->dai_name = "SSP2 Pin"; } } - } else if (soc_intel_is_cml()) { - unsigned int i; - - broxton_audio_card.name = "cmlda7219max"; - - for (i = 0; i < ARRAY_SIZE(broxton_dais); i++) { - if (!broxton_dais[i].codecs->dai_name) - continue; - - /* MAXIM_CODEC is connected to SSP1. */ - if (!strcmp(broxton_dais[i].codecs->dai_name, - BXT_MAXIM_CODEC_DAI)) { - broxton_dais[i].name = "SSP1-Codec"; - broxton_dais[i].cpus->dai_name = "SSP1 Pin"; - } - /* DIALOG_CODEC is connected to SSP0 */ - else if (!strcmp(broxton_dais[i].codecs->dai_name, - BXT_DIALOG_CODEC_DAI)) { - broxton_dais[i].name = "SSP0-Codec"; - broxton_dais[i].cpus->dai_name = "SSP0 Pin"; - } - } } /* override platform name, if required */ @@ -762,7 +737,6 @@ static int broxton_audio_probe(struct platform_device *pdev) static const struct platform_device_id bxt_board_ids[] = { { .name = "bxt_da7219_mx98357a" }, { .name = "glk_da7219_mx98357a" }, - { .name = "cml_da7219_mx98357a" }, { } }; MODULE_DEVICE_TABLE(platform, bxt_board_ids); diff --git a/sound/soc/intel/common/soc-acpi-intel-cml-match.c b/sound/soc/intel/common/soc-acpi-intel-cml-match.c index 4217dbb716dc..f79d7558174a 100644 --- a/sound/soc/intel/common/soc-acpi-intel-cml-match.c +++ b/sound/soc/intel/common/soc-acpi-intel-cml-match.c @@ -68,7 +68,7 @@ struct snd_soc_acpi_mach snd_soc_acpi_intel_cml_machines[] = { }, { .id = "DLGS7219", - .drv_name = "cml_da7219_mx98357a", + .drv_name = "cml_da7219_def", .machine_quirk = snd_soc_acpi_codec_list, .quirk_data = &max98357a_spk_codecs, .sof_tplg_filename = "sof-cml-da7219-max98357a.tplg", -- cgit v1.2.3 From c7f9523d21d49b56498ac58e4b1afcb930eb551a Mon Sep 17 00:00:00 2001 From: Brent Lu Date: Fri, 26 Apr 2024 10:25:17 -0500 Subject: ASoC: Intel: sof_da7219: add glk_da7219_def for glk boards Add the board config glk_da7219_def to da7219 machine driver for all glk boards using default SSP port allocation (headphone codec on SSP2, speaker amplifiers on SSP1). Reviewed-by: Bard Liao Signed-off-by: Brent Lu Signed-off-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20240426152529.38345-12-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/intel/boards/sof_da7219.c | 29 +++++++++++++++++++++++++---- 1 file changed, 25 insertions(+), 4 deletions(-) diff --git a/sound/soc/intel/boards/sof_da7219.c b/sound/soc/intel/boards/sof_da7219.c index ecb1d4b25ea6..cc5e99b21456 100644 --- a/sound/soc/intel/boards/sof_da7219.c +++ b/sound/soc/intel/boards/sof_da7219.c @@ -19,9 +19,10 @@ #include "sof_maxim_common.h" /* Driver-specific board quirks: from bit 0 to 7 */ -#define SOF_DA7219_CML_BOARD BIT(0) -#define SOF_DA7219_JSL_BOARD BIT(1) -#define SOF_DA7219_MCLK_EN BIT(2) +#define SOF_DA7219_GLK_BOARD BIT(0) +#define SOF_DA7219_CML_BOARD BIT(1) +#define SOF_DA7219_JSL_BOARD BIT(2) +#define SOF_DA7219_MCLK_EN BIT(3) #define DIALOG_CODEC_DAI "da7219-hifi" @@ -296,6 +297,14 @@ sof_card_dai_links_create(struct device *dev, struct snd_soc_card *card, return 0; } +#define GLK_LINK_ORDER SOF_LINK_ORDER(SOF_LINK_AMP, \ + SOF_LINK_CODEC, \ + SOF_LINK_DMIC01, \ + SOF_LINK_IDISP_HDMI, \ + SOF_LINK_NONE, \ + SOF_LINK_NONE, \ + SOF_LINK_NONE) + #define CML_LINK_ORDER SOF_LINK_ORDER(SOF_LINK_AMP, \ SOF_LINK_CODEC, \ SOF_LINK_DMIC01, \ @@ -333,7 +342,13 @@ static int audio_probe(struct platform_device *pdev) if (mach->mach_params.codec_mask & IDISP_CODEC_MASK) ctx->hdmi.idisp_codec = true; - if (board_quirk & SOF_DA7219_CML_BOARD) { + if (board_quirk & SOF_DA7219_GLK_BOARD) { + /* dmic16k not support */ + ctx->dmic_be_num = 1; + + /* overwrite the DAI link order for GLK boards */ + ctx->link_order_overwrite = GLK_LINK_ORDER; + } else if (board_quirk & SOF_DA7219_CML_BOARD) { /* overwrite the DAI link order for CML boards */ ctx->link_order_overwrite = CML_LINK_ORDER; @@ -427,6 +442,12 @@ static int audio_probe(struct platform_device *pdev) } static const struct platform_device_id board_ids[] = { + { + .name = "glk_da7219_def", + .driver_data = (kernel_ulong_t)(SOF_DA7219_GLK_BOARD | + SOF_SSP_PORT_CODEC(2) | + SOF_SSP_PORT_AMP(1)), + }, { .name = "cml_da7219_def", .driver_data = (kernel_ulong_t)(SOF_DA7219_CML_BOARD | -- cgit v1.2.3 From f46b768b7281e4ef784d06788be2f941c13eddde Mon Sep 17 00:00:00 2001 From: Brent Lu Date: Fri, 26 Apr 2024 10:25:18 -0500 Subject: ASoC: Intel: sof_da7219: support MAX98357A on glk boards For glk boards, MAX98357A speaker amplifier is supported by machine driver bxt_da7219_max98357a with sound card name glkda7219max. Use same name for backward compatibility with existing devices on market. Reviewed-by: Bard Liao Signed-off-by: Brent Lu Signed-off-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20240426152529.38345-13-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/intel/boards/sof_da7219.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/sound/soc/intel/boards/sof_da7219.c b/sound/soc/intel/boards/sof_da7219.c index cc5e99b21456..d7b605896f89 100644 --- a/sound/soc/intel/boards/sof_da7219.c +++ b/sound/soc/intel/boards/sof_da7219.c @@ -348,6 +348,20 @@ static int audio_probe(struct platform_device *pdev) /* overwrite the DAI link order for GLK boards */ ctx->link_order_overwrite = GLK_LINK_ORDER; + + /* backward-compatible with existing devices */ + switch (ctx->amp_type) { + case CODEC_MAX98357A: + card_name = devm_kstrdup(&pdev->dev, "glkda7219max", + GFP_KERNEL); + if (!card_name) + return -ENOMEM; + + card_da7219.name = card_name; + break; + default: + break; + } } else if (board_quirk & SOF_DA7219_CML_BOARD) { /* overwrite the DAI link order for CML boards */ ctx->link_order_overwrite = CML_LINK_ORDER; -- cgit v1.2.3 From 8d6114b81d72c522f1ad55cd84ed37699d58c840 Mon Sep 17 00:00:00 2001 From: Brent Lu Date: Fri, 26 Apr 2024 10:25:19 -0500 Subject: ASoC: Intel: bxt_da7219_max98357a: remove glk support Remove glk platform support and use sof_da7219 machine driver instead for existing glk boards with MAX98357A speaker amplifier. Reviewed-by: Bard Liao Signed-off-by: Brent Lu Signed-off-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20240426152529.38345-14-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/intel/boards/Kconfig | 14 +++----- sound/soc/intel/boards/Makefile | 2 +- sound/soc/intel/boards/bxt_da7219_max98357a.c | 44 ----------------------- sound/soc/intel/common/soc-acpi-intel-glk-match.c | 2 +- 4 files changed, 6 insertions(+), 56 deletions(-) diff --git a/sound/soc/intel/boards/Kconfig b/sound/soc/intel/boards/Kconfig index 134512a7d3b8..d48b196817b4 100644 --- a/sound/soc/intel/boards/Kconfig +++ b/sound/soc/intel/boards/Kconfig @@ -305,10 +305,6 @@ config SND_SOC_INTEL_DA7219_MAX98357A_GENERIC select SND_SOC_HDAC_HDMI select SND_SOC_INTEL_HDA_DSP_COMMON -config SND_SOC_INTEL_BXT_DA7219_MAX98357A_COMMON - tristate - select SND_SOC_INTEL_DA7219_MAX98357A_GENERIC - if SND_SOC_INTEL_APL config SND_SOC_INTEL_BXT_DA7219_MAX98357A_MACH @@ -316,7 +312,7 @@ config SND_SOC_INTEL_BXT_DA7219_MAX98357A_MACH depends on I2C && ACPI depends on MFD_INTEL_LPSS || COMPILE_TEST depends on SND_HDA_CODEC_HDMI - select SND_SOC_INTEL_BXT_DA7219_MAX98357A_COMMON + select SND_SOC_INTEL_DA7219_MAX98357A_GENERIC help This adds support for ASoC machine driver for Broxton-P platforms with DA7219 + MAX98357A I2S audio codec. @@ -432,13 +428,11 @@ if SND_SOC_SOF_GEMINILAKE config SND_SOC_INTEL_GLK_DA7219_MAX98357A_MACH tristate "GLK with DA7219 and MAX98357A in I2S Mode" - depends on I2C && ACPI - depends on MFD_INTEL_LPSS || COMPILE_TEST - depends on SND_HDA_CODEC_HDMI && SND_SOC_SOF_HDA_AUDIO_CODEC - select SND_SOC_INTEL_BXT_DA7219_MAX98357A_COMMON + imply SND_SOC_INTEL_SOF_DA7219_MACH help This adds support for ASoC machine driver for Geminilake platforms - with DA7219 + MAX98357A I2S audio codec. + with DA7219 + MAX98357A I2S audio codec. This option is deprecated + and please use SND_SOC_INTEL_SOF_DA7219_MACH instead. Say Y or m if you have such a device. This is a recommended option. If unsure select "N". diff --git a/sound/soc/intel/boards/Makefile b/sound/soc/intel/boards/Makefile index 119413c262de..e4bd5689eb1c 100644 --- a/sound/soc/intel/boards/Makefile +++ b/sound/soc/intel/boards/Makefile @@ -51,7 +51,7 @@ obj-$(CONFIG_SND_SOC_INTEL_SOF_ES8336_MACH) += snd-soc-sof_es8336.o obj-$(CONFIG_SND_SOC_INTEL_SOF_NAU8825_MACH) += snd-soc-sof_nau8825.o obj-$(CONFIG_SND_SOC_INTEL_SOF_DA7219_MACH) += snd-soc-sof_da7219.o obj-$(CONFIG_SND_SOC_INTEL_HASWELL_MACH) += snd-soc-hsw-rt5640.o -obj-$(CONFIG_SND_SOC_INTEL_BXT_DA7219_MAX98357A_COMMON) += snd-soc-sst-bxt-da7219_max98357a.o +obj-$(CONFIG_SND_SOC_INTEL_BXT_DA7219_MAX98357A_MACH) += snd-soc-sst-bxt-da7219_max98357a.o obj-$(CONFIG_SND_SOC_INTEL_BXT_RT298_MACH) += snd-soc-sst-bxt-rt298.o obj-$(CONFIG_SND_SOC_INTEL_SOF_PCM512x_MACH) += snd-soc-sst-sof-pcm512x.o obj-$(CONFIG_SND_SOC_INTEL_SOF_WM8804_MACH) += snd-soc-sst-sof-wm8804.o diff --git a/sound/soc/intel/boards/bxt_da7219_max98357a.c b/sound/soc/intel/boards/bxt_da7219_max98357a.c index 45fe1d7b8865..57e75f87bea6 100644 --- a/sound/soc/intel/boards/bxt_da7219_max98357a.c +++ b/sound/soc/intel/boards/bxt_da7219_max98357a.c @@ -134,9 +134,7 @@ static const struct snd_soc_dapm_route audio_map[] = { /* speaker */ {"Spk", NULL, "Speaker"}, -}; -static const struct snd_soc_dapm_route broxton_map[] = { {"HiFi Playback", NULL, "ssp5 Tx"}, {"ssp5 Tx", NULL, "codec0_out"}, @@ -147,17 +145,6 @@ static const struct snd_soc_dapm_route broxton_map[] = { {"ssp1 Rx", NULL, "Capture"}, }; -static const struct snd_soc_dapm_route gemini_map[] = { - {"HiFi Playback", NULL, "ssp1 Tx"}, - {"ssp1 Tx", NULL, "codec0_out"}, - - {"Playback", NULL, "ssp2 Tx"}, - {"ssp2 Tx", NULL, "codec1_out"}, - - {"codec0_in", NULL, "ssp2 Rx"}, - {"ssp2 Rx", NULL, "Capture"}, -}; - static struct snd_soc_jack_pin jack_pins[] = { { .pin = "Headphone Jack", @@ -626,13 +613,6 @@ static int bxt_card_late_probe(struct snd_soc_card *card) int err, i = 0; char jack_name[NAME_SIZE]; - if (soc_intel_is_glk()) - snd_soc_dapm_add_routes(&card->dapm, gemini_map, - ARRAY_SIZE(gemini_map)); - else - snd_soc_dapm_add_routes(&card->dapm, broxton_map, - ARRAY_SIZE(broxton_map)); - if (list_empty(&ctx->hdmi_pcm_list)) return -EINVAL; @@ -696,29 +676,6 @@ static int broxton_audio_probe(struct platform_device *pdev) broxton_audio_card.dev = &pdev->dev; snd_soc_card_set_drvdata(&broxton_audio_card, ctx); - if (soc_intel_is_glk()) { - unsigned int i; - - broxton_audio_card.name = "glkda7219max"; - /* Fixup the SSP entries for geminilake */ - for (i = 0; i < ARRAY_SIZE(broxton_dais); i++) { - if (!broxton_dais[i].codecs->dai_name) - continue; - - /* MAXIM_CODEC is connected to SSP1. */ - if (!strcmp(broxton_dais[i].codecs->dai_name, - BXT_MAXIM_CODEC_DAI)) { - broxton_dais[i].name = "SSP1-Codec"; - broxton_dais[i].cpus->dai_name = "SSP1 Pin"; - } - /* DIALOG_CODE is connected to SSP2 */ - else if (!strcmp(broxton_dais[i].codecs->dai_name, - BXT_DIALOG_CODEC_DAI)) { - broxton_dais[i].name = "SSP2-Codec"; - broxton_dais[i].cpus->dai_name = "SSP2 Pin"; - } - } - } /* override platform name, if required */ mach = pdev->dev.platform_data; @@ -736,7 +693,6 @@ static int broxton_audio_probe(struct platform_device *pdev) static const struct platform_device_id bxt_board_ids[] = { { .name = "bxt_da7219_mx98357a" }, - { .name = "glk_da7219_mx98357a" }, { } }; MODULE_DEVICE_TABLE(platform, bxt_board_ids); diff --git a/sound/soc/intel/common/soc-acpi-intel-glk-match.c b/sound/soc/intel/common/soc-acpi-intel-glk-match.c index 8911c90bbaf6..1d30991afdc8 100644 --- a/sound/soc/intel/common/soc-acpi-intel-glk-match.c +++ b/sound/soc/intel/common/soc-acpi-intel-glk-match.c @@ -33,7 +33,7 @@ struct snd_soc_acpi_mach snd_soc_acpi_intel_glk_machines[] = { }, { .id = "DLGS7219", - .drv_name = "glk_da7219_mx98357a", + .drv_name = "glk_da7219_def", .fw_filename = "intel/dsp_fw_glk.bin", .machine_quirk = snd_soc_acpi_codec_list, .quirk_data = &glk_codecs, -- cgit v1.2.3 From 44567d3d62dfe9df514299a98429a59129e0a2d0 Mon Sep 17 00:00:00 2001 From: Brent Lu Date: Fri, 26 Apr 2024 10:25:20 -0500 Subject: ASoC: Intel: sof_rt5682: add glk_rt5682_def for glk boards Add the board config glk_rt5682_def to rt5682 machine driver for all glk boards using default SSP port allocation (headphone codec on SSP2, speaker amplifiers on SSP1). Reviewed-by: Bard Liao Signed-off-by: Brent Lu Signed-off-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20240426152529.38345-15-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/intel/boards/sof_rt5682.c | 48 +++++++++++++++++++++++++++---------- 1 file changed, 36 insertions(+), 12 deletions(-) diff --git a/sound/soc/intel/boards/sof_rt5682.c b/sound/soc/intel/boards/sof_rt5682.c index 1e70ce469650..80ecf31c936a 100644 --- a/sound/soc/intel/boards/sof_rt5682.c +++ b/sound/soc/intel/boards/sof_rt5682.c @@ -635,6 +635,14 @@ sof_card_dai_links_create(struct device *dev, struct snd_soc_card *card, return 0; } +#define GLK_LINK_ORDER SOF_LINK_ORDER(SOF_LINK_AMP, \ + SOF_LINK_CODEC, \ + SOF_LINK_DMIC01, \ + SOF_LINK_IDISP_HDMI, \ + SOF_LINK_NONE, \ + SOF_LINK_NONE, \ + SOF_LINK_NONE) + static int sof_audio_probe(struct platform_device *pdev) { struct snd_soc_acpi_mach *mach = pdev->dev.platform_data; @@ -676,24 +684,34 @@ static int sof_audio_probe(struct platform_device *pdev) ctx->amp_type = CODEC_RT5650; } - if (ctx->amp_type == CODEC_RT1011 && soc_intel_is_cml()) { - /* backward-compatible with existing cml devices */ - card_name = devm_kstrdup(&pdev->dev, "cml_rt1011_rt5682", - GFP_KERNEL); - if (!card_name) - return -ENOMEM; - - sof_audio_card_rt5682.name = card_name; - } + if (mach->mach_params.codec_mask & IDISP_CODEC_MASK) + ctx->hdmi.idisp_codec = true; if (is_legacy_cpu) { ctx->rt5682.is_legacy_cpu = true; ctx->dmic_be_num = 0; /* HDMI is not supported by SOF on Baytrail/CherryTrail */ ctx->hdmi_num = 0; - } else { - if (mach->mach_params.codec_mask & IDISP_CODEC_MASK) - ctx->hdmi.idisp_codec = true; + } else if (soc_intel_is_glk()) { + /* dmic16k not support */ + ctx->dmic_be_num = 1; + + /* overwrite the DAI link order for GLK boards */ + ctx->link_order_overwrite = GLK_LINK_ORDER; + } else if (soc_intel_is_cml()) { + /* backward-compatible with existing devices */ + switch (ctx->amp_type) { + case CODEC_RT1011: + card_name = devm_kstrdup(&pdev->dev, "cml_rt1011_rt5682", + GFP_KERNEL); + if (!card_name) + return -ENOMEM; + + sof_audio_card_rt5682.name = card_name; + break; + default: + break; + } } /* need to get main clock from pmc */ @@ -768,6 +786,12 @@ static const struct platform_device_id board_ids[] = { { .name = "sof_rt5682", }, + { + .name = "glk_rt5682_def", + .driver_data = (kernel_ulong_t)(SOF_RT5682_MCLK_EN | + SOF_SSP_PORT_CODEC(2) | + SOF_SSP_PORT_AMP(1)), + }, { .name = "cml_rt5682_def", .driver_data = (kernel_ulong_t)(SOF_RT5682_MCLK_EN | -- cgit v1.2.3 From 5498a4edbf314532b7138aabe705faa34fb5df8d Mon Sep 17 00:00:00 2001 From: Brent Lu Date: Fri, 26 Apr 2024 10:25:21 -0500 Subject: ASoC: Intel: sof_rt5682: support MAX98357A on glk boards For glk boards, MAX98357A speaker amplifier is supported by machine driver glk_rt5682_mx98357a with sound card name glkrt5682max. Use same name for backward compatibility with existing devices on market. Reviewed-by: Bard Liao Signed-off-by: Brent Lu Signed-off-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20240426152529.38345-16-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/intel/boards/sof_rt5682.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/sound/soc/intel/boards/sof_rt5682.c b/sound/soc/intel/boards/sof_rt5682.c index 80ecf31c936a..efca7604040e 100644 --- a/sound/soc/intel/boards/sof_rt5682.c +++ b/sound/soc/intel/boards/sof_rt5682.c @@ -698,6 +698,20 @@ static int sof_audio_probe(struct platform_device *pdev) /* overwrite the DAI link order for GLK boards */ ctx->link_order_overwrite = GLK_LINK_ORDER; + + /* backward-compatible with existing devices */ + switch (ctx->amp_type) { + case CODEC_MAX98357A: + card_name = devm_kstrdup(&pdev->dev, "glkrt5682max", + GFP_KERNEL); + if (!card_name) + return -ENOMEM; + + sof_audio_card_rt5682.name = card_name; + break; + default: + break; + } } else if (soc_intel_is_cml()) { /* backward-compatible with existing devices */ switch (ctx->amp_type) { -- cgit v1.2.3 From 0cb6a8134c1cb59d8f41d84968c2e20cfbd7f6cc Mon Sep 17 00:00:00 2001 From: Brent Lu Date: Fri, 26 Apr 2024 10:25:22 -0500 Subject: ASoC: Intel: glk_rt5682_max98357a: delete driver Delete this driver and use sof_rt5682 machine driver instead. Reviewed-by: Bard Liao Signed-off-by: Brent Lu Signed-off-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20240426152529.38345-17-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/intel/boards/Kconfig | 13 +- sound/soc/intel/boards/Makefile | 2 - sound/soc/intel/boards/glk_rt5682_max98357a.c | 693 ---------------------- sound/soc/intel/common/soc-acpi-intel-glk-match.c | 2 +- 4 files changed, 4 insertions(+), 706 deletions(-) delete mode 100644 sound/soc/intel/boards/glk_rt5682_max98357a.c diff --git a/sound/soc/intel/boards/Kconfig b/sound/soc/intel/boards/Kconfig index d48b196817b4..e7ea6fe3dcd1 100644 --- a/sound/soc/intel/boards/Kconfig +++ b/sound/soc/intel/boards/Kconfig @@ -438,18 +438,11 @@ config SND_SOC_INTEL_GLK_DA7219_MAX98357A_MACH config SND_SOC_INTEL_GLK_RT5682_MAX98357A_MACH tristate "GLK with RT5682 and MAX98357A in I2S Mode" - depends on I2C && ACPI - depends on MFD_INTEL_LPSS || COMPILE_TEST - depends on SND_HDA_CODEC_HDMI && SND_SOC_SOF_HDA_AUDIO_CODEC - select SND_SOC_RT5682_I2C - select SND_SOC_RT5682S - select SND_SOC_MAX98357A - select SND_SOC_DMIC - select SND_SOC_HDAC_HDMI - select SND_SOC_INTEL_HDA_DSP_COMMON + imply SND_SOC_INTEL_SOF_RT5682_MACH help This adds support for ASoC machine driver for Geminilake platforms - with RT5682 + MAX98357A I2S audio codec. + with RT5682 + MAX98357A I2S audio codec. This option is deprecated + and please use SND_SOC_INTEL_SOF_RT5682_MACH instead. Say Y if you have such a device. If unsure select "N". diff --git a/sound/soc/intel/boards/Makefile b/sound/soc/intel/boards/Makefile index e4bd5689eb1c..949e06490858 100644 --- a/sound/soc/intel/boards/Makefile +++ b/sound/soc/intel/boards/Makefile @@ -7,7 +7,6 @@ snd-soc-sst-bxt-da7219_max98357a-objs := bxt_da7219_max98357a.o snd-soc-sst-bxt-rt298-objs := bxt_rt298.o snd-soc-sst-sof-pcm512x-objs := sof_pcm512x.o snd-soc-sst-sof-wm8804-objs := sof_wm8804.o -snd-soc-sst-glk-rt5682_max98357a-objs := glk_rt5682_max98357a.o snd-soc-sst-bytcr-rt5640-objs := bytcr_rt5640.o snd-soc-sst-bytcr-rt5651-objs := bytcr_rt5651.o snd-soc-sst-bytcr-wm5102-objs := bytcr_wm5102.o @@ -55,7 +54,6 @@ obj-$(CONFIG_SND_SOC_INTEL_BXT_DA7219_MAX98357A_MACH) += snd-soc-sst-bxt-da7219_ obj-$(CONFIG_SND_SOC_INTEL_BXT_RT298_MACH) += snd-soc-sst-bxt-rt298.o obj-$(CONFIG_SND_SOC_INTEL_SOF_PCM512x_MACH) += snd-soc-sst-sof-pcm512x.o obj-$(CONFIG_SND_SOC_INTEL_SOF_WM8804_MACH) += snd-soc-sst-sof-wm8804.o -obj-$(CONFIG_SND_SOC_INTEL_GLK_RT5682_MAX98357A_MACH) += snd-soc-sst-glk-rt5682_max98357a.o obj-$(CONFIG_SND_SOC_INTEL_BROADWELL_MACH) += snd-soc-bdw-rt286.o obj-$(CONFIG_SND_SOC_INTEL_BDW_RT5650_MACH) += snd-soc-sst-bdw-rt5650-mach.o obj-$(CONFIG_SND_SOC_INTEL_BDW_RT5677_MACH) += snd-soc-sst-bdw-rt5677-mach.o diff --git a/sound/soc/intel/boards/glk_rt5682_max98357a.c b/sound/soc/intel/boards/glk_rt5682_max98357a.c deleted file mode 100644 index 4098b2d32f9b..000000000000 --- a/sound/soc/intel/boards/glk_rt5682_max98357a.c +++ /dev/null @@ -1,693 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -// Copyright(c) 2018 Intel Corporation. - -/* - * Intel Geminilake I2S Machine Driver with MAX98357A & RT5682 Codecs - * - * Modified from: - * Intel Apollolake I2S Machine driver - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "../../codecs/rt5682.h" -#include "../../codecs/rt5682s.h" -#include "../../codecs/hdac_hdmi.h" -#include "hda_dsp_common.h" - -/* The platform clock outputs 19.2Mhz clock to codec as I2S MCLK */ -#define GLK_PLAT_CLK_FREQ 19200000 -#define RT5682_PLL_FREQ (48000 * 512) -#define RT5682_DAI_NAME "rt5682-aif1" -#define RT5682S_DAI_NAME "rt5682s-aif1" -#define GLK_MAXIM_CODEC_DAI "HiFi" -#define RT5682_DEV0_NAME "i2c-10EC5682:00" -#define RT5682S_DEV0_NAME "i2c-RTL5682:00" -#define MAXIM_DEV0_NAME "MX98357A:00" -#define DUAL_CHANNEL 2 -#define QUAD_CHANNEL 4 -#define NAME_SIZE 32 - -static struct snd_soc_jack geminilake_hdmi[3]; - -struct glk_hdmi_pcm { - struct list_head head; - struct snd_soc_dai *codec_dai; - int device; -}; - -struct glk_card_private { - struct snd_soc_jack geminilake_headset; - struct list_head hdmi_pcm_list; - bool common_hdmi_codec_drv; - int is_rt5682s; -}; - -enum { - GLK_DPCM_AUDIO_PB = 0, - GLK_DPCM_AUDIO_CP, - GLK_DPCM_AUDIO_HS_PB, - GLK_DPCM_AUDIO_ECHO_REF_CP, - GLK_DPCM_AUDIO_REF_CP, - GLK_DPCM_AUDIO_DMIC_CP, - GLK_DPCM_AUDIO_HDMI1_PB, - GLK_DPCM_AUDIO_HDMI2_PB, - GLK_DPCM_AUDIO_HDMI3_PB, -}; - -static const struct snd_kcontrol_new geminilake_controls[] = { - SOC_DAPM_PIN_SWITCH("Headphone Jack"), - SOC_DAPM_PIN_SWITCH("Headset Mic"), - SOC_DAPM_PIN_SWITCH("Spk"), -}; - -static const struct snd_soc_dapm_widget geminilake_widgets[] = { - SND_SOC_DAPM_HP("Headphone Jack", NULL), - SND_SOC_DAPM_MIC("Headset Mic", NULL), - SND_SOC_DAPM_SPK("Spk", NULL), - SND_SOC_DAPM_MIC("SoC DMIC", NULL), - SND_SOC_DAPM_SPK("HDMI1", NULL), - SND_SOC_DAPM_SPK("HDMI2", NULL), - SND_SOC_DAPM_SPK("HDMI3", NULL), -}; - -static struct snd_soc_jack_pin jack_pins[] = { - { - .pin = "Headphone Jack", - .mask = SND_JACK_HEADPHONE, - }, - { - .pin = "Headset Mic", - .mask = SND_JACK_MICROPHONE, - }, -}; - -static const struct snd_soc_dapm_route geminilake_map[] = { - /* HP jack connectors - unknown if we have jack detection */ - { "Headphone Jack", NULL, "HPOL" }, - { "Headphone Jack", NULL, "HPOR" }, - - /* speaker */ - { "Spk", NULL, "Speaker" }, - - /* other jacks */ - { "IN1P", NULL, "Headset Mic" }, - - /* digital mics */ - { "DMic", NULL, "SoC DMIC" }, - - /* CODEC BE connections */ - { "HiFi Playback", NULL, "ssp1 Tx" }, - { "ssp1 Tx", NULL, "codec0_out" }, - - { "AIF1 Playback", NULL, "ssp2 Tx" }, - { "ssp2 Tx", NULL, "codec1_out" }, - - { "codec0_in", NULL, "ssp2 Rx" }, - { "ssp2 Rx", NULL, "AIF1 Capture" }, - - { "HDMI1", NULL, "hif5-0 Output" }, - { "HDMI2", NULL, "hif6-0 Output" }, - { "HDMI2", NULL, "hif7-0 Output" }, - - { "hifi3", NULL, "iDisp3 Tx" }, - { "iDisp3 Tx", NULL, "iDisp3_out" }, - { "hifi2", NULL, "iDisp2 Tx" }, - { "iDisp2 Tx", NULL, "iDisp2_out" }, - { "hifi1", NULL, "iDisp1 Tx" }, - { "iDisp1 Tx", NULL, "iDisp1_out" }, - - /* DMIC */ - { "dmic01_hifi", NULL, "DMIC01 Rx" }, - { "DMIC01 Rx", NULL, "DMIC AIF" }, -}; - -static int geminilake_ssp_fixup(struct snd_soc_pcm_runtime *rtd, - struct snd_pcm_hw_params *params) -{ - struct snd_interval *rate = hw_param_interval(params, - SNDRV_PCM_HW_PARAM_RATE); - struct snd_interval *chan = hw_param_interval(params, - SNDRV_PCM_HW_PARAM_CHANNELS); - struct snd_mask *fmt = hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT); - - /* The ADSP will convert the FE rate to 48k, stereo */ - rate->min = rate->max = 48000; - chan->min = chan->max = DUAL_CHANNEL; - - /* set SSP to 24 bit */ - snd_mask_none(fmt); - snd_mask_set_format(fmt, SNDRV_PCM_FORMAT_S24_LE); - - return 0; -} - -static int geminilake_rt5682_codec_init(struct snd_soc_pcm_runtime *rtd) -{ - struct glk_card_private *ctx = snd_soc_card_get_drvdata(rtd->card); - struct snd_soc_component *component = snd_soc_rtd_to_codec(rtd, 0)->component; - struct snd_soc_dai *codec_dai = snd_soc_rtd_to_codec(rtd, 0); - struct snd_soc_jack *jack; - int pll_id, pll_source, clk_id, ret; - - if (ctx->is_rt5682s) { - pll_id = RT5682S_PLL2; - pll_source = RT5682S_PLL_S_MCLK; - clk_id = RT5682S_SCLK_S_PLL2; - } else { - pll_id = RT5682_PLL1; - pll_source = RT5682_PLL1_S_MCLK; - clk_id = RT5682_SCLK_S_PLL1; - } - - ret = snd_soc_dai_set_pll(codec_dai, pll_id, pll_source, - GLK_PLAT_CLK_FREQ, RT5682_PLL_FREQ); - if (ret < 0) { - dev_err(rtd->dev, "can't set codec pll: %d\n", ret); - return ret; - } - - /* Configure sysclk for codec */ - ret = snd_soc_dai_set_sysclk(codec_dai, clk_id, - RT5682_PLL_FREQ, SND_SOC_CLOCK_IN); - if (ret < 0) - dev_err(rtd->dev, "snd_soc_dai_set_sysclk err = %d\n", ret); - - /* - * Headset buttons map to the google Reference headset. - * These can be configured by userspace. - */ - ret = snd_soc_card_jack_new_pins(rtd->card, "Headset Jack", - SND_JACK_HEADSET | SND_JACK_BTN_0 | SND_JACK_BTN_1 | - SND_JACK_BTN_2 | SND_JACK_BTN_3 | SND_JACK_LINEOUT, - &ctx->geminilake_headset, - jack_pins, - ARRAY_SIZE(jack_pins)); - if (ret) { - dev_err(rtd->dev, "Headset Jack creation failed: %d\n", ret); - return ret; - } - - jack = &ctx->geminilake_headset; - - snd_jack_set_key(jack->jack, SND_JACK_BTN_0, KEY_PLAYPAUSE); - snd_jack_set_key(jack->jack, SND_JACK_BTN_1, KEY_VOICECOMMAND); - snd_jack_set_key(jack->jack, SND_JACK_BTN_2, KEY_VOLUMEUP); - snd_jack_set_key(jack->jack, SND_JACK_BTN_3, KEY_VOLUMEDOWN); - - ret = snd_soc_component_set_jack(component, jack, NULL); - - if (ret) { - dev_err(rtd->dev, "Headset Jack call-back failed: %d\n", ret); - return ret; - } - - return ret; -}; - -static int geminilake_rt5682_hw_params(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *params) -{ - struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream); - struct snd_soc_dai *codec_dai = snd_soc_rtd_to_codec(rtd, 0); - int ret; - - /* Set valid bitmask & configuration for I2S in 24 bit */ - ret = snd_soc_dai_set_tdm_slot(codec_dai, 0x0, 0x0, 2, 24); - if (ret < 0) { - dev_err(rtd->dev, "set TDM slot err:%d\n", ret); - return ret; - } - - return ret; -} - -static struct snd_soc_ops geminilake_rt5682_ops = { - .hw_params = geminilake_rt5682_hw_params, -}; - -static int geminilake_hdmi_init(struct snd_soc_pcm_runtime *rtd) -{ - struct glk_card_private *ctx = snd_soc_card_get_drvdata(rtd->card); - struct snd_soc_dai *dai = snd_soc_rtd_to_codec(rtd, 0); - struct glk_hdmi_pcm *pcm; - - pcm = devm_kzalloc(rtd->card->dev, sizeof(*pcm), GFP_KERNEL); - if (!pcm) - return -ENOMEM; - - pcm->device = GLK_DPCM_AUDIO_HDMI1_PB + dai->id; - pcm->codec_dai = dai; - - list_add_tail(&pcm->head, &ctx->hdmi_pcm_list); - - return 0; -} - -static int geminilake_rt5682_fe_init(struct snd_soc_pcm_runtime *rtd) -{ - struct snd_soc_component *component = snd_soc_rtd_to_cpu(rtd, 0)->component; - struct snd_soc_dapm_context *dapm; - int ret; - - dapm = snd_soc_component_get_dapm(component); - ret = snd_soc_dapm_ignore_suspend(dapm, "Reference Capture"); - if (ret) { - dev_err(rtd->dev, "Ref Cap ignore suspend failed %d\n", ret); - return ret; - } - - return ret; -} - -static const unsigned int rates[] = { - 48000, -}; - -static const struct snd_pcm_hw_constraint_list constraints_rates = { - .count = ARRAY_SIZE(rates), - .list = rates, - .mask = 0, -}; - -static unsigned int channels_quad[] = { - QUAD_CHANNEL, -}; - -static struct snd_pcm_hw_constraint_list constraints_channels_quad = { - .count = ARRAY_SIZE(channels_quad), - .list = channels_quad, - .mask = 0, -}; - -static int geminilake_dmic_fixup(struct snd_soc_pcm_runtime *rtd, - struct snd_pcm_hw_params *params) -{ - struct snd_interval *chan = hw_param_interval(params, - SNDRV_PCM_HW_PARAM_CHANNELS); - - /* - * set BE channel constraint as user FE channels - */ - chan->min = chan->max = 4; - - return 0; -} - -static int geminilake_dmic_startup(struct snd_pcm_substream *substream) -{ - struct snd_pcm_runtime *runtime = substream->runtime; - - runtime->hw.channels_min = runtime->hw.channels_max = QUAD_CHANNEL; - snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS, - &constraints_channels_quad); - - return snd_pcm_hw_constraint_list(substream->runtime, 0, - SNDRV_PCM_HW_PARAM_RATE, &constraints_rates); -} - -static const struct snd_soc_ops geminilake_dmic_ops = { - .startup = geminilake_dmic_startup, -}; - -static const unsigned int rates_16000[] = { - 16000, -}; - -static const struct snd_pcm_hw_constraint_list constraints_16000 = { - .count = ARRAY_SIZE(rates_16000), - .list = rates_16000, -}; - -static int geminilake_refcap_startup(struct snd_pcm_substream *substream) -{ - return snd_pcm_hw_constraint_list(substream->runtime, 0, - SNDRV_PCM_HW_PARAM_RATE, - &constraints_16000); -}; - -static const struct snd_soc_ops geminilake_refcap_ops = { - .startup = geminilake_refcap_startup, -}; - -SND_SOC_DAILINK_DEF(dummy, - DAILINK_COMP_ARRAY(COMP_DUMMY())); - -SND_SOC_DAILINK_DEF(system, - DAILINK_COMP_ARRAY(COMP_CPU("System Pin"))); - -SND_SOC_DAILINK_DEF(system2, - DAILINK_COMP_ARRAY(COMP_CPU("System Pin2"))); - -SND_SOC_DAILINK_DEF(echoref, - DAILINK_COMP_ARRAY(COMP_CPU("Echoref Pin"))); - -SND_SOC_DAILINK_DEF(reference, - DAILINK_COMP_ARRAY(COMP_CPU("Reference Pin"))); - -SND_SOC_DAILINK_DEF(dmic, - DAILINK_COMP_ARRAY(COMP_CPU("DMIC Pin"))); - -SND_SOC_DAILINK_DEF(hdmi1, - DAILINK_COMP_ARRAY(COMP_CPU("HDMI1 Pin"))); - -SND_SOC_DAILINK_DEF(hdmi2, - DAILINK_COMP_ARRAY(COMP_CPU("HDMI2 Pin"))); - -SND_SOC_DAILINK_DEF(hdmi3, - DAILINK_COMP_ARRAY(COMP_CPU("HDMI3 Pin"))); - -SND_SOC_DAILINK_DEF(ssp1_pin, - DAILINK_COMP_ARRAY(COMP_CPU("SSP1 Pin"))); -SND_SOC_DAILINK_DEF(ssp1_codec, - DAILINK_COMP_ARRAY(COMP_CODEC(MAXIM_DEV0_NAME, - GLK_MAXIM_CODEC_DAI))); - -SND_SOC_DAILINK_DEF(ssp2_pin, - DAILINK_COMP_ARRAY(COMP_CPU("SSP2 Pin"))); -SND_SOC_DAILINK_DEF(ssp2_codec_5682, - DAILINK_COMP_ARRAY(COMP_CODEC(RT5682_DEV0_NAME, - RT5682_DAI_NAME))); -SND_SOC_DAILINK_DEF(ssp2_codec_5682s, - DAILINK_COMP_ARRAY(COMP_CODEC(RT5682S_DEV0_NAME, - RT5682S_DAI_NAME))); - -SND_SOC_DAILINK_DEF(dmic_pin, - DAILINK_COMP_ARRAY(COMP_CPU("DMIC01 Pin"))); -SND_SOC_DAILINK_DEF(dmic_codec, - DAILINK_COMP_ARRAY(COMP_CODEC("dmic-codec", "dmic-hifi"))); - -SND_SOC_DAILINK_DEF(idisp1_pin, - DAILINK_COMP_ARRAY(COMP_CPU("iDisp1 Pin"))); -SND_SOC_DAILINK_DEF(idisp1_codec, - DAILINK_COMP_ARRAY(COMP_CODEC("ehdaudio0D2", "intel-hdmi-hifi1"))); - -SND_SOC_DAILINK_DEF(idisp2_pin, - DAILINK_COMP_ARRAY(COMP_CPU("iDisp2 Pin"))); -SND_SOC_DAILINK_DEF(idisp2_codec, - DAILINK_COMP_ARRAY(COMP_CODEC("ehdaudio0D2", "intel-hdmi-hifi2"))); - -SND_SOC_DAILINK_DEF(idisp3_pin, - DAILINK_COMP_ARRAY(COMP_CPU("iDisp3 Pin"))); -SND_SOC_DAILINK_DEF(idisp3_codec, - DAILINK_COMP_ARRAY(COMP_CODEC("ehdaudio0D2", "intel-hdmi-hifi3"))); - -SND_SOC_DAILINK_DEF(platform, - DAILINK_COMP_ARRAY(COMP_PLATFORM("0000:00:0e.0"))); - -/* geminilake digital audio interface glue - connects codec <--> CPU */ -static struct snd_soc_dai_link geminilake_dais[] = { - /* Front End DAI links */ - [GLK_DPCM_AUDIO_PB] = { - .name = "Glk Audio Port", - .stream_name = "Audio", - .dynamic = 1, - .nonatomic = 1, - .init = geminilake_rt5682_fe_init, - .trigger = { - SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST}, - .dpcm_playback = 1, - SND_SOC_DAILINK_REG(system, dummy, platform), - }, - [GLK_DPCM_AUDIO_CP] = { - .name = "Glk Audio Capture Port", - .stream_name = "Audio Record", - .dynamic = 1, - .nonatomic = 1, - .trigger = { - SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST}, - .dpcm_capture = 1, - SND_SOC_DAILINK_REG(system, dummy, platform), - }, - [GLK_DPCM_AUDIO_HS_PB] = { - .name = "Glk Audio Headset Playback", - .stream_name = "Headset Audio", - .dpcm_playback = 1, - .nonatomic = 1, - .dynamic = 1, - SND_SOC_DAILINK_REG(system2, dummy, platform), - }, - [GLK_DPCM_AUDIO_ECHO_REF_CP] = { - .name = "Glk Audio Echo Reference cap", - .stream_name = "Echoreference Capture", - .init = NULL, - .dpcm_capture = 1, - .nonatomic = 1, - .dynamic = 1, - SND_SOC_DAILINK_REG(echoref, dummy, platform), - }, - [GLK_DPCM_AUDIO_REF_CP] = { - .name = "Glk Audio Reference cap", - .stream_name = "Refcap", - .init = NULL, - .dpcm_capture = 1, - .nonatomic = 1, - .dynamic = 1, - .ops = &geminilake_refcap_ops, - SND_SOC_DAILINK_REG(reference, dummy, platform), - }, - [GLK_DPCM_AUDIO_DMIC_CP] = { - .name = "Glk Audio DMIC cap", - .stream_name = "dmiccap", - .init = NULL, - .dpcm_capture = 1, - .nonatomic = 1, - .dynamic = 1, - .ops = &geminilake_dmic_ops, - SND_SOC_DAILINK_REG(dmic, dummy, platform), - }, - [GLK_DPCM_AUDIO_HDMI1_PB] = { - .name = "Glk HDMI Port1", - .stream_name = "Hdmi1", - .dpcm_playback = 1, - .init = NULL, - .trigger = { - SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST}, - .nonatomic = 1, - .dynamic = 1, - SND_SOC_DAILINK_REG(hdmi1, dummy, platform), - }, - [GLK_DPCM_AUDIO_HDMI2_PB] = { - .name = "Glk HDMI Port2", - .stream_name = "Hdmi2", - .dpcm_playback = 1, - .init = NULL, - .trigger = { - SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST}, - .nonatomic = 1, - .dynamic = 1, - SND_SOC_DAILINK_REG(hdmi2, dummy, platform), - }, - [GLK_DPCM_AUDIO_HDMI3_PB] = { - .name = "Glk HDMI Port3", - .stream_name = "Hdmi3", - .trigger = { - SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST}, - .dpcm_playback = 1, - .init = NULL, - .nonatomic = 1, - .dynamic = 1, - SND_SOC_DAILINK_REG(hdmi3, dummy, platform), - }, - /* Back End DAI links */ - { - /* SSP1 - Codec */ - .name = "SSP1-Codec", - .id = 0, - .no_pcm = 1, - .dai_fmt = SND_SOC_DAIFMT_I2S | - SND_SOC_DAIFMT_NB_NF | - SND_SOC_DAIFMT_CBC_CFC, - .ignore_pmdown_time = 1, - .be_hw_params_fixup = geminilake_ssp_fixup, - .dpcm_playback = 1, - SND_SOC_DAILINK_REG(ssp1_pin, ssp1_codec, platform), - }, - { - /* SSP2 - Codec */ - .name = "SSP2-Codec", - .id = 1, - .no_pcm = 1, - .init = geminilake_rt5682_codec_init, - .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | - SND_SOC_DAIFMT_CBC_CFC, - .ignore_pmdown_time = 1, - .be_hw_params_fixup = geminilake_ssp_fixup, - .ops = &geminilake_rt5682_ops, - .dpcm_playback = 1, - .dpcm_capture = 1, - SND_SOC_DAILINK_REG(ssp2_pin, ssp2_codec_5682, platform), - }, - { - .name = "dmic01", - .id = 2, - .ignore_suspend = 1, - .be_hw_params_fixup = geminilake_dmic_fixup, - .dpcm_capture = 1, - .no_pcm = 1, - SND_SOC_DAILINK_REG(dmic_pin, dmic_codec, platform), - }, - { - .name = "iDisp1", - .id = 3, - .init = geminilake_hdmi_init, - .dpcm_playback = 1, - .no_pcm = 1, - SND_SOC_DAILINK_REG(idisp1_pin, idisp1_codec, platform), - }, - { - .name = "iDisp2", - .id = 4, - .init = geminilake_hdmi_init, - .dpcm_playback = 1, - .no_pcm = 1, - SND_SOC_DAILINK_REG(idisp2_pin, idisp2_codec, platform), - }, - { - .name = "iDisp3", - .id = 5, - .init = geminilake_hdmi_init, - .dpcm_playback = 1, - .no_pcm = 1, - SND_SOC_DAILINK_REG(idisp3_pin, idisp3_codec, platform), - }, -}; - -static int glk_card_late_probe(struct snd_soc_card *card) -{ - struct glk_card_private *ctx = snd_soc_card_get_drvdata(card); - struct snd_soc_component *component = NULL; - char jack_name[NAME_SIZE]; - struct glk_hdmi_pcm *pcm; - int err; - int i = 0; - - if (list_empty(&ctx->hdmi_pcm_list)) - return -EINVAL; - - if (ctx->common_hdmi_codec_drv) { - pcm = list_first_entry(&ctx->hdmi_pcm_list, struct glk_hdmi_pcm, - head); - component = pcm->codec_dai->component; - return hda_dsp_hdmi_build_controls(card, component); - } - - list_for_each_entry(pcm, &ctx->hdmi_pcm_list, head) { - component = pcm->codec_dai->component; - snprintf(jack_name, sizeof(jack_name), - "HDMI/DP, pcm=%d Jack", pcm->device); - err = snd_soc_card_jack_new(card, jack_name, - SND_JACK_AVOUT, &geminilake_hdmi[i]); - - if (err) - return err; - - err = hdac_hdmi_jack_init(pcm->codec_dai, pcm->device, - &geminilake_hdmi[i]); - if (err < 0) - return err; - - i++; - } - - return hdac_hdmi_jack_port_init(component, &card->dapm); -} - -/* geminilake audio machine driver for SPT + RT5682 */ -static struct snd_soc_card glk_audio_card_rt5682_m98357a = { - .name = "glkrt5682max", - .owner = THIS_MODULE, - .dai_link = geminilake_dais, - .num_links = ARRAY_SIZE(geminilake_dais), - .controls = geminilake_controls, - .num_controls = ARRAY_SIZE(geminilake_controls), - .dapm_widgets = geminilake_widgets, - .num_dapm_widgets = ARRAY_SIZE(geminilake_widgets), - .dapm_routes = geminilake_map, - .num_dapm_routes = ARRAY_SIZE(geminilake_map), - .fully_routed = true, - .late_probe = glk_card_late_probe, -}; - -static int geminilake_audio_probe(struct platform_device *pdev) -{ - struct glk_card_private *ctx; - struct snd_soc_acpi_mach *mach; - const char *platform_name; - struct snd_soc_card *card; - int ret, i; - - ctx = devm_kzalloc(&pdev->dev, sizeof(*ctx), GFP_KERNEL); - if (!ctx) - return -ENOMEM; - - /* Detect the headset codec variant */ - if (acpi_dev_present("RTL5682", NULL, -1)) { - /* ALC5682I-VS is detected */ - ctx->is_rt5682s = 1; - - for (i = 0; i < glk_audio_card_rt5682_m98357a.num_links; i++) { - if (strcmp(geminilake_dais[i].name, "SSP2-Codec")) - continue; - - /* update the dai link to use rt5682s codec */ - geminilake_dais[i].codecs = ssp2_codec_5682s; - geminilake_dais[i].num_codecs = ARRAY_SIZE(ssp2_codec_5682s); - break; - } - } - - INIT_LIST_HEAD(&ctx->hdmi_pcm_list); - - card = &glk_audio_card_rt5682_m98357a; - card->dev = &pdev->dev; - snd_soc_card_set_drvdata(card, ctx); - if (!snd_soc_acpi_sof_parent(&pdev->dev)) - card->disable_route_checks = true; - - /* override platform name, if required */ - mach = pdev->dev.platform_data; - platform_name = mach->mach_params.platform; - - ret = snd_soc_fixup_dai_links_platform_name(card, platform_name); - if (ret) - return ret; - - ctx->common_hdmi_codec_drv = mach->mach_params.common_hdmi_codec_drv; - - return devm_snd_soc_register_card(&pdev->dev, card); -} - -static const struct platform_device_id glk_board_ids[] = { - { - .name = "glk_rt5682_mx98357a", - .driver_data = - (kernel_ulong_t)&glk_audio_card_rt5682_m98357a, - }, - { } -}; -MODULE_DEVICE_TABLE(platform, glk_board_ids); - -static struct platform_driver geminilake_audio = { - .probe = geminilake_audio_probe, - .driver = { - .name = "glk_rt5682_max98357a", - .pm = &snd_soc_pm_ops, - }, - .id_table = glk_board_ids, -}; -module_platform_driver(geminilake_audio) - -/* Module information */ -MODULE_DESCRIPTION("Geminilake Audio Machine driver-RT5682 & MAX98357A in I2S mode"); -MODULE_AUTHOR("Naveen Manohar "); -MODULE_AUTHOR("Harsha Priya "); -MODULE_LICENSE("GPL v2"); -MODULE_IMPORT_NS(SND_SOC_INTEL_HDA_DSP_COMMON); diff --git a/sound/soc/intel/common/soc-acpi-intel-glk-match.c b/sound/soc/intel/common/soc-acpi-intel-glk-match.c index 1d30991afdc8..c82c8c93d200 100644 --- a/sound/soc/intel/common/soc-acpi-intel-glk-match.c +++ b/sound/soc/intel/common/soc-acpi-intel-glk-match.c @@ -41,7 +41,7 @@ struct snd_soc_acpi_mach snd_soc_acpi_intel_glk_machines[] = { }, { .comp_ids = &glk_rt5682_rt5682s_hp, - .drv_name = "glk_rt5682_mx98357a", + .drv_name = "glk_rt5682_def", .fw_filename = "intel/dsp_fw_glk.bin", .machine_quirk = snd_soc_acpi_codec_list, .quirk_data = &glk_codecs, -- cgit v1.2.3 From e91d54f8b1bd3393d91fd754a1c40df6f408e84b Mon Sep 17 00:00:00 2001 From: Brent Lu Date: Fri, 26 Apr 2024 10:25:23 -0500 Subject: ASoC: Intel: sof-rt5682: add mclk_en to sof_rt5682_private Add a variable mclk_en to sof_rt5682_private structure to reduce global variable access. No functional change. Reviewed-by: Bard Liao Signed-off-by: Brent Lu Signed-off-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20240426152529.38345-18-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/intel/boards/sof_board_helpers.h | 2 ++ sound/soc/intel/boards/sof_rt5682.c | 7 +++++-- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/sound/soc/intel/boards/sof_board_helpers.h b/sound/soc/intel/boards/sof_board_helpers.h index 644f6b4a1b7b..dfcc2c5c25cc 100644 --- a/sound/soc/intel/boards/sof_board_helpers.h +++ b/sound/soc/intel/boards/sof_board_helpers.h @@ -101,10 +101,12 @@ struct sof_da7219_private { * * @mclk: mclk clock data * @is_legacy_cpu: true for BYT/CHT boards + * @mclk_en: true for mclk pin is connected */ struct sof_rt5682_private { struct clk *mclk; bool is_legacy_cpu; + bool mclk_en; }; /* diff --git a/sound/soc/intel/boards/sof_rt5682.c b/sound/soc/intel/boards/sof_rt5682.c index efca7604040e..654c2428f625 100644 --- a/sound/soc/intel/boards/sof_rt5682.c +++ b/sound/soc/intel/boards/sof_rt5682.c @@ -165,7 +165,7 @@ static int sof_rt5682_codec_init(struct snd_soc_pcm_runtime *rtd) int extra_jack_data; int ret, mclk_freq; - if (sof_rt5682_quirk & SOF_RT5682_MCLK_EN) { + if (ctx->rt5682.mclk_en) { mclk_freq = sof_dai_get_mclk(rtd); if (mclk_freq <= 0) { dev_err(rtd->dev, "invalid mclk freq %d\n", mclk_freq); @@ -278,7 +278,7 @@ static int sof_rt5682_hw_params(struct snd_pcm_substream *substream, struct snd_soc_dai *codec_dai = snd_soc_rtd_to_codec(rtd, 0); int pll_id, pll_source, pll_in, pll_out, clk_id, ret; - if (sof_rt5682_quirk & SOF_RT5682_MCLK_EN) { + if (ctx->rt5682.mclk_en) { if (sof_rt5682_quirk & SOF_RT5682_MCLK_BYTCHT_EN) { ret = clk_prepare_enable(ctx->rt5682.mclk); if (ret < 0) { @@ -728,6 +728,9 @@ static int sof_audio_probe(struct platform_device *pdev) } } + if (sof_rt5682_quirk & SOF_RT5682_MCLK_EN) + ctx->rt5682.mclk_en = true; + /* need to get main clock from pmc */ if (sof_rt5682_quirk & SOF_RT5682_MCLK_BYTCHT_EN) { ctx->rt5682.mclk = devm_clk_get(&pdev->dev, "pmc_plt_clk_3"); -- cgit v1.2.3 From 207255f3ae4d0cf5034666652668be572d9c5c1e Mon Sep 17 00:00:00 2001 From: Brent Lu Date: Fri, 26 Apr 2024 10:25:24 -0500 Subject: ASoC: Intel: sof-rt5682: remove SOF_RT5682_MCLK_BYTCHT_EN We don't need this quirk flag since 'is_legacy_cpu' will be true if this is a BYT/CHT board. Reviewed-by: Bard Liao Signed-off-by: Brent Lu Signed-off-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20240426152529.38345-19-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/intel/boards/sof_rt5682.c | 39 ++++++++++++++++++------------------- 1 file changed, 19 insertions(+), 20 deletions(-) diff --git a/sound/soc/intel/boards/sof_rt5682.c b/sound/soc/intel/boards/sof_rt5682.c index 654c2428f625..4c6dfe632edf 100644 --- a/sound/soc/intel/boards/sof_rt5682.c +++ b/sound/soc/intel/boards/sof_rt5682.c @@ -30,7 +30,6 @@ /* Driver-specific board quirks: from bit 0 to 7 */ #define SOF_RT5682_MCLK_EN BIT(0) -#define SOF_RT5682_MCLK_BYTCHT_EN BIT(1) /* Default: MCLK on, MCLK 19.2M, SSP0 */ static unsigned long sof_rt5682_quirk = SOF_RT5682_MCLK_EN | @@ -206,7 +205,7 @@ static int sof_rt5682_codec_init(struct snd_soc_pcm_runtime *rtd) } } - if (sof_rt5682_quirk & SOF_RT5682_MCLK_BYTCHT_EN) { + if (ctx->rt5682.is_legacy_cpu) { /* * The firmware might enable the clock at * boot (this information may or may not @@ -279,7 +278,7 @@ static int sof_rt5682_hw_params(struct snd_pcm_substream *substream, int pll_id, pll_source, pll_in, pll_out, clk_id, ret; if (ctx->rt5682.mclk_en) { - if (sof_rt5682_quirk & SOF_RT5682_MCLK_BYTCHT_EN) { + if (ctx->rt5682.is_legacy_cpu) { ret = clk_prepare_enable(ctx->rt5682.mclk); if (ret < 0) { dev_err(rtd->dev, @@ -661,7 +660,6 @@ static int sof_audio_probe(struct platform_device *pdev) /* default quirk for legacy cpu */ sof_rt5682_quirk = SOF_RT5682_MCLK_EN | - SOF_RT5682_MCLK_BYTCHT_EN | SOF_SSP_PORT_CODEC(2); } @@ -728,26 +726,27 @@ static int sof_audio_probe(struct platform_device *pdev) } } - if (sof_rt5682_quirk & SOF_RT5682_MCLK_EN) + if (sof_rt5682_quirk & SOF_RT5682_MCLK_EN) { ctx->rt5682.mclk_en = true; - /* need to get main clock from pmc */ - if (sof_rt5682_quirk & SOF_RT5682_MCLK_BYTCHT_EN) { - ctx->rt5682.mclk = devm_clk_get(&pdev->dev, "pmc_plt_clk_3"); - if (IS_ERR(ctx->rt5682.mclk)) { - ret = PTR_ERR(ctx->rt5682.mclk); + /* need to get main clock from pmc */ + if (ctx->rt5682.is_legacy_cpu) { + ctx->rt5682.mclk = devm_clk_get(&pdev->dev, "pmc_plt_clk_3"); + if (IS_ERR(ctx->rt5682.mclk)) { + ret = PTR_ERR(ctx->rt5682.mclk); - dev_err(&pdev->dev, - "Failed to get MCLK from pmc_plt_clk_3: %d\n", - ret); - return ret; - } + dev_err(&pdev->dev, + "Failed to get MCLK from pmc_plt_clk_3: %d\n", + ret); + return ret; + } - ret = clk_prepare_enable(ctx->rt5682.mclk); - if (ret < 0) { - dev_err(&pdev->dev, - "could not configure MCLK state"); - return ret; + ret = clk_prepare_enable(ctx->rt5682.mclk); + if (ret < 0) { + dev_err(&pdev->dev, + "could not configure MCLK state"); + return ret; + } } } -- cgit v1.2.3 From 76fb0d3221833e87b9150ba06728cdde215ec687 Mon Sep 17 00:00:00 2001 From: Brent Lu Date: Fri, 26 Apr 2024 10:25:25 -0500 Subject: ASoC: Intel: sof_rt5682: add icl_rt5682_def for icl boards Add the board config icl_rt5682_def to rt5682 machine driver for all icl boards using default SSP port allocation (headphone codec on SSP0). Reviewed-by: Bard Liao Signed-off-by: Brent Lu Signed-off-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20240426152529.38345-20-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/intel/boards/sof_rt5682.c | 14 +++++--------- sound/soc/intel/common/soc-acpi-intel-icl-match.c | 2 +- 2 files changed, 6 insertions(+), 10 deletions(-) diff --git a/sound/soc/intel/boards/sof_rt5682.c b/sound/soc/intel/boards/sof_rt5682.c index 4c6dfe632edf..7a35db5cab35 100644 --- a/sound/soc/intel/boards/sof_rt5682.c +++ b/sound/soc/intel/boards/sof_rt5682.c @@ -76,15 +76,6 @@ static const struct dmi_system_id sof_rt5682_quirk_table[] = { SOF_SSP_PORT_CODEC(0) | SOF_SSP_PORT_AMP(1)), }, - { - .callback = sof_rt5682_quirk_cb, - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "Intel Corporation"), - DMI_MATCH(DMI_PRODUCT_NAME, "Ice Lake Client"), - }, - .driver_data = (void *)(SOF_RT5682_MCLK_EN | - SOF_SSP_PORT_CODEC(0)), - }, { .callback = sof_rt5682_quirk_cb, .matches = { @@ -808,6 +799,11 @@ static const struct platform_device_id board_ids[] = { SOF_SSP_PORT_CODEC(2) | SOF_SSP_PORT_AMP(1)), }, + { + .name = "icl_rt5682_def", + .driver_data = (kernel_ulong_t)(SOF_RT5682_MCLK_EN | + SOF_SSP_PORT_CODEC(0)), + }, { .name = "cml_rt5682_def", .driver_data = (kernel_ulong_t)(SOF_RT5682_MCLK_EN | diff --git a/sound/soc/intel/common/soc-acpi-intel-icl-match.c b/sound/soc/intel/common/soc-acpi-intel-icl-match.c index d0062f2cd256..39875d67dcd1 100644 --- a/sound/soc/intel/common/soc-acpi-intel-icl-match.c +++ b/sound/soc/intel/common/soc-acpi-intel-icl-match.c @@ -29,7 +29,7 @@ struct snd_soc_acpi_mach snd_soc_acpi_intel_icl_machines[] = { }, { .id = "10EC5682", - .drv_name = "sof_rt5682", + .drv_name = "icl_rt5682_def", .sof_tplg_filename = "sof-icl-rt5682.tplg", }, { -- cgit v1.2.3 From 76f33e2f93d63eaac93458fdfde3a505b8e73fa2 Mon Sep 17 00:00:00 2001 From: Brent Lu Date: Fri, 26 Apr 2024 10:25:26 -0500 Subject: ASoC: Intel: sof-rt5682: add driver_data to sof_rt5682 board Move default BYT/CHT quirk to driver_data of sof_rt5682 board. This fixes a problem that DMI quirk of Minnowboard board got overwritten in probe function since it's a BYT board. Fixes: c68e07970eca ("ASoC: intel: sof_rt5682: Add quirk for number of HDMI DAI's") Reviewed-by: Bard Liao Signed-off-by: Brent Lu Signed-off-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20240426152529.38345-21-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/intel/boards/sof_rt5682.c | 13 +++---------- 1 file changed, 3 insertions(+), 10 deletions(-) diff --git a/sound/soc/intel/boards/sof_rt5682.c b/sound/soc/intel/boards/sof_rt5682.c index 7a35db5cab35..668b1672f570 100644 --- a/sound/soc/intel/boards/sof_rt5682.c +++ b/sound/soc/intel/boards/sof_rt5682.c @@ -638,7 +638,6 @@ static int sof_audio_probe(struct platform_device *pdev) struct snd_soc_acpi_mach *mach = pdev->dev.platform_data; struct sof_card_private *ctx; char *card_name; - bool is_legacy_cpu = false; int ret; if (pdev->id_entry && pdev->id_entry->driver_data) @@ -646,14 +645,6 @@ static int sof_audio_probe(struct platform_device *pdev) dmi_check_system(sof_rt5682_quirk_table); - if (soc_intel_is_byt() || soc_intel_is_cht()) { - is_legacy_cpu = true; - - /* default quirk for legacy cpu */ - sof_rt5682_quirk = SOF_RT5682_MCLK_EN | - SOF_SSP_PORT_CODEC(2); - } - dev_dbg(&pdev->dev, "sof_rt5682_quirk = %lx\n", sof_rt5682_quirk); /* initialize ctx with board quirk */ @@ -676,7 +667,7 @@ static int sof_audio_probe(struct platform_device *pdev) if (mach->mach_params.codec_mask & IDISP_CODEC_MASK) ctx->hdmi.idisp_codec = true; - if (is_legacy_cpu) { + if (soc_intel_is_byt() || soc_intel_is_cht()) { ctx->rt5682.is_legacy_cpu = true; ctx->dmic_be_num = 0; /* HDMI is not supported by SOF on Baytrail/CherryTrail */ @@ -792,6 +783,8 @@ static int sof_audio_probe(struct platform_device *pdev) static const struct platform_device_id board_ids[] = { { .name = "sof_rt5682", + .driver_data = (kernel_ulong_t)(SOF_RT5682_MCLK_EN | + SOF_SSP_PORT_CODEC(2)), }, { .name = "glk_rt5682_def", -- cgit v1.2.3 From b5aaf6a56dcafc2aeefdc7da1f9f86fa5cfa8df7 Mon Sep 17 00:00:00 2001 From: Brent Lu Date: Fri, 26 Apr 2024 10:25:27 -0500 Subject: ASoC: Intel: sof-rt5682: setup pll_id only when needed The variable 'pll_id' is needed only when we use snd_soc_dai_set_pll() to setup PLL. Move the code segment to improve some readability. Reviewed-by: Bard Liao Signed-off-by: Brent Lu Signed-off-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20240426152529.38345-22-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/intel/boards/sof_rt5682.c | 58 ++++++++++++++++++------------------- 1 file changed, 29 insertions(+), 29 deletions(-) diff --git a/sound/soc/intel/boards/sof_rt5682.c b/sound/soc/intel/boards/sof_rt5682.c index 668b1672f570..6a79dd5271cc 100644 --- a/sound/soc/intel/boards/sof_rt5682.c +++ b/sound/soc/intel/boards/sof_rt5682.c @@ -320,35 +320,6 @@ static int sof_rt5682_hw_params(struct snd_pcm_substream *substream, pll_in = params_rate(params) * 50; } - switch (ctx->codec_type) { - case CODEC_RT5650: - pll_id = 0; /* not used in codec driver */ - clk_id = RT5645_SCLK_S_PLL1; - break; - case CODEC_RT5682: - pll_id = RT5682_PLL1; - clk_id = RT5682_SCLK_S_PLL1; - break; - case CODEC_RT5682S: - /* - * For MCLK = 24.576MHz and sample rate = 96KHz case, use PLL1 We don't test - * pll_out or params_rate() here since rt5682s PLL2 doesn't support 24.576MHz - * input, so we have no choice but to use PLL1. Besides, we will not use PLL at - * all if pll_in == pll_out. ex, MCLK = 24.576Mhz and sample rate = 48KHz - */ - if (pll_in == 24576000) { - pll_id = RT5682S_PLL1; - clk_id = RT5682S_SCLK_S_PLL1; - } else { - pll_id = RT5682S_PLL2; - clk_id = RT5682S_SCLK_S_PLL2; - } - break; - default: - dev_err(rtd->dev, "invalid codec type %d\n", ctx->codec_type); - return -EINVAL; - } - pll_out = params_rate(params) * 512; /* when MCLK is 512FS, no need to set PLL configuration additionally. */ @@ -369,6 +340,35 @@ static int sof_rt5682_hw_params(struct snd_pcm_substream *substream, return -EINVAL; } } else { + switch (ctx->codec_type) { + case CODEC_RT5650: + pll_id = 0; /* not used in codec driver */ + clk_id = RT5645_SCLK_S_PLL1; + break; + case CODEC_RT5682: + pll_id = RT5682_PLL1; + clk_id = RT5682_SCLK_S_PLL1; + break; + case CODEC_RT5682S: + /* + * For MCLK = 24.576MHz and sample rate = 96KHz case, use PLL1 We don't test + * pll_out or params_rate() here since rt5682s PLL2 doesn't support 24.576MHz + * input, so we have no choice but to use PLL1. Besides, we will not use PLL at + * all if pll_in == pll_out. ex, MCLK = 24.576Mhz and sample rate = 48KHz + */ + if (pll_in == 24576000) { + pll_id = RT5682S_PLL1; + clk_id = RT5682S_SCLK_S_PLL1; + } else { + pll_id = RT5682S_PLL2; + clk_id = RT5682S_SCLK_S_PLL2; + } + break; + default: + dev_err(rtd->dev, "invalid codec type %d\n", ctx->codec_type); + return -EINVAL; + } + /* Configure pll for codec */ ret = snd_soc_dai_set_pll(codec_dai, pll_id, pll_source, pll_in, pll_out); -- cgit v1.2.3 From 4524b1e3ef7884e0a54484dce8d921be7a06af13 Mon Sep 17 00:00:00 2001 From: Brent Lu Date: Fri, 26 Apr 2024 10:25:28 -0500 Subject: ASoC: Intel: sof-rt5682: get bclk frequency from topology A different bclk frequency 3.072MHz was introduced to tgl platform and is used in mtl topologies. Use SOF API to get frequency from topology instead of hardcoding. Reviewed-by: Bard Liao Signed-off-by: Brent Lu Signed-off-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20240426152529.38345-23-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/intel/boards/sof_rt5682.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/sound/soc/intel/boards/sof_rt5682.c b/sound/soc/intel/boards/sof_rt5682.c index 6a79dd5271cc..c3b026868653 100644 --- a/sound/soc/intel/boards/sof_rt5682.c +++ b/sound/soc/intel/boards/sof_rt5682.c @@ -317,7 +317,12 @@ static int sof_rt5682_hw_params(struct snd_pcm_substream *substream, return -EINVAL; } - pll_in = params_rate(params) * 50; + /* get the tplg configured bclk. */ + pll_in = sof_dai_get_bclk(rtd); + if (pll_in <= 0) { + dev_err(rtd->dev, "invalid bclk freq %d\n", pll_in); + return -EINVAL; + } } pll_out = params_rate(params) * 512; -- cgit v1.2.3 From 3d84e070253eb853e3190a23994aa3074615efd1 Mon Sep 17 00:00:00 2001 From: Brent Lu Date: Fri, 26 Apr 2024 10:25:29 -0500 Subject: ASoC: Intel: sof-rt5682: support bclk as PLL source on rt5682s For rt5682s codec, we could use bclk as PLL source when the frequency is 3.072MHz but no 2.4MHz. Update the code to select correct pll_id and clk_id for 3.072MHz bclk. Reviewed-by: Bard Liao Signed-off-by: Brent Lu Signed-off-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20240426152529.38345-24-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/intel/boards/sof_rt5682.c | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/sound/soc/intel/boards/sof_rt5682.c b/sound/soc/intel/boards/sof_rt5682.c index c3b026868653..e3a2ec6b4c7c 100644 --- a/sound/soc/intel/boards/sof_rt5682.c +++ b/sound/soc/intel/boards/sof_rt5682.c @@ -355,18 +355,23 @@ static int sof_rt5682_hw_params(struct snd_pcm_substream *substream, clk_id = RT5682_SCLK_S_PLL1; break; case CODEC_RT5682S: - /* - * For MCLK = 24.576MHz and sample rate = 96KHz case, use PLL1 We don't test - * pll_out or params_rate() here since rt5682s PLL2 doesn't support 24.576MHz - * input, so we have no choice but to use PLL1. Besides, we will not use PLL at - * all if pll_in == pll_out. ex, MCLK = 24.576Mhz and sample rate = 48KHz - */ - if (pll_in == 24576000) { + /* check plla_table and pllb_table in rt5682s.c */ + switch (pll_in) { + case 3072000: + case 24576000: + /* + * For MCLK = 24.576MHz and sample rate = 96KHz case, use PLL1 We don't test + * pll_out or params_rate() here since rt5682s PLL2 doesn't support 24.576MHz + * input, so we have no choice but to use PLL1. Besides, we will not use PLL at + * all if pll_in == pll_out. ex, MCLK = 24.576Mhz and sample rate = 48KHz + */ pll_id = RT5682S_PLL1; clk_id = RT5682S_SCLK_S_PLL1; - } else { + break; + default: pll_id = RT5682S_PLL2; clk_id = RT5682S_SCLK_S_PLL2; + break; } break; default: -- cgit v1.2.3 From 534e0cd89baf74c22ca55b442fb4add8d844e272 Mon Sep 17 00:00:00 2001 From: Luca Ceresoli Date: Fri, 26 Apr 2024 18:56:34 +0200 Subject: ASoC: doc: dapm: fix typos Fix various typos. Reviewed-by: Alexandre Belloni Reviewed-by: Bagas Sanjaya Signed-off-by: Luca Ceresoli Link: https://lore.kernel.org/r/20240426-dapm-docs-v2-1-87b07547eb5b@bootlin.com Signed-off-by: Mark Brown --- Documentation/sound/soc/dapm.rst | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Documentation/sound/soc/dapm.rst b/Documentation/sound/soc/dapm.rst index c3154ce6e1b2..59f65b181828 100644 --- a/Documentation/sound/soc/dapm.rst +++ b/Documentation/sound/soc/dapm.rst @@ -50,7 +50,7 @@ Stream domain All DAPM power switching decisions are made automatically by consulting an audio routing map of the whole machine. This map is specific to each machine and consists of the interconnections between every audio component (including -internal codec components). All audio components that effect power are called +internal codec components). All audio components that affect power are called widgets hereafter. @@ -221,7 +221,7 @@ when the Mic is inserted:-:: Codec (BIAS) Domain ------------------- -The codec bias power domain has no widgets and is handled by the codecs DAPM +The codec bias power domain has no widgets and is handled by the codec DAPM event handler. This handler is called when the codec powerstate is changed wrt to any stream event or by kernel PM events. @@ -236,7 +236,7 @@ a virtual widget - a widget with no control bits e.g. SND_SOC_DAPM_MIXER("AC97 Mixer", SND_SOC_NOPM, 0, 0, NULL, 0), -This can be used to merge to signal paths together in software. +This can be used to merge two signal paths together in software. After all the widgets have been defined, they can then be added to the DAPM subsystem individually with a call to snd_soc_dapm_new_control(). -- cgit v1.2.3 From eaf84bda623e0a034fe03b871addf7dc4f70dfff Mon Sep 17 00:00:00 2001 From: Luca Ceresoli Date: Fri, 26 Apr 2024 18:56:35 +0200 Subject: ASoC: doc: dapm: fix struct name struct snd_soc_codec_dai does not exist. Reviewed-by: Alexandre Belloni Signed-off-by: Luca Ceresoli Link: https://lore.kernel.org/r/20240426-dapm-docs-v2-2-87b07547eb5b@bootlin.com Signed-off-by: Mark Brown --- Documentation/sound/soc/dapm.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Documentation/sound/soc/dapm.rst b/Documentation/sound/soc/dapm.rst index 59f65b181828..68ef79f539f2 100644 --- a/Documentation/sound/soc/dapm.rst +++ b/Documentation/sound/soc/dapm.rst @@ -148,7 +148,7 @@ Stream widgets have the following format:- SND_SOC_DAPM_AIF_IN(name, stream, slot, reg, shift, invert) NOTE: the stream name must match the corresponding stream name in your codec -snd_soc_codec_dai. +snd_soc_dai_driver. e.g. stream widgets for HiFi playback and capture :: -- cgit v1.2.3 From 610277caa77f07997857ab2e31a073d8ad7ed090 Mon Sep 17 00:00:00 2001 From: Luca Ceresoli Date: Fri, 26 Apr 2024 18:56:36 +0200 Subject: ASoC: doc: dapm: minor rewording Slightly reword for better readability: replace "PM" -> "power management frameworks", add missing comma. Reviewed-by: Alexandre Belloni Reviewed-by: Bagas Sanjaya Signed-off-by: Luca Ceresoli Link: https://lore.kernel.org/r/20240426-dapm-docs-v2-3-87b07547eb5b@bootlin.com Signed-off-by: Mark Brown --- Documentation/sound/soc/dapm.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Documentation/sound/soc/dapm.rst b/Documentation/sound/soc/dapm.rst index 68ef79f539f2..479c010d2dac 100644 --- a/Documentation/sound/soc/dapm.rst +++ b/Documentation/sound/soc/dapm.rst @@ -7,8 +7,8 @@ Description Dynamic Audio Power Management (DAPM) is designed to allow portable Linux devices to use the minimum amount of power within the audio -subsystem at all times. It is independent of other kernel PM and as -such, can easily co-exist with the other PM systems. +subsystem at all times. It is independent of other kernel power +management frameworks and, as such, can easily co-exist with them. DAPM is also completely transparent to all user space applications as all power switching is done within the ASoC core. No code changes or -- cgit v1.2.3 From 3233a68fcb216a2d8615862841c1fca7a940fc5c Mon Sep 17 00:00:00 2001 From: Luca Ceresoli Date: Fri, 26 Apr 2024 18:56:37 +0200 Subject: ASoC: doc: dapm: remove dash after colon There is no need for a dash after colons. Also fix an incorrect ":-::" sequence. Reviewed-by: Alexandre Belloni Signed-off-by: Luca Ceresoli Link: https://lore.kernel.org/r/20240426-dapm-docs-v2-4-87b07547eb5b@bootlin.com Signed-off-by: Mark Brown --- Documentation/sound/soc/dapm.rst | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/Documentation/sound/soc/dapm.rst b/Documentation/sound/soc/dapm.rst index 479c010d2dac..be849879274d 100644 --- a/Documentation/sound/soc/dapm.rst +++ b/Documentation/sound/soc/dapm.rst @@ -20,7 +20,7 @@ DAPM spans the whole machine. It covers power control within the entire audio subsystem, this includes internal codec power blocks and machine level power systems. -There are 4 power domains within DAPM +There are 4 power domains within DAPM: Codec bias domain VREF, VMID (core codec and audio power) @@ -57,7 +57,7 @@ widgets hereafter. DAPM Widgets ============ -Audio DAPM widgets fall into a number of types:- +Audio DAPM widgets fall into a number of types: Mixer Mixes several analog signals into a single analog signal. @@ -141,7 +141,7 @@ Stream Widgets relate to the stream power domain and only consist of ADCs (analog to digital converters), DACs (digital to analog converters), AIF IN and AIF OUT. -Stream widgets have the following format:- +Stream widgets have the following format: :: SND_SOC_DAPM_DAC(name, stream name, reg, shift, invert), @@ -167,7 +167,7 @@ Path Domain Widgets ------------------- Path domain widgets have a ability to control or affect the audio signal or -audio paths within the audio subsystem. They have the following form:- +audio paths within the audio subsystem. They have the following form: :: SND_SOC_DAPM_PGA(name, reg, shift, invert, controls, num_controls) @@ -207,7 +207,7 @@ powered. e.g. A machine widget can have an optional call back. e.g. Jack connector widget for an external Mic that enables Mic Bias -when the Mic is inserted:-:: +when the Mic is inserted:: static int spitz_mic_bias(struct snd_soc_dapm_widget* w, int event) { @@ -271,7 +271,7 @@ connect the destination widget (wrt audio signal) with its source widgets. {"Output Mixer", "HiFi Playback Switch", "DAC"}, {"Output Mixer", "Mic Sidetone Switch", "Mic Bias"}, -So we have :- +So we have : * Destination Widget <=== Path Name <=== Source Widget, or * Sink, Path, Source, or @@ -280,7 +280,7 @@ So we have :- When there is no path name connecting widgets (e.g. a direct connection) we pass NULL for the path name. -Interconnections are created with a call to:- +Interconnections are created with a call to: :: snd_soc_dapm_connect_input(codec, sink, path, source); -- cgit v1.2.3 From 7d0e76107894377a14f211c85a821a53416d5ab2 Mon Sep 17 00:00:00 2001 From: Luca Ceresoli Date: Fri, 26 Apr 2024 18:56:39 +0200 Subject: ASoC: doc: dapm: replace "map" with "graph" DAPM is actually based on a graph, so use this specific term instead of the more generic "map". Reviewed-by: Alexandre Belloni Signed-off-by: Luca Ceresoli Link: https://lore.kernel.org/r/20240426-dapm-docs-v2-6-87b07547eb5b@bootlin.com Signed-off-by: Mark Brown --- Documentation/sound/soc/dapm.rst | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Documentation/sound/soc/dapm.rst b/Documentation/sound/soc/dapm.rst index be849879274d..eb50400fa321 100644 --- a/Documentation/sound/soc/dapm.rst +++ b/Documentation/sound/soc/dapm.rst @@ -48,7 +48,7 @@ Stream domain stopped respectively. e.g. aplay, arecord. All DAPM power switching decisions are made automatically by consulting an audio -routing map of the whole machine. This map is specific to each machine and +routing graph of the whole machine. This graph is specific to each machine and consists of the interconnections between every audio component (including internal codec components). All audio components that affect power are called widgets hereafter. @@ -229,7 +229,7 @@ to any stream event or by kernel PM events. Virtual Widgets --------------- -Sometimes widgets exist in the codec or machine audio map that don't have any +Sometimes widgets exist in the codec or machine audio graph that don't have any corresponding soft power control. In this case it is necessary to create a virtual widget - a widget with no control bits e.g. :: @@ -247,7 +247,7 @@ Codec/DSP Widget Interconnections Widgets are connected to each other within the codec, platform and machine by audio paths (called interconnections). Each interconnection must be defined in -order to create a map of all audio paths between widgets. +order to create a graph of all audio paths between widgets. This is easiest with a diagram of the codec or DSP (and schematic of the machine audio system), as it requires joining widgets together via their audio signal -- cgit v1.2.3 From dd5f36e59134654f9fd7b39d4d66327a1a2db82d Mon Sep 17 00:00:00 2001 From: Luca Ceresoli Date: Fri, 26 Apr 2024 18:56:40 +0200 Subject: ASoC: doc: dapm: extend initial descrption Extend the initial description providing clearer definitions of "widget" and "route", and to stop using the word "component" to mean "widget". Give more details and clarify wording and add a picture representing a real DAPM graph. Group all the introductory paragraphs before the "DAPM power domains", and split the latter to a specific section. Reviewed-by: Alexandre Belloni Reviewed-by: Bagas Sanjaya Signed-off-by: Luca Ceresoli Link: https://lore.kernel.org/r/20240426-dapm-docs-v2-7-87b07547eb5b@bootlin.com Signed-off-by: Mark Brown --- Documentation/sound/soc/dapm-graph.svg | 375 +++++++++++++++++++++++++++++++++ Documentation/sound/soc/dapm.rst | 30 ++- 2 files changed, 396 insertions(+), 9 deletions(-) create mode 100644 Documentation/sound/soc/dapm-graph.svg diff --git a/Documentation/sound/soc/dapm-graph.svg b/Documentation/sound/soc/dapm-graph.svg new file mode 100644 index 000000000000..d783672db815 --- /dev/null +++ b/Documentation/sound/soc/dapm-graph.svg @@ -0,0 +1,375 @@ + + + + + + +G + + +ROOT + +ROOT + + +4000b000.audio-controller + +4000b000.audio-controller + + +cs42l51.0-004a + +cs42l51.0-004a + + +hdmi-audio-codec.1.auto + +hdmi-audio-codec.1.auto + + + +ROOT_Amplifier + +Amplifier +[out_drv] + + + +4000b000.audio-controller_capture + +capture +[dai_out] + + + +4000b000.audio-controller_playback + +playback +[dai_in] + + + +hdmi-audio-codec.1.auto_I2S Playback + +I2S Playback +[dai_in] + + + +4000b000.audio-controller_playback->hdmi-audio-codec.1.auto_I2S Playback + + + + + +hdmi-audio-codec.1.auto_Capture + +Capture +[dai_out] + + + +hdmi-audio-codec.1.auto_Capture->4000b000.audio-controller_capture + + + + + +cs42l51.0-004a_AIN1L + +AIN1L +[input] + + + +cs42l51.0-004a_PGA-ADC Mux Left + +PGA-ADC Mux Left +[mux] + + + +cs42l51.0-004a_AIN1L->cs42l51.0-004a_PGA-ADC Mux Left + + + + + +cs42l51.0-004a_AIN1R + +AIN1R +[input] + + + +cs42l51.0-004a_PGA-ADC Mux Right + +PGA-ADC Mux Right +[mux] + + + +cs42l51.0-004a_AIN1R->cs42l51.0-004a_PGA-ADC Mux Right + + + + + +cs42l51.0-004a_AIN2L + +AIN2L +[input] + + + +cs42l51.0-004a_AIN2R + +AIN2R +[input] + + + +cs42l51.0-004a_Capture + +Capture +[dai_out] + + + +cs42l51.0-004a_DAC Mux + +DAC Mux +[mux] + + + +cs42l51.0-004a_Left DAC + +Left DAC +[dac] + + + +cs42l51.0-004a_DAC Mux->cs42l51.0-004a_Left DAC + + + + + +cs42l51.0-004a_Right DAC + +Right DAC +[dac] + + + +cs42l51.0-004a_DAC Mux->cs42l51.0-004a_Right DAC + + + + + +cs42l51.0-004a_HPL + +HPL +[output] + + + +cs42l51.0-004a_HPR + +HPR +[output] + + + +cs42l51.0-004a_Left ADC + +Left ADC +[adc] + + + +cs42l51.0-004a_Left ADC->cs42l51.0-004a_Capture + + + + + +cs42l51.0-004a_Left DAC->cs42l51.0-004a_HPL + + + + + +cs42l51.0-004a_Left PGA + +Left PGA +[pga] + + + +cs42l51.0-004a_Left PGA->cs42l51.0-004a_Left ADC + + + + + +cs42l51.0-004a_MCLK + +MCLK +[supply] + + + +cs42l51.0-004a_MCLK->cs42l51.0-004a_Capture + + + + + +cs42l51.0-004a_Playback + +Playback +[dai_in] + + + +cs42l51.0-004a_MCLK->cs42l51.0-004a_Playback + + + + + +cs42l51.0-004a_MICL + +MICL +[input] + + + +cs42l51.0-004a_Mic Preamp Left + +Mic Preamp Left +[mixer] + + + +cs42l51.0-004a_MICL->cs42l51.0-004a_Mic Preamp Left + + + + + +cs42l51.0-004a_MICR + +MICR +[input] + + + +cs42l51.0-004a_Mic Preamp Right + +Mic Preamp Right +[mixer] + + + +cs42l51.0-004a_MICR->cs42l51.0-004a_Mic Preamp Right + + + + + +cs42l51.0-004a_Mic Bias + +Mic Bias +[supply] + + + +cs42l51.0-004a_Mic Bias->cs42l51.0-004a_MICL + + + + + +cs42l51.0-004a_PGA-ADC Mux Left->cs42l51.0-004a_Left PGA + + + + + +cs42l51.0-004a_Right PGA + +Right PGA +[pga] + + + +cs42l51.0-004a_PGA-ADC Mux Right->cs42l51.0-004a_Right PGA + + + + + +cs42l51.0-004a_Playback->cs42l51.0-004a_DAC Mux + + + + + +cs42l51.0-004a_Right ADC + +Right ADC +[adc] + + + +cs42l51.0-004a_Right ADC->cs42l51.0-004a_Capture + + + + + +cs42l51.0-004a_Right DAC->cs42l51.0-004a_HPR + + + + + +cs42l51.0-004a_Right PGA->cs42l51.0-004a_Right ADC + + + + + +hdmi-audio-codec.1.auto_TX + +TX +[output] + + + +hdmi-audio-codec.1.auto_I2S Playback->hdmi-audio-codec.1.auto_TX + + + + + +hdmi-audio-codec.1.auto_RX + +RX +[output] + + + +hdmi-audio-codec.1.auto_RX->hdmi-audio-codec.1.auto_Capture + + + + + diff --git a/Documentation/sound/soc/dapm.rst b/Documentation/sound/soc/dapm.rst index eb50400fa321..8d741295fc40 100644 --- a/Documentation/sound/soc/dapm.rst +++ b/Documentation/sound/soc/dapm.rst @@ -16,9 +16,27 @@ recompiling are required for user space applications. DAPM makes power switching decisions based upon any audio stream (capture/playback) activity and audio mixer settings within the device. -DAPM spans the whole machine. It covers power control within the entire -audio subsystem, this includes internal codec power blocks and machine -level power systems. +DAPM is based on two basic elements, called widgets and routes: + + * a **widget** is every part of the audio hardware that can be enabled by + software when in use and disabled to save power when not in use + * a **route** is an interconnection between widgets that exists when sound + can flow from one widget to the other + +All DAPM power switching decisions are made automatically by consulting an +audio routing graph. This graph is specific to each sound card and spans +the whole sound card, so some DAPM routes connect two widgets belonging to +different components (e.g. the LINE OUT pin of a CODEC and the input pin of +an amplifier). + +The graph for the STM32MP1-DK1 sound card is shown in picture: + +.. kernel-figure:: dapm-graph.svg + :alt: Example DAPM graph + :align: center + +DAPM power domains +================== There are 4 power domains within DAPM: @@ -47,12 +65,6 @@ Stream domain Enabled and disabled when stream playback/capture is started and stopped respectively. e.g. aplay, arecord. -All DAPM power switching decisions are made automatically by consulting an audio -routing graph of the whole machine. This graph is specific to each machine and -consists of the interconnections between every audio component (including -internal codec components). All audio components that affect power are called -widgets hereafter. - DAPM Widgets ============ -- cgit v1.2.3 From 36de8c0e26793beeda1d6a7592f44b4551271469 Mon Sep 17 00:00:00 2001 From: Luca Ceresoli Date: Fri, 26 Apr 2024 18:56:41 +0200 Subject: ASoC: doc: dapm: describe how widgets and routes are registered The small paragraph describing how to register widgets is incomplete (does not mention routes) and mentions snd_soc_dapm_new_control() which is not really used. Moreover it appears as a part of the "Virtual Widgets" subsection. Replace it with a detailed and current description of how widgets and routes are registered, mentioning both static declaration and runtime registration. Also make this a section on its own. Reviewed-by: Alexandre Belloni Reviewed-by: Bagas Sanjaya Signed-off-by: Luca Ceresoli Link: https://lore.kernel.org/r/20240426-dapm-docs-v2-8-87b07547eb5b@bootlin.com Signed-off-by: Mark Brown --- Documentation/sound/soc/dapm.rst | 38 ++++++++++++++++++++++++++++++++++++-- 1 file changed, 36 insertions(+), 2 deletions(-) diff --git a/Documentation/sound/soc/dapm.rst b/Documentation/sound/soc/dapm.rst index 8d741295fc40..57d96a39f124 100644 --- a/Documentation/sound/soc/dapm.rst +++ b/Documentation/sound/soc/dapm.rst @@ -250,8 +250,42 @@ a virtual widget - a widget with no control bits e.g. This can be used to merge two signal paths together in software. -After all the widgets have been defined, they can then be added to the DAPM -subsystem individually with a call to snd_soc_dapm_new_control(). +Registering DAPM controls +========================= + +In many cases the DAPM widgets implemented statically in a ``static const +struct snd_soc_dapm_widget`` array and the routes connecting them in a +``static const struct snd_soc_dapm_route`` array in a codec driver, and +simply declared via the ``dapm_widgets`` and ``num_dapm_widgets`` fields of +the ``struct snd_soc_component_driver`` so the driver registration will +take care of populating them:: + + static const struct snd_soc_dapm_widget wm2000_dapm_widgets[] = { + SND_SOC_DAPM_OUTPUT("SPKN"), + SND_SOC_DAPM_OUTPUT("SPKP"), + ... + }; + + /* Target, Path, Source */ + static const struct snd_soc_dapm_route wm2000_audio_map[] = { + { "SPKN", NULL, "ANC Engine" }, + { "SPKP", NULL, "ANC Engine" }, + ... + }; + + static const struct snd_soc_component_driver soc_component_dev_wm2000 = { + ... + .dapm_widgets = wm2000_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(wm2000_dapm_widgets), + ... + }; + +In more complex cases the list of DAPM widgets and/or routes can be only +known at build time. This happens for example when a driver supports +different models having a different set of features. In those cases +separate widgets and routes arrays implementing the case-specific features +can be registered programmatically by calling snd_soc_dapm_new_controls() +and snd_soc_dapm_add_routes(). Codec/DSP Widget Interconnections -- cgit v1.2.3 From d40e82194423c9d058bdeff863373b7da9f7045b Mon Sep 17 00:00:00 2001 From: Luca Ceresoli Date: Fri, 26 Apr 2024 18:56:42 +0200 Subject: ASoC: doc: dapm: fix and improve section "Registering DAPM controls" Extend the first paragraph to mention the {,num_}dapm_routes fields just like the widget conterparts. Mention the route fields also in the code example. Fix "at build time", this really means "at probe time". Reviewed-by: Alexandre Belloni Reviewed-by: Bagas Sanjaya Signed-off-by: Luca Ceresoli Link: https://lore.kernel.org/r/20240426-dapm-docs-v2-9-87b07547eb5b@bootlin.com Signed-off-by: Mark Brown --- Documentation/sound/soc/dapm.rst | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/Documentation/sound/soc/dapm.rst b/Documentation/sound/soc/dapm.rst index 57d96a39f124..50f908f4e8ed 100644 --- a/Documentation/sound/soc/dapm.rst +++ b/Documentation/sound/soc/dapm.rst @@ -253,12 +253,17 @@ This can be used to merge two signal paths together in software. Registering DAPM controls ========================= -In many cases the DAPM widgets implemented statically in a ``static const -struct snd_soc_dapm_widget`` array and the routes connecting them in a -``static const struct snd_soc_dapm_route`` array in a codec driver, and -simply declared via the ``dapm_widgets`` and ``num_dapm_widgets`` fields of -the ``struct snd_soc_component_driver`` so the driver registration will -take care of populating them:: +In many cases the DAPM widgets are implemented statically in a ``static +const struct snd_soc_dapm_widget`` array in a codec driver, and simply +declared via the ``dapm_widgets`` and ``num_dapm_widgets`` fields of the +``struct snd_soc_component_driver``. + +Similarly, routes connecting them are implemented statically in a ``static +const struct snd_soc_dapm_route`` array and declared via the +``dapm_routes`` and ``num_dapm_routes`` fields of the same struct. + +With the above declared, the driver registration will take care of +populating them:: static const struct snd_soc_dapm_widget wm2000_dapm_widgets[] = { SND_SOC_DAPM_OUTPUT("SPKN"), @@ -277,11 +282,13 @@ take care of populating them:: ... .dapm_widgets = wm2000_dapm_widgets, .num_dapm_widgets = ARRAY_SIZE(wm2000_dapm_widgets), + .dapm_routes = wm2000_audio_map, + .num_dapm_routes = ARRAY_SIZE(wm2000_audio_map), ... }; In more complex cases the list of DAPM widgets and/or routes can be only -known at build time. This happens for example when a driver supports +known at probe time. This happens for example when a driver supports different models having a different set of features. In those cases separate widgets and routes arrays implementing the case-specific features can be registered programmatically by calling snd_soc_dapm_new_controls() -- cgit v1.2.3 From 057acfb460d6792c7d3ec088f57c411fb0e4d395 Mon Sep 17 00:00:00 2001 From: Luca Ceresoli Date: Fri, 26 Apr 2024 18:56:43 +0200 Subject: ASoC: doc: dapm: improve section "Codec/DSP Widget Interconnections" Improve wording in a few places, cleanup ReST colon syntax, remove space before colon, and remove the "codec" parameter in the parentheses of snd_soc_dapm_new_widgets() (there should be no parameters in the docs, and that function takes a card, not a codec). Reviewed-by: Alexandre Belloni Signed-off-by: Luca Ceresoli Link: https://lore.kernel.org/r/20240426-dapm-docs-v2-10-87b07547eb5b@bootlin.com Signed-off-by: Mark Brown --- Documentation/sound/soc/dapm.rst | 19 ++++++++----------- 1 file changed, 8 insertions(+), 11 deletions(-) diff --git a/Documentation/sound/soc/dapm.rst b/Documentation/sound/soc/dapm.rst index 50f908f4e8ed..8fccdb0d6454 100644 --- a/Documentation/sound/soc/dapm.rst +++ b/Documentation/sound/soc/dapm.rst @@ -306,25 +306,23 @@ This is easiest with a diagram of the codec or DSP (and schematic of the machine audio system), as it requires joining widgets together via their audio signal paths. -e.g., from the WM8731 output mixer (wm8731.c) - -The WM8731 output mixer has 3 inputs (sources) +For example the WM8731 output mixer (wm8731.c) has 3 inputs (sources): 1. Line Bypass Input 2. DAC (HiFi playback) 3. Mic Sidetone Input -Each input in this example has a kcontrol associated with it (defined in example -above) and is connected to the output mixer via its kcontrol name. We can now -connect the destination widget (wrt audio signal) with its source widgets. -:: +Each input in this example has a kcontrol associated with it (defined in +the example above) and is connected to the output mixer via its kcontrol +name. We can now connect the destination widget (wrt audio signal) with its +source widgets. :: /* output mixer */ {"Output Mixer", "Line Bypass Switch", "Line Input"}, {"Output Mixer", "HiFi Playback Switch", "DAC"}, {"Output Mixer", "Mic Sidetone Switch", "Mic Bias"}, -So we have : +So we have: * Destination Widget <=== Path Name <=== Source Widget, or * Sink, Path, Source, or @@ -333,12 +331,11 @@ So we have : When there is no path name connecting widgets (e.g. a direct connection) we pass NULL for the path name. -Interconnections are created with a call to: -:: +Interconnections are created with a call to:: snd_soc_dapm_connect_input(codec, sink, path, source); -Finally, snd_soc_dapm_new_widgets(codec) must be called after all widgets and +Finally, snd_soc_dapm_new_widgets() must be called after all widgets and interconnections have been registered with the core. This causes the core to scan the codec and machine so that the internal DAPM state matches the physical state of the machine. -- cgit v1.2.3 From ce5a4f101cd0dfbda391d4f1815222d82a9d8a5a Mon Sep 17 00:00:00 2001 From: Luca Ceresoli Date: Fri, 26 Apr 2024 18:56:44 +0200 Subject: ASoC: doc: dapm: update section "DAPM Widget Events" The example in this section is not in the kernel sources anymore. Replace it with an up to date code fragment. Reword the initial paragraph. Remove "Please" which is not standard practice in documentation. Reviewed-by: Alexandre Belloni Signed-off-by: Luca Ceresoli Link: https://lore.kernel.org/r/20240426-dapm-docs-v2-11-87b07547eb5b@bootlin.com Signed-off-by: Mark Brown --- Documentation/sound/soc/dapm.rst | 30 ++++++++++++++++++------------ 1 file changed, 18 insertions(+), 12 deletions(-) diff --git a/Documentation/sound/soc/dapm.rst b/Documentation/sound/soc/dapm.rst index 8fccdb0d6454..2a1cfa2eca83 100644 --- a/Documentation/sound/soc/dapm.rst +++ b/Documentation/sound/soc/dapm.rst @@ -376,23 +376,29 @@ jacks can also be switched OFF. DAPM Widget Events ================== -Some widgets can register their interest with the DAPM core in PM events. -e.g. A Speaker with an amplifier registers a widget so the amplifier can be -powered only when the spk is in use. -:: +Widgets needing to implement a more complex behaviour than what DAPM can do +can set a custom "event handler" by setting a function pointer. An example +is a power supply needing to enable a GPIO:: - /* turn speaker amplifier on/off depending on use */ - static int corgi_amp_event(struct snd_soc_dapm_widget *w, int event) + static int sof_es8316_speaker_power_event(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, int event) { - gpio_set_value(CORGI_GPIO_APM_ON, SND_SOC_DAPM_EVENT_ON(event)); - return 0; + if (SND_SOC_DAPM_EVENT_ON(event)) + gpiod_set_value_cansleep(gpio_pa, true); + else + gpiod_set_value_cansleep(gpio_pa, false); + + return 0; } - /* corgi machine dapm widgets */ - static const struct snd_soc_dapm_widget wm8731_dapm_widgets = - SND_SOC_DAPM_SPK("Ext Spk", corgi_amp_event); + static const struct snd_soc_dapm_widget st_widgets[] = { + ... + SND_SOC_DAPM_SUPPLY("Speaker Power", SND_SOC_NOPM, 0, 0, + sof_es8316_speaker_power_event, + SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU), + }; -Please see soc-dapm.h for all other widgets that support events. +See soc-dapm.h for all other widgets that support events. Event types -- cgit v1.2.3 From 4155a82f6af8068473cd66b55da56fd379835fb0 Mon Sep 17 00:00:00 2001 From: Luca Ceresoli Date: Fri, 26 Apr 2024 18:56:45 +0200 Subject: ASoC: doc: dapm: update event types Some new event types now exist, so update the code fragment. Reviewed-by: Alexandre Belloni Signed-off-by: Luca Ceresoli Link: https://lore.kernel.org/r/20240426-dapm-docs-v2-12-87b07547eb5b@bootlin.com Signed-off-by: Mark Brown --- Documentation/sound/soc/dapm.rst | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/Documentation/sound/soc/dapm.rst b/Documentation/sound/soc/dapm.rst index 2a1cfa2eca83..14c4dc026e6b 100644 --- a/Documentation/sound/soc/dapm.rst +++ b/Documentation/sound/soc/dapm.rst @@ -404,13 +404,16 @@ See soc-dapm.h for all other widgets that support events. Event types ----------- -The following event types are supported by event widgets. -:: +The following event types are supported by event widgets:: /* dapm event types */ - #define SND_SOC_DAPM_PRE_PMU 0x1 /* before widget power up */ - #define SND_SOC_DAPM_POST_PMU 0x2 /* after widget power up */ - #define SND_SOC_DAPM_PRE_PMD 0x4 /* before widget power down */ - #define SND_SOC_DAPM_POST_PMD 0x8 /* after widget power down */ - #define SND_SOC_DAPM_PRE_REG 0x10 /* before audio path setup */ - #define SND_SOC_DAPM_POST_REG 0x20 /* after audio path setup */ + #define SND_SOC_DAPM_PRE_PMU 0x1 /* before widget power up */ + #define SND_SOC_DAPM_POST_PMU 0x2 /* after widget power up */ + #define SND_SOC_DAPM_PRE_PMD 0x4 /* before widget power down */ + #define SND_SOC_DAPM_POST_PMD 0x8 /* after widget power down */ + #define SND_SOC_DAPM_PRE_REG 0x10 /* before audio path setup */ + #define SND_SOC_DAPM_POST_REG 0x20 /* after audio path setup */ + #define SND_SOC_DAPM_WILL_PMU 0x40 /* called at start of sequence */ + #define SND_SOC_DAPM_WILL_PMD 0x80 /* called at start of sequence */ + #define SND_SOC_DAPM_PRE_POST_PMD (SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD) + #define SND_SOC_DAPM_PRE_POST_PMU (SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU) -- cgit v1.2.3 From 31a70a71b3a730aa703bbd05713d21115dd6d33a Mon Sep 17 00:00:00 2001 From: Cezary Rojewski Date: Fri, 26 Apr 2024 11:57:26 +0200 Subject: ASoC: pcm: Reverse iterate DAIs when shutting them down During startup snd_soc_dai_startup() is launched in ascending order and the exact same thing is done during shutdown procedure. Reverse the order in the latter so that it is symmetric to the former. Signed-off-by: Cezary Rojewski Link: https://lore.kernel.org/r/20240426095733.3946951-2-cezary.rojewski@intel.com Signed-off-by: Mark Brown --- include/sound/soc.h | 4 ++++ sound/soc/soc-pcm.c | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/include/sound/soc.h b/include/sound/soc.h index 2a1b6c198547..8aa6ddb7ee1e 100644 --- a/include/sound/soc.h +++ b/include/sound/soc.h @@ -1235,6 +1235,10 @@ struct snd_soc_pcm_runtime { ((i) < (rtd)->dai_link->num_cpus + (rtd)->dai_link->num_codecs) && \ ((dai) = (rtd)->dais[i]); \ (i)++) +#define for_each_rtd_dais_reverse(rtd, i, dai) \ + for ((i) = (rtd)->dai_link->num_cpus + (rtd)->dai_link->num_codecs - 1; \ + (i) >= 0 && ((dai) = (rtd)->dais[i]); \ + (i)--) #define for_each_rtd_ch_maps(rtd, i, ch_maps) for_each_link_ch_maps(rtd->dai_link, i, ch_maps) void snd_soc_close_delayed_work(struct snd_soc_pcm_runtime *rtd); diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c index b0e1bd7f588b..711b2f49ed88 100644 --- a/sound/soc/soc-pcm.c +++ b/sound/soc/soc-pcm.c @@ -724,7 +724,7 @@ static int soc_pcm_clean(struct snd_soc_pcm_runtime *rtd, } } - for_each_rtd_dais(rtd, i, dai) + for_each_rtd_dais_reverse(rtd, i, dai) snd_soc_dai_shutdown(dai, substream, rollback); snd_soc_link_shutdown(substream, rollback); -- cgit v1.2.3 From 140df6d4d5f541e950a35cad2e3dffb49186ed74 Mon Sep 17 00:00:00 2001 From: Cezary Rojewski Date: Fri, 26 Apr 2024 11:57:27 +0200 Subject: ASoC: Intel: avs: Relocate HDA BE DAI specific operations DAI's startup()/shutdown() shall deal with allocation and freeing of resources needed to facilitate streaming over it. Currently for HDAudio BE DAIs some of that task is done in component->open()/close(). Relocate the relevant pieces to address that. Signed-off-by: Cezary Rojewski Link: https://lore.kernel.org/r/20240426095733.3946951-3-cezary.rojewski@intel.com Signed-off-by: Mark Brown --- sound/soc/intel/avs/pcm.c | 55 ++++++++++++++++++++++------------------------- 1 file changed, 26 insertions(+), 29 deletions(-) diff --git a/sound/soc/intel/avs/pcm.c b/sound/soc/intel/avs/pcm.c index 77a7e8f93951..f3cd54f355ef 100644 --- a/sound/soc/intel/avs/pcm.c +++ b/sound/soc/intel/avs/pcm.c @@ -277,12 +277,36 @@ static const struct snd_soc_dai_ops avs_dai_hda_be_ops; static int avs_dai_hda_be_startup(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) { - return avs_dai_startup(substream, dai, false, &avs_dai_hda_be_ops); + struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream); + struct hdac_ext_stream *link_stream; + struct hda_codec *codec; + int ret; + + ret = avs_dai_startup(substream, dai, false, &avs_dai_hda_be_ops); + if (ret) + return ret; + + codec = dev_to_hda_codec(snd_soc_rtd_to_codec(rtd, 0)->dev); + link_stream = snd_hdac_ext_stream_assign(&codec->bus->core, substream, + HDAC_EXT_STREAM_TYPE_LINK); + if (!link_stream) { + avs_dai_nonhda_be_shutdown(substream, dai); + return -EBUSY; + } + + substream->runtime->private_data = link_stream; + return 0; } static void avs_dai_hda_be_shutdown(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) { - return avs_dai_nonhda_be_shutdown(substream, dai); + struct hdac_ext_stream *link_stream; + + link_stream = substream->runtime->private_data; + snd_hdac_ext_stream_release(link_stream, HDAC_EXT_STREAM_TYPE_LINK); + substream->runtime->private_data = NULL; + + avs_dai_nonhda_be_shutdown(substream, dai); } static int avs_dai_hda_be_hw_params(struct snd_pcm_substream *substream, @@ -1576,8 +1600,6 @@ static int avs_component_hda_open(struct snd_soc_component *component, struct snd_pcm_substream *substream) { struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream); - struct hdac_ext_stream *link_stream; - struct hda_codec *codec; if (!rtd->dai_link->no_pcm) { struct snd_pcm_hardware hwparams = avs_pcm_hardware; @@ -1609,30 +1631,6 @@ static int avs_component_hda_open(struct snd_soc_component *component, return snd_soc_set_runtime_hwparams(substream, &hwparams); } - codec = dev_to_hda_codec(snd_soc_rtd_to_codec(rtd, 0)->dev); - link_stream = snd_hdac_ext_stream_assign(&codec->bus->core, substream, - HDAC_EXT_STREAM_TYPE_LINK); - if (!link_stream) - return -EBUSY; - - substream->runtime->private_data = link_stream; - return 0; -} - -static int avs_component_hda_close(struct snd_soc_component *component, - struct snd_pcm_substream *substream) -{ - struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream); - struct hdac_ext_stream *link_stream; - - /* only BE DAI links are handled here */ - if (!rtd->dai_link->no_pcm) - return 0; - - link_stream = substream->runtime->private_data; - snd_hdac_ext_stream_release(link_stream, HDAC_EXT_STREAM_TYPE_LINK); - substream->runtime->private_data = NULL; - return 0; } @@ -1643,7 +1641,6 @@ static const struct snd_soc_component_driver avs_hda_component_driver = { .suspend = avs_component_suspend, .resume = avs_component_resume, .open = avs_component_hda_open, - .close = avs_component_hda_close, .pointer = avs_component_pointer, .mmap = avs_component_mmap, .pcm_construct = avs_component_construct, -- cgit v1.2.3 From b9d59f970ea7772957f6da02ca1ba272ef4495b8 Mon Sep 17 00:00:00 2001 From: Cezary Rojewski Date: Fri, 26 Apr 2024 11:57:28 +0200 Subject: ASoC: Intel: avs: Remove redundancy around DAI shutdown Move avs_dai_nonhda_be_shutdown() to avs_dai_shutdown() as the function is common for all transfer types, not just non-HDAudio ones. Use it to simplify avs_dai_fe_shutdown(). While at it, fix explicit kfree(data) and use the destructor instead. Signed-off-by: Cezary Rojewski Link: https://lore.kernel.org/r/20240426095733.3946951-4-cezary.rojewski@intel.com Signed-off-by: Mark Brown --- sound/soc/intel/avs/pcm.c | 44 +++++++++++++++++++------------------------- 1 file changed, 19 insertions(+), 25 deletions(-) diff --git a/sound/soc/intel/avs/pcm.c b/sound/soc/intel/avs/pcm.c index f3cd54f355ef..23f7e0fae817 100644 --- a/sound/soc/intel/avs/pcm.c +++ b/sound/soc/intel/avs/pcm.c @@ -85,6 +85,21 @@ static int avs_dai_startup(struct snd_pcm_substream *substream, struct snd_soc_d return 0; } +static void avs_dai_shutdown(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) +{ + struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream); + struct avs_dev *adev = to_avs_dev(dai->dev); + struct avs_dma_data *data; + + data = snd_soc_dai_get_dma_data(dai, substream); + + if (rtd->dai_link->ignore_suspend) + adev->num_lp_paths--; + + snd_soc_dai_set_dma_data(dai, substream, NULL); + kfree(data); +} + static int avs_dai_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *fe_hw_params, struct snd_pcm_hw_params *be_hw_params, struct snd_soc_dai *dai, @@ -166,21 +181,6 @@ static int avs_dai_nonhda_be_startup(struct snd_pcm_substream *substream, struct return avs_dai_startup(substream, dai, false, &avs_dai_nonhda_be_ops); } -static void avs_dai_nonhda_be_shutdown(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) -{ - struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream); - struct avs_dev *adev = to_avs_dev(dai->dev); - struct avs_dma_data *data; - - if (rtd->dai_link->ignore_suspend) - adev->num_lp_paths--; - - data = snd_soc_dai_get_dma_data(dai, substream); - - snd_soc_dai_set_dma_data(dai, substream, NULL); - kfree(data); -} - static int avs_dai_nonhda_be_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *hw_params, struct snd_soc_dai *dai) { @@ -266,7 +266,7 @@ static int avs_dai_nonhda_be_trigger(struct snd_pcm_substream *substream, int cm static const struct snd_soc_dai_ops avs_dai_nonhda_be_ops = { .startup = avs_dai_nonhda_be_startup, - .shutdown = avs_dai_nonhda_be_shutdown, + .shutdown = avs_dai_shutdown, .hw_params = avs_dai_nonhda_be_hw_params, .hw_free = avs_dai_nonhda_be_hw_free, .prepare = avs_dai_nonhda_be_prepare, @@ -290,7 +290,7 @@ static int avs_dai_hda_be_startup(struct snd_pcm_substream *substream, struct sn link_stream = snd_hdac_ext_stream_assign(&codec->bus->core, substream, HDAC_EXT_STREAM_TYPE_LINK); if (!link_stream) { - avs_dai_nonhda_be_shutdown(substream, dai); + avs_dai_shutdown(substream, dai); return -EBUSY; } @@ -306,7 +306,7 @@ static void avs_dai_hda_be_shutdown(struct snd_pcm_substream *substream, struct snd_hdac_ext_stream_release(link_stream, HDAC_EXT_STREAM_TYPE_LINK); substream->runtime->private_data = NULL; - avs_dai_nonhda_be_shutdown(substream, dai); + avs_dai_shutdown(substream, dai); } static int avs_dai_hda_be_hw_params(struct snd_pcm_substream *substream, @@ -558,18 +558,12 @@ err: static void avs_dai_fe_shutdown(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) { - struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream); - struct avs_dev *adev = to_avs_dev(dai->dev); struct avs_dma_data *data; - if (rtd->dai_link->ignore_suspend) - adev->num_lp_paths--; - data = snd_soc_dai_get_dma_data(dai, substream); - snd_soc_dai_set_dma_data(dai, substream, NULL); snd_hdac_ext_stream_release(data->host_stream, HDAC_EXT_STREAM_TYPE_HOST); - kfree(data); + avs_dai_shutdown(substream, dai); } static int avs_dai_fe_hw_params(struct snd_pcm_substream *substream, -- cgit v1.2.3 From c303a994e5d0f7d297cb6ac56052dce8f412ee67 Mon Sep 17 00:00:00 2001 From: Cezary Rojewski Date: Fri, 26 Apr 2024 11:57:29 +0200 Subject: ASoC: Intel: avs: Store pointer to adev in DAI dma_data Reduce the number of to_avs_dev() casts by storing the driver context in DAI's dma_data. Signed-off-by: Cezary Rojewski Link: https://lore.kernel.org/r/20240426095733.3946951-5-cezary.rojewski@intel.com Signed-off-by: Mark Brown --- sound/soc/intel/avs/pcm.c | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/sound/soc/intel/avs/pcm.c b/sound/soc/intel/avs/pcm.c index 23f7e0fae817..a3a04115216c 100644 --- a/sound/soc/intel/avs/pcm.c +++ b/sound/soc/intel/avs/pcm.c @@ -22,6 +22,7 @@ struct avs_dma_data { struct avs_tplg_path_template *template; struct avs_path *path; + struct avs_dev *adev; /* * link stream is stored within substream's runtime * private_data to fulfill the needs of codec BE path @@ -60,7 +61,7 @@ static int avs_dai_startup(struct snd_pcm_substream *substream, struct snd_soc_d const struct snd_soc_dai_ops *ops) { struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream); - struct avs_dev *adev = to_avs_dev(dai->dev); + struct avs_dev *adev = to_avs_dev(dai->component->dev); struct avs_tplg_path_template *template; struct avs_dma_data *data; @@ -77,6 +78,7 @@ static int avs_dai_startup(struct snd_pcm_substream *substream, struct snd_soc_d data->substream = substream; data->template = template; + data->adev = adev; snd_soc_dai_set_dma_data(dai, substream, data); if (rtd->dai_link->ignore_suspend) @@ -88,13 +90,12 @@ static int avs_dai_startup(struct snd_pcm_substream *substream, struct snd_soc_d static void avs_dai_shutdown(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) { struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream); - struct avs_dev *adev = to_avs_dev(dai->dev); struct avs_dma_data *data; data = snd_soc_dai_get_dma_data(dai, substream); if (rtd->dai_link->ignore_suspend) - adev->num_lp_paths--; + data->adev->num_lp_paths--; snd_soc_dai_set_dma_data(dai, substream, NULL); kfree(data); @@ -107,7 +108,6 @@ static int avs_dai_hw_params(struct snd_pcm_substream *substream, { struct avs_dma_data *data; struct avs_path *path; - struct avs_dev *adev = to_avs_dev(dai->dev); int ret; data = snd_soc_dai_get_dma_data(dai, substream); @@ -124,7 +124,7 @@ static int avs_dai_hw_params(struct snd_pcm_substream *substream, params_rate(be_hw_params), params_channels(be_hw_params), params_width(be_hw_params), params_physical_width(be_hw_params)); - path = avs_path_create(adev, dma_id, data->template, fe_hw_params, be_hw_params); + path = avs_path_create(data->adev, dma_id, data->template, fe_hw_params, be_hw_params); if (IS_ERR(path)) { ret = PTR_ERR(path); dev_err(dai->dev, "create path failed: %d\n", ret); @@ -505,8 +505,7 @@ static int avs_dai_fe_startup(struct snd_pcm_substream *substream, struct snd_so { struct snd_pcm_runtime *runtime = substream->runtime; struct avs_dma_data *data; - struct avs_dev *adev = to_avs_dev(dai->dev); - struct hdac_bus *bus = &adev->base.core; + struct hdac_bus *bus; struct hdac_ext_stream *host_stream; int ret; @@ -515,6 +514,7 @@ static int avs_dai_fe_startup(struct snd_pcm_substream *substream, struct snd_so return ret; data = snd_soc_dai_get_dma_data(dai, substream); + bus = &data->adev->base.core; host_stream = snd_hdac_ext_stream_assign(bus, substream, HDAC_EXT_STREAM_TYPE_HOST); if (!host_stream) { @@ -655,7 +655,6 @@ static int avs_dai_fe_prepare(struct snd_pcm_substream *substream, struct snd_so struct snd_pcm_runtime *runtime = substream->runtime; struct snd_soc_pcm_stream *stream_info; struct avs_dma_data *data; - struct avs_dev *adev = to_avs_dev(dai->dev); struct hdac_ext_stream *host_stream; unsigned int format_val; struct hdac_bus *bus; @@ -685,7 +684,7 @@ static int avs_dai_fe_prepare(struct snd_pcm_substream *substream, struct snd_so if (ret < 0) return ret; - ret = avs_dai_prepare(adev, substream, dai); + ret = avs_dai_prepare(data->adev, substream, dai); if (ret) return ret; -- cgit v1.2.3 From 3a48d146aa761bc591272bc453eda64743128a31 Mon Sep 17 00:00:00 2001 From: Cezary Rojewski Date: Fri, 26 Apr 2024 11:57:30 +0200 Subject: ASoC: Intel: avs: Remove redundancy around DAI startup Half of the arguments in avs_dai_startup() are unused and can be dropped. With the function updated, it matches its template in snd_soc_dai_ops and can be referenced throughout the pcm.c file without need of any wrappers. Signed-off-by: Cezary Rojewski Link: https://lore.kernel.org/r/20240426095733.3946951-6-cezary.rojewski@intel.com Signed-off-by: Mark Brown --- sound/soc/intel/avs/pcm.c | 22 +++++----------------- 1 file changed, 5 insertions(+), 17 deletions(-) diff --git a/sound/soc/intel/avs/pcm.c b/sound/soc/intel/avs/pcm.c index a3a04115216c..0771a9716f4b 100644 --- a/sound/soc/intel/avs/pcm.c +++ b/sound/soc/intel/avs/pcm.c @@ -57,15 +57,14 @@ avs_dai_find_path_template(struct snd_soc_dai *dai, bool is_fe, int direction) return dw->priv; } -static int avs_dai_startup(struct snd_pcm_substream *substream, struct snd_soc_dai *dai, bool is_fe, - const struct snd_soc_dai_ops *ops) +static int avs_dai_startup(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) { struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream); struct avs_dev *adev = to_avs_dev(dai->component->dev); struct avs_tplg_path_template *template; struct avs_dma_data *data; - template = avs_dai_find_path_template(dai, is_fe, substream->stream); + template = avs_dai_find_path_template(dai, !rtd->dai_link->no_pcm, substream->stream); if (!template) { dev_err(dai->dev, "no %s path for dai %s, invalid tplg?\n", snd_pcm_stream_str(substream), dai->name); @@ -174,13 +173,6 @@ static int avs_dai_prepare(struct avs_dev *adev, struct snd_pcm_substream *subst return ret; } -static const struct snd_soc_dai_ops avs_dai_nonhda_be_ops; - -static int avs_dai_nonhda_be_startup(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) -{ - return avs_dai_startup(substream, dai, false, &avs_dai_nonhda_be_ops); -} - static int avs_dai_nonhda_be_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *hw_params, struct snd_soc_dai *dai) { @@ -265,7 +257,7 @@ static int avs_dai_nonhda_be_trigger(struct snd_pcm_substream *substream, int cm } static const struct snd_soc_dai_ops avs_dai_nonhda_be_ops = { - .startup = avs_dai_nonhda_be_startup, + .startup = avs_dai_startup, .shutdown = avs_dai_shutdown, .hw_params = avs_dai_nonhda_be_hw_params, .hw_free = avs_dai_nonhda_be_hw_free, @@ -273,8 +265,6 @@ static const struct snd_soc_dai_ops avs_dai_nonhda_be_ops = { .trigger = avs_dai_nonhda_be_trigger, }; -static const struct snd_soc_dai_ops avs_dai_hda_be_ops; - static int avs_dai_hda_be_startup(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) { struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream); @@ -282,7 +272,7 @@ static int avs_dai_hda_be_startup(struct snd_pcm_substream *substream, struct sn struct hda_codec *codec; int ret; - ret = avs_dai_startup(substream, dai, false, &avs_dai_hda_be_ops); + ret = avs_dai_startup(substream, dai); if (ret) return ret; @@ -479,8 +469,6 @@ static const struct snd_pcm_hw_constraint_list hw_rates = { .mask = 0, }; -const struct snd_soc_dai_ops avs_dai_fe_ops; - static int hw_rule_param_size(struct snd_pcm_hw_params *params, struct snd_pcm_hw_rule *rule) { struct snd_interval *interval = hw_param_interval(params, rule->var); @@ -509,7 +497,7 @@ static int avs_dai_fe_startup(struct snd_pcm_substream *substream, struct snd_so struct hdac_ext_stream *host_stream; int ret; - ret = avs_dai_startup(substream, dai, true, &avs_dai_fe_ops); + ret = avs_dai_startup(substream, dai); if (ret) return ret; -- cgit v1.2.3 From 0f8843ca4f6cbf0efb8c2d5516a3b92fb2771a04 Mon Sep 17 00:00:00 2001 From: Cezary Rojewski Date: Fri, 26 Apr 2024 11:57:31 +0200 Subject: ASoC: Intel: avs: Remove redundancy around DAI prepare Drop unused arguments in the avs_dai_prepare() function. With the function updated, it matches its template in snd_soc_dai_ops and can be referenced throughout the pcm.c file without need of any wrappers. Signed-off-by: Cezary Rojewski Link: https://lore.kernel.org/r/20240426095733.3946951-7-cezary.rojewski@intel.com Signed-off-by: Mark Brown --- sound/soc/intel/avs/pcm.c | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) diff --git a/sound/soc/intel/avs/pcm.c b/sound/soc/intel/avs/pcm.c index 0771a9716f4b..d4557b7b1c6c 100644 --- a/sound/soc/intel/avs/pcm.c +++ b/sound/soc/intel/avs/pcm.c @@ -151,8 +151,7 @@ static int avs_dai_be_hw_params(struct snd_pcm_substream *substream, return avs_dai_hw_params(substream, fe_hw_params, be_hw_params, dai, dma_id); } -static int avs_dai_prepare(struct avs_dev *adev, struct snd_pcm_substream *substream, - struct snd_soc_dai *dai) +static int avs_dai_prepare(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) { struct avs_dma_data *data; int ret; @@ -201,11 +200,6 @@ static int avs_dai_nonhda_be_hw_free(struct snd_pcm_substream *substream, struct return 0; } -static int avs_dai_nonhda_be_prepare(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) -{ - return avs_dai_prepare(to_avs_dev(dai->dev), substream, dai); -} - static int avs_dai_nonhda_be_trigger(struct snd_pcm_substream *substream, int cmd, struct snd_soc_dai *dai) { @@ -261,7 +255,7 @@ static const struct snd_soc_dai_ops avs_dai_nonhda_be_ops = { .shutdown = avs_dai_shutdown, .hw_params = avs_dai_nonhda_be_hw_params, .hw_free = avs_dai_nonhda_be_hw_free, - .prepare = avs_dai_nonhda_be_prepare, + .prepare = avs_dai_prepare, .trigger = avs_dai_nonhda_be_trigger, }; @@ -381,7 +375,7 @@ static int avs_dai_hda_be_prepare(struct snd_pcm_substream *substream, struct sn if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) snd_hdac_ext_bus_link_set_stream_id(link, hdac_stream(link_stream)->stream_tag); - ret = avs_dai_prepare(to_avs_dev(dai->dev), substream, dai); + ret = avs_dai_prepare(substream, dai); if (ret) return ret; @@ -672,7 +666,7 @@ static int avs_dai_fe_prepare(struct snd_pcm_substream *substream, struct snd_so if (ret < 0) return ret; - ret = avs_dai_prepare(data->adev, substream, dai); + ret = avs_dai_prepare(substream, dai); if (ret) return ret; -- cgit v1.2.3 From cdcb770a60e8e6b9fbb737ebe21b2daadaba1744 Mon Sep 17 00:00:00 2001 From: Cezary Rojewski Date: Fri, 26 Apr 2024 11:57:32 +0200 Subject: ASoC: Intel: avs: Store pointer to link_stream in dma_data While the HDAudio codec driver expectations must be met - store valid pointer to HDAudio LINK stream in substream->runtime->private_data - the code is more readable and easier to maintain if dma_data stores pointers to both HOST and LINK stream. DAI BE operations can refer to the LINK stream with data->link_stream, similarly to how DAI FE operations access the HOST stream with data->host_stream. Signed-off-by: Cezary Rojewski Link: https://lore.kernel.org/r/20240426095733.3946951-8-cezary.rojewski@intel.com Signed-off-by: Mark Brown --- sound/soc/intel/avs/pcm.c | 40 +++++++++++++++++++--------------------- 1 file changed, 19 insertions(+), 21 deletions(-) diff --git a/sound/soc/intel/avs/pcm.c b/sound/soc/intel/avs/pcm.c index d4557b7b1c6c..168e16e82116 100644 --- a/sound/soc/intel/avs/pcm.c +++ b/sound/soc/intel/avs/pcm.c @@ -23,13 +23,12 @@ struct avs_dma_data { struct avs_tplg_path_template *template; struct avs_path *path; struct avs_dev *adev; - /* - * link stream is stored within substream's runtime - * private_data to fulfill the needs of codec BE path - * - * host stream assigned - */ - struct hdac_ext_stream *host_stream; + + /* LINK-stream utilized in BE operations while HOST in FE ones. */ + union { + struct hdac_ext_stream *link_stream; + struct hdac_ext_stream *host_stream; + }; struct snd_pcm_substream *substream; }; @@ -263,6 +262,7 @@ static int avs_dai_hda_be_startup(struct snd_pcm_substream *substream, struct sn { struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream); struct hdac_ext_stream *link_stream; + struct avs_dma_data *data; struct hda_codec *codec; int ret; @@ -278,18 +278,18 @@ static int avs_dai_hda_be_startup(struct snd_pcm_substream *substream, struct sn return -EBUSY; } + data = snd_soc_dai_get_dma_data(dai, substream); + data->link_stream = link_stream; substream->runtime->private_data = link_stream; return 0; } static void avs_dai_hda_be_shutdown(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) { - struct hdac_ext_stream *link_stream; + struct avs_dma_data *data = snd_soc_dai_get_dma_data(dai, substream); - link_stream = substream->runtime->private_data; - snd_hdac_ext_stream_release(link_stream, HDAC_EXT_STREAM_TYPE_LINK); + snd_hdac_ext_stream_release(data->link_stream, HDAC_EXT_STREAM_TYPE_LINK); substream->runtime->private_data = NULL; - avs_dai_shutdown(substream, dai); } @@ -297,16 +297,13 @@ static int avs_dai_hda_be_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *hw_params, struct snd_soc_dai *dai) { struct avs_dma_data *data; - struct hdac_ext_stream *link_stream; data = snd_soc_dai_get_dma_data(dai, substream); if (data->path) return 0; - link_stream = substream->runtime->private_data; - return avs_dai_be_hw_params(substream, hw_params, dai, - hdac_stream(link_stream)->stream_tag - 1); + hdac_stream(data->link_stream)->stream_tag - 1); } static int avs_dai_hda_be_hw_free(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) @@ -323,7 +320,7 @@ static int avs_dai_hda_be_hw_free(struct snd_pcm_substream *substream, struct sn if (!data->path) return 0; - link_stream = substream->runtime->private_data; + link_stream = data->link_stream; link_stream->link_prepared = false; avs_path_free(data->path); data->path = NULL; @@ -347,13 +344,16 @@ static int avs_dai_hda_be_prepare(struct snd_pcm_substream *substream, struct sn struct snd_soc_pcm_stream *stream_info; struct hdac_ext_stream *link_stream; struct hdac_ext_link *link; + struct avs_dma_data *data; struct hda_codec *codec; struct hdac_bus *bus; unsigned int format_val; unsigned int bits; int ret; - link_stream = runtime->private_data; + data = snd_soc_dai_get_dma_data(dai, substream); + link_stream = data->link_stream; + if (link_stream->link_prepared) return 0; @@ -387,14 +387,12 @@ static int avs_dai_hda_be_trigger(struct snd_pcm_substream *substream, int cmd, struct snd_soc_dai *dai) { struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream); - struct hdac_ext_stream *link_stream; struct avs_dma_data *data; int ret = 0; dev_dbg(dai->dev, "entry %s cmd=%d\n", __func__, cmd); data = snd_soc_dai_get_dma_data(dai, substream); - link_stream = substream->runtime->private_data; switch (cmd) { case SNDRV_PCM_TRIGGER_RESUME: @@ -403,7 +401,7 @@ static int avs_dai_hda_be_trigger(struct snd_pcm_substream *substream, int cmd, fallthrough; case SNDRV_PCM_TRIGGER_START: case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: - snd_hdac_ext_stream_start(link_stream); + snd_hdac_ext_stream_start(data->link_stream); ret = avs_path_pause(data->path); if (ret < 0) { @@ -426,7 +424,7 @@ static int avs_dai_hda_be_trigger(struct snd_pcm_substream *substream, int cmd, if (ret < 0) dev_err(dai->dev, "pause BE path failed: %d\n", ret); - snd_hdac_ext_stream_clear(link_stream); + snd_hdac_ext_stream_clear(data->link_stream); ret = avs_path_reset(data->path); if (ret < 0) -- cgit v1.2.3 From e85e75b67993c1fb0c80306783c31266261170d4 Mon Sep 17 00:00:00 2001 From: Cezary Rojewski Date: Fri, 26 Apr 2024 11:57:33 +0200 Subject: ASoC: Intel: avs: Clean up hw constraints initialization Provide a separate function that initializes all PCM hardware constraints for the driver. No functional changes. Signed-off-by: Cezary Rojewski Link: https://lore.kernel.org/r/20240426095733.3946951-9-cezary.rojewski@intel.com Signed-off-by: Mark Brown --- sound/soc/intel/avs/pcm.c | 84 +++++++++++++++++++++++++---------------------- 1 file changed, 44 insertions(+), 40 deletions(-) diff --git a/sound/soc/intel/avs/pcm.c b/sound/soc/intel/avs/pcm.c index 168e16e82116..845b5ed9eb1b 100644 --- a/sound/soc/intel/avs/pcm.c +++ b/sound/soc/intel/avs/pcm.c @@ -448,19 +448,6 @@ static const struct snd_soc_dai_ops avs_dai_hda_be_ops = { .trigger = avs_dai_hda_be_trigger, }; -static const unsigned int rates[] = { - 8000, 11025, 12000, 16000, - 22050, 24000, 32000, 44100, - 48000, 64000, 88200, 96000, - 128000, 176400, 192000, -}; - -static const struct snd_pcm_hw_constraint_list hw_rates = { - .count = ARRAY_SIZE(rates), - .list = rates, - .mask = 0, -}; - static int hw_rule_param_size(struct snd_pcm_hw_params *params, struct snd_pcm_hw_rule *rule) { struct snd_interval *interval = hw_param_interval(params, rule->var); @@ -481,40 +468,33 @@ static int hw_rule_param_size(struct snd_pcm_hw_params *params, struct snd_pcm_h return snd_interval_refine(interval, &to); } -static int avs_dai_fe_startup(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) +static int avs_pcm_hw_constraints_init(struct snd_pcm_substream *substream) { struct snd_pcm_runtime *runtime = substream->runtime; - struct avs_dma_data *data; - struct hdac_bus *bus; - struct hdac_ext_stream *host_stream; + static const unsigned int rates[] = { + 8000, 11025, 12000, 16000, + 22050, 24000, 32000, 44100, + 48000, 64000, 88200, 96000, + 128000, 176400, 192000, + }; + static const struct snd_pcm_hw_constraint_list rate_list = { + .count = ARRAY_SIZE(rates), + .list = rates, + }; int ret; - ret = avs_dai_startup(substream, dai); - if (ret) - return ret; - - data = snd_soc_dai_get_dma_data(dai, substream); - bus = &data->adev->base.core; - - host_stream = snd_hdac_ext_stream_assign(bus, substream, HDAC_EXT_STREAM_TYPE_HOST); - if (!host_stream) { - ret = -EBUSY; - goto err; - } - - data->host_stream = host_stream; ret = snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS); if (ret < 0) - goto err; + return ret; - /* avoid wrap-around with wall-clock */ + /* Avoid wrap-around with wall-clock. */ ret = snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_BUFFER_TIME, 20, 178000000); if (ret < 0) - goto err; + return ret; - ret = snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, &hw_rates); + ret = snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, &rate_list); if (ret < 0) - goto err; + return ret; /* Adjust buffer and period size based on the audio format. */ snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_BUFFER_SIZE, hw_rule_param_size, NULL, @@ -524,16 +504,40 @@ static int avs_dai_fe_startup(struct snd_pcm_substream *substream, struct snd_so SNDRV_PCM_HW_PARAM_FORMAT, SNDRV_PCM_HW_PARAM_CHANNELS, SNDRV_PCM_HW_PARAM_RATE, -1); + return ret; +} + +static int avs_dai_fe_startup(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) +{ + struct hdac_ext_stream *host_stream; + struct avs_dma_data *data; + struct hdac_bus *bus; + int ret; + + ret = avs_pcm_hw_constraints_init(substream); + if (ret) + return ret; + + ret = avs_dai_startup(substream, dai); + if (ret) + return ret; + + data = snd_soc_dai_get_dma_data(dai, substream); + bus = &data->adev->base.core; + + host_stream = snd_hdac_ext_stream_assign(bus, substream, HDAC_EXT_STREAM_TYPE_HOST); + if (!host_stream) { + avs_dai_shutdown(substream, dai); + return -EBUSY; + } + + data->host_stream = host_stream; snd_pcm_set_sync(substream); dev_dbg(dai->dev, "%s fe STARTUP tag %d str %p", __func__, hdac_stream(host_stream)->stream_tag, substream); return 0; - -err: - kfree(data); - return ret; } static void avs_dai_fe_shutdown(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) -- cgit v1.2.3 From 33e59e50ee7610473c85030edca73ad3df60b5c1 Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Fri, 26 Apr 2024 10:21:12 -0500 Subject: ASoC: Intel: skl_hda_dsp_generic: Allocate snd_soc_card dynamically The static hda_soc_card might be modified during runtime which might cause issues on next time when the card is created. For example if the dmic_num was set with module parameter then removed for the next module loading then the card's components will still going to point to the previous boot's cfg-dmics:X string. There might be other places where devm allocated memory have been freed but the hda_soc_card still pointing to the now unallocated memory (the memory is freed when the platform device is removed). Fix this issue by moving the snd_soc_card into skl_hda_private and use it for the card registration to ensure that it is correctly initialized every time. Reviewed-by: Bard Liao Reviewed-by: Ranjani Sridharan Reviewed-by: Kai Vehmanen Signed-off-by: Peter Ujfalusi Signed-off-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20240426152123.36284-2-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/intel/boards/skl_hda_dsp_common.h | 1 + sound/soc/intel/boards/skl_hda_dsp_generic.c | 42 ++++++++++++++-------------- 2 files changed, 22 insertions(+), 21 deletions(-) diff --git a/sound/soc/intel/boards/skl_hda_dsp_common.h b/sound/soc/intel/boards/skl_hda_dsp_common.h index 4b0b3959182e..19b814dee4ad 100644 --- a/sound/soc/intel/boards/skl_hda_dsp_common.h +++ b/sound/soc/intel/boards/skl_hda_dsp_common.h @@ -28,6 +28,7 @@ struct skl_hda_hdmi_pcm { }; struct skl_hda_private { + struct snd_soc_card card; struct list_head hdmi_pcm_list; int pcm_count; int dai_index; diff --git a/sound/soc/intel/boards/skl_hda_dsp_generic.c b/sound/soc/intel/boards/skl_hda_dsp_generic.c index 4aa7fd2a05e4..208395872d8b 100644 --- a/sound/soc/intel/boards/skl_hda_dsp_generic.c +++ b/sound/soc/intel/boards/skl_hda_dsp_generic.c @@ -92,17 +92,6 @@ skl_hda_add_dai_link(struct snd_soc_card *card, struct snd_soc_dai_link *link) return ret; } -static struct snd_soc_card hda_soc_card = { - .name = "hda-dsp", - .owner = THIS_MODULE, - .dai_link = skl_hda_be_dai_links, - .dapm_widgets = skl_hda_widgets, - .dapm_routes = skl_hda_map, - .add_dai_link = skl_hda_add_dai_link, - .fully_routed = true, - .late_probe = skl_hda_card_late_probe, -}; - static char hda_soc_components[30]; #define IDISP_DAI_COUNT 3 @@ -115,9 +104,9 @@ static char hda_soc_components[30]; #define HDA_CODEC_AUTOSUSPEND_DELAY_MS 1000 -static int skl_hda_fill_card_info(struct snd_soc_acpi_mach_params *mach_params) +static int skl_hda_fill_card_info(struct snd_soc_card *card, + struct snd_soc_acpi_mach_params *mach_params) { - struct snd_soc_card *card = &hda_soc_card; struct skl_hda_private *ctx = snd_soc_card_get_drvdata(card); struct snd_soc_dai_link *dai_link; u32 codec_count, codec_mask; @@ -199,6 +188,7 @@ static int skl_hda_audio_probe(struct platform_device *pdev) { struct snd_soc_acpi_mach *mach; struct skl_hda_private *ctx; + struct snd_soc_card *card; int ret; dev_dbg(&pdev->dev, "entry\n"); @@ -213,32 +203,42 @@ static int skl_hda_audio_probe(struct platform_device *pdev) if (!mach) return -EINVAL; - snd_soc_card_set_drvdata(&hda_soc_card, ctx); + card = &ctx->card; + card->name = "hda-dsp", + card->owner = THIS_MODULE, + card->dai_link = skl_hda_be_dai_links, + card->dapm_widgets = skl_hda_widgets, + card->dapm_routes = skl_hda_map, + card->add_dai_link = skl_hda_add_dai_link, + card->fully_routed = true, + card->late_probe = skl_hda_card_late_probe, + + snd_soc_card_set_drvdata(card, ctx); - ret = skl_hda_fill_card_info(&mach->mach_params); + ret = skl_hda_fill_card_info(card, &mach->mach_params); if (ret < 0) { dev_err(&pdev->dev, "Unsupported HDAudio/iDisp configuration found\n"); return ret; } - ctx->pcm_count = hda_soc_card.num_links; + ctx->pcm_count = card->num_links; ctx->dai_index = 1; /* hdmi codec dai name starts from index 1 */ ctx->platform_name = mach->mach_params.platform; ctx->common_hdmi_codec_drv = mach->mach_params.common_hdmi_codec_drv; - hda_soc_card.dev = &pdev->dev; + card->dev = &pdev->dev; if (!snd_soc_acpi_sof_parent(&pdev->dev)) - hda_soc_card.disable_route_checks = true; + card->disable_route_checks = true; if (mach->mach_params.dmic_num > 0) { snprintf(hda_soc_components, sizeof(hda_soc_components), "cfg-dmics:%d", mach->mach_params.dmic_num); - hda_soc_card.components = hda_soc_components; + card->components = hda_soc_components; } - ret = devm_snd_soc_register_card(&pdev->dev, &hda_soc_card); + ret = devm_snd_soc_register_card(&pdev->dev, card); if (!ret) - skl_set_hda_codec_autosuspend_delay(&hda_soc_card); + skl_set_hda_codec_autosuspend_delay(card); return ret; } -- cgit v1.2.3 From 69d0f88b9aebb5749ab0dbaead7414d718994380 Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Fri, 26 Apr 2024 10:21:13 -0500 Subject: ASoC: Intel: skl_hda_dsp_generic: Use devm_kasprintf for the components string Instead of using a global char array, allocate the string with devm_kasprintf if needed. Reviewed-by: Bard Liao Reviewed-by: Ranjani Sridharan Reviewed-by: Kai Vehmanen Signed-off-by: Peter Ujfalusi Signed-off-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20240426152123.36284-3-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/intel/boards/skl_hda_dsp_generic.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/sound/soc/intel/boards/skl_hda_dsp_generic.c b/sound/soc/intel/boards/skl_hda_dsp_generic.c index 208395872d8b..88d91c0280bb 100644 --- a/sound/soc/intel/boards/skl_hda_dsp_generic.c +++ b/sound/soc/intel/boards/skl_hda_dsp_generic.c @@ -92,8 +92,6 @@ skl_hda_add_dai_link(struct snd_soc_card *card, struct snd_soc_dai_link *link) return ret; } -static char hda_soc_components[30]; - #define IDISP_DAI_COUNT 3 #define HDAC_DAI_COUNT 2 #define DMIC_DAI_COUNT 2 @@ -231,9 +229,11 @@ static int skl_hda_audio_probe(struct platform_device *pdev) card->disable_route_checks = true; if (mach->mach_params.dmic_num > 0) { - snprintf(hda_soc_components, sizeof(hda_soc_components), - "cfg-dmics:%d", mach->mach_params.dmic_num); - card->components = hda_soc_components; + card->components = devm_kasprintf(card->dev, GFP_KERNEL, + "cfg-dmics:%d", + mach->mach_params.dmic_num); + if (!card->components) + return -ENOMEM; } ret = devm_snd_soc_register_card(&pdev->dev, card); -- cgit v1.2.3 From 02e6f7cb487f18e1171ae6d12ad1066fbd25176d Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Fri, 26 Apr 2024 10:21:14 -0500 Subject: ASoC: Intel: soc-acpi: mtl: add Dell SKU 0C64 and 0CC6 SKU 0C64 relies on rt713 (jack codec) on link0, rt1318 (single amplifier) on link1 and rt1713 (dmic) on link3. SKU 0CC6 relies on rt713 (jack codec) on link0, rt1318 (two amplifiers) on link 1-2 and rt1713 (dmic) on link3. Reviewed-by: Bard Liao Signed-off-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20240426152123.36284-4-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/intel/common/soc-acpi-intel-mtl-match.c | 64 +++++++++++++++++++++++ 1 file changed, 64 insertions(+) diff --git a/sound/soc/intel/common/soc-acpi-intel-mtl-match.c b/sound/soc/intel/common/soc-acpi-intel-mtl-match.c index f95490a16b55..8c1c430f5482 100644 --- a/sound/soc/intel/common/soc-acpi-intel-mtl-match.c +++ b/sound/soc/intel/common/soc-acpi-intel-mtl-match.c @@ -312,6 +312,15 @@ static const struct snd_soc_acpi_adr_device rt1316_3_single_adr[] = { } }; +static const struct snd_soc_acpi_adr_device rt1318_1_single_adr[] = { + { + .adr = 0x000130025D131801, + .num_endpoints = 1, + .endpoints = &single_endpoint, + .name_prefix = "rt1318" + } +}; + static const struct snd_soc_acpi_adr_device rt1318_1_group1_adr[] = { { .adr = 0x000130025D131801ull, @@ -559,6 +568,49 @@ static const struct snd_soc_acpi_link_adr mtl_rt713_l0_rt1316_l12_rt1713_l3[] = {} }; +static const struct snd_soc_acpi_link_adr mtl_rt713_l0_rt1318_l1_rt1713_l3[] = { + { + .mask = BIT(0), + .num_adr = ARRAY_SIZE(rt713_0_single_adr), + .adr_d = rt713_0_single_adr, + }, + { + .mask = BIT(1), + .num_adr = ARRAY_SIZE(rt1318_1_single_adr), + .adr_d = rt1318_1_single_adr, + }, + { + .mask = BIT(3), + .num_adr = ARRAY_SIZE(rt1713_3_single_adr), + .adr_d = rt1713_3_single_adr, + }, + {} +}; + +static const struct snd_soc_acpi_link_adr mtl_rt713_l0_rt1318_l12_rt1713_l3[] = { + { + .mask = BIT(0), + .num_adr = ARRAY_SIZE(rt713_0_single_adr), + .adr_d = rt713_0_single_adr, + }, + { + .mask = BIT(1), + .num_adr = ARRAY_SIZE(rt1318_1_group1_adr), + .adr_d = rt1318_1_group1_adr, + }, + { + .mask = BIT(2), + .num_adr = ARRAY_SIZE(rt1318_2_group1_adr), + .adr_d = rt1318_2_group1_adr, + }, + { + .mask = BIT(3), + .num_adr = ARRAY_SIZE(rt1713_3_single_adr), + .adr_d = rt1713_3_single_adr, + }, + {} +}; + static const struct snd_soc_acpi_link_adr mtl_rt713_l0_rt1316_l12[] = { { .mask = BIT(0), @@ -697,6 +749,18 @@ struct snd_soc_acpi_mach snd_soc_acpi_intel_mtl_sdw_machines[] = { .drv_name = "sof_sdw", .sof_tplg_filename = "sof-mtl-rt713-l0-rt1316-l12-rt1713-l3.tplg", }, + { + .link_mask = GENMASK(3, 0), + .links = mtl_rt713_l0_rt1318_l12_rt1713_l3, + .drv_name = "sof_sdw", + .sof_tplg_filename = "sof-mtl-rt713-l0-rt1318-l12-rt1713-l3.tplg", + }, + { + .link_mask = BIT(0) | BIT(1) | BIT(3), + .links = mtl_rt713_l0_rt1318_l1_rt1713_l3, + .drv_name = "sof_sdw", + .sof_tplg_filename = "sof-mtl-rt713-l0-rt1318-l1-rt1713-l3.tplg", + }, { .link_mask = GENMASK(2, 0), .links = mtl_rt713_l0_rt1316_l12, -- cgit v1.2.3 From 64bfd26d982ec29123c65949229fa12c15f7df8f Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Fri, 26 Apr 2024 10:21:15 -0500 Subject: ASoC: Intel: soc-acpi: mtl: add support for Acer Swift Go 14 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This device has an RT712 on link0, but does not rely on RT1712 for the DMIC. PCH-attached DMICs are used instead. Closes: https://github.com/thesofproject/linux/issues/4923 Reviewed-by: Bard Liao Reviewed-by: Péter Ujfalusi Signed-off-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20240426152123.36284-5-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/intel/common/soc-acpi-intel-mtl-match.c | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/sound/soc/intel/common/soc-acpi-intel-mtl-match.c b/sound/soc/intel/common/soc-acpi-intel-mtl-match.c index 8c1c430f5482..4eeec0bc92dc 100644 --- a/sound/soc/intel/common/soc-acpi-intel-mtl-match.c +++ b/sound/soc/intel/common/soc-acpi-intel-mtl-match.c @@ -357,7 +357,7 @@ static const struct snd_soc_acpi_adr_device rt714_1_adr[] = { } }; -static const struct snd_soc_acpi_link_adr mtl_712_only[] = { +static const struct snd_soc_acpi_link_adr mtl_712_l0_1712_l3[] = { { .mask = BIT(0), .num_adr = ARRAY_SIZE(rt712_0_single_adr), @@ -371,6 +371,15 @@ static const struct snd_soc_acpi_link_adr mtl_712_only[] = { {} }; +static const struct snd_soc_acpi_link_adr mtl_712_l0[] = { + { + .mask = BIT(0), + .num_adr = ARRAY_SIZE(rt712_0_single_adr), + .adr_d = rt712_0_single_adr, + }, + {} +}; + static const struct snd_soc_acpi_endpoint cs42l43_endpoints[] = { { /* Jack Playback Endpoint */ .num = 0, @@ -769,10 +778,16 @@ struct snd_soc_acpi_mach snd_soc_acpi_intel_mtl_sdw_machines[] = { }, { .link_mask = BIT(3) | BIT(0), - .links = mtl_712_only, + .links = mtl_712_l0_1712_l3, .drv_name = "sof_sdw", .sof_tplg_filename = "sof-mtl-rt712-l0-rt1712-l3.tplg", }, + { + .link_mask = BIT(0), + .links = mtl_712_l0, + .drv_name = "sof_sdw", + .sof_tplg_filename = "sof-mtl-rt712-l0.tplg", + }, { .link_mask = GENMASK(2, 0), .links = mtl_sdw_rt1318_l12_rt714_l0, -- cgit v1.2.3 From 6d339113df3ab510ce075a18ccb10a20cb325d4e Mon Sep 17 00:00:00 2001 From: Mac Chiang Date: Fri, 26 Apr 2024 10:21:16 -0500 Subject: ASoC: Intel: soc-acpi-intel-lnl-match: adds RT714 and RT1318 support MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This patch adds support for corresponding codecs on LNL hardware configuration: SDW0: RT714 DMIC SDW1: RT1318 Left Speaker SDW2: RT1318 Right Speaker Reviewed-by: Bard Liao Reviewed-by: Péter Ujfalusi Signed-off-by: Mac Chiang Signed-off-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20240426152123.36284-6-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/intel/common/soc-acpi-intel-lnl-match.c | 52 +++++++++++++++++++++++ 1 file changed, 52 insertions(+) diff --git a/sound/soc/intel/common/soc-acpi-intel-lnl-match.c b/sound/soc/intel/common/soc-acpi-intel-lnl-match.c index 74d6dcd7471f..0318c1a46f3c 100644 --- a/sound/soc/intel/common/soc-acpi-intel-lnl-match.c +++ b/sound/soc/intel/common/soc-acpi-intel-lnl-match.c @@ -130,6 +130,33 @@ static const struct snd_soc_acpi_adr_device rt1316_3_group1_adr[] = { } }; +static const struct snd_soc_acpi_adr_device rt1318_1_group1_adr[] = { + { + .adr = 0x000130025D131801ull, + .num_endpoints = 1, + .endpoints = &spk_l_endpoint, + .name_prefix = "rt1318-1" + } +}; + +static const struct snd_soc_acpi_adr_device rt1318_2_group1_adr[] = { + { + .adr = 0x000232025D131801ull, + .num_endpoints = 1, + .endpoints = &spk_r_endpoint, + .name_prefix = "rt1318-2" + } +}; + +static const struct snd_soc_acpi_adr_device rt714_0_adr[] = { + { + .adr = 0x000030025D071401ull, + .num_endpoints = 1, + .endpoints = &single_endpoint, + .name_prefix = "rt714" + } +}; + static const struct snd_soc_acpi_adr_device rt714_1_adr[] = { { .adr = 0x000130025D071401ull, @@ -195,6 +222,25 @@ static const struct snd_soc_acpi_link_adr lnl_3_in_1_sdca[] = { {} }; +static const struct snd_soc_acpi_link_adr lnl_sdw_rt1318_l12_rt714_l0[] = { + { + .mask = BIT(1), + .num_adr = ARRAY_SIZE(rt1318_1_group1_adr), + .adr_d = rt1318_1_group1_adr, + }, + { + .mask = BIT(2), + .num_adr = ARRAY_SIZE(rt1318_2_group1_adr), + .adr_d = rt1318_2_group1_adr, + }, + { + .mask = BIT(0), + .num_adr = ARRAY_SIZE(rt714_0_adr), + .adr_d = rt714_0_adr, + }, + {} +}; + /* this table is used when there is no I2S codec present */ struct snd_soc_acpi_mach snd_soc_acpi_intel_lnl_sdw_machines[] = { /* mockup tests need to be first */ @@ -240,6 +286,12 @@ struct snd_soc_acpi_mach snd_soc_acpi_intel_lnl_sdw_machines[] = { .drv_name = "sof_sdw", .sof_tplg_filename = "sof-lnl-rt722-l0.tplg", }, + { + .link_mask = GENMASK(2, 0), + .links = lnl_sdw_rt1318_l12_rt714_l0, + .drv_name = "sof_sdw", + .sof_tplg_filename = "sof-lnl-rt1318-l12-rt714-l0.tplg" + }, {}, }; EXPORT_SYMBOL_GPL(snd_soc_acpi_intel_lnl_sdw_machines); -- cgit v1.2.3 From 38068d91cf3948ffa220d45f738505cc9f6e13d0 Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Fri, 26 Apr 2024 10:21:17 -0500 Subject: ASoC: Intel: sof_sdw: Allocate snd_soc_card dynamically The static card_sof_sdw struct is modified during runtime and in case the module is not removed, but the card is, then the next time the card is created the card_sof_sdw will contain information from the previous card which might lead to hard to debug issues, side effects. Move the snd_soc_card into mc_private and use that to make sure that the card is initialized correctly. Reviewed-by: Bard Liao Reviewed-by: Ranjani Sridharan Reviewed-by: Kai Vehmanen Signed-off-by: Peter Ujfalusi Signed-off-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20240426152123.36284-7-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/intel/boards/sof_sdw.c | 20 +++++++++----------- sound/soc/intel/boards/sof_sdw_common.h | 1 + 2 files changed, 10 insertions(+), 11 deletions(-) diff --git a/sound/soc/intel/boards/sof_sdw.c b/sound/soc/intel/boards/sof_sdw.c index d65c5da49000..384c3d41a9ad 100644 --- a/sound/soc/intel/boards/sof_sdw.c +++ b/sound/soc/intel/boards/sof_sdw.c @@ -1882,12 +1882,6 @@ static int sof_sdw_card_late_probe(struct snd_soc_card *card) /* SoC card */ static const char sdw_card_long_name[] = "Intel Soundwire SOF"; -static struct snd_soc_card card_sof_sdw = { - .name = "soundwire", - .owner = THIS_MODULE, - .late_probe = sof_sdw_card_late_probe, -}; - /* helper to get the link that the codec DAI is used */ static struct snd_soc_dai_link *mc_find_codec_dai_used(struct snd_soc_card *card, const char *dai_name) @@ -1939,20 +1933,24 @@ static void mc_dailink_exit_loop(struct snd_soc_card *card) static int mc_probe(struct platform_device *pdev) { - struct snd_soc_card *card = &card_sof_sdw; struct snd_soc_acpi_mach *mach = dev_get_platdata(&pdev->dev); + struct snd_soc_card *card; struct mc_private *ctx; int amp_num = 0, i; int ret; - card->dev = &pdev->dev; - - dev_dbg(card->dev, "Entry\n"); + dev_dbg(&pdev->dev, "Entry\n"); - ctx = devm_kzalloc(card->dev, sizeof(*ctx), GFP_KERNEL); + ctx = devm_kzalloc(&pdev->dev, sizeof(*ctx), GFP_KERNEL); if (!ctx) return -ENOMEM; + card = &ctx->card; + card->dev = &pdev->dev; + card->name = "soundwire", + card->owner = THIS_MODULE, + card->late_probe = sof_sdw_card_late_probe, + snd_soc_card_set_drvdata(card, ctx); dmi_check_system(sof_sdw_quirk_table); diff --git a/sound/soc/intel/boards/sof_sdw_common.h b/sound/soc/intel/boards/sof_sdw_common.h index 89253938ebaa..853278c6e525 100644 --- a/sound/soc/intel/boards/sof_sdw_common.h +++ b/sound/soc/intel/boards/sof_sdw_common.h @@ -101,6 +101,7 @@ struct sof_sdw_codec_info { }; struct mc_private { + struct snd_soc_card card; struct snd_soc_jack sdw_headset; struct sof_hdmi_private hdmi; struct device *headset_codec_dev; /* only one headset per card */ -- cgit v1.2.3 From 2086b55fd6ddcaa92e473ba7017f6a986870337e Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Fri, 26 Apr 2024 10:21:18 -0500 Subject: ASoC: Intel: sof-sdw: don't set card long_name MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit UCM can load a board-specific file based on the card long_name. Remove the constant "Intel Soundwire SOF" long_name so that the ASoC core can set the long_name based on DMI information. Reviewed-by: Ranjani Sridharan Reviewed-by: Péter Ujfalusi Reviewed-by: Bard Liao Signed-off-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20240426152123.36284-8-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/intel/boards/sof_sdw.c | 5 ----- 1 file changed, 5 deletions(-) diff --git a/sound/soc/intel/boards/sof_sdw.c b/sound/soc/intel/boards/sof_sdw.c index 384c3d41a9ad..b9a5fcb42847 100644 --- a/sound/soc/intel/boards/sof_sdw.c +++ b/sound/soc/intel/boards/sof_sdw.c @@ -1879,9 +1879,6 @@ static int sof_sdw_card_late_probe(struct snd_soc_card *card) return ret; } -/* SoC card */ -static const char sdw_card_long_name[] = "Intel Soundwire SOF"; - /* helper to get the link that the codec DAI is used */ static struct snd_soc_dai_link *mc_find_codec_dai_used(struct snd_soc_card *card, const char *dai_name) @@ -1999,8 +1996,6 @@ static int mc_probe(struct platform_device *pdev) return -ENOMEM; } - card->long_name = sdw_card_long_name; - /* Register the card */ ret = devm_snd_soc_register_card(card->dev, card); if (ret) { -- cgit v1.2.3 From 6be269d274353d2604bf49b92f703610cb4734e9 Mon Sep 17 00:00:00 2001 From: Bard Liao Date: Fri, 26 Apr 2024 10:21:19 -0500 Subject: ASoC: Intel: sof_sdw: add a space before cfg-amp in components UCM parse amp with Regex " cfg-amp:([0-9]+)". The "ASoC: Intel: sof_sdw: remove FOUR_SPEAKER quirks" patch removed "cfg-spk:%d " from components which removed the necessary space as well and cause UCM can't parse the amp number properly. Fixes: 744866d28fe6 ("ASoC: Intel: sof_sdw: remove FOUR_SPEAKER quirks") Signed-off-by: Bard Liao Signed-off-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20240426152123.36284-9-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/intel/boards/sof_sdw.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/intel/boards/sof_sdw.c b/sound/soc/intel/boards/sof_sdw.c index b9a5fcb42847..f0622aa1b748 100644 --- a/sound/soc/intel/boards/sof_sdw.c +++ b/sound/soc/intel/boards/sof_sdw.c @@ -1983,7 +1983,7 @@ static int mc_probe(struct platform_device *pdev) amp_num += codec_info_list[i].amp_num; card->components = devm_kasprintf(card->dev, GFP_KERNEL, - "cfg-amp:%d", amp_num); + " cfg-amp:%d", amp_num); if (!card->components) return -ENOMEM; -- cgit v1.2.3 From 0bab4cfd7c1560095e29919e2ebe01783b9096dc Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Fri, 26 Apr 2024 10:21:20 -0500 Subject: ASoC: Intel: sof-sdw: really remove FOUR_SPEAKER quirk Two independent GitHub PRs let to the addition of one quirk after it was removed.. Fixes: b10cb955c6c0 ("ASoC: Intel: sof_sdw: add quirk for Dell SKU 0C0F") Reviewed-by: Bard Liao Signed-off-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20240426152123.36284-10-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/intel/boards/sof_sdw.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/sound/soc/intel/boards/sof_sdw.c b/sound/soc/intel/boards/sof_sdw.c index f0622aa1b748..86bbf1c66ce8 100644 --- a/sound/soc/intel/boards/sof_sdw.c +++ b/sound/soc/intel/boards/sof_sdw.c @@ -421,8 +421,7 @@ static const struct dmi_system_id sof_sdw_quirk_table[] = { DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0C0F") }, .driver_data = (void *)(SOF_SDW_TGL_HDMI | - RT711_JD2 | - SOF_SDW_FOUR_SPK), + RT711_JD2), }, { .callback = sof_sdw_quirk_cb, -- cgit v1.2.3 From 628cc5d0c4bd6a3f70c793968f8e2546afc8c3a3 Mon Sep 17 00:00:00 2001 From: Charles Keepax Date: Fri, 26 Apr 2024 10:21:21 -0500 Subject: ASoC: Intel: sof_sdw: Delay update of the codec_conf array Move the population of the codec_conf array from endpoint parsing time to link creation time. This is slightly cleaner as the population is done whilst the DAI links are also being populated, putting all population together. However, primarily this facilitates allowing additional non-SoundWire devices to be easily added into the array in future feature additions. Reviewed-by: Bard Liao Signed-off-by: Charles Keepax Signed-off-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20240426152123.36284-11-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/intel/boards/sof_sdw.c | 48 ++++++++++++++++++++++------------------ 1 file changed, 27 insertions(+), 21 deletions(-) diff --git a/sound/soc/intel/boards/sof_sdw.c b/sound/soc/intel/boards/sof_sdw.c index 86bbf1c66ce8..bf5f46a4c4aa 100644 --- a/sound/soc/intel/boards/sof_sdw.c +++ b/sound/soc/intel/boards/sof_sdw.c @@ -1279,6 +1279,7 @@ struct sof_sdw_endpoint { u32 link_mask; const char *codec_name; + const char *name_prefix; struct sof_sdw_codec_info *codec_info; const struct sof_sdw_dai_info *dai_info; @@ -1340,7 +1341,6 @@ static int parse_sdw_endpoints(struct snd_soc_card *card, struct mc_private *ctx = snd_soc_card_get_drvdata(card); struct snd_soc_acpi_mach *mach = dev_get_platdata(dev); struct snd_soc_acpi_mach_params *mach_params = &mach->mach_params; - struct snd_soc_codec_conf *codec_conf = card->codec_conf; const struct snd_soc_acpi_link_adr *adr_link; struct sof_sdw_endpoint *sof_end = sof_ends; int num_dais = 0; @@ -1376,13 +1376,11 @@ static int parse_sdw_endpoints(struct snd_soc_card *card, if (!codec_name) return -ENOMEM; - codec_conf->dlc.name = codec_name; - codec_conf->name_prefix = adr_dev->name_prefix; - codec_conf++; - dev_dbg(dev, "Adding prefix %s for %s\n", adr_dev->name_prefix, codec_name); + sof_end->name_prefix = adr_dev->name_prefix; + for (j = 0; j < adr_dev->num_endpoints; j++) { const struct snd_soc_acpi_endpoint *adr_end; const struct sof_sdw_dai_info *dai_info; @@ -1443,21 +1441,27 @@ static int parse_sdw_endpoints(struct snd_soc_card *card, ctx->append_dai_type |= (num_link_dailinks > 1); } - WARN_ON(codec_conf != card->codec_conf + card->num_configs); - return num_dais; } static int create_sdw_dailink(struct snd_soc_card *card, struct sof_sdw_dailink *sof_dai, struct snd_soc_dai_link **dai_links, - int *be_id) + int *be_id, struct snd_soc_codec_conf **codec_conf) { struct device *dev = card->dev; struct mc_private *ctx = snd_soc_card_get_drvdata(card); struct sof_sdw_endpoint *sof_end; int stream; + list_for_each_entry(sof_end, &sof_dai->endpoints, list) { + if (sof_end->name_prefix) { + (*codec_conf)->dlc.name = sof_end->codec_name; + (*codec_conf)->name_prefix = sof_end->name_prefix; + (*codec_conf)++; + } + } + for_each_pcm_streams(stream) { static const char * const sdw_stream_name[] = { "SDW%d-Playback", @@ -1569,7 +1573,8 @@ static int create_sdw_dailink(struct snd_soc_card *card, static int create_sdw_dailinks(struct snd_soc_card *card, struct snd_soc_dai_link **dai_links, int *be_id, - struct sof_sdw_dailink *sof_dais) + struct sof_sdw_dailink *sof_dais, + struct snd_soc_codec_conf **codec_conf) { struct mc_private *ctx = snd_soc_card_get_drvdata(card); int ret, i; @@ -1581,7 +1586,8 @@ static int create_sdw_dailinks(struct snd_soc_card *card, while (sof_dais->initialised) { int current_be_id; - ret = create_sdw_dailink(card, sof_dais, dai_links, ¤t_be_id); + ret = create_sdw_dailink(card, sof_dais, dai_links, + ¤t_be_id, codec_conf); if (ret) return ret; @@ -1751,16 +1757,6 @@ static int sof_card_dai_links_create(struct snd_soc_card *card) goto err_dai; } - /* will be populated when acpi endpoints are parsed */ - codec_conf = devm_kcalloc(dev, num_devs, sizeof(*codec_conf), GFP_KERNEL); - if (!codec_conf) { - ret = -ENOMEM; - goto err_end; - } - - card->codec_conf = codec_conf; - card->num_configs = num_devs; - ret = parse_sdw_endpoints(card, sof_dais, sof_ends); if (ret < 0) goto err_end; @@ -1798,6 +1794,12 @@ static int sof_card_dai_links_create(struct snd_soc_card *card) sdw_be_num, ssp_num, dmic_num, ctx->hdmi.idisp_codec ? hdmi_num : 0, bt_num); + codec_conf = devm_kcalloc(dev, num_devs, sizeof(*codec_conf), GFP_KERNEL); + if (!codec_conf) { + ret = -ENOMEM; + goto err_end; + } + /* allocate BE dailinks */ num_links = sdw_be_num + ssp_num + dmic_num + hdmi_num + bt_num; dai_links = devm_kcalloc(dev, num_links, sizeof(*dai_links), GFP_KERNEL); @@ -1806,12 +1808,15 @@ static int sof_card_dai_links_create(struct snd_soc_card *card) goto err_end; } + card->codec_conf = codec_conf; + card->num_configs = num_devs; card->dai_link = dai_links; card->num_links = num_links; /* SDW */ if (sdw_be_num) { - ret = create_sdw_dailinks(card, &dai_links, &be_id, sof_dais); + ret = create_sdw_dailinks(card, &dai_links, &be_id, + sof_dais, &codec_conf); if (ret) goto err_end; } @@ -1847,6 +1852,7 @@ static int sof_card_dai_links_create(struct snd_soc_card *card) goto err_end; } + WARN_ON(codec_conf != card->codec_conf + card->num_configs); WARN_ON(dai_links != card->dai_link + card->num_links); err_end: -- cgit v1.2.3 From da5244180281a18c4c7859674fec308514aaf629 Mon Sep 17 00:00:00 2001 From: Charles Keepax Date: Fri, 26 Apr 2024 10:21:22 -0500 Subject: ASoC: Intel: sof_sdw: Add callbacks to register sidecar devices Add support for systems that have additional non-SoundWire devices (sidecars) connected to one of the SoundWire devices in the system. This is done through the addition of two callbacks, one used at endpoint parsing time that will return the number of devices and DAI links to be added, and another called later as the DAI links are created that will populate those devices into the appropriate arrays. Reviewed-by: Bard Liao Signed-off-by: Charles Keepax Signed-off-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20240426152123.36284-12-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/intel/boards/sof_sdw.c | 22 ++++++++++++++++++++-- sound/soc/intel/boards/sof_sdw_common.h | 6 ++++++ 2 files changed, 26 insertions(+), 2 deletions(-) diff --git a/sound/soc/intel/boards/sof_sdw.c b/sound/soc/intel/boards/sof_sdw.c index bf5f46a4c4aa..eaa79e29f5c2 100644 --- a/sound/soc/intel/boards/sof_sdw.c +++ b/sound/soc/intel/boards/sof_sdw.c @@ -1280,6 +1280,7 @@ struct sof_sdw_endpoint { u32 link_mask; const char *codec_name; const char *name_prefix; + bool include_sidecar; struct sof_sdw_codec_info *codec_info; const struct sof_sdw_dai_info *dai_info; @@ -1335,7 +1336,8 @@ static struct sof_sdw_dailink *find_dailink(struct sof_sdw_dailink *dailinks, static int parse_sdw_endpoints(struct snd_soc_card *card, struct sof_sdw_dailink *sof_dais, - struct sof_sdw_endpoint *sof_ends) + struct sof_sdw_endpoint *sof_ends, + int *num_devs) { struct device *dev = card->dev; struct mc_private *ctx = snd_soc_card_get_drvdata(card); @@ -1345,6 +1347,7 @@ static int parse_sdw_endpoints(struct snd_soc_card *card, struct sof_sdw_endpoint *sof_end = sof_ends; int num_dais = 0; int i, j; + int ret; for (adr_link = mach_params->links; adr_link->num_adr; adr_link++) { int num_link_dailinks = 0; @@ -1381,6 +1384,14 @@ static int parse_sdw_endpoints(struct snd_soc_card *card, sof_end->name_prefix = adr_dev->name_prefix; + if (codec_info->count_sidecar && codec_info->add_sidecar) { + ret = codec_info->count_sidecar(card, &num_dais, num_devs); + if (ret) + return ret; + + sof_end->include_sidecar = true; + } + for (j = 0; j < adr_dev->num_endpoints; j++) { const struct snd_soc_acpi_endpoint *adr_end; const struct sof_sdw_dai_info *dai_info; @@ -1453,6 +1464,7 @@ static int create_sdw_dailink(struct snd_soc_card *card, struct mc_private *ctx = snd_soc_card_get_drvdata(card); struct sof_sdw_endpoint *sof_end; int stream; + int ret; list_for_each_entry(sof_end, &sof_dai->endpoints, list) { if (sof_end->name_prefix) { @@ -1460,6 +1472,12 @@ static int create_sdw_dailink(struct snd_soc_card *card, (*codec_conf)->name_prefix = sof_end->name_prefix; (*codec_conf)++; } + + if (sof_end->include_sidecar) { + ret = sof_end->codec_info->add_sidecar(card, dai_links, codec_conf); + if (ret) + return ret; + } } for_each_pcm_streams(stream) { @@ -1757,7 +1775,7 @@ static int sof_card_dai_links_create(struct snd_soc_card *card) goto err_dai; } - ret = parse_sdw_endpoints(card, sof_dais, sof_ends); + ret = parse_sdw_endpoints(card, sof_dais, sof_ends, &num_devs); if (ret < 0) goto err_end; diff --git a/sound/soc/intel/boards/sof_sdw_common.h b/sound/soc/intel/boards/sof_sdw_common.h index 853278c6e525..9dd42a8da8d7 100644 --- a/sound/soc/intel/boards/sof_sdw_common.h +++ b/sound/soc/intel/boards/sof_sdw_common.h @@ -98,6 +98,12 @@ struct sof_sdw_codec_info { const int dai_num; int (*codec_card_late_probe)(struct snd_soc_card *card); + + int (*count_sidecar)(struct snd_soc_card *card, + int *num_dais, int *num_devs); + int (*add_sidecar)(struct snd_soc_card *card, + struct snd_soc_dai_link **dai_links, + struct snd_soc_codec_conf **codec_conf); }; struct mc_private { -- cgit v1.2.3 From b831b4dca48dbe0f1f7705b44460dd9ca7f2f940 Mon Sep 17 00:00:00 2001 From: Maciej Strozek Date: Fri, 26 Apr 2024 10:21:23 -0500 Subject: ASoC: intel: sof_sdw: Add support for cs42l43-cs35l56 sidecar amps The cs42l43 has both a SPI master and an I2S interface, these can be used to populate 2 cs35l56 amplifiers as sidecar devices along side the cs42l43. Giving a system that looks like: +-----+ +---------+ <- SPI -> +---------+ | CPU | <- SDW -> | CS42L43 | | CS35L56 | +-----+ +---------+ <- I2S -> +---------+ Add a quirk to specify this feature is present and use it to add codec to codec DAI link to connect the amplifiers into the sound card, add appropriate widgets, and setup clocking on the amplifiers. Reviewed-by: Bard Liao Signed-off-by: Maciej Strozek Signed-off-by: Charles Keepax Signed-off-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20240426152123.36284-13-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/intel/boards/Kconfig | 1 + sound/soc/intel/boards/Makefile | 1 + sound/soc/intel/boards/bridge_cs35l56.c | 137 +++++++++++++++++++++++++++++++ sound/soc/intel/boards/sof_sdw.c | 6 +- sound/soc/intel/boards/sof_sdw_common.h | 20 +++++ sound/soc/intel/boards/sof_sdw_cs42l43.c | 14 ++-- 6 files changed, 173 insertions(+), 6 deletions(-) create mode 100644 sound/soc/intel/boards/bridge_cs35l56.c diff --git a/sound/soc/intel/boards/Kconfig b/sound/soc/intel/boards/Kconfig index 0ad7b0a1e237..b122b8aedd9a 100644 --- a/sound/soc/intel/boards/Kconfig +++ b/sound/soc/intel/boards/Kconfig @@ -690,6 +690,7 @@ config SND_SOC_INTEL_SOUNDWIRE_SOF_MACH select SND_SOC_CS42L43_SDW select MFD_CS42L43 select MFD_CS42L43_SDW + select SND_SOC_CS35L56_SPI select SND_SOC_CS35L56_SDW select SND_SOC_DMIC select SND_SOC_INTEL_HDA_DSP_COMMON diff --git a/sound/soc/intel/boards/Makefile b/sound/soc/intel/boards/Makefile index 119413c262de..1c099e717eca 100644 --- a/sound/soc/intel/boards/Makefile +++ b/sound/soc/intel/boards/Makefile @@ -37,6 +37,7 @@ snd-soc-ehl-rt5660-objs := ehl_rt5660.o snd-soc-sof-ssp-amp-objs := sof_ssp_amp.o snd-soc-sof-sdw-objs += sof_sdw.o \ sof_sdw_maxim.o sof_sdw_rt_amp.o \ + bridge_cs35l56.o \ sof_sdw_rt5682.o sof_sdw_rt700.o \ sof_sdw_rt711.o sof_sdw_rt_sdca_jack_common.o \ sof_sdw_rt712_sdca.o sof_sdw_rt722_sdca.o \ diff --git a/sound/soc/intel/boards/bridge_cs35l56.c b/sound/soc/intel/boards/bridge_cs35l56.c new file mode 100644 index 000000000000..c3995e724aed --- /dev/null +++ b/sound/soc/intel/boards/bridge_cs35l56.c @@ -0,0 +1,137 @@ +// SPDX-License-Identifier: GPL-2.0-only +// +// Intel SOF Machine Driver with Cirrus Logic CS35L56 Smart Amp + +#include +#include +#include +#include +#include +#include +#include +#include "sof_sdw_common.h" + +static const struct snd_soc_dapm_widget bridge_widgets[] = { + SND_SOC_DAPM_SPK("Bridge Speaker", NULL), +}; + +static const struct snd_soc_dapm_route bridge_map[] = { + {"Bridge Speaker", NULL, "AMPL SPK"}, + {"Bridge Speaker", NULL, "AMPR SPK"}, +}; + +static const char * const bridge_cs35l56_name_prefixes[] = { + "AMPL", + "AMPR", +}; + +static int bridge_cs35l56_asp_init(struct snd_soc_pcm_runtime *rtd) +{ + struct snd_soc_card *card = rtd->card; + int i, ret; + unsigned int rx_mask = 3; // ASP RX1, RX2 + unsigned int tx_mask = 3; // ASP TX1, TX2 + struct snd_soc_dai *codec_dai; + struct snd_soc_dai *cpu_dai; + + card->components = devm_kasprintf(card->dev, GFP_KERNEL, + "%s spk:cs35l56-bridge", + card->components); + if (!card->components) + return -ENOMEM; + + ret = snd_soc_dapm_new_controls(&card->dapm, bridge_widgets, + ARRAY_SIZE(bridge_widgets)); + if (ret) { + dev_err(card->dev, "widgets addition failed: %d\n", ret); + return ret; + } + + ret = snd_soc_dapm_add_routes(&card->dapm, bridge_map, ARRAY_SIZE(bridge_map)); + if (ret) { + dev_err(card->dev, "map addition failed: %d\n", ret); + return ret; + } + + /* 4 x 16-bit sample slots and FSYNC=48000, BCLK=3.072 MHz */ + for_each_rtd_codec_dais(rtd, i, codec_dai) { + ret = snd_soc_dai_set_tdm_slot(codec_dai, tx_mask, rx_mask, 4, 16); + if (ret < 0) + return ret; + + ret = snd_soc_dai_set_sysclk(codec_dai, 0, 3072000, SND_SOC_CLOCK_IN); + if (ret < 0) + return ret; + } + + for_each_rtd_cpu_dais(rtd, i, cpu_dai) { + ret = snd_soc_dai_set_tdm_slot(cpu_dai, tx_mask, rx_mask, 4, 16); + if (ret < 0) + return ret; + } + + return 0; +} + +static const struct snd_soc_pcm_stream bridge_params = { + .formats = SNDRV_PCM_FMTBIT_S16_LE, + .rate_min = 48000, + .rate_max = 48000, + .channels_min = 2, + .channels_max = 2, +}; + +SND_SOC_DAILINK_DEFS(bridge_dai, + DAILINK_COMP_ARRAY(COMP_CODEC("cs42l43-codec", "cs42l43-asp")), + DAILINK_COMP_ARRAY(COMP_CODEC("spi-cs35l56-left", "cs35l56-asp1"), + COMP_CODEC("spi-cs35l56-right", "cs35l56-asp1")), + DAILINK_COMP_ARRAY(COMP_PLATFORM("cs42l43-codec"))); + +static const struct snd_soc_dai_link bridge_dai_template = { + .name = "cs42l43-cs35l56", + .init = bridge_cs35l56_asp_init, + .c2c_params = &bridge_params, + .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_IB_IF | SND_SOC_DAIFMT_CBC_CFC, + SND_SOC_DAILINK_REG(bridge_dai), +}; + +int bridge_cs35l56_count_sidecar(struct snd_soc_card *card, + int *num_dais, int *num_devs) +{ + if (sof_sdw_quirk & SOF_SIDECAR_AMPS) { + (*num_dais)++; + (*num_devs) += ARRAY_SIZE(bridge_cs35l56_name_prefixes); + } + + return 0; +} + +int bridge_cs35l56_add_sidecar(struct snd_soc_card *card, + struct snd_soc_dai_link **dai_links, + struct snd_soc_codec_conf **codec_conf) +{ + if (sof_sdw_quirk & SOF_SIDECAR_AMPS) { + **dai_links = bridge_dai_template; + + for (int i = 0; i < ARRAY_SIZE(bridge_cs35l56_name_prefixes); i++) { + (*codec_conf)->dlc.name = (*dai_links)->codecs[i].name; + (*codec_conf)->name_prefix = bridge_cs35l56_name_prefixes[i]; + (*codec_conf)++; + } + + (*dai_links)++; + } + + return 0; +} + +int bridge_cs35l56_spk_init(struct snd_soc_card *card, + struct snd_soc_dai_link *dai_links, + struct sof_sdw_codec_info *info, + bool playback) +{ + if (sof_sdw_quirk & SOF_SIDECAR_AMPS) + info->amp_num += ARRAY_SIZE(bridge_cs35l56_name_prefixes); + + return 0; +} diff --git a/sound/soc/intel/boards/sof_sdw.c b/sound/soc/intel/boards/sof_sdw.c index eaa79e29f5c2..b1595fdb500d 100644 --- a/sound/soc/intel/boards/sof_sdw.c +++ b/sound/soc/intel/boards/sof_sdw.c @@ -39,6 +39,8 @@ static void log_quirks(struct device *dev) dev_err(dev, "quirk SOF_SDW_NO_AGGREGATION enabled but no longer supported\n"); if (sof_sdw_quirk & SOF_CODEC_SPKR) dev_dbg(dev, "quirk SOF_CODEC_SPKR enabled\n"); + if (sof_sdw_quirk & SOF_SIDECAR_AMPS) + dev_dbg(dev, "quirk SOF_SIDECAR_AMPS enabled\n"); } static int sof_sdw_quirk_cb(const struct dmi_system_id *id) @@ -995,6 +997,8 @@ static struct sof_sdw_codec_info codec_info_list[] = { { .part_id = 0x4243, .codec_name = "cs42l43-codec", + .count_sidecar = bridge_cs35l56_count_sidecar, + .add_sidecar = bridge_cs35l56_add_sidecar, .dais = { { .direction = {true, false}, @@ -1023,7 +1027,7 @@ static struct sof_sdw_codec_info codec_info_list[] = { .dailink = {SDW_AMP_OUT_DAI_ID, SDW_UNUSED_DAI_ID}, .init = sof_sdw_cs42l43_spk_init, .rtd_init = cs42l43_spk_rtd_init, - .quirk = SOF_CODEC_SPKR, + .quirk = SOF_CODEC_SPKR | SOF_SIDECAR_AMPS, }, }, .dai_num = 4, diff --git a/sound/soc/intel/boards/sof_sdw_common.h b/sound/soc/intel/boards/sof_sdw_common.h index 9dd42a8da8d7..94657dd210f5 100644 --- a/sound/soc/intel/boards/sof_sdw_common.h +++ b/sound/soc/intel/boards/sof_sdw_common.h @@ -55,6 +55,16 @@ enum { #define SOF_SDW_NO_AGGREGATION BIT(14) /* If a CODEC has an optional speaker output, this quirk will enable it */ #define SOF_CODEC_SPKR BIT(15) +/* + * If the CODEC has additional devices attached directly to it. + * + * For the cs42l43: + * - 0 - No speaker output + * - SOF_CODEC_SPKR - CODEC internal speaker + * - SOF_SIDECAR_AMPS - 2x Sidecar amplifiers + CODEC internal speaker + * - SOF_CODEC_SPKR | SOF_SIDECAR_AMPS - Not currently supported + */ +#define SOF_SIDECAR_AMPS BIT(16) /* BT audio offload: reserve 3 bits for future */ #define SOF_BT_OFFLOAD_SSP_SHIFT 15 @@ -177,6 +187,16 @@ int sof_sdw_cs42l43_spk_init(struct snd_soc_card *card, bool playback); /* CS AMP support */ +int bridge_cs35l56_count_sidecar(struct snd_soc_card *card, + int *num_dais, int *num_devs); +int bridge_cs35l56_add_sidecar(struct snd_soc_card *card, + struct snd_soc_dai_link **dai_links, + struct snd_soc_codec_conf **codec_conf); +int bridge_cs35l56_spk_init(struct snd_soc_card *card, + struct snd_soc_dai_link *dai_links, + struct sof_sdw_codec_info *info, + bool playback); + int sof_sdw_cs_amp_init(struct snd_soc_card *card, struct snd_soc_dai_link *dai_links, struct sof_sdw_codec_info *info, diff --git a/sound/soc/intel/boards/sof_sdw_cs42l43.c b/sound/soc/intel/boards/sof_sdw_cs42l43.c index 5361249f0f53..0fd5e099bb1a 100644 --- a/sound/soc/intel/boards/sof_sdw_cs42l43.c +++ b/sound/soc/intel/boards/sof_sdw_cs42l43.c @@ -124,10 +124,14 @@ int cs42l43_spk_rtd_init(struct snd_soc_pcm_runtime *rtd) struct snd_soc_card *card = rtd->card; int ret; - card->components = devm_kasprintf(card->dev, GFP_KERNEL, "%s spk:cs42l43-spk", - card->components); - if (!card->components) - return -ENOMEM; + if (!(sof_sdw_quirk & SOF_SIDECAR_AMPS)) { + /* Will be set by the bridge code in this case */ + card->components = devm_kasprintf(card->dev, GFP_KERNEL, + "%s spk:cs42l43-spk", + card->components); + if (!card->components) + return -ENOMEM; + } ret = snd_soc_dapm_new_controls(&card->dapm, cs42l43_spk_widgets, ARRAY_SIZE(cs42l43_spk_widgets)); @@ -155,7 +159,7 @@ int sof_sdw_cs42l43_spk_init(struct snd_soc_card *card, info->amp_num++; - return 0; + return bridge_cs35l56_spk_init(card, dai_links, info, playback); } int cs42l43_dmic_rtd_init(struct snd_soc_pcm_runtime *rtd) -- cgit v1.2.3 From b32487ca7b51ce430f15ec785269f11c25a6a560 Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Fri, 26 Apr 2024 10:38:58 -0500 Subject: ASoC: SOF: debug: Handle cases when fw_lib_prefix is not set, NULL The firmware libraries are not supported by IPC3, the fw_lib_path is not a valid parameter and it is always NULL. Do not create the debugfs file for IPC3 at all as it is not applicable. With IPC4 some vendors/platforms might not support loadable libraries and the fw_lib_prefix is left to NULL to indicate this. Handle such case with allocating "Not supported" string. Reviewed-by: Marc Herbert Fixes: 17f4041244e6 ("ASoC: SOF: debug: show firmware/topology prefix/names") Signed-off-by: Peter Ujfalusi Signed-off-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20240426153902.39560-2-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/debug.c | 23 +++++++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) diff --git a/sound/soc/sof/debug.c b/sound/soc/sof/debug.c index cf282c8b18af..bf635cc96ede 100644 --- a/sound/soc/sof/debug.c +++ b/sound/soc/sof/debug.c @@ -326,8 +326,27 @@ int snd_sof_dbg_init(struct snd_sof_dev *sdev) debugfs_create_str("fw_path", 0444, fw_profile, (char **)&plat_data->fw_filename_prefix); - debugfs_create_str("fw_lib_path", 0444, fw_profile, - (char **)&plat_data->fw_lib_prefix); + /* library path is not valid for IPC3 */ + if (plat_data->ipc_type != SOF_IPC_TYPE_3) { + /* + * fw_lib_prefix can be NULL if the vendor/platform does not + * support loadable libraries + */ + if (plat_data->fw_lib_prefix) { + debugfs_create_str("fw_lib_path", 0444, fw_profile, + (char **)&plat_data->fw_lib_prefix); + } else { + static char *fw_lib_path; + + fw_lib_path = devm_kasprintf(sdev->dev, GFP_KERNEL, + "Not supported"); + if (!fw_lib_path) + return -ENOMEM; + + debugfs_create_str("fw_lib_path", 0444, fw_profile, + (char **)&fw_lib_path); + } + } debugfs_create_str("tplg_path", 0444, fw_profile, (char **)&plat_data->tplg_filename_prefix); debugfs_create_str("fw_name", 0444, fw_profile, -- cgit v1.2.3 From 490e6c9b81e0c22087d250246717aee26ac5002e Mon Sep 17 00:00:00 2001 From: Yong Zhi Date: Fri, 26 Apr 2024 10:38:59 -0500 Subject: ASoC: SOF: topology: remove incorrect widget id in error message In sof_widget_ready() function, the shift field of struct snd_soc_tplg_dapm_widget is incorrectly used to print widget id in dev_err(scomp->dev, "error: failed to add widget id %d ..", this patch removes the useless tw->shift from the error output. Reviewed-by: Ranjani Sridharan Signed-off-by: Yong Zhi Signed-off-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20240426153902.39560-3-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/topology.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/sound/soc/sof/topology.c b/sound/soc/sof/topology.c index bcdb499c96a0..ec931a26b54f 100644 --- a/sound/soc/sof/topology.c +++ b/sound/soc/sof/topology.c @@ -1531,10 +1531,9 @@ static int sof_widget_ready(struct snd_soc_component *scomp, int index, /* check token parsing reply */ if (ret < 0) { dev_err(scomp->dev, - "error: failed to add widget id %d type %d name : %s stream %s\n", - tw->shift, swidget->id, tw->name, - strnlen(tw->sname, SNDRV_CTL_ELEM_ID_NAME_MAXLEN) > 0 - ? tw->sname : "none"); + "failed to add widget type %d name : %s stream %s\n", + swidget->id, tw->name, strnlen(tw->sname, SNDRV_CTL_ELEM_ID_NAME_MAXLEN) > 0 + ? tw->sname : "none"); goto widget_free; } -- cgit v1.2.3 From 5d4788b2647fabeaeeaf331e53451e0ed6241252 Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Fri, 26 Apr 2024 10:39:00 -0500 Subject: ASoC: SOF: Intel: hda: simplify and reduce indentation for hda_sdw_machine_select() Simplify code to return when no links are enabled. No functional change, just code cleanup before updates. Signed-off-by: Pierre-Louis Bossart Reviewed-by: Bard Liao Link: https://lore.kernel.org/r/20240426153902.39560-4-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/intel/hda.c | 143 +++++++++++++++++++++++----------------------- 1 file changed, 73 insertions(+), 70 deletions(-) diff --git a/sound/soc/sof/intel/hda.c b/sound/soc/sof/intel/hda.c index 2fc10bec7331..d69cafc2d313 100644 --- a/sound/soc/sof/intel/hda.c +++ b/sound/soc/sof/intel/hda.c @@ -1653,92 +1653,95 @@ static struct snd_soc_acpi_mach *hda_sdw_machine_select(struct snd_sof_dev *sdev hdev = pdata->hw_pdata; link_mask = hdev->info.link_mask; + if (!link_mask) { + dev_info(sdev->dev, "SoundWire links not enabled\n"); + return NULL; + } + /* * Select SoundWire machine driver if needed using the * alternate tables. This case deals with SoundWire-only * machines, for mixed cases with I2C/I2S the detection relies * on the HID list. */ - if (link_mask) { - for (mach = pdata->desc->alt_machines; - mach && mach->link_mask; mach++) { - /* - * On some platforms such as Up Extreme all links - * are enabled but only one link can be used by - * external codec. Instead of exact match of two masks, - * first check whether link_mask of mach is subset of - * link_mask supported by hw and then go on searching - * link_adr - */ - if (~link_mask & mach->link_mask) - continue; - - /* No need to match adr if there is no links defined */ - if (!mach->links) - break; - - link = mach->links; - for (i = 0; i < hdev->info.count && link->num_adr; - i++, link++) { - /* - * Try next machine if any expected Slaves - * are not found on this link. - */ - if (!snd_soc_acpi_sdw_link_slaves_found(sdev->dev, link, - hdev->sdw->ids, - hdev->sdw->num_slaves)) - break; - } - /* Found if all Slaves are checked */ - if (i == hdev->info.count || !link->num_adr) - break; - } - if (mach && mach->link_mask) { - int dmic_num = 0; - bool tplg_fixup; - const char *tplg_filename; - - mach->mach_params.links = mach->links; - mach->mach_params.link_mask = mach->link_mask; - mach->mach_params.platform = dev_name(sdev->dev); + for (mach = pdata->desc->alt_machines; + mach && mach->link_mask; mach++) { + /* + * On some platforms such as Up Extreme all links + * are enabled but only one link can be used by + * external codec. Instead of exact match of two masks, + * first check whether link_mask of mach is subset of + * link_mask supported by hw and then go on searching + * link_adr + */ + if (~link_mask & mach->link_mask) + continue; - if (pdata->tplg_filename) { - tplg_fixup = false; - } else { - tplg_fixup = true; - tplg_filename = mach->sof_tplg_filename; - } + /* No need to match adr if there is no links defined */ + if (!mach->links) + break; + link = mach->links; + for (i = 0; i < hdev->info.count && link->num_adr; + i++, link++) { /* - * DMICs use up to 4 pins and are typically pin-muxed with SoundWire - * link 2 and 3, or link 1 and 2, thus we only try to enable dmics - * if all conditions are true: - * a) 2 or fewer links are used by SoundWire - * b) the NHLT table reports the presence of microphones + * Try next machine if any expected Slaves + * are not found on this link. */ - if (hweight_long(mach->link_mask) <= 2) { - int ret; - - ret = dmic_detect_topology_fixup(sdev, &tplg_filename, "", - &dmic_num, tplg_fixup); - if (ret < 0) - return NULL; - } - if (tplg_fixup) - pdata->tplg_filename = tplg_filename; - mach->mach_params.dmic_num = dmic_num; + if (!snd_soc_acpi_sdw_link_slaves_found(sdev->dev, link, + hdev->sdw->ids, + hdev->sdw->num_slaves)) + break; + } + /* Found if all Slaves are checked */ + if (i == hdev->info.count || !link->num_adr) + break; + } + if (mach && mach->link_mask) { + int dmic_num = 0; + bool tplg_fixup; + const char *tplg_filename; + + mach->mach_params.links = mach->links; + mach->mach_params.link_mask = mach->link_mask; + mach->mach_params.platform = dev_name(sdev->dev); + + if (pdata->tplg_filename) { + tplg_fixup = false; + } else { + tplg_fixup = true; + tplg_filename = mach->sof_tplg_filename; + } - dev_dbg(sdev->dev, - "SoundWire machine driver %s topology %s\n", - mach->drv_name, - pdata->tplg_filename); + /* + * DMICs use up to 4 pins and are typically pin-muxed with SoundWire + * link 2 and 3, or link 1 and 2, thus we only try to enable dmics + * if all conditions are true: + * a) 2 or fewer links are used by SoundWire + * b) the NHLT table reports the presence of microphones + */ + if (hweight_long(mach->link_mask) <= 2) { + int ret; - return mach; + ret = dmic_detect_topology_fixup(sdev, &tplg_filename, "", + &dmic_num, tplg_fixup); + if (ret < 0) + return NULL; } + if (tplg_fixup) + pdata->tplg_filename = tplg_filename; + mach->mach_params.dmic_num = dmic_num; - dev_info(sdev->dev, "No SoundWire machine driver found\n"); + dev_dbg(sdev->dev, + "SoundWire machine driver %s topology %s\n", + mach->drv_name, + pdata->tplg_filename); + + return mach; } + dev_info(sdev->dev, "No SoundWire machine driver found\n"); + return NULL; } #else -- cgit v1.2.3 From 7ff01ca730f240811c13d9c3f8f8030211b3c911 Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Fri, 26 Apr 2024 10:39:01 -0500 Subject: ASoC: SOF: Intel: hda: list SoundWire peripherals on mismatch Most of the SoundWire support issues come from bad ACPI information, or configuration reported by ACPI that are not supported by the SOF driver/topology. The users see a "No SoundWire machine driver found" message without any details, and the fallback to HDaudio w/ HDMI is used. We can reduce our support load with a clear dev_info() log that will give us a clear hint on the mismatch and why a machine driver/topology were not found. Example log on a MTL device: [ 13.158599] sof-audio-pci-intel-mtl 0000:00:1f.3: No SoundWire machine driver found for the ACPI-reported configuration: [ 13.158603] sof-audio-pci-intel-mtl 0000:00:1f.3: link 0 mfg_id 0x025d part_id 0x0713 version 0x3 [ 13.158606] sof-audio-pci-intel-mtl 0000:00:1f.3: link 1 mfg_id 0x025d part_id 0x1316 version 0x3 [ 13.158608] sof-audio-pci-intel-mtl 0000:00:1f.3: link 2 mfg_id 0x025d part_id 0x1316 version 0x3 In parallel, we will also provide an update to `alsa-info` to log all SoundWire peripherals found in ACPI tables. Signed-off-by: Pierre-Louis Bossart Reviewed-by: Bard Liao Link: https://lore.kernel.org/r/20240426153902.39560-5-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/intel/hda.c | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/sound/soc/sof/intel/hda.c b/sound/soc/sof/intel/hda.c index d69cafc2d313..d509cfa38a64 100644 --- a/sound/soc/sof/intel/hda.c +++ b/sound/soc/sof/intel/hda.c @@ -1645,6 +1645,7 @@ static struct snd_soc_acpi_mach *hda_sdw_machine_select(struct snd_sof_dev *sdev { struct snd_sof_pdata *pdata = sdev->pdata; const struct snd_soc_acpi_link_adr *link; + struct sdw_extended_slave_id *ids; struct snd_soc_acpi_mach *mach; struct sof_intel_hda_dev *hdev; u32 link_mask; @@ -1658,6 +1659,16 @@ static struct snd_soc_acpi_mach *hda_sdw_machine_select(struct snd_sof_dev *sdev return NULL; } + if (!hdev->sdw) { + dev_dbg(sdev->dev, "SoundWire context not allocated\n"); + return NULL; + } + + if (!hdev->sdw->num_slaves) { + dev_warn(sdev->dev, "No SoundWire peripheral detected in ACPI tables\n"); + return NULL; + } + /* * Select SoundWire machine driver if needed using the * alternate tables. This case deals with SoundWire-only @@ -1740,7 +1751,11 @@ static struct snd_soc_acpi_mach *hda_sdw_machine_select(struct snd_sof_dev *sdev return mach; } - dev_info(sdev->dev, "No SoundWire machine driver found\n"); + dev_info(sdev->dev, "No SoundWire machine driver found for the ACPI-reported configuration:\n"); + ids = hdev->sdw->ids; + for (i = 0; i < hdev->sdw->num_slaves; i++) + dev_info(sdev->dev, "link %d mfg_id 0x%04x part_id 0x%04x version %#x\n", + ids[i].link_id, ids[i].id.mfg_id, ids[i].id.part_id, ids[i].id.sdw_version); return NULL; } -- cgit v1.2.3 From eed4872a4220f30de37aeca695d2881630410b66 Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Fri, 26 Apr 2024 10:39:02 -0500 Subject: ASoC: SOF: ipc4-topology: Advertise passthrough capable PCMs (using ChainDMA) If a PCM is set to use ChainDMA then add it to the card->components string after a marker of iec61937-pcm:, for example on current HDA platforms where HDMI is set to use ChainDMA: iec61937-pcm:5,4,3 (the order of the PCM ids can differ) UCM is expected to parse and use this property to allow applications to use bytestream passthrough in a standard way. Reviewed-by: Ranjani Sridharan Signed-off-by: Peter Ujfalusi Signed-off-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20240426153902.39560-6-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/ipc4-topology.c | 50 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 50 insertions(+) diff --git a/sound/soc/sof/ipc4-topology.c b/sound/soc/sof/ipc4-topology.c index c29c1de4e925..a972b2b5122a 100644 --- a/sound/soc/sof/ipc4-topology.c +++ b/sound/soc/sof/ipc4-topology.c @@ -407,6 +407,52 @@ static void sof_ipc4_widget_update_kcontrol_module_id(struct snd_sof_widget *swi } } +static int +sof_ipc4_update_card_components_string(struct snd_sof_widget *swidget, + struct snd_sof_pcm *spcm, int dir) +{ + struct snd_sof_widget *pipe_widget = swidget->spipe->pipe_widget; + struct sof_ipc4_pipeline *pipeline = pipe_widget->private; + struct snd_soc_component *scomp = spcm->scomp; + struct snd_soc_card *card = scomp->card; + const char *pt_marker = "iec61937-pcm"; + + /* + * Update the card's components list with iec61937-pcm and a list of PCM + * ids where ChainDMA is enabled. + * These PCMs can be used for bytestream passthrough. + */ + if (!pipeline->use_chain_dma) + return 0; + + if (card->components) { + const char *tmp = card->components; + + if (strstr(card->components, pt_marker)) + card->components = devm_kasprintf(card->dev, GFP_KERNEL, + "%s,%d", + card->components, + spcm->pcm.pcm_id); + else + card->components = devm_kasprintf(card->dev, GFP_KERNEL, + "%s %s:%d", + card->components, + pt_marker, + spcm->pcm.pcm_id); + + devm_kfree(card->dev, tmp); + } else { + card->components = devm_kasprintf(card->dev, GFP_KERNEL, + "%s:%d", pt_marker, + spcm->pcm.pcm_id); + } + + if (!card->components) + return -ENOMEM; + + return 0; +} + static int sof_ipc4_widget_setup_pcm(struct snd_sof_widget *swidget) { struct sof_ipc4_available_audio_format *available_fmt; @@ -452,6 +498,10 @@ static int sof_ipc4_widget_setup_pcm(struct snd_sof_widget *swidget) if (!spcm) goto skip_gtw_cfg; + ret = sof_ipc4_update_card_components_string(swidget, spcm, dir); + if (ret) + goto free_available_fmt; + if (dir == SNDRV_PCM_STREAM_PLAYBACK) { struct snd_sof_pcm_stream *sps = &spcm->stream[dir]; -- cgit v1.2.3 From ffca099bbff1978bc9c97b076f0d35b4fe6ddf27 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Fri, 26 Apr 2024 11:03:48 +0200 Subject: ASoC: SOF: debug: Constify local snd_sof_dsp_ops Constify the pointer to 'struct snd_sof_dsp_ops' to annotate that functioon does not modify pointed data. Tested-by: Pierre-Louis Bossart Signed-off-by: Krzysztof Kozlowski Link: https://lore.kernel.org/r/20240426-n-const-ops-var-v2-1-e553fe67ae82@kernel.org Signed-off-by: Mark Brown --- sound/soc/sof/debug.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/sof/debug.c b/sound/soc/sof/debug.c index cf282c8b18af..884d85770426 100644 --- a/sound/soc/sof/debug.c +++ b/sound/soc/sof/debug.c @@ -311,8 +311,8 @@ EXPORT_SYMBOL_GPL(snd_sof_dbg_memory_info_init); int snd_sof_dbg_init(struct snd_sof_dev *sdev) { + const struct snd_sof_dsp_ops *ops = sof_ops(sdev); struct snd_sof_pdata *plat_data = sdev->pdata; - struct snd_sof_dsp_ops *ops = sof_ops(sdev); const struct snd_sof_debugfs_map *map; struct dentry *fw_profile; int i; -- cgit v1.2.3 From ee5acc1e035ec5ed5d9f0f63fda9d627220090c2 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Fri, 26 Apr 2024 11:03:49 +0200 Subject: ASoC: SOF: ipc3: Constify local snd_sof_dsp_ops Constify the pointer to 'struct snd_sof_dsp_ops' to annotate that functioon does not modify pointed data. Tested-by: Pierre-Louis Bossart Signed-off-by: Krzysztof Kozlowski Link: https://lore.kernel.org/r/20240426-n-const-ops-var-v2-2-e553fe67ae82@kernel.org Signed-off-by: Mark Brown --- sound/soc/sof/ipc3-priv.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/sound/soc/sof/ipc3-priv.h b/sound/soc/sof/ipc3-priv.h index 0bbca418e67e..9cd7794f3cb6 100644 --- a/sound/soc/sof/ipc3-priv.h +++ b/sound/soc/sof/ipc3-priv.h @@ -36,7 +36,7 @@ static inline int sof_dtrace_host_init(struct snd_sof_dev *sdev, struct snd_dma_buffer *dmatb, struct sof_ipc_dma_trace_params_ext *dtrace_params) { - struct snd_sof_dsp_ops *dsp_ops = sdev->pdata->desc->ops; + const struct snd_sof_dsp_ops *dsp_ops = sdev->pdata->desc->ops; if (dsp_ops->trace_init) return dsp_ops->trace_init(sdev, dmatb, dtrace_params); @@ -46,7 +46,7 @@ static inline int sof_dtrace_host_init(struct snd_sof_dev *sdev, static inline int sof_dtrace_host_release(struct snd_sof_dev *sdev) { - struct snd_sof_dsp_ops *dsp_ops = sdev->pdata->desc->ops; + const struct snd_sof_dsp_ops *dsp_ops = sdev->pdata->desc->ops; if (dsp_ops->trace_release) return dsp_ops->trace_release(sdev); @@ -56,7 +56,7 @@ static inline int sof_dtrace_host_release(struct snd_sof_dev *sdev) static inline int sof_dtrace_host_trigger(struct snd_sof_dev *sdev, int cmd) { - struct snd_sof_dsp_ops *dsp_ops = sdev->pdata->desc->ops; + const struct snd_sof_dsp_ops *dsp_ops = sdev->pdata->desc->ops; if (dsp_ops->trace_trigger) return dsp_ops->trace_trigger(sdev, cmd); -- cgit v1.2.3 From a0db037df9630edad76153c7937c6f5ca04ed44f Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Fri, 26 Apr 2024 11:03:50 +0200 Subject: ASoC: SOF: pcm: Constify local snd_sof_dsp_ops Constify the pointer to 'struct snd_sof_dsp_ops' to annotate that functioon does not modify pointed data. Tested-by: Pierre-Louis Bossart Signed-off-by: Krzysztof Kozlowski Link: https://lore.kernel.org/r/20240426-n-const-ops-var-v2-3-e553fe67ae82@kernel.org Signed-off-by: Mark Brown --- sound/soc/sof/pcm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/sof/pcm.c b/sound/soc/sof/pcm.c index 8fca4b0d63de..cb774e011e31 100644 --- a/sound/soc/sof/pcm.c +++ b/sound/soc/sof/pcm.c @@ -423,7 +423,7 @@ static int sof_pcm_open(struct snd_soc_component *component, struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream); struct snd_pcm_runtime *runtime = substream->runtime; struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(component); - struct snd_sof_dsp_ops *ops = sof_ops(sdev); + const struct snd_sof_dsp_ops *ops = sof_ops(sdev); struct snd_sof_pcm *spcm; struct snd_soc_tplg_stream_caps *caps; int ret; -- cgit v1.2.3 From 8bbc692d1abce5bc949dea9acba85fc686601c04 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Fri, 26 Apr 2024 11:03:51 +0200 Subject: ASoC: SOF: Constify stored pointer to snd_sof_dsp_ops The core code does not modify the 'struct snd_sof_dsp_ops', stored in 'struct sof_dev_desc'. Make the pointer to 'struct snd_sof_dsp_ops' const to annotate this, make code a bit safer and allow individual drivers to also define this structure as const. Tested-by: Pierre-Louis Bossart Signed-off-by: Krzysztof Kozlowski Link: https://lore.kernel.org/r/20240426-n-const-ops-var-v2-4-e553fe67ae82@kernel.org Signed-off-by: Mark Brown --- include/sound/sof.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/sound/sof.h b/include/sound/sof.h index 05213bb515a3..780c1a755917 100644 --- a/include/sound/sof.h +++ b/include/sound/sof.h @@ -166,7 +166,7 @@ struct sof_dev_desc { /* default firmware name */ const char *default_fw_filename[SOF_IPC_TYPE_COUNT]; - struct snd_sof_dsp_ops *ops; + const struct snd_sof_dsp_ops *ops; int (*ops_init)(struct snd_sof_dev *sdev); void (*ops_free)(struct snd_sof_dev *sdev); }; -- cgit v1.2.3 From 8f2b0d55abc44676b076128903a5dc730aab23c6 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Fri, 26 Apr 2024 11:03:52 +0200 Subject: ASoC: SOF: intel: pci-tng: Constify snd_sof_dsp_ops 'struct snd_sof_dsp_ops' is not modified by core code, so it can be made const for increased code safety. Tested-by: Pierre-Louis Bossart Signed-off-by: Krzysztof Kozlowski Link: https://lore.kernel.org/r/20240426-n-const-ops-var-v2-5-e553fe67ae82@kernel.org Signed-off-by: Mark Brown --- sound/soc/sof/intel/pci-tng.c | 2 +- sound/soc/sof/intel/shim.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/soc/sof/intel/pci-tng.c b/sound/soc/sof/intel/pci-tng.c index c90173003c2b..d8a36d5a29f7 100644 --- a/sound/soc/sof/intel/pci-tng.c +++ b/sound/soc/sof/intel/pci-tng.c @@ -132,7 +132,7 @@ irq: return ret; } -struct snd_sof_dsp_ops sof_tng_ops = { +const struct snd_sof_dsp_ops sof_tng_ops = { /* device init */ .probe = tangier_pci_probe, diff --git a/sound/soc/sof/intel/shim.h b/sound/soc/sof/intel/shim.h index 9515d753c816..18ce3d33fa80 100644 --- a/sound/soc/sof/intel/shim.h +++ b/sound/soc/sof/intel/shim.h @@ -196,7 +196,7 @@ struct sof_intel_dsp_desc { int (*cl_init)(struct snd_sof_dev *sdev, int stream_tag, bool imr_boot); }; -extern struct snd_sof_dsp_ops sof_tng_ops; +extern const struct snd_sof_dsp_ops sof_tng_ops; extern const struct sof_intel_dsp_desc tng_chip_info; -- cgit v1.2.3 From 6032eefc2c478243a511352dda04495c9a9fec6a Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Fri, 26 Apr 2024 11:03:53 +0200 Subject: ASoC: SOF: intel: hda: Constify snd_sof_dsp_ops 'struct snd_sof_dsp_ops' is not modified by core code, so it can be made const for increased code safety. Tested-by: Pierre-Louis Bossart Signed-off-by: Krzysztof Kozlowski Link: https://lore.kernel.org/r/20240426-n-const-ops-var-v2-6-e553fe67ae82@kernel.org Signed-off-by: Mark Brown --- sound/soc/sof/intel/hda-common-ops.c | 2 +- sound/soc/sof/intel/hda.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/soc/sof/intel/hda-common-ops.c b/sound/soc/sof/intel/hda-common-ops.c index d71bb66b9991..466769c68da5 100644 --- a/sound/soc/sof/intel/hda-common-ops.c +++ b/sound/soc/sof/intel/hda-common-ops.c @@ -14,7 +14,7 @@ #include "hda.h" #include "../sof-audio.h" -struct snd_sof_dsp_ops sof_hda_common_ops = { +const struct snd_sof_dsp_ops sof_hda_common_ops = { /* probe/remove/shutdown */ .probe_early = hda_dsp_probe_early, .probe = hda_dsp_probe, diff --git a/sound/soc/sof/intel/hda.h b/sound/soc/sof/intel/hda.h index b59d1a572bce..7804c5b50c26 100644 --- a/sound/soc/sof/intel/hda.h +++ b/sound/soc/sof/intel/hda.h @@ -874,7 +874,7 @@ int hda_dsp_dais_suspend(struct snd_sof_dev *sdev); /* * Platform Specific HW abstraction Ops. */ -extern struct snd_sof_dsp_ops sof_hda_common_ops; +extern const struct snd_sof_dsp_ops sof_hda_common_ops; extern struct snd_sof_dsp_ops sof_skl_ops; int sof_skl_ops_init(struct snd_sof_dev *sdev); -- cgit v1.2.3 From 04f2f516be09d5493d764e0020a771c46b5470d8 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Fri, 26 Apr 2024 11:03:54 +0200 Subject: ASoC: SOF: amd: acp: Constify snd_sof_dsp_ops 'struct snd_sof_dsp_ops' is not modified by core code, so it can be made const for increased code safety. Tested-by: Pierre-Louis Bossart Signed-off-by: Krzysztof Kozlowski Link: https://lore.kernel.org/r/20240426-n-const-ops-var-v2-7-e553fe67ae82@kernel.org Signed-off-by: Mark Brown --- sound/soc/sof/amd/acp-common.c | 2 +- sound/soc/sof/amd/acp.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/soc/sof/amd/acp-common.c b/sound/soc/sof/amd/acp-common.c index 0fc4e20ec673..b26fa471b431 100644 --- a/sound/soc/sof/amd/acp-common.c +++ b/sound/soc/sof/amd/acp-common.c @@ -193,7 +193,7 @@ struct snd_soc_acpi_mach *amd_sof_machine_select(struct snd_sof_dev *sdev) } /* AMD Common DSP ops */ -struct snd_sof_dsp_ops sof_acp_common_ops = { +const struct snd_sof_dsp_ops sof_acp_common_ops = { /* probe and remove */ .probe = amd_sof_acp_probe, .remove = amd_sof_acp_remove, diff --git a/sound/soc/sof/amd/acp.h b/sound/soc/sof/amd/acp.h index e229bb6b849d..87e79d500865 100644 --- a/sound/soc/sof/amd/acp.h +++ b/sound/soc/sof/amd/acp.h @@ -310,7 +310,7 @@ int acp_pcm_hw_params(struct snd_sof_dev *sdev, struct snd_pcm_substream *substr snd_pcm_uframes_t acp_pcm_pointer(struct snd_sof_dev *sdev, struct snd_pcm_substream *substream); -extern struct snd_sof_dsp_ops sof_acp_common_ops; +extern const struct snd_sof_dsp_ops sof_acp_common_ops; extern struct snd_sof_dsp_ops sof_renoir_ops; int sof_renoir_ops_init(struct snd_sof_dev *sdev); -- cgit v1.2.3 From ab85c44973298b69eb32795de11ce4d426705532 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Fri, 26 Apr 2024 11:03:55 +0200 Subject: ASoC: SOF: imx8: Constify snd_sof_dsp_ops 'struct snd_sof_dsp_ops' is not modified by core code, so it can be made const for increased code safety. Tested-by: Pierre-Louis Bossart Signed-off-by: Krzysztof Kozlowski Link: https://lore.kernel.org/r/20240426-n-const-ops-var-v2-8-e553fe67ae82@kernel.org Signed-off-by: Mark Brown --- sound/soc/sof/imx/imx8.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/soc/sof/imx/imx8.c b/sound/soc/sof/imx/imx8.c index d65e09a927f6..3021dc87ab5a 100644 --- a/sound/soc/sof/imx/imx8.c +++ b/sound/soc/sof/imx/imx8.c @@ -478,7 +478,7 @@ static int imx8_dsp_set_power_state(struct snd_sof_dev *sdev, } /* i.MX8 ops */ -static struct snd_sof_dsp_ops sof_imx8_ops = { +static const struct snd_sof_dsp_ops sof_imx8_ops = { /* probe and remove */ .probe = imx8_probe, .remove = imx8_remove, @@ -539,7 +539,7 @@ static struct snd_sof_dsp_ops sof_imx8_ops = { }; /* i.MX8X ops */ -static struct snd_sof_dsp_ops sof_imx8x_ops = { +static const struct snd_sof_dsp_ops sof_imx8x_ops = { /* probe and remove */ .probe = imx8_probe, .remove = imx8_remove, -- cgit v1.2.3 From 66d49ab5fb51bb8d1b4c2c9c8fa0fbe8e4c8ca1c Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Fri, 26 Apr 2024 11:03:56 +0200 Subject: ASoC: SOF: imx8m: Constify snd_sof_dsp_ops 'struct snd_sof_dsp_ops' is not modified by core code, so it can be made const for increased code safety. Tested-by: Pierre-Louis Bossart Signed-off-by: Krzysztof Kozlowski Link: https://lore.kernel.org/r/20240426-n-const-ops-var-v2-9-e553fe67ae82@kernel.org Signed-off-by: Mark Brown --- sound/soc/sof/imx/imx8m.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/sof/imx/imx8m.c b/sound/soc/sof/imx/imx8m.c index 3e0b88002b4f..4ed415f04345 100644 --- a/sound/soc/sof/imx/imx8m.c +++ b/sound/soc/sof/imx/imx8m.c @@ -411,7 +411,7 @@ static int imx8m_dsp_suspend(struct snd_sof_dev *sdev, unsigned int target_state } /* i.MX8 ops */ -static struct snd_sof_dsp_ops sof_imx8m_ops = { +static const struct snd_sof_dsp_ops sof_imx8m_ops = { /* probe and remove */ .probe = imx8m_probe, .remove = imx8m_remove, -- cgit v1.2.3 From 232e0da9fa778233358586617bd22173bcac6bcc Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Fri, 26 Apr 2024 11:03:57 +0200 Subject: ASoC: SOF: imx8ulp: Constify snd_sof_dsp_ops 'struct snd_sof_dsp_ops' is not modified by core code, so it can be made const for increased code safety. Tested-by: Pierre-Louis Bossart Signed-off-by: Krzysztof Kozlowski Link: https://lore.kernel.org/r/20240426-n-const-ops-var-v2-10-e553fe67ae82@kernel.org Signed-off-by: Mark Brown --- sound/soc/sof/imx/imx8ulp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/sof/imx/imx8ulp.c b/sound/soc/sof/imx/imx8ulp.c index 296fbf11f6d0..8adfdd00413a 100644 --- a/sound/soc/sof/imx/imx8ulp.c +++ b/sound/soc/sof/imx/imx8ulp.c @@ -408,7 +408,7 @@ static int imx8ulp_dsp_set_power_state(struct snd_sof_dev *sdev, } /* i.MX8 ops */ -static struct snd_sof_dsp_ops sof_imx8ulp_ops = { +static const struct snd_sof_dsp_ops sof_imx8ulp_ops = { /* probe and remove */ .probe = imx8ulp_probe, .remove = imx8ulp_remove, -- cgit v1.2.3 From 936cc56044a87ae7fbd0e4098a7daefa0f2f4e8e Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Fri, 26 Apr 2024 11:03:58 +0200 Subject: ASoC: SOF: intel: bdw: Constify snd_sof_dsp_ops 'struct snd_sof_dsp_ops' is not modified by core code, so it can be made const for increased code safety. Tested-by: Pierre-Louis Bossart Signed-off-by: Krzysztof Kozlowski Link: https://lore.kernel.org/r/20240426-n-const-ops-var-v2-11-e553fe67ae82@kernel.org Signed-off-by: Mark Brown --- sound/soc/sof/intel/bdw.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/sof/intel/bdw.c b/sound/soc/sof/intel/bdw.c index e30ca086f3f8..2e8926cd00f6 100644 --- a/sound/soc/sof/intel/bdw.c +++ b/sound/soc/sof/intel/bdw.c @@ -567,7 +567,7 @@ static struct snd_soc_dai_driver bdw_dai[] = { }; /* broadwell ops */ -static struct snd_sof_dsp_ops sof_bdw_ops = { +static const struct snd_sof_dsp_ops sof_bdw_ops = { /*Device init */ .probe = bdw_probe, -- cgit v1.2.3 From 48d5f1800d0cbda0212c5a58177918c419a24f8a Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Fri, 26 Apr 2024 11:03:59 +0200 Subject: ASoC: SOF: intel: byt: Constify snd_sof_dsp_ops 'struct snd_sof_dsp_ops' is not modified by core code, so it can be made const for increased code safety. Tested-by: Pierre-Louis Bossart Signed-off-by: Krzysztof Kozlowski Link: https://lore.kernel.org/r/20240426-n-const-ops-var-v2-12-e553fe67ae82@kernel.org Signed-off-by: Mark Brown --- sound/soc/sof/intel/byt.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/soc/sof/intel/byt.c b/sound/soc/sof/intel/byt.c index 373527b206d7..14a065999a89 100644 --- a/sound/soc/sof/intel/byt.c +++ b/sound/soc/sof/intel/byt.c @@ -214,7 +214,7 @@ irq: } /* baytrail ops */ -static struct snd_sof_dsp_ops sof_byt_ops = { +static const struct snd_sof_dsp_ops sof_byt_ops = { /* device init */ .probe = byt_acpi_probe, .remove = byt_remove, @@ -289,7 +289,7 @@ static const struct sof_intel_dsp_desc byt_chip_info = { }; /* cherrytrail and braswell ops */ -static struct snd_sof_dsp_ops sof_cht_ops = { +static const struct snd_sof_dsp_ops sof_cht_ops = { /* device init */ .probe = byt_acpi_probe, .remove = byt_remove, -- cgit v1.2.3 From fe80673f59da01776a1402e4b508a66fca43a24d Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Fri, 26 Apr 2024 11:04:00 +0200 Subject: ASoC: SOF: mediatek: mt8186: Constify snd_sof_dsp_ops 'struct snd_sof_dsp_ops' is not modified by core code, so it can be made const for increased code safety. Reviewed-by: AngeloGioacchino Del Regno Tested-by: Pierre-Louis Bossart Signed-off-by: Krzysztof Kozlowski Link: https://lore.kernel.org/r/20240426-n-const-ops-var-v2-13-e553fe67ae82@kernel.org Signed-off-by: Mark Brown --- sound/soc/sof/mediatek/mt8186/mt8186.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/sof/mediatek/mt8186/mt8186.c b/sound/soc/sof/mediatek/mt8186/mt8186.c index 0d2d7d697de0..c63e0d2f4b96 100644 --- a/sound/soc/sof/mediatek/mt8186/mt8186.c +++ b/sound/soc/sof/mediatek/mt8186/mt8186.c @@ -481,7 +481,7 @@ static struct snd_soc_dai_driver mt8186_dai[] = { }; /* mt8186 ops */ -static struct snd_sof_dsp_ops sof_mt8186_ops = { +static const struct snd_sof_dsp_ops sof_mt8186_ops = { /* probe and remove */ .probe = mt8186_dsp_probe, .remove = mt8186_dsp_remove, -- cgit v1.2.3 From 8b6d678fede700db6466d73f11fcbad496fa515e Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Fri, 26 Apr 2024 11:04:01 +0200 Subject: ASoC: SOF: mediatek: mt8195: Constify snd_sof_dsp_ops 'struct snd_sof_dsp_ops' is not modified by core code, so it can be made const for increased code safety. Reviewed-by: AngeloGioacchino Del Regno Tested-by: Pierre-Louis Bossart Signed-off-by: Krzysztof Kozlowski Link: https://lore.kernel.org/r/20240426-n-const-ops-var-v2-14-e553fe67ae82@kernel.org Signed-off-by: Mark Brown --- sound/soc/sof/mediatek/mt8195/mt8195.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/sof/mediatek/mt8195/mt8195.c b/sound/soc/sof/mediatek/mt8195/mt8195.c index 8ee7ee246344..fc1c016104ae 100644 --- a/sound/soc/sof/mediatek/mt8195/mt8195.c +++ b/sound/soc/sof/mediatek/mt8195/mt8195.c @@ -505,7 +505,7 @@ static struct snd_soc_dai_driver mt8195_dai[] = { }; /* mt8195 ops */ -static struct snd_sof_dsp_ops sof_mt8195_ops = { +static const struct snd_sof_dsp_ops sof_mt8195_ops = { /* probe and remove */ .probe = mt8195_dsp_probe, .remove = mt8195_dsp_remove, -- cgit v1.2.3 From 4a1baeefd1d5a955b5a55a75539244e03e623b0b Mon Sep 17 00:00:00 2001 From: Mohammad Shehar Yaar Tausif Date: Fri, 26 Apr 2024 22:33:18 +0530 Subject: ASoC: dt-bindings: tegra30-i2s: convert to dt schema Convert NVIDIA Tegra30 I2S binding to DT schema and add "clock-names" property used by multiple tegra i2s blocks in arch/arm64/boot/dts/nvidia/tegra132.dtsi. This is not a required property by the binding. Signed-off-by: Mohammad Shehar Yaar Tausif Reviewed-by: Rob Herring (Arm) Link: https://lore.kernel.org/r/20240426170322.36273-1-sheharyaar48@gmail.com Signed-off-by: Mark Brown --- .../bindings/sound/nvidia,tegra30-i2s.txt | 27 --------- .../bindings/sound/nvidia,tegra30-i2s.yaml | 67 ++++++++++++++++++++++ 2 files changed, 67 insertions(+), 27 deletions(-) delete mode 100644 Documentation/devicetree/bindings/sound/nvidia,tegra30-i2s.txt create mode 100644 Documentation/devicetree/bindings/sound/nvidia,tegra30-i2s.yaml diff --git a/Documentation/devicetree/bindings/sound/nvidia,tegra30-i2s.txt b/Documentation/devicetree/bindings/sound/nvidia,tegra30-i2s.txt deleted file mode 100644 index 38caa936f6f8..000000000000 --- a/Documentation/devicetree/bindings/sound/nvidia,tegra30-i2s.txt +++ /dev/null @@ -1,27 +0,0 @@ -NVIDIA Tegra30 I2S controller - -Required properties: -- compatible : For Tegra30, must contain "nvidia,tegra30-i2s". For Tegra124, - must contain "nvidia,tegra124-i2s". Otherwise, must contain - "nvidia,-i2s" plus at least one of the above, where is - tegra114 or tegra132. -- reg : Should contain I2S registers location and length -- clocks : Must contain one entry, for the module clock. - See ../clocks/clock-bindings.txt for details. -- resets : Must contain an entry for each entry in reset-names. - See ../reset/reset.txt for details. -- reset-names : Must include the following entries: - - i2s -- nvidia,ahub-cif-ids : The list of AHUB CIF IDs for this port, rx (playback) - first, tx (capture) second. See nvidia,tegra30-ahub.txt for values. - -Example: - -i2s@70080300 { - compatible = "nvidia,tegra30-i2s"; - reg = <0x70080300 0x100>; - nvidia,ahub-cif-ids = <4 4>; - clocks = <&tegra_car 11>; - resets = <&tegra_car 11>; - reset-names = "i2s"; -}; diff --git a/Documentation/devicetree/bindings/sound/nvidia,tegra30-i2s.yaml b/Documentation/devicetree/bindings/sound/nvidia,tegra30-i2s.yaml new file mode 100644 index 000000000000..89c3c6414ab1 --- /dev/null +++ b/Documentation/devicetree/bindings/sound/nvidia,tegra30-i2s.yaml @@ -0,0 +1,67 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/sound/nvidia,tegra30-i2s.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: NVIDIA Tegra30 I2S controller + +maintainers: + - Thierry Reding + - Jon Hunter + +properties: + compatible: + oneOf: + - enum: + - nvidia,tegra124-i2s + - nvidia,tegra30-i2s + - items: + - const: nvidia,tegra114-i2s + - const: nvidia,tegra30-i2s + + reg: + maxItems: 1 + + clocks: + maxItems: 1 + + clock-names: + const: i2s + + resets: + maxItems: 1 + + reset-names: + const: i2s + + nvidia,ahub-cif-ids: + description: list of AHUB CIF IDs + $ref: /schemas/types.yaml#/definitions/uint32-array + items: + - description: rx (playback) + - description: tx (capture) + +required: + - compatible + - reg + - clocks + - resets + - reset-names + - nvidia,ahub-cif-ids + +additionalProperties: false + +examples: + - | + #include + + i2s@70080300 { + compatible = "nvidia,tegra30-i2s"; + reg = <0x70080300 0x100>; + nvidia,ahub-cif-ids = <4 4>; + clocks = <&tegra_car TEGRA30_CLK_I2S0>; + resets = <&tegra_car 30>; + reset-names = "i2s"; + }; +... -- cgit v1.2.3 From 9a8cadddd9303ae15d1d518c4f2ddf00ee668729 Mon Sep 17 00:00:00 2001 From: Joao Schim Date: Mon, 29 Apr 2024 21:49:20 +0200 Subject: ASoC: sunxi: DMIC: Add controls for adjusting the mic gains The AllWinner H6 and later SoCs that sport a DMIC block contain a set of registers to control the gain (left + right) of each of the four supported channels. Add ASoC controls for changing each of the stereo channel gains using alsamixer and alike Signed-off-by: Joao Schim Reviewed-by: Jernej Skrabec Link: https://lore.kernel.org/r/20240429194920.1596257-1-joao@schimsalabim.eu Signed-off-by: Mark Brown --- sound/soc/sunxi/sun50i-dmic.c | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/sound/soc/sunxi/sun50i-dmic.c b/sound/soc/sunxi/sun50i-dmic.c index c76628bc86c6..dd32780fb6a4 100644 --- a/sound/soc/sunxi/sun50i-dmic.c +++ b/sound/soc/sunxi/sun50i-dmic.c @@ -14,6 +14,7 @@ #include #include #include +#include #define SUN50I_DMIC_EN_CTL (0x00) #define SUN50I_DMIC_EN_CTL_GLOBE BIT(8) @@ -43,6 +44,17 @@ #define SUN50I_DMIC_CH_NUM_N_MASK GENMASK(2, 0) #define SUN50I_DMIC_CNT (0x2c) #define SUN50I_DMIC_CNT_N (1 << 0) +#define SUN50I_DMIC_D0D1_VOL_CTR (0x30) + #define SUN50I_DMIC_D0D1_VOL_CTR_0R (0) + #define SUN50I_DMIC_D0D1_VOL_CTR_0L (8) + #define SUN50I_DMIC_D0D1_VOL_CTR_1R (16) + #define SUN50I_DMIC_D0D1_VOL_CTR_1L (24) +#define SUN50I_DMIC_D2D3_VOL_CTR (0x34) + #define SUN50I_DMIC_D2D3_VOL_CTR_2R (0) + #define SUN50I_DMIC_D2D3_VOL_CTR_2L (8) + #define SUN50I_DMIC_D2D3_VOL_CTR_3R (16) + #define SUN50I_DMIC_D2D3_VOL_CTR_3L (24) + #define SUN50I_DMIC_HPF_CTRL (0x38) #define SUN50I_DMIC_VERSION (0x50) @@ -273,8 +285,30 @@ static const struct of_device_id sun50i_dmic_of_match[] = { }; MODULE_DEVICE_TABLE(of, sun50i_dmic_of_match); +static const SNDRV_CTL_TLVD_DECLARE_DB_SCALE(sun50i_dmic_vol_scale, -12000, 75, 1); + +static const struct snd_kcontrol_new sun50i_dmic_controls[] = { + + SOC_DOUBLE_TLV("DMIC Channel 0 Capture Volume", SUN50I_DMIC_D0D1_VOL_CTR, + SUN50I_DMIC_D0D1_VOL_CTR_0L, SUN50I_DMIC_D0D1_VOL_CTR_0R, + 0xFF, 0, sun50i_dmic_vol_scale), + SOC_DOUBLE_TLV("DMIC Channel 1 Capture Volume", SUN50I_DMIC_D0D1_VOL_CTR, + SUN50I_DMIC_D0D1_VOL_CTR_1L, SUN50I_DMIC_D0D1_VOL_CTR_1R, + 0xFF, 0, sun50i_dmic_vol_scale), + SOC_DOUBLE_TLV("DMIC Channel 2 Capture Volume", SUN50I_DMIC_D2D3_VOL_CTR, + SUN50I_DMIC_D2D3_VOL_CTR_2L, SUN50I_DMIC_D2D3_VOL_CTR_2R, + 0xFF, 0, sun50i_dmic_vol_scale), + SOC_DOUBLE_TLV("DMIC Channel 3 Capture Volume", SUN50I_DMIC_D2D3_VOL_CTR, + SUN50I_DMIC_D2D3_VOL_CTR_3L, SUN50I_DMIC_D2D3_VOL_CTR_3R, + 0xFF, 0, sun50i_dmic_vol_scale), + + +}; + static const struct snd_soc_component_driver sun50i_dmic_component = { .name = "sun50i-dmic", + .controls = sun50i_dmic_controls, + .num_controls = ARRAY_SIZE(sun50i_dmic_controls), }; static int sun50i_dmic_runtime_suspend(struct device *dev) -- cgit v1.2.3 From 9723cab054d59d770cd1927f92fe315c26cc6a78 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Wed, 1 May 2024 19:51:27 +0200 Subject: ASoC: Use inline function for type safety in snd_soc_substream_to_rtd() A common pattern in sound drivers is getting 'struct snd_soc_pcm_runtime' from 'struct snd_pcm_substream' opaque pointer private_data field with snd_soc_substream_to_rtd(). However 'private_data' appears in several other structures as well, including 'struct snd_compr_stream'. The field might not hold the same type for every structure, although seems the case at least for 'struct snd_compr_stream', so code can easily make a mistake by using macro for wrong structure passed as argument. Switch from macro to inline function, so such mistake will be build-time detectable. Signed-off-by: Krzysztof Kozlowski Link: https://lore.kernel.org/r/20240501175127.34301-1-krzysztof.kozlowski@linaro.org Signed-off-by: Mark Brown --- include/sound/soc.h | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/include/sound/soc.h b/include/sound/soc.h index 8aa6ddb7ee1e..33671437ee89 100644 --- a/include/sound/soc.h +++ b/include/sound/soc.h @@ -1215,8 +1215,12 @@ struct snd_soc_pcm_runtime { /* see soc_new_pcm_runtime() */ #define snd_soc_rtd_to_cpu(rtd, n) (rtd)->dais[n] #define snd_soc_rtd_to_codec(rtd, n) (rtd)->dais[n + (rtd)->dai_link->num_cpus] -#define snd_soc_substream_to_rtd(substream) \ - (struct snd_soc_pcm_runtime *)snd_pcm_substream_chip(substream) + +static inline struct snd_soc_pcm_runtime * +snd_soc_substream_to_rtd(const struct snd_pcm_substream *substream) +{ + return snd_pcm_substream_chip(substream); +} #define for_each_rtd_components(rtd, i, component) \ for ((i) = 0, component = NULL; \ -- cgit v1.2.3 From ba2a2c378ada0cd641a1887151ea8af532617c69 Mon Sep 17 00:00:00 2001 From: Uwe Kleine-König Date: Thu, 2 May 2024 09:47:20 +0200 Subject: ASoC: codecs: Drop explicit initialization of struct i2c_device_id::driver_data to 0 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit These drivers don't use the driver_data member of struct i2c_device_id, so don't explicitly initialize this member. This prepares putting driver_data in an anonymous union which requires either no initialization or named designators. But it's also a nice cleanup on its own. Signed-off-by: Uwe Kleine-König Reviewed-by: Andy Shevchenko Link: https://lore.kernel.org/r/20240502074722.1103986-2-u.kleine-koenig@pengutronix.de Signed-off-by: Mark Brown --- sound/soc/codecs/adau1372-i2c.c | 2 +- sound/soc/codecs/adau1373.c | 2 +- sound/soc/codecs/adau1701.c | 8 ++++---- sound/soc/codecs/adau7118-i2c.c | 2 +- sound/soc/codecs/adav803.c | 2 +- sound/soc/codecs/ak4118.c | 2 +- sound/soc/codecs/ak4535.c | 2 +- sound/soc/codecs/ak4641.c | 2 +- sound/soc/codecs/ak4671.c | 2 +- sound/soc/codecs/cs35l32.c | 2 +- sound/soc/codecs/cs35l33.c | 2 +- sound/soc/codecs/cs35l34.c | 2 +- sound/soc/codecs/cs35l35.c | 2 +- sound/soc/codecs/cs35l36.c | 2 +- sound/soc/codecs/cs35l41-i2c.c | 8 ++++---- sound/soc/codecs/cs35l45-i2c.c | 2 +- sound/soc/codecs/cs35l56-i2c.c | 2 +- sound/soc/codecs/cs4265.c | 2 +- sound/soc/codecs/cs4270.c | 2 +- sound/soc/codecs/cs4271-i2c.c | 2 +- sound/soc/codecs/cs42l42-i2c.c | 2 +- sound/soc/codecs/cs42l51-i2c.c | 2 +- sound/soc/codecs/cs42l52.c | 2 +- sound/soc/codecs/cs42l56.c | 2 +- sound/soc/codecs/cs42l73.c | 2 +- sound/soc/codecs/cs43130.c | 8 ++++---- sound/soc/codecs/cs4341.c | 2 +- sound/soc/codecs/cs4349.c | 2 +- sound/soc/codecs/cs53l30.c | 2 +- sound/soc/codecs/cx2072x.c | 4 ++-- sound/soc/codecs/da7210.c | 2 +- sound/soc/codecs/da7213.c | 2 +- sound/soc/codecs/da732x.c | 2 +- sound/soc/codecs/da9055.c | 2 +- sound/soc/codecs/es8316.c | 2 +- sound/soc/codecs/es8326.c | 2 +- sound/soc/codecs/es8328-i2c.c | 4 ++-- sound/soc/codecs/isabelle.c | 2 +- sound/soc/codecs/lm4857.c | 2 +- sound/soc/codecs/lm49453.c | 2 +- sound/soc/codecs/max9768.c | 2 +- sound/soc/codecs/max98371.c | 2 +- sound/soc/codecs/max98373-i2c.c | 2 +- sound/soc/codecs/max98388.c | 2 +- sound/soc/codecs/max98390.c | 2 +- sound/soc/codecs/max9850.c | 2 +- sound/soc/codecs/max98520.c | 2 +- sound/soc/codecs/max9867.c | 2 +- sound/soc/codecs/max9877.c | 2 +- sound/soc/codecs/max98925.c | 2 +- sound/soc/codecs/max98926.c | 2 +- sound/soc/codecs/max98927.c | 2 +- sound/soc/codecs/ml26124.c | 2 +- sound/soc/codecs/mt6660.c | 2 +- sound/soc/codecs/nau8325.c | 2 +- sound/soc/codecs/nau8540.c | 2 +- sound/soc/codecs/nau8810.c | 6 +++--- sound/soc/codecs/nau8821.c | 2 +- sound/soc/codecs/nau8822.c | 2 +- sound/soc/codecs/nau8824.c | 2 +- sound/soc/codecs/nau8825.c | 2 +- sound/soc/codecs/pcm1681.c | 2 +- sound/soc/codecs/pcm1789-i2c.c | 2 +- sound/soc/codecs/pcm179x-i2c.c | 2 +- sound/soc/codecs/rt1011.c | 2 +- sound/soc/codecs/rt1015.c | 2 +- sound/soc/codecs/rt1016.c | 2 +- sound/soc/codecs/rt1019.c | 2 +- sound/soc/codecs/rt1305.c | 4 ++-- sound/soc/codecs/rt1308.c | 2 +- sound/soc/codecs/rt274.c | 2 +- sound/soc/codecs/rt286.c | 4 ++-- sound/soc/codecs/rt298.c | 2 +- sound/soc/codecs/rt5514.c | 2 +- sound/soc/codecs/rt5616.c | 2 +- sound/soc/codecs/rt5631.c | 4 ++-- sound/soc/codecs/rt5640.c | 6 +++--- sound/soc/codecs/rt5645.c | 4 ++-- sound/soc/codecs/rt5651.c | 2 +- sound/soc/codecs/rt5659.c | 4 ++-- sound/soc/codecs/rt5660.c | 2 +- sound/soc/codecs/rt5663.c | 2 +- sound/soc/codecs/rt5665.c | 2 +- sound/soc/codecs/rt5668.c | 2 +- sound/soc/codecs/rt5670.c | 6 +++--- sound/soc/codecs/rt5682-i2c.c | 2 +- sound/soc/codecs/rt5682s.c | 2 +- sound/soc/codecs/sgtl5000.c | 2 +- sound/soc/codecs/sma1303.c | 2 +- sound/soc/codecs/src4xxx-i2c.c | 2 +- sound/soc/codecs/ssm2518.c | 2 +- sound/soc/codecs/ssm4567.c | 2 +- sound/soc/codecs/sta32x.c | 6 +++--- sound/soc/codecs/sta350.c | 2 +- sound/soc/codecs/sta529.c | 2 +- sound/soc/codecs/tas2552.c | 2 +- sound/soc/codecs/tas2764.c | 2 +- sound/soc/codecs/tas2770.c | 2 +- sound/soc/codecs/tas2780.c | 2 +- sound/soc/codecs/tas5086.c | 2 +- sound/soc/codecs/tas6424.c | 2 +- sound/soc/codecs/tda7419.c | 2 +- sound/soc/codecs/tfa9879.c | 2 +- sound/soc/codecs/tlv320aic23-i2c.c | 2 +- sound/soc/codecs/ts3a227e.c | 2 +- sound/soc/codecs/tscs42xx.c | 4 ++-- sound/soc/codecs/tscs454.c | 2 +- sound/soc/codecs/uda1380.c | 2 +- sound/soc/codecs/wm1250-ev1.c | 2 +- sound/soc/codecs/wm2000.c | 2 +- sound/soc/codecs/wm2200.c | 2 +- sound/soc/codecs/wm5100.c | 2 +- sound/soc/codecs/wm8510.c | 2 +- sound/soc/codecs/wm8523.c | 2 +- sound/soc/codecs/wm8711.c | 2 +- sound/soc/codecs/wm8728.c | 2 +- sound/soc/codecs/wm8731-i2c.c | 2 +- sound/soc/codecs/wm8737.c | 2 +- sound/soc/codecs/wm8741.c | 2 +- sound/soc/codecs/wm8750.c | 4 ++-- sound/soc/codecs/wm8753.c | 2 +- sound/soc/codecs/wm8804-i2c.c | 2 +- sound/soc/codecs/wm8900.c | 2 +- sound/soc/codecs/wm8903.c | 2 +- sound/soc/codecs/wm8940.c | 2 +- sound/soc/codecs/wm8955.c | 2 +- sound/soc/codecs/wm8960.c | 2 +- sound/soc/codecs/wm8961.c | 2 +- sound/soc/codecs/wm8962.c | 2 +- sound/soc/codecs/wm8971.c | 2 +- sound/soc/codecs/wm8974.c | 2 +- sound/soc/codecs/wm8978.c | 2 +- sound/soc/codecs/wm8983.c | 2 +- sound/soc/codecs/wm8988.c | 2 +- sound/soc/codecs/wm8990.c | 2 +- sound/soc/codecs/wm8991.c | 2 +- sound/soc/codecs/wm8993.c | 2 +- sound/soc/codecs/wm8995.c | 2 +- sound/soc/codecs/wm8996.c | 2 +- sound/soc/codecs/wm9081.c | 2 +- sound/soc/codecs/wm9090.c | 4 ++-- 141 files changed, 168 insertions(+), 168 deletions(-) diff --git a/sound/soc/codecs/adau1372-i2c.c b/sound/soc/codecs/adau1372-i2c.c index 132b9e2cca59..2869325f9ace 100644 --- a/sound/soc/codecs/adau1372-i2c.c +++ b/sound/soc/codecs/adau1372-i2c.c @@ -21,7 +21,7 @@ static int adau1372_i2c_probe(struct i2c_client *client) } static const struct i2c_device_id adau1372_i2c_ids[] = { - { "adau1372", 0 }, + { "adau1372" }, { } }; MODULE_DEVICE_TABLE(i2c, adau1372_i2c_ids); diff --git a/sound/soc/codecs/adau1373.c b/sound/soc/codecs/adau1373.c index 3582c4b968a0..a910e252aa12 100644 --- a/sound/soc/codecs/adau1373.c +++ b/sound/soc/codecs/adau1373.c @@ -1496,7 +1496,7 @@ static int adau1373_i2c_probe(struct i2c_client *client) } static const struct i2c_device_id adau1373_i2c_id[] = { - { "adau1373", 0 }, + { "adau1373" }, { } }; MODULE_DEVICE_TABLE(i2c, adau1373_i2c_id); diff --git a/sound/soc/codecs/adau1701.c b/sound/soc/codecs/adau1701.c index d1392d9abccd..8bd6067df7f7 100644 --- a/sound/soc/codecs/adau1701.c +++ b/sound/soc/codecs/adau1701.c @@ -862,10 +862,10 @@ exit_regulators_disable: } static const struct i2c_device_id adau1701_i2c_id[] = { - { "adau1401", 0 }, - { "adau1401a", 0 }, - { "adau1701", 0 }, - { "adau1702", 0 }, + { "adau1401" }, + { "adau1401a" }, + { "adau1701" }, + { "adau1702" }, { } }; MODULE_DEVICE_TABLE(i2c, adau1701_i2c_id); diff --git a/sound/soc/codecs/adau7118-i2c.c b/sound/soc/codecs/adau7118-i2c.c index b302b28eca7c..f9dc8f4ef9a4 100644 --- a/sound/soc/codecs/adau7118-i2c.c +++ b/sound/soc/codecs/adau7118-i2c.c @@ -68,7 +68,7 @@ static const struct of_device_id adau7118_of_match[] = { MODULE_DEVICE_TABLE(of, adau7118_of_match); static const struct i2c_device_id adau7118_id[] = { - {"adau7118", 0}, + {"adau7118"}, {} }; MODULE_DEVICE_TABLE(i2c, adau7118_id); diff --git a/sound/soc/codecs/adav803.c b/sound/soc/codecs/adav803.c index 78a317947df9..8b96c41f0354 100644 --- a/sound/soc/codecs/adav803.c +++ b/sound/soc/codecs/adav803.c @@ -14,7 +14,7 @@ #include "adav80x.h" static const struct i2c_device_id adav803_id[] = { - { "adav803", 0 }, + { "adav803" }, { } }; MODULE_DEVICE_TABLE(i2c, adav803_id); diff --git a/sound/soc/codecs/ak4118.c b/sound/soc/codecs/ak4118.c index 74a10108c1d4..9a43235e6a11 100644 --- a/sound/soc/codecs/ak4118.c +++ b/sound/soc/codecs/ak4118.c @@ -396,7 +396,7 @@ MODULE_DEVICE_TABLE(of, ak4118_of_match); #endif static const struct i2c_device_id ak4118_id_table[] = { - { "ak4118", 0 }, + { "ak4118" }, {} }; MODULE_DEVICE_TABLE(i2c, ak4118_id_table); diff --git a/sound/soc/codecs/ak4535.c b/sound/soc/codecs/ak4535.c index 904bf91090aa..aadc46a47280 100644 --- a/sound/soc/codecs/ak4535.c +++ b/sound/soc/codecs/ak4535.c @@ -430,7 +430,7 @@ static int ak4535_i2c_probe(struct i2c_client *i2c) } static const struct i2c_device_id ak4535_i2c_id[] = { - { "ak4535", 0 }, + { "ak4535" }, { } }; MODULE_DEVICE_TABLE(i2c, ak4535_i2c_id); diff --git a/sound/soc/codecs/ak4641.c b/sound/soc/codecs/ak4641.c index 5b7df2f0dd6a..ec33e7d73c6c 100644 --- a/sound/soc/codecs/ak4641.c +++ b/sound/soc/codecs/ak4641.c @@ -619,7 +619,7 @@ static void ak4641_i2c_remove(struct i2c_client *i2c) } static const struct i2c_device_id ak4641_i2c_id[] = { - { "ak4641", 0 }, + { "ak4641" }, { } }; MODULE_DEVICE_TABLE(i2c, ak4641_i2c_id); diff --git a/sound/soc/codecs/ak4671.c b/sound/soc/codecs/ak4671.c index 5b849b390c2a..d545aa2e0a39 100644 --- a/sound/soc/codecs/ak4671.c +++ b/sound/soc/codecs/ak4671.c @@ -646,7 +646,7 @@ static int ak4671_i2c_probe(struct i2c_client *client) } static const struct i2c_device_id ak4671_i2c_id[] = { - { "ak4671", 0 }, + { "ak4671" }, { } }; MODULE_DEVICE_TABLE(i2c, ak4671_i2c_id); diff --git a/sound/soc/codecs/cs35l32.c b/sound/soc/codecs/cs35l32.c index d1350ffbf3bd..96555263e10b 100644 --- a/sound/soc/codecs/cs35l32.c +++ b/sound/soc/codecs/cs35l32.c @@ -558,7 +558,7 @@ MODULE_DEVICE_TABLE(of, cs35l32_of_match); static const struct i2c_device_id cs35l32_id[] = { - {"cs35l32", 0}, + {"cs35l32"}, {} }; diff --git a/sound/soc/codecs/cs35l33.c b/sound/soc/codecs/cs35l33.c index a19a2bafb37c..b03aab147530 100644 --- a/sound/soc/codecs/cs35l33.c +++ b/sound/soc/codecs/cs35l33.c @@ -1264,7 +1264,7 @@ static const struct of_device_id cs35l33_of_match[] = { MODULE_DEVICE_TABLE(of, cs35l33_of_match); static const struct i2c_device_id cs35l33_id[] = { - {"cs35l33", 0}, + {"cs35l33"}, {} }; diff --git a/sound/soc/codecs/cs35l34.c b/sound/soc/codecs/cs35l34.c index cca59de66b73..4c517231d765 100644 --- a/sound/soc/codecs/cs35l34.c +++ b/sound/soc/codecs/cs35l34.c @@ -1198,7 +1198,7 @@ static const struct of_device_id cs35l34_of_match[] = { MODULE_DEVICE_TABLE(of, cs35l34_of_match); static const struct i2c_device_id cs35l34_id[] = { - {"cs35l34", 0}, + {"cs35l34"}, {} }; MODULE_DEVICE_TABLE(i2c, cs35l34_id); diff --git a/sound/soc/codecs/cs35l35.c b/sound/soc/codecs/cs35l35.c index ddb7d63213a3..c39b3cfe9574 100644 --- a/sound/soc/codecs/cs35l35.c +++ b/sound/soc/codecs/cs35l35.c @@ -1639,7 +1639,7 @@ static const struct of_device_id cs35l35_of_match[] = { MODULE_DEVICE_TABLE(of, cs35l35_of_match); static const struct i2c_device_id cs35l35_id[] = { - {"cs35l35", 0}, + {"cs35l35"}, {} }; diff --git a/sound/soc/codecs/cs35l36.c b/sound/soc/codecs/cs35l36.c index f5bd32e434a0..bc79990615e8 100644 --- a/sound/soc/codecs/cs35l36.c +++ b/sound/soc/codecs/cs35l36.c @@ -1930,7 +1930,7 @@ static const struct of_device_id cs35l36_of_match[] = { MODULE_DEVICE_TABLE(of, cs35l36_of_match); static const struct i2c_device_id cs35l36_id[] = { - {"cs35l36", 0}, + {"cs35l36"}, {} }; diff --git a/sound/soc/codecs/cs35l41-i2c.c b/sound/soc/codecs/cs35l41-i2c.c index a0c457c0d04b..34097996b784 100644 --- a/sound/soc/codecs/cs35l41-i2c.c +++ b/sound/soc/codecs/cs35l41-i2c.c @@ -20,10 +20,10 @@ #include "cs35l41.h" static const struct i2c_device_id cs35l41_id_i2c[] = { - { "cs35l40", 0 }, - { "cs35l41", 0 }, - { "cs35l51", 0 }, - { "cs35l53", 0 }, + { "cs35l40" }, + { "cs35l41" }, + { "cs35l51" }, + { "cs35l53" }, {} }; diff --git a/sound/soc/codecs/cs35l45-i2c.c b/sound/soc/codecs/cs35l45-i2c.c index bc2af1ed0fe9..f5fc42dcc8c7 100644 --- a/sound/soc/codecs/cs35l45-i2c.c +++ b/sound/soc/codecs/cs35l45-i2c.c @@ -53,7 +53,7 @@ static const struct of_device_id cs35l45_of_match[] = { MODULE_DEVICE_TABLE(of, cs35l45_of_match); static const struct i2c_device_id cs35l45_id_i2c[] = { - { "cs35l45", 0 }, + { "cs35l45" }, {} }; MODULE_DEVICE_TABLE(i2c, cs35l45_id_i2c); diff --git a/sound/soc/codecs/cs35l56-i2c.c b/sound/soc/codecs/cs35l56-i2c.c index 7063c400e896..2bd2ff75cd50 100644 --- a/sound/soc/codecs/cs35l56-i2c.c +++ b/sound/soc/codecs/cs35l56-i2c.c @@ -57,7 +57,7 @@ static void cs35l56_i2c_remove(struct i2c_client *client) } static const struct i2c_device_id cs35l56_id_i2c[] = { - { "cs35l56", 0 }, + { "cs35l56" }, {} }; MODULE_DEVICE_TABLE(i2c, cs35l56_id_i2c); diff --git a/sound/soc/codecs/cs4265.c b/sound/soc/codecs/cs4265.c index 1ed1e60d8e53..78ffb7fa7fc5 100644 --- a/sound/soc/codecs/cs4265.c +++ b/sound/soc/codecs/cs4265.c @@ -638,7 +638,7 @@ static const struct of_device_id cs4265_of_match[] = { MODULE_DEVICE_TABLE(of, cs4265_of_match); static const struct i2c_device_id cs4265_id[] = { - { "cs4265", 0 }, + { "cs4265" }, { } }; MODULE_DEVICE_TABLE(i2c, cs4265_id); diff --git a/sound/soc/codecs/cs4270.c b/sound/soc/codecs/cs4270.c index 3bbb90c827f2..67e92bfecb56 100644 --- a/sound/soc/codecs/cs4270.c +++ b/sound/soc/codecs/cs4270.c @@ -734,7 +734,7 @@ static int cs4270_i2c_probe(struct i2c_client *i2c_client) * cs4270_id - I2C device IDs supported by this driver */ static const struct i2c_device_id cs4270_id[] = { - {"cs4270", 0}, + {"cs4270"}, {} }; MODULE_DEVICE_TABLE(i2c, cs4270_id); diff --git a/sound/soc/codecs/cs4271-i2c.c b/sound/soc/codecs/cs4271-i2c.c index 89fe7d1665df..1d210b969173 100644 --- a/sound/soc/codecs/cs4271-i2c.c +++ b/sound/soc/codecs/cs4271-i2c.c @@ -23,7 +23,7 @@ static int cs4271_i2c_probe(struct i2c_client *client) } static const struct i2c_device_id cs4271_i2c_id[] = { - { "cs4271", 0 }, + { "cs4271" }, { } }; MODULE_DEVICE_TABLE(i2c, cs4271_i2c_id); diff --git a/sound/soc/codecs/cs42l42-i2c.c b/sound/soc/codecs/cs42l42-i2c.c index 2552a1e6b82f..8d10f9328e02 100644 --- a/sound/soc/codecs/cs42l42-i2c.c +++ b/sound/soc/codecs/cs42l42-i2c.c @@ -78,7 +78,7 @@ static const struct acpi_device_id __maybe_unused cs42l42_acpi_match[] = { MODULE_DEVICE_TABLE(acpi, cs42l42_acpi_match); static const struct i2c_device_id cs42l42_id[] = { - {"cs42l42", 0}, + {"cs42l42"}, {} }; diff --git a/sound/soc/codecs/cs42l51-i2c.c b/sound/soc/codecs/cs42l51-i2c.c index 5ed2ef83dcdb..e7cc50096297 100644 --- a/sound/soc/codecs/cs42l51-i2c.c +++ b/sound/soc/codecs/cs42l51-i2c.c @@ -14,7 +14,7 @@ #include "cs42l51.h" static struct i2c_device_id cs42l51_i2c_id[] = { - {"cs42l51", 0}, + {"cs42l51"}, {} }; MODULE_DEVICE_TABLE(i2c, cs42l51_i2c_id); diff --git a/sound/soc/codecs/cs42l52.c b/sound/soc/codecs/cs42l52.c index 4fc8a6ae8d92..7128d4c62f50 100644 --- a/sound/soc/codecs/cs42l52.c +++ b/sound/soc/codecs/cs42l52.c @@ -1215,7 +1215,7 @@ MODULE_DEVICE_TABLE(of, cs42l52_of_match); static const struct i2c_device_id cs42l52_id[] = { - { "cs42l52", 0 }, + { "cs42l52" }, { } }; MODULE_DEVICE_TABLE(i2c, cs42l52_id); diff --git a/sound/soc/codecs/cs42l56.c b/sound/soc/codecs/cs42l56.c index 3e3a86dab4fc..aaa10c459b52 100644 --- a/sound/soc/codecs/cs42l56.c +++ b/sound/soc/codecs/cs42l56.c @@ -1330,7 +1330,7 @@ MODULE_DEVICE_TABLE(of, cs42l56_of_match); static const struct i2c_device_id cs42l56_id[] = { - { "cs42l56", 0 }, + { "cs42l56" }, { } }; MODULE_DEVICE_TABLE(i2c, cs42l56_id); diff --git a/sound/soc/codecs/cs42l73.c b/sound/soc/codecs/cs42l73.c index 6ab67d196d10..21ba796a5cd9 100644 --- a/sound/soc/codecs/cs42l73.c +++ b/sound/soc/codecs/cs42l73.c @@ -1372,7 +1372,7 @@ static const struct of_device_id cs42l73_of_match[] = { MODULE_DEVICE_TABLE(of, cs42l73_of_match); static const struct i2c_device_id cs42l73_id[] = { - {"cs42l73", 0}, + {"cs42l73"}, {} }; diff --git a/sound/soc/codecs/cs43130.c b/sound/soc/codecs/cs43130.c index b6d829bbe3cc..be4037890fdb 100644 --- a/sound/soc/codecs/cs43130.c +++ b/sound/soc/codecs/cs43130.c @@ -2763,10 +2763,10 @@ MODULE_DEVICE_TABLE(acpi, cs43130_acpi_match); static const struct i2c_device_id cs43130_i2c_id[] = { - {"cs43130", 0}, - {"cs4399", 0}, - {"cs43131", 0}, - {"cs43198", 0}, + {"cs43130"}, + {"cs4399"}, + {"cs43131"}, + {"cs43198"}, {} }; diff --git a/sound/soc/codecs/cs4341.c b/sound/soc/codecs/cs4341.c index 2ceca5d0e5bf..d87aae31c516 100644 --- a/sound/soc/codecs/cs4341.c +++ b/sound/soc/codecs/cs4341.c @@ -248,7 +248,7 @@ static int cs4341_i2c_probe(struct i2c_client *i2c) } static const struct i2c_device_id cs4341_i2c_id[] = { - { "cs4341", 0 }, + { "cs4341" }, { } }; MODULE_DEVICE_TABLE(i2c, cs4341_i2c_id); diff --git a/sound/soc/codecs/cs4349.c b/sound/soc/codecs/cs4349.c index ca8f21aa4837..a134ca722892 100644 --- a/sound/soc/codecs/cs4349.c +++ b/sound/soc/codecs/cs4349.c @@ -361,7 +361,7 @@ static const struct of_device_id cs4349_of_match[] = { MODULE_DEVICE_TABLE(of, cs4349_of_match); static const struct i2c_device_id cs4349_i2c_id[] = { - {"cs4349", 0}, + {"cs4349"}, {} }; diff --git a/sound/soc/codecs/cs53l30.c b/sound/soc/codecs/cs53l30.c index f4065555c36e..c0893146423b 100644 --- a/sound/soc/codecs/cs53l30.c +++ b/sound/soc/codecs/cs53l30.c @@ -1104,7 +1104,7 @@ static const struct of_device_id cs53l30_of_match[] = { MODULE_DEVICE_TABLE(of, cs53l30_of_match); static const struct i2c_device_id cs53l30_id[] = { - { "cs53l30", 0 }, + { "cs53l30" }, {} }; diff --git a/sound/soc/codecs/cx2072x.c b/sound/soc/codecs/cx2072x.c index f8b128084015..e8e22b1a1963 100644 --- a/sound/soc/codecs/cx2072x.c +++ b/sound/soc/codecs/cx2072x.c @@ -1686,8 +1686,8 @@ static void cx2072x_i2c_remove(struct i2c_client *i2c) } static const struct i2c_device_id cx2072x_i2c_id[] = { - { "cx20721", 0 }, - { "cx20723", 0 }, + { "cx20721" }, + { "cx20723" }, {} }; MODULE_DEVICE_TABLE(i2c, cx2072x_i2c_id); diff --git a/sound/soc/codecs/da7210.c b/sound/soc/codecs/da7210.c index 1e232d01809c..da2d0242019e 100644 --- a/sound/soc/codecs/da7210.c +++ b/sound/soc/codecs/da7210.c @@ -1238,7 +1238,7 @@ static int da7210_i2c_probe(struct i2c_client *i2c) } static const struct i2c_device_id da7210_i2c_id[] = { - { "da7210", 0 }, + { "da7210" }, { } }; MODULE_DEVICE_TABLE(i2c, da7210_i2c_id); diff --git a/sound/soc/codecs/da7213.c b/sound/soc/codecs/da7213.c index 369c62078780..a2b328f3b39f 100644 --- a/sound/soc/codecs/da7213.c +++ b/sound/soc/codecs/da7213.c @@ -2238,7 +2238,7 @@ static const struct dev_pm_ops da7213_pm = { }; static const struct i2c_device_id da7213_i2c_id[] = { - { "da7213", 0 }, + { "da7213" }, { } }; MODULE_DEVICE_TABLE(i2c, da7213_i2c_id); diff --git a/sound/soc/codecs/da732x.c b/sound/soc/codecs/da732x.c index f8ca1afa8af5..b747f6fa12e4 100644 --- a/sound/soc/codecs/da732x.c +++ b/sound/soc/codecs/da732x.c @@ -1546,7 +1546,7 @@ err: } static const struct i2c_device_id da732x_i2c_id[] = { - { "da7320", 0}, + { "da7320"}, { } }; MODULE_DEVICE_TABLE(i2c, da732x_i2c_id); diff --git a/sound/soc/codecs/da9055.c b/sound/soc/codecs/da9055.c index c8a34572965d..8bb8fef2a1d1 100644 --- a/sound/soc/codecs/da9055.c +++ b/sound/soc/codecs/da9055.c @@ -1511,7 +1511,7 @@ static int da9055_i2c_probe(struct i2c_client *i2c) * and PMIC, which must be different to operate together. */ static const struct i2c_device_id da9055_i2c_id[] = { - { "da9055-codec", 0 }, + { "da9055-codec" }, { } }; MODULE_DEVICE_TABLE(i2c, da9055_i2c_id); diff --git a/sound/soc/codecs/es8316.c b/sound/soc/codecs/es8316.c index e53b2856d625..61729e5b50a8 100644 --- a/sound/soc/codecs/es8316.c +++ b/sound/soc/codecs/es8316.c @@ -887,7 +887,7 @@ static int es8316_i2c_probe(struct i2c_client *i2c_client) } static const struct i2c_device_id es8316_i2c_id[] = { - {"es8316", 0 }, + {"es8316" }, {} }; MODULE_DEVICE_TABLE(i2c, es8316_i2c_id); diff --git a/sound/soc/codecs/es8326.c b/sound/soc/codecs/es8326.c index 93385f181d2c..833ea52638ab 100644 --- a/sound/soc/codecs/es8326.c +++ b/sound/soc/codecs/es8326.c @@ -1263,7 +1263,7 @@ static void es8326_i2c_remove(struct i2c_client *i2c) } static const struct i2c_device_id es8326_i2c_id[] = { - {"es8326", 0 }, + {"es8326" }, {} }; MODULE_DEVICE_TABLE(i2c, es8326_i2c_id); diff --git a/sound/soc/codecs/es8328-i2c.c b/sound/soc/codecs/es8328-i2c.c index 3c4aaa0032a0..56bfbe9261ce 100644 --- a/sound/soc/codecs/es8328-i2c.c +++ b/sound/soc/codecs/es8328-i2c.c @@ -16,8 +16,8 @@ #include "es8328.h" static const struct i2c_device_id es8328_id[] = { - { "es8328", 0 }, - { "es8388", 0 }, + { "es8328" }, + { "es8388" }, { } }; MODULE_DEVICE_TABLE(i2c, es8328_id); diff --git a/sound/soc/codecs/isabelle.c b/sound/soc/codecs/isabelle.c index f9456133a89a..b7a94631d77d 100644 --- a/sound/soc/codecs/isabelle.c +++ b/sound/soc/codecs/isabelle.c @@ -1133,7 +1133,7 @@ static int isabelle_i2c_probe(struct i2c_client *i2c) } static const struct i2c_device_id isabelle_i2c_id[] = { - { "isabelle", 0 }, + { "isabelle" }, { } }; MODULE_DEVICE_TABLE(i2c, isabelle_i2c_id); diff --git a/sound/soc/codecs/lm4857.c b/sound/soc/codecs/lm4857.c index e7542f71323d..26cdb750cbca 100644 --- a/sound/soc/codecs/lm4857.c +++ b/sound/soc/codecs/lm4857.c @@ -128,7 +128,7 @@ static int lm4857_i2c_probe(struct i2c_client *i2c) } static const struct i2c_device_id lm4857_i2c_id[] = { - { "lm4857", 0 }, + { "lm4857" }, { } }; MODULE_DEVICE_TABLE(i2c, lm4857_i2c_id); diff --git a/sound/soc/codecs/lm49453.c b/sound/soc/codecs/lm49453.c index a4094689b3dd..ab89af7965bf 100644 --- a/sound/soc/codecs/lm49453.c +++ b/sound/soc/codecs/lm49453.c @@ -1442,7 +1442,7 @@ static int lm49453_i2c_probe(struct i2c_client *i2c) } static const struct i2c_device_id lm49453_i2c_id[] = { - { "lm49453", 0 }, + { "lm49453" }, { } }; MODULE_DEVICE_TABLE(i2c, lm49453_i2c_id); diff --git a/sound/soc/codecs/max9768.c b/sound/soc/codecs/max9768.c index 8d0ca1be99c0..e4793a5d179e 100644 --- a/sound/soc/codecs/max9768.c +++ b/sound/soc/codecs/max9768.c @@ -206,7 +206,7 @@ static int max9768_i2c_probe(struct i2c_client *client) } static const struct i2c_device_id max9768_i2c_id[] = { - { "max9768", 0 }, + { "max9768" }, { } }; MODULE_DEVICE_TABLE(i2c, max9768_i2c_id); diff --git a/sound/soc/codecs/max98371.c b/sound/soc/codecs/max98371.c index f0e49179c38f..852db211ba1e 100644 --- a/sound/soc/codecs/max98371.c +++ b/sound/soc/codecs/max98371.c @@ -400,7 +400,7 @@ static int max98371_i2c_probe(struct i2c_client *i2c) } static const struct i2c_device_id max98371_i2c_id[] = { - { "max98371", 0 }, + { "max98371" }, { } }; diff --git a/sound/soc/codecs/max98373-i2c.c b/sound/soc/codecs/max98373-i2c.c index e7ec7875c4a9..1f7ff3dbcbbe 100644 --- a/sound/soc/codecs/max98373-i2c.c +++ b/sound/soc/codecs/max98373-i2c.c @@ -578,7 +578,7 @@ static int max98373_i2c_probe(struct i2c_client *i2c) } static const struct i2c_device_id max98373_i2c_id[] = { - { "max98373", 0}, + { "max98373"}, { }, }; diff --git a/sound/soc/codecs/max98388.c b/sound/soc/codecs/max98388.c index 078adec29312..b847d7c59ec0 100644 --- a/sound/soc/codecs/max98388.c +++ b/sound/soc/codecs/max98388.c @@ -976,7 +976,7 @@ static int max98388_i2c_probe(struct i2c_client *i2c) } static const struct i2c_device_id max98388_i2c_id[] = { - { "max98388", 0}, + { "max98388"}, { }, }; diff --git a/sound/soc/codecs/max98390.c b/sound/soc/codecs/max98390.c index 5b8e78e51630..57fa2db1e148 100644 --- a/sound/soc/codecs/max98390.c +++ b/sound/soc/codecs/max98390.c @@ -1104,7 +1104,7 @@ static int max98390_i2c_probe(struct i2c_client *i2c) } static const struct i2c_device_id max98390_i2c_id[] = { - { "max98390", 0}, + { "max98390"}, {}, }; diff --git a/sound/soc/codecs/max9850.c b/sound/soc/codecs/max9850.c index 8b012a85360a..c395132689b4 100644 --- a/sound/soc/codecs/max9850.c +++ b/sound/soc/codecs/max9850.c @@ -320,7 +320,7 @@ static int max9850_i2c_probe(struct i2c_client *i2c) } static const struct i2c_device_id max9850_i2c_id[] = { - { "max9850", 0 }, + { "max9850" }, { } }; MODULE_DEVICE_TABLE(i2c, max9850_i2c_id); diff --git a/sound/soc/codecs/max98520.c b/sound/soc/codecs/max98520.c index edd05253d37c..479ded22672e 100644 --- a/sound/soc/codecs/max98520.c +++ b/sound/soc/codecs/max98520.c @@ -734,7 +734,7 @@ static int max98520_i2c_probe(struct i2c_client *i2c) } static const struct i2c_device_id max98520_i2c_id[] = { - { "max98520", 0}, + { "max98520"}, { }, }; diff --git a/sound/soc/codecs/max9867.c b/sound/soc/codecs/max9867.c index 3b9dd158c34b..50db88fce904 100644 --- a/sound/soc/codecs/max9867.c +++ b/sound/soc/codecs/max9867.c @@ -684,7 +684,7 @@ static int max9867_i2c_probe(struct i2c_client *i2c) } static const struct i2c_device_id max9867_i2c_id[] = { - { "max9867", 0 }, + { "max9867" }, { } }; MODULE_DEVICE_TABLE(i2c, max9867_i2c_id); diff --git a/sound/soc/codecs/max9877.c b/sound/soc/codecs/max9877.c index 2ae64fcf29c7..1bd0d4761ca6 100644 --- a/sound/soc/codecs/max9877.c +++ b/sound/soc/codecs/max9877.c @@ -151,7 +151,7 @@ static int max9877_i2c_probe(struct i2c_client *client) } static const struct i2c_device_id max9877_i2c_id[] = { - { "max9877", 0 }, + { "max9877" }, { } }; MODULE_DEVICE_TABLE(i2c, max9877_i2c_id); diff --git a/sound/soc/codecs/max98925.c b/sound/soc/codecs/max98925.c index a9c1d85cd0d5..66c78051bd09 100644 --- a/sound/soc/codecs/max98925.c +++ b/sound/soc/codecs/max98925.c @@ -617,7 +617,7 @@ static int max98925_i2c_probe(struct i2c_client *i2c) } static const struct i2c_device_id max98925_i2c_id[] = { - { "max98925", 0 }, + { "max98925" }, { } }; MODULE_DEVICE_TABLE(i2c, max98925_i2c_id); diff --git a/sound/soc/codecs/max98926.c b/sound/soc/codecs/max98926.c index 922ce0dc4e60..ae962bda163e 100644 --- a/sound/soc/codecs/max98926.c +++ b/sound/soc/codecs/max98926.c @@ -565,7 +565,7 @@ err_out: } static const struct i2c_device_id max98926_i2c_id[] = { - { "max98926", 0 }, + { "max98926" }, { } }; MODULE_DEVICE_TABLE(i2c, max98926_i2c_id); diff --git a/sound/soc/codecs/max98927.c b/sound/soc/codecs/max98927.c index 70db9d3ff5a5..747aa6f1d54f 100644 --- a/sound/soc/codecs/max98927.c +++ b/sound/soc/codecs/max98927.c @@ -875,7 +875,7 @@ static void max98927_i2c_remove(struct i2c_client *i2c) } static const struct i2c_device_id max98927_i2c_id[] = { - { "max98927", 0}, + { "max98927"}, { }, }; diff --git a/sound/soc/codecs/ml26124.c b/sound/soc/codecs/ml26124.c index a45ef9d65703..c6585e8143a5 100644 --- a/sound/soc/codecs/ml26124.c +++ b/sound/soc/codecs/ml26124.c @@ -572,7 +572,7 @@ static int ml26124_i2c_probe(struct i2c_client *i2c) } static const struct i2c_device_id ml26124_i2c_id[] = { - { "ml26124", 0 }, + { "ml26124" }, { } }; MODULE_DEVICE_TABLE(i2c, ml26124_i2c_id); diff --git a/sound/soc/codecs/mt6660.c b/sound/soc/codecs/mt6660.c index 5c50c7de26cd..39a57f643d81 100644 --- a/sound/soc/codecs/mt6660.c +++ b/sound/soc/codecs/mt6660.c @@ -559,7 +559,7 @@ static const struct of_device_id __maybe_unused mt6660_of_id[] = { MODULE_DEVICE_TABLE(of, mt6660_of_id); static const struct i2c_device_id mt6660_i2c_id[] = { - {"mt6660", 0 }, + {"mt6660" }, {}, }; MODULE_DEVICE_TABLE(i2c, mt6660_i2c_id); diff --git a/sound/soc/codecs/nau8325.c b/sound/soc/codecs/nau8325.c index d65f73144597..2266f320a8f2 100644 --- a/sound/soc/codecs/nau8325.c +++ b/sound/soc/codecs/nau8325.c @@ -871,7 +871,7 @@ err: } static const struct i2c_device_id nau8325_i2c_ids[] = { - { "nau8325", 0 }, + { "nau8325" }, { } }; MODULE_DEVICE_TABLE(i2c, nau8325_i2c_ids); diff --git a/sound/soc/codecs/nau8540.c b/sound/soc/codecs/nau8540.c index 22251fb2fa1f..7e59448e7ac6 100644 --- a/sound/soc/codecs/nau8540.c +++ b/sound/soc/codecs/nau8540.c @@ -965,7 +965,7 @@ static int nau8540_i2c_probe(struct i2c_client *i2c) } static const struct i2c_device_id nau8540_i2c_ids[] = { - { "nau8540", 0 }, + { "nau8540" }, { } }; MODULE_DEVICE_TABLE(i2c, nau8540_i2c_ids); diff --git a/sound/soc/codecs/nau8810.c b/sound/soc/codecs/nau8810.c index 97a54059474c..dc3aaca89919 100644 --- a/sound/soc/codecs/nau8810.c +++ b/sound/soc/codecs/nau8810.c @@ -895,9 +895,9 @@ static int nau8810_i2c_probe(struct i2c_client *i2c) } static const struct i2c_device_id nau8810_i2c_id[] = { - { "nau8810", 0 }, - { "nau8812", 0 }, - { "nau8814", 0 }, + { "nau8810" }, + { "nau8812" }, + { "nau8814" }, { } }; MODULE_DEVICE_TABLE(i2c, nau8810_i2c_id); diff --git a/sound/soc/codecs/nau8821.c b/sound/soc/codecs/nau8821.c index 6818bbd1d3c7..de5c4db05c8f 100644 --- a/sound/soc/codecs/nau8821.c +++ b/sound/soc/codecs/nau8821.c @@ -1922,7 +1922,7 @@ static int nau8821_i2c_probe(struct i2c_client *i2c) } static const struct i2c_device_id nau8821_i2c_ids[] = { - { "nau8821", 0 }, + { "nau8821" }, { } }; MODULE_DEVICE_TABLE(i2c, nau8821_i2c_ids); diff --git a/sound/soc/codecs/nau8822.c b/sound/soc/codecs/nau8822.c index 7199d734c79f..e6909e64dfa3 100644 --- a/sound/soc/codecs/nau8822.c +++ b/sound/soc/codecs/nau8822.c @@ -1151,7 +1151,7 @@ static int nau8822_i2c_probe(struct i2c_client *i2c) } static const struct i2c_device_id nau8822_i2c_id[] = { - { "nau8822", 0 }, + { "nau8822" }, { } }; MODULE_DEVICE_TABLE(i2c, nau8822_i2c_id); diff --git a/sound/soc/codecs/nau8824.c b/sound/soc/codecs/nau8824.c index 704af1cf8cbf..f92b95b21cae 100644 --- a/sound/soc/codecs/nau8824.c +++ b/sound/soc/codecs/nau8824.c @@ -2003,7 +2003,7 @@ static int nau8824_i2c_probe(struct i2c_client *i2c) } static const struct i2c_device_id nau8824_i2c_ids[] = { - { "nau8824", 0 }, + { "nau8824" }, { } }; MODULE_DEVICE_TABLE(i2c, nau8824_i2c_ids); diff --git a/sound/soc/codecs/nau8825.c b/sound/soc/codecs/nau8825.c index cd30ad649bae..bde25bc6909d 100644 --- a/sound/soc/codecs/nau8825.c +++ b/sound/soc/codecs/nau8825.c @@ -2934,7 +2934,7 @@ static void nau8825_i2c_remove(struct i2c_client *client) {} static const struct i2c_device_id nau8825_i2c_ids[] = { - { "nau8825", 0 }, + { "nau8825" }, { } }; MODULE_DEVICE_TABLE(i2c, nau8825_i2c_ids); diff --git a/sound/soc/codecs/pcm1681.c b/sound/soc/codecs/pcm1681.c index 316ad53bc66a..fc152496d5dc 100644 --- a/sound/soc/codecs/pcm1681.c +++ b/sound/soc/codecs/pcm1681.c @@ -291,7 +291,7 @@ static const struct snd_soc_component_driver soc_component_dev_pcm1681 = { }; static const struct i2c_device_id pcm1681_i2c_id[] = { - {"pcm1681", 0}, + {"pcm1681"}, {} }; MODULE_DEVICE_TABLE(i2c, pcm1681_i2c_id); diff --git a/sound/soc/codecs/pcm1789-i2c.c b/sound/soc/codecs/pcm1789-i2c.c index f2d0b4d21e41..abadf4f8ed5e 100644 --- a/sound/soc/codecs/pcm1789-i2c.c +++ b/sound/soc/codecs/pcm1789-i2c.c @@ -41,7 +41,7 @@ MODULE_DEVICE_TABLE(of, pcm1789_of_match); #endif static const struct i2c_device_id pcm1789_i2c_ids[] = { - { "pcm1789", 0 }, + { "pcm1789" }, { } }; MODULE_DEVICE_TABLE(i2c, pcm1789_i2c_ids); diff --git a/sound/soc/codecs/pcm179x-i2c.c b/sound/soc/codecs/pcm179x-i2c.c index 10579681f44b..effc1dd6df22 100644 --- a/sound/soc/codecs/pcm179x-i2c.c +++ b/sound/soc/codecs/pcm179x-i2c.c @@ -38,7 +38,7 @@ MODULE_DEVICE_TABLE(of, pcm179x_of_match); #endif static const struct i2c_device_id pcm179x_i2c_ids[] = { - { "pcm179x", 0 }, + { "pcm179x" }, { } }; MODULE_DEVICE_TABLE(i2c, pcm179x_i2c_ids); diff --git a/sound/soc/codecs/rt1011.c b/sound/soc/codecs/rt1011.c index d5285baad53a..a0e75b03e9dc 100644 --- a/sound/soc/codecs/rt1011.c +++ b/sound/soc/codecs/rt1011.c @@ -2206,7 +2206,7 @@ MODULE_DEVICE_TABLE(acpi, rt1011_acpi_match); #endif static const struct i2c_device_id rt1011_i2c_id[] = { - { "rt1011", 0 }, + { "rt1011" }, { } }; MODULE_DEVICE_TABLE(i2c, rt1011_i2c_id); diff --git a/sound/soc/codecs/rt1015.c b/sound/soc/codecs/rt1015.c index 1250cfaf2adc..0f806dde9c39 100644 --- a/sound/soc/codecs/rt1015.c +++ b/sound/soc/codecs/rt1015.c @@ -1097,7 +1097,7 @@ static const struct regmap_config rt1015_regmap = { }; static const struct i2c_device_id rt1015_i2c_id[] = { - { "rt1015", 0 }, + { "rt1015" }, { } }; MODULE_DEVICE_TABLE(i2c, rt1015_i2c_id); diff --git a/sound/soc/codecs/rt1016.c b/sound/soc/codecs/rt1016.c index 919a1f25e584..fed4da23cba2 100644 --- a/sound/soc/codecs/rt1016.c +++ b/sound/soc/codecs/rt1016.c @@ -608,7 +608,7 @@ static const struct regmap_config rt1016_regmap = { }; static const struct i2c_device_id rt1016_i2c_id[] = { - { "rt1016", 0 }, + { "rt1016" }, { } }; MODULE_DEVICE_TABLE(i2c, rt1016_i2c_id); diff --git a/sound/soc/codecs/rt1019.c b/sound/soc/codecs/rt1019.c index ceb8baa6a20d..d989d06a2614 100644 --- a/sound/soc/codecs/rt1019.c +++ b/sound/soc/codecs/rt1019.c @@ -540,7 +540,7 @@ static const struct regmap_config rt1019_regmap = { }; static const struct i2c_device_id rt1019_i2c_id[] = { - { "rt1019", 0 }, + { "rt1019" }, { } }; MODULE_DEVICE_TABLE(i2c, rt1019_i2c_id); diff --git a/sound/soc/codecs/rt1305.c b/sound/soc/codecs/rt1305.c index 80888cbcf49c..c2b55be8d165 100644 --- a/sound/soc/codecs/rt1305.c +++ b/sound/soc/codecs/rt1305.c @@ -981,8 +981,8 @@ MODULE_DEVICE_TABLE(acpi, rt1305_acpi_match); #endif static const struct i2c_device_id rt1305_i2c_id[] = { - { "rt1305", 0 }, - { "rt1306", 0 }, + { "rt1305" }, + { "rt1306" }, { } }; MODULE_DEVICE_TABLE(i2c, rt1305_i2c_id); diff --git a/sound/soc/codecs/rt1308.c b/sound/soc/codecs/rt1308.c index 86afb429d423..b366338cea71 100644 --- a/sound/soc/codecs/rt1308.c +++ b/sound/soc/codecs/rt1308.c @@ -795,7 +795,7 @@ MODULE_DEVICE_TABLE(acpi, rt1308_acpi_match); #endif static const struct i2c_device_id rt1308_i2c_id[] = { - { "rt1308", 0 }, + { "rt1308" }, { } }; MODULE_DEVICE_TABLE(i2c, rt1308_i2c_id); diff --git a/sound/soc/codecs/rt274.c b/sound/soc/codecs/rt274.c index 6e7843484250..bd61a257d7b5 100644 --- a/sound/soc/codecs/rt274.c +++ b/sound/soc/codecs/rt274.c @@ -1097,7 +1097,7 @@ MODULE_DEVICE_TABLE(of, rt274_of_match); #endif static const struct i2c_device_id rt274_i2c_id[] = { - {"rt274", 0}, + {"rt274"}, {} }; MODULE_DEVICE_TABLE(i2c, rt274_i2c_id); diff --git a/sound/soc/codecs/rt286.c b/sound/soc/codecs/rt286.c index f8994f4968c5..d0f533120c33 100644 --- a/sound/soc/codecs/rt286.c +++ b/sound/soc/codecs/rt286.c @@ -1075,8 +1075,8 @@ static const struct regmap_config rt286_regmap = { }; static const struct i2c_device_id rt286_i2c_id[] = { - {"rt286", 0}, - {"rt288", 0}, + {"rt286"}, + {"rt288"}, {} }; MODULE_DEVICE_TABLE(i2c, rt286_i2c_id); diff --git a/sound/soc/codecs/rt298.c b/sound/soc/codecs/rt298.c index 03d9839a5de3..13aef6c5e91c 100644 --- a/sound/soc/codecs/rt298.c +++ b/sound/soc/codecs/rt298.c @@ -1137,7 +1137,7 @@ static const struct regmap_config rt298_regmap = { }; static const struct i2c_device_id rt298_i2c_id[] = { - {"rt298", 0}, + {"rt298"}, {} }; MODULE_DEVICE_TABLE(i2c, rt298_i2c_id); diff --git a/sound/soc/codecs/rt5514.c b/sound/soc/codecs/rt5514.c index a8cdc3d6994d..2b3c0f9e178c 100644 --- a/sound/soc/codecs/rt5514.c +++ b/sound/soc/codecs/rt5514.c @@ -1199,7 +1199,7 @@ static const struct regmap_config rt5514_regmap = { }; static const struct i2c_device_id rt5514_i2c_id[] = { - { "rt5514", 0 }, + { "rt5514" }, { } }; MODULE_DEVICE_TABLE(i2c, rt5514_i2c_id); diff --git a/sound/soc/codecs/rt5616.c b/sound/soc/codecs/rt5616.c index e7aa60e73961..34461c462009 100644 --- a/sound/soc/codecs/rt5616.c +++ b/sound/soc/codecs/rt5616.c @@ -1320,7 +1320,7 @@ static const struct regmap_config rt5616_regmap = { }; static const struct i2c_device_id rt5616_i2c_id[] = { - { "rt5616", 0 }, + { "rt5616" }, { } }; MODULE_DEVICE_TABLE(i2c, rt5616_i2c_id); diff --git a/sound/soc/codecs/rt5631.c b/sound/soc/codecs/rt5631.c index a64e66c2d3c4..12df0c4f2097 100644 --- a/sound/soc/codecs/rt5631.c +++ b/sound/soc/codecs/rt5631.c @@ -1669,8 +1669,8 @@ static const struct snd_soc_component_driver soc_component_dev_rt5631 = { }; static const struct i2c_device_id rt5631_i2c_id[] = { - { "rt5631", 0 }, - { "alc5631", 0 }, + { "rt5631" }, + { "alc5631" }, { } }; MODULE_DEVICE_TABLE(i2c, rt5631_i2c_id); diff --git a/sound/soc/codecs/rt5640.c b/sound/soc/codecs/rt5640.c index 174872ef35d2..16f3425a3e35 100644 --- a/sound/soc/codecs/rt5640.c +++ b/sound/soc/codecs/rt5640.c @@ -2949,9 +2949,9 @@ static const struct regmap_config rt5640_regmap = { }; static const struct i2c_device_id rt5640_i2c_id[] = { - { "rt5640", 0 }, - { "rt5639", 0 }, - { "rt5642", 0 }, + { "rt5640" }, + { "rt5639" }, + { "rt5642" }, { } }; MODULE_DEVICE_TABLE(i2c, rt5640_i2c_id); diff --git a/sound/soc/codecs/rt5645.c b/sound/soc/codecs/rt5645.c index d0d24a53df74..05f574bf8b8f 100644 --- a/sound/soc/codecs/rt5645.c +++ b/sound/soc/codecs/rt5645.c @@ -3630,8 +3630,8 @@ static const struct regmap_config temp_regmap = { }; static const struct i2c_device_id rt5645_i2c_id[] = { - { "rt5645", 0 }, - { "rt5650", 0 }, + { "rt5645" }, + { "rt5650" }, { } }; MODULE_DEVICE_TABLE(i2c, rt5645_i2c_id); diff --git a/sound/soc/codecs/rt5651.c b/sound/soc/codecs/rt5651.c index 33a34bd0b405..00421a1f54bf 100644 --- a/sound/soc/codecs/rt5651.c +++ b/sound/soc/codecs/rt5651.c @@ -2199,7 +2199,7 @@ MODULE_DEVICE_TABLE(acpi, rt5651_acpi_match); #endif static const struct i2c_device_id rt5651_i2c_id[] = { - { "rt5651", 0 }, + { "rt5651" }, { } }; MODULE_DEVICE_TABLE(i2c, rt5651_i2c_id); diff --git a/sound/soc/codecs/rt5659.c b/sound/soc/codecs/rt5659.c index fb094c0fe740..a2652fa6e1d7 100644 --- a/sound/soc/codecs/rt5659.c +++ b/sound/soc/codecs/rt5659.c @@ -3815,8 +3815,8 @@ static const struct regmap_config rt5659_regmap = { }; static const struct i2c_device_id rt5659_i2c_id[] = { - { "rt5658", 0 }, - { "rt5659", 0 }, + { "rt5658" }, + { "rt5659" }, { } }; MODULE_DEVICE_TABLE(i2c, rt5659_i2c_id); diff --git a/sound/soc/codecs/rt5660.c b/sound/soc/codecs/rt5660.c index d5c2f0f2df98..3ac41d2c279b 100644 --- a/sound/soc/codecs/rt5660.c +++ b/sound/soc/codecs/rt5660.c @@ -1224,7 +1224,7 @@ static const struct regmap_config rt5660_regmap = { }; static const struct i2c_device_id rt5660_i2c_id[] = { - { "rt5660", 0 }, + { "rt5660" }, { } }; MODULE_DEVICE_TABLE(i2c, rt5660_i2c_id); diff --git a/sound/soc/codecs/rt5663.c b/sound/soc/codecs/rt5663.c index 161dcb3915f9..9d32debd3689 100644 --- a/sound/soc/codecs/rt5663.c +++ b/sound/soc/codecs/rt5663.c @@ -3307,7 +3307,7 @@ static const struct regmap_config temp_regmap = { }; static const struct i2c_device_id rt5663_i2c_id[] = { - { "rt5663", 0 }, + { "rt5663" }, {} }; MODULE_DEVICE_TABLE(i2c, rt5663_i2c_id); diff --git a/sound/soc/codecs/rt5665.c b/sound/soc/codecs/rt5665.c index 6f778c8f0832..47df14ba5278 100644 --- a/sound/soc/codecs/rt5665.c +++ b/sound/soc/codecs/rt5665.c @@ -4635,7 +4635,7 @@ static const struct regmap_config rt5665_regmap = { }; static const struct i2c_device_id rt5665_i2c_id[] = { - {"rt5665", 0}, + {"rt5665"}, {} }; MODULE_DEVICE_TABLE(i2c, rt5665_i2c_id); diff --git a/sound/soc/codecs/rt5668.c b/sound/soc/codecs/rt5668.c index 6d8e228ccb57..494ca3ce9b96 100644 --- a/sound/soc/codecs/rt5668.c +++ b/sound/soc/codecs/rt5668.c @@ -2378,7 +2378,7 @@ static const struct regmap_config rt5668_regmap = { }; static const struct i2c_device_id rt5668_i2c_id[] = { - {"rt5668b", 0}, + {"rt5668b"}, {} }; MODULE_DEVICE_TABLE(i2c, rt5668_i2c_id); diff --git a/sound/soc/codecs/rt5670.c b/sound/soc/codecs/rt5670.c index 0e34293f3395..30bf96c35b58 100644 --- a/sound/soc/codecs/rt5670.c +++ b/sound/soc/codecs/rt5670.c @@ -2871,9 +2871,9 @@ static const struct regmap_config rt5670_regmap = { }; static const struct i2c_device_id rt5670_i2c_id[] = { - { "rt5670", 0 }, - { "rt5671", 0 }, - { "rt5672", 0 }, + { "rt5670" }, + { "rt5671" }, + { "rt5672" }, { } }; MODULE_DEVICE_TABLE(i2c, rt5670_i2c_id); diff --git a/sound/soc/codecs/rt5682-i2c.c b/sound/soc/codecs/rt5682-i2c.c index 62f26ce9d476..ff9e14fad0cd 100644 --- a/sound/soc/codecs/rt5682-i2c.c +++ b/sound/soc/codecs/rt5682-i2c.c @@ -318,7 +318,7 @@ static const struct acpi_device_id rt5682_acpi_match[] = { MODULE_DEVICE_TABLE(acpi, rt5682_acpi_match); static const struct i2c_device_id rt5682_i2c_id[] = { - {"rt5682", 0}, + {"rt5682"}, {} }; MODULE_DEVICE_TABLE(i2c, rt5682_i2c_id); diff --git a/sound/soc/codecs/rt5682s.c b/sound/soc/codecs/rt5682s.c index 12741668fdb3..f50f196d700d 100644 --- a/sound/soc/codecs/rt5682s.c +++ b/sound/soc/codecs/rt5682s.c @@ -3319,7 +3319,7 @@ static const struct acpi_device_id rt5682s_acpi_match[] = { MODULE_DEVICE_TABLE(acpi, rt5682s_acpi_match); static const struct i2c_device_id rt5682s_i2c_id[] = { - {"rt5682s", 0}, + {"rt5682s"}, {} }; MODULE_DEVICE_TABLE(i2c, rt5682s_i2c_id); diff --git a/sound/soc/codecs/sgtl5000.c b/sound/soc/codecs/sgtl5000.c index 2f468f41b94d..7aa89e34657e 100644 --- a/sound/soc/codecs/sgtl5000.c +++ b/sound/soc/codecs/sgtl5000.c @@ -1809,7 +1809,7 @@ static void sgtl5000_i2c_shutdown(struct i2c_client *client) } static const struct i2c_device_id sgtl5000_id[] = { - {"sgtl5000", 0}, + {"sgtl5000"}, {}, }; diff --git a/sound/soc/codecs/sma1303.c b/sound/soc/codecs/sma1303.c index 61072e7574a0..980c48cbc348 100644 --- a/sound/soc/codecs/sma1303.c +++ b/sound/soc/codecs/sma1303.c @@ -1791,7 +1791,7 @@ static void sma1303_i2c_remove(struct i2c_client *client) } static const struct i2c_device_id sma1303_i2c_id[] = { - {"sma1303", 0}, + {"sma1303"}, {} }; MODULE_DEVICE_TABLE(i2c, sma1303_i2c_id); diff --git a/sound/soc/codecs/src4xxx-i2c.c b/sound/soc/codecs/src4xxx-i2c.c index 93af8e209b05..55f00ce7c718 100644 --- a/sound/soc/codecs/src4xxx-i2c.c +++ b/sound/soc/codecs/src4xxx-i2c.c @@ -19,7 +19,7 @@ static int src4xxx_i2c_probe(struct i2c_client *i2c) } static const struct i2c_device_id src4xxx_i2c_ids[] = { - { "src4392", 0 }, + { "src4392" }, { } }; MODULE_DEVICE_TABLE(i2c, src4xxx_i2c_ids); diff --git a/sound/soc/codecs/ssm2518.c b/sound/soc/codecs/ssm2518.c index d20d897407eb..06016e88dd27 100644 --- a/sound/soc/codecs/ssm2518.c +++ b/sound/soc/codecs/ssm2518.c @@ -793,7 +793,7 @@ MODULE_DEVICE_TABLE(of, ssm2518_dt_ids); #endif static const struct i2c_device_id ssm2518_i2c_ids[] = { - { "ssm2518", 0 }, + { "ssm2518" }, { } }; MODULE_DEVICE_TABLE(i2c, ssm2518_i2c_ids); diff --git a/sound/soc/codecs/ssm4567.c b/sound/soc/codecs/ssm4567.c index 0a6f04d8f636..3e09c85abedb 100644 --- a/sound/soc/codecs/ssm4567.c +++ b/sound/soc/codecs/ssm4567.c @@ -471,7 +471,7 @@ static int ssm4567_i2c_probe(struct i2c_client *i2c) } static const struct i2c_device_id ssm4567_i2c_ids[] = { - { "ssm4567", 0 }, + { "ssm4567" }, { } }; MODULE_DEVICE_TABLE(i2c, ssm4567_i2c_ids); diff --git a/sound/soc/codecs/sta32x.c b/sound/soc/codecs/sta32x.c index fcf0dbfbbbca..bd8848ea1ec2 100644 --- a/sound/soc/codecs/sta32x.c +++ b/sound/soc/codecs/sta32x.c @@ -1154,9 +1154,9 @@ static int sta32x_i2c_probe(struct i2c_client *i2c) } static const struct i2c_device_id sta32x_i2c_id[] = { - { "sta326", 0 }, - { "sta328", 0 }, - { "sta329", 0 }, + { "sta326" }, + { "sta328" }, + { "sta329" }, { } }; MODULE_DEVICE_TABLE(i2c, sta32x_i2c_id); diff --git a/sound/soc/codecs/sta350.c b/sound/soc/codecs/sta350.c index 612cc1d7eafe..d1450de92652 100644 --- a/sound/soc/codecs/sta350.c +++ b/sound/soc/codecs/sta350.c @@ -1238,7 +1238,7 @@ static void sta350_i2c_remove(struct i2c_client *client) {} static const struct i2c_device_id sta350_i2c_id[] = { - { "sta350", 0 }, + { "sta350" }, { } }; MODULE_DEVICE_TABLE(i2c, sta350_i2c_id); diff --git a/sound/soc/codecs/sta529.c b/sound/soc/codecs/sta529.c index eedafef775e5..f7718491c899 100644 --- a/sound/soc/codecs/sta529.c +++ b/sound/soc/codecs/sta529.c @@ -363,7 +363,7 @@ static int sta529_i2c_probe(struct i2c_client *i2c) } static const struct i2c_device_id sta529_i2c_id[] = { - { "sta529", 0 }, + { "sta529" }, { } }; MODULE_DEVICE_TABLE(i2c, sta529_i2c_id); diff --git a/sound/soc/codecs/tas2552.c b/sound/soc/codecs/tas2552.c index 8c9dc318b0e8..40f5f27e74c0 100644 --- a/sound/soc/codecs/tas2552.c +++ b/sound/soc/codecs/tas2552.c @@ -742,7 +742,7 @@ static void tas2552_i2c_remove(struct i2c_client *client) } static const struct i2c_device_id tas2552_id[] = { - { "tas2552", 0 }, + { "tas2552" }, { } }; MODULE_DEVICE_TABLE(i2c, tas2552_id); diff --git a/sound/soc/codecs/tas2764.c b/sound/soc/codecs/tas2764.c index a9838e0738cc..1dc719d726ab 100644 --- a/sound/soc/codecs/tas2764.c +++ b/sound/soc/codecs/tas2764.c @@ -738,7 +738,7 @@ static int tas2764_i2c_probe(struct i2c_client *client) } static const struct i2c_device_id tas2764_i2c_id[] = { - { "tas2764", 0}, + { "tas2764"}, { } }; MODULE_DEVICE_TABLE(i2c, tas2764_i2c_id); diff --git a/sound/soc/codecs/tas2770.c b/sound/soc/codecs/tas2770.c index 99bf402eb566..67bc1c8b0131 100644 --- a/sound/soc/codecs/tas2770.c +++ b/sound/soc/codecs/tas2770.c @@ -702,7 +702,7 @@ static int tas2770_i2c_probe(struct i2c_client *client) } static const struct i2c_device_id tas2770_i2c_id[] = { - { "tas2770", 0}, + { "tas2770"}, { } }; MODULE_DEVICE_TABLE(i2c, tas2770_i2c_id); diff --git a/sound/soc/codecs/tas2780.c b/sound/soc/codecs/tas2780.c index 972e8ea5ebde..a18ccf5fb7ad 100644 --- a/sound/soc/codecs/tas2780.c +++ b/sound/soc/codecs/tas2780.c @@ -626,7 +626,7 @@ static int tas2780_i2c_probe(struct i2c_client *client) } static const struct i2c_device_id tas2780_i2c_id[] = { - { "tas2780", 0}, + { "tas2780"}, { } }; MODULE_DEVICE_TABLE(i2c, tas2780_i2c_id); diff --git a/sound/soc/codecs/tas5086.c b/sound/soc/codecs/tas5086.c index f52c14b43f28..6d45df3b9ba4 100644 --- a/sound/soc/codecs/tas5086.c +++ b/sound/soc/codecs/tas5086.c @@ -891,7 +891,7 @@ static const struct snd_soc_component_driver soc_component_dev_tas5086 = { }; static const struct i2c_device_id tas5086_i2c_id[] = { - { "tas5086", 0 }, + { "tas5086" }, { } }; MODULE_DEVICE_TABLE(i2c, tas5086_i2c_id); diff --git a/sound/soc/codecs/tas6424.c b/sound/soc/codecs/tas6424.c index da89e8c681dd..bb0500e9d3ea 100644 --- a/sound/soc/codecs/tas6424.c +++ b/sound/soc/codecs/tas6424.c @@ -792,7 +792,7 @@ static void tas6424_i2c_remove(struct i2c_client *client) } static const struct i2c_device_id tas6424_i2c_ids[] = { - { "tas6424", 0 }, + { "tas6424" }, { } }; MODULE_DEVICE_TABLE(i2c, tas6424_i2c_ids); diff --git a/sound/soc/codecs/tda7419.c b/sound/soc/codecs/tda7419.c index e187d74a1737..386b99c8023b 100644 --- a/sound/soc/codecs/tda7419.c +++ b/sound/soc/codecs/tda7419.c @@ -614,7 +614,7 @@ static int tda7419_probe(struct i2c_client *i2c) } static const struct i2c_device_id tda7419_i2c_id[] = { - { "tda7419", 0 }, + { "tda7419" }, { } }; MODULE_DEVICE_TABLE(i2c, tda7419_i2c_id); diff --git a/sound/soc/codecs/tfa9879.c b/sound/soc/codecs/tfa9879.c index 8cca2ceadd9e..ac0c5c337677 100644 --- a/sound/soc/codecs/tfa9879.c +++ b/sound/soc/codecs/tfa9879.c @@ -296,7 +296,7 @@ static int tfa9879_i2c_probe(struct i2c_client *i2c) } static const struct i2c_device_id tfa9879_i2c_id[] = { - { "tfa9879", 0 }, + { "tfa9879" }, { } }; MODULE_DEVICE_TABLE(i2c, tfa9879_i2c_id); diff --git a/sound/soc/codecs/tlv320aic23-i2c.c b/sound/soc/codecs/tlv320aic23-i2c.c index 9692ae007c91..a31fb95048b8 100644 --- a/sound/soc/codecs/tlv320aic23-i2c.c +++ b/sound/soc/codecs/tlv320aic23-i2c.c @@ -28,7 +28,7 @@ static int tlv320aic23_i2c_probe(struct i2c_client *i2c) } static const struct i2c_device_id tlv320aic23_id[] = { - {"tlv320aic23", 0}, + {"tlv320aic23"}, {} }; diff --git a/sound/soc/codecs/ts3a227e.c b/sound/soc/codecs/ts3a227e.c index 6d9166d9116a..dbf448dd8864 100644 --- a/sound/soc/codecs/ts3a227e.c +++ b/sound/soc/codecs/ts3a227e.c @@ -427,7 +427,7 @@ static const struct dev_pm_ops ts3a227e_pm = { }; static const struct i2c_device_id ts3a227e_i2c_ids[] = { - { "ts3a227e", 0 }, + { "ts3a227e" }, { } }; MODULE_DEVICE_TABLE(i2c, ts3a227e_i2c_ids); diff --git a/sound/soc/codecs/tscs42xx.c b/sound/soc/codecs/tscs42xx.c index 1eefc1fe6ea8..f8a3d1b40990 100644 --- a/sound/soc/codecs/tscs42xx.c +++ b/sound/soc/codecs/tscs42xx.c @@ -1485,8 +1485,8 @@ static int tscs42xx_i2c_probe(struct i2c_client *i2c) } static const struct i2c_device_id tscs42xx_i2c_id[] = { - { "tscs42A1", 0 }, - { "tscs42A2", 0 }, + { "tscs42A1" }, + { "tscs42A2" }, { } }; MODULE_DEVICE_TABLE(i2c, tscs42xx_i2c_id); diff --git a/sound/soc/codecs/tscs454.c b/sound/soc/codecs/tscs454.c index 744aef32a21f..850e5de9271e 100644 --- a/sound/soc/codecs/tscs454.c +++ b/sound/soc/codecs/tscs454.c @@ -3457,7 +3457,7 @@ static int tscs454_i2c_probe(struct i2c_client *i2c) } static const struct i2c_device_id tscs454_i2c_id[] = { - { "tscs454", 0 }, + { "tscs454" }, { } }; MODULE_DEVICE_TABLE(i2c, tscs454_i2c_id); diff --git a/sound/soc/codecs/uda1380.c b/sound/soc/codecs/uda1380.c index 5c5751dc14e5..4f8fdd574585 100644 --- a/sound/soc/codecs/uda1380.c +++ b/sound/soc/codecs/uda1380.c @@ -782,7 +782,7 @@ static int uda1380_i2c_probe(struct i2c_client *i2c) } static const struct i2c_device_id uda1380_i2c_id[] = { - { "uda1380", 0 }, + { "uda1380" }, { } }; MODULE_DEVICE_TABLE(i2c, uda1380_i2c_id); diff --git a/sound/soc/codecs/wm1250-ev1.c b/sound/soc/codecs/wm1250-ev1.c index 9fa6df48799b..1f59309d8c69 100644 --- a/sound/soc/codecs/wm1250-ev1.c +++ b/sound/soc/codecs/wm1250-ev1.c @@ -204,7 +204,7 @@ static int wm1250_ev1_probe(struct i2c_client *i2c) } static const struct i2c_device_id wm1250_ev1_i2c_id[] = { - { "wm1250-ev1", 0 }, + { "wm1250-ev1" }, { } }; MODULE_DEVICE_TABLE(i2c, wm1250_ev1_i2c_id); diff --git a/sound/soc/codecs/wm2000.c b/sound/soc/codecs/wm2000.c index 9571ea53cb3f..a07a443ba196 100644 --- a/sound/soc/codecs/wm2000.c +++ b/sound/soc/codecs/wm2000.c @@ -929,7 +929,7 @@ out: } static const struct i2c_device_id wm2000_i2c_id[] = { - { "wm2000", 0 }, + { "wm2000" }, { } }; MODULE_DEVICE_TABLE(i2c, wm2000_i2c_id); diff --git a/sound/soc/codecs/wm2200.c b/sound/soc/codecs/wm2200.c index 69c9c2bd7e7b..841247173d98 100644 --- a/sound/soc/codecs/wm2200.c +++ b/sound/soc/codecs/wm2200.c @@ -2474,7 +2474,7 @@ static const struct dev_pm_ops wm2200_pm = { }; static const struct i2c_device_id wm2200_i2c_id[] = { - { "wm2200", 0 }, + { "wm2200" }, { } }; MODULE_DEVICE_TABLE(i2c, wm2200_i2c_id); diff --git a/sound/soc/codecs/wm5100.c b/sound/soc/codecs/wm5100.c index 7ee4b45c0834..11bbc94a282c 100644 --- a/sound/soc/codecs/wm5100.c +++ b/sound/soc/codecs/wm5100.c @@ -2670,7 +2670,7 @@ static const struct dev_pm_ops wm5100_pm = { }; static const struct i2c_device_id wm5100_i2c_id[] = { - { "wm5100", 0 }, + { "wm5100" }, { } }; MODULE_DEVICE_TABLE(i2c, wm5100_i2c_id); diff --git a/sound/soc/codecs/wm8510.c b/sound/soc/codecs/wm8510.c index 0e671cce8447..4a31d6f89502 100644 --- a/sound/soc/codecs/wm8510.c +++ b/sound/soc/codecs/wm8510.c @@ -668,7 +668,7 @@ static int wm8510_i2c_probe(struct i2c_client *i2c) } static const struct i2c_device_id wm8510_i2c_id[] = { - { "wm8510", 0 }, + { "wm8510" }, { } }; MODULE_DEVICE_TABLE(i2c, wm8510_i2c_id); diff --git a/sound/soc/codecs/wm8523.c b/sound/soc/codecs/wm8523.c index 41b14538b03c..138eba7e577a 100644 --- a/sound/soc/codecs/wm8523.c +++ b/sound/soc/codecs/wm8523.c @@ -517,7 +517,7 @@ err_enable: } static const struct i2c_device_id wm8523_i2c_id[] = { - { "wm8523", 0 }, + { "wm8523" }, { } }; MODULE_DEVICE_TABLE(i2c, wm8523_i2c_id); diff --git a/sound/soc/codecs/wm8711.c b/sound/soc/codecs/wm8711.c index 7d339cc65208..a1c99bbf5aa1 100644 --- a/sound/soc/codecs/wm8711.c +++ b/sound/soc/codecs/wm8711.c @@ -454,7 +454,7 @@ static int wm8711_i2c_probe(struct i2c_client *client) } static const struct i2c_device_id wm8711_i2c_id[] = { - { "wm8711", 0 }, + { "wm8711" }, { } }; MODULE_DEVICE_TABLE(i2c, wm8711_i2c_id); diff --git a/sound/soc/codecs/wm8728.c b/sound/soc/codecs/wm8728.c index d9cc78fbf1ea..2cbd6b189416 100644 --- a/sound/soc/codecs/wm8728.c +++ b/sound/soc/codecs/wm8728.c @@ -295,7 +295,7 @@ static int wm8728_i2c_probe(struct i2c_client *i2c) } static const struct i2c_device_id wm8728_i2c_id[] = { - { "wm8728", 0 }, + { "wm8728" }, { } }; MODULE_DEVICE_TABLE(i2c, wm8728_i2c_id); diff --git a/sound/soc/codecs/wm8731-i2c.c b/sound/soc/codecs/wm8731-i2c.c index 7f68ad0380e0..1254e583af51 100644 --- a/sound/soc/codecs/wm8731-i2c.c +++ b/sound/soc/codecs/wm8731-i2c.c @@ -47,7 +47,7 @@ static int wm8731_i2c_probe(struct i2c_client *i2c) } static const struct i2c_device_id wm8731_i2c_id[] = { - { "wm8731", 0 }, + { "wm8731" }, { } }; MODULE_DEVICE_TABLE(i2c, wm8731_i2c_id); diff --git a/sound/soc/codecs/wm8737.c b/sound/soc/codecs/wm8737.c index a0ba1e7dee98..efdc242c2ede 100644 --- a/sound/soc/codecs/wm8737.c +++ b/sound/soc/codecs/wm8737.c @@ -639,7 +639,7 @@ static int wm8737_i2c_probe(struct i2c_client *i2c) } static const struct i2c_device_id wm8737_i2c_id[] = { - { "wm8737", 0 }, + { "wm8737" }, { } }; MODULE_DEVICE_TABLE(i2c, wm8737_i2c_id); diff --git a/sound/soc/codecs/wm8741.c b/sound/soc/codecs/wm8741.c index a0848774427b..4863d6ac461b 100644 --- a/sound/soc/codecs/wm8741.c +++ b/sound/soc/codecs/wm8741.c @@ -606,7 +606,7 @@ static int wm8741_i2c_probe(struct i2c_client *i2c) } static const struct i2c_device_id wm8741_i2c_id[] = { - { "wm8741", 0 }, + { "wm8741" }, { } }; MODULE_DEVICE_TABLE(i2c, wm8741_i2c_id); diff --git a/sound/soc/codecs/wm8750.c b/sound/soc/codecs/wm8750.c index b8d76cd001da..cae97fa3bcb0 100644 --- a/sound/soc/codecs/wm8750.c +++ b/sound/soc/codecs/wm8750.c @@ -802,8 +802,8 @@ static int wm8750_i2c_probe(struct i2c_client *i2c) } static const struct i2c_device_id wm8750_i2c_id[] = { - { "wm8750", 0 }, - { "wm8987", 0 }, + { "wm8750" }, + { "wm8987" }, { } }; MODULE_DEVICE_TABLE(i2c, wm8750_i2c_id); diff --git a/sound/soc/codecs/wm8753.c b/sound/soc/codecs/wm8753.c index f42ed24314f3..38b76b7275e5 100644 --- a/sound/soc/codecs/wm8753.c +++ b/sound/soc/codecs/wm8753.c @@ -1580,7 +1580,7 @@ static int wm8753_i2c_probe(struct i2c_client *i2c) } static const struct i2c_device_id wm8753_i2c_id[] = { - { "wm8753", 0 }, + { "wm8753" }, { } }; MODULE_DEVICE_TABLE(i2c, wm8753_i2c_id); diff --git a/sound/soc/codecs/wm8804-i2c.c b/sound/soc/codecs/wm8804-i2c.c index 7062a8b2f8b5..e80dad87219b 100644 --- a/sound/soc/codecs/wm8804-i2c.c +++ b/sound/soc/codecs/wm8804-i2c.c @@ -31,7 +31,7 @@ static void wm8804_i2c_remove(struct i2c_client *i2c) } static const struct i2c_device_id wm8804_i2c_id[] = { - { "wm8804", 0 }, + { "wm8804" }, { } }; MODULE_DEVICE_TABLE(i2c, wm8804_i2c_id); diff --git a/sound/soc/codecs/wm8900.c b/sound/soc/codecs/wm8900.c index 84d06c190411..e44fdf97796f 100644 --- a/sound/soc/codecs/wm8900.c +++ b/sound/soc/codecs/wm8900.c @@ -1286,7 +1286,7 @@ static void wm8900_i2c_remove(struct i2c_client *client) {} static const struct i2c_device_id wm8900_i2c_id[] = { - { "wm8900", 0 }, + { "wm8900" }, { } }; MODULE_DEVICE_TABLE(i2c, wm8900_i2c_id); diff --git a/sound/soc/codecs/wm8903.c b/sound/soc/codecs/wm8903.c index 84ae1102ac88..c643b5377d3a 100644 --- a/sound/soc/codecs/wm8903.c +++ b/sound/soc/codecs/wm8903.c @@ -2199,7 +2199,7 @@ static const struct of_device_id wm8903_of_match[] = { MODULE_DEVICE_TABLE(of, wm8903_of_match); static const struct i2c_device_id wm8903_i2c_id[] = { - { "wm8903", 0 }, + { "wm8903" }, { } }; MODULE_DEVICE_TABLE(i2c, wm8903_i2c_id); diff --git a/sound/soc/codecs/wm8940.c b/sound/soc/codecs/wm8940.c index b9432f8b64e5..8a532f7d750c 100644 --- a/sound/soc/codecs/wm8940.c +++ b/sound/soc/codecs/wm8940.c @@ -844,7 +844,7 @@ static int wm8940_i2c_probe(struct i2c_client *i2c) } static const struct i2c_device_id wm8940_i2c_id[] = { - { "wm8940", 0 }, + { "wm8940" }, { } }; MODULE_DEVICE_TABLE(i2c, wm8940_i2c_id); diff --git a/sound/soc/codecs/wm8955.c b/sound/soc/codecs/wm8955.c index 4f4338326438..bae52a8a2e11 100644 --- a/sound/soc/codecs/wm8955.c +++ b/sound/soc/codecs/wm8955.c @@ -994,7 +994,7 @@ static int wm8955_i2c_probe(struct i2c_client *i2c) } static const struct i2c_device_id wm8955_i2c_id[] = { - { "wm8955", 0 }, + { "wm8955" }, { } }; MODULE_DEVICE_TABLE(i2c, wm8955_i2c_id); diff --git a/sound/soc/codecs/wm8960.c b/sound/soc/codecs/wm8960.c index 7689fe3cc86d..00858b9c9568 100644 --- a/sound/soc/codecs/wm8960.c +++ b/sound/soc/codecs/wm8960.c @@ -1549,7 +1549,7 @@ static void wm8960_i2c_remove(struct i2c_client *client) } static const struct i2c_device_id wm8960_i2c_id[] = { - { "wm8960", 0 }, + { "wm8960" }, { } }; MODULE_DEVICE_TABLE(i2c, wm8960_i2c_id); diff --git a/sound/soc/codecs/wm8961.c b/sound/soc/codecs/wm8961.c index 8f8330efb341..d1c731e25777 100644 --- a/sound/soc/codecs/wm8961.c +++ b/sound/soc/codecs/wm8961.c @@ -966,7 +966,7 @@ static int wm8961_i2c_probe(struct i2c_client *i2c) } static const struct i2c_device_id wm8961_i2c_id[] = { - { "wm8961", 0 }, + { "wm8961" }, { } }; MODULE_DEVICE_TABLE(i2c, wm8961_i2c_id); diff --git a/sound/soc/codecs/wm8962.c b/sound/soc/codecs/wm8962.c index 7c6ed2983128..3ef95b7dcbdb 100644 --- a/sound/soc/codecs/wm8962.c +++ b/sound/soc/codecs/wm8962.c @@ -3938,7 +3938,7 @@ static const struct dev_pm_ops wm8962_pm = { }; static const struct i2c_device_id wm8962_i2c_id[] = { - { "wm8962", 0 }, + { "wm8962" }, { } }; MODULE_DEVICE_TABLE(i2c, wm8962_i2c_id); diff --git a/sound/soc/codecs/wm8971.c b/sound/soc/codecs/wm8971.c index e88f323d28b2..b97c7d5bd4e7 100644 --- a/sound/soc/codecs/wm8971.c +++ b/sound/soc/codecs/wm8971.c @@ -691,7 +691,7 @@ static int wm8971_i2c_probe(struct i2c_client *i2c) } static const struct i2c_device_id wm8971_i2c_id[] = { - { "wm8971", 0 }, + { "wm8971" }, { } }; MODULE_DEVICE_TABLE(i2c, wm8971_i2c_id); diff --git a/sound/soc/codecs/wm8974.c b/sound/soc/codecs/wm8974.c index 260bac695b20..0ee3655cad01 100644 --- a/sound/soc/codecs/wm8974.c +++ b/sound/soc/codecs/wm8974.c @@ -707,7 +707,7 @@ static int wm8974_i2c_probe(struct i2c_client *i2c) } static const struct i2c_device_id wm8974_i2c_id[] = { - { "wm8974", 0 }, + { "wm8974" }, { } }; MODULE_DEVICE_TABLE(i2c, wm8974_i2c_id); diff --git a/sound/soc/codecs/wm8978.c b/sound/soc/codecs/wm8978.c index 718bfef302cc..40d22b36b7a9 100644 --- a/sound/soc/codecs/wm8978.c +++ b/sound/soc/codecs/wm8978.c @@ -1056,7 +1056,7 @@ static int wm8978_i2c_probe(struct i2c_client *i2c) } static const struct i2c_device_id wm8978_i2c_id[] = { - { "wm8978", 0 }, + { "wm8978" }, { } }; MODULE_DEVICE_TABLE(i2c, wm8978_i2c_id); diff --git a/sound/soc/codecs/wm8983.c b/sound/soc/codecs/wm8983.c index b26d6a68e8d2..252b4a6cac04 100644 --- a/sound/soc/codecs/wm8983.c +++ b/sound/soc/codecs/wm8983.c @@ -1059,7 +1059,7 @@ static int wm8983_i2c_probe(struct i2c_client *i2c) } static const struct i2c_device_id wm8983_i2c_id[] = { - { "wm8983", 0 }, + { "wm8983" }, { } }; MODULE_DEVICE_TABLE(i2c, wm8983_i2c_id); diff --git a/sound/soc/codecs/wm8988.c b/sound/soc/codecs/wm8988.c index 76f214f12ce0..f0e9d6e38dc0 100644 --- a/sound/soc/codecs/wm8988.c +++ b/sound/soc/codecs/wm8988.c @@ -896,7 +896,7 @@ static int wm8988_i2c_probe(struct i2c_client *i2c) } static const struct i2c_device_id wm8988_i2c_id[] = { - { "wm8988", 0 }, + { "wm8988" }, { } }; MODULE_DEVICE_TABLE(i2c, wm8988_i2c_id); diff --git a/sound/soc/codecs/wm8990.c b/sound/soc/codecs/wm8990.c index 5a8e765090af..573bd3d487ba 100644 --- a/sound/soc/codecs/wm8990.c +++ b/sound/soc/codecs/wm8990.c @@ -1238,7 +1238,7 @@ static int wm8990_i2c_probe(struct i2c_client *i2c) } static const struct i2c_device_id wm8990_i2c_id[] = { - { "wm8990", 0 }, + { "wm8990" }, { } }; MODULE_DEVICE_TABLE(i2c, wm8990_i2c_id); diff --git a/sound/soc/codecs/wm8991.c b/sound/soc/codecs/wm8991.c index 590318aafaea..3bd9b362051b 100644 --- a/sound/soc/codecs/wm8991.c +++ b/sound/soc/codecs/wm8991.c @@ -1314,7 +1314,7 @@ static int wm8991_i2c_probe(struct i2c_client *i2c) } static const struct i2c_device_id wm8991_i2c_id[] = { - { "wm8991", 0 }, + { "wm8991" }, { } }; MODULE_DEVICE_TABLE(i2c, wm8991_i2c_id); diff --git a/sound/soc/codecs/wm8993.c b/sound/soc/codecs/wm8993.c index 5b788f35e5e4..98a83f51ab26 100644 --- a/sound/soc/codecs/wm8993.c +++ b/sound/soc/codecs/wm8993.c @@ -1732,7 +1732,7 @@ static void wm8993_i2c_remove(struct i2c_client *i2c) } static const struct i2c_device_id wm8993_i2c_id[] = { - { "wm8993", 0 }, + { "wm8993" }, { } }; MODULE_DEVICE_TABLE(i2c, wm8993_i2c_id); diff --git a/sound/soc/codecs/wm8995.c b/sound/soc/codecs/wm8995.c index 59ef2ef8ce00..1f9a9b636935 100644 --- a/sound/soc/codecs/wm8995.c +++ b/sound/soc/codecs/wm8995.c @@ -2258,7 +2258,7 @@ static int wm8995_i2c_probe(struct i2c_client *i2c) } static const struct i2c_device_id wm8995_i2c_id[] = { - {"wm8995", 0}, + {"wm8995"}, {} }; diff --git a/sound/soc/codecs/wm8996.c b/sound/soc/codecs/wm8996.c index e738326e33ed..f6c5adce164e 100644 --- a/sound/soc/codecs/wm8996.c +++ b/sound/soc/codecs/wm8996.c @@ -3069,7 +3069,7 @@ static void wm8996_i2c_remove(struct i2c_client *client) } static const struct i2c_device_id wm8996_i2c_id[] = { - { "wm8996", 0 }, + { "wm8996" }, { } }; MODULE_DEVICE_TABLE(i2c, wm8996_i2c_id); diff --git a/sound/soc/codecs/wm9081.c b/sound/soc/codecs/wm9081.c index e7ec799573d3..cb9d040b34d6 100644 --- a/sound/soc/codecs/wm9081.c +++ b/sound/soc/codecs/wm9081.c @@ -1360,7 +1360,7 @@ static void wm9081_i2c_remove(struct i2c_client *client) {} static const struct i2c_device_id wm9081_i2c_id[] = { - { "wm9081", 0 }, + { "wm9081" }, { } }; MODULE_DEVICE_TABLE(i2c, wm9081_i2c_id); diff --git a/sound/soc/codecs/wm9090.c b/sound/soc/codecs/wm9090.c index 50c1cbccfdb9..26191bcc161d 100644 --- a/sound/soc/codecs/wm9090.c +++ b/sound/soc/codecs/wm9090.c @@ -606,8 +606,8 @@ static int wm9090_i2c_probe(struct i2c_client *i2c) } static const struct i2c_device_id wm9090_id[] = { - { "wm9090", 0 }, - { "wm9093", 0 }, + { "wm9090" }, + { "wm9093" }, { } }; MODULE_DEVICE_TABLE(i2c, wm9090_id); -- cgit v1.2.3 From 5a7543d0ca01d68d992f480d151efd693807e0ce Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Fri, 3 May 2024 08:32:51 -0500 Subject: ASoC: SOF: Intel: discard SoundWire configuration if HDaudio codec is reported MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The machine driver and topology selection starts with I2S, then SoundWire and last uses HDaudio as a fallback. That assumes that the ACPI information is correct but there are of course exceptions to the rule. On a Lenovo platform, an external HDaudio codec is detected, but the ACPI tables expose TWO RT711 jack codecs. This patch skips the SoundWire selection in case an external HDaudio codec is detected - which only works with the additional assumption that no one will mix HDaudio and SoundWire. Closes: https://github.com/thesofproject/linux/issues/4962 Reviewed-by: Bard Liao Reviewed-by: Péter Ujfalusi Reviewed-by: Kai Vehmanen Reviewed-by: Ranjani Sridharan Signed-off-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20240503133253.108201-2-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/intel/hda.c | 9 +++++++-- sound/soc/sof/intel/hda.h | 2 ++ 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/sound/soc/sof/intel/hda.c b/sound/soc/sof/intel/hda.c index d509cfa38a64..6c10eb2c8241 100644 --- a/sound/soc/sof/intel/hda.c +++ b/sound/soc/sof/intel/hda.c @@ -1809,6 +1809,7 @@ struct snd_soc_acpi_mach *hda_machine_select(struct snd_sof_dev *sdev) u32 interface_mask = hda_get_interface_mask(sdev); struct snd_sof_pdata *sof_pdata = sdev->pdata; const struct sof_dev_desc *desc = sof_pdata->desc; + struct hdac_bus *bus = sof_to_bus(sdev); struct snd_soc_acpi_mach *mach = NULL; enum snd_soc_acpi_intel_codec codec_type; const char *tplg_filename; @@ -1981,8 +1982,12 @@ struct snd_soc_acpi_mach *hda_machine_select(struct snd_sof_dev *sdev) } } - /* If I2S fails, try SoundWire if it is supported */ - if (!mach && (interface_mask & BIT(SOF_DAI_INTEL_ALH))) + /* + * If I2S fails and no external HDaudio codec is detected, + * try SoundWire if it is supported + */ + if (!mach && !HDA_EXT_CODEC(bus->codec_mask) && + (interface_mask & BIT(SOF_DAI_INTEL_ALH))) mach = hda_sdw_machine_select(sdev); /* diff --git a/sound/soc/sof/intel/hda.h b/sound/soc/sof/intel/hda.h index 7804c5b50c26..8b495264f23d 100644 --- a/sound/soc/sof/intel/hda.h +++ b/sound/soc/sof/intel/hda.h @@ -454,6 +454,8 @@ #define SSP_SET_SFRM_CONSUMER BIT(24) #define SSP_SET_CBP_CFP (SSP_SET_SCLK_CONSUMER | SSP_SET_SFRM_CONSUMER) +#define HDA_EXT_ADDR 0 +#define HDA_EXT_CODEC(x) ((x) & BIT(HDA_EXT_ADDR)) #define HDA_IDISP_ADDR 2 #define HDA_IDISP_CODEC(x) ((x) & BIT(HDA_IDISP_ADDR)) -- cgit v1.2.3 From b679302526d637700e998da85ed1e06d8f7d3674 Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Fri, 3 May 2024 08:32:52 -0500 Subject: ASoC: SOF: ipc4-topology: Allow selective update in sof_ipc4_update_hw_params Add a bitmask parameter to sof_ipc4_update_hw_params() to be able to select the param to be updated. This feature can be used when not all params should be updated, for example if caller only wants to update the format in the params, leaving the channels and rates untouched. Reviewed-by: Seppo Ingalsuo Reviewed-by: Ranjani Sridharan Signed-off-by: Peter Ujfalusi Signed-off-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20240503133253.108201-3-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/ipc4-topology.c | 83 ++++++++++++++++++++++++++----------------- 1 file changed, 51 insertions(+), 32 deletions(-) diff --git a/sound/soc/sof/ipc4-topology.c b/sound/soc/sof/ipc4-topology.c index a972b2b5122a..f56b7fbbe10f 100644 --- a/sound/soc/sof/ipc4-topology.c +++ b/sound/soc/sof/ipc4-topology.c @@ -1119,42 +1119,50 @@ static int sof_ipc4_widget_assign_instance_id(struct snd_sof_dev *sdev, /* update hw_params based on the audio stream format */ static int sof_ipc4_update_hw_params(struct snd_sof_dev *sdev, struct snd_pcm_hw_params *params, - struct sof_ipc4_audio_format *fmt) + struct sof_ipc4_audio_format *fmt, u32 param_to_update) { - snd_pcm_format_t snd_fmt; struct snd_interval *i; - struct snd_mask *m; - int valid_bits = SOF_IPC4_AUDIO_FORMAT_CFG_V_BIT_DEPTH(fmt->fmt_cfg); - unsigned int channels, rate; - switch (valid_bits) { - case 16: - snd_fmt = SNDRV_PCM_FORMAT_S16_LE; - break; - case 24: - snd_fmt = SNDRV_PCM_FORMAT_S24_LE; - break; - case 32: - snd_fmt = SNDRV_PCM_FORMAT_S32_LE; - break; - default: - dev_err(sdev->dev, "invalid PCM valid_bits %d\n", valid_bits); - return -EINVAL; + if (param_to_update & BIT(SNDRV_PCM_HW_PARAM_FORMAT)) { + int valid_bits = SOF_IPC4_AUDIO_FORMAT_CFG_V_BIT_DEPTH(fmt->fmt_cfg); + snd_pcm_format_t snd_fmt; + struct snd_mask *m; + + switch (valid_bits) { + case 16: + snd_fmt = SNDRV_PCM_FORMAT_S16_LE; + break; + case 24: + snd_fmt = SNDRV_PCM_FORMAT_S24_LE; + break; + case 32: + snd_fmt = SNDRV_PCM_FORMAT_S32_LE; + break; + default: + dev_err(sdev->dev, "invalid PCM valid_bits %d\n", valid_bits); + return -EINVAL; + } + + m = hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT); + snd_mask_none(m); + snd_mask_set_format(m, snd_fmt); } - m = hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT); - snd_mask_none(m); - snd_mask_set_format(m, snd_fmt); + if (param_to_update & BIT(SNDRV_PCM_HW_PARAM_RATE)) { + unsigned int rate = fmt->sampling_frequency; - rate = fmt->sampling_frequency; - i = hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE); - i->min = rate; - i->max = rate; + i = hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE); + i->min = rate; + i->max = rate; + } - channels = SOF_IPC4_AUDIO_FORMAT_CFG_CHANNELS_COUNT(fmt->fmt_cfg); - i = hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS); - i->min = channels; - i->max = channels; + if (param_to_update & BIT(SNDRV_PCM_HW_PARAM_CHANNELS)) { + unsigned int channels = SOF_IPC4_AUDIO_FORMAT_CFG_CHANNELS_COUNT(fmt->fmt_cfg); + + i = hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS); + i->min = channels; + i->max = channels; + } return 0; } @@ -1844,7 +1852,11 @@ sof_ipc4_prepare_copier_module(struct snd_sof_widget *swidget, } /* modify the input params for the next widget */ - ret = sof_ipc4_update_hw_params(sdev, pipeline_params, &copier_data->out_format); + ret = sof_ipc4_update_hw_params(sdev, pipeline_params, + &copier_data->out_format, + BIT(SNDRV_PCM_HW_PARAM_FORMAT) | + BIT(SNDRV_PCM_HW_PARAM_CHANNELS) | + BIT(SNDRV_PCM_HW_PARAM_RATE)); if (ret) return ret; @@ -2069,7 +2081,10 @@ static int sof_ipc4_prepare_src_module(struct snd_sof_widget *swidget, src->data.sink_rate = out_audio_fmt->sampling_frequency; /* update pipeline_params for sink widgets */ - return sof_ipc4_update_hw_params(sdev, pipeline_params, out_audio_fmt); + return sof_ipc4_update_hw_params(sdev, pipeline_params, out_audio_fmt, + BIT(SNDRV_PCM_HW_PARAM_FORMAT) | + BIT(SNDRV_PCM_HW_PARAM_CHANNELS) | + BIT(SNDRV_PCM_HW_PARAM_RATE)); } static int @@ -2193,7 +2208,11 @@ static int sof_ipc4_prepare_process_module(struct snd_sof_widget *swidget, sizeof(struct sof_ipc4_audio_format)); /* modify the pipeline params with the pin 0 output format */ - ret = sof_ipc4_update_hw_params(sdev, pipeline_params, &process->output_format); + ret = sof_ipc4_update_hw_params(sdev, pipeline_params, + &process->output_format, + BIT(SNDRV_PCM_HW_PARAM_FORMAT) | + BIT(SNDRV_PCM_HW_PARAM_CHANNELS) | + BIT(SNDRV_PCM_HW_PARAM_RATE)); if (ret) return ret; } -- cgit v1.2.3 From f9209644ae7688e82f629e737417bc8916db7b57 Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Fri, 3 May 2024 08:32:53 -0500 Subject: ASoC: SOF: ipc4-topology: Correct DAI copier config and NHLT blob request In case of capture and when the DAI copier have single bit depth supported on it's input side we should use this format instead of the one in fe_params. Regardless of the stream direction for the NHLT blob lookup when the DAI copier only supports single bit depth on the DAI side we should only look for a blob which matches with this single configuration. For DMIC if the DAI copier supports multiple bit depths, try to request 32-bit blob first if the requested bit depth is 16-bit. If the 32-bit blob is available then look for marching (32-bit) copier format to make sure that both the blob and copier have correct parameters. Reviewed-by: Seppo Ingalsuo Reviewed-by: Ranjani Sridharan Signed-off-by: Peter Ujfalusi Signed-off-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20240503133253.108201-4-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/ipc4-topology.c | 162 +++++++++++++++++++++++++++++++++++------- 1 file changed, 136 insertions(+), 26 deletions(-) diff --git a/sound/soc/sof/ipc4-topology.c b/sound/soc/sof/ipc4-topology.c index f56b7fbbe10f..d0125fd1c09f 100644 --- a/sound/soc/sof/ipc4-topology.c +++ b/sound/soc/sof/ipc4-topology.c @@ -1420,13 +1420,16 @@ static int snd_sof_get_hw_config_params(struct snd_sof_dev *sdev, struct snd_sof return 0; } -static int snd_sof_get_nhlt_endpoint_data(struct snd_sof_dev *sdev, struct snd_sof_dai *dai, - struct snd_pcm_hw_params *params, u32 dai_index, - u32 linktype, u8 dir, u32 **dst, u32 *len) +static int +snd_sof_get_nhlt_endpoint_data(struct snd_sof_dev *sdev, struct snd_sof_dai *dai, + bool single_format, + struct snd_pcm_hw_params *params, u32 dai_index, + u32 linktype, u8 dir, u32 **dst, u32 *len) { struct sof_ipc4_fw_data *ipc4_data = sdev->private; struct nhlt_specific_cfg *cfg; int sample_rate, channel_count; + bool format_change = false; int bit_depth, ret; u32 nhlt_type; int dev_type = 0; @@ -1435,9 +1438,18 @@ static int snd_sof_get_nhlt_endpoint_data(struct snd_sof_dev *sdev, struct snd_s switch (linktype) { case SOF_DAI_INTEL_DMIC: nhlt_type = NHLT_LINK_DMIC; - bit_depth = params_width(params); channel_count = params_channels(params); sample_rate = params_rate(params); + bit_depth = params_width(params); + /* + * Look for 32-bit blob first instead of 16-bit if copier + * supports multiple formats + */ + if (bit_depth == 16 && !single_format) { + dev_dbg(sdev->dev, "Looking for 32-bit blob first for DMIC\n"); + format_change = true; + bit_depth = 32; + } break; case SOF_DAI_INTEL_SSP: nhlt_type = NHLT_LINK_SSP; @@ -1471,22 +1483,56 @@ static int snd_sof_get_nhlt_endpoint_data(struct snd_sof_dev *sdev, struct snd_s dir, dev_type); if (!cfg) { + if (format_change) { + /* + * The 32-bit blob was not found in NHLT table, try to + * look for one based on the params + */ + bit_depth = params_width(params); + format_change = false; + + cfg = intel_nhlt_get_endpoint_blob(sdev->dev, ipc4_data->nhlt, + dai_index, nhlt_type, + bit_depth, bit_depth, + channel_count, sample_rate, + dir, dev_type); + if (cfg) + goto out; + } + dev_err(sdev->dev, "no matching blob for sample rate: %d sample width: %d channels: %d\n", sample_rate, bit_depth, channel_count); return -EINVAL; } +out: /* config length should be in dwords */ *len = cfg->size >> 2; *dst = (u32 *)cfg->caps; + if (format_change) { + /* + * Update the params to reflect that we have loaded 32-bit blob + * instead of the 16-bit. + * This information is going to be used by the caller to find + * matching copier format on the dai side. + */ + struct snd_mask *m; + + m = hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT); + snd_mask_none(m); + snd_mask_set_format(m, SNDRV_PCM_FORMAT_S32_LE); + } + return 0; } #else -static int snd_sof_get_nhlt_endpoint_data(struct snd_sof_dev *sdev, struct snd_sof_dai *dai, - struct snd_pcm_hw_params *params, u32 dai_index, - u32 linktype, u8 dir, u32 **dst, u32 *len) +static int +snd_sof_get_nhlt_endpoint_data(struct snd_sof_dev *sdev, struct snd_sof_dai *dai, + bool single_format, + struct snd_pcm_hw_params *params, u32 dai_index, + u32 linktype, u8 dir, u32 **dst, u32 *len) { return 0; } @@ -1517,6 +1563,68 @@ bool sof_ipc4_copier_is_single_format(struct snd_sof_dev *sdev, return true; } +static int +sof_ipc4_prepare_dai_copier(struct snd_sof_dev *sdev, struct snd_sof_dai *dai, + struct snd_pcm_hw_params *params, int dir) +{ + struct sof_ipc4_available_audio_format *available_fmt; + struct snd_pcm_hw_params dai_params = *params; + struct sof_ipc4_copier_data *copier_data; + struct sof_ipc4_copier *ipc4_copier; + bool single_format; + int ret; + + ipc4_copier = dai->private; + copier_data = &ipc4_copier->data; + available_fmt = &ipc4_copier->available_fmt; + + /* + * If the copier on the DAI side supports only single bit depth then + * this depth (format) should be used to look for the NHLT blob (if + * needed) and in case of capture this should be used for the input + * format lookup + */ + if (dir == SNDRV_PCM_STREAM_PLAYBACK) { + single_format = sof_ipc4_copier_is_single_format(sdev, + available_fmt->output_pin_fmts, + available_fmt->num_output_formats); + + /* Update the dai_params with the only supported format */ + if (single_format) { + ret = sof_ipc4_update_hw_params(sdev, &dai_params, + &available_fmt->output_pin_fmts[0].audio_fmt, + BIT(SNDRV_PCM_HW_PARAM_FORMAT)); + if (ret) + return ret; + } + } else { + single_format = sof_ipc4_copier_is_single_format(sdev, + available_fmt->input_pin_fmts, + available_fmt->num_input_formats); + + /* Update the dai_params with the only supported format */ + if (single_format) { + ret = sof_ipc4_update_hw_params(sdev, &dai_params, + &available_fmt->input_pin_fmts[0].audio_fmt, + BIT(SNDRV_PCM_HW_PARAM_FORMAT)); + if (ret) + return ret; + } + } + + ret = snd_sof_get_nhlt_endpoint_data(sdev, dai, single_format, + &dai_params, + ipc4_copier->dai_index, + ipc4_copier->dai_type, dir, + &ipc4_copier->copier_config, + &copier_data->gtw_cfg.config_length); + /* Update the params to reflect the changes made in this function */ + if (!ret) + *params = dai_params; + + return ret; +} + static int sof_ipc4_prepare_copier_module(struct snd_sof_widget *swidget, struct snd_pcm_hw_params *fe_params, @@ -1527,7 +1635,7 @@ sof_ipc4_prepare_copier_module(struct snd_sof_widget *swidget, struct snd_soc_component *scomp = swidget->scomp; struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp); struct sof_ipc4_copier_data *copier_data; - struct snd_pcm_hw_params *ref_params; + struct snd_pcm_hw_params ref_params; struct sof_ipc4_copier *ipc4_copier; struct snd_sof_dai *dai; u32 gtw_cfg_config_length; @@ -1605,9 +1713,9 @@ sof_ipc4_prepare_copier_module(struct snd_sof_widget *swidget, * for capture. */ if (dir == SNDRV_PCM_STREAM_PLAYBACK) - ref_params = fe_params; + ref_params = *fe_params; else - ref_params = pipeline_params; + ref_params = *pipeline_params; copier_data->gtw_cfg.node_id &= ~SOF_IPC4_NODE_INDEX_MASK; copier_data->gtw_cfg.node_id |= @@ -1633,23 +1741,25 @@ sof_ipc4_prepare_copier_module(struct snd_sof_widget *swidget, available_fmt = &ipc4_copier->available_fmt; /* - * When there is format conversion within a pipeline, the number of supported - * output formats is typically limited to just 1 for the DAI copiers. But when there - * is no format conversion, the DAI copiers input format must match that of the - * FE hw_params for capture and the pipeline params for playback. + * Use the fe_params as a base for the copier configuration. + * The ref_params might get updated to reflect what format is + * supported by the copier on the DAI side. + * + * In case of capture the ref_params returned will be used to + * find the input configuration of the copier. */ - if (dir == SNDRV_PCM_STREAM_PLAYBACK) - ref_params = pipeline_params; - else - ref_params = fe_params; - - ret = snd_sof_get_nhlt_endpoint_data(sdev, dai, fe_params, ipc4_copier->dai_index, - ipc4_copier->dai_type, dir, - &ipc4_copier->copier_config, - &copier_data->gtw_cfg.config_length); + ref_params = *fe_params; + ret = sof_ipc4_prepare_dai_copier(sdev, dai, &ref_params, dir); if (ret < 0) return ret; + /* + * For playback the pipeline_params needs to be used to find the + * input configuration of the copier. + */ + if (dir == SNDRV_PCM_STREAM_PLAYBACK) + ref_params = *pipeline_params; + break; } case snd_soc_dapm_buffer: @@ -1657,7 +1767,7 @@ sof_ipc4_prepare_copier_module(struct snd_sof_widget *swidget, ipc4_copier = (struct sof_ipc4_copier *)swidget->private; copier_data = &ipc4_copier->data; available_fmt = &ipc4_copier->available_fmt; - ref_params = pipeline_params; + ref_params = *pipeline_params; break; } @@ -1668,8 +1778,8 @@ sof_ipc4_prepare_copier_module(struct snd_sof_widget *swidget, } /* set input and output audio formats */ - ret = sof_ipc4_init_input_audio_fmt(sdev, swidget, &copier_data->base_config, ref_params, - available_fmt); + ret = sof_ipc4_init_input_audio_fmt(sdev, swidget, &copier_data->base_config, + &ref_params, available_fmt); if (ret < 0) return ret; -- cgit v1.2.3 From 9e7fd21ab03e6fadc4856f4c06e642daa9ccf7c6 Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Fri, 3 May 2024 08:52:15 -0500 Subject: ASoC: SOF: Intel: hda-stream: export stream_get_position() helper Export this helper so that we can report the DPIB position if the BPT DMA do not complete - this is very useful to see if the DMA started or gets stuck somehow with invalid bandwidth configurations. Signed-off-by: Pierre-Louis Bossart Reviewed-by: Bard Liao Reviewed-by: Rander Wang Link: https://lore.kernel.org/r/20240503135221.229202-2-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/intel/hda-stream.c | 1 + 1 file changed, 1 insertion(+) diff --git a/sound/soc/sof/intel/hda-stream.c b/sound/soc/sof/intel/hda-stream.c index 91b1371745e6..c5afcda18359 100644 --- a/sound/soc/sof/intel/hda-stream.c +++ b/sound/soc/sof/intel/hda-stream.c @@ -1079,6 +1079,7 @@ snd_pcm_uframes_t hda_dsp_stream_get_position(struct hdac_stream *hstream, return pos; } +EXPORT_SYMBOL_NS(hda_dsp_stream_get_position, SND_SOC_SOF_INTEL_HDA_COMMON); #define merge_u64(u32_u, u32_l) (((u64)(u32_u) << 32) | (u32_l)) -- cgit v1.2.3 From e4c6eba86d9618d99ba9892bc5d6e47715038530 Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Fri, 3 May 2024 08:52:16 -0500 Subject: ASoC: SOF: Intel: regroup all SoundWire/Intel functions in hda.c To avoid circular dependencies between SOF/Intel and SoundWire/Intel, we need to split the top-level hda.c from the rest of the code. This patch first regroups all SoundWire related code in hda.c. Signed-off-by: Pierre-Louis Bossart Reviewed-by: Bard Liao Reviewed-by: Ranjani Sridharan Link: https://lore.kernel.org/r/20240503135221.229202-3-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/intel/hda-loader.c | 40 ---------------------------------------- sound/soc/sof/intel/hda.c | 39 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 39 insertions(+), 40 deletions(-) diff --git a/sound/soc/sof/intel/hda-loader.c b/sound/soc/sof/intel/hda-loader.c index dc88b7ea599e..d0474522ea76 100644 --- a/sound/soc/sof/intel/hda-loader.c +++ b/sound/soc/sof/intel/hda-loader.c @@ -15,7 +15,6 @@ * Hardware interface for HDA DSP code loader */ -#include #include #include #include @@ -651,45 +650,6 @@ cleanup: return ret; } -/* pre fw run operations */ -int hda_dsp_pre_fw_run(struct snd_sof_dev *sdev) -{ - /* disable clock gating and power gating */ - return hda_dsp_ctrl_clock_power_gating(sdev, false); -} - -/* post fw run operations */ -int hda_dsp_post_fw_run(struct snd_sof_dev *sdev) -{ - int ret; - - if (sdev->first_boot) { - struct sof_intel_hda_dev *hdev = sdev->pdata->hw_pdata; - - ret = hda_sdw_startup(sdev); - if (ret < 0) { - dev_err(sdev->dev, - "error: could not startup SoundWire links\n"); - return ret; - } - - /* Check if IMR boot is usable */ - if (!sof_debug_check_flag(SOF_DBG_IGNORE_D3_PERSISTENT) && - (sdev->fw_ready.flags & SOF_IPC_INFO_D3_PERSISTENT || - sdev->pdata->ipc_type == SOF_IPC_TYPE_4)) { - hdev->imrboot_supported = true; - debugfs_create_bool("skip_imr_boot", - 0644, sdev->debugfs_root, - &hdev->skip_imr_boot); - } - } - - hda_sdw_int_enable(sdev, true); - - /* re-enable clock gating and power gating */ - return hda_dsp_ctrl_clock_power_gating(sdev, true); -} - int hda_dsp_ext_man_get_cavs_config_data(struct snd_sof_dev *sdev, const struct sof_ext_man_elem_header *hdr) { diff --git a/sound/soc/sof/intel/hda.c b/sound/soc/sof/intel/hda.c index d509cfa38a64..93f316300043 100644 --- a/sound/soc/sof/intel/hda.c +++ b/sound/soc/sof/intel/hda.c @@ -545,6 +545,45 @@ static inline bool hda_sdw_check_wakeen_irq(struct snd_sof_dev *sdev) #endif /* IS_ENABLED(CONFIG_SND_SOC_SOF_INTEL_SOUNDWIRE) */ +/* pre fw run operations */ +int hda_dsp_pre_fw_run(struct snd_sof_dev *sdev) +{ + /* disable clock gating and power gating */ + return hda_dsp_ctrl_clock_power_gating(sdev, false); +} + +/* post fw run operations */ +int hda_dsp_post_fw_run(struct snd_sof_dev *sdev) +{ + int ret; + + if (sdev->first_boot) { + struct sof_intel_hda_dev *hdev = sdev->pdata->hw_pdata; + + ret = hda_sdw_startup(sdev); + if (ret < 0) { + dev_err(sdev->dev, + "error: could not startup SoundWire links\n"); + return ret; + } + + /* Check if IMR boot is usable */ + if (!sof_debug_check_flag(SOF_DBG_IGNORE_D3_PERSISTENT) && + (sdev->fw_ready.flags & SOF_IPC_INFO_D3_PERSISTENT || + sdev->pdata->ipc_type == SOF_IPC_TYPE_4)) { + hdev->imrboot_supported = true; + debugfs_create_bool("skip_imr_boot", + 0644, sdev->debugfs_root, + &hdev->skip_imr_boot); + } + } + + hda_sdw_int_enable(sdev, true); + + /* re-enable clock gating and power gating */ + return hda_dsp_ctrl_clock_power_gating(sdev, true); +} + /* * Debug */ -- cgit v1.2.3 From 456644cbeab14394fff1308ffdaf87d4e0e6fb01 Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Fri, 3 May 2024 08:52:17 -0500 Subject: ASoC: SOF: Intel: start splitting top-level from common parts The existing code relies on the 'HDA_COMMON' module and namespace. We need to start splitting top-level parts from the low-level ones, otherwise we will not be able to reuse the low-level parts DMA support for SoundWire/BPT. In the end the dependencies will be: +----------------------------------------------+ | | | v sof-pci-intel-xxx --> sof-intel-hda ------------> sof-hda-common | ^ | | +-> soundwire_intel --> sof_hda_sdw_bpt This patch adds the initial split between the sof-pci-intel-xxx modules and the common parts, in a follow-up patch we will further split the HDA_COMMON parts Since the PCI modules are not all independent, i.e. the CNL parts are also used in JSL and TGL, additional Kconfig and namespace modules were added. Signed-off-by: Pierre-Louis Bossart Reviewed-by: Bard Liao Reviewed-by: Ranjani Sridharan Link: https://lore.kernel.org/r/20240503135221.229202-4-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/intel/Kconfig | 3 +++ sound/soc/sof/intel/Makefile | 17 ++++++++--------- sound/soc/sof/intel/apl.c | 3 --- sound/soc/sof/intel/cnl.c | 13 +++++++++---- sound/soc/sof/intel/hda-common-ops.c | 1 + sound/soc/sof/intel/hda-ctrl.c | 1 + sound/soc/sof/intel/hda-dai.c | 1 + sound/soc/sof/intel/hda-dsp.c | 16 ++++++++++++++++ sound/soc/sof/intel/hda-ipc.c | 11 +++++++++++ sound/soc/sof/intel/hda-loader.c | 4 ++++ sound/soc/sof/intel/hda.c | 18 ++++++++++++++++++ sound/soc/sof/intel/icl.c | 3 --- sound/soc/sof/intel/lnl.c | 3 --- sound/soc/sof/intel/mtl.c | 19 +++++++++++++++---- sound/soc/sof/intel/pci-icl.c | 1 + sound/soc/sof/intel/pci-lnl.c | 2 ++ sound/soc/sof/intel/pci-tgl.c | 1 + sound/soc/sof/intel/telemetry.c | 1 + sound/soc/sof/intel/tgl.c | 6 ------ 19 files changed, 92 insertions(+), 32 deletions(-) diff --git a/sound/soc/sof/intel/Kconfig b/sound/soc/sof/intel/Kconfig index 9de86aaa8d07..b804be7321be 100644 --- a/sound/soc/sof/intel/Kconfig +++ b/sound/soc/sof/intel/Kconfig @@ -188,6 +188,7 @@ config SND_SOC_SOF_INTEL_ICL select SND_SOC_SOF_INTEL_SOUNDWIRE_LINK_BASELINE select SND_SOC_SOF_IPC3 select SND_SOC_SOF_IPC4 + select SND_SOC_SOF_INTEL_CNL config SND_SOC_SOF_ICELAKE tristate "SOF support for Icelake" @@ -215,6 +216,7 @@ config SND_SOC_SOF_INTEL_TGL select SND_SOC_SOF_INTEL_SOUNDWIRE_LINK_BASELINE select SND_SOC_SOF_IPC3 select SND_SOC_SOF_IPC4 + select SND_SOC_SOF_INTEL_CNL config SND_SOC_SOF_TIGERLAKE tristate "SOF support for Tigerlake" @@ -267,6 +269,7 @@ config SND_SOC_SOF_INTEL_LNL select SND_SOC_SOF_HDA_COMMON select SND_SOC_SOF_INTEL_SOUNDWIRE_LINK_BASELINE select SND_SOC_SOF_IPC4 + select SND_SOC_SOF_INTEL_MTL config SND_SOC_SOF_LUNARLAKE tristate "SOF support for Lunarlake" diff --git a/sound/soc/sof/intel/Makefile b/sound/soc/sof/intel/Makefile index 6489d0660d58..c895bae0efdd 100644 --- a/sound/soc/sof/intel/Makefile +++ b/sound/soc/sof/intel/Makefile @@ -6,8 +6,7 @@ snd-sof-acpi-intel-bdw-objs := bdw.o snd-sof-intel-hda-common-objs := hda.o hda-loader.o hda-stream.o hda-trace.o \ hda-dsp.o hda-ipc.o hda-ctrl.o hda-pcm.o \ hda-dai.o hda-dai-ops.o hda-bus.o \ - skl.o hda-loader-skl.o \ - apl.o cnl.o tgl.o icl.o mtl.o lnl.o hda-common-ops.o \ + hda-common-ops.o \ telemetry.o snd-sof-intel-hda-mlink-objs := hda-mlink.o @@ -26,13 +25,13 @@ obj-$(CONFIG_SND_SOC_SOF_HDA_MLINK) += snd-sof-intel-hda-mlink.o obj-$(CONFIG_SND_SOC_SOF_HDA) += snd-sof-intel-hda.o snd-sof-pci-intel-tng-objs := pci-tng.o -snd-sof-pci-intel-skl-objs := pci-skl.o -snd-sof-pci-intel-apl-objs := pci-apl.o -snd-sof-pci-intel-cnl-objs := pci-cnl.o -snd-sof-pci-intel-icl-objs := pci-icl.o -snd-sof-pci-intel-tgl-objs := pci-tgl.o -snd-sof-pci-intel-mtl-objs := pci-mtl.o -snd-sof-pci-intel-lnl-objs := pci-lnl.o +snd-sof-pci-intel-skl-objs := pci-skl.o skl.o hda-loader-skl.o +snd-sof-pci-intel-apl-objs := pci-apl.o apl.o +snd-sof-pci-intel-cnl-objs := pci-cnl.o cnl.o +snd-sof-pci-intel-icl-objs := pci-icl.o icl.o +snd-sof-pci-intel-tgl-objs := pci-tgl.o tgl.o +snd-sof-pci-intel-mtl-objs := pci-mtl.o mtl.o +snd-sof-pci-intel-lnl-objs := pci-lnl.o lnl.o obj-$(CONFIG_SND_SOC_SOF_MERRIFIELD) += snd-sof-pci-intel-tng.o obj-$(CONFIG_SND_SOC_SOF_INTEL_SKL) += snd-sof-pci-intel-skl.o diff --git a/sound/soc/sof/intel/apl.c b/sound/soc/sof/intel/apl.c index dee6c7f73e80..bc364c7cb3b6 100644 --- a/sound/soc/sof/intel/apl.c +++ b/sound/soc/sof/intel/apl.c @@ -29,7 +29,6 @@ static const struct snd_sof_debugfs_map apl_dsp_debugfs[] = { /* apollolake ops */ struct snd_sof_dsp_ops sof_apl_ops; -EXPORT_SYMBOL_NS(sof_apl_ops, SND_SOC_SOF_INTEL_HDA_COMMON); int sof_apl_ops_init(struct snd_sof_dev *sdev) { @@ -97,7 +96,6 @@ int sof_apl_ops_init(struct snd_sof_dev *sdev) return 0; }; -EXPORT_SYMBOL_NS(sof_apl_ops_init, SND_SOC_SOF_INTEL_HDA_COMMON); const struct sof_intel_dsp_desc apl_chip_info = { /* Apollolake */ @@ -121,4 +119,3 @@ const struct sof_intel_dsp_desc apl_chip_info = { .disable_interrupts = hda_dsp_disable_interrupts, .hw_ip_version = SOF_INTEL_CAVS_1_5_PLUS, }; -EXPORT_SYMBOL_NS(apl_chip_info, SND_SOC_SOF_INTEL_HDA_COMMON); diff --git a/sound/soc/sof/intel/cnl.c b/sound/soc/sof/intel/cnl.c index 85e1e4760d0e..460bc404ddb6 100644 --- a/sound/soc/sof/intel/cnl.c +++ b/sound/soc/sof/intel/cnl.c @@ -110,6 +110,7 @@ irqreturn_t cnl_ipc4_irq_thread(int irq, void *context) return IRQ_HANDLED; } +EXPORT_SYMBOL_NS(cnl_ipc4_irq_thread, SND_SOC_SOF_INTEL_CNL); irqreturn_t cnl_ipc_irq_thread(int irq, void *context) { @@ -202,6 +203,7 @@ irqreturn_t cnl_ipc_irq_thread(int irq, void *context) return IRQ_HANDLED; } +EXPORT_SYMBOL_NS(cnl_ipc_irq_thread, SND_SOC_SOF_INTEL_CNL); static void cnl_ipc_host_done(struct snd_sof_dev *sdev) { @@ -284,6 +286,7 @@ int cnl_ipc4_send_msg(struct snd_sof_dev *sdev, struct snd_sof_ipc_msg *msg) return 0; } +EXPORT_SYMBOL_NS(cnl_ipc4_send_msg, SND_SOC_SOF_INTEL_CNL); int cnl_ipc_send_msg(struct snd_sof_dev *sdev, struct snd_sof_ipc_msg *msg) { @@ -331,6 +334,7 @@ int cnl_ipc_send_msg(struct snd_sof_dev *sdev, struct snd_sof_ipc_msg *msg) return 0; } +EXPORT_SYMBOL_NS(cnl_ipc_send_msg, SND_SOC_SOF_INTEL_CNL); void cnl_ipc_dump(struct snd_sof_dev *sdev) { @@ -351,6 +355,7 @@ void cnl_ipc_dump(struct snd_sof_dev *sdev) "error: host status 0x%8.8x dsp status 0x%8.8x mask 0x%8.8x\n", hipcida, hipctdr, hipcctl); } +EXPORT_SYMBOL_NS(cnl_ipc_dump, SND_SOC_SOF_INTEL_CNL); void cnl_ipc4_dump(struct snd_sof_dev *sdev) { @@ -372,10 +377,11 @@ void cnl_ipc4_dump(struct snd_sof_dev *sdev) "Host IPC initiator: %#x|%#x|%#x, target: %#x|%#x|%#x, ctl: %#x\n", hipcidr, hipcidd, hipcida, hipctdr, hipctdd, hipctda, hipcctl); } +EXPORT_SYMBOL_NS(cnl_ipc4_dump, SND_SOC_SOF_INTEL_CNL); /* cannonlake ops */ struct snd_sof_dsp_ops sof_cnl_ops; -EXPORT_SYMBOL_NS(sof_cnl_ops, SND_SOC_SOF_INTEL_HDA_COMMON); +EXPORT_SYMBOL_NS(sof_cnl_ops, SND_SOC_SOF_INTEL_CNL); int sof_cnl_ops_init(struct snd_sof_dev *sdev) { @@ -444,7 +450,7 @@ int sof_cnl_ops_init(struct snd_sof_dev *sdev) return 0; }; -EXPORT_SYMBOL_NS(sof_cnl_ops_init, SND_SOC_SOF_INTEL_HDA_COMMON); +EXPORT_SYMBOL_NS(sof_cnl_ops_init, SND_SOC_SOF_INTEL_CNL); const struct sof_intel_dsp_desc cnl_chip_info = { /* Cannonlake */ @@ -473,7 +479,6 @@ const struct sof_intel_dsp_desc cnl_chip_info = { .disable_interrupts = hda_dsp_disable_interrupts, .hw_ip_version = SOF_INTEL_CAVS_1_8, }; -EXPORT_SYMBOL_NS(cnl_chip_info, SND_SOC_SOF_INTEL_HDA_COMMON); /* * JasperLake is technically derived from IceLake, and should be in @@ -509,4 +514,4 @@ const struct sof_intel_dsp_desc jsl_chip_info = { .disable_interrupts = hda_dsp_disable_interrupts, .hw_ip_version = SOF_INTEL_CAVS_2_0, }; -EXPORT_SYMBOL_NS(jsl_chip_info, SND_SOC_SOF_INTEL_HDA_COMMON); +EXPORT_SYMBOL_NS(jsl_chip_info, SND_SOC_SOF_INTEL_CNL); diff --git a/sound/soc/sof/intel/hda-common-ops.c b/sound/soc/sof/intel/hda-common-ops.c index 466769c68da5..6a863ceba8da 100644 --- a/sound/soc/sof/intel/hda-common-ops.c +++ b/sound/soc/sof/intel/hda-common-ops.c @@ -105,3 +105,4 @@ const struct snd_sof_dsp_ops sof_hda_common_ops = { .dsp_arch_ops = &sof_xtensa_arch_ops, }; +EXPORT_SYMBOL_NS(sof_hda_common_ops, SND_SOC_SOF_INTEL_HDA_COMMON); diff --git a/sound/soc/sof/intel/hda-ctrl.c b/sound/soc/sof/intel/hda-ctrl.c index 6d941209847f..56c0f493042c 100644 --- a/sound/soc/sof/intel/hda-ctrl.c +++ b/sound/soc/sof/intel/hda-ctrl.c @@ -178,6 +178,7 @@ int hda_dsp_ctrl_clock_power_gating(struct snd_sof_dev *sdev, bool enable) return 0; } +EXPORT_SYMBOL_NS(hda_dsp_ctrl_clock_power_gating, SND_SOC_SOF_INTEL_HDA_COMMON); int hda_dsp_ctrl_init_chip(struct snd_sof_dev *sdev) { diff --git a/sound/soc/sof/intel/hda-dai.c b/sound/soc/sof/intel/hda-dai.c index 3f2fd84907d2..650e3a37326e 100644 --- a/sound/soc/sof/intel/hda-dai.c +++ b/sound/soc/sof/intel/hda-dai.c @@ -690,6 +690,7 @@ void hda_set_dai_drv_ops(struct snd_sof_dev *sdev, struct snd_sof_dsp_ops *ops) ipc4_data->nhlt = intel_nhlt_init(sdev->dev); } } +EXPORT_SYMBOL_NS(hda_set_dai_drv_ops, SND_SOC_SOF_INTEL_HDA_COMMON); void hda_ops_free(struct snd_sof_dev *sdev) { diff --git a/sound/soc/sof/intel/hda-dsp.c b/sound/soc/sof/intel/hda-dsp.c index ef5c915db8ff..32f034074668 100644 --- a/sound/soc/sof/intel/hda-dsp.c +++ b/sound/soc/sof/intel/hda-dsp.c @@ -126,6 +126,7 @@ int hda_dsp_core_stall_reset(struct snd_sof_dev *sdev, unsigned int core_mask) /* set reset state */ return hda_dsp_core_reset_enter(sdev, core_mask); } +EXPORT_SYMBOL_NS(hda_dsp_core_stall_reset, SND_SOC_SOF_INTEL_HDA_COMMON); bool hda_dsp_core_is_enabled(struct snd_sof_dev *sdev, unsigned int core_mask) { @@ -151,6 +152,7 @@ bool hda_dsp_core_is_enabled(struct snd_sof_dev *sdev, unsigned int core_mask) return is_enable; } +EXPORT_SYMBOL_NS(hda_dsp_core_is_enabled, SND_SOC_SOF_INTEL_HDA_COMMON); int hda_dsp_core_run(struct snd_sof_dev *sdev, unsigned int core_mask) { @@ -178,6 +180,7 @@ int hda_dsp_core_run(struct snd_sof_dev *sdev, unsigned int core_mask) return ret; } +EXPORT_SYMBOL_NS(hda_dsp_core_run, SND_SOC_SOF_INTEL_HDA_COMMON); /* * Power Management. @@ -229,6 +232,7 @@ int hda_dsp_core_power_up(struct snd_sof_dev *sdev, unsigned int core_mask) return ret; } +EXPORT_SYMBOL_NS(hda_dsp_core_power_up, SND_SOC_SOF_INTEL_HDA_COMMON); static int hda_dsp_core_power_down(struct snd_sof_dev *sdev, unsigned int core_mask) { @@ -276,6 +280,7 @@ int hda_dsp_enable_core(struct snd_sof_dev *sdev, unsigned int core_mask) return hda_dsp_core_run(sdev, core_mask); } +EXPORT_SYMBOL_NS(hda_dsp_enable_core, SND_SOC_SOF_INTEL_HDA_COMMON); int hda_dsp_core_reset_power_down(struct snd_sof_dev *sdev, unsigned int core_mask) @@ -316,6 +321,7 @@ int hda_dsp_core_reset_power_down(struct snd_sof_dev *sdev, return ret; } +EXPORT_SYMBOL_NS(hda_dsp_core_reset_power_down, SND_SOC_SOF_INTEL_HDA_COMMON); void hda_dsp_ipc_int_enable(struct snd_sof_dev *sdev) { @@ -334,6 +340,7 @@ void hda_dsp_ipc_int_enable(struct snd_sof_dev *sdev) snd_sof_dsp_update_bits(sdev, HDA_DSP_BAR, HDA_DSP_REG_ADSPIC, HDA_DSP_ADSPIC_IPC, HDA_DSP_ADSPIC_IPC); } +EXPORT_SYMBOL_NS(hda_dsp_ipc_int_enable, SND_SOC_SOF_INTEL_HDA_COMMON); void hda_dsp_ipc_int_disable(struct snd_sof_dev *sdev) { @@ -351,6 +358,7 @@ void hda_dsp_ipc_int_disable(struct snd_sof_dev *sdev) snd_sof_dsp_update_bits(sdev, HDA_DSP_BAR, chip->ipc_ctl, HDA_DSP_REG_HIPCCTL_BUSY | HDA_DSP_REG_HIPCCTL_DONE, 0); } +EXPORT_SYMBOL_NS(hda_dsp_ipc_int_disable, SND_SOC_SOF_INTEL_HDA_COMMON); static int hda_dsp_wait_d0i3c_done(struct snd_sof_dev *sdev) { @@ -634,6 +642,7 @@ int hda_dsp_set_power_state_ipc3(struct snd_sof_dev *sdev, return hda_dsp_set_power_state(sdev, target_state); } +EXPORT_SYMBOL_NS(hda_dsp_set_power_state_ipc3, SND_SOC_SOF_INTEL_HDA_COMMON); int hda_dsp_set_power_state_ipc4(struct snd_sof_dev *sdev, const struct sof_dsp_power_state *target_state) @@ -645,6 +654,7 @@ int hda_dsp_set_power_state_ipc4(struct snd_sof_dev *sdev, return hda_dsp_set_power_state(sdev, target_state); } +EXPORT_SYMBOL_NS(hda_dsp_set_power_state_ipc4, SND_SOC_SOF_INTEL_HDA_COMMON); /* * Audio DSP states may transform as below:- @@ -853,6 +863,7 @@ int hda_dsp_resume(struct snd_sof_dev *sdev) return snd_sof_dsp_set_power_state(sdev, &target_state); } +EXPORT_SYMBOL_NS(hda_dsp_resume, SND_SOC_SOF_INTEL_HDA_COMMON); int hda_dsp_runtime_resume(struct snd_sof_dev *sdev) { @@ -868,6 +879,7 @@ int hda_dsp_runtime_resume(struct snd_sof_dev *sdev) return snd_sof_dsp_set_power_state(sdev, &target_state); } +EXPORT_SYMBOL_NS(hda_dsp_runtime_resume, SND_SOC_SOF_INTEL_HDA_COMMON); int hda_dsp_runtime_idle(struct snd_sof_dev *sdev) { @@ -1034,12 +1046,14 @@ int hda_dsp_shutdown_dma_flush(struct snd_sof_dev *sdev) return ret; } +EXPORT_SYMBOL_NS(hda_dsp_shutdown_dma_flush, SND_SOC_SOF_INTEL_HDA_COMMON); int hda_dsp_shutdown(struct snd_sof_dev *sdev) { sdev->system_suspend_target = SOF_SUSPEND_S3; return snd_sof_suspend(sdev->dev); } +EXPORT_SYMBOL_NS(hda_dsp_shutdown, SND_SOC_SOF_INTEL_HDA_COMMON); int hda_dsp_set_hw_params_upon_resume(struct snd_sof_dev *sdev) { @@ -1118,6 +1132,7 @@ power_down: return ret; } +EXPORT_SYMBOL_NS(hda_dsp_core_get, SND_SOC_SOF_INTEL_HDA_COMMON); int hda_dsp_disable_interrupts(struct snd_sof_dev *sdev) { @@ -1126,3 +1141,4 @@ int hda_dsp_disable_interrupts(struct snd_sof_dev *sdev) return 0; } +EXPORT_SYMBOL_NS(hda_dsp_disable_interrupts, SND_SOC_SOF_INTEL_HDA_COMMON); diff --git a/sound/soc/sof/intel/hda-ipc.c b/sound/soc/sof/intel/hda-ipc.c index a838dddb1d32..6919729cef52 100644 --- a/sound/soc/sof/intel/hda-ipc.c +++ b/sound/soc/sof/intel/hda-ipc.c @@ -20,6 +20,10 @@ #include "../ops.h" #include "hda.h" +EXPORT_TRACEPOINT_SYMBOL(sof_intel_ipc_firmware_initiated); +EXPORT_TRACEPOINT_SYMBOL(sof_intel_ipc_firmware_response); +EXPORT_TRACEPOINT_SYMBOL(sof_intel_hda_irq_ipc_check); + static void hda_dsp_ipc_host_done(struct snd_sof_dev *sdev) { /* @@ -66,6 +70,7 @@ int hda_dsp_ipc_send_msg(struct snd_sof_dev *sdev, struct snd_sof_ipc_msg *msg) return 0; } +EXPORT_SYMBOL_NS(hda_dsp_ipc_send_msg, SND_SOC_SOF_INTEL_HDA_COMMON); static inline bool hda_dsp_ipc4_pm_msg(u32 primary) { @@ -92,6 +97,7 @@ void hda_dsp_ipc4_schedule_d0i3_work(struct sof_intel_hda_dev *hdev, mod_delayed_work(system_wq, &hdev->d0i3_work, msecs_to_jiffies(SOF_HDA_D0I3_WORK_DELAY_MS)); } +EXPORT_SYMBOL_NS(hda_dsp_ipc4_schedule_d0i3_work, SND_SOC_SOF_INTEL_HDA_COMMON); int hda_dsp_ipc4_send_msg(struct snd_sof_dev *sdev, struct snd_sof_ipc_msg *msg) { @@ -118,6 +124,7 @@ int hda_dsp_ipc4_send_msg(struct snd_sof_dev *sdev, struct snd_sof_ipc_msg *msg) return 0; } +EXPORT_SYMBOL_NS(hda_dsp_ipc4_send_msg, SND_SOC_SOF_INTEL_HDA_COMMON); void hda_dsp_ipc_get_reply(struct snd_sof_dev *sdev) { @@ -153,6 +160,7 @@ void hda_dsp_ipc_get_reply(struct snd_sof_dev *sdev) snd_sof_ipc_get_reply(sdev); } } +EXPORT_SYMBOL_NS(hda_dsp_ipc_get_reply, SND_SOC_SOF_INTEL_HDA_COMMON); irqreturn_t hda_dsp_ipc4_irq_thread(int irq, void *context) { @@ -235,6 +243,7 @@ irqreturn_t hda_dsp_ipc4_irq_thread(int irq, void *context) return IRQ_HANDLED; } +EXPORT_SYMBOL_NS(hda_dsp_ipc4_irq_thread, SND_SOC_SOF_INTEL_HDA_COMMON); /* IPC handler thread */ irqreturn_t hda_dsp_ipc_irq_thread(int irq, void *context) @@ -347,6 +356,7 @@ irqreturn_t hda_dsp_ipc_irq_thread(int irq, void *context) return IRQ_HANDLED; } +EXPORT_SYMBOL_NS(hda_dsp_ipc_irq_thread, SND_SOC_SOF_INTEL_HDA_COMMON); /* Check if an IPC IRQ occurred */ bool hda_dsp_check_ipc_irq(struct snd_sof_dev *sdev) @@ -380,6 +390,7 @@ bool hda_dsp_check_ipc_irq(struct snd_sof_dev *sdev) out: return ret; } +EXPORT_SYMBOL_NS(hda_dsp_check_ipc_irq, SND_SOC_SOF_INTEL_HDA_COMMON); int hda_dsp_ipc_get_mailbox_offset(struct snd_sof_dev *sdev) { diff --git a/sound/soc/sof/intel/hda-loader.c b/sound/soc/sof/intel/hda-loader.c index d0474522ea76..34c18275c949 100644 --- a/sound/soc/sof/intel/hda-loader.c +++ b/sound/soc/sof/intel/hda-loader.c @@ -219,6 +219,7 @@ err: kfree(dump_msg); return ret; } +EXPORT_SYMBOL_NS(cl_dsp_init, SND_SOC_SOF_INTEL_HDA_COMMON); int hda_cl_trigger(struct device *dev, struct hdac_ext_stream *hext_stream, int cmd) { @@ -393,6 +394,7 @@ int hda_dsp_cl_boot_firmware_iccmax(struct snd_sof_dev *sdev) return ret; } +EXPORT_SYMBOL_NS(hda_dsp_cl_boot_firmware_iccmax, SND_SOC_SOF_INTEL_CNL); static int hda_dsp_boot_imr(struct snd_sof_dev *sdev) { @@ -546,6 +548,7 @@ cleanup: return ret; } +EXPORT_SYMBOL_NS(hda_dsp_cl_boot_firmware, SND_SOC_SOF_INTEL_HDA_COMMON); int hda_dsp_ipc4_load_library(struct snd_sof_dev *sdev, struct sof_ipc4_fw_library *fw_lib, bool reload) @@ -649,6 +652,7 @@ cleanup: return ret; } +EXPORT_SYMBOL_NS(hda_dsp_ipc4_load_library, SND_SOC_SOF_INTEL_HDA_COMMON); int hda_dsp_ext_man_get_cavs_config_data(struct snd_sof_dev *sdev, const struct sof_ext_man_elem_header *hdr) diff --git a/sound/soc/sof/intel/hda.c b/sound/soc/sof/intel/hda.c index 93f316300043..e4ee2918614e 100644 --- a/sound/soc/sof/intel/hda.c +++ b/sound/soc/sof/intel/hda.c @@ -223,6 +223,7 @@ void hda_common_enable_sdw_irq(struct snd_sof_dev *sdev, bool enable) HDA_DSP_REG_ADSPIC2_SNDW, enable ? HDA_DSP_REG_ADSPIC2_SNDW : 0); } +EXPORT_SYMBOL_NS(hda_common_enable_sdw_irq, SND_SOC_SOF_INTEL_HDA_COMMON); void hda_sdw_int_enable(struct snd_sof_dev *sdev, bool enable) { @@ -236,6 +237,7 @@ void hda_sdw_int_enable(struct snd_sof_dev *sdev, bool enable) if (chip && chip->enable_sdw_irq) chip->enable_sdw_irq(sdev, enable); } +EXPORT_SYMBOL_NS(hda_sdw_int_enable, SND_SOC_SOF_INTEL_HDA_COMMON); static int hda_sdw_acpi_scan(struct snd_sof_dev *sdev) { @@ -350,6 +352,7 @@ int hda_sdw_check_lcount_common(struct snd_sof_dev *sdev) return 0; } +EXPORT_SYMBOL_NS(hda_sdw_check_lcount_common, SND_SOC_SOF_INTEL_HDA_COMMON); int hda_sdw_check_lcount_ext(struct snd_sof_dev *sdev) { @@ -375,6 +378,7 @@ int hda_sdw_check_lcount_ext(struct snd_sof_dev *sdev) return 0; } +EXPORT_SYMBOL_NS(hda_sdw_check_lcount_ext, SND_SOC_SOF_INTEL_HDA_COMMON); static int hda_sdw_check_lcount(struct snd_sof_dev *sdev) { @@ -407,6 +411,7 @@ int hda_sdw_startup(struct snd_sof_dev *sdev) return sdw_intel_startup(hdev->sdw); } +EXPORT_SYMBOL_NS(hda_sdw_startup, SND_SOC_SOF_INTEL_HDA_COMMON); static int hda_sdw_exit(struct snd_sof_dev *sdev) { @@ -448,6 +453,7 @@ bool hda_common_check_sdw_irq(struct snd_sof_dev *sdev) out: return ret; } +EXPORT_SYMBOL_NS(hda_common_check_sdw_irq, SND_SOC_SOF_INTEL_HDA_COMMON); static bool hda_dsp_check_sdw_irq(struct snd_sof_dev *sdev) { @@ -481,6 +487,7 @@ bool hda_sdw_check_wakeen_irq_common(struct snd_sof_dev *sdev) return false; } +EXPORT_SYMBOL_NS(hda_sdw_check_wakeen_irq_common, SND_SOC_SOF_INTEL_HDA_COMMON); static bool hda_sdw_check_wakeen_irq(struct snd_sof_dev *sdev) { @@ -583,6 +590,7 @@ int hda_dsp_post_fw_run(struct snd_sof_dev *sdev) /* re-enable clock gating and power gating */ return hda_dsp_ctrl_clock_power_gating(sdev, true); } +EXPORT_SYMBOL_NS(hda_dsp_post_fw_run, SND_SOC_SOF_INTEL_HDA_COMMON); /* * Debug @@ -826,6 +834,7 @@ void hda_dsp_get_state(struct snd_sof_dev *sdev, const char *level) dev_printk(level, sdev->dev, "error code: %#x (%s)\n", error_code, error_text); } +EXPORT_SYMBOL_NS(hda_dsp_get_state, SND_SOC_SOF_INTEL_HDA_COMMON); static void hda_dsp_get_registers(struct snd_sof_dev *sdev, struct sof_ipc_dsp_oops_xtensa *xoops, @@ -911,6 +920,7 @@ void hda_ipc4_dsp_dump(struct snd_sof_dev *sdev, u32 flags) else hda_dsp_dump_ext_rom_status(sdev, level, flags); } +EXPORT_SYMBOL_NS(hda_ipc4_dsp_dump, SND_SOC_SOF_INTEL_HDA_COMMON); static bool hda_check_ipc_irq(struct snd_sof_dev *sdev) { @@ -942,6 +952,7 @@ void hda_ipc_irq_dump(struct snd_sof_dev *sdev) intsts, intctl, rirbsts); dev_err(sdev->dev, "dsp irq ppsts 0x%8.8x adspis 0x%8.8x\n", ppsts, adspis); } +EXPORT_SYMBOL_NS(hda_ipc_irq_dump, SND_SOC_SOF_INTEL_HDA_COMMON); void hda_ipc_dump(struct snd_sof_dev *sdev) { @@ -961,6 +972,7 @@ void hda_ipc_dump(struct snd_sof_dev *sdev) dev_err(sdev->dev, "host status 0x%8.8x dsp status 0x%8.8x mask 0x%8.8x\n", hipcie, hipct, hipcctl); } +EXPORT_SYMBOL_NS(hda_ipc_dump, SND_SOC_SOF_INTEL_HDA_COMMON); void hda_ipc4_dump(struct snd_sof_dev *sdev) { @@ -979,6 +991,7 @@ void hda_ipc4_dump(struct snd_sof_dev *sdev) dev_err(sdev->dev, "Host IPC initiator: %#x|%#x, target: %#x|%#x, ctl: %#x\n", hipci, hipcie, hipct, hipcte, hipcctl); } +EXPORT_SYMBOL_NS(hda_ipc4_dump, SND_SOC_SOF_INTEL_HDA_COMMON); bool hda_ipc4_tx_is_busy(struct snd_sof_dev *sdev) { @@ -990,6 +1003,7 @@ bool hda_ipc4_tx_is_busy(struct snd_sof_dev *sdev) return !!(val & chip->ipc_req_mask); } +EXPORT_SYMBOL_NS(hda_ipc4_tx_is_busy, SND_SOC_SOF_INTEL_HDA_COMMON); static int hda_init(struct snd_sof_dev *sdev) { @@ -1354,6 +1368,7 @@ int hda_dsp_probe_early(struct snd_sof_dev *sdev) err: return ret; } +EXPORT_SYMBOL_NS(hda_dsp_probe_early, SND_SOC_SOF_INTEL_HDA_COMMON); int hda_dsp_probe(struct snd_sof_dev *sdev) { @@ -1510,6 +1525,7 @@ hdac_bus_unmap: return ret; } +EXPORT_SYMBOL_NS(hda_dsp_probe, SND_SOC_SOF_INTEL_HDA_COMMON); void hda_dsp_remove(struct snd_sof_dev *sdev) { @@ -1563,6 +1579,7 @@ skip_disable_dsp: if (!sdev->dspless_mode_selected) iounmap(sdev->bar[HDA_DSP_BAR]); } +EXPORT_SYMBOL_NS(hda_dsp_remove, SND_SOC_SOF_INTEL_HDA_COMMON); void hda_dsp_remove_late(struct snd_sof_dev *sdev) { @@ -1578,6 +1595,7 @@ int hda_power_down_dsp(struct snd_sof_dev *sdev) return hda_dsp_core_reset_power_down(sdev, chip->host_managed_cores_mask); } +EXPORT_SYMBOL_NS(hda_power_down_dsp, SND_SOC_SOF_INTEL_HDA_COMMON); #if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA_AUDIO_CODEC) static void hda_generic_machine_select(struct snd_sof_dev *sdev, diff --git a/sound/soc/sof/intel/icl.c b/sound/soc/sof/intel/icl.c index 040698591992..115866225e05 100644 --- a/sound/soc/sof/intel/icl.c +++ b/sound/soc/sof/intel/icl.c @@ -97,7 +97,6 @@ static int icl_dsp_post_fw_run(struct snd_sof_dev *sdev) /* Icelake ops */ struct snd_sof_dsp_ops sof_icl_ops; -EXPORT_SYMBOL_NS(sof_icl_ops, SND_SOC_SOF_INTEL_HDA_COMMON); int sof_icl_ops_init(struct snd_sof_dev *sdev) { @@ -166,7 +165,6 @@ int sof_icl_ops_init(struct snd_sof_dev *sdev) return 0; }; -EXPORT_SYMBOL_NS(sof_icl_ops_init, SND_SOC_SOF_INTEL_HDA_COMMON); const struct sof_intel_dsp_desc icl_chip_info = { /* Icelake */ @@ -195,4 +193,3 @@ const struct sof_intel_dsp_desc icl_chip_info = { .disable_interrupts = hda_dsp_disable_interrupts, .hw_ip_version = SOF_INTEL_CAVS_2_0, }; -EXPORT_SYMBOL_NS(icl_chip_info, SND_SOC_SOF_INTEL_HDA_COMMON); diff --git a/sound/soc/sof/intel/lnl.c b/sound/soc/sof/intel/lnl.c index 82c975823ab3..ca0cb91d2b2c 100644 --- a/sound/soc/sof/intel/lnl.c +++ b/sound/soc/sof/intel/lnl.c @@ -22,7 +22,6 @@ /* LunarLake ops */ struct snd_sof_dsp_ops sof_lnl_ops; -EXPORT_SYMBOL_NS(sof_lnl_ops, SND_SOC_SOF_INTEL_HDA_COMMON); static const struct snd_sof_debugfs_map lnl_dsp_debugfs[] = { {"hda", HDA_DSP_HDA_BAR, 0, 0x4000, SOF_DEBUGFS_ACCESS_ALWAYS}, @@ -182,7 +181,6 @@ int sof_lnl_ops_init(struct snd_sof_dev *sdev) return 0; }; -EXPORT_SYMBOL_NS(sof_lnl_ops_init, SND_SOC_SOF_INTEL_HDA_COMMON); /* Check if an SDW IRQ occurred */ static bool lnl_dsp_check_sdw_irq(struct snd_sof_dev *sdev) @@ -246,4 +244,3 @@ const struct sof_intel_dsp_desc lnl_chip_info = { .disable_interrupts = lnl_dsp_disable_interrupts, .hw_ip_version = SOF_INTEL_ACE_2_0, }; -EXPORT_SYMBOL_NS(lnl_chip_info, SND_SOC_SOF_INTEL_HDA_COMMON); diff --git a/sound/soc/sof/intel/mtl.c b/sound/soc/sof/intel/mtl.c index 5d3b2d4be78a..13f780f33c22 100644 --- a/sound/soc/sof/intel/mtl.c +++ b/sound/soc/sof/intel/mtl.c @@ -77,6 +77,7 @@ bool mtl_dsp_check_ipc_irq(struct snd_sof_dev *sdev) return false; } +EXPORT_SYMBOL_NS(mtl_dsp_check_ipc_irq, SND_SOC_SOF_INTEL_MTL); /* Check if an SDW IRQ occurred */ static bool mtl_dsp_check_sdw_irq(struct snd_sof_dev *sdev) @@ -120,6 +121,7 @@ int mtl_ipc_send_msg(struct snd_sof_dev *sdev, struct snd_sof_ipc_msg *msg) return 0; } +EXPORT_SYMBOL_NS(mtl_ipc_send_msg, SND_SOC_SOF_INTEL_MTL); void mtl_enable_ipc_interrupts(struct snd_sof_dev *sdev) { @@ -147,6 +149,7 @@ void mtl_disable_ipc_interrupts(struct snd_sof_dev *sdev) snd_sof_dsp_update_bits(sdev, HDA_DSP_BAR, chip->ipc_ctl, MTL_DSP_REG_HFIPCXCTL_BUSY | MTL_DSP_REG_HFIPCXCTL_DONE, 0); } +EXPORT_SYMBOL_NS(mtl_disable_ipc_interrupts, SND_SOC_SOF_INTEL_MTL); static void mtl_enable_sdw_irq(struct snd_sof_dev *sdev, bool enable) { @@ -231,6 +234,7 @@ int mtl_enable_interrupts(struct snd_sof_dev *sdev, bool enable) return ret; } +EXPORT_SYMBOL_NS(mtl_enable_interrupts, SND_SOC_SOF_INTEL_MTL); /* pre fw run operations */ int mtl_dsp_pre_fw_run(struct snd_sof_dev *sdev) @@ -281,6 +285,7 @@ int mtl_dsp_pre_fw_run(struct snd_sof_dev *sdev) return ret; } +EXPORT_SYMBOL_NS(mtl_dsp_pre_fw_run, SND_SOC_SOF_INTEL_MTL); int mtl_dsp_post_fw_run(struct snd_sof_dev *sdev) { @@ -307,6 +312,7 @@ int mtl_dsp_post_fw_run(struct snd_sof_dev *sdev) hda_sdw_int_enable(sdev, true); return 0; } +EXPORT_SYMBOL_NS(mtl_dsp_post_fw_run, SND_SOC_SOF_INTEL_MTL); void mtl_dsp_dump(struct snd_sof_dev *sdev, u32 flags) { @@ -324,6 +330,7 @@ void mtl_dsp_dump(struct snd_sof_dev *sdev, u32 flags) sof_ipc4_intel_dump_telemetry_state(sdev, flags); } +EXPORT_SYMBOL_NS(mtl_dsp_dump, SND_SOC_SOF_INTEL_MTL); static bool mtl_dsp_primary_core_is_enabled(struct snd_sof_dev *sdev) { @@ -434,6 +441,7 @@ int mtl_power_down_dsp(struct snd_sof_dev *sdev) (dsphfdsscs & cpa) == 0, HDA_DSP_REG_POLL_INTERVAL_US, HDA_DSP_RESET_TIMEOUT_US); } +EXPORT_SYMBOL_NS(mtl_power_down_dsp, SND_SOC_SOF_INTEL_MTL); int mtl_dsp_cl_init(struct snd_sof_dev *sdev, int stream_tag, bool imr_boot) { @@ -536,6 +544,7 @@ err: kfree(dump_msg); return ret; } +EXPORT_SYMBOL_NS(mtl_dsp_cl_init, SND_SOC_SOF_INTEL_MTL); irqreturn_t mtl_ipc_irq_thread(int irq, void *context) { @@ -619,16 +628,19 @@ irqreturn_t mtl_ipc_irq_thread(int irq, void *context) return IRQ_HANDLED; } +EXPORT_SYMBOL_NS(mtl_ipc_irq_thread, SND_SOC_SOF_INTEL_MTL); int mtl_dsp_ipc_get_mailbox_offset(struct snd_sof_dev *sdev) { return MTL_DSP_MBOX_UPLINK_OFFSET; } +EXPORT_SYMBOL_NS(mtl_dsp_ipc_get_mailbox_offset, SND_SOC_SOF_INTEL_MTL); int mtl_dsp_ipc_get_window_offset(struct snd_sof_dev *sdev, u32 id) { return MTL_SRAM_WINDOW_OFFSET(id); } +EXPORT_SYMBOL_NS(mtl_dsp_ipc_get_window_offset, SND_SOC_SOF_INTEL_MTL); void mtl_ipc_dump(struct snd_sof_dev *sdev) { @@ -646,6 +658,7 @@ void mtl_ipc_dump(struct snd_sof_dev *sdev) "Host IPC initiator: %#x|%#x|%#x, target: %#x|%#x|%#x, ctl: %#x\n", hipcidr, hipcidd, hipcida, hipctdr, hipctdd, hipctda, hipcctl); } +EXPORT_SYMBOL_NS(mtl_ipc_dump, SND_SOC_SOF_INTEL_MTL); static int mtl_dsp_disable_interrupts(struct snd_sof_dev *sdev) { @@ -666,6 +679,7 @@ int mtl_dsp_core_get(struct snd_sof_dev *sdev, int core) return 0; } +EXPORT_SYMBOL_NS(mtl_dsp_core_get, SND_SOC_SOF_INTEL_MTL); int mtl_dsp_core_put(struct snd_sof_dev *sdev, int core) { @@ -683,10 +697,10 @@ int mtl_dsp_core_put(struct snd_sof_dev *sdev, int core) return 0; } +EXPORT_SYMBOL_NS(mtl_dsp_core_put, SND_SOC_SOF_INTEL_MTL); /* Meteorlake ops */ struct snd_sof_dsp_ops sof_mtl_ops; -EXPORT_SYMBOL_NS(sof_mtl_ops, SND_SOC_SOF_INTEL_HDA_COMMON); int sof_mtl_ops_init(struct snd_sof_dev *sdev) { @@ -744,7 +758,6 @@ int sof_mtl_ops_init(struct snd_sof_dev *sdev) return 0; }; -EXPORT_SYMBOL_NS(sof_mtl_ops_init, SND_SOC_SOF_INTEL_HDA_COMMON); const struct sof_intel_dsp_desc mtl_chip_info = { .cores_num = 3, @@ -772,7 +785,6 @@ const struct sof_intel_dsp_desc mtl_chip_info = { .disable_interrupts = mtl_dsp_disable_interrupts, .hw_ip_version = SOF_INTEL_ACE_1_0, }; -EXPORT_SYMBOL_NS(mtl_chip_info, SND_SOC_SOF_INTEL_HDA_COMMON); const struct sof_intel_dsp_desc arl_s_chip_info = { .cores_num = 2, @@ -800,4 +812,3 @@ const struct sof_intel_dsp_desc arl_s_chip_info = { .disable_interrupts = mtl_dsp_disable_interrupts, .hw_ip_version = SOF_INTEL_ACE_1_0, }; -EXPORT_SYMBOL_NS(arl_s_chip_info, SND_SOC_SOF_INTEL_HDA_COMMON); diff --git a/sound/soc/sof/intel/pci-icl.c b/sound/soc/sof/intel/pci-icl.c index b99c7c9aad7d..70689b8b431b 100644 --- a/sound/soc/sof/intel/pci-icl.c +++ b/sound/soc/sof/intel/pci-icl.c @@ -109,4 +109,5 @@ module_pci_driver(snd_sof_pci_intel_icl_driver); MODULE_LICENSE("Dual BSD/GPL"); MODULE_IMPORT_NS(SND_SOC_SOF_INTEL_HDA_COMMON); +MODULE_IMPORT_NS(SND_SOC_SOF_INTEL_CNL); MODULE_IMPORT_NS(SND_SOC_SOF_PCI_DEV); diff --git a/sound/soc/sof/intel/pci-lnl.c b/sound/soc/sof/intel/pci-lnl.c index b14e508f1f31..38ae649d1def 100644 --- a/sound/soc/sof/intel/pci-lnl.c +++ b/sound/soc/sof/intel/pci-lnl.c @@ -71,4 +71,6 @@ module_pci_driver(snd_sof_pci_intel_lnl_driver); MODULE_LICENSE("Dual BSD/GPL"); MODULE_IMPORT_NS(SND_SOC_SOF_INTEL_HDA_COMMON); +MODULE_IMPORT_NS(SND_SOC_SOF_INTEL_MTL); +MODULE_IMPORT_NS(SND_SOC_SOF_HDA_MLINK); MODULE_IMPORT_NS(SND_SOC_SOF_PCI_DEV); diff --git a/sound/soc/sof/intel/pci-tgl.c b/sound/soc/sof/intel/pci-tgl.c index a361ee9d1107..d7ecb892550f 100644 --- a/sound/soc/sof/intel/pci-tgl.c +++ b/sound/soc/sof/intel/pci-tgl.c @@ -318,4 +318,5 @@ module_pci_driver(snd_sof_pci_intel_tgl_driver); MODULE_LICENSE("Dual BSD/GPL"); MODULE_IMPORT_NS(SND_SOC_SOF_INTEL_HDA_COMMON); +MODULE_IMPORT_NS(SND_SOC_SOF_INTEL_CNL); MODULE_IMPORT_NS(SND_SOC_SOF_PCI_DEV); diff --git a/sound/soc/sof/intel/telemetry.c b/sound/soc/sof/intel/telemetry.c index 1a3b5c28a6f0..042360f0d03f 100644 --- a/sound/soc/sof/intel/telemetry.c +++ b/sound/soc/sof/intel/telemetry.c @@ -93,3 +93,4 @@ free_block: free_telemetry_data: kfree(telemetry_data); } +EXPORT_SYMBOL_NS(sof_ipc4_intel_dump_telemetry_state, SND_SOC_SOF_INTEL_HDA_COMMON); diff --git a/sound/soc/sof/intel/tgl.c b/sound/soc/sof/intel/tgl.c index 6cda47a78118..6acc65923834 100644 --- a/sound/soc/sof/intel/tgl.c +++ b/sound/soc/sof/intel/tgl.c @@ -63,7 +63,6 @@ static int tgl_dsp_core_put(struct snd_sof_dev *sdev, int core) /* Tigerlake ops */ struct snd_sof_dsp_ops sof_tgl_ops; -EXPORT_SYMBOL_NS(sof_tgl_ops, SND_SOC_SOF_INTEL_HDA_COMMON); int sof_tgl_ops_init(struct snd_sof_dev *sdev) { @@ -135,7 +134,6 @@ int sof_tgl_ops_init(struct snd_sof_dev *sdev) return 0; }; -EXPORT_SYMBOL_NS(sof_tgl_ops_init, SND_SOC_SOF_INTEL_HDA_COMMON); const struct sof_intel_dsp_desc tgl_chip_info = { /* Tigerlake , Alderlake */ @@ -164,7 +162,6 @@ const struct sof_intel_dsp_desc tgl_chip_info = { .disable_interrupts = hda_dsp_disable_interrupts, .hw_ip_version = SOF_INTEL_CAVS_2_5, }; -EXPORT_SYMBOL_NS(tgl_chip_info, SND_SOC_SOF_INTEL_HDA_COMMON); const struct sof_intel_dsp_desc tglh_chip_info = { /* Tigerlake-H */ @@ -193,7 +190,6 @@ const struct sof_intel_dsp_desc tglh_chip_info = { .disable_interrupts = hda_dsp_disable_interrupts, .hw_ip_version = SOF_INTEL_CAVS_2_5, }; -EXPORT_SYMBOL_NS(tglh_chip_info, SND_SOC_SOF_INTEL_HDA_COMMON); const struct sof_intel_dsp_desc ehl_chip_info = { /* Elkhartlake */ @@ -222,7 +218,6 @@ const struct sof_intel_dsp_desc ehl_chip_info = { .disable_interrupts = hda_dsp_disable_interrupts, .hw_ip_version = SOF_INTEL_CAVS_2_5, }; -EXPORT_SYMBOL_NS(ehl_chip_info, SND_SOC_SOF_INTEL_HDA_COMMON); const struct sof_intel_dsp_desc adls_chip_info = { /* Alderlake-S */ @@ -251,4 +246,3 @@ const struct sof_intel_dsp_desc adls_chip_info = { .disable_interrupts = hda_dsp_disable_interrupts, .hw_ip_version = SOF_INTEL_CAVS_2_5, }; -EXPORT_SYMBOL_NS(adls_chip_info, SND_SOC_SOF_INTEL_HDA_COMMON); -- cgit v1.2.3 From 0bfbe91a2dbba31d41add146ab173721dee85ab3 Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Fri, 3 May 2024 08:52:18 -0500 Subject: ASoC: SOF: Intel: move common code from hda.c To avoid circular dependencies when moving hda.c to a separate module, we need to move the common code to hda-ipc.c and hda-dsp.c No functionality change, just code move. Signed-off-by: Pierre-Louis Bossart Reviewed-by: Bard Liao Reviewed-by: Ranjani Sridharan Link: https://lore.kernel.org/r/20240503135221.229202-5-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/intel/hda-dsp.c | 462 ++++++++++++++++++++++++++++++++ sound/soc/sof/intel/hda-ipc.c | 99 +++++++ sound/soc/sof/intel/hda-stream.c | 4 + sound/soc/sof/intel/hda.c | 561 --------------------------------------- sound/soc/sof/intel/hda.h | 10 + 5 files changed, 575 insertions(+), 561 deletions(-) diff --git a/sound/soc/sof/intel/hda-dsp.c b/sound/soc/sof/intel/hda-dsp.c index 32f034074668..974ac1cd8c6e 100644 --- a/sound/soc/sof/intel/hda-dsp.c +++ b/sound/soc/sof/intel/hda-dsp.c @@ -20,11 +20,21 @@ #include #include #include +#include #include "../sof-audio.h" #include "../ops.h" #include "hda.h" +#include "mtl.h" #include "hda-ipc.h" +#define EXCEPT_MAX_HDR_SIZE 0x400 +#define HDA_EXT_ROM_STATUS_SIZE 8 + +struct hda_dsp_msg_code { + u32 code; + const char *text; +}; + static bool hda_enable_trace_D0I3_S0; #if IS_ENABLED(CONFIG_SND_SOC_SOF_DEBUG) module_param_named(enable_trace_D0I3_S0, hda_enable_trace_D0I3_S0, bool, 0444); @@ -32,6 +42,83 @@ MODULE_PARM_DESC(enable_trace_D0I3_S0, "SOF HDA enable trace when the DSP is in D0I3 in S0"); #endif +static void hda_get_interfaces(struct snd_sof_dev *sdev, u32 *interface_mask) +{ + const struct sof_intel_dsp_desc *chip; + + chip = get_chip_info(sdev->pdata); + switch (chip->hw_ip_version) { + case SOF_INTEL_TANGIER: + case SOF_INTEL_BAYTRAIL: + case SOF_INTEL_BROADWELL: + interface_mask[SOF_DAI_DSP_ACCESS] = BIT(SOF_DAI_INTEL_SSP); + break; + case SOF_INTEL_CAVS_1_5: + case SOF_INTEL_CAVS_1_5_PLUS: + interface_mask[SOF_DAI_DSP_ACCESS] = + BIT(SOF_DAI_INTEL_SSP) | BIT(SOF_DAI_INTEL_DMIC) | BIT(SOF_DAI_INTEL_HDA); + interface_mask[SOF_DAI_HOST_ACCESS] = BIT(SOF_DAI_INTEL_HDA); + break; + case SOF_INTEL_CAVS_1_8: + case SOF_INTEL_CAVS_2_0: + case SOF_INTEL_CAVS_2_5: + case SOF_INTEL_ACE_1_0: + interface_mask[SOF_DAI_DSP_ACCESS] = + BIT(SOF_DAI_INTEL_SSP) | BIT(SOF_DAI_INTEL_DMIC) | + BIT(SOF_DAI_INTEL_HDA) | BIT(SOF_DAI_INTEL_ALH); + interface_mask[SOF_DAI_HOST_ACCESS] = BIT(SOF_DAI_INTEL_HDA); + break; + case SOF_INTEL_ACE_2_0: + interface_mask[SOF_DAI_DSP_ACCESS] = + BIT(SOF_DAI_INTEL_SSP) | BIT(SOF_DAI_INTEL_DMIC) | + BIT(SOF_DAI_INTEL_HDA) | BIT(SOF_DAI_INTEL_ALH); + /* all interfaces accessible without DSP */ + interface_mask[SOF_DAI_HOST_ACCESS] = + interface_mask[SOF_DAI_DSP_ACCESS]; + break; + default: + break; + } +} + +u32 hda_get_interface_mask(struct snd_sof_dev *sdev) +{ + u32 interface_mask[SOF_DAI_ACCESS_NUM] = { 0 }; + + hda_get_interfaces(sdev, interface_mask); + + return interface_mask[sdev->dspless_mode_selected]; +} + +bool hda_is_chain_dma_supported(struct snd_sof_dev *sdev, u32 dai_type) +{ + u32 interface_mask[SOF_DAI_ACCESS_NUM] = { 0 }; + const struct sof_intel_dsp_desc *chip; + + if (sdev->dspless_mode_selected) + return false; + + hda_get_interfaces(sdev, interface_mask); + + if (!(interface_mask[SOF_DAI_DSP_ACCESS] & BIT(dai_type))) + return false; + + if (dai_type == SOF_DAI_INTEL_HDA) + return true; + + switch (dai_type) { + case SOF_DAI_INTEL_SSP: + case SOF_DAI_INTEL_DMIC: + case SOF_DAI_INTEL_ALH: + chip = get_chip_info(sdev->pdata); + if (chip->hw_ip_version < SOF_INTEL_ACE_2_0) + return false; + return true; + default: + return false; + } +} + /* * DSP Core control. */ @@ -1134,6 +1221,98 @@ power_down: } EXPORT_SYMBOL_NS(hda_dsp_core_get, SND_SOC_SOF_INTEL_HDA_COMMON); +#if IS_ENABLED(CONFIG_SND_SOC_SOF_INTEL_SOUNDWIRE) +void hda_common_enable_sdw_irq(struct snd_sof_dev *sdev, bool enable) +{ + struct sof_intel_hda_dev *hdev; + + hdev = sdev->pdata->hw_pdata; + + if (!hdev->sdw) + return; + + snd_sof_dsp_update_bits(sdev, HDA_DSP_BAR, HDA_DSP_REG_ADSPIC2, + HDA_DSP_REG_ADSPIC2_SNDW, + enable ? HDA_DSP_REG_ADSPIC2_SNDW : 0); +} +EXPORT_SYMBOL_NS(hda_common_enable_sdw_irq, SND_SOC_SOF_INTEL_HDA_COMMON); + +void hda_sdw_int_enable(struct snd_sof_dev *sdev, bool enable) +{ + u32 interface_mask = hda_get_interface_mask(sdev); + const struct sof_intel_dsp_desc *chip; + + if (!(interface_mask & BIT(SOF_DAI_INTEL_ALH))) + return; + + chip = get_chip_info(sdev->pdata); + if (chip && chip->enable_sdw_irq) + chip->enable_sdw_irq(sdev, enable); +} +EXPORT_SYMBOL_NS(hda_sdw_int_enable, SND_SOC_SOF_INTEL_HDA_COMMON); + +int hda_sdw_check_lcount_common(struct snd_sof_dev *sdev) +{ + struct sof_intel_hda_dev *hdev; + struct sdw_intel_ctx *ctx; + u32 caps; + + hdev = sdev->pdata->hw_pdata; + ctx = hdev->sdw; + + caps = snd_sof_dsp_read(sdev, HDA_DSP_BAR, ctx->shim_base + SDW_SHIM_LCAP); + caps &= SDW_SHIM_LCAP_LCOUNT_MASK; + + /* Check HW supported vs property value */ + if (caps < ctx->count) { + dev_err(sdev->dev, + "%s: BIOS master count %d is larger than hardware capabilities %d\n", + __func__, ctx->count, caps); + return -EINVAL; + } + + return 0; +} +EXPORT_SYMBOL_NS(hda_sdw_check_lcount_common, SND_SOC_SOF_INTEL_HDA_COMMON); + +int hda_sdw_check_lcount_ext(struct snd_sof_dev *sdev) +{ + struct sof_intel_hda_dev *hdev; + struct sdw_intel_ctx *ctx; + struct hdac_bus *bus; + u32 slcount; + + bus = sof_to_bus(sdev); + + hdev = sdev->pdata->hw_pdata; + ctx = hdev->sdw; + + slcount = hdac_bus_eml_get_count(bus, true, AZX_REG_ML_LEPTR_ID_SDW); + + /* Check HW supported vs property value */ + if (slcount < ctx->count) { + dev_err(sdev->dev, + "%s: BIOS master count %d is larger than hardware capabilities %d\n", + __func__, ctx->count, slcount); + return -EINVAL; + } + + return 0; +} +EXPORT_SYMBOL_NS(hda_sdw_check_lcount_ext, SND_SOC_SOF_INTEL_HDA_COMMON); + +int hda_sdw_check_lcount(struct snd_sof_dev *sdev) +{ + const struct sof_intel_dsp_desc *chip; + + chip = get_chip_info(sdev->pdata); + if (chip && chip->read_sdw_lcount) + return chip->read_sdw_lcount(sdev); + + return 0; +} +#endif + int hda_dsp_disable_interrupts(struct snd_sof_dev *sdev) { hda_sdw_int_enable(sdev, false); @@ -1142,3 +1321,286 @@ int hda_dsp_disable_interrupts(struct snd_sof_dev *sdev) return 0; } EXPORT_SYMBOL_NS(hda_dsp_disable_interrupts, SND_SOC_SOF_INTEL_HDA_COMMON); + +static const struct hda_dsp_msg_code hda_dsp_rom_fw_error_texts[] = { + {HDA_DSP_ROM_CSE_ERROR, "error: cse error"}, + {HDA_DSP_ROM_CSE_WRONG_RESPONSE, "error: cse wrong response"}, + {HDA_DSP_ROM_IMR_TO_SMALL, "error: IMR too small"}, + {HDA_DSP_ROM_BASE_FW_NOT_FOUND, "error: base fw not found"}, + {HDA_DSP_ROM_CSE_VALIDATION_FAILED, "error: signature verification failed"}, + {HDA_DSP_ROM_IPC_FATAL_ERROR, "error: ipc fatal error"}, + {HDA_DSP_ROM_L2_CACHE_ERROR, "error: L2 cache error"}, + {HDA_DSP_ROM_LOAD_OFFSET_TO_SMALL, "error: load offset too small"}, + {HDA_DSP_ROM_API_PTR_INVALID, "error: API ptr invalid"}, + {HDA_DSP_ROM_BASEFW_INCOMPAT, "error: base fw incompatible"}, + {HDA_DSP_ROM_UNHANDLED_INTERRUPT, "error: unhandled interrupt"}, + {HDA_DSP_ROM_MEMORY_HOLE_ECC, "error: ECC memory hole"}, + {HDA_DSP_ROM_KERNEL_EXCEPTION, "error: kernel exception"}, + {HDA_DSP_ROM_USER_EXCEPTION, "error: user exception"}, + {HDA_DSP_ROM_UNEXPECTED_RESET, "error: unexpected reset"}, + {HDA_DSP_ROM_NULL_FW_ENTRY, "error: null FW entry point"}, +}; + +#define FSR_ROM_STATE_ENTRY(state) {FSR_STATE_ROM_##state, #state} +static const struct hda_dsp_msg_code cavs_fsr_rom_state_names[] = { + FSR_ROM_STATE_ENTRY(INIT), + FSR_ROM_STATE_ENTRY(INIT_DONE), + FSR_ROM_STATE_ENTRY(CSE_MANIFEST_LOADED), + FSR_ROM_STATE_ENTRY(FW_MANIFEST_LOADED), + FSR_ROM_STATE_ENTRY(FW_FW_LOADED), + FSR_ROM_STATE_ENTRY(FW_ENTERED), + FSR_ROM_STATE_ENTRY(VERIFY_FEATURE_MASK), + FSR_ROM_STATE_ENTRY(GET_LOAD_OFFSET), + FSR_ROM_STATE_ENTRY(FETCH_ROM_EXT), + FSR_ROM_STATE_ENTRY(FETCH_ROM_EXT_DONE), + /* CSE states */ + FSR_ROM_STATE_ENTRY(CSE_IMR_REQUEST), + FSR_ROM_STATE_ENTRY(CSE_IMR_GRANTED), + FSR_ROM_STATE_ENTRY(CSE_VALIDATE_IMAGE_REQUEST), + FSR_ROM_STATE_ENTRY(CSE_IMAGE_VALIDATED), + FSR_ROM_STATE_ENTRY(CSE_IPC_IFACE_INIT), + FSR_ROM_STATE_ENTRY(CSE_IPC_RESET_PHASE_1), + FSR_ROM_STATE_ENTRY(CSE_IPC_OPERATIONAL_ENTRY), + FSR_ROM_STATE_ENTRY(CSE_IPC_OPERATIONAL), + FSR_ROM_STATE_ENTRY(CSE_IPC_DOWN), +}; + +static const struct hda_dsp_msg_code ace_fsr_rom_state_names[] = { + FSR_ROM_STATE_ENTRY(INIT), + FSR_ROM_STATE_ENTRY(INIT_DONE), + FSR_ROM_STATE_ENTRY(CSE_MANIFEST_LOADED), + FSR_ROM_STATE_ENTRY(FW_MANIFEST_LOADED), + FSR_ROM_STATE_ENTRY(FW_FW_LOADED), + FSR_ROM_STATE_ENTRY(FW_ENTERED), + FSR_ROM_STATE_ENTRY(VERIFY_FEATURE_MASK), + FSR_ROM_STATE_ENTRY(GET_LOAD_OFFSET), + FSR_ROM_STATE_ENTRY(RESET_VECTOR_DONE), + FSR_ROM_STATE_ENTRY(PURGE_BOOT), + FSR_ROM_STATE_ENTRY(RESTORE_BOOT), + FSR_ROM_STATE_ENTRY(FW_ENTRY_POINT), + FSR_ROM_STATE_ENTRY(VALIDATE_PUB_KEY), + FSR_ROM_STATE_ENTRY(POWER_DOWN_HPSRAM), + FSR_ROM_STATE_ENTRY(POWER_DOWN_ULPSRAM), + FSR_ROM_STATE_ENTRY(POWER_UP_ULPSRAM_STACK), + FSR_ROM_STATE_ENTRY(POWER_UP_HPSRAM_DMA), + FSR_ROM_STATE_ENTRY(BEFORE_EP_POINTER_READ), + FSR_ROM_STATE_ENTRY(VALIDATE_MANIFEST), + FSR_ROM_STATE_ENTRY(VALIDATE_FW_MODULE), + FSR_ROM_STATE_ENTRY(PROTECT_IMR_REGION), + FSR_ROM_STATE_ENTRY(PUSH_MODEL_ROUTINE), + FSR_ROM_STATE_ENTRY(PULL_MODEL_ROUTINE), + FSR_ROM_STATE_ENTRY(VALIDATE_PKG_DIR), + FSR_ROM_STATE_ENTRY(VALIDATE_CPD), + FSR_ROM_STATE_ENTRY(VALIDATE_CSS_MAN_HEADER), + FSR_ROM_STATE_ENTRY(VALIDATE_BLOB_SVN), + FSR_ROM_STATE_ENTRY(VERIFY_IFWI_PARTITION), + FSR_ROM_STATE_ENTRY(REMOVE_ACCESS_CONTROL), + FSR_ROM_STATE_ENTRY(AUTH_BYPASS), + FSR_ROM_STATE_ENTRY(AUTH_ENABLED), + FSR_ROM_STATE_ENTRY(INIT_DMA), + FSR_ROM_STATE_ENTRY(PURGE_FW_ENTRY), + FSR_ROM_STATE_ENTRY(PURGE_FW_END), + FSR_ROM_STATE_ENTRY(CLEAN_UP_BSS_DONE), + FSR_ROM_STATE_ENTRY(IMR_RESTORE_ENTRY), + FSR_ROM_STATE_ENTRY(IMR_RESTORE_END), + FSR_ROM_STATE_ENTRY(FW_MANIFEST_IN_DMA_BUFF), + FSR_ROM_STATE_ENTRY(LOAD_CSE_MAN_TO_IMR), + FSR_ROM_STATE_ENTRY(LOAD_FW_MAN_TO_IMR), + FSR_ROM_STATE_ENTRY(LOAD_FW_CODE_TO_IMR), + FSR_ROM_STATE_ENTRY(FW_LOADING_DONE), + FSR_ROM_STATE_ENTRY(FW_CODE_LOADED), + FSR_ROM_STATE_ENTRY(VERIFY_IMAGE_TYPE), + FSR_ROM_STATE_ENTRY(AUTH_API_INIT), + FSR_ROM_STATE_ENTRY(AUTH_API_PROC), + FSR_ROM_STATE_ENTRY(AUTH_API_FIRST_BUSY), + FSR_ROM_STATE_ENTRY(AUTH_API_FIRST_RESULT), + FSR_ROM_STATE_ENTRY(AUTH_API_CLEANUP), +}; + +#define FSR_BRINGUP_STATE_ENTRY(state) {FSR_STATE_BRINGUP_##state, #state} +static const struct hda_dsp_msg_code fsr_bringup_state_names[] = { + FSR_BRINGUP_STATE_ENTRY(INIT), + FSR_BRINGUP_STATE_ENTRY(INIT_DONE), + FSR_BRINGUP_STATE_ENTRY(HPSRAM_LOAD), + FSR_BRINGUP_STATE_ENTRY(UNPACK_START), + FSR_BRINGUP_STATE_ENTRY(IMR_RESTORE), + FSR_BRINGUP_STATE_ENTRY(FW_ENTERED), +}; + +#define FSR_WAIT_STATE_ENTRY(state) {FSR_WAIT_FOR_##state, #state} +static const struct hda_dsp_msg_code fsr_wait_state_names[] = { + FSR_WAIT_STATE_ENTRY(IPC_BUSY), + FSR_WAIT_STATE_ENTRY(IPC_DONE), + FSR_WAIT_STATE_ENTRY(CACHE_INVALIDATION), + FSR_WAIT_STATE_ENTRY(LP_SRAM_OFF), + FSR_WAIT_STATE_ENTRY(DMA_BUFFER_FULL), + FSR_WAIT_STATE_ENTRY(CSE_CSR), +}; + +#define FSR_MODULE_NAME_ENTRY(mod) [FSR_MOD_##mod] = #mod +static const char * const fsr_module_names[] = { + FSR_MODULE_NAME_ENTRY(ROM), + FSR_MODULE_NAME_ENTRY(ROM_BYP), + FSR_MODULE_NAME_ENTRY(BASE_FW), + FSR_MODULE_NAME_ENTRY(LP_BOOT), + FSR_MODULE_NAME_ENTRY(BRNGUP), + FSR_MODULE_NAME_ENTRY(ROM_EXT), +}; + +static const char * +hda_dsp_get_state_text(u32 code, const struct hda_dsp_msg_code *msg_code, + size_t array_size) +{ + int i; + + for (i = 0; i < array_size; i++) { + if (code == msg_code[i].code) + return msg_code[i].text; + } + + return NULL; +} + +void hda_dsp_get_state(struct snd_sof_dev *sdev, const char *level) +{ + const struct sof_intel_dsp_desc *chip = get_chip_info(sdev->pdata); + const char *state_text, *error_text, *module_text; + u32 fsr, state, wait_state, module, error_code; + + fsr = snd_sof_dsp_read(sdev, HDA_DSP_BAR, chip->rom_status_reg); + state = FSR_TO_STATE_CODE(fsr); + wait_state = FSR_TO_WAIT_STATE_CODE(fsr); + module = FSR_TO_MODULE_CODE(fsr); + + if (module > FSR_MOD_ROM_EXT) + module_text = "unknown"; + else + module_text = fsr_module_names[module]; + + if (module == FSR_MOD_BRNGUP) { + state_text = hda_dsp_get_state_text(state, fsr_bringup_state_names, + ARRAY_SIZE(fsr_bringup_state_names)); + } else { + if (chip->hw_ip_version < SOF_INTEL_ACE_1_0) + state_text = hda_dsp_get_state_text(state, + cavs_fsr_rom_state_names, + ARRAY_SIZE(cavs_fsr_rom_state_names)); + else + state_text = hda_dsp_get_state_text(state, + ace_fsr_rom_state_names, + ARRAY_SIZE(ace_fsr_rom_state_names)); + } + + /* not for us, must be generic sof message */ + if (!state_text) { + dev_printk(level, sdev->dev, "%#010x: unknown ROM status value\n", fsr); + return; + } + + if (wait_state) { + const char *wait_state_text; + + wait_state_text = hda_dsp_get_state_text(wait_state, fsr_wait_state_names, + ARRAY_SIZE(fsr_wait_state_names)); + if (!wait_state_text) + wait_state_text = "unknown"; + + dev_printk(level, sdev->dev, + "%#010x: module: %s, state: %s, waiting for: %s, %s\n", + fsr, module_text, state_text, wait_state_text, + fsr & FSR_HALTED ? "not running" : "running"); + } else { + dev_printk(level, sdev->dev, "%#010x: module: %s, state: %s, %s\n", + fsr, module_text, state_text, + fsr & FSR_HALTED ? "not running" : "running"); + } + + error_code = snd_sof_dsp_read(sdev, HDA_DSP_BAR, chip->rom_status_reg + 4); + if (!error_code) + return; + + error_text = hda_dsp_get_state_text(error_code, hda_dsp_rom_fw_error_texts, + ARRAY_SIZE(hda_dsp_rom_fw_error_texts)); + if (!error_text) + error_text = "unknown"; + + if (state == FSR_STATE_FW_ENTERED) + dev_printk(level, sdev->dev, "status code: %#x (%s)\n", error_code, + error_text); + else + dev_printk(level, sdev->dev, "error code: %#x (%s)\n", error_code, + error_text); +} +EXPORT_SYMBOL_NS(hda_dsp_get_state, SND_SOC_SOF_INTEL_HDA_COMMON); + +static void hda_dsp_get_registers(struct snd_sof_dev *sdev, + struct sof_ipc_dsp_oops_xtensa *xoops, + struct sof_ipc_panic_info *panic_info, + u32 *stack, size_t stack_words) +{ + u32 offset = sdev->dsp_oops_offset; + + /* first read registers */ + sof_mailbox_read(sdev, offset, xoops, sizeof(*xoops)); + + /* note: variable AR register array is not read */ + + /* then get panic info */ + if (xoops->arch_hdr.totalsize > EXCEPT_MAX_HDR_SIZE) { + dev_err(sdev->dev, "invalid header size 0x%x. FW oops is bogus\n", + xoops->arch_hdr.totalsize); + return; + } + offset += xoops->arch_hdr.totalsize; + sof_block_read(sdev, sdev->mmio_bar, offset, + panic_info, sizeof(*panic_info)); + + /* then get the stack */ + offset += sizeof(*panic_info); + sof_block_read(sdev, sdev->mmio_bar, offset, stack, + stack_words * sizeof(u32)); +} + +/* dump the first 8 dwords representing the extended ROM status */ +void hda_dsp_dump_ext_rom_status(struct snd_sof_dev *sdev, const char *level, + u32 flags) +{ + const struct sof_intel_dsp_desc *chip; + char msg[128]; + int len = 0; + u32 value; + int i; + + chip = get_chip_info(sdev->pdata); + for (i = 0; i < HDA_EXT_ROM_STATUS_SIZE; i++) { + value = snd_sof_dsp_read(sdev, HDA_DSP_BAR, chip->rom_status_reg + i * 0x4); + len += scnprintf(msg + len, sizeof(msg) - len, " 0x%x", value); + } + + dev_printk(level, sdev->dev, "extended rom status: %s", msg); + +} + +void hda_dsp_dump(struct snd_sof_dev *sdev, u32 flags) +{ + char *level = (flags & SOF_DBG_DUMP_OPTIONAL) ? KERN_DEBUG : KERN_ERR; + struct sof_ipc_dsp_oops_xtensa xoops; + struct sof_ipc_panic_info panic_info; + u32 stack[HDA_DSP_STACK_DUMP_SIZE]; + + /* print ROM/FW status */ + hda_dsp_get_state(sdev, level); + + /* The firmware register dump only available with IPC3 */ + if (flags & SOF_DBG_DUMP_REGS && sdev->pdata->ipc_type == SOF_IPC_TYPE_3) { + u32 status = snd_sof_dsp_read(sdev, HDA_DSP_BAR, HDA_DSP_SRAM_REG_FW_STATUS); + u32 panic = snd_sof_dsp_read(sdev, HDA_DSP_BAR, HDA_DSP_SRAM_REG_FW_TRACEP); + + hda_dsp_get_registers(sdev, &xoops, &panic_info, stack, + HDA_DSP_STACK_DUMP_SIZE); + sof_print_oops_and_stack(sdev, level, status, panic, &xoops, + &panic_info, stack, HDA_DSP_STACK_DUMP_SIZE); + } else { + hda_dsp_dump_ext_rom_status(sdev, level, flags); + } +} diff --git a/sound/soc/sof/intel/hda-ipc.c b/sound/soc/sof/intel/hda-ipc.c index 6919729cef52..2252c9198cc0 100644 --- a/sound/soc/sof/intel/hda-ipc.c +++ b/sound/soc/sof/intel/hda-ipc.c @@ -15,10 +15,12 @@ * Hardware interface for generic Intel audio DSP HDA IP */ +#include #include #include #include "../ops.h" #include "hda.h" +#include "telemetry.h" EXPORT_TRACEPOINT_SYMBOL(sof_intel_ipc_firmware_initiated); EXPORT_TRACEPOINT_SYMBOL(sof_intel_ipc_firmware_response); @@ -450,3 +452,100 @@ int hda_set_stream_data_offset(struct snd_sof_dev *sdev, return 0; } + +void hda_ipc4_dsp_dump(struct snd_sof_dev *sdev, u32 flags) +{ + char *level = (flags & SOF_DBG_DUMP_OPTIONAL) ? KERN_DEBUG : KERN_ERR; + + /* print ROM/FW status */ + hda_dsp_get_state(sdev, level); + + if (flags & SOF_DBG_DUMP_REGS) + sof_ipc4_intel_dump_telemetry_state(sdev, flags); + else + hda_dsp_dump_ext_rom_status(sdev, level, flags); +} +EXPORT_SYMBOL_NS(hda_ipc4_dsp_dump, SND_SOC_SOF_INTEL_HDA_COMMON); + +bool hda_check_ipc_irq(struct snd_sof_dev *sdev) +{ + const struct sof_intel_dsp_desc *chip; + + chip = get_chip_info(sdev->pdata); + if (chip && chip->check_ipc_irq) + return chip->check_ipc_irq(sdev); + + return false; +} + +void hda_ipc_irq_dump(struct snd_sof_dev *sdev) +{ + u32 adspis; + u32 intsts; + u32 intctl; + u32 ppsts; + u8 rirbsts; + + /* read key IRQ stats and config registers */ + adspis = snd_sof_dsp_read(sdev, HDA_DSP_BAR, HDA_DSP_REG_ADSPIS); + intsts = snd_sof_dsp_read(sdev, HDA_DSP_HDA_BAR, SOF_HDA_INTSTS); + intctl = snd_sof_dsp_read(sdev, HDA_DSP_HDA_BAR, SOF_HDA_INTCTL); + ppsts = snd_sof_dsp_read(sdev, HDA_DSP_PP_BAR, SOF_HDA_REG_PP_PPSTS); + rirbsts = snd_sof_dsp_read8(sdev, HDA_DSP_HDA_BAR, AZX_REG_RIRBSTS); + + dev_err(sdev->dev, "hda irq intsts 0x%8.8x intlctl 0x%8.8x rirb %2.2x\n", + intsts, intctl, rirbsts); + dev_err(sdev->dev, "dsp irq ppsts 0x%8.8x adspis 0x%8.8x\n", ppsts, adspis); +} +EXPORT_SYMBOL_NS(hda_ipc_irq_dump, SND_SOC_SOF_INTEL_HDA_COMMON); + +void hda_ipc_dump(struct snd_sof_dev *sdev) +{ + u32 hipcie; + u32 hipct; + u32 hipcctl; + + hda_ipc_irq_dump(sdev); + + /* read IPC status */ + hipcie = snd_sof_dsp_read(sdev, HDA_DSP_BAR, HDA_DSP_REG_HIPCIE); + hipct = snd_sof_dsp_read(sdev, HDA_DSP_BAR, HDA_DSP_REG_HIPCT); + hipcctl = snd_sof_dsp_read(sdev, HDA_DSP_BAR, HDA_DSP_REG_HIPCCTL); + + /* dump the IPC regs */ + /* TODO: parse the raw msg */ + dev_err(sdev->dev, "host status 0x%8.8x dsp status 0x%8.8x mask 0x%8.8x\n", + hipcie, hipct, hipcctl); +} +EXPORT_SYMBOL_NS(hda_ipc_dump, SND_SOC_SOF_INTEL_HDA_COMMON); + +void hda_ipc4_dump(struct snd_sof_dev *sdev) +{ + u32 hipci, hipcie, hipct, hipcte, hipcctl; + + hda_ipc_irq_dump(sdev); + + hipci = snd_sof_dsp_read(sdev, HDA_DSP_BAR, HDA_DSP_REG_HIPCI); + hipcie = snd_sof_dsp_read(sdev, HDA_DSP_BAR, HDA_DSP_REG_HIPCIE); + hipct = snd_sof_dsp_read(sdev, HDA_DSP_BAR, HDA_DSP_REG_HIPCT); + hipcte = snd_sof_dsp_read(sdev, HDA_DSP_BAR, HDA_DSP_REG_HIPCTE); + hipcctl = snd_sof_dsp_read(sdev, HDA_DSP_BAR, HDA_DSP_REG_HIPCCTL); + + /* dump the IPC regs */ + /* TODO: parse the raw msg */ + dev_err(sdev->dev, "Host IPC initiator: %#x|%#x, target: %#x|%#x, ctl: %#x\n", + hipci, hipcie, hipct, hipcte, hipcctl); +} +EXPORT_SYMBOL_NS(hda_ipc4_dump, SND_SOC_SOF_INTEL_HDA_COMMON); + +bool hda_ipc4_tx_is_busy(struct snd_sof_dev *sdev) +{ + struct sof_intel_hda_dev *hda = sdev->pdata->hw_pdata; + const struct sof_intel_dsp_desc *chip = hda->desc; + u32 val; + + val = snd_sof_dsp_read(sdev, HDA_DSP_BAR, chip->ipc_req); + + return !!(val & chip->ipc_req_mask); +} +EXPORT_SYMBOL_NS(hda_ipc4_tx_is_busy, SND_SOC_SOF_INTEL_HDA_COMMON); diff --git a/sound/soc/sof/intel/hda-stream.c b/sound/soc/sof/intel/hda-stream.c index c5afcda18359..4fef1964b5cd 100644 --- a/sound/soc/sof/intel/hda-stream.c +++ b/sound/soc/sof/intel/hda-stream.c @@ -24,6 +24,10 @@ #include "../ipc4-priv.h" #include "hda.h" +int sof_hda_position_quirk = SOF_HDA_POSITION_QUIRK_USE_DPIB_REGISTERS; +module_param_named(position_quirk, sof_hda_position_quirk, int, 0444); +MODULE_PARM_DESC(position_quirk, "SOF HDaudio position quirk"); + #define HDA_LTRP_GB_VALUE_US 95 static inline const char *hda_hstream_direction_str(struct hdac_stream *hstream) diff --git a/sound/soc/sof/intel/hda.c b/sound/soc/sof/intel/hda.c index e4ee2918614e..a96926fb45b6 100644 --- a/sound/soc/sof/intel/hda.c +++ b/sound/soc/sof/intel/hda.c @@ -34,8 +34,6 @@ #include "../ops.h" #include "../ipc4-topology.h" #include "hda.h" -#include "telemetry.h" -#include "mtl.h" #define CREATE_TRACE_POINTS #include @@ -47,86 +45,6 @@ /* platform specific devices */ #include "shim.h" -#define EXCEPT_MAX_HDR_SIZE 0x400 -#define HDA_EXT_ROM_STATUS_SIZE 8 - -static void hda_get_interfaces(struct snd_sof_dev *sdev, u32 *interface_mask) -{ - const struct sof_intel_dsp_desc *chip; - - chip = get_chip_info(sdev->pdata); - switch (chip->hw_ip_version) { - case SOF_INTEL_TANGIER: - case SOF_INTEL_BAYTRAIL: - case SOF_INTEL_BROADWELL: - interface_mask[SOF_DAI_DSP_ACCESS] = BIT(SOF_DAI_INTEL_SSP); - break; - case SOF_INTEL_CAVS_1_5: - case SOF_INTEL_CAVS_1_5_PLUS: - interface_mask[SOF_DAI_DSP_ACCESS] = - BIT(SOF_DAI_INTEL_SSP) | BIT(SOF_DAI_INTEL_DMIC) | BIT(SOF_DAI_INTEL_HDA); - interface_mask[SOF_DAI_HOST_ACCESS] = BIT(SOF_DAI_INTEL_HDA); - break; - case SOF_INTEL_CAVS_1_8: - case SOF_INTEL_CAVS_2_0: - case SOF_INTEL_CAVS_2_5: - case SOF_INTEL_ACE_1_0: - interface_mask[SOF_DAI_DSP_ACCESS] = - BIT(SOF_DAI_INTEL_SSP) | BIT(SOF_DAI_INTEL_DMIC) | - BIT(SOF_DAI_INTEL_HDA) | BIT(SOF_DAI_INTEL_ALH); - interface_mask[SOF_DAI_HOST_ACCESS] = BIT(SOF_DAI_INTEL_HDA); - break; - case SOF_INTEL_ACE_2_0: - interface_mask[SOF_DAI_DSP_ACCESS] = - BIT(SOF_DAI_INTEL_SSP) | BIT(SOF_DAI_INTEL_DMIC) | - BIT(SOF_DAI_INTEL_HDA) | BIT(SOF_DAI_INTEL_ALH); - /* all interfaces accessible without DSP */ - interface_mask[SOF_DAI_HOST_ACCESS] = - interface_mask[SOF_DAI_DSP_ACCESS]; - break; - default: - break; - } -} - -static u32 hda_get_interface_mask(struct snd_sof_dev *sdev) -{ - u32 interface_mask[SOF_DAI_ACCESS_NUM] = { 0 }; - - hda_get_interfaces(sdev, interface_mask); - - return interface_mask[sdev->dspless_mode_selected]; -} - -bool hda_is_chain_dma_supported(struct snd_sof_dev *sdev, u32 dai_type) -{ - u32 interface_mask[SOF_DAI_ACCESS_NUM] = { 0 }; - const struct sof_intel_dsp_desc *chip; - - if (sdev->dspless_mode_selected) - return false; - - hda_get_interfaces(sdev, interface_mask); - - if (!(interface_mask[SOF_DAI_DSP_ACCESS] & BIT(dai_type))) - return false; - - if (dai_type == SOF_DAI_INTEL_HDA) - return true; - - switch (dai_type) { - case SOF_DAI_INTEL_SSP: - case SOF_DAI_INTEL_DMIC: - case SOF_DAI_INTEL_ALH: - chip = get_chip_info(sdev->pdata); - if (chip->hw_ip_version < SOF_INTEL_ACE_2_0) - return false; - return true; - default: - return false; - } -} - #if IS_ENABLED(CONFIG_SND_SOC_SOF_INTEL_SOUNDWIRE) /* @@ -210,35 +128,6 @@ static struct sdw_intel_ops sdw_ace2x_callback = { .trigger = sdw_ace2x_trigger, }; -void hda_common_enable_sdw_irq(struct snd_sof_dev *sdev, bool enable) -{ - struct sof_intel_hda_dev *hdev; - - hdev = sdev->pdata->hw_pdata; - - if (!hdev->sdw) - return; - - snd_sof_dsp_update_bits(sdev, HDA_DSP_BAR, HDA_DSP_REG_ADSPIC2, - HDA_DSP_REG_ADSPIC2_SNDW, - enable ? HDA_DSP_REG_ADSPIC2_SNDW : 0); -} -EXPORT_SYMBOL_NS(hda_common_enable_sdw_irq, SND_SOC_SOF_INTEL_HDA_COMMON); - -void hda_sdw_int_enable(struct snd_sof_dev *sdev, bool enable) -{ - u32 interface_mask = hda_get_interface_mask(sdev); - const struct sof_intel_dsp_desc *chip; - - if (!(interface_mask & BIT(SOF_DAI_INTEL_ALH))) - return; - - chip = get_chip_info(sdev->pdata); - if (chip && chip->enable_sdw_irq) - chip->enable_sdw_irq(sdev, enable); -} -EXPORT_SYMBOL_NS(hda_sdw_int_enable, SND_SOC_SOF_INTEL_HDA_COMMON); - static int hda_sdw_acpi_scan(struct snd_sof_dev *sdev) { u32 interface_mask = hda_get_interface_mask(sdev); @@ -330,67 +219,6 @@ static int hda_sdw_probe(struct snd_sof_dev *sdev) return 0; } -int hda_sdw_check_lcount_common(struct snd_sof_dev *sdev) -{ - struct sof_intel_hda_dev *hdev; - struct sdw_intel_ctx *ctx; - u32 caps; - - hdev = sdev->pdata->hw_pdata; - ctx = hdev->sdw; - - caps = snd_sof_dsp_read(sdev, HDA_DSP_BAR, ctx->shim_base + SDW_SHIM_LCAP); - caps &= SDW_SHIM_LCAP_LCOUNT_MASK; - - /* Check HW supported vs property value */ - if (caps < ctx->count) { - dev_err(sdev->dev, - "%s: BIOS master count %d is larger than hardware capabilities %d\n", - __func__, ctx->count, caps); - return -EINVAL; - } - - return 0; -} -EXPORT_SYMBOL_NS(hda_sdw_check_lcount_common, SND_SOC_SOF_INTEL_HDA_COMMON); - -int hda_sdw_check_lcount_ext(struct snd_sof_dev *sdev) -{ - struct sof_intel_hda_dev *hdev; - struct sdw_intel_ctx *ctx; - struct hdac_bus *bus; - u32 slcount; - - bus = sof_to_bus(sdev); - - hdev = sdev->pdata->hw_pdata; - ctx = hdev->sdw; - - slcount = hdac_bus_eml_get_count(bus, true, AZX_REG_ML_LEPTR_ID_SDW); - - /* Check HW supported vs property value */ - if (slcount < ctx->count) { - dev_err(sdev->dev, - "%s: BIOS master count %d is larger than hardware capabilities %d\n", - __func__, ctx->count, slcount); - return -EINVAL; - } - - return 0; -} -EXPORT_SYMBOL_NS(hda_sdw_check_lcount_ext, SND_SOC_SOF_INTEL_HDA_COMMON); - -static int hda_sdw_check_lcount(struct snd_sof_dev *sdev) -{ - const struct sof_intel_dsp_desc *chip; - - chip = get_chip_info(sdev->pdata); - if (chip && chip->read_sdw_lcount) - return chip->read_sdw_lcount(sdev); - - return 0; -} - int hda_sdw_startup(struct snd_sof_dev *sdev) { struct sof_intel_hda_dev *hdev; @@ -596,11 +424,6 @@ EXPORT_SYMBOL_NS(hda_dsp_post_fw_run, SND_SOC_SOF_INTEL_HDA_COMMON); * Debug */ -struct hda_dsp_msg_code { - u32 code; - const char *text; -}; - #if IS_ENABLED(CONFIG_SND_SOC_SOF_DEBUG) static bool hda_use_msi = true; module_param_named(use_msi, hda_use_msi, bool, 0444); @@ -609,10 +432,6 @@ MODULE_PARM_DESC(use_msi, "SOF HDA use PCI MSI mode"); #define hda_use_msi (1) #endif -int sof_hda_position_quirk = SOF_HDA_POSITION_QUIRK_USE_DPIB_REGISTERS; -module_param_named(position_quirk, sof_hda_position_quirk, int, 0444); -MODULE_PARM_DESC(position_quirk, "SOF HDaudio position quirk"); - static char *hda_model; module_param(hda_model, charp, 0444); MODULE_PARM_DESC(hda_model, "Use the given HDA board model."); @@ -625,386 +444,6 @@ static int mclk_id_override = -1; module_param_named(mclk_id, mclk_id_override, int, 0444); MODULE_PARM_DESC(mclk_id, "SOF SSP mclk_id"); -static const struct hda_dsp_msg_code hda_dsp_rom_fw_error_texts[] = { - {HDA_DSP_ROM_CSE_ERROR, "error: cse error"}, - {HDA_DSP_ROM_CSE_WRONG_RESPONSE, "error: cse wrong response"}, - {HDA_DSP_ROM_IMR_TO_SMALL, "error: IMR too small"}, - {HDA_DSP_ROM_BASE_FW_NOT_FOUND, "error: base fw not found"}, - {HDA_DSP_ROM_CSE_VALIDATION_FAILED, "error: signature verification failed"}, - {HDA_DSP_ROM_IPC_FATAL_ERROR, "error: ipc fatal error"}, - {HDA_DSP_ROM_L2_CACHE_ERROR, "error: L2 cache error"}, - {HDA_DSP_ROM_LOAD_OFFSET_TO_SMALL, "error: load offset too small"}, - {HDA_DSP_ROM_API_PTR_INVALID, "error: API ptr invalid"}, - {HDA_DSP_ROM_BASEFW_INCOMPAT, "error: base fw incompatible"}, - {HDA_DSP_ROM_UNHANDLED_INTERRUPT, "error: unhandled interrupt"}, - {HDA_DSP_ROM_MEMORY_HOLE_ECC, "error: ECC memory hole"}, - {HDA_DSP_ROM_KERNEL_EXCEPTION, "error: kernel exception"}, - {HDA_DSP_ROM_USER_EXCEPTION, "error: user exception"}, - {HDA_DSP_ROM_UNEXPECTED_RESET, "error: unexpected reset"}, - {HDA_DSP_ROM_NULL_FW_ENTRY, "error: null FW entry point"}, -}; - -#define FSR_ROM_STATE_ENTRY(state) {FSR_STATE_ROM_##state, #state} -static const struct hda_dsp_msg_code cavs_fsr_rom_state_names[] = { - FSR_ROM_STATE_ENTRY(INIT), - FSR_ROM_STATE_ENTRY(INIT_DONE), - FSR_ROM_STATE_ENTRY(CSE_MANIFEST_LOADED), - FSR_ROM_STATE_ENTRY(FW_MANIFEST_LOADED), - FSR_ROM_STATE_ENTRY(FW_FW_LOADED), - FSR_ROM_STATE_ENTRY(FW_ENTERED), - FSR_ROM_STATE_ENTRY(VERIFY_FEATURE_MASK), - FSR_ROM_STATE_ENTRY(GET_LOAD_OFFSET), - FSR_ROM_STATE_ENTRY(FETCH_ROM_EXT), - FSR_ROM_STATE_ENTRY(FETCH_ROM_EXT_DONE), - /* CSE states */ - FSR_ROM_STATE_ENTRY(CSE_IMR_REQUEST), - FSR_ROM_STATE_ENTRY(CSE_IMR_GRANTED), - FSR_ROM_STATE_ENTRY(CSE_VALIDATE_IMAGE_REQUEST), - FSR_ROM_STATE_ENTRY(CSE_IMAGE_VALIDATED), - FSR_ROM_STATE_ENTRY(CSE_IPC_IFACE_INIT), - FSR_ROM_STATE_ENTRY(CSE_IPC_RESET_PHASE_1), - FSR_ROM_STATE_ENTRY(CSE_IPC_OPERATIONAL_ENTRY), - FSR_ROM_STATE_ENTRY(CSE_IPC_OPERATIONAL), - FSR_ROM_STATE_ENTRY(CSE_IPC_DOWN), -}; - -static const struct hda_dsp_msg_code ace_fsr_rom_state_names[] = { - FSR_ROM_STATE_ENTRY(INIT), - FSR_ROM_STATE_ENTRY(INIT_DONE), - FSR_ROM_STATE_ENTRY(CSE_MANIFEST_LOADED), - FSR_ROM_STATE_ENTRY(FW_MANIFEST_LOADED), - FSR_ROM_STATE_ENTRY(FW_FW_LOADED), - FSR_ROM_STATE_ENTRY(FW_ENTERED), - FSR_ROM_STATE_ENTRY(VERIFY_FEATURE_MASK), - FSR_ROM_STATE_ENTRY(GET_LOAD_OFFSET), - FSR_ROM_STATE_ENTRY(RESET_VECTOR_DONE), - FSR_ROM_STATE_ENTRY(PURGE_BOOT), - FSR_ROM_STATE_ENTRY(RESTORE_BOOT), - FSR_ROM_STATE_ENTRY(FW_ENTRY_POINT), - FSR_ROM_STATE_ENTRY(VALIDATE_PUB_KEY), - FSR_ROM_STATE_ENTRY(POWER_DOWN_HPSRAM), - FSR_ROM_STATE_ENTRY(POWER_DOWN_ULPSRAM), - FSR_ROM_STATE_ENTRY(POWER_UP_ULPSRAM_STACK), - FSR_ROM_STATE_ENTRY(POWER_UP_HPSRAM_DMA), - FSR_ROM_STATE_ENTRY(BEFORE_EP_POINTER_READ), - FSR_ROM_STATE_ENTRY(VALIDATE_MANIFEST), - FSR_ROM_STATE_ENTRY(VALIDATE_FW_MODULE), - FSR_ROM_STATE_ENTRY(PROTECT_IMR_REGION), - FSR_ROM_STATE_ENTRY(PUSH_MODEL_ROUTINE), - FSR_ROM_STATE_ENTRY(PULL_MODEL_ROUTINE), - FSR_ROM_STATE_ENTRY(VALIDATE_PKG_DIR), - FSR_ROM_STATE_ENTRY(VALIDATE_CPD), - FSR_ROM_STATE_ENTRY(VALIDATE_CSS_MAN_HEADER), - FSR_ROM_STATE_ENTRY(VALIDATE_BLOB_SVN), - FSR_ROM_STATE_ENTRY(VERIFY_IFWI_PARTITION), - FSR_ROM_STATE_ENTRY(REMOVE_ACCESS_CONTROL), - FSR_ROM_STATE_ENTRY(AUTH_BYPASS), - FSR_ROM_STATE_ENTRY(AUTH_ENABLED), - FSR_ROM_STATE_ENTRY(INIT_DMA), - FSR_ROM_STATE_ENTRY(PURGE_FW_ENTRY), - FSR_ROM_STATE_ENTRY(PURGE_FW_END), - FSR_ROM_STATE_ENTRY(CLEAN_UP_BSS_DONE), - FSR_ROM_STATE_ENTRY(IMR_RESTORE_ENTRY), - FSR_ROM_STATE_ENTRY(IMR_RESTORE_END), - FSR_ROM_STATE_ENTRY(FW_MANIFEST_IN_DMA_BUFF), - FSR_ROM_STATE_ENTRY(LOAD_CSE_MAN_TO_IMR), - FSR_ROM_STATE_ENTRY(LOAD_FW_MAN_TO_IMR), - FSR_ROM_STATE_ENTRY(LOAD_FW_CODE_TO_IMR), - FSR_ROM_STATE_ENTRY(FW_LOADING_DONE), - FSR_ROM_STATE_ENTRY(FW_CODE_LOADED), - FSR_ROM_STATE_ENTRY(VERIFY_IMAGE_TYPE), - FSR_ROM_STATE_ENTRY(AUTH_API_INIT), - FSR_ROM_STATE_ENTRY(AUTH_API_PROC), - FSR_ROM_STATE_ENTRY(AUTH_API_FIRST_BUSY), - FSR_ROM_STATE_ENTRY(AUTH_API_FIRST_RESULT), - FSR_ROM_STATE_ENTRY(AUTH_API_CLEANUP), -}; - -#define FSR_BRINGUP_STATE_ENTRY(state) {FSR_STATE_BRINGUP_##state, #state} -static const struct hda_dsp_msg_code fsr_bringup_state_names[] = { - FSR_BRINGUP_STATE_ENTRY(INIT), - FSR_BRINGUP_STATE_ENTRY(INIT_DONE), - FSR_BRINGUP_STATE_ENTRY(HPSRAM_LOAD), - FSR_BRINGUP_STATE_ENTRY(UNPACK_START), - FSR_BRINGUP_STATE_ENTRY(IMR_RESTORE), - FSR_BRINGUP_STATE_ENTRY(FW_ENTERED), -}; - -#define FSR_WAIT_STATE_ENTRY(state) {FSR_WAIT_FOR_##state, #state} -static const struct hda_dsp_msg_code fsr_wait_state_names[] = { - FSR_WAIT_STATE_ENTRY(IPC_BUSY), - FSR_WAIT_STATE_ENTRY(IPC_DONE), - FSR_WAIT_STATE_ENTRY(CACHE_INVALIDATION), - FSR_WAIT_STATE_ENTRY(LP_SRAM_OFF), - FSR_WAIT_STATE_ENTRY(DMA_BUFFER_FULL), - FSR_WAIT_STATE_ENTRY(CSE_CSR), -}; - -#define FSR_MODULE_NAME_ENTRY(mod) [FSR_MOD_##mod] = #mod -static const char * const fsr_module_names[] = { - FSR_MODULE_NAME_ENTRY(ROM), - FSR_MODULE_NAME_ENTRY(ROM_BYP), - FSR_MODULE_NAME_ENTRY(BASE_FW), - FSR_MODULE_NAME_ENTRY(LP_BOOT), - FSR_MODULE_NAME_ENTRY(BRNGUP), - FSR_MODULE_NAME_ENTRY(ROM_EXT), -}; - -static const char * -hda_dsp_get_state_text(u32 code, const struct hda_dsp_msg_code *msg_code, - size_t array_size) -{ - int i; - - for (i = 0; i < array_size; i++) { - if (code == msg_code[i].code) - return msg_code[i].text; - } - - return NULL; -} - -void hda_dsp_get_state(struct snd_sof_dev *sdev, const char *level) -{ - const struct sof_intel_dsp_desc *chip = get_chip_info(sdev->pdata); - const char *state_text, *error_text, *module_text; - u32 fsr, state, wait_state, module, error_code; - - fsr = snd_sof_dsp_read(sdev, HDA_DSP_BAR, chip->rom_status_reg); - state = FSR_TO_STATE_CODE(fsr); - wait_state = FSR_TO_WAIT_STATE_CODE(fsr); - module = FSR_TO_MODULE_CODE(fsr); - - if (module > FSR_MOD_ROM_EXT) - module_text = "unknown"; - else - module_text = fsr_module_names[module]; - - if (module == FSR_MOD_BRNGUP) { - state_text = hda_dsp_get_state_text(state, fsr_bringup_state_names, - ARRAY_SIZE(fsr_bringup_state_names)); - } else { - if (chip->hw_ip_version < SOF_INTEL_ACE_1_0) - state_text = hda_dsp_get_state_text(state, - cavs_fsr_rom_state_names, - ARRAY_SIZE(cavs_fsr_rom_state_names)); - else - state_text = hda_dsp_get_state_text(state, - ace_fsr_rom_state_names, - ARRAY_SIZE(ace_fsr_rom_state_names)); - } - - /* not for us, must be generic sof message */ - if (!state_text) { - dev_printk(level, sdev->dev, "%#010x: unknown ROM status value\n", fsr); - return; - } - - if (wait_state) { - const char *wait_state_text; - - wait_state_text = hda_dsp_get_state_text(wait_state, fsr_wait_state_names, - ARRAY_SIZE(fsr_wait_state_names)); - if (!wait_state_text) - wait_state_text = "unknown"; - - dev_printk(level, sdev->dev, - "%#010x: module: %s, state: %s, waiting for: %s, %s\n", - fsr, module_text, state_text, wait_state_text, - fsr & FSR_HALTED ? "not running" : "running"); - } else { - dev_printk(level, sdev->dev, "%#010x: module: %s, state: %s, %s\n", - fsr, module_text, state_text, - fsr & FSR_HALTED ? "not running" : "running"); - } - - error_code = snd_sof_dsp_read(sdev, HDA_DSP_BAR, chip->rom_status_reg + 4); - if (!error_code) - return; - - error_text = hda_dsp_get_state_text(error_code, hda_dsp_rom_fw_error_texts, - ARRAY_SIZE(hda_dsp_rom_fw_error_texts)); - if (!error_text) - error_text = "unknown"; - - if (state == FSR_STATE_FW_ENTERED) - dev_printk(level, sdev->dev, "status code: %#x (%s)\n", error_code, - error_text); - else - dev_printk(level, sdev->dev, "error code: %#x (%s)\n", error_code, - error_text); -} -EXPORT_SYMBOL_NS(hda_dsp_get_state, SND_SOC_SOF_INTEL_HDA_COMMON); - -static void hda_dsp_get_registers(struct snd_sof_dev *sdev, - struct sof_ipc_dsp_oops_xtensa *xoops, - struct sof_ipc_panic_info *panic_info, - u32 *stack, size_t stack_words) -{ - u32 offset = sdev->dsp_oops_offset; - - /* first read registers */ - sof_mailbox_read(sdev, offset, xoops, sizeof(*xoops)); - - /* note: variable AR register array is not read */ - - /* then get panic info */ - if (xoops->arch_hdr.totalsize > EXCEPT_MAX_HDR_SIZE) { - dev_err(sdev->dev, "invalid header size 0x%x. FW oops is bogus\n", - xoops->arch_hdr.totalsize); - return; - } - offset += xoops->arch_hdr.totalsize; - sof_block_read(sdev, sdev->mmio_bar, offset, - panic_info, sizeof(*panic_info)); - - /* then get the stack */ - offset += sizeof(*panic_info); - sof_block_read(sdev, sdev->mmio_bar, offset, stack, - stack_words * sizeof(u32)); -} - -/* dump the first 8 dwords representing the extended ROM status */ -static void hda_dsp_dump_ext_rom_status(struct snd_sof_dev *sdev, const char *level, - u32 flags) -{ - const struct sof_intel_dsp_desc *chip; - char msg[128]; - int len = 0; - u32 value; - int i; - - chip = get_chip_info(sdev->pdata); - for (i = 0; i < HDA_EXT_ROM_STATUS_SIZE; i++) { - value = snd_sof_dsp_read(sdev, HDA_DSP_BAR, chip->rom_status_reg + i * 0x4); - len += scnprintf(msg + len, sizeof(msg) - len, " 0x%x", value); - } - - dev_printk(level, sdev->dev, "extended rom status: %s", msg); - -} - -void hda_dsp_dump(struct snd_sof_dev *sdev, u32 flags) -{ - char *level = (flags & SOF_DBG_DUMP_OPTIONAL) ? KERN_DEBUG : KERN_ERR; - struct sof_ipc_dsp_oops_xtensa xoops; - struct sof_ipc_panic_info panic_info; - u32 stack[HDA_DSP_STACK_DUMP_SIZE]; - - /* print ROM/FW status */ - hda_dsp_get_state(sdev, level); - - /* The firmware register dump only available with IPC3 */ - if (flags & SOF_DBG_DUMP_REGS && sdev->pdata->ipc_type == SOF_IPC_TYPE_3) { - u32 status = snd_sof_dsp_read(sdev, HDA_DSP_BAR, HDA_DSP_SRAM_REG_FW_STATUS); - u32 panic = snd_sof_dsp_read(sdev, HDA_DSP_BAR, HDA_DSP_SRAM_REG_FW_TRACEP); - - hda_dsp_get_registers(sdev, &xoops, &panic_info, stack, - HDA_DSP_STACK_DUMP_SIZE); - sof_print_oops_and_stack(sdev, level, status, panic, &xoops, - &panic_info, stack, HDA_DSP_STACK_DUMP_SIZE); - } else { - hda_dsp_dump_ext_rom_status(sdev, level, flags); - } -} - -void hda_ipc4_dsp_dump(struct snd_sof_dev *sdev, u32 flags) -{ - char *level = (flags & SOF_DBG_DUMP_OPTIONAL) ? KERN_DEBUG : KERN_ERR; - - /* print ROM/FW status */ - hda_dsp_get_state(sdev, level); - - if (flags & SOF_DBG_DUMP_REGS) - sof_ipc4_intel_dump_telemetry_state(sdev, flags); - else - hda_dsp_dump_ext_rom_status(sdev, level, flags); -} -EXPORT_SYMBOL_NS(hda_ipc4_dsp_dump, SND_SOC_SOF_INTEL_HDA_COMMON); - -static bool hda_check_ipc_irq(struct snd_sof_dev *sdev) -{ - const struct sof_intel_dsp_desc *chip; - - chip = get_chip_info(sdev->pdata); - if (chip && chip->check_ipc_irq) - return chip->check_ipc_irq(sdev); - - return false; -} - -void hda_ipc_irq_dump(struct snd_sof_dev *sdev) -{ - u32 adspis; - u32 intsts; - u32 intctl; - u32 ppsts; - u8 rirbsts; - - /* read key IRQ stats and config registers */ - adspis = snd_sof_dsp_read(sdev, HDA_DSP_BAR, HDA_DSP_REG_ADSPIS); - intsts = snd_sof_dsp_read(sdev, HDA_DSP_HDA_BAR, SOF_HDA_INTSTS); - intctl = snd_sof_dsp_read(sdev, HDA_DSP_HDA_BAR, SOF_HDA_INTCTL); - ppsts = snd_sof_dsp_read(sdev, HDA_DSP_PP_BAR, SOF_HDA_REG_PP_PPSTS); - rirbsts = snd_sof_dsp_read8(sdev, HDA_DSP_HDA_BAR, AZX_REG_RIRBSTS); - - dev_err(sdev->dev, "hda irq intsts 0x%8.8x intlctl 0x%8.8x rirb %2.2x\n", - intsts, intctl, rirbsts); - dev_err(sdev->dev, "dsp irq ppsts 0x%8.8x adspis 0x%8.8x\n", ppsts, adspis); -} -EXPORT_SYMBOL_NS(hda_ipc_irq_dump, SND_SOC_SOF_INTEL_HDA_COMMON); - -void hda_ipc_dump(struct snd_sof_dev *sdev) -{ - u32 hipcie; - u32 hipct; - u32 hipcctl; - - hda_ipc_irq_dump(sdev); - - /* read IPC status */ - hipcie = snd_sof_dsp_read(sdev, HDA_DSP_BAR, HDA_DSP_REG_HIPCIE); - hipct = snd_sof_dsp_read(sdev, HDA_DSP_BAR, HDA_DSP_REG_HIPCT); - hipcctl = snd_sof_dsp_read(sdev, HDA_DSP_BAR, HDA_DSP_REG_HIPCCTL); - - /* dump the IPC regs */ - /* TODO: parse the raw msg */ - dev_err(sdev->dev, "host status 0x%8.8x dsp status 0x%8.8x mask 0x%8.8x\n", - hipcie, hipct, hipcctl); -} -EXPORT_SYMBOL_NS(hda_ipc_dump, SND_SOC_SOF_INTEL_HDA_COMMON); - -void hda_ipc4_dump(struct snd_sof_dev *sdev) -{ - u32 hipci, hipcie, hipct, hipcte, hipcctl; - - hda_ipc_irq_dump(sdev); - - hipci = snd_sof_dsp_read(sdev, HDA_DSP_BAR, HDA_DSP_REG_HIPCI); - hipcie = snd_sof_dsp_read(sdev, HDA_DSP_BAR, HDA_DSP_REG_HIPCIE); - hipct = snd_sof_dsp_read(sdev, HDA_DSP_BAR, HDA_DSP_REG_HIPCT); - hipcte = snd_sof_dsp_read(sdev, HDA_DSP_BAR, HDA_DSP_REG_HIPCTE); - hipcctl = snd_sof_dsp_read(sdev, HDA_DSP_BAR, HDA_DSP_REG_HIPCCTL); - - /* dump the IPC regs */ - /* TODO: parse the raw msg */ - dev_err(sdev->dev, "Host IPC initiator: %#x|%#x, target: %#x|%#x, ctl: %#x\n", - hipci, hipcie, hipct, hipcte, hipcctl); -} -EXPORT_SYMBOL_NS(hda_ipc4_dump, SND_SOC_SOF_INTEL_HDA_COMMON); - -bool hda_ipc4_tx_is_busy(struct snd_sof_dev *sdev) -{ - struct sof_intel_hda_dev *hda = sdev->pdata->hw_pdata; - const struct sof_intel_dsp_desc *chip = hda->desc; - u32 val; - - val = snd_sof_dsp_read(sdev, HDA_DSP_BAR, chip->ipc_req); - - return !!(val & chip->ipc_req_mask); -} -EXPORT_SYMBOL_NS(hda_ipc4_tx_is_busy, SND_SOC_SOF_INTEL_HDA_COMMON); - static int hda_init(struct snd_sof_dev *sdev) { struct hda_bus *hbus; diff --git a/sound/soc/sof/intel/hda.h b/sound/soc/sof/intel/hda.h index 7804c5b50c26..809a1be0d388 100644 --- a/sound/soc/sof/intel/hda.h +++ b/sound/soc/sof/intel/hda.h @@ -617,6 +617,8 @@ void hda_ipc_dump(struct snd_sof_dev *sdev); void hda_ipc_irq_dump(struct snd_sof_dev *sdev); void hda_dsp_d0i3_work(struct work_struct *work); int hda_dsp_disable_interrupts(struct snd_sof_dev *sdev); +bool hda_check_ipc_irq(struct snd_sof_dev *sdev); +u32 hda_get_interface_mask(struct snd_sof_dev *sdev); /* * DSP PCM Operations. @@ -698,6 +700,8 @@ irqreturn_t hda_dsp_ipc_irq_thread(int irq, void *context); int hda_dsp_ipc_cmd_done(struct snd_sof_dev *sdev, int dir); void hda_dsp_get_state(struct snd_sof_dev *sdev, const char *level); +void hda_dsp_dump_ext_rom_status(struct snd_sof_dev *sdev, const char *level, + u32 flags); /* * DSP Code loader. @@ -806,6 +810,7 @@ int hda_dsp_trace_trigger(struct snd_sof_dev *sdev, int cmd); int hda_sdw_check_lcount_common(struct snd_sof_dev *sdev); int hda_sdw_check_lcount_ext(struct snd_sof_dev *sdev); +int hda_sdw_check_lcount(struct snd_sof_dev *sdev); int hda_sdw_startup(struct snd_sof_dev *sdev); void hda_common_enable_sdw_irq(struct snd_sof_dev *sdev, bool enable); void hda_sdw_int_enable(struct snd_sof_dev *sdev, bool enable); @@ -825,6 +830,11 @@ static inline int hda_sdw_check_lcount_ext(struct snd_sof_dev *sdev) return 0; } +static inline int hda_sdw_check_lcount(struct snd_sof_dev *sdev) +{ + return 0; +} + static inline int hda_sdw_startup(struct snd_sof_dev *sdev) { return 0; -- cgit v1.2.3 From 136b37369cc4f044139b886133f3b9a721ecacd1 Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Fri, 3 May 2024 08:52:19 -0500 Subject: ASoC: SOF: Intel: move tracepoint creation CREATE_TRACEPOINTS is supposed to be used once. To avoid modpost issues when creating modules, let's move the tracepoint creation in a single object file. Signed-off-by: Pierre-Louis Bossart Reviewed-by: Bard Liao Reviewed-by: Ranjani Sridharan Link: https://lore.kernel.org/r/20240503135221.229202-6-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/intel/Makefile | 2 +- sound/soc/sof/intel/hda.c | 1 - sound/soc/sof/intel/tracepoints.c | 3 +++ 3 files changed, 4 insertions(+), 2 deletions(-) create mode 100644 sound/soc/sof/intel/tracepoints.c diff --git a/sound/soc/sof/intel/Makefile b/sound/soc/sof/intel/Makefile index c895bae0efdd..cf74548f87ad 100644 --- a/sound/soc/sof/intel/Makefile +++ b/sound/soc/sof/intel/Makefile @@ -7,7 +7,7 @@ snd-sof-intel-hda-common-objs := hda.o hda-loader.o hda-stream.o hda-trace.o \ hda-dsp.o hda-ipc.o hda-ctrl.o hda-pcm.o \ hda-dai.o hda-dai-ops.o hda-bus.o \ hda-common-ops.o \ - telemetry.o + telemetry.o tracepoints.o snd-sof-intel-hda-mlink-objs := hda-mlink.o diff --git a/sound/soc/sof/intel/hda.c b/sound/soc/sof/intel/hda.c index a96926fb45b6..ea7dcda90f2a 100644 --- a/sound/soc/sof/intel/hda.c +++ b/sound/soc/sof/intel/hda.c @@ -35,7 +35,6 @@ #include "../ipc4-topology.h" #include "hda.h" -#define CREATE_TRACE_POINTS #include #if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA) diff --git a/sound/soc/sof/intel/tracepoints.c b/sound/soc/sof/intel/tracepoints.c new file mode 100644 index 000000000000..c223c96fe0e3 --- /dev/null +++ b/sound/soc/sof/intel/tracepoints.c @@ -0,0 +1,3 @@ +// SPDX-License-Identifier: GPL-2.0 +#define CREATE_TRACE_POINTS +#include -- cgit v1.2.3 From 3b7bd0c139849e95981961525b7f6dd20097a563 Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Fri, 3 May 2024 08:52:20 -0500 Subject: ASoC: SOF: Intel: remove circular dependency on hda_sdw_process_wakeen() hda_sdw_process_wakeen() is used in hda-loader.c, but defined in hda.c. This code split will create a circular dependency when hda.c is moved to a different module. Rather than an invasive code change, this patch follows the model used for sdw_check_wakeen_irq() with an abstraction. For now all abstractions point to the same common routine, which is arguably not great, but this also provides us with a future-proof way of addressing platform-specific wake processing. Signed-off-by: Pierre-Louis Bossart Reviewed-by: Bard Liao Reviewed-by: Ranjani Sridharan Link: https://lore.kernel.org/r/20240503135221.229202-7-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/intel/cnl.c | 2 ++ sound/soc/sof/intel/hda-dsp.c | 15 +++++++++++++++ sound/soc/sof/intel/hda.c | 3 ++- sound/soc/sof/intel/hda.h | 5 +++++ sound/soc/sof/intel/icl.c | 1 + sound/soc/sof/intel/lnl.c | 1 + sound/soc/sof/intel/mtl.c | 2 ++ sound/soc/sof/intel/shim.h | 1 + sound/soc/sof/intel/tgl.c | 4 ++++ 9 files changed, 33 insertions(+), 1 deletion(-) diff --git a/sound/soc/sof/intel/cnl.c b/sound/soc/sof/intel/cnl.c index 460bc404ddb6..1936865b2937 100644 --- a/sound/soc/sof/intel/cnl.c +++ b/sound/soc/sof/intel/cnl.c @@ -473,6 +473,7 @@ const struct sof_intel_dsp_desc cnl_chip_info = { .enable_sdw_irq = hda_common_enable_sdw_irq, .check_sdw_irq = hda_common_check_sdw_irq, .check_sdw_wakeen_irq = hda_sdw_check_wakeen_irq_common, + .sdw_process_wakeen = hda_sdw_process_wakeen_common, .check_ipc_irq = hda_dsp_check_ipc_irq, .cl_init = cl_dsp_init, .power_down_dsp = hda_power_down_dsp, @@ -508,6 +509,7 @@ const struct sof_intel_dsp_desc jsl_chip_info = { .enable_sdw_irq = hda_common_enable_sdw_irq, .check_sdw_irq = hda_common_check_sdw_irq, .check_sdw_wakeen_irq = hda_sdw_check_wakeen_irq_common, + .sdw_process_wakeen = hda_sdw_process_wakeen_common, .check_ipc_irq = hda_dsp_check_ipc_irq, .cl_init = cl_dsp_init, .power_down_dsp = hda_power_down_dsp, diff --git a/sound/soc/sof/intel/hda-dsp.c b/sound/soc/sof/intel/hda-dsp.c index 974ac1cd8c6e..780f4c33e678 100644 --- a/sound/soc/sof/intel/hda-dsp.c +++ b/sound/soc/sof/intel/hda-dsp.c @@ -1311,6 +1311,21 @@ int hda_sdw_check_lcount(struct snd_sof_dev *sdev) return 0; } + +void hda_sdw_process_wakeen(struct snd_sof_dev *sdev) +{ + u32 interface_mask = hda_get_interface_mask(sdev); + const struct sof_intel_dsp_desc *chip; + + if (!(interface_mask & BIT(SOF_DAI_INTEL_ALH))) + return; + + chip = get_chip_info(sdev->pdata); + if (chip && chip->sdw_process_wakeen) + chip->sdw_process_wakeen(sdev); +} +EXPORT_SYMBOL_NS(hda_sdw_process_wakeen, SND_SOC_SOF_INTEL_HDA_COMMON); + #endif int hda_dsp_disable_interrupts(struct snd_sof_dev *sdev) diff --git a/sound/soc/sof/intel/hda.c b/sound/soc/sof/intel/hda.c index ea7dcda90f2a..87b0375250a2 100644 --- a/sound/soc/sof/intel/hda.c +++ b/sound/soc/sof/intel/hda.c @@ -331,7 +331,7 @@ static bool hda_sdw_check_wakeen_irq(struct snd_sof_dev *sdev) return false; } -void hda_sdw_process_wakeen(struct snd_sof_dev *sdev) +void hda_sdw_process_wakeen_common(struct snd_sof_dev *sdev) { u32 interface_mask = hda_get_interface_mask(sdev); struct sof_intel_hda_dev *hdev; @@ -345,6 +345,7 @@ void hda_sdw_process_wakeen(struct snd_sof_dev *sdev) sdw_intel_process_wakeen_event(hdev->sdw); } +EXPORT_SYMBOL_NS(hda_sdw_process_wakeen_common, SND_SOC_SOF_INTEL_HDA_COMMON); #else /* IS_ENABLED(CONFIG_SND_SOC_SOF_INTEL_SOUNDWIRE) */ static inline int hda_sdw_acpi_scan(struct snd_sof_dev *sdev) diff --git a/sound/soc/sof/intel/hda.h b/sound/soc/sof/intel/hda.h index 809a1be0d388..ef78c9b5c250 100644 --- a/sound/soc/sof/intel/hda.h +++ b/sound/soc/sof/intel/hda.h @@ -815,6 +815,7 @@ int hda_sdw_startup(struct snd_sof_dev *sdev); void hda_common_enable_sdw_irq(struct snd_sof_dev *sdev, bool enable); void hda_sdw_int_enable(struct snd_sof_dev *sdev, bool enable); bool hda_sdw_check_wakeen_irq_common(struct snd_sof_dev *sdev); +void hda_sdw_process_wakeen_common(struct snd_sof_dev *sdev); void hda_sdw_process_wakeen(struct snd_sof_dev *sdev); bool hda_common_check_sdw_irq(struct snd_sof_dev *sdev); @@ -853,6 +854,10 @@ static inline bool hda_sdw_check_wakeen_irq_common(struct snd_sof_dev *sdev) return false; } +static inline void hda_sdw_process_wakeen_common(struct snd_sof_dev *sdev) +{ +} + static inline void hda_sdw_process_wakeen(struct snd_sof_dev *sdev) { } diff --git a/sound/soc/sof/intel/icl.c b/sound/soc/sof/intel/icl.c index 115866225e05..9b916eb4fc21 100644 --- a/sound/soc/sof/intel/icl.c +++ b/sound/soc/sof/intel/icl.c @@ -187,6 +187,7 @@ const struct sof_intel_dsp_desc icl_chip_info = { .enable_sdw_irq = hda_common_enable_sdw_irq, .check_sdw_irq = hda_common_check_sdw_irq, .check_sdw_wakeen_irq = hda_sdw_check_wakeen_irq_common, + .sdw_process_wakeen = hda_sdw_process_wakeen_common, .check_ipc_irq = hda_dsp_check_ipc_irq, .cl_init = cl_dsp_init, .power_down_dsp = hda_power_down_dsp, diff --git a/sound/soc/sof/intel/lnl.c b/sound/soc/sof/intel/lnl.c index ca0cb91d2b2c..a7446be36627 100644 --- a/sound/soc/sof/intel/lnl.c +++ b/sound/soc/sof/intel/lnl.c @@ -238,6 +238,7 @@ const struct sof_intel_dsp_desc lnl_chip_info = { .enable_sdw_irq = lnl_enable_sdw_irq, .check_sdw_irq = lnl_dsp_check_sdw_irq, .check_sdw_wakeen_irq = lnl_sdw_check_wakeen_irq, + .sdw_process_wakeen = hda_sdw_process_wakeen_common, .check_ipc_irq = mtl_dsp_check_ipc_irq, .cl_init = mtl_dsp_cl_init, .power_down_dsp = mtl_power_down_dsp, diff --git a/sound/soc/sof/intel/mtl.c b/sound/soc/sof/intel/mtl.c index 13f780f33c22..b9fc123be75d 100644 --- a/sound/soc/sof/intel/mtl.c +++ b/sound/soc/sof/intel/mtl.c @@ -779,6 +779,7 @@ const struct sof_intel_dsp_desc mtl_chip_info = { .enable_sdw_irq = mtl_enable_sdw_irq, .check_sdw_irq = mtl_dsp_check_sdw_irq, .check_sdw_wakeen_irq = hda_sdw_check_wakeen_irq_common, + .sdw_process_wakeen = hda_sdw_process_wakeen_common, .check_ipc_irq = mtl_dsp_check_ipc_irq, .cl_init = mtl_dsp_cl_init, .power_down_dsp = mtl_power_down_dsp, @@ -806,6 +807,7 @@ const struct sof_intel_dsp_desc arl_s_chip_info = { .enable_sdw_irq = mtl_enable_sdw_irq, .check_sdw_irq = mtl_dsp_check_sdw_irq, .check_sdw_wakeen_irq = hda_sdw_check_wakeen_irq_common, + .sdw_process_wakeen = hda_sdw_process_wakeen_common, .check_ipc_irq = mtl_dsp_check_ipc_irq, .cl_init = mtl_dsp_cl_init, .power_down_dsp = mtl_power_down_dsp, diff --git a/sound/soc/sof/intel/shim.h b/sound/soc/sof/intel/shim.h index 18ce3d33fa80..448ec54a6aa9 100644 --- a/sound/soc/sof/intel/shim.h +++ b/sound/soc/sof/intel/shim.h @@ -190,6 +190,7 @@ struct sof_intel_dsp_desc { void (*enable_sdw_irq)(struct snd_sof_dev *sdev, bool enable); bool (*check_sdw_irq)(struct snd_sof_dev *sdev); bool (*check_sdw_wakeen_irq)(struct snd_sof_dev *sdev); + void (*sdw_process_wakeen)(struct snd_sof_dev *sdev); bool (*check_ipc_irq)(struct snd_sof_dev *sdev); int (*power_down_dsp)(struct snd_sof_dev *sdev); int (*disable_interrupts)(struct snd_sof_dev *sdev); diff --git a/sound/soc/sof/intel/tgl.c b/sound/soc/sof/intel/tgl.c index 6acc65923834..062327d4f068 100644 --- a/sound/soc/sof/intel/tgl.c +++ b/sound/soc/sof/intel/tgl.c @@ -156,6 +156,7 @@ const struct sof_intel_dsp_desc tgl_chip_info = { .enable_sdw_irq = hda_common_enable_sdw_irq, .check_sdw_irq = hda_common_check_sdw_irq, .check_sdw_wakeen_irq = hda_sdw_check_wakeen_irq_common, + .sdw_process_wakeen = hda_sdw_process_wakeen_common, .check_ipc_irq = hda_dsp_check_ipc_irq, .cl_init = cl_dsp_init, .power_down_dsp = hda_power_down_dsp, @@ -184,6 +185,7 @@ const struct sof_intel_dsp_desc tglh_chip_info = { .enable_sdw_irq = hda_common_enable_sdw_irq, .check_sdw_irq = hda_common_check_sdw_irq, .check_sdw_wakeen_irq = hda_sdw_check_wakeen_irq_common, + .sdw_process_wakeen = hda_sdw_process_wakeen_common, .check_ipc_irq = hda_dsp_check_ipc_irq, .cl_init = cl_dsp_init, .power_down_dsp = hda_power_down_dsp, @@ -212,6 +214,7 @@ const struct sof_intel_dsp_desc ehl_chip_info = { .enable_sdw_irq = hda_common_enable_sdw_irq, .check_sdw_irq = hda_common_check_sdw_irq, .check_sdw_wakeen_irq = hda_sdw_check_wakeen_irq_common, + .sdw_process_wakeen = hda_sdw_process_wakeen_common, .check_ipc_irq = hda_dsp_check_ipc_irq, .cl_init = cl_dsp_init, .power_down_dsp = hda_power_down_dsp, @@ -240,6 +243,7 @@ const struct sof_intel_dsp_desc adls_chip_info = { .enable_sdw_irq = hda_common_enable_sdw_irq, .check_sdw_irq = hda_common_check_sdw_irq, .check_sdw_wakeen_irq = hda_sdw_check_wakeen_irq_common, + .sdw_process_wakeen = hda_sdw_process_wakeen_common, .check_ipc_irq = hda_dsp_check_ipc_irq, .cl_init = cl_dsp_init, .power_down_dsp = hda_power_down_dsp, -- cgit v1.2.3 From 6fe61f31eab1ec84c385786cd052415d966e5235 Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Fri, 3 May 2024 08:52:21 -0500 Subject: ASoC: SOF: Intel: move hda.c to different module Now that most of the code moves are done, we can add a new module and the required EXPORT_SYMBOL definitions. No functionality change, just a new module added. Signed-off-by: Pierre-Louis Bossart Reviewed-by: Bard Liao Reviewed-by: Ranjani Sridharan Link: https://lore.kernel.org/r/20240503135221.229202-8-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/intel/Kconfig | 22 +++++++++++++--------- sound/soc/sof/intel/Makefile | 6 ++++-- sound/soc/sof/intel/hda-bus.c | 2 ++ sound/soc/sof/intel/hda-common-ops.c | 2 +- sound/soc/sof/intel/hda-ctrl.c | 9 +++++++++ sound/soc/sof/intel/hda-dai.c | 5 +++++ sound/soc/sof/intel/hda-dsp.c | 9 +++++++++ sound/soc/sof/intel/hda-ipc.c | 5 +++++ sound/soc/sof/intel/hda-loader.c | 1 + sound/soc/sof/intel/hda-pcm.c | 6 ++++++ sound/soc/sof/intel/hda-probes.c | 2 ++ sound/soc/sof/intel/hda-stream.c | 8 ++++++++ sound/soc/sof/intel/hda-trace.c | 3 +++ sound/soc/sof/intel/hda.c | 21 +++++++++++---------- sound/soc/sof/intel/pci-apl.c | 1 + sound/soc/sof/intel/pci-cnl.c | 1 + sound/soc/sof/intel/pci-icl.c | 1 + sound/soc/sof/intel/pci-lnl.c | 1 + sound/soc/sof/intel/pci-mtl.c | 1 + sound/soc/sof/intel/pci-skl.c | 1 + sound/soc/sof/intel/pci-tgl.c | 1 + sound/soc/sof/intel/tracepoints.c | 2 ++ 22 files changed, 88 insertions(+), 22 deletions(-) diff --git a/sound/soc/sof/intel/Kconfig b/sound/soc/sof/intel/Kconfig index b804be7321be..3396bd46b778 100644 --- a/sound/soc/sof/intel/Kconfig +++ b/sound/soc/sof/intel/Kconfig @@ -97,7 +97,7 @@ config SND_SOC_SOF_MERRIFIELD config SND_SOC_SOF_INTEL_SKL tristate - select SND_SOC_SOF_HDA_COMMON + select SND_SOC_SOF_HDA_GENERIC select SND_SOC_SOF_IPC4 config SND_SOC_SOF_SKYLAKE @@ -122,7 +122,7 @@ config SND_SOC_SOF_KABYLAKE config SND_SOC_SOF_INTEL_APL tristate - select SND_SOC_SOF_HDA_COMMON + select SND_SOC_SOF_HDA_GENERIC select SND_SOC_SOF_IPC3 select SND_SOC_SOF_IPC4 @@ -148,7 +148,7 @@ config SND_SOC_SOF_GEMINILAKE config SND_SOC_SOF_INTEL_CNL tristate - select SND_SOC_SOF_HDA_COMMON + select SND_SOC_SOF_HDA_GENERIC select SND_SOC_SOF_INTEL_SOUNDWIRE_LINK_BASELINE select SND_SOC_SOF_IPC3 select SND_SOC_SOF_IPC4 @@ -184,7 +184,7 @@ config SND_SOC_SOF_COMETLAKE config SND_SOC_SOF_INTEL_ICL tristate - select SND_SOC_SOF_HDA_COMMON + select SND_SOC_SOF_HDA_GENERIC select SND_SOC_SOF_INTEL_SOUNDWIRE_LINK_BASELINE select SND_SOC_SOF_IPC3 select SND_SOC_SOF_IPC4 @@ -212,7 +212,7 @@ config SND_SOC_SOF_JASPERLAKE config SND_SOC_SOF_INTEL_TGL tristate - select SND_SOC_SOF_HDA_COMMON + select SND_SOC_SOF_HDA_GENERIC select SND_SOC_SOF_INTEL_SOUNDWIRE_LINK_BASELINE select SND_SOC_SOF_IPC3 select SND_SOC_SOF_IPC4 @@ -250,7 +250,7 @@ config SND_SOC_SOF_ALDERLAKE config SND_SOC_SOF_INTEL_MTL tristate - select SND_SOC_SOF_HDA_COMMON + select SND_SOC_SOF_HDA_GENERIC select SND_SOC_SOF_INTEL_SOUNDWIRE_LINK_BASELINE select SND_SOC_SOF_IPC4 @@ -266,7 +266,7 @@ config SND_SOC_SOF_METEORLAKE config SND_SOC_SOF_INTEL_LNL tristate - select SND_SOC_SOF_HDA_COMMON + select SND_SOC_SOF_HDA_GENERIC select SND_SOC_SOF_INTEL_SOUNDWIRE_LINK_BASELINE select SND_SOC_SOF_IPC4 select SND_SOC_SOF_INTEL_MTL @@ -283,6 +283,10 @@ config SND_SOC_SOF_LUNARLAKE config SND_SOC_SOF_HDA_COMMON tristate + +config SND_SOC_SOF_HDA_GENERIC + tristate + select SND_SOC_SOF_HDA_COMMON select SND_SOC_SOF_INTEL_COMMON select SND_SOC_SOF_PCI_DEV select SND_INTEL_DSP_CONFIG @@ -299,7 +303,7 @@ config SND_SOC_SOF_HDA_MLINK This option is not user-selectable but automagically handled by 'select' statements at a higher level. -if SND_SOC_SOF_HDA_COMMON +if SND_SOC_SOF_HDA_GENERIC config SND_SOC_SOF_HDA_LINK bool "SOF support for HDA Links(HDA/HDMI)" @@ -319,7 +323,7 @@ config SND_SOC_SOF_HDA_AUDIO_CODEC Say Y if you want to enable HDAudio codecs with SOF. If unsure select "N". -endif ## SND_SOC_SOF_HDA_COMMON +endif ## SND_SOC_SOF_HDA_GENERIC config SND_SOC_SOF_HDA_LINK_BASELINE tristate diff --git a/sound/soc/sof/intel/Makefile b/sound/soc/sof/intel/Makefile index cf74548f87ad..806df08e3fd5 100644 --- a/sound/soc/sof/intel/Makefile +++ b/sound/soc/sof/intel/Makefile @@ -3,12 +3,13 @@ snd-sof-acpi-intel-byt-objs := byt.o snd-sof-acpi-intel-bdw-objs := bdw.o -snd-sof-intel-hda-common-objs := hda.o hda-loader.o hda-stream.o hda-trace.o \ +snd-sof-intel-hda-common-objs := hda-loader.o hda-stream.o hda-trace.o \ hda-dsp.o hda-ipc.o hda-ctrl.o hda-pcm.o \ hda-dai.o hda-dai-ops.o hda-bus.o \ - hda-common-ops.o \ telemetry.o tracepoints.o +snd-sof-intel-hda-generic-objs := hda.o hda-common-ops.o + snd-sof-intel-hda-mlink-objs := hda-mlink.o snd-sof-intel-hda-common-$(CONFIG_SND_SOC_SOF_HDA_PROBES) += hda-probes.o @@ -21,6 +22,7 @@ obj-$(CONFIG_SND_SOC_SOF_INTEL_ATOM_HIFI_EP) += snd-sof-intel-atom.o obj-$(CONFIG_SND_SOC_SOF_BAYTRAIL) += snd-sof-acpi-intel-byt.o obj-$(CONFIG_SND_SOC_SOF_BROADWELL) += snd-sof-acpi-intel-bdw.o obj-$(CONFIG_SND_SOC_SOF_HDA_COMMON) += snd-sof-intel-hda-common.o +obj-$(CONFIG_SND_SOC_SOF_HDA_GENERIC) += snd-sof-intel-hda-generic.o obj-$(CONFIG_SND_SOC_SOF_HDA_MLINK) += snd-sof-intel-hda-mlink.o obj-$(CONFIG_SND_SOC_SOF_HDA) += snd-sof-intel-hda.o diff --git a/sound/soc/sof/intel/hda-bus.c b/sound/soc/sof/intel/hda-bus.c index fc63085d2d74..e9f65386e480 100644 --- a/sound/soc/sof/intel/hda-bus.c +++ b/sound/soc/sof/intel/hda-bus.c @@ -94,6 +94,7 @@ void sof_hda_bus_init(struct snd_sof_dev *sdev, struct device *dev) spin_lock_init(&bus->reg_lock); #endif /* CONFIG_SND_SOC_SOF_HDA_LINK */ } +EXPORT_SYMBOL_NS(sof_hda_bus_init, SND_SOC_SOF_INTEL_HDA_COMMON); void sof_hda_bus_exit(struct snd_sof_dev *sdev) { @@ -103,3 +104,4 @@ void sof_hda_bus_exit(struct snd_sof_dev *sdev) snd_hdac_ext_bus_exit(bus); #endif } +EXPORT_SYMBOL_NS(sof_hda_bus_exit, SND_SOC_SOF_INTEL_HDA_COMMON); diff --git a/sound/soc/sof/intel/hda-common-ops.c b/sound/soc/sof/intel/hda-common-ops.c index 6a863ceba8da..e4c5031d227e 100644 --- a/sound/soc/sof/intel/hda-common-ops.c +++ b/sound/soc/sof/intel/hda-common-ops.c @@ -105,4 +105,4 @@ const struct snd_sof_dsp_ops sof_hda_common_ops = { .dsp_arch_ops = &sof_xtensa_arch_ops, }; -EXPORT_SYMBOL_NS(sof_hda_common_ops, SND_SOC_SOF_INTEL_HDA_COMMON); +EXPORT_SYMBOL_NS(sof_hda_common_ops, SND_SOC_SOF_INTEL_HDA_GENERIC); diff --git a/sound/soc/sof/intel/hda-ctrl.c b/sound/soc/sof/intel/hda-ctrl.c index 56c0f493042c..810a2ba4fbe4 100644 --- a/sound/soc/sof/intel/hda-ctrl.c +++ b/sound/soc/sof/intel/hda-ctrl.c @@ -128,6 +128,7 @@ int hda_dsp_ctrl_get_caps(struct snd_sof_dev *sdev) return 0; } +EXPORT_SYMBOL_NS(hda_dsp_ctrl_get_caps, SND_SOC_SOF_INTEL_HDA_COMMON); void hda_dsp_ctrl_ppcap_enable(struct snd_sof_dev *sdev, bool enable) { @@ -136,6 +137,7 @@ void hda_dsp_ctrl_ppcap_enable(struct snd_sof_dev *sdev, bool enable) snd_sof_dsp_update_bits(sdev, HDA_DSP_PP_BAR, SOF_HDA_REG_PP_PPCTL, SOF_HDA_PPCTL_GPROCEN, val); } +EXPORT_SYMBOL_NS(hda_dsp_ctrl_ppcap_enable, SND_SOC_SOF_INTEL_HDA_COMMON); void hda_dsp_ctrl_ppcap_int_enable(struct snd_sof_dev *sdev, bool enable) { @@ -144,6 +146,7 @@ void hda_dsp_ctrl_ppcap_int_enable(struct snd_sof_dev *sdev, bool enable) snd_sof_dsp_update_bits(sdev, HDA_DSP_PP_BAR, SOF_HDA_REG_PP_PPCTL, SOF_HDA_PPCTL_PIE, val); } +EXPORT_SYMBOL_NS(hda_dsp_ctrl_ppcap_int_enable, SND_SOC_SOF_INTEL_HDA_COMMON); void hda_dsp_ctrl_misc_clock_gating(struct snd_sof_dev *sdev, bool enable) { @@ -263,6 +266,7 @@ err: return ret; } +EXPORT_SYMBOL_NS(hda_dsp_ctrl_init_chip, SND_SOC_SOF_INTEL_HDA_COMMON); void hda_dsp_ctrl_stop_chip(struct snd_sof_dev *sdev) { @@ -322,3 +326,8 @@ void hda_dsp_ctrl_stop_chip(struct snd_sof_dev *sdev) bus->chip_init = false; } + +MODULE_LICENSE("Dual BSD/GPL"); +MODULE_IMPORT_NS(SND_SOC_SOF_HDA_MLINK); +MODULE_IMPORT_NS(SND_SOC_SOF_HDA_AUDIO_CODEC); +MODULE_IMPORT_NS(SND_SOC_SOF_HDA_AUDIO_CODEC_I915); diff --git a/sound/soc/sof/intel/hda-dai.c b/sound/soc/sof/intel/hda-dai.c index 650e3a37326e..f494d8701345 100644 --- a/sound/soc/sof/intel/hda-dai.c +++ b/sound/soc/sof/intel/hda-dai.c @@ -54,6 +54,7 @@ int hda_dai_config(struct snd_soc_dapm_widget *w, unsigned int flags, return 0; } +EXPORT_SYMBOL_NS(hda_dai_config, SND_SOC_SOF_INTEL_HDA_COMMON); #if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA_LINK) @@ -542,6 +543,7 @@ int sdw_hda_dai_hw_params(struct snd_pcm_substream *substream, } return 0; } +EXPORT_SYMBOL_NS(sdw_hda_dai_hw_params, SND_SOC_SOF_INTEL_HDA_COMMON); int sdw_hda_dai_hw_free(struct snd_pcm_substream *substream, struct snd_soc_dai *cpu_dai, @@ -570,12 +572,14 @@ int sdw_hda_dai_hw_free(struct snd_pcm_substream *substream, return 0; } +EXPORT_SYMBOL_NS(sdw_hda_dai_hw_free, SND_SOC_SOF_INTEL_HDA_COMMON); int sdw_hda_dai_trigger(struct snd_pcm_substream *substream, int cmd, struct snd_soc_dai *cpu_dai) { return hda_dai_trigger(substream, cmd, cpu_dai); } +EXPORT_SYMBOL_NS(sdw_hda_dai_trigger, SND_SOC_SOF_INTEL_HDA_COMMON); static int hda_dai_suspend(struct hdac_bus *bus) { @@ -856,6 +860,7 @@ struct snd_soc_dai_driver skl_dai[] = { }, #endif }; +EXPORT_SYMBOL_NS(skl_dai, SND_SOC_SOF_INTEL_HDA_COMMON); int hda_dsp_dais_suspend(struct snd_sof_dev *sdev) { diff --git a/sound/soc/sof/intel/hda-dsp.c b/sound/soc/sof/intel/hda-dsp.c index 780f4c33e678..4a27e1dfca39 100644 --- a/sound/soc/sof/intel/hda-dsp.c +++ b/sound/soc/sof/intel/hda-dsp.c @@ -89,6 +89,7 @@ u32 hda_get_interface_mask(struct snd_sof_dev *sdev) return interface_mask[sdev->dspless_mode_selected]; } +EXPORT_SYMBOL_NS(hda_get_interface_mask, SND_SOC_SOF_INTEL_HDA_COMMON); bool hda_is_chain_dma_supported(struct snd_sof_dev *sdev, u32 dai_type) { @@ -118,6 +119,7 @@ bool hda_is_chain_dma_supported(struct snd_sof_dev *sdev, u32 dai_type) return false; } } +EXPORT_SYMBOL_NS(hda_is_chain_dma_supported, SND_SOC_SOF_INTEL_HDA_COMMON); /* * DSP Core control. @@ -980,6 +982,7 @@ int hda_dsp_runtime_idle(struct snd_sof_dev *sdev) return 0; } +EXPORT_SYMBOL_NS(hda_dsp_runtime_idle, SND_SOC_SOF_INTEL_HDA_COMMON); int hda_dsp_runtime_suspend(struct snd_sof_dev *sdev) { @@ -1001,6 +1004,7 @@ int hda_dsp_runtime_suspend(struct snd_sof_dev *sdev) return snd_sof_dsp_set_power_state(sdev, &target_state); } +EXPORT_SYMBOL_NS(hda_dsp_runtime_suspend, SND_SOC_SOF_INTEL_HDA_COMMON); int hda_dsp_suspend(struct snd_sof_dev *sdev, u32 target_state) { @@ -1061,6 +1065,7 @@ int hda_dsp_suspend(struct snd_sof_dev *sdev, u32 target_state) return snd_sof_dsp_set_power_state(sdev, &target_dsp_state); } +EXPORT_SYMBOL_NS(hda_dsp_suspend, SND_SOC_SOF_INTEL_HDA_COMMON); static unsigned int hda_dsp_check_for_dma_streams(struct snd_sof_dev *sdev) { @@ -1153,6 +1158,7 @@ int hda_dsp_set_hw_params_upon_resume(struct snd_sof_dev *sdev) return ret; } +EXPORT_SYMBOL_NS(hda_dsp_set_hw_params_upon_resume, SND_SOC_SOF_INTEL_HDA_COMMON); void hda_dsp_d0i3_work(struct work_struct *work) { @@ -1179,6 +1185,7 @@ void hda_dsp_d0i3_work(struct work_struct *work) "error: failed to set DSP state %d substate %d\n", target_state.state, target_state.substate); } +EXPORT_SYMBOL_NS(hda_dsp_d0i3_work, SND_SOC_SOF_INTEL_HDA_COMMON); int hda_dsp_core_get(struct snd_sof_dev *sdev, int core) { @@ -1311,6 +1318,7 @@ int hda_sdw_check_lcount(struct snd_sof_dev *sdev) return 0; } +EXPORT_SYMBOL_NS(hda_sdw_check_lcount, SND_SOC_SOF_INTEL_HDA_COMMON); void hda_sdw_process_wakeen(struct snd_sof_dev *sdev) { @@ -1619,3 +1627,4 @@ void hda_dsp_dump(struct snd_sof_dev *sdev, u32 flags) hda_dsp_dump_ext_rom_status(sdev, level, flags); } } +EXPORT_SYMBOL_NS(hda_dsp_dump, SND_SOC_SOF_INTEL_HDA_COMMON); diff --git a/sound/soc/sof/intel/hda-ipc.c b/sound/soc/sof/intel/hda-ipc.c index 2252c9198cc0..6b7f2337567c 100644 --- a/sound/soc/sof/intel/hda-ipc.c +++ b/sound/soc/sof/intel/hda-ipc.c @@ -398,11 +398,13 @@ int hda_dsp_ipc_get_mailbox_offset(struct snd_sof_dev *sdev) { return HDA_DSP_MBOX_UPLINK_OFFSET; } +EXPORT_SYMBOL_NS(hda_dsp_ipc_get_mailbox_offset, SND_SOC_SOF_INTEL_HDA_COMMON); int hda_dsp_ipc_get_window_offset(struct snd_sof_dev *sdev, u32 id) { return SRAM_WINDOW_OFFSET(id); } +EXPORT_SYMBOL_NS(hda_dsp_ipc_get_window_offset, SND_SOC_SOF_INTEL_HDA_COMMON); int hda_ipc_msg_data(struct snd_sof_dev *sdev, struct snd_sof_pcm_stream *sps, @@ -428,6 +430,7 @@ int hda_ipc_msg_data(struct snd_sof_dev *sdev, return 0; } +EXPORT_SYMBOL_NS(hda_ipc_msg_data, SND_SOC_SOF_INTEL_HDA_COMMON); int hda_set_stream_data_offset(struct snd_sof_dev *sdev, struct snd_sof_pcm_stream *sps, @@ -452,6 +455,7 @@ int hda_set_stream_data_offset(struct snd_sof_dev *sdev, return 0; } +EXPORT_SYMBOL_NS(hda_set_stream_data_offset, SND_SOC_SOF_INTEL_HDA_COMMON); void hda_ipc4_dsp_dump(struct snd_sof_dev *sdev, u32 flags) { @@ -477,6 +481,7 @@ bool hda_check_ipc_irq(struct snd_sof_dev *sdev) return false; } +EXPORT_SYMBOL_NS(hda_check_ipc_irq, SND_SOC_SOF_INTEL_HDA_COMMON); void hda_ipc_irq_dump(struct snd_sof_dev *sdev) { diff --git a/sound/soc/sof/intel/hda-loader.c b/sound/soc/sof/intel/hda-loader.c index 34c18275c949..df668806a8c4 100644 --- a/sound/soc/sof/intel/hda-loader.c +++ b/sound/soc/sof/intel/hda-loader.c @@ -691,3 +691,4 @@ int hda_dsp_ext_man_get_cavs_config_data(struct snd_sof_dev *sdev, return 0; } +EXPORT_SYMBOL_NS(hda_dsp_ext_man_get_cavs_config_data, SND_SOC_SOF_INTEL_HDA_COMMON); diff --git a/sound/soc/sof/intel/hda-pcm.c b/sound/soc/sof/intel/hda-pcm.c index d7b446f3f973..27dc134f04a8 100644 --- a/sound/soc/sof/intel/hda-pcm.c +++ b/sound/soc/sof/intel/hda-pcm.c @@ -142,6 +142,7 @@ int hda_dsp_pcm_hw_params(struct snd_sof_dev *sdev, return 0; } +EXPORT_SYMBOL_NS(hda_dsp_pcm_hw_params, SND_SOC_SOF_INTEL_HDA_COMMON); /* update SPIB register with appl position */ int hda_dsp_pcm_ack(struct snd_sof_dev *sdev, struct snd_pcm_substream *substream) @@ -164,6 +165,7 @@ int hda_dsp_pcm_ack(struct snd_sof_dev *sdev, struct snd_pcm_substream *substrea return 0; } +EXPORT_SYMBOL_NS(hda_dsp_pcm_ack, SND_SOC_SOF_INTEL_HDA_COMMON); int hda_dsp_pcm_trigger(struct snd_sof_dev *sdev, struct snd_pcm_substream *substream, int cmd) @@ -173,6 +175,7 @@ int hda_dsp_pcm_trigger(struct snd_sof_dev *sdev, return hda_dsp_stream_trigger(sdev, hext_stream, cmd); } +EXPORT_SYMBOL_NS(hda_dsp_pcm_trigger, SND_SOC_SOF_INTEL_HDA_COMMON); snd_pcm_uframes_t hda_dsp_pcm_pointer(struct snd_sof_dev *sdev, struct snd_pcm_substream *substream) @@ -204,6 +207,7 @@ found: trace_sof_intel_hda_dsp_pcm(sdev, hstream, substream, pos); return pos; } +EXPORT_SYMBOL_NS(hda_dsp_pcm_pointer, SND_SOC_SOF_INTEL_HDA_COMMON); int hda_dsp_pcm_open(struct snd_sof_dev *sdev, struct snd_pcm_substream *substream) @@ -292,6 +296,7 @@ int hda_dsp_pcm_open(struct snd_sof_dev *sdev, return 0; } +EXPORT_SYMBOL_NS(hda_dsp_pcm_open, SND_SOC_SOF_INTEL_HDA_COMMON); int hda_dsp_pcm_close(struct snd_sof_dev *sdev, struct snd_pcm_substream *substream) @@ -311,3 +316,4 @@ int hda_dsp_pcm_close(struct snd_sof_dev *sdev, substream->runtime->private_data = NULL; return 0; } +EXPORT_SYMBOL_NS(hda_dsp_pcm_close, SND_SOC_SOF_INTEL_HDA_COMMON); diff --git a/sound/soc/sof/intel/hda-probes.c b/sound/soc/sof/intel/hda-probes.c index 56a533c63cb0..be0fd56ddb27 100644 --- a/sound/soc/sof/intel/hda-probes.c +++ b/sound/soc/sof/intel/hda-probes.c @@ -139,10 +139,12 @@ int hda_probes_register(struct snd_sof_dev *sdev) return sof_client_dev_register(sdev, "hda-probes", 0, &hda_probes_ops, sizeof(hda_probes_ops)); } +EXPORT_SYMBOL_NS(hda_probes_register, SND_SOC_SOF_INTEL_HDA_COMMON); void hda_probes_unregister(struct snd_sof_dev *sdev) { sof_client_dev_unregister(sdev, "hda-probes", 0); } +EXPORT_SYMBOL_NS(hda_probes_unregister, SND_SOC_SOF_INTEL_HDA_COMMON); MODULE_IMPORT_NS(SND_SOC_SOF_CLIENT); diff --git a/sound/soc/sof/intel/hda-stream.c b/sound/soc/sof/intel/hda-stream.c index 4fef1964b5cd..7a38bea663fe 100644 --- a/sound/soc/sof/intel/hda-stream.c +++ b/sound/soc/sof/intel/hda-stream.c @@ -27,6 +27,7 @@ int sof_hda_position_quirk = SOF_HDA_POSITION_QUIRK_USE_DPIB_REGISTERS; module_param_named(position_quirk, sof_hda_position_quirk, int, 0444); MODULE_PARM_DESC(position_quirk, "SOF HDaudio position quirk"); +EXPORT_SYMBOL_NS(sof_hda_position_quirk, SND_SOC_SOF_INTEL_HDA_COMMON); #define HDA_LTRP_GB_VALUE_US 95 @@ -713,6 +714,7 @@ int hda_dsp_stream_hw_free(struct snd_sof_dev *sdev, return 0; } +EXPORT_SYMBOL_NS(hda_dsp_stream_hw_free, SND_SOC_SOF_INTEL_HDA_COMMON); bool hda_dsp_check_stream_irq(struct snd_sof_dev *sdev) { @@ -735,6 +737,7 @@ bool hda_dsp_check_stream_irq(struct snd_sof_dev *sdev) return ret; } +EXPORT_SYMBOL_NS(hda_dsp_check_stream_irq, SND_SOC_SOF_INTEL_HDA_COMMON); static void hda_dsp_compr_bytes_transferred(struct hdac_stream *hstream, int direction) @@ -831,6 +834,7 @@ irqreturn_t hda_dsp_stream_threaded_handler(int irq, void *context) return IRQ_HANDLED; } +EXPORT_SYMBOL_NS(hda_dsp_stream_threaded_handler, SND_SOC_SOF_INTEL_HDA_COMMON); int hda_dsp_stream_init(struct snd_sof_dev *sdev) { @@ -968,6 +972,7 @@ int hda_dsp_stream_init(struct snd_sof_dev *sdev) return 0; } +EXPORT_SYMBOL_NS(hda_dsp_stream_init, SND_SOC_SOF_INTEL_HDA_COMMON); void hda_dsp_stream_free(struct snd_sof_dev *sdev) { @@ -997,6 +1002,7 @@ void hda_dsp_stream_free(struct snd_sof_dev *sdev) devm_kfree(sdev->dev, hda_stream); } } +EXPORT_SYMBOL_NS(hda_dsp_stream_free, SND_SOC_SOF_INTEL_HDA_COMMON); snd_pcm_uframes_t hda_dsp_stream_get_position(struct hdac_stream *hstream, int direction, bool can_sleep) @@ -1123,6 +1129,7 @@ u64 hda_dsp_get_stream_llp(struct snd_sof_dev *sdev, return merge_u64(llp_u, llp_l); } +EXPORT_SYMBOL_NS(hda_dsp_get_stream_llp, SND_SOC_SOF_INTEL_HDA_COMMON); /** * hda_dsp_get_stream_ldp - Retrieve the LDP (Linear DMA Position) of the stream @@ -1154,3 +1161,4 @@ u64 hda_dsp_get_stream_ldp(struct snd_sof_dev *sdev, return ((u64)ldp_u << 32) | ldp_l; } +EXPORT_SYMBOL_NS(hda_dsp_get_stream_ldp, SND_SOC_SOF_INTEL_HDA_COMMON); diff --git a/sound/soc/sof/intel/hda-trace.c b/sound/soc/sof/intel/hda-trace.c index cbb9bd7770e6..f0d959ba50c4 100644 --- a/sound/soc/sof/intel/hda-trace.c +++ b/sound/soc/sof/intel/hda-trace.c @@ -68,6 +68,7 @@ int hda_dsp_trace_init(struct snd_sof_dev *sdev, struct snd_dma_buffer *dmab, return ret; } +EXPORT_SYMBOL_NS(hda_dsp_trace_init, SND_SOC_SOF_INTEL_HDA_COMMON); int hda_dsp_trace_release(struct snd_sof_dev *sdev) { @@ -86,6 +87,7 @@ int hda_dsp_trace_release(struct snd_sof_dev *sdev) dev_dbg(sdev->dev, "DMA trace stream is not opened!\n"); return -ENODEV; } +EXPORT_SYMBOL_NS(hda_dsp_trace_release, SND_SOC_SOF_INTEL_HDA_COMMON); int hda_dsp_trace_trigger(struct snd_sof_dev *sdev, int cmd) { @@ -93,3 +95,4 @@ int hda_dsp_trace_trigger(struct snd_sof_dev *sdev, int cmd) return hda_dsp_stream_trigger(sdev, hda->dtrace_stream, cmd); } +EXPORT_SYMBOL_NS(hda_dsp_trace_trigger, SND_SOC_SOF_INTEL_HDA_COMMON); diff --git a/sound/soc/sof/intel/hda.c b/sound/soc/sof/intel/hda.c index 87b0375250a2..87b2be025f40 100644 --- a/sound/soc/sof/intel/hda.c +++ b/sound/soc/sof/intel/hda.c @@ -238,7 +238,7 @@ int hda_sdw_startup(struct snd_sof_dev *sdev) return sdw_intel_startup(hdev->sdw); } -EXPORT_SYMBOL_NS(hda_sdw_startup, SND_SOC_SOF_INTEL_HDA_COMMON); +EXPORT_SYMBOL_NS(hda_sdw_startup, SND_SOC_SOF_INTEL_HDA_GENERIC); static int hda_sdw_exit(struct snd_sof_dev *sdev) { @@ -280,7 +280,7 @@ bool hda_common_check_sdw_irq(struct snd_sof_dev *sdev) out: return ret; } -EXPORT_SYMBOL_NS(hda_common_check_sdw_irq, SND_SOC_SOF_INTEL_HDA_COMMON); +EXPORT_SYMBOL_NS(hda_common_check_sdw_irq, SND_SOC_SOF_INTEL_HDA_GENERIC); static bool hda_dsp_check_sdw_irq(struct snd_sof_dev *sdev) { @@ -314,7 +314,7 @@ bool hda_sdw_check_wakeen_irq_common(struct snd_sof_dev *sdev) return false; } -EXPORT_SYMBOL_NS(hda_sdw_check_wakeen_irq_common, SND_SOC_SOF_INTEL_HDA_COMMON); +EXPORT_SYMBOL_NS(hda_sdw_check_wakeen_irq_common, SND_SOC_SOF_INTEL_HDA_GENERIC); static bool hda_sdw_check_wakeen_irq(struct snd_sof_dev *sdev) { @@ -345,7 +345,7 @@ void hda_sdw_process_wakeen_common(struct snd_sof_dev *sdev) sdw_intel_process_wakeen_event(hdev->sdw); } -EXPORT_SYMBOL_NS(hda_sdw_process_wakeen_common, SND_SOC_SOF_INTEL_HDA_COMMON); +EXPORT_SYMBOL_NS(hda_sdw_process_wakeen_common, SND_SOC_SOF_INTEL_HDA_GENERIC); #else /* IS_ENABLED(CONFIG_SND_SOC_SOF_INTEL_SOUNDWIRE) */ static inline int hda_sdw_acpi_scan(struct snd_sof_dev *sdev) @@ -418,7 +418,7 @@ int hda_dsp_post_fw_run(struct snd_sof_dev *sdev) /* re-enable clock gating and power gating */ return hda_dsp_ctrl_clock_power_gating(sdev, true); } -EXPORT_SYMBOL_NS(hda_dsp_post_fw_run, SND_SOC_SOF_INTEL_HDA_COMMON); +EXPORT_SYMBOL_NS(hda_dsp_post_fw_run, SND_SOC_SOF_INTEL_HDA_GENERIC); /* * Debug @@ -807,7 +807,7 @@ int hda_dsp_probe_early(struct snd_sof_dev *sdev) err: return ret; } -EXPORT_SYMBOL_NS(hda_dsp_probe_early, SND_SOC_SOF_INTEL_HDA_COMMON); +EXPORT_SYMBOL_NS(hda_dsp_probe_early, SND_SOC_SOF_INTEL_HDA_GENERIC); int hda_dsp_probe(struct snd_sof_dev *sdev) { @@ -964,7 +964,7 @@ hdac_bus_unmap: return ret; } -EXPORT_SYMBOL_NS(hda_dsp_probe, SND_SOC_SOF_INTEL_HDA_COMMON); +EXPORT_SYMBOL_NS(hda_dsp_probe, SND_SOC_SOF_INTEL_HDA_GENERIC); void hda_dsp_remove(struct snd_sof_dev *sdev) { @@ -1018,7 +1018,7 @@ skip_disable_dsp: if (!sdev->dspless_mode_selected) iounmap(sdev->bar[HDA_DSP_BAR]); } -EXPORT_SYMBOL_NS(hda_dsp_remove, SND_SOC_SOF_INTEL_HDA_COMMON); +EXPORT_SYMBOL_NS(hda_dsp_remove, SND_SOC_SOF_INTEL_HDA_GENERIC); void hda_dsp_remove_late(struct snd_sof_dev *sdev) { @@ -1034,7 +1034,7 @@ int hda_power_down_dsp(struct snd_sof_dev *sdev) return hda_dsp_core_reset_power_down(sdev, chip->host_managed_cores_mask); } -EXPORT_SYMBOL_NS(hda_power_down_dsp, SND_SOC_SOF_INTEL_HDA_COMMON); +EXPORT_SYMBOL_NS(hda_power_down_dsp, SND_SOC_SOF_INTEL_HDA_GENERIC); #if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA_AUDIO_CODEC) static void hda_generic_machine_select(struct snd_sof_dev *sdev, @@ -1504,7 +1504,7 @@ int hda_pci_intel_probe(struct pci_dev *pci, const struct pci_device_id *pci_id) return sof_pci_probe(pci, pci_id); } -EXPORT_SYMBOL_NS(hda_pci_intel_probe, SND_SOC_SOF_INTEL_HDA_COMMON); +EXPORT_SYMBOL_NS(hda_pci_intel_probe, SND_SOC_SOF_INTEL_HDA_GENERIC); int hda_register_clients(struct snd_sof_dev *sdev) { @@ -1525,4 +1525,5 @@ MODULE_IMPORT_NS(SND_INTEL_SOUNDWIRE_ACPI); MODULE_IMPORT_NS(SOUNDWIRE_INTEL_INIT); MODULE_IMPORT_NS(SOUNDWIRE_INTEL); MODULE_IMPORT_NS(SND_SOC_SOF_HDA_MLINK); +MODULE_IMPORT_NS(SND_SOC_SOF_INTEL_HDA_COMMON); MODULE_IMPORT_NS(SND_SOC_ACPI_INTEL_MATCH); diff --git a/sound/soc/sof/intel/pci-apl.c b/sound/soc/sof/intel/pci-apl.c index 4b287b5e9077..7551d4eb150d 100644 --- a/sound/soc/sof/intel/pci-apl.c +++ b/sound/soc/sof/intel/pci-apl.c @@ -105,5 +105,6 @@ static struct pci_driver snd_sof_pci_intel_apl_driver = { module_pci_driver(snd_sof_pci_intel_apl_driver); MODULE_LICENSE("Dual BSD/GPL"); +MODULE_IMPORT_NS(SND_SOC_SOF_INTEL_HDA_GENERIC); MODULE_IMPORT_NS(SND_SOC_SOF_INTEL_HDA_COMMON); MODULE_IMPORT_NS(SND_SOC_SOF_PCI_DEV); diff --git a/sound/soc/sof/intel/pci-cnl.c b/sound/soc/sof/intel/pci-cnl.c index 9fa0cd2eae79..f2584a314711 100644 --- a/sound/soc/sof/intel/pci-cnl.c +++ b/sound/soc/sof/intel/pci-cnl.c @@ -143,5 +143,6 @@ static struct pci_driver snd_sof_pci_intel_cnl_driver = { module_pci_driver(snd_sof_pci_intel_cnl_driver); MODULE_LICENSE("Dual BSD/GPL"); +MODULE_IMPORT_NS(SND_SOC_SOF_INTEL_HDA_GENERIC); MODULE_IMPORT_NS(SND_SOC_SOF_INTEL_HDA_COMMON); MODULE_IMPORT_NS(SND_SOC_SOF_PCI_DEV); diff --git a/sound/soc/sof/intel/pci-icl.c b/sound/soc/sof/intel/pci-icl.c index 70689b8b431b..a2826073ad3b 100644 --- a/sound/soc/sof/intel/pci-icl.c +++ b/sound/soc/sof/intel/pci-icl.c @@ -108,6 +108,7 @@ static struct pci_driver snd_sof_pci_intel_icl_driver = { module_pci_driver(snd_sof_pci_intel_icl_driver); MODULE_LICENSE("Dual BSD/GPL"); +MODULE_IMPORT_NS(SND_SOC_SOF_INTEL_HDA_GENERIC); MODULE_IMPORT_NS(SND_SOC_SOF_INTEL_HDA_COMMON); MODULE_IMPORT_NS(SND_SOC_SOF_INTEL_CNL); MODULE_IMPORT_NS(SND_SOC_SOF_PCI_DEV); diff --git a/sound/soc/sof/intel/pci-lnl.c b/sound/soc/sof/intel/pci-lnl.c index 38ae649d1def..5ad497826983 100644 --- a/sound/soc/sof/intel/pci-lnl.c +++ b/sound/soc/sof/intel/pci-lnl.c @@ -70,6 +70,7 @@ static struct pci_driver snd_sof_pci_intel_lnl_driver = { module_pci_driver(snd_sof_pci_intel_lnl_driver); MODULE_LICENSE("Dual BSD/GPL"); +MODULE_IMPORT_NS(SND_SOC_SOF_INTEL_HDA_GENERIC); MODULE_IMPORT_NS(SND_SOC_SOF_INTEL_HDA_COMMON); MODULE_IMPORT_NS(SND_SOC_SOF_INTEL_MTL); MODULE_IMPORT_NS(SND_SOC_SOF_HDA_MLINK); diff --git a/sound/soc/sof/intel/pci-mtl.c b/sound/soc/sof/intel/pci-mtl.c index cacc985d80f4..ad2615808394 100644 --- a/sound/soc/sof/intel/pci-mtl.c +++ b/sound/soc/sof/intel/pci-mtl.c @@ -133,5 +133,6 @@ static struct pci_driver snd_sof_pci_intel_mtl_driver = { module_pci_driver(snd_sof_pci_intel_mtl_driver); MODULE_LICENSE("Dual BSD/GPL"); +MODULE_IMPORT_NS(SND_SOC_SOF_INTEL_HDA_GENERIC); MODULE_IMPORT_NS(SND_SOC_SOF_INTEL_HDA_COMMON); MODULE_IMPORT_NS(SND_SOC_SOF_PCI_DEV); diff --git a/sound/soc/sof/intel/pci-skl.c b/sound/soc/sof/intel/pci-skl.c index 9dde439a0b0f..0bbfc4f55ff3 100644 --- a/sound/soc/sof/intel/pci-skl.c +++ b/sound/soc/sof/intel/pci-skl.c @@ -89,5 +89,6 @@ static struct pci_driver snd_sof_pci_intel_skl_driver = { module_pci_driver(snd_sof_pci_intel_skl_driver); MODULE_LICENSE("Dual BSD/GPL"); +MODULE_IMPORT_NS(SND_SOC_SOF_INTEL_HDA_GENERIC); MODULE_IMPORT_NS(SND_SOC_SOF_INTEL_HDA_COMMON); MODULE_IMPORT_NS(SND_SOC_SOF_PCI_DEV); diff --git a/sound/soc/sof/intel/pci-tgl.c b/sound/soc/sof/intel/pci-tgl.c index d7ecb892550f..dc40ec8c6256 100644 --- a/sound/soc/sof/intel/pci-tgl.c +++ b/sound/soc/sof/intel/pci-tgl.c @@ -317,6 +317,7 @@ static struct pci_driver snd_sof_pci_intel_tgl_driver = { module_pci_driver(snd_sof_pci_intel_tgl_driver); MODULE_LICENSE("Dual BSD/GPL"); +MODULE_IMPORT_NS(SND_SOC_SOF_INTEL_HDA_GENERIC); MODULE_IMPORT_NS(SND_SOC_SOF_INTEL_HDA_COMMON); MODULE_IMPORT_NS(SND_SOC_SOF_INTEL_CNL); MODULE_IMPORT_NS(SND_SOC_SOF_PCI_DEV); diff --git a/sound/soc/sof/intel/tracepoints.c b/sound/soc/sof/intel/tracepoints.c index c223c96fe0e3..9e3260a062c2 100644 --- a/sound/soc/sof/intel/tracepoints.c +++ b/sound/soc/sof/intel/tracepoints.c @@ -1,3 +1,5 @@ // SPDX-License-Identifier: GPL-2.0 #define CREATE_TRACE_POINTS #include + +EXPORT_TRACEPOINT_SYMBOL(sof_intel_hda_irq); -- cgit v1.2.3 From 1ae14f3520b1a0ad144610a3f592c81a3e81cd1b Mon Sep 17 00:00:00 2001 From: Shenghao Ding Date: Sun, 5 May 2024 20:23:45 +0800 Subject: ASoC: tas2781: Fix a warning reported by robot kernel test Fix a warning reported by robot kernel test that 'fw_entry' in function 'tas2781_load_calibration' is used uninitialized with compiler sh4-linux-gcc (GCC) 13.2.0, an update of copyright and a correction of the comments. Fixes: ef3bcde75d06 ("ASoc: tas2781: Add tas2781 driver") Signed-off-by: Shenghao Ding Link: https://lore.kernel.org/r/20240505122346.1326-1-shenghao-ding@ti.com Signed-off-by: Mark Brown --- sound/soc/codecs/tas2781-fmwlib.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/sound/soc/codecs/tas2781-fmwlib.c b/sound/soc/codecs/tas2781-fmwlib.c index 45760fe19523..a6be81adcb83 100644 --- a/sound/soc/codecs/tas2781-fmwlib.c +++ b/sound/soc/codecs/tas2781-fmwlib.c @@ -1,8 +1,8 @@ // SPDX-License-Identifier: GPL-2.0 // -// tasdevice-fmw.c -- TASDEVICE firmware support +// tas2781-fmwlib.c -- TASDEVICE firmware support // -// Copyright 2023 Texas Instruments, Inc. +// Copyright 2023 - 2024 Texas Instruments, Inc. // // Author: Shenghao Ding @@ -1878,7 +1878,7 @@ int tas2781_load_calibration(void *context, char *file_name, { struct tasdevice_priv *tas_priv = (struct tasdevice_priv *)context; struct tasdevice *tasdev = &(tas_priv->tasdevice[i]); - const struct firmware *fw_entry; + const struct firmware *fw_entry = NULL; struct tasdevice_fw *tas_fmw; struct firmware fmw; int offset = 0; -- cgit v1.2.3 From 293ad28116e2c3e4d3eb28bd0378558edc897f55 Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Fri, 3 May 2024 09:03:51 -0500 Subject: ASoC: SOF: Intel: clarify Copyright information MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit For some reason a number of files included the "All rights reserved" statement. Good old copy-paste made sure this mistake proliferated. Remove the "All rights reserved" in all Intel-copyright to align with internal guidance. Reviewed-by: Cezary Rojewski Signed-off-by: Pierre-Louis Bossart Reviewed-by: Bard Liao Reviewed-by: Péter Ujfalusi Link: https://lore.kernel.org/r/20240503140359.259762-2-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/control.c | 2 +- sound/soc/sof/core.c | 2 +- sound/soc/sof/debug.c | 2 +- sound/soc/sof/fw-file-profile.c | 2 +- sound/soc/sof/intel/apl.c | 2 +- sound/soc/sof/intel/atom.c | 2 +- sound/soc/sof/intel/atom.h | 2 +- sound/soc/sof/intel/bdw.c | 2 +- sound/soc/sof/intel/byt.c | 2 +- sound/soc/sof/intel/cnl.c | 2 +- sound/soc/sof/intel/ext_manifest.h | 2 +- sound/soc/sof/intel/hda-bus.c | 2 +- sound/soc/sof/intel/hda-codec.c | 2 +- sound/soc/sof/intel/hda-common-ops.c | 2 +- sound/soc/sof/intel/hda-ctrl.c | 2 +- sound/soc/sof/intel/hda-dai-ops.c | 2 +- sound/soc/sof/intel/hda-dai.c | 2 +- sound/soc/sof/intel/hda-dsp.c | 2 +- sound/soc/sof/intel/hda-ipc.c | 2 +- sound/soc/sof/intel/hda-ipc.h | 2 +- sound/soc/sof/intel/hda-loader-skl.c | 2 +- sound/soc/sof/intel/hda-loader.c | 2 +- sound/soc/sof/intel/hda-mlink.c | 2 +- sound/soc/sof/intel/hda-pcm.c | 2 +- sound/soc/sof/intel/hda-probes.c | 2 +- sound/soc/sof/intel/hda-stream.c | 2 +- sound/soc/sof/intel/hda-trace.c | 2 +- sound/soc/sof/intel/hda.c | 2 +- sound/soc/sof/intel/hda.h | 2 +- sound/soc/sof/intel/icl.c | 2 +- sound/soc/sof/intel/lnl.c | 2 +- sound/soc/sof/intel/lnl.h | 2 +- sound/soc/sof/intel/mtl.c | 2 +- sound/soc/sof/intel/mtl.h | 2 +- sound/soc/sof/intel/pci-apl.c | 2 +- sound/soc/sof/intel/pci-cnl.c | 2 +- sound/soc/sof/intel/pci-icl.c | 2 +- sound/soc/sof/intel/pci-lnl.c | 2 +- sound/soc/sof/intel/pci-mtl.c | 2 +- sound/soc/sof/intel/pci-skl.c | 2 +- sound/soc/sof/intel/pci-tgl.c | 2 +- sound/soc/sof/intel/pci-tng.c | 2 +- sound/soc/sof/intel/shim.h | 2 +- sound/soc/sof/intel/skl.c | 2 +- sound/soc/sof/intel/telemetry.c | 2 +- sound/soc/sof/intel/telemetry.h | 2 +- sound/soc/sof/intel/tgl.c | 2 +- sound/soc/sof/iomem-utils.c | 2 +- sound/soc/sof/ipc.c | 2 +- sound/soc/sof/ipc3-control.c | 2 +- sound/soc/sof/ipc3-dtrace.c | 2 +- sound/soc/sof/ipc3-loader.c | 2 +- sound/soc/sof/ipc3-pcm.c | 2 +- sound/soc/sof/ipc3-priv.h | 2 +- sound/soc/sof/ipc3-topology.c | 2 +- sound/soc/sof/ipc3.c | 2 +- sound/soc/sof/ipc4-control.c | 2 +- sound/soc/sof/ipc4-fw-reg.h | 2 +- sound/soc/sof/ipc4-loader.c | 2 +- sound/soc/sof/ipc4-mtrace.c | 2 +- sound/soc/sof/ipc4-pcm.c | 2 +- sound/soc/sof/ipc4-priv.h | 2 +- sound/soc/sof/ipc4-telemetry.c | 2 +- sound/soc/sof/ipc4-telemetry.h | 2 +- sound/soc/sof/ipc4-topology.c | 2 +- sound/soc/sof/ipc4-topology.h | 2 +- sound/soc/sof/ipc4.c | 2 +- sound/soc/sof/loader.c | 2 +- sound/soc/sof/nocodec.c | 2 +- sound/soc/sof/ops.c | 2 +- sound/soc/sof/ops.h | 2 +- sound/soc/sof/pcm.c | 2 +- sound/soc/sof/pm.c | 2 +- sound/soc/sof/sof-acpi-dev.c | 2 +- sound/soc/sof/sof-acpi-dev.h | 2 +- sound/soc/sof/sof-audio.c | 2 +- sound/soc/sof/sof-audio.h | 2 +- sound/soc/sof/sof-client-ipc-flood-test.c | 2 +- sound/soc/sof/sof-client-ipc-kernel-injector.c | 2 +- sound/soc/sof/sof-client-ipc-msg-injector.c | 2 +- sound/soc/sof/sof-client-probes-ipc3.c | 2 +- sound/soc/sof/sof-client-probes-ipc4.c | 2 +- sound/soc/sof/sof-client-probes.c | 2 +- sound/soc/sof/sof-client.c | 2 +- sound/soc/sof/sof-pci-dev.c | 2 +- sound/soc/sof/sof-pci-dev.h | 2 +- sound/soc/sof/sof-priv.h | 2 +- sound/soc/sof/sof-utils.c | 2 +- sound/soc/sof/sof-utils.h | 2 +- sound/soc/sof/stream-ipc.c | 2 +- sound/soc/sof/topology.c | 2 +- sound/soc/sof/trace.c | 2 +- sound/soc/sof/xtensa/core.c | 2 +- 93 files changed, 93 insertions(+), 93 deletions(-) diff --git a/sound/soc/sof/control.c b/sound/soc/sof/control.c index 75e13f4fd1eb..463d418e7200 100644 --- a/sound/soc/sof/control.c +++ b/sound/soc/sof/control.c @@ -3,7 +3,7 @@ // This file is provided under a dual BSD/GPLv2 license. When using or // redistributing this file, you may do so under either license. // -// Copyright(c) 2018 Intel Corporation. All rights reserved. +// Copyright(c) 2018 Intel Corporation // // Author: Liam Girdwood // diff --git a/sound/soc/sof/core.c b/sound/soc/sof/core.c index 238bda5f6b76..0a4917136ff9 100644 --- a/sound/soc/sof/core.c +++ b/sound/soc/sof/core.c @@ -3,7 +3,7 @@ // This file is provided under a dual BSD/GPLv2 license. When using or // redistributing this file, you may do so under either license. // -// Copyright(c) 2018 Intel Corporation. All rights reserved. +// Copyright(c) 2018 Intel Corporation // // Author: Liam Girdwood // diff --git a/sound/soc/sof/debug.c b/sound/soc/sof/debug.c index a620d1bcd49d..d0ffa1d71145 100644 --- a/sound/soc/sof/debug.c +++ b/sound/soc/sof/debug.c @@ -3,7 +3,7 @@ // This file is provided under a dual BSD/GPLv2 license. When using or // redistributing this file, you may do so under either license. // -// Copyright(c) 2018 Intel Corporation. All rights reserved. +// Copyright(c) 2018 Intel Corporation // // Author: Liam Girdwood // diff --git a/sound/soc/sof/fw-file-profile.c b/sound/soc/sof/fw-file-profile.c index b56b14232444..1c0eb13ae557 100644 --- a/sound/soc/sof/fw-file-profile.c +++ b/sound/soc/sof/fw-file-profile.c @@ -3,7 +3,7 @@ // This file is provided under a dual BSD/GPLv2 license. When using or // redistributing this file, you may do so under either license. // -// Copyright(c) 2023 Intel Corporation. All rights reserved. +// Copyright(c) 2023 Intel Corporation // #include diff --git a/sound/soc/sof/intel/apl.c b/sound/soc/sof/intel/apl.c index dee6c7f73e80..68e1ede270eb 100644 --- a/sound/soc/sof/intel/apl.c +++ b/sound/soc/sof/intel/apl.c @@ -3,7 +3,7 @@ // This file is provided under a dual BSD/GPLv2 license. When using or // redistributing this file, you may do so under either license. // -// Copyright(c) 2018 Intel Corporation. All rights reserved. +// Copyright(c) 2018 Intel Corporation // // Authors: Liam Girdwood // Ranjani Sridharan diff --git a/sound/soc/sof/intel/atom.c b/sound/soc/sof/intel/atom.c index bd9789b483b1..86af4e9a716e 100644 --- a/sound/soc/sof/intel/atom.c +++ b/sound/soc/sof/intel/atom.c @@ -3,7 +3,7 @@ // This file is provided under a dual BSD/GPLv2 license. When using or // redistributing this file, you may do so under either license. // -// Copyright(c) 2018-2021 Intel Corporation. All rights reserved. +// Copyright(c) 2018-2021 Intel Corporation // // Author: Liam Girdwood // diff --git a/sound/soc/sof/intel/atom.h b/sound/soc/sof/intel/atom.h index b965e5e080a6..20fb19102cb0 100644 --- a/sound/soc/sof/intel/atom.h +++ b/sound/soc/sof/intel/atom.h @@ -3,7 +3,7 @@ * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. * - * Copyright(c) 2017-2021 Intel Corporation. All rights reserved. + * Copyright(c) 2017-2021 Intel Corporation * * Author: Liam Girdwood */ diff --git a/sound/soc/sof/intel/bdw.c b/sound/soc/sof/intel/bdw.c index 2e8926cd00f6..3262286a9a9d 100644 --- a/sound/soc/sof/intel/bdw.c +++ b/sound/soc/sof/intel/bdw.c @@ -3,7 +3,7 @@ // This file is provided under a dual BSD/GPLv2 license. When using or // redistributing this file, you may do so under either license. // -// Copyright(c) 2018 Intel Corporation. All rights reserved. +// Copyright(c) 2018 Intel Corporation // // Author: Liam Girdwood // diff --git a/sound/soc/sof/intel/byt.c b/sound/soc/sof/intel/byt.c index 14a065999a89..d78d11d4cfbf 100644 --- a/sound/soc/sof/intel/byt.c +++ b/sound/soc/sof/intel/byt.c @@ -3,7 +3,7 @@ // This file is provided under a dual BSD/GPLv2 license. When using or // redistributing this file, you may do so under either license. // -// Copyright(c) 2018 Intel Corporation. All rights reserved. +// Copyright(c) 2018 Intel Corporation // // Author: Liam Girdwood // diff --git a/sound/soc/sof/intel/cnl.c b/sound/soc/sof/intel/cnl.c index 85e1e4760d0e..108a13ce5c5c 100644 --- a/sound/soc/sof/intel/cnl.c +++ b/sound/soc/sof/intel/cnl.c @@ -3,7 +3,7 @@ // This file is provided under a dual BSD/GPLv2 license. When using or // redistributing this file, you may do so under either license. // -// Copyright(c) 2018 Intel Corporation. All rights reserved. +// Copyright(c) 2018 Intel Corporation // // Authors: Liam Girdwood // Ranjani Sridharan diff --git a/sound/soc/sof/intel/ext_manifest.h b/sound/soc/sof/intel/ext_manifest.h index 2dfae9285d3c..1ca19c691852 100644 --- a/sound/soc/sof/intel/ext_manifest.h +++ b/sound/soc/sof/intel/ext_manifest.h @@ -3,7 +3,7 @@ * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. * - * Copyright(c) 2020 Intel Corporation. All rights reserved. + * Copyright(c) 2020 Intel Corporation */ /* diff --git a/sound/soc/sof/intel/hda-bus.c b/sound/soc/sof/intel/hda-bus.c index fc63085d2d74..96315613f7d9 100644 --- a/sound/soc/sof/intel/hda-bus.c +++ b/sound/soc/sof/intel/hda-bus.c @@ -3,7 +3,7 @@ // This file is provided under a dual BSD/GPLv2 license. When using or // redistributing this file, you may do so under either license. // -// Copyright(c) 2018 Intel Corporation. All rights reserved. +// Copyright(c) 2018 Intel Corporation // // Authors: Keyon Jie diff --git a/sound/soc/sof/intel/hda-codec.c b/sound/soc/sof/intel/hda-codec.c index 6a13f38a8d21..da3db3ed379e 100644 --- a/sound/soc/sof/intel/hda-codec.c +++ b/sound/soc/sof/intel/hda-codec.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only // -// Copyright(c) 2018 Intel Corporation. All rights reserved. +// Copyright(c) 2018 Intel Corporation // // Authors: Keyon Jie // diff --git a/sound/soc/sof/intel/hda-common-ops.c b/sound/soc/sof/intel/hda-common-ops.c index 466769c68da5..79d1f8ca4f84 100644 --- a/sound/soc/sof/intel/hda-common-ops.c +++ b/sound/soc/sof/intel/hda-common-ops.c @@ -3,7 +3,7 @@ // This file is provided under a dual BSD/GPLv2 license. When using or // redistributing this file, you may do so under either license. // -// Copyright(c) 2022 Intel Corporation. All rights reserved. +// Copyright(c) 2022 Intel Corporation // /* diff --git a/sound/soc/sof/intel/hda-ctrl.c b/sound/soc/sof/intel/hda-ctrl.c index 6d941209847f..243dc6df911a 100644 --- a/sound/soc/sof/intel/hda-ctrl.c +++ b/sound/soc/sof/intel/hda-ctrl.c @@ -3,7 +3,7 @@ // This file is provided under a dual BSD/GPLv2 license. When using or // redistributing this file, you may do so under either license. // -// Copyright(c) 2018 Intel Corporation. All rights reserved. +// Copyright(c) 2018 Intel Corporation // // Authors: Liam Girdwood // Ranjani Sridharan diff --git a/sound/soc/sof/intel/hda-dai-ops.c b/sound/soc/sof/intel/hda-dai-ops.c index 457144203999..484c76147885 100644 --- a/sound/soc/sof/intel/hda-dai-ops.c +++ b/sound/soc/sof/intel/hda-dai-ops.c @@ -3,7 +3,7 @@ // This file is provided under a dual BSD/GPLv2 license. When using or // redistributing this file, you may do so under either license. // -// Copyright(c) 2022 Intel Corporation. All rights reserved. +// Copyright(c) 2022 Intel Corporation #include #include diff --git a/sound/soc/sof/intel/hda-dai.c b/sound/soc/sof/intel/hda-dai.c index 3f2fd84907d2..ee159d239b40 100644 --- a/sound/soc/sof/intel/hda-dai.c +++ b/sound/soc/sof/intel/hda-dai.c @@ -3,7 +3,7 @@ // This file is provided under a dual BSD/GPLv2 license. When using or // redistributing this file, you may do so under either license. // -// Copyright(c) 2018 Intel Corporation. All rights reserved. +// Copyright(c) 2018 Intel Corporation // // Authors: Keyon Jie // diff --git a/sound/soc/sof/intel/hda-dsp.c b/sound/soc/sof/intel/hda-dsp.c index ef5c915db8ff..3ef9b98bcf63 100644 --- a/sound/soc/sof/intel/hda-dsp.c +++ b/sound/soc/sof/intel/hda-dsp.c @@ -3,7 +3,7 @@ // This file is provided under a dual BSD/GPLv2 license. When using or // redistributing this file, you may do so under either license. // -// Copyright(c) 2018 Intel Corporation. All rights reserved. +// Copyright(c) 2018 Intel Corporation // // Authors: Liam Girdwood // Ranjani Sridharan diff --git a/sound/soc/sof/intel/hda-ipc.c b/sound/soc/sof/intel/hda-ipc.c index a838dddb1d32..de0426ab8021 100644 --- a/sound/soc/sof/intel/hda-ipc.c +++ b/sound/soc/sof/intel/hda-ipc.c @@ -3,7 +3,7 @@ // This file is provided under a dual BSD/GPLv2 license. When using or // redistributing this file, you may do so under either license. // -// Copyright(c) 2018 Intel Corporation. All rights reserved. +// Copyright(c) 2018 Intel Corporation // // Authors: Liam Girdwood // Ranjani Sridharan diff --git a/sound/soc/sof/intel/hda-ipc.h b/sound/soc/sof/intel/hda-ipc.h index 8ec5e9f6f8d7..ad9478b8c390 100644 --- a/sound/soc/sof/intel/hda-ipc.h +++ b/sound/soc/sof/intel/hda-ipc.h @@ -3,7 +3,7 @@ * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. * - * Copyright(c) 2019 Intel Corporation. All rights reserved. + * Copyright(c) 2019 Intel Corporation * * Author: Keyon Jie */ diff --git a/sound/soc/sof/intel/hda-loader-skl.c b/sound/soc/sof/intel/hda-loader-skl.c index 1e77ca936f80..f38178c904de 100644 --- a/sound/soc/sof/intel/hda-loader-skl.c +++ b/sound/soc/sof/intel/hda-loader-skl.c @@ -3,7 +3,7 @@ // This file is provided under a dual BSD/GPLv2 license. When using or // redistributing this file, you may do so under either license. // -// Copyright(c) 2018-2022 Intel Corporation. All rights reserved. +// Copyright(c) 2018-2022 Intel Corporation // #include diff --git a/sound/soc/sof/intel/hda-loader.c b/sound/soc/sof/intel/hda-loader.c index dc88b7ea599e..3065ebe62ed3 100644 --- a/sound/soc/sof/intel/hda-loader.c +++ b/sound/soc/sof/intel/hda-loader.c @@ -3,7 +3,7 @@ // This file is provided under a dual BSD/GPLv2 license. When using or // redistributing this file, you may do so under either license. // -// Copyright(c) 2018 Intel Corporation. All rights reserved. +// Copyright(c) 2018 Intel Corporation // // Authors: Liam Girdwood // Ranjani Sridharan diff --git a/sound/soc/sof/intel/hda-mlink.c b/sound/soc/sof/intel/hda-mlink.c index b592e687a87a..04bbc5c9904c 100644 --- a/sound/soc/sof/intel/hda-mlink.c +++ b/sound/soc/sof/intel/hda-mlink.c @@ -3,7 +3,7 @@ // This file is provided under a dual BSD/GPLv2 license. When using or // redistributing this file, you may do so under either license. // -// Copyright(c) 2022 Intel Corporation. All rights reserved. +// Copyright(c) 2022 Intel Corporation // /* diff --git a/sound/soc/sof/intel/hda-pcm.c b/sound/soc/sof/intel/hda-pcm.c index d7b446f3f973..d4628527165d 100644 --- a/sound/soc/sof/intel/hda-pcm.c +++ b/sound/soc/sof/intel/hda-pcm.c @@ -3,7 +3,7 @@ // This file is provided under a dual BSD/GPLv2 license. When using or // redistributing this file, you may do so under either license. // -// Copyright(c) 2018 Intel Corporation. All rights reserved. +// Copyright(c) 2018 Intel Corporation // // Authors: Liam Girdwood // Ranjani Sridharan diff --git a/sound/soc/sof/intel/hda-probes.c b/sound/soc/sof/intel/hda-probes.c index 56a533c63cb0..2c15975c2a72 100644 --- a/sound/soc/sof/intel/hda-probes.c +++ b/sound/soc/sof/intel/hda-probes.c @@ -3,7 +3,7 @@ // This file is provided under a dual BSD/GPLv2 license. When using or // redistributing this file, you may do so under either license. // -// Copyright(c) 2019-2021 Intel Corporation. All rights reserved. +// Copyright(c) 2019-2021 Intel Corporation // // Author: Cezary Rojewski // Converted to SOF client: diff --git a/sound/soc/sof/intel/hda-stream.c b/sound/soc/sof/intel/hda-stream.c index 91b1371745e6..0ff05b1006a7 100644 --- a/sound/soc/sof/intel/hda-stream.c +++ b/sound/soc/sof/intel/hda-stream.c @@ -3,7 +3,7 @@ // This file is provided under a dual BSD/GPLv2 license. When using or // redistributing this file, you may do so under either license. // -// Copyright(c) 2018 Intel Corporation. All rights reserved. +// Copyright(c) 2018 Intel Corporation // // Authors: Liam Girdwood // Ranjani Sridharan diff --git a/sound/soc/sof/intel/hda-trace.c b/sound/soc/sof/intel/hda-trace.c index cbb9bd7770e6..fed4e4c08fdf 100644 --- a/sound/soc/sof/intel/hda-trace.c +++ b/sound/soc/sof/intel/hda-trace.c @@ -3,7 +3,7 @@ // This file is provided under a dual BSD/GPLv2 license. When using or // redistributing this file, you may do so under either license. // -// Copyright(c) 2018 Intel Corporation. All rights reserved. +// Copyright(c) 2018 Intel Corporation // // Authors: Liam Girdwood // Ranjani Sridharan diff --git a/sound/soc/sof/intel/hda.c b/sound/soc/sof/intel/hda.c index d509cfa38a64..72354748bede 100644 --- a/sound/soc/sof/intel/hda.c +++ b/sound/soc/sof/intel/hda.c @@ -3,7 +3,7 @@ // This file is provided under a dual BSD/GPLv2 license. When using or // redistributing this file, you may do so under either license. // -// Copyright(c) 2018 Intel Corporation. All rights reserved. +// Copyright(c) 2018 Intel Corporation // // Authors: Liam Girdwood // Ranjani Sridharan diff --git a/sound/soc/sof/intel/hda.h b/sound/soc/sof/intel/hda.h index 7804c5b50c26..88d63ecc9f92 100644 --- a/sound/soc/sof/intel/hda.h +++ b/sound/soc/sof/intel/hda.h @@ -3,7 +3,7 @@ * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. * - * Copyright(c) 2017 Intel Corporation. All rights reserved. + * Copyright(c) 2017 Intel Corporation * * Author: Liam Girdwood */ diff --git a/sound/soc/sof/intel/icl.c b/sound/soc/sof/intel/icl.c index 040698591992..a8dde7b37b1b 100644 --- a/sound/soc/sof/intel/icl.c +++ b/sound/soc/sof/intel/icl.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause) // -// Copyright(c) 2020 Intel Corporation. All rights reserved. +// Copyright(c) 2020 Intel Corporation // // Author: Fred Oh // diff --git a/sound/soc/sof/intel/lnl.c b/sound/soc/sof/intel/lnl.c index 82c975823ab3..219c46ddbf6a 100644 --- a/sound/soc/sof/intel/lnl.c +++ b/sound/soc/sof/intel/lnl.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause) // -// Copyright(c) 2023 Intel Corporation. All rights reserved. +// Copyright(c) 2023 Intel Corporation /* * Hardware interface for audio DSP on LunarLake. diff --git a/sound/soc/sof/intel/lnl.h b/sound/soc/sof/intel/lnl.h index 4f4734fe7e08..79101af84b2e 100644 --- a/sound/soc/sof/intel/lnl.h +++ b/sound/soc/sof/intel/lnl.h @@ -3,7 +3,7 @@ * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. * - * Copyright(c) 2024 Intel Corporation. All rights reserved. + * Copyright(c) 2024 Intel Corporation */ #ifndef __SOF_INTEL_LNL_H diff --git a/sound/soc/sof/intel/mtl.c b/sound/soc/sof/intel/mtl.c index 5d3b2d4be78a..9fd19ad3f03d 100644 --- a/sound/soc/sof/intel/mtl.c +++ b/sound/soc/sof/intel/mtl.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause) // -// Copyright(c) 2022 Intel Corporation. All rights reserved. +// Copyright(c) 2022 Intel Corporation // // Authors: Ranjani Sridharan // diff --git a/sound/soc/sof/intel/mtl.h b/sound/soc/sof/intel/mtl.h index d2d709fb4f06..7acaa7e724f4 100644 --- a/sound/soc/sof/intel/mtl.h +++ b/sound/soc/sof/intel/mtl.h @@ -3,7 +3,7 @@ * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. * - * Copyright(c) 2020-2022 Intel Corporation. All rights reserved. + * Copyright(c) 2020-2022 Intel Corporation */ /* DSP Registers */ diff --git a/sound/soc/sof/intel/pci-apl.c b/sound/soc/sof/intel/pci-apl.c index 4b287b5e9077..0b076ff70d80 100644 --- a/sound/soc/sof/intel/pci-apl.c +++ b/sound/soc/sof/intel/pci-apl.c @@ -3,7 +3,7 @@ // This file is provided under a dual BSD/GPLv2 license. When using or // redistributing this file, you may do so under either license. // -// Copyright(c) 2018-2021 Intel Corporation. All rights reserved. +// Copyright(c) 2018-2021 Intel Corporation // // Author: Liam Girdwood // diff --git a/sound/soc/sof/intel/pci-cnl.c b/sound/soc/sof/intel/pci-cnl.c index 9fa0cd2eae79..fcaee9ec790d 100644 --- a/sound/soc/sof/intel/pci-cnl.c +++ b/sound/soc/sof/intel/pci-cnl.c @@ -3,7 +3,7 @@ // This file is provided under a dual BSD/GPLv2 license. When using or // redistributing this file, you may do so under either license. // -// Copyright(c) 2018 Intel Corporation. All rights reserved. +// Copyright(c) 2018 Intel Corporation // // Author: Liam Girdwood // diff --git a/sound/soc/sof/intel/pci-icl.c b/sound/soc/sof/intel/pci-icl.c index b99c7c9aad7d..284e7c873287 100644 --- a/sound/soc/sof/intel/pci-icl.c +++ b/sound/soc/sof/intel/pci-icl.c @@ -3,7 +3,7 @@ // This file is provided under a dual BSD/GPLv2 license. When using or // redistributing this file, you may do so under either license. // -// Copyright(c) 2018-2021 Intel Corporation. All rights reserved. +// Copyright(c) 2018-2021 Intel Corporation // // Author: Liam Girdwood // diff --git a/sound/soc/sof/intel/pci-lnl.c b/sound/soc/sof/intel/pci-lnl.c index b14e508f1f31..6daa5acb8645 100644 --- a/sound/soc/sof/intel/pci-lnl.c +++ b/sound/soc/sof/intel/pci-lnl.c @@ -3,7 +3,7 @@ // This file is provided under a dual BSD/GPLv2 license. When using or // redistributing this file, you may do so under either license. // -// Copyright(c) 2023 Intel Corporation. All rights reserved. +// Copyright(c) 2023 Intel Corporation // // Author: Ranjani Sridharan // diff --git a/sound/soc/sof/intel/pci-mtl.c b/sound/soc/sof/intel/pci-mtl.c index cacc985d80f4..bd1590282f67 100644 --- a/sound/soc/sof/intel/pci-mtl.c +++ b/sound/soc/sof/intel/pci-mtl.c @@ -3,7 +3,7 @@ // This file is provided under a dual BSD/GPLv2 license. When using or // redistributing this file, you may do so under either license. // -// Copyright(c) 2018-2022 Intel Corporation. All rights reserved. +// Copyright(c) 2018-2022 Intel Corporation // // Author: Ranjani Sridharan // diff --git a/sound/soc/sof/intel/pci-skl.c b/sound/soc/sof/intel/pci-skl.c index 9dde439a0b0f..d9f5f4a7adbd 100644 --- a/sound/soc/sof/intel/pci-skl.c +++ b/sound/soc/sof/intel/pci-skl.c @@ -3,7 +3,7 @@ // This file is provided under a dual BSD/GPLv2 license. When using or // redistributing this file, you may do so under either license. // -// Copyright(c) 2018-2022 Intel Corporation. All rights reserved. +// Copyright(c) 2018-2022 Intel Corporation // #include diff --git a/sound/soc/sof/intel/pci-tgl.c b/sound/soc/sof/intel/pci-tgl.c index a361ee9d1107..aa0afe4112d0 100644 --- a/sound/soc/sof/intel/pci-tgl.c +++ b/sound/soc/sof/intel/pci-tgl.c @@ -3,7 +3,7 @@ // This file is provided under a dual BSD/GPLv2 license. When using or // redistributing this file, you may do so under either license. // -// Copyright(c) 2018-2021 Intel Corporation. All rights reserved. +// Copyright(c) 2018-2021 Intel Corporation // // Author: Liam Girdwood // diff --git a/sound/soc/sof/intel/pci-tng.c b/sound/soc/sof/intel/pci-tng.c index d8a36d5a29f7..5c3069588bb7 100644 --- a/sound/soc/sof/intel/pci-tng.c +++ b/sound/soc/sof/intel/pci-tng.c @@ -3,7 +3,7 @@ // This file is provided under a dual BSD/GPLv2 license. When using or // redistributing this file, you may do so under either license. // -// Copyright(c) 2018-2021 Intel Corporation. All rights reserved. +// Copyright(c) 2018-2021 Intel Corporation // // Author: Liam Girdwood // diff --git a/sound/soc/sof/intel/shim.h b/sound/soc/sof/intel/shim.h index 18ce3d33fa80..9d2de2e8f746 100644 --- a/sound/soc/sof/intel/shim.h +++ b/sound/soc/sof/intel/shim.h @@ -3,7 +3,7 @@ * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. * - * Copyright(c) 2017 Intel Corporation. All rights reserved. + * Copyright(c) 2017 Intel Corporation * * Author: Liam Girdwood */ diff --git a/sound/soc/sof/intel/skl.c b/sound/soc/sof/intel/skl.c index 93824e6ce573..9a002811e9ff 100644 --- a/sound/soc/sof/intel/skl.c +++ b/sound/soc/sof/intel/skl.c @@ -3,7 +3,7 @@ // This file is provided under a dual BSD/GPLv2 license. When using or // redistributing this file, you may do so under either license. // -// Copyright(c) 2018-2022 Intel Corporation. All rights reserved. +// Copyright(c) 2018-2022 Intel Corporation // /* diff --git a/sound/soc/sof/intel/telemetry.c b/sound/soc/sof/intel/telemetry.c index 1a3b5c28a6f0..5053075028a0 100644 --- a/sound/soc/sof/intel/telemetry.c +++ b/sound/soc/sof/intel/telemetry.c @@ -3,7 +3,7 @@ // This file is provided under a dual BSD/GPLv2 license. When using or // redistributing this file, you may do so under either license. // -// Copyright(c) 2023 Intel Corporation. All rights reserved. +// Copyright(c) 2023 Intel Corporation /* telemetry data queried from debug window */ diff --git a/sound/soc/sof/intel/telemetry.h b/sound/soc/sof/intel/telemetry.h index 3c2b23c75f5d..e4e91943a41a 100644 --- a/sound/soc/sof/intel/telemetry.h +++ b/sound/soc/sof/intel/telemetry.h @@ -3,7 +3,7 @@ * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. * - * Copyright(c) 2023 Intel Corporation. All rights reserved. + * Copyright(c) 2023 Intel Corporation * * telemetry data in debug windows */ diff --git a/sound/soc/sof/intel/tgl.c b/sound/soc/sof/intel/tgl.c index 6cda47a78118..d17c4e549c48 100644 --- a/sound/soc/sof/intel/tgl.c +++ b/sound/soc/sof/intel/tgl.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause) // -// Copyright(c) 2020 Intel Corporation. All rights reserved. +// Copyright(c) 2020 Intel Corporation // // Authors: Ranjani Sridharan // diff --git a/sound/soc/sof/iomem-utils.c b/sound/soc/sof/iomem-utils.c index 3f57f6cf6542..cd9cb54e7b23 100644 --- a/sound/soc/sof/iomem-utils.c +++ b/sound/soc/sof/iomem-utils.c @@ -3,7 +3,7 @@ // This file is provided under a dual BSD/GPLv2 license. When using or // redistributing this file, you may do so under either license. // -// Copyright(c) 2018-2022 Intel Corporation. All rights reserved. +// Copyright(c) 2018-2022 Intel Corporation // // Author: Keyon Jie // diff --git a/sound/soc/sof/ipc.c b/sound/soc/sof/ipc.c index febe372f9aa8..3fb8d3e9dc6a 100644 --- a/sound/soc/sof/ipc.c +++ b/sound/soc/sof/ipc.c @@ -3,7 +3,7 @@ // This file is provided under a dual BSD/GPLv2 license. When using or // redistributing this file, you may do so under either license. // -// Copyright(c) 2018 Intel Corporation. All rights reserved. +// Copyright(c) 2018 Intel Corporation // // Author: Liam Girdwood // diff --git a/sound/soc/sof/ipc3-control.c b/sound/soc/sof/ipc3-control.c index a8deec7dc021..2b1befad6d5c 100644 --- a/sound/soc/sof/ipc3-control.c +++ b/sound/soc/sof/ipc3-control.c @@ -3,7 +3,7 @@ // This file is provided under a dual BSD/GPLv2 license. When using or // redistributing this file, you may do so under either license. // -// Copyright(c) 2021 Intel Corporation. All rights reserved. +// Copyright(c) 2021 Intel Corporation // // diff --git a/sound/soc/sof/ipc3-dtrace.c b/sound/soc/sof/ipc3-dtrace.c index 0dca139322f3..744a91a150bc 100644 --- a/sound/soc/sof/ipc3-dtrace.c +++ b/sound/soc/sof/ipc3-dtrace.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only // -// Copyright(c) 2022 Intel Corporation. All rights reserved. +// Copyright(c) 2022 Intel Corporation // // Author: Liam Girdwood diff --git a/sound/soc/sof/ipc3-loader.c b/sound/soc/sof/ipc3-loader.c index 6e3ef0672110..35b89c2b9d4c 100644 --- a/sound/soc/sof/ipc3-loader.c +++ b/sound/soc/sof/ipc3-loader.c @@ -3,7 +3,7 @@ // This file is provided under a dual BSD/GPLv2 license. When using or // redistributing this file, you may do so under either license. // -// Copyright(c) 2022 Intel Corporation. All rights reserved. +// Copyright(c) 2022 Intel Corporation #include #include "sof-priv.h" diff --git a/sound/soc/sof/ipc3-pcm.c b/sound/soc/sof/ipc3-pcm.c index af0bf354cb20..1c1b8f595367 100644 --- a/sound/soc/sof/ipc3-pcm.c +++ b/sound/soc/sof/ipc3-pcm.c @@ -3,7 +3,7 @@ // This file is provided under a dual BSD/GPLv2 license. When using or // redistributing this file, you may do so under either license. // -// Copyright(c) 2021 Intel Corporation. All rights reserved. +// Copyright(c) 2021 Intel Corporation // // diff --git a/sound/soc/sof/ipc3-priv.h b/sound/soc/sof/ipc3-priv.h index 9cd7794f3cb6..866c5f67b91a 100644 --- a/sound/soc/sof/ipc3-priv.h +++ b/sound/soc/sof/ipc3-priv.h @@ -3,7 +3,7 @@ * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. * - * Copyright(c) 2021 Intel Corporation. All rights reserved. + * Copyright(c) 2021 Intel Corporation */ #ifndef __SOUND_SOC_SOF_IPC3_PRIV_H diff --git a/sound/soc/sof/ipc3-topology.c b/sound/soc/sof/ipc3-topology.c index ab7f46a162da..32c7d1f3b528 100644 --- a/sound/soc/sof/ipc3-topology.c +++ b/sound/soc/sof/ipc3-topology.c @@ -3,7 +3,7 @@ // This file is provided under a dual BSD/GPLv2 license. When using or // redistributing this file, you may do so under either license. // -// Copyright(c) 2021 Intel Corporation. All rights reserved. +// Copyright(c) 2021 Intel Corporation // // diff --git a/sound/soc/sof/ipc3.c b/sound/soc/sof/ipc3.c index c03dd513fbff..83c22d4a4830 100644 --- a/sound/soc/sof/ipc3.c +++ b/sound/soc/sof/ipc3.c @@ -3,7 +3,7 @@ // This file is provided under a dual BSD/GPLv2 license. When using or // redistributing this file, you may do so under either license. // -// Copyright(c) 2021 Intel Corporation. All rights reserved. +// Copyright(c) 2021 Intel Corporation // // diff --git a/sound/soc/sof/ipc4-control.c b/sound/soc/sof/ipc4-control.c index 1be9519de909..576f407cd456 100644 --- a/sound/soc/sof/ipc4-control.c +++ b/sound/soc/sof/ipc4-control.c @@ -3,7 +3,7 @@ // This file is provided under a dual BSD/GPLv2 license. When using or // redistributing this file, you may do so under either license. // -// Copyright(c) 2022 Intel Corporation. All rights reserved. +// Copyright(c) 2022 Intel Corporation // // diff --git a/sound/soc/sof/ipc4-fw-reg.h b/sound/soc/sof/ipc4-fw-reg.h index 7226161e57e1..7b85a364a6a6 100644 --- a/sound/soc/sof/ipc4-fw-reg.h +++ b/sound/soc/sof/ipc4-fw-reg.h @@ -3,7 +3,7 @@ * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. * - * Copyright(c) 2022 Intel Corporation. All rights reserved. + * Copyright(c) 2022 Intel Corporation */ #ifndef __IPC4_FW_REG_H__ diff --git a/sound/soc/sof/ipc4-loader.c b/sound/soc/sof/ipc4-loader.c index 641c4f24cca9..bcdb33d03682 100644 --- a/sound/soc/sof/ipc4-loader.c +++ b/sound/soc/sof/ipc4-loader.c @@ -3,7 +3,7 @@ // This file is provided under a dual BSD/GPLv2 license. When using or // redistributing this file, you may do so under either license. // -// Copyright(c) 2022 Intel Corporation. All rights reserved. +// Copyright(c) 2022 Intel Corporation #include #include diff --git a/sound/soc/sof/ipc4-mtrace.c b/sound/soc/sof/ipc4-mtrace.c index 0e04bea9432d..aa5b78604db6 100644 --- a/sound/soc/sof/ipc4-mtrace.c +++ b/sound/soc/sof/ipc4-mtrace.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only // -// Copyright(c) 2022 Intel Corporation. All rights reserved. +// Copyright(c) 2022 Intel Corporation #include #include diff --git a/sound/soc/sof/ipc4-pcm.c b/sound/soc/sof/ipc4-pcm.c index 4594470ed08b..307bee63756b 100644 --- a/sound/soc/sof/ipc4-pcm.c +++ b/sound/soc/sof/ipc4-pcm.c @@ -3,7 +3,7 @@ // This file is provided under a dual BSD/GPLv2 license. When using or // redistributing this file, you may do so under either license. // -// Copyright(c) 2022 Intel Corporation. All rights reserved. +// Copyright(c) 2022 Intel Corporation // #include diff --git a/sound/soc/sof/ipc4-priv.h b/sound/soc/sof/ipc4-priv.h index e157ab80a103..ea3323b90343 100644 --- a/sound/soc/sof/ipc4-priv.h +++ b/sound/soc/sof/ipc4-priv.h @@ -3,7 +3,7 @@ * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. * - * Copyright(c) 2022 Intel Corporation. All rights reserved. + * Copyright(c) 2022 Intel Corporation */ #ifndef __SOUND_SOC_SOF_IPC4_PRIV_H diff --git a/sound/soc/sof/ipc4-telemetry.c b/sound/soc/sof/ipc4-telemetry.c index ec4ae9674364..ddc3bc494ffe 100644 --- a/sound/soc/sof/ipc4-telemetry.c +++ b/sound/soc/sof/ipc4-telemetry.c @@ -3,7 +3,7 @@ // This file is provided under a dual BSD/GPLv2 license. When using or // redistributing this file, you may do so under either license. // -// Copyright(c) 2018-2023 Intel Corporation. All rights reserved. +// Copyright(c) 2018-2023 Intel Corporation // #include diff --git a/sound/soc/sof/ipc4-telemetry.h b/sound/soc/sof/ipc4-telemetry.h index ab3599e3d87d..9298f8acc648 100644 --- a/sound/soc/sof/ipc4-telemetry.h +++ b/sound/soc/sof/ipc4-telemetry.h @@ -3,7 +3,7 @@ * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. * - * Copyright(c) 2023 Intel Corporation. All rights reserved. + * Copyright(c) 2023 Intel Corporation */ #ifndef __SOUND_SOC_SOF_IPC4_TELEMETRY_H diff --git a/sound/soc/sof/ipc4-topology.c b/sound/soc/sof/ipc4-topology.c index a972b2b5122a..b85715d33c86 100644 --- a/sound/soc/sof/ipc4-topology.c +++ b/sound/soc/sof/ipc4-topology.c @@ -3,7 +3,7 @@ // This file is provided under a dual BSD/GPLv2 license. When using or // redistributing this file, you may do so under either license. // -// Copyright(c) 2022 Intel Corporation. All rights reserved. +// Copyright(c) 2022 Intel Corporation // // #include diff --git a/sound/soc/sof/ipc4-topology.h b/sound/soc/sof/ipc4-topology.h index 6e33208a357f..4488762f6a71 100644 --- a/sound/soc/sof/ipc4-topology.h +++ b/sound/soc/sof/ipc4-topology.h @@ -3,7 +3,7 @@ * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. * - * Copyright(c) 2022 Intel Corporation. All rights reserved. + * Copyright(c) 2022 Intel Corporation */ #ifndef __INCLUDE_SOUND_SOF_IPC4_TOPOLOGY_H__ diff --git a/sound/soc/sof/ipc4.c b/sound/soc/sof/ipc4.c index ac5c6bc66d2a..4386cbae16d4 100644 --- a/sound/soc/sof/ipc4.c +++ b/sound/soc/sof/ipc4.c @@ -3,7 +3,7 @@ // This file is provided under a dual BSD/GPLv2 license. When using or // redistributing this file, you may do so under either license. // -// Copyright(c) 2022 Intel Corporation. All rights reserved. +// Copyright(c) 2022 Intel Corporation // // Authors: Rander Wang // Peter Ujfalusi diff --git a/sound/soc/sof/loader.c b/sound/soc/sof/loader.c index 2f8555f11c03..0baf316b0064 100644 --- a/sound/soc/sof/loader.c +++ b/sound/soc/sof/loader.c @@ -3,7 +3,7 @@ // This file is provided under a dual BSD/GPLv2 license. When using or // redistributing this file, you may do so under either license. // -// Copyright(c) 2018 Intel Corporation. All rights reserved. +// Copyright(c) 2018 Intel Corporation // // Author: Liam Girdwood // diff --git a/sound/soc/sof/nocodec.c b/sound/soc/sof/nocodec.c index 34aa8a7cfc7d..fdcbe33d3dcf 100644 --- a/sound/soc/sof/nocodec.c +++ b/sound/soc/sof/nocodec.c @@ -3,7 +3,7 @@ // This file is provided under a dual BSD/GPLv2 license. When using or // redistributing this file, you may do so under either license. // -// Copyright(c) 2018 Intel Corporation. All rights reserved. +// Copyright(c) 2018 Intel Corporation // // Author: Liam Girdwood // diff --git a/sound/soc/sof/ops.c b/sound/soc/sof/ops.c index ff066de4ceb9..bd52e7ec6883 100644 --- a/sound/soc/sof/ops.c +++ b/sound/soc/sof/ops.c @@ -3,7 +3,7 @@ // This file is provided under a dual BSD/GPLv2 license. When using or // redistributing this file, you may do so under either license. // -// Copyright(c) 2018 Intel Corporation. All rights reserved. +// Copyright(c) 2018 Intel Corporation // // Author: Liam Girdwood // diff --git a/sound/soc/sof/ops.h b/sound/soc/sof/ops.h index 3cd748e13460..2584621c3b2d 100644 --- a/sound/soc/sof/ops.h +++ b/sound/soc/sof/ops.h @@ -3,7 +3,7 @@ * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. * - * Copyright(c) 2018 Intel Corporation. All rights reserved. + * Copyright(c) 2018 Intel Corporation * * Author: Liam Girdwood */ diff --git a/sound/soc/sof/pcm.c b/sound/soc/sof/pcm.c index cb774e011e31..baad4c1445aa 100644 --- a/sound/soc/sof/pcm.c +++ b/sound/soc/sof/pcm.c @@ -3,7 +3,7 @@ // This file is provided under a dual BSD/GPLv2 license. When using or // redistributing this file, you may do so under either license. // -// Copyright(c) 2018 Intel Corporation. All rights reserved. +// Copyright(c) 2018 Intel Corporation // // Author: Liam Girdwood // diff --git a/sound/soc/sof/pm.c b/sound/soc/sof/pm.c index 704b21413c71..8e3bcf602beb 100644 --- a/sound/soc/sof/pm.c +++ b/sound/soc/sof/pm.c @@ -3,7 +3,7 @@ // This file is provided under a dual BSD/GPLv2 license. When using or // redistributing this file, you may do so under either license. // -// Copyright(c) 2018 Intel Corporation. All rights reserved. +// Copyright(c) 2018 Intel Corporation // // Author: Liam Girdwood // diff --git a/sound/soc/sof/sof-acpi-dev.c b/sound/soc/sof/sof-acpi-dev.c index 2977f0a63fba..2d96d00f1c44 100644 --- a/sound/soc/sof/sof-acpi-dev.c +++ b/sound/soc/sof/sof-acpi-dev.c @@ -3,7 +3,7 @@ // This file is provided under a dual BSD/GPLv2 license. When using or // redistributing this file, you may do so under either license. // -// Copyright(c) 2018 Intel Corporation. All rights reserved. +// Copyright(c) 2018 Intel Corporation // // Author: Liam Girdwood // diff --git a/sound/soc/sof/sof-acpi-dev.h b/sound/soc/sof/sof-acpi-dev.h index 9bf8f75ceaae..89adfa507035 100644 --- a/sound/soc/sof/sof-acpi-dev.h +++ b/sound/soc/sof/sof-acpi-dev.h @@ -3,7 +3,7 @@ * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. * - * Copyright(c) 2021 Intel Corporation. All rights reserved. + * Copyright(c) 2021 Intel Corporation */ #ifndef __SOUND_SOC_SOF_ACPI_H diff --git a/sound/soc/sof/sof-audio.c b/sound/soc/sof/sof-audio.c index 32fef64ef10d..b3ac040811e7 100644 --- a/sound/soc/sof/sof-audio.c +++ b/sound/soc/sof/sof-audio.c @@ -3,7 +3,7 @@ // This file is provided under a dual BSD/GPLv2 license. When using or // redistributing this file, you may do so under either license. // -// Copyright(c) 2019 Intel Corporation. All rights reserved. +// Copyright(c) 2019 Intel Corporation // // Author: Ranjani Sridharan // diff --git a/sound/soc/sof/sof-audio.h b/sound/soc/sof/sof-audio.h index 2aeb269af752..ec2a3bb644d2 100644 --- a/sound/soc/sof/sof-audio.h +++ b/sound/soc/sof/sof-audio.h @@ -3,7 +3,7 @@ * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. * - * Copyright(c) 2019 Intel Corporation. All rights reserved. + * Copyright(c) 2019 Intel Corporation * * Author: Ranjani Sridharan */ diff --git a/sound/soc/sof/sof-client-ipc-flood-test.c b/sound/soc/sof/sof-client-ipc-flood-test.c index 1b2e9e25a836..435614926092 100644 --- a/sound/soc/sof/sof-client-ipc-flood-test.c +++ b/sound/soc/sof/sof-client-ipc-flood-test.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only // -// Copyright(c) 2022 Intel Corporation. All rights reserved. +// Copyright(c) 2022 Intel Corporation // // Authors: Ranjani Sridharan // Peter Ujfalusi diff --git a/sound/soc/sof/sof-client-ipc-kernel-injector.c b/sound/soc/sof/sof-client-ipc-kernel-injector.c index ad0ed2d570a9..6973b6690df4 100644 --- a/sound/soc/sof/sof-client-ipc-kernel-injector.c +++ b/sound/soc/sof/sof-client-ipc-kernel-injector.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only // -// Copyright(c) 2023 Google Inc. All rights reserved. +// Copyright(c) 2023 Google Inc // // Author: Curtis Malainey // diff --git a/sound/soc/sof/sof-client-ipc-msg-injector.c b/sound/soc/sof/sof-client-ipc-msg-injector.c index e249d3a9afb5..af22e6421029 100644 --- a/sound/soc/sof/sof-client-ipc-msg-injector.c +++ b/sound/soc/sof/sof-client-ipc-msg-injector.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only // -// Copyright(c) 2022 Intel Corporation. All rights reserved. +// Copyright(c) 2022 Intel Corporation // // Author: Peter Ujfalusi // diff --git a/sound/soc/sof/sof-client-probes-ipc3.c b/sound/soc/sof/sof-client-probes-ipc3.c index 5e8eb19582a8..816df745c9af 100644 --- a/sound/soc/sof/sof-client-probes-ipc3.c +++ b/sound/soc/sof/sof-client-probes-ipc3.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only // -// Copyright(c) 2019-2022 Intel Corporation. All rights reserved. +// Copyright(c) 2019-2022 Intel Corporation // // Author: Cezary Rojewski // diff --git a/sound/soc/sof/sof-client-probes-ipc4.c b/sound/soc/sof/sof-client-probes-ipc4.c index c56a85854d92..796eac0a2e74 100644 --- a/sound/soc/sof/sof-client-probes-ipc4.c +++ b/sound/soc/sof/sof-client-probes-ipc4.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only // -// Copyright(c) 2019-2022 Intel Corporation. All rights reserved. +// Copyright(c) 2019-2022 Intel Corporation // // Author: Jyri Sarha // diff --git a/sound/soc/sof/sof-client-probes.c b/sound/soc/sof/sof-client-probes.c index 30f771ac7bbf..b8f297307565 100644 --- a/sound/soc/sof/sof-client-probes.c +++ b/sound/soc/sof/sof-client-probes.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only // -// Copyright(c) 2019-2022 Intel Corporation. All rights reserved. +// Copyright(c) 2019-2022 Intel Corporation // // Author: Cezary Rojewski // diff --git a/sound/soc/sof/sof-client.c b/sound/soc/sof/sof-client.c index 54dca91255a0..99f74def4ab6 100644 --- a/sound/soc/sof/sof-client.c +++ b/sound/soc/sof/sof-client.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only // -// Copyright(c) 2022 Intel Corporation. All rights reserved. +// Copyright(c) 2022 Intel Corporation // // Authors: Ranjani Sridharan // Peter Ujfalusi diff --git a/sound/soc/sof/sof-pci-dev.c b/sound/soc/sof/sof-pci-dev.c index aab5c900cecf..4365405783e6 100644 --- a/sound/soc/sof/sof-pci-dev.c +++ b/sound/soc/sof/sof-pci-dev.c @@ -3,7 +3,7 @@ // This file is provided under a dual BSD/GPLv2 license. When using or // redistributing this file, you may do so under either license. // -// Copyright(c) 2018 Intel Corporation. All rights reserved. +// Copyright(c) 2018 Intel Corporation // // Author: Liam Girdwood // diff --git a/sound/soc/sof/sof-pci-dev.h b/sound/soc/sof/sof-pci-dev.h index 81155a59e63a..c90e6276c83b 100644 --- a/sound/soc/sof/sof-pci-dev.h +++ b/sound/soc/sof/sof-pci-dev.h @@ -3,7 +3,7 @@ * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. * - * Copyright(c) 2021 Intel Corporation. All rights reserved. + * Copyright(c) 2021 Intel Corporation */ #ifndef __SOUND_SOC_SOF_PCI_H diff --git a/sound/soc/sof/sof-priv.h b/sound/soc/sof/sof-priv.h index d3c436f82604..4d6a1517f9b3 100644 --- a/sound/soc/sof/sof-priv.h +++ b/sound/soc/sof/sof-priv.h @@ -3,7 +3,7 @@ * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. * - * Copyright(c) 2018 Intel Corporation. All rights reserved. + * Copyright(c) 2018 Intel Corporation * * Author: Liam Girdwood */ diff --git a/sound/soc/sof/sof-utils.c b/sound/soc/sof/sof-utils.c index b6345a7345af..cad041bf56cc 100644 --- a/sound/soc/sof/sof-utils.c +++ b/sound/soc/sof/sof-utils.c @@ -3,7 +3,7 @@ // This file is provided under a dual BSD/GPLv2 license. When using or // redistributing this file, you may do so under either license. // -// Copyright(c) 2018-2022 Intel Corporation. All rights reserved. +// Copyright(c) 2018-2022 Intel Corporation // // Author: Keyon Jie // diff --git a/sound/soc/sof/sof-utils.h b/sound/soc/sof/sof-utils.h index 6f902893807e..9ac6de9a6d6a 100644 --- a/sound/soc/sof/sof-utils.h +++ b/sound/soc/sof/sof-utils.h @@ -3,7 +3,7 @@ * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. * - * Copyright(c) 2022 Intel Corporation. All rights reserved. + * Copyright(c) 2022 Intel Corporation */ #ifndef __SOC_SOF_UTILS_H diff --git a/sound/soc/sof/stream-ipc.c b/sound/soc/sof/stream-ipc.c index 216b454f6b94..eb71303aa24c 100644 --- a/sound/soc/sof/stream-ipc.c +++ b/sound/soc/sof/stream-ipc.c @@ -3,7 +3,7 @@ // This file is provided under a dual BSD/GPLv2 license. When using or // redistributing this file, you may do so under either license. // -// Copyright(c) 2019 Intel Corporation. All rights reserved. +// Copyright(c) 2019 Intel Corporation // // Authors: Guennadi Liakhovetski diff --git a/sound/soc/sof/topology.c b/sound/soc/sof/topology.c index ec931a26b54f..da182314aa87 100644 --- a/sound/soc/sof/topology.c +++ b/sound/soc/sof/topology.c @@ -3,7 +3,7 @@ // This file is provided under a dual BSD/GPLv2 license. When using or // redistributing this file, you may do so under either license. // -// Copyright(c) 2018 Intel Corporation. All rights reserved. +// Copyright(c) 2018 Intel Corporation // // Author: Liam Girdwood // diff --git a/sound/soc/sof/trace.c b/sound/soc/sof/trace.c index b2ab51e5214a..fe6c67c01b0d 100644 --- a/sound/soc/sof/trace.c +++ b/sound/soc/sof/trace.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only // -// Copyright(c) 2022 Intel Corporation. All rights reserved. +// Copyright(c) 2022 Intel Corporation #include "sof-priv.h" diff --git a/sound/soc/sof/xtensa/core.c b/sound/soc/sof/xtensa/core.c index 7c91a919eadc..ccbc3fcdadd5 100644 --- a/sound/soc/sof/xtensa/core.c +++ b/sound/soc/sof/xtensa/core.c @@ -3,7 +3,7 @@ // This file is provided under a dual BSD/GPLv2 license. When using or // redistributing this file, you may do so under either license. // -// Copyright(c) 2018 Intel Corporation. All rights reserved. +// Copyright(c) 2018 Intel Corporation // // Author: Pan Xiuli // -- cgit v1.2.3 From 0e0440535de8e7c5c0ae0bd469b6ae184f9c732c Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Fri, 3 May 2024 09:03:52 -0500 Subject: ASoC: Intel: boards: clarify Copyright information MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit For some reason a number of files included the "All rights reserved" statement. Good old copy-paste made sure this mistake proliferated. Remove the "All rights reserved" in all Intel-copyright to align with internal guidance. Acked-by: Cezary Rojewski Signed-off-by: Pierre-Louis Bossart Reviewed-by: Bard Liao Reviewed-by: Péter Ujfalusi Link: https://lore.kernel.org/r/20240503140359.259762-3-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/intel/boards/bdw_rt286.c | 2 +- sound/soc/intel/boards/bxt_da7219_max98357a.c | 2 +- sound/soc/intel/boards/bxt_rt298.c | 2 +- sound/soc/intel/boards/hda_dsp_common.c | 2 +- sound/soc/intel/boards/hsw_rt5640.c | 2 +- sound/soc/intel/boards/kbl_rt5663_max98927.c | 2 +- sound/soc/intel/boards/kbl_rt5663_rt5514_max98927.c | 2 +- sound/soc/intel/boards/skl_nau88l25_max98357a.c | 2 +- sound/soc/intel/boards/skl_nau88l25_ssm4567.c | 4 ++-- sound/soc/intel/boards/skl_rt286.c | 4 ++-- sound/soc/intel/boards/sof_board_helpers.c | 2 +- sound/soc/intel/boards/sof_maxim_common.c | 2 +- sound/soc/intel/boards/sof_realtek_common.c | 2 +- sound/soc/intel/boards/sof_ssp_amp.c | 2 +- sound/soc/intel/common/soc-acpi-intel-ssp-common.c | 2 +- 15 files changed, 17 insertions(+), 17 deletions(-) diff --git a/sound/soc/intel/boards/bdw_rt286.c b/sound/soc/intel/boards/bdw_rt286.c index 7f20159c23e5..58db09d9b6e1 100644 --- a/sound/soc/intel/boards/bdw_rt286.c +++ b/sound/soc/intel/boards/bdw_rt286.c @@ -2,7 +2,7 @@ /* * Sound card driver for Intel Broadwell Wildcat Point with Realtek 286 * - * Copyright (C) 2013, Intel Corporation. All rights reserved. + * Copyright (C) 2013, Intel Corporation */ #include diff --git a/sound/soc/intel/boards/bxt_da7219_max98357a.c b/sound/soc/intel/boards/bxt_da7219_max98357a.c index 57e75f87bea6..e1082bfe5ca9 100644 --- a/sound/soc/intel/boards/bxt_da7219_max98357a.c +++ b/sound/soc/intel/boards/bxt_da7219_max98357a.c @@ -2,7 +2,7 @@ /* * Intel Broxton-P I2S Machine Driver * - * Copyright (C) 2016, Intel Corporation. All rights reserved. + * Copyright (C) 2016, Intel Corporation * * Modified from: * Intel Skylake I2S Machine driver diff --git a/sound/soc/intel/boards/bxt_rt298.c b/sound/soc/intel/boards/bxt_rt298.c index afc499be8db2..dce6a2086f2a 100644 --- a/sound/soc/intel/boards/bxt_rt298.c +++ b/sound/soc/intel/boards/bxt_rt298.c @@ -2,7 +2,7 @@ /* * Intel Broxton-P I2S Machine Driver * - * Copyright (C) 2014-2016, Intel Corporation. All rights reserved. + * Copyright (C) 2014-2016, Intel Corporation * * Modified from: * Intel Skylake I2S Machine driver diff --git a/sound/soc/intel/boards/hda_dsp_common.c b/sound/soc/intel/boards/hda_dsp_common.c index 04b7d4f7f9e2..fda5a92b0006 100644 --- a/sound/soc/intel/boards/hda_dsp_common.c +++ b/sound/soc/intel/boards/hda_dsp_common.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only // -// Copyright(c) 2019 Intel Corporation. All rights reserved. +// Copyright(c) 2019 Intel Corporation #include #include diff --git a/sound/soc/intel/boards/hsw_rt5640.c b/sound/soc/intel/boards/hsw_rt5640.c index 2a2fe27dff0e..1826a4dfd0f3 100644 --- a/sound/soc/intel/boards/hsw_rt5640.c +++ b/sound/soc/intel/boards/hsw_rt5640.c @@ -2,7 +2,7 @@ /* * Sound card driver for Intel Haswell Lynx Point with Realtek 5640 * - * Copyright (C) 2013, Intel Corporation. All rights reserved. + * Copyright (C) 2013, Intel Corporation */ #include diff --git a/sound/soc/intel/boards/kbl_rt5663_max98927.c b/sound/soc/intel/boards/kbl_rt5663_max98927.c index 646e8ff8e961..e16c42e81eca 100644 --- a/sound/soc/intel/boards/kbl_rt5663_max98927.c +++ b/sound/soc/intel/boards/kbl_rt5663_max98927.c @@ -3,7 +3,7 @@ * Intel Kabylake I2S Machine Driver with MAXIM98927 * and RT5663 Codecs * - * Copyright (C) 2017, Intel Corporation. All rights reserved. + * Copyright (C) 2017, Intel Corporation * * Modified from: * Intel Skylake I2S Machine driver diff --git a/sound/soc/intel/boards/kbl_rt5663_rt5514_max98927.c b/sound/soc/intel/boards/kbl_rt5663_rt5514_max98927.c index 924d5d1de03a..a9501cd106ff 100644 --- a/sound/soc/intel/boards/kbl_rt5663_rt5514_max98927.c +++ b/sound/soc/intel/boards/kbl_rt5663_rt5514_max98927.c @@ -3,7 +3,7 @@ * Intel Kabylake I2S Machine Driver with MAXIM98927 * RT5514 and RT5663 Codecs * - * Copyright (C) 2017, Intel Corporation. All rights reserved. + * Copyright (C) 2017, Intel Corporation * * Modified from: * Intel Kabylake I2S Machine driver supporting MAXIM98927 and diff --git a/sound/soc/intel/boards/skl_nau88l25_max98357a.c b/sound/soc/intel/boards/skl_nau88l25_max98357a.c index e4630c33176e..91fe9834aab4 100644 --- a/sound/soc/intel/boards/skl_nau88l25_max98357a.c +++ b/sound/soc/intel/boards/skl_nau88l25_max98357a.c @@ -3,7 +3,7 @@ * Intel Skylake I2S Machine Driver with MAXIM98357A * and NAU88L25 * - * Copyright (C) 2015, Intel Corporation. All rights reserved. + * Copyright (C) 2015, Intel Corporation */ #include diff --git a/sound/soc/intel/boards/skl_nau88l25_ssm4567.c b/sound/soc/intel/boards/skl_nau88l25_ssm4567.c index fadc25a536b4..d53bf3516c0d 100644 --- a/sound/soc/intel/boards/skl_nau88l25_ssm4567.c +++ b/sound/soc/intel/boards/skl_nau88l25_ssm4567.c @@ -2,12 +2,12 @@ /* * Intel Skylake I2S Machine Driver for NAU88L25+SSM4567 * - * Copyright (C) 2015, Intel Corporation. All rights reserved. + * Copyright (C) 2015, Intel Corporation * * Modified from: * Intel Skylake I2S Machine Driver for NAU88L25 and SSM4567 * - * Copyright (C) 2015, Intel Corporation. All rights reserved. + * Copyright (C) 2015, Intel Corporation */ #include diff --git a/sound/soc/intel/boards/skl_rt286.c b/sound/soc/intel/boards/skl_rt286.c index 9a8044274908..3ea03f814403 100644 --- a/sound/soc/intel/boards/skl_rt286.c +++ b/sound/soc/intel/boards/skl_rt286.c @@ -2,12 +2,12 @@ /* * Intel Skylake I2S Machine Driver * - * Copyright (C) 2014-2015, Intel Corporation. All rights reserved. + * Copyright (C) 2014-2015, Intel Corporation * * Modified from: * Intel Broadwell Wildcatpoint SST Audio * - * Copyright (C) 2013, Intel Corporation. All rights reserved. + * Copyright (C) 2013, Intel Corporation */ #include diff --git a/sound/soc/intel/boards/sof_board_helpers.c b/sound/soc/intel/boards/sof_board_helpers.c index eb140e13153f..7519c545cbe2 100644 --- a/sound/soc/intel/boards/sof_board_helpers.c +++ b/sound/soc/intel/boards/sof_board_helpers.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only // -// Copyright(c) 2023 Intel Corporation. All rights reserved. +// Copyright(c) 2023 Intel Corporation #include #include "../common/soc-intel-quirks.h" diff --git a/sound/soc/intel/boards/sof_maxim_common.c b/sound/soc/intel/boards/sof_maxim_common.c index bb12aab15ad5..7e1f485dce7a 100644 --- a/sound/soc/intel/boards/sof_maxim_common.c +++ b/sound/soc/intel/boards/sof_maxim_common.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only // -// Copyright(c) 2020 Intel Corporation. All rights reserved. +// Copyright(c) 2020 Intel Corporation #include #include #include diff --git a/sound/soc/intel/boards/sof_realtek_common.c b/sound/soc/intel/boards/sof_realtek_common.c index cb1c21d822f6..6915ff8b8716 100644 --- a/sound/soc/intel/boards/sof_realtek_common.c +++ b/sound/soc/intel/boards/sof_realtek_common.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only // -// Copyright(c) 2020 Intel Corporation. All rights reserved. +// Copyright(c) 2020 Intel Corporation #include #include diff --git a/sound/soc/intel/boards/sof_ssp_amp.c b/sound/soc/intel/boards/sof_ssp_amp.c index 206c9b723805..f51f1008e016 100644 --- a/sound/soc/intel/boards/sof_ssp_amp.c +++ b/sound/soc/intel/boards/sof_ssp_amp.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only // -// Copyright(c) 2022 Intel Corporation. All rights reserved. +// Copyright(c) 2022 Intel Corporation /* * sof_ssp_amp.c - ASoc Machine driver for Intel platforms diff --git a/sound/soc/intel/common/soc-acpi-intel-ssp-common.c b/sound/soc/intel/common/soc-acpi-intel-ssp-common.c index a887f019afe2..75d0b931d895 100644 --- a/sound/soc/intel/common/soc-acpi-intel-ssp-common.c +++ b/sound/soc/intel/common/soc-acpi-intel-ssp-common.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only // -// Copyright(c) 2023 Intel Corporation. All rights reserved. +// Copyright(c) 2023 Intel Corporation #include #include -- cgit v1.2.3 From 5cf4ffa4113da2e797c8281bac2838d29f5a03bf Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Fri, 3 May 2024 09:03:53 -0500 Subject: ASoC: Intel: common: clarify Copyright information MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit For some reason a number of files included the "All rights reserved" statement. Good old copy-paste made sure this mistake proliferated. Remove the "All rights reserved" in all Intel-copyright to align with internal guidance. Acked-by: Cezary Rojewski Signed-off-by: Pierre-Louis Bossart Reviewed-by: Bard Liao Reviewed-by: Péter Ujfalusi Link: https://lore.kernel.org/r/20240503140359.259762-4-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/intel/common/soc-acpi-intel-lnl-match.c | 2 +- sound/soc/intel/common/sst-dsp-priv.h | 2 +- sound/soc/intel/common/sst-dsp.c | 2 +- sound/soc/intel/common/sst-dsp.h | 2 +- sound/soc/intel/common/sst-ipc.c | 2 +- sound/soc/intel/common/sst-ipc.h | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/sound/soc/intel/common/soc-acpi-intel-lnl-match.c b/sound/soc/intel/common/soc-acpi-intel-lnl-match.c index 0318c1a46f3c..0c08859c4773 100644 --- a/sound/soc/intel/common/soc-acpi-intel-lnl-match.c +++ b/sound/soc/intel/common/soc-acpi-intel-lnl-match.c @@ -2,7 +2,7 @@ /* * soc-acpi-intel-lnl-match.c - tables and support for LNL ACPI enumeration. * - * Copyright (c) 2023, Intel Corporation. All rights reserved. + * Copyright (c) 2023, Intel Corporation * */ diff --git a/sound/soc/intel/common/sst-dsp-priv.h b/sound/soc/intel/common/sst-dsp-priv.h index de2b44568feb..de32bb9afccb 100644 --- a/sound/soc/intel/common/sst-dsp-priv.h +++ b/sound/soc/intel/common/sst-dsp-priv.h @@ -2,7 +2,7 @@ /* * Intel Smart Sound Technology * - * Copyright (C) 2013, Intel Corporation. All rights reserved. + * Copyright (C) 2013, Intel Corporation */ #ifndef __SOUND_SOC_SST_DSP_PRIV_H diff --git a/sound/soc/intel/common/sst-dsp.c b/sound/soc/intel/common/sst-dsp.c index 229d09d61afb..cdd2f7cf50ae 100644 --- a/sound/soc/intel/common/sst-dsp.c +++ b/sound/soc/intel/common/sst-dsp.c @@ -2,7 +2,7 @@ /* * Intel Smart Sound Technology (SST) DSP Core Driver * - * Copyright (C) 2013, Intel Corporation. All rights reserved. + * Copyright (C) 2013, Intel Corporation */ #include diff --git a/sound/soc/intel/common/sst-dsp.h b/sound/soc/intel/common/sst-dsp.h index f111fd3f334b..998b1a052281 100644 --- a/sound/soc/intel/common/sst-dsp.h +++ b/sound/soc/intel/common/sst-dsp.h @@ -2,7 +2,7 @@ /* * Intel Smart Sound Technology (SST) Core * - * Copyright (C) 2013, Intel Corporation. All rights reserved. + * Copyright (C) 2013, Intel Corporation */ #ifndef __SOUND_SOC_SST_DSP_H diff --git a/sound/soc/intel/common/sst-ipc.c b/sound/soc/intel/common/sst-ipc.c index 89c10724d2a3..6b2c83f9f010 100644 --- a/sound/soc/intel/common/sst-ipc.c +++ b/sound/soc/intel/common/sst-ipc.c @@ -2,7 +2,7 @@ /* * Intel SST generic IPC Support * - * Copyright (C) 2015, Intel Corporation. All rights reserved. + * Copyright (C) 2015, Intel Corporation */ #include diff --git a/sound/soc/intel/common/sst-ipc.h b/sound/soc/intel/common/sst-ipc.h index 77d651e888f9..86d44ceadc92 100644 --- a/sound/soc/intel/common/sst-ipc.h +++ b/sound/soc/intel/common/sst-ipc.h @@ -2,7 +2,7 @@ /* * Intel SST generic IPC Support * - * Copyright (C) 2015, Intel Corporation. All rights reserved. + * Copyright (C) 2015, Intel Corporation */ #ifndef __SST_GENERIC_IPC_H -- cgit v1.2.3 From 884077bd7110db61eddff086f9ab7f2c6748d169 Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Fri, 3 May 2024 09:03:54 -0500 Subject: ASoC: codecs: Intel: clarify Copyright information MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit For some reason a number of files included the "All rights reserved" statement. Good old copy-paste made sure this mistake proliferated. Remove the "All rights reserved" in all Intel-copyright to align with internal guidance. Acked-by: Cezary Rojewski Signed-off-by: Pierre-Louis Bossart Reviewed-by: Bard Liao Reviewed-by: Péter Ujfalusi Link: https://lore.kernel.org/r/20240503140359.259762-5-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/codecs/hda-dai.c | 2 +- sound/soc/codecs/hda.c | 2 +- sound/soc/codecs/hda.h | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/sound/soc/codecs/hda-dai.c b/sound/soc/codecs/hda-dai.c index 7bd7ddcd810f..b9caae7e4817 100644 --- a/sound/soc/codecs/hda-dai.c +++ b/sound/soc/codecs/hda-dai.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0 // -// Copyright(c) 2021-2022 Intel Corporation. All rights reserved. +// Copyright(c) 2021-2022 Intel Corporation // // Author: Cezary Rojewski // diff --git a/sound/soc/codecs/hda.c b/sound/soc/codecs/hda.c index 5a58723dc0e9..ddc00927313c 100644 --- a/sound/soc/codecs/hda.c +++ b/sound/soc/codecs/hda.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0 // -// Copyright(c) 2021-2022 Intel Corporation. All rights reserved. +// Copyright(c) 2021-2022 Intel Corporation // // Author: Cezary Rojewski // diff --git a/sound/soc/codecs/hda.h b/sound/soc/codecs/hda.h index 78a2be4945b1..59308cc6afef 100644 --- a/sound/soc/codecs/hda.h +++ b/sound/soc/codecs/hda.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0 */ /* - * Copyright(c) 2021-2022 Intel Corporation. All rights reserved. + * Copyright(c) 2021-2022 Intel Corporation * * Author: Cezary Rojewski */ -- cgit v1.2.3 From 618ae0d7e740d212044ba25d0f1013374eda448a Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Fri, 3 May 2024 09:03:55 -0500 Subject: ASoC: Intel: catpt: clarify Copyright information MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit For some reason a number of files included the "All rights reserved" statement. Good old copy-paste made sure this mistake proliferated. Remove the "All rights reserved" in all Intel-copyright to align with internal guidance. Acked-by: Cezary Rojewski Signed-off-by: Pierre-Louis Bossart Reviewed-by: Bard Liao Reviewed-by: Péter Ujfalusi Link: https://lore.kernel.org/r/20240503140359.259762-6-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/intel/catpt/core.h | 2 +- sound/soc/intel/catpt/device.c | 2 +- sound/soc/intel/catpt/dsp.c | 2 +- sound/soc/intel/catpt/ipc.c | 2 +- sound/soc/intel/catpt/loader.c | 2 +- sound/soc/intel/catpt/messages.c | 2 +- sound/soc/intel/catpt/messages.h | 2 +- sound/soc/intel/catpt/pcm.c | 2 +- sound/soc/intel/catpt/registers.h | 2 +- sound/soc/intel/catpt/sysfs.c | 2 +- sound/soc/intel/catpt/trace.h | 2 +- 11 files changed, 11 insertions(+), 11 deletions(-) diff --git a/sound/soc/intel/catpt/core.h b/sound/soc/intel/catpt/core.h index a64a0a77dcb7..c01d27e9fd88 100644 --- a/sound/soc/intel/catpt/core.h +++ b/sound/soc/intel/catpt/core.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright(c) 2020 Intel Corporation. All rights reserved. + * Copyright(c) 2020 Intel Corporation * * Author: Cezary Rojewski */ diff --git a/sound/soc/intel/catpt/device.c b/sound/soc/intel/catpt/device.c index cac3dffbd0d9..2e1fa79a04d4 100644 --- a/sound/soc/intel/catpt/device.c +++ b/sound/soc/intel/catpt/device.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only // -// Copyright(c) 2020 Intel Corporation. All rights reserved. +// Copyright(c) 2020 Intel Corporation // // Author: Cezary Rojewski // diff --git a/sound/soc/intel/catpt/dsp.c b/sound/soc/intel/catpt/dsp.c index 5454c6d9ab5b..5993819cc58a 100644 --- a/sound/soc/intel/catpt/dsp.c +++ b/sound/soc/intel/catpt/dsp.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only // -// Copyright(c) 2020 Intel Corporation. All rights reserved. +// Copyright(c) 2020 Intel Corporation // // Author: Cezary Rojewski // diff --git a/sound/soc/intel/catpt/ipc.c b/sound/soc/intel/catpt/ipc.c index 5b718a846fda..d26863249097 100644 --- a/sound/soc/intel/catpt/ipc.c +++ b/sound/soc/intel/catpt/ipc.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only // -// Copyright(c) 2020 Intel Corporation. All rights reserved. +// Copyright(c) 2020 Intel Corporation // // Author: Cezary Rojewski // diff --git a/sound/soc/intel/catpt/loader.c b/sound/soc/intel/catpt/loader.c index ff7b8f0d34ac..696d84314eeb 100644 --- a/sound/soc/intel/catpt/loader.c +++ b/sound/soc/intel/catpt/loader.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only // -// Copyright(c) 2020 Intel Corporation. All rights reserved. +// Copyright(c) 2020 Intel Corporation // // Author: Cezary Rojewski // diff --git a/sound/soc/intel/catpt/messages.c b/sound/soc/intel/catpt/messages.c index a793d114afa4..30eec2de4dc1 100644 --- a/sound/soc/intel/catpt/messages.c +++ b/sound/soc/intel/catpt/messages.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only // -// Copyright(c) 2020 Intel Corporation. All rights reserved. +// Copyright(c) 2020 Intel Corporation // // Author: Cezary Rojewski // diff --git a/sound/soc/intel/catpt/messages.h b/sound/soc/intel/catpt/messages.h index c17e948d9f52..a634943eb669 100644 --- a/sound/soc/intel/catpt/messages.h +++ b/sound/soc/intel/catpt/messages.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright(c) 2020 Intel Corporation. All rights reserved. + * Copyright(c) 2020 Intel Corporation * * Author: Cezary Rojewski */ diff --git a/sound/soc/intel/catpt/pcm.c b/sound/soc/intel/catpt/pcm.c index 3daf5eb37f7b..81a2f0339e05 100644 --- a/sound/soc/intel/catpt/pcm.c +++ b/sound/soc/intel/catpt/pcm.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only // -// Copyright(c) 2020 Intel Corporation. All rights reserved. +// Copyright(c) 2020 Intel Corporation // // Author: Cezary Rojewski // diff --git a/sound/soc/intel/catpt/registers.h b/sound/soc/intel/catpt/registers.h index 47280d82842e..6c1ad28c6d69 100644 --- a/sound/soc/intel/catpt/registers.h +++ b/sound/soc/intel/catpt/registers.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright(c) 2020 Intel Corporation. All rights reserved. + * Copyright(c) 2020 Intel Corporation * * Author: Cezary Rojewski */ diff --git a/sound/soc/intel/catpt/sysfs.c b/sound/soc/intel/catpt/sysfs.c index 9b6d2d93a2e7..936ac9d503ff 100644 --- a/sound/soc/intel/catpt/sysfs.c +++ b/sound/soc/intel/catpt/sysfs.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only // -// Copyright(c) 2020 Intel Corporation. All rights reserved. +// Copyright(c) 2020 Intel Corporation // // Author: Cezary Rojewski // diff --git a/sound/soc/intel/catpt/trace.h b/sound/soc/intel/catpt/trace.h index bb3d627dbeaf..010f57b6a7a8 100644 --- a/sound/soc/intel/catpt/trace.h +++ b/sound/soc/intel/catpt/trace.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright(c) 2020 Intel Corporation. All rights reserved. + * Copyright(c) 2020 Intel Corporation * * Author: Cezary Rojewski */ -- cgit v1.2.3 From 94001147a09ffeaf0657db7c189af77cda427f30 Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Fri, 3 May 2024 09:03:56 -0500 Subject: ASoC: Intel: avs: clarify Copyright information MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit For some reason a number of files included the "All rights reserved" statement. Good old copy-paste made sure this mistake proliferated. Remove the "All rights reserved" in all Intel-copyright to align with internal guidance. Acked-by: Cezary Rojewski Signed-off-by: Pierre-Louis Bossart Reviewed-by: Bard Liao Reviewed-by: Péter Ujfalusi Link: https://lore.kernel.org/r/20240503140359.259762-7-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/intel/avs/apl.c | 2 +- sound/soc/intel/avs/avs.h | 2 +- sound/soc/intel/avs/board_selection.c | 2 +- sound/soc/intel/avs/boards/da7219.c | 2 +- sound/soc/intel/avs/boards/dmic.c | 2 +- sound/soc/intel/avs/boards/es8336.c | 2 +- sound/soc/intel/avs/boards/hdaudio.c | 2 +- sound/soc/intel/avs/boards/i2s_test.c | 2 +- sound/soc/intel/avs/boards/max98357a.c | 2 +- sound/soc/intel/avs/boards/max98373.c | 2 +- sound/soc/intel/avs/boards/max98927.c | 2 +- sound/soc/intel/avs/boards/nau8825.c | 2 +- sound/soc/intel/avs/boards/probe.c | 2 +- sound/soc/intel/avs/boards/rt274.c | 2 +- sound/soc/intel/avs/boards/rt286.c | 2 +- sound/soc/intel/avs/boards/rt298.c | 2 +- sound/soc/intel/avs/boards/rt5514.c | 2 +- sound/soc/intel/avs/boards/rt5663.c | 2 +- sound/soc/intel/avs/boards/rt5682.c | 2 +- sound/soc/intel/avs/boards/ssm4567.c | 2 +- sound/soc/intel/avs/cldma.c | 2 +- sound/soc/intel/avs/cldma.h | 2 +- sound/soc/intel/avs/cnl.c | 2 +- sound/soc/intel/avs/control.c | 2 +- sound/soc/intel/avs/control.h | 2 +- sound/soc/intel/avs/core.c | 2 +- sound/soc/intel/avs/debugfs.c | 2 +- sound/soc/intel/avs/dsp.c | 2 +- sound/soc/intel/avs/icl.c | 2 +- sound/soc/intel/avs/ipc.c | 2 +- sound/soc/intel/avs/loader.c | 2 +- sound/soc/intel/avs/messages.c | 2 +- sound/soc/intel/avs/messages.h | 2 +- sound/soc/intel/avs/path.c | 2 +- sound/soc/intel/avs/path.h | 2 +- sound/soc/intel/avs/pcm.c | 2 +- sound/soc/intel/avs/probes.c | 2 +- sound/soc/intel/avs/registers.h | 2 +- sound/soc/intel/avs/skl.c | 2 +- sound/soc/intel/avs/sysfs.c | 2 +- sound/soc/intel/avs/tgl.c | 2 +- sound/soc/intel/avs/topology.c | 2 +- sound/soc/intel/avs/topology.h | 2 +- sound/soc/intel/avs/trace.c | 2 +- sound/soc/intel/avs/utils.c | 2 +- sound/soc/intel/avs/utils.h | 2 +- 46 files changed, 46 insertions(+), 46 deletions(-) diff --git a/sound/soc/intel/avs/apl.c b/sound/soc/intel/avs/apl.c index bf97e4e428a4..27516ef57185 100644 --- a/sound/soc/intel/avs/apl.c +++ b/sound/soc/intel/avs/apl.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only // -// Copyright(c) 2021-2022 Intel Corporation. All rights reserved. +// Copyright(c) 2021-2022 Intel Corporation // // Authors: Cezary Rojewski // Amadeusz Slawinski diff --git a/sound/soc/intel/avs/avs.h b/sound/soc/intel/avs/avs.h index 101b1902a715..eca6ec0428bb 100644 --- a/sound/soc/intel/avs/avs.h +++ b/sound/soc/intel/avs/avs.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright(c) 2021-2022 Intel Corporation. All rights reserved. + * Copyright(c) 2021-2022 Intel Corporation * * Authors: Cezary Rojewski * Amadeusz Slawinski diff --git a/sound/soc/intel/avs/board_selection.c b/sound/soc/intel/avs/board_selection.c index 290ea314ace8..0266edeafc19 100644 --- a/sound/soc/intel/avs/board_selection.c +++ b/sound/soc/intel/avs/board_selection.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only // -// Copyright(c) 2021-2022 Intel Corporation. All rights reserved. +// Copyright(c) 2021-2022 Intel Corporation // // Authors: Cezary Rojewski // Amadeusz Slawinski diff --git a/sound/soc/intel/avs/boards/da7219.c b/sound/soc/intel/avs/boards/da7219.c index fc072dc58968..80c0a1a95654 100644 --- a/sound/soc/intel/avs/boards/da7219.c +++ b/sound/soc/intel/avs/boards/da7219.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only // -// Copyright(c) 2021-2022 Intel Corporation. All rights reserved. +// Copyright(c) 2021-2022 Intel Corporation // // Author: Cezary Rojewski // diff --git a/sound/soc/intel/avs/boards/dmic.c b/sound/soc/intel/avs/boards/dmic.c index d9e5e85f5233..a31aa471a1c2 100644 --- a/sound/soc/intel/avs/boards/dmic.c +++ b/sound/soc/intel/avs/boards/dmic.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only // -// Copyright(c) 2021-2022 Intel Corporation. All rights reserved. +// Copyright(c) 2021-2022 Intel Corporation // // Authors: Cezary Rojewski // Amadeusz Slawinski diff --git a/sound/soc/intel/avs/boards/es8336.c b/sound/soc/intel/avs/boards/es8336.c index ff3bd1513269..e19ad8deed5c 100644 --- a/sound/soc/intel/avs/boards/es8336.c +++ b/sound/soc/intel/avs/boards/es8336.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only // -// Copyright(c) 2023 Intel Corporation. All rights reserved. +// Copyright(c) 2023 Intel Corporation // // Authors: Cezary Rojewski // Amadeusz Slawinski diff --git a/sound/soc/intel/avs/boards/hdaudio.c b/sound/soc/intel/avs/boards/hdaudio.c index 4433175814f8..430c070a1a0e 100644 --- a/sound/soc/intel/avs/boards/hdaudio.c +++ b/sound/soc/intel/avs/boards/hdaudio.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only // -// Copyright(c) 2021-2022 Intel Corporation. All rights reserved. +// Copyright(c) 2021-2022 Intel Corporation // // Authors: Cezary Rojewski // Amadeusz Slawinski diff --git a/sound/soc/intel/avs/boards/i2s_test.c b/sound/soc/intel/avs/boards/i2s_test.c index d41955685664..7e6c8d9c900b 100644 --- a/sound/soc/intel/avs/boards/i2s_test.c +++ b/sound/soc/intel/avs/boards/i2s_test.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only // -// Copyright(c) 2021-2022 Intel Corporation. All rights reserved. +// Copyright(c) 2021-2022 Intel Corporation // // Authors: Cezary Rojewski // Amadeusz Slawinski diff --git a/sound/soc/intel/avs/boards/max98357a.c b/sound/soc/intel/avs/boards/max98357a.c index 1ff85e4d8e16..8d550e82b46a 100644 --- a/sound/soc/intel/avs/boards/max98357a.c +++ b/sound/soc/intel/avs/boards/max98357a.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only // -// Copyright(c) 2021-2022 Intel Corporation. All rights reserved. +// Copyright(c) 2021-2022 Intel Corporation // // Authors: Cezary Rojewski // Amadeusz Slawinski diff --git a/sound/soc/intel/avs/boards/max98373.c b/sound/soc/intel/avs/boards/max98373.c index 8d31586b73ea..fdef5a008daf 100644 --- a/sound/soc/intel/avs/boards/max98373.c +++ b/sound/soc/intel/avs/boards/max98373.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only // -// Copyright(c) 2022 Intel Corporation. All rights reserved. +// Copyright(c) 2022 Intel Corporation // // Authors: Cezary Rojewski // Amadeusz Slawinski diff --git a/sound/soc/intel/avs/boards/max98927.c b/sound/soc/intel/avs/boards/max98927.c index 572ec58073d0..082f311d8b84 100644 --- a/sound/soc/intel/avs/boards/max98927.c +++ b/sound/soc/intel/avs/boards/max98927.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only // -// Copyright(c) 2022 Intel Corporation. All rights reserved. +// Copyright(c) 2022 Intel Corporation // // Authors: Cezary Rojewski // Amadeusz Slawinski diff --git a/sound/soc/intel/avs/boards/nau8825.c b/sound/soc/intel/avs/boards/nau8825.c index 3164745b1516..8dee6801fe51 100644 --- a/sound/soc/intel/avs/boards/nau8825.c +++ b/sound/soc/intel/avs/boards/nau8825.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only // -// Copyright(c) 2021-2022 Intel Corporation. All rights reserved. +// Copyright(c) 2021-2022 Intel Corporation // // Authors: Cezary Rojewski // Amadeusz Slawinski diff --git a/sound/soc/intel/avs/boards/probe.c b/sound/soc/intel/avs/boards/probe.c index 8be6887bbc6e..1cdc285ab810 100644 --- a/sound/soc/intel/avs/boards/probe.c +++ b/sound/soc/intel/avs/boards/probe.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only // -// Copyright(c) 2021-2022 Intel Corporation. All rights reserved. +// Copyright(c) 2021-2022 Intel Corporation // // Authors: Cezary Rojewski // Amadeusz Slawinski diff --git a/sound/soc/intel/avs/boards/rt274.c b/sound/soc/intel/avs/boards/rt274.c index e3aa28780df5..68d6fcb215bb 100644 --- a/sound/soc/intel/avs/boards/rt274.c +++ b/sound/soc/intel/avs/boards/rt274.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only // -// Copyright(c) 2021-2022 Intel Corporation. All rights reserved. +// Copyright(c) 2021-2022 Intel Corporation // // Authors: Cezary Rojewski // Amadeusz Slawinski diff --git a/sound/soc/intel/avs/boards/rt286.c b/sound/soc/intel/avs/boards/rt286.c index d24316fc4db9..a3d0c5da5dfe 100644 --- a/sound/soc/intel/avs/boards/rt286.c +++ b/sound/soc/intel/avs/boards/rt286.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only // -// Copyright(c) 2021-2022 Intel Corporation. All rights reserved. +// Copyright(c) 2021-2022 Intel Corporation // // Authors: Cezary Rojewski // Amadeusz Slawinski diff --git a/sound/soc/intel/avs/boards/rt298.c b/sound/soc/intel/avs/boards/rt298.c index 7fd28544f786..f819f8dd447b 100644 --- a/sound/soc/intel/avs/boards/rt298.c +++ b/sound/soc/intel/avs/boards/rt298.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only // -// Copyright(c) 2021-2022 Intel Corporation. All rights reserved. +// Copyright(c) 2021-2022 Intel Corporation // // Authors: Cezary Rojewski // Amadeusz Slawinski diff --git a/sound/soc/intel/avs/boards/rt5514.c b/sound/soc/intel/avs/boards/rt5514.c index 097ae5f73241..cfa146b6cf08 100644 --- a/sound/soc/intel/avs/boards/rt5514.c +++ b/sound/soc/intel/avs/boards/rt5514.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only // -// Copyright(c) 2021-2023 Intel Corporation. All rights reserved. +// Copyright(c) 2021-2023 Intel Corporation // // Authors: Cezary Rojewski // Amadeusz Slawinski diff --git a/sound/soc/intel/avs/boards/rt5663.c b/sound/soc/intel/avs/boards/rt5663.c index ba8c42d026da..44f857e90969 100644 --- a/sound/soc/intel/avs/boards/rt5663.c +++ b/sound/soc/intel/avs/boards/rt5663.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only // -// Copyright(c) 2022-2023 Intel Corporation. All rights reserved. +// Copyright(c) 2022-2023 Intel Corporation // // Authors: Cezary Rojewski // Amadeusz Slawinski diff --git a/sound/soc/intel/avs/boards/rt5682.c b/sound/soc/intel/avs/boards/rt5682.c index 823f04dba2f7..0dcc6392a0cc 100644 --- a/sound/soc/intel/avs/boards/rt5682.c +++ b/sound/soc/intel/avs/boards/rt5682.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only // -// Copyright(c) 2021-2022 Intel Corporation. All rights reserved. +// Copyright(c) 2021-2022 Intel Corporation // // Authors: Cezary Rojewski // Amadeusz Slawinski diff --git a/sound/soc/intel/avs/boards/ssm4567.c b/sound/soc/intel/avs/boards/ssm4567.c index 9e78a3b91208..63bbfc30f35e 100644 --- a/sound/soc/intel/avs/boards/ssm4567.c +++ b/sound/soc/intel/avs/boards/ssm4567.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only // -// Copyright(c) 2021-2022 Intel Corporation. All rights reserved. +// Copyright(c) 2021-2022 Intel Corporation // // Authors: Cezary Rojewski // Amadeusz Slawinski diff --git a/sound/soc/intel/avs/cldma.c b/sound/soc/intel/avs/cldma.c index 945ea376d031..61326d7059b1 100644 --- a/sound/soc/intel/avs/cldma.c +++ b/sound/soc/intel/avs/cldma.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only // -// Copyright(c) 2021-2022 Intel Corporation. All rights reserved. +// Copyright(c) 2021-2022 Intel Corporation // // Author: Cezary Rojewski // diff --git a/sound/soc/intel/avs/cldma.h b/sound/soc/intel/avs/cldma.h index 7d95e2747f52..7f9b2b1c566e 100644 --- a/sound/soc/intel/avs/cldma.h +++ b/sound/soc/intel/avs/cldma.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright(c) 2021-2022 Intel Corporation. All rights reserved. + * Copyright(c) 2021-2022 Intel Corporation * * Author: Cezary Rojewski */ diff --git a/sound/soc/intel/avs/cnl.c b/sound/soc/intel/avs/cnl.c index 0d03e1e03c11..bd3c4bb8bf5a 100644 --- a/sound/soc/intel/avs/cnl.c +++ b/sound/soc/intel/avs/cnl.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only // -// Copyright(c) 2021-2024 Intel Corporation. All rights reserved. +// Copyright(c) 2021-2024 Intel Corporation // // Authors: Cezary Rojewski // Amadeusz Slawinski diff --git a/sound/soc/intel/avs/control.c b/sound/soc/intel/avs/control.c index 3dfa2e9816db..dc7dc45e0a0a 100644 --- a/sound/soc/intel/avs/control.c +++ b/sound/soc/intel/avs/control.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only // -// Copyright(c) 2021-2022 Intel Corporation. All rights reserved. +// Copyright(c) 2021-2022 Intel Corporation // // Authors: Amadeusz Slawinski // Cezary Rojewski diff --git a/sound/soc/intel/avs/control.h b/sound/soc/intel/avs/control.h index 08631bde13c3..d9fac3569e8d 100644 --- a/sound/soc/intel/avs/control.h +++ b/sound/soc/intel/avs/control.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright(c) 2021-2022 Intel Corporation. All rights reserved. + * Copyright(c) 2021-2022 Intel Corporation * * Authors: Amadeusz Slawinski * Cezary Rojewski diff --git a/sound/soc/intel/avs/core.c b/sound/soc/intel/avs/core.c index f56f9e19276a..d9816d0701a8 100644 --- a/sound/soc/intel/avs/core.c +++ b/sound/soc/intel/avs/core.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only // -// Copyright(c) 2021-2022 Intel Corporation. All rights reserved. +// Copyright(c) 2021-2022 Intel Corporation // // Authors: Cezary Rojewski // Amadeusz Slawinski diff --git a/sound/soc/intel/avs/debugfs.c b/sound/soc/intel/avs/debugfs.c index 4dfbff0ce508..3fc2bbb63369 100644 --- a/sound/soc/intel/avs/debugfs.c +++ b/sound/soc/intel/avs/debugfs.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only // -// Copyright(c) 2021-2022 Intel Corporation. All rights reserved. +// Copyright(c) 2021-2022 Intel Corporation // // Authors: Cezary Rojewski // Amadeusz Slawinski diff --git a/sound/soc/intel/avs/dsp.c b/sound/soc/intel/avs/dsp.c index aa03af4473e9..7b47e52c2b39 100644 --- a/sound/soc/intel/avs/dsp.c +++ b/sound/soc/intel/avs/dsp.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only // -// Copyright(c) 2021-2022 Intel Corporation. All rights reserved. +// Copyright(c) 2021-2022 Intel Corporation // // Authors: Cezary Rojewski // Amadeusz Slawinski diff --git a/sound/soc/intel/avs/icl.c b/sound/soc/intel/avs/icl.c index 3a96c4304ca6..f8d327ea2656 100644 --- a/sound/soc/intel/avs/icl.c +++ b/sound/soc/intel/avs/icl.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only // -// Copyright(c) 2021-2024 Intel Corporation. All rights reserved. +// Copyright(c) 2021-2024 Intel Corporation // // Authors: Cezary Rojewski // Amadeusz Slawinski diff --git a/sound/soc/intel/avs/ipc.c b/sound/soc/intel/avs/ipc.c index f9b302215c37..4fba46e77c47 100644 --- a/sound/soc/intel/avs/ipc.c +++ b/sound/soc/intel/avs/ipc.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only // -// Copyright(c) 2021-2022 Intel Corporation. All rights reserved. +// Copyright(c) 2021-2022 Intel Corporation // // Authors: Cezary Rojewski // Amadeusz Slawinski diff --git a/sound/soc/intel/avs/loader.c b/sound/soc/intel/avs/loader.c index c255c898b7a8..890efd2f1fea 100644 --- a/sound/soc/intel/avs/loader.c +++ b/sound/soc/intel/avs/loader.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only // -// Copyright(c) 2021-2022 Intel Corporation. All rights reserved. +// Copyright(c) 2021-2022 Intel Corporation // // Authors: Cezary Rojewski // Amadeusz Slawinski diff --git a/sound/soc/intel/avs/messages.c b/sound/soc/intel/avs/messages.c index f874e4f0d95f..ec458bd51b10 100644 --- a/sound/soc/intel/avs/messages.c +++ b/sound/soc/intel/avs/messages.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only // -// Copyright(c) 2021-2022 Intel Corporation. All rights reserved. +// Copyright(c) 2021-2022 Intel Corporation // // Authors: Cezary Rojewski // Amadeusz Slawinski diff --git a/sound/soc/intel/avs/messages.h b/sound/soc/intel/avs/messages.h index 285d89607b6a..d0bdb7d9266c 100644 --- a/sound/soc/intel/avs/messages.h +++ b/sound/soc/intel/avs/messages.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright(c) 2021-2022 Intel Corporation. All rights reserved. + * Copyright(c) 2021-2022 Intel Corporation * * Authors: Cezary Rojewski * Amadeusz Slawinski diff --git a/sound/soc/intel/avs/path.c b/sound/soc/intel/avs/path.c index 0a34d63e262e..f31d5e2caa7b 100644 --- a/sound/soc/intel/avs/path.c +++ b/sound/soc/intel/avs/path.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only // -// Copyright(c) 2021 Intel Corporation. All rights reserved. +// Copyright(c) 2021 Intel Corporation // // Authors: Cezary Rojewski // Amadeusz Slawinski diff --git a/sound/soc/intel/avs/path.h b/sound/soc/intel/avs/path.h index 657f7b093e80..bfd253c9fa95 100644 --- a/sound/soc/intel/avs/path.h +++ b/sound/soc/intel/avs/path.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright(c) 2021 Intel Corporation. All rights reserved. + * Copyright(c) 2021 Intel Corporation * * Authors: Cezary Rojewski * Amadeusz Slawinski diff --git a/sound/soc/intel/avs/pcm.c b/sound/soc/intel/avs/pcm.c index 845b5ed9eb1b..88e711875004 100644 --- a/sound/soc/intel/avs/pcm.c +++ b/sound/soc/intel/avs/pcm.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only // -// Copyright(c) 2021-2022 Intel Corporation. All rights reserved. +// Copyright(c) 2021-2022 Intel Corporation // // Authors: Cezary Rojewski // Amadeusz Slawinski diff --git a/sound/soc/intel/avs/probes.c b/sound/soc/intel/avs/probes.c index 7e781a315690..f0b010956303 100644 --- a/sound/soc/intel/avs/probes.c +++ b/sound/soc/intel/avs/probes.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only // -// Copyright(c) 2021-2022 Intel Corporation. All rights reserved. +// Copyright(c) 2021-2022 Intel Corporation // // Authors: Cezary Rojewski // Amadeusz Slawinski diff --git a/sound/soc/intel/avs/registers.h b/sound/soc/intel/avs/registers.h index 6126adca500c..f76e91cff2a9 100644 --- a/sound/soc/intel/avs/registers.h +++ b/sound/soc/intel/avs/registers.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright(c) 2021-2022 Intel Corporation. All rights reserved. + * Copyright(c) 2021-2022 Intel Corporation * * Authors: Cezary Rojewski * Amadeusz Slawinski diff --git a/sound/soc/intel/avs/skl.c b/sound/soc/intel/avs/skl.c index fceed353449a..34f859d6e5a4 100644 --- a/sound/soc/intel/avs/skl.c +++ b/sound/soc/intel/avs/skl.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only // -// Copyright(c) 2021-2022 Intel Corporation. All rights reserved. +// Copyright(c) 2021-2022 Intel Corporation // // Authors: Cezary Rojewski // Amadeusz Slawinski diff --git a/sound/soc/intel/avs/sysfs.c b/sound/soc/intel/avs/sysfs.c index cce21636fbc0..74b2e6f38d76 100644 --- a/sound/soc/intel/avs/sysfs.c +++ b/sound/soc/intel/avs/sysfs.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only // -// Copyright(c) 2021-2024 Intel Corporation. All rights reserved. +// Copyright(c) 2021-2024 Intel Corporation // // Authors: Cezary Rojewski // Amadeusz Slawinski diff --git a/sound/soc/intel/avs/tgl.c b/sound/soc/intel/avs/tgl.c index b985a8299b72..a9019ff5e3af 100644 --- a/sound/soc/intel/avs/tgl.c +++ b/sound/soc/intel/avs/tgl.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only // -// Copyright(c) 2021-2024 Intel Corporation. All rights reserved. +// Copyright(c) 2021-2024 Intel Corporation // // Authors: Cezary Rojewski // Amadeusz Slawinski diff --git a/sound/soc/intel/avs/topology.c b/sound/soc/intel/avs/topology.c index 42b42903ae9d..02bae207f6ec 100644 --- a/sound/soc/intel/avs/topology.c +++ b/sound/soc/intel/avs/topology.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only // -// Copyright(c) 2021 Intel Corporation. All rights reserved. +// Copyright(c) 2021 Intel Corporation // // Authors: Cezary Rojewski // Amadeusz Slawinski diff --git a/sound/soc/intel/avs/topology.h b/sound/soc/intel/avs/topology.h index 6a59dd766603..7892e3797f63 100644 --- a/sound/soc/intel/avs/topology.h +++ b/sound/soc/intel/avs/topology.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright(c) 2021 Intel Corporation. All rights reserved. + * Copyright(c) 2021 Intel Corporation * * Authors: Cezary Rojewski * Amadeusz Slawinski diff --git a/sound/soc/intel/avs/trace.c b/sound/soc/intel/avs/trace.c index c63eea909b5e..a98da521db0f 100644 --- a/sound/soc/intel/avs/trace.c +++ b/sound/soc/intel/avs/trace.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only // -// Copyright(c) 2021-2022 Intel Corporation. All rights reserved. +// Copyright(c) 2021-2022 Intel Corporation // // Author: Cezary Rojewski // Amadeusz Slawinski diff --git a/sound/soc/intel/avs/utils.c b/sound/soc/intel/avs/utils.c index 8100c2fa0a7e..81f9b67d8e29 100644 --- a/sound/soc/intel/avs/utils.c +++ b/sound/soc/intel/avs/utils.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only // -// Copyright(c) 2021-2022 Intel Corporation. All rights reserved. +// Copyright(c) 2021-2022 Intel Corporation // // Authors: Cezary Rojewski // Amadeusz Slawinski diff --git a/sound/soc/intel/avs/utils.h b/sound/soc/intel/avs/utils.h index 0b82a98ed024..5ee569c39380 100644 --- a/sound/soc/intel/avs/utils.h +++ b/sound/soc/intel/avs/utils.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright(c) 2023 Intel Corporation. All rights reserved. + * Copyright(c) 2023 Intel Corporation * * Authors: Cezary Rojewski * Amadeusz Slawinski -- cgit v1.2.3 From 83e495d7b29b663861c68a1ad77710b6315472ad Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Fri, 3 May 2024 09:03:57 -0500 Subject: ASoC: soc-topology-test: clarify Copyright information MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit For some reason a number of files included the "All rights reserved" statement. Good old copy-paste made sure this mistake proliferated. Remove the "All rights reserved" in all Intel-copyright to align with internal guidance. Reviewed-by: Cezary Rojewski Signed-off-by: Pierre-Louis Bossart Reviewed-by: Bard Liao Reviewed-by: Péter Ujfalusi Link: https://lore.kernel.org/r/20240503140359.259762-8-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/soc-topology-test.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/soc-topology-test.c b/sound/soc/soc-topology-test.c index 70cbccc42a42..02aa2448f0e6 100644 --- a/sound/soc/soc-topology-test.c +++ b/sound/soc/soc-topology-test.c @@ -2,7 +2,7 @@ /* * soc-topology-test.c -- ALSA SoC Topology Kernel Unit Tests * - * Copyright(c) 2021 Intel Corporation. All rights reserved. + * Copyright(c) 2021 Intel Corporation. */ #include -- cgit v1.2.3 From 77678a25d1ecf70dc1d7ea2c0ab7609af15b83d3 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Tue, 30 Apr 2024 16:02:10 +0200 Subject: ASoC: qcom: Use snd_soc_substream_to_rtd() for accessing private_data Do not open-code snd_soc_substream_to_rtd(). Signed-off-by: Krzysztof Kozlowski Link: https://lore.kernel.org/r/20240430-asoc-snd-substream-clean-v1-1-6f8a8902b479@linaro.org Signed-off-by: Mark Brown --- sound/soc/qcom/apq8016_sbc.c | 4 ++-- sound/soc/qcom/qdsp6/q6apm-dai.c | 2 +- sound/soc/qcom/sc7180.c | 10 +++++----- sound/soc/qcom/sc7280.c | 12 ++++++------ sound/soc/qcom/sc8280xp.c | 8 ++++---- sound/soc/qcom/sdw.c | 8 ++++---- sound/soc/qcom/sm8250.c | 10 +++++----- sound/soc/qcom/x1e80100.c | 8 ++++---- 8 files changed, 31 insertions(+), 31 deletions(-) diff --git a/sound/soc/qcom/apq8016_sbc.c b/sound/soc/qcom/apq8016_sbc.c index 4834a56eaa88..3023cf180a75 100644 --- a/sound/soc/qcom/apq8016_sbc.c +++ b/sound/soc/qcom/apq8016_sbc.c @@ -192,7 +192,7 @@ static int msm8916_qdsp6_dai_init(struct snd_soc_pcm_runtime *rtd) static int msm8916_qdsp6_startup(struct snd_pcm_substream *substream) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream); struct snd_soc_card *card = rtd->card; struct apq8016_sbc_data *data = snd_soc_card_get_drvdata(card); struct snd_soc_dai *cpu_dai = snd_soc_rtd_to_cpu(rtd, 0); @@ -213,7 +213,7 @@ static int msm8916_qdsp6_startup(struct snd_pcm_substream *substream) static void msm8916_qdsp6_shutdown(struct snd_pcm_substream *substream) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream); struct snd_soc_card *card = rtd->card; struct apq8016_sbc_data *data = snd_soc_card_get_drvdata(card); struct snd_soc_dai *cpu_dai = snd_soc_rtd_to_cpu(rtd, 0); diff --git a/sound/soc/qcom/qdsp6/q6apm-dai.c b/sound/soc/qcom/qdsp6/q6apm-dai.c index 00bbd291be5c..8a66c05ef209 100644 --- a/sound/soc/qcom/qdsp6/q6apm-dai.c +++ b/sound/soc/qcom/qdsp6/q6apm-dai.c @@ -331,7 +331,7 @@ static int q6apm_dai_open(struct snd_soc_component *component, struct snd_pcm_substream *substream) { struct snd_pcm_runtime *runtime = substream->runtime; - struct snd_soc_pcm_runtime *soc_prtd = substream->private_data; + struct snd_soc_pcm_runtime *soc_prtd = snd_soc_substream_to_rtd(substream); struct snd_soc_dai *cpu_dai = snd_soc_rtd_to_cpu(soc_prtd, 0); struct device *dev = component->dev; struct q6apm_dai_data *pdata; diff --git a/sound/soc/qcom/sc7180.c b/sound/soc/qcom/sc7180.c index 029780d6fe6d..bc030ce29680 100644 --- a/sound/soc/qcom/sc7180.c +++ b/sound/soc/qcom/sc7180.c @@ -200,7 +200,7 @@ static int sc7180_startup_realtek_codec(struct snd_soc_pcm_runtime *rtd) static int sc7180_snd_startup(struct snd_pcm_substream *substream) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream); struct snd_soc_card *card = rtd->card; struct sc7180_snd_data *data = snd_soc_card_get_drvdata(card); struct snd_soc_dai *cpu_dai = snd_soc_rtd_to_cpu(rtd, 0); @@ -234,7 +234,7 @@ static int sc7180_snd_startup(struct snd_pcm_substream *substream) static int sc7180_qdsp_snd_startup(struct snd_pcm_substream *substream) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream); struct snd_soc_card *card = rtd->card; struct sc7180_snd_data *data = snd_soc_card_get_drvdata(card); struct snd_soc_dai *cpu_dai = snd_soc_rtd_to_cpu(rtd, 0); @@ -307,7 +307,7 @@ static int dmic_set(struct snd_kcontrol *kcontrol, static void sc7180_snd_shutdown(struct snd_pcm_substream *substream) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream); struct snd_soc_card *card = rtd->card; struct sc7180_snd_data *data = snd_soc_card_get_drvdata(card); struct snd_soc_dai *cpu_dai = snd_soc_rtd_to_cpu(rtd, 0); @@ -334,7 +334,7 @@ static void sc7180_snd_shutdown(struct snd_pcm_substream *substream) static void sc7180_qdsp_snd_shutdown(struct snd_pcm_substream *substream) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream); struct snd_soc_card *card = rtd->card; struct sc7180_snd_data *data = snd_soc_card_get_drvdata(card); struct snd_soc_dai *cpu_dai = snd_soc_rtd_to_cpu(rtd, 0); @@ -389,7 +389,7 @@ static int sc7180_adau7002_init(struct snd_soc_pcm_runtime *rtd) static int sc7180_adau7002_snd_startup(struct snd_pcm_substream *substream) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream); struct snd_soc_dai *cpu_dai = snd_soc_rtd_to_cpu(rtd, 0); struct snd_soc_dai *codec_dai = snd_soc_rtd_to_codec(rtd, 0); struct snd_pcm_runtime *runtime = substream->runtime; diff --git a/sound/soc/qcom/sc7280.c b/sound/soc/qcom/sc7280.c index d36f029b7888..207ac5da4dd4 100644 --- a/sound/soc/qcom/sc7280.c +++ b/sound/soc/qcom/sc7280.c @@ -205,7 +205,7 @@ static int sc7280_snd_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { struct snd_pcm_runtime *runtime = substream->runtime; - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream); struct snd_soc_dai *codec_dai; const struct snd_soc_dai *cpu_dai = snd_soc_rtd_to_cpu(rtd, 0); struct sc7280_snd_data *pdata = snd_soc_card_get_drvdata(rtd->card); @@ -237,7 +237,7 @@ static int sc7280_snd_hw_params(struct snd_pcm_substream *substream, static int sc7280_snd_swr_prepare(struct snd_pcm_substream *substream) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream); const struct snd_soc_dai *cpu_dai = snd_soc_rtd_to_cpu(rtd, 0); struct sc7280_snd_data *data = snd_soc_card_get_drvdata(rtd->card); struct sdw_stream_runtime *sruntime = data->sruntime[cpu_dai->id]; @@ -268,7 +268,7 @@ static int sc7280_snd_swr_prepare(struct snd_pcm_substream *substream) static int sc7280_snd_prepare(struct snd_pcm_substream *substream) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream); const struct snd_soc_dai *cpu_dai = snd_soc_rtd_to_cpu(rtd, 0); switch (cpu_dai->id) { @@ -287,7 +287,7 @@ static int sc7280_snd_prepare(struct snd_pcm_substream *substream) static int sc7280_snd_hw_free(struct snd_pcm_substream *substream) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream); struct sc7280_snd_data *data = snd_soc_card_get_drvdata(rtd->card); const struct snd_soc_dai *cpu_dai = snd_soc_rtd_to_cpu(rtd, 0); struct sdw_stream_runtime *sruntime = data->sruntime[cpu_dai->id]; @@ -312,7 +312,7 @@ static int sc7280_snd_hw_free(struct snd_pcm_substream *substream) static void sc7280_snd_shutdown(struct snd_pcm_substream *substream) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream); struct snd_soc_card *card = rtd->card; struct sc7280_snd_data *data = snd_soc_card_get_drvdata(card); struct snd_soc_dai *cpu_dai = snd_soc_rtd_to_cpu(rtd, 0); @@ -339,7 +339,7 @@ static int sc7280_snd_startup(struct snd_pcm_substream *substream) { unsigned int fmt = SND_SOC_DAIFMT_CBS_CFS; unsigned int codec_dai_fmt = SND_SOC_DAIFMT_CBS_CFS; - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream); struct snd_soc_dai *cpu_dai = snd_soc_rtd_to_cpu(rtd, 0); struct snd_soc_dai *codec_dai = snd_soc_rtd_to_codec(rtd, 0); int ret = 0; diff --git a/sound/soc/qcom/sc8280xp.c b/sound/soc/qcom/sc8280xp.c index 878bd50ad4a7..06fd47c4178f 100644 --- a/sound/soc/qcom/sc8280xp.c +++ b/sound/soc/qcom/sc8280xp.c @@ -50,7 +50,7 @@ static int sc8280xp_snd_init(struct snd_soc_pcm_runtime *rtd) static void sc8280xp_snd_shutdown(struct snd_pcm_substream *substream) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream); struct snd_soc_dai *cpu_dai = snd_soc_rtd_to_cpu(rtd, 0); struct sc8280xp_snd_data *pdata = snd_soc_card_get_drvdata(rtd->card); struct sdw_stream_runtime *sruntime = pdata->sruntime[cpu_dai->id]; @@ -89,7 +89,7 @@ static int sc8280xp_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd, static int sc8280xp_snd_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream); struct snd_soc_dai *cpu_dai = snd_soc_rtd_to_cpu(rtd, 0); struct sc8280xp_snd_data *pdata = snd_soc_card_get_drvdata(rtd->card); @@ -98,7 +98,7 @@ static int sc8280xp_snd_hw_params(struct snd_pcm_substream *substream, static int sc8280xp_snd_prepare(struct snd_pcm_substream *substream) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream); struct snd_soc_dai *cpu_dai = snd_soc_rtd_to_cpu(rtd, 0); struct sc8280xp_snd_data *data = snd_soc_card_get_drvdata(rtd->card); struct sdw_stream_runtime *sruntime = data->sruntime[cpu_dai->id]; @@ -109,7 +109,7 @@ static int sc8280xp_snd_prepare(struct snd_pcm_substream *substream) static int sc8280xp_snd_hw_free(struct snd_pcm_substream *substream) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream); struct sc8280xp_snd_data *data = snd_soc_card_get_drvdata(rtd->card); struct snd_soc_dai *cpu_dai = snd_soc_rtd_to_cpu(rtd, 0); struct sdw_stream_runtime *sruntime = data->sruntime[cpu_dai->id]; diff --git a/sound/soc/qcom/sdw.c b/sound/soc/qcom/sdw.c index 7f5089bbe022..eaa8bb016e50 100644 --- a/sound/soc/qcom/sdw.c +++ b/sound/soc/qcom/sdw.c @@ -21,7 +21,7 @@ */ int qcom_snd_sdw_startup(struct snd_pcm_substream *substream) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream); struct snd_soc_dai *cpu_dai = snd_soc_rtd_to_cpu(rtd, 0); struct sdw_stream_runtime *sruntime; struct snd_soc_dai *codec_dai; @@ -54,7 +54,7 @@ int qcom_snd_sdw_prepare(struct snd_pcm_substream *substream, struct sdw_stream_runtime *sruntime, bool *stream_prepared) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream); struct snd_soc_dai *cpu_dai = snd_soc_rtd_to_cpu(rtd, 0); int ret; @@ -105,7 +105,7 @@ int qcom_snd_sdw_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params, struct sdw_stream_runtime **psruntime) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream); struct snd_soc_dai *codec_dai; struct snd_soc_dai *cpu_dai = snd_soc_rtd_to_cpu(rtd, 0); struct sdw_stream_runtime *sruntime; @@ -135,7 +135,7 @@ EXPORT_SYMBOL_GPL(qcom_snd_sdw_hw_params); int qcom_snd_sdw_hw_free(struct snd_pcm_substream *substream, struct sdw_stream_runtime *sruntime, bool *stream_prepared) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream); struct snd_soc_dai *cpu_dai = snd_soc_rtd_to_cpu(rtd, 0); switch (cpu_dai->id) { diff --git a/sound/soc/qcom/sm8250.c b/sound/soc/qcom/sm8250.c index d70df72c0160..a15dafb99b33 100644 --- a/sound/soc/qcom/sm8250.c +++ b/sound/soc/qcom/sm8250.c @@ -50,7 +50,7 @@ static int sm8250_snd_startup(struct snd_pcm_substream *substream) { unsigned int fmt = SND_SOC_DAIFMT_BP_FP; unsigned int codec_dai_fmt = SND_SOC_DAIFMT_BC_FC; - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream); struct snd_soc_dai *cpu_dai = snd_soc_rtd_to_cpu(rtd, 0); struct snd_soc_dai *codec_dai = snd_soc_rtd_to_codec(rtd, 0); @@ -72,7 +72,7 @@ static int sm8250_snd_startup(struct snd_pcm_substream *substream) static void sm2450_snd_shutdown(struct snd_pcm_substream *substream) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream); struct snd_soc_dai *cpu_dai = snd_soc_rtd_to_cpu(rtd, 0); struct sm8250_snd_data *data = snd_soc_card_get_drvdata(rtd->card); struct sdw_stream_runtime *sruntime = data->sruntime[cpu_dai->id]; @@ -84,7 +84,7 @@ static void sm2450_snd_shutdown(struct snd_pcm_substream *substream) static int sm8250_snd_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream); struct snd_soc_dai *cpu_dai = snd_soc_rtd_to_cpu(rtd, 0); struct sm8250_snd_data *pdata = snd_soc_card_get_drvdata(rtd->card); @@ -93,7 +93,7 @@ static int sm8250_snd_hw_params(struct snd_pcm_substream *substream, static int sm8250_snd_prepare(struct snd_pcm_substream *substream) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream); struct snd_soc_dai *cpu_dai = snd_soc_rtd_to_cpu(rtd, 0); struct sm8250_snd_data *data = snd_soc_card_get_drvdata(rtd->card); struct sdw_stream_runtime *sruntime = data->sruntime[cpu_dai->id]; @@ -104,7 +104,7 @@ static int sm8250_snd_prepare(struct snd_pcm_substream *substream) static int sm8250_snd_hw_free(struct snd_pcm_substream *substream) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream); struct sm8250_snd_data *data = snd_soc_card_get_drvdata(rtd->card); struct snd_soc_dai *cpu_dai = snd_soc_rtd_to_cpu(rtd, 0); struct sdw_stream_runtime *sruntime = data->sruntime[cpu_dai->id]; diff --git a/sound/soc/qcom/x1e80100.c b/sound/soc/qcom/x1e80100.c index c3c8bf7ffb5b..0e0773a85809 100644 --- a/sound/soc/qcom/x1e80100.c +++ b/sound/soc/qcom/x1e80100.c @@ -31,7 +31,7 @@ static int x1e80100_snd_init(struct snd_soc_pcm_runtime *rtd) static void x1e80100_snd_shutdown(struct snd_pcm_substream *substream) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream); struct snd_soc_dai *cpu_dai = snd_soc_rtd_to_cpu(rtd, 0); struct x1e80100_snd_data *data = snd_soc_card_get_drvdata(rtd->card); struct sdw_stream_runtime *sruntime = data->sruntime[cpu_dai->id]; @@ -67,7 +67,7 @@ static int x1e80100_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd, static int x1e80100_snd_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream); struct snd_soc_dai *cpu_dai = snd_soc_rtd_to_cpu(rtd, 0); struct x1e80100_snd_data *data = snd_soc_card_get_drvdata(rtd->card); @@ -76,7 +76,7 @@ static int x1e80100_snd_hw_params(struct snd_pcm_substream *substream, static int x1e80100_snd_prepare(struct snd_pcm_substream *substream) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream); struct snd_soc_dai *cpu_dai = snd_soc_rtd_to_cpu(rtd, 0); struct x1e80100_snd_data *data = snd_soc_card_get_drvdata(rtd->card); struct sdw_stream_runtime *sruntime = data->sruntime[cpu_dai->id]; @@ -87,7 +87,7 @@ static int x1e80100_snd_prepare(struct snd_pcm_substream *substream) static int x1e80100_snd_hw_free(struct snd_pcm_substream *substream) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream); struct x1e80100_snd_data *data = snd_soc_card_get_drvdata(rtd->card); struct snd_soc_dai *cpu_dai = snd_soc_rtd_to_cpu(rtd, 0); struct sdw_stream_runtime *sruntime = data->sruntime[cpu_dai->id]; -- cgit v1.2.3 From 3beb985abbf29e660edd1708f8a120ae9bbbddc3 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Tue, 30 Apr 2024 16:02:11 +0200 Subject: ASoC: tegra: Use snd_soc_substream_to_rtd() for accessing private_data Do not open-code snd_soc_substream_to_rtd(). Signed-off-by: Krzysztof Kozlowski Link: https://lore.kernel.org/r/20240430-asoc-snd-substream-clean-v1-2-6f8a8902b479@linaro.org Signed-off-by: Mark Brown --- sound/soc/tegra/tegra_asoc_machine.c | 2 +- sound/soc/tegra/tegra_pcm.c | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/sound/soc/tegra/tegra_asoc_machine.c b/sound/soc/tegra/tegra_asoc_machine.c index 192e9692bdf2..775ce433fdbf 100644 --- a/sound/soc/tegra/tegra_asoc_machine.c +++ b/sound/soc/tegra/tegra_asoc_machine.c @@ -290,7 +290,7 @@ static unsigned int tegra_machine_mclk_rate_6mhz(unsigned int srate) static int tegra_machine_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream); struct snd_soc_dai *codec_dai = snd_soc_rtd_to_codec(rtd, 0); struct snd_soc_card *card = rtd->card; struct tegra_machine *machine = snd_soc_card_get_drvdata(card); diff --git a/sound/soc/tegra/tegra_pcm.c b/sound/soc/tegra/tegra_pcm.c index 42acb56543db..4bdbcd2635ef 100644 --- a/sound/soc/tegra/tegra_pcm.c +++ b/sound/soc/tegra/tegra_pcm.c @@ -76,7 +76,7 @@ EXPORT_SYMBOL_GPL(tegra_pcm_platform_unregister); int tegra_pcm_open(struct snd_soc_component *component, struct snd_pcm_substream *substream) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream); struct snd_dmaengine_dai_dma_data *dmap; struct dma_chan *chan; struct snd_soc_dai *cpu_dai = snd_soc_rtd_to_cpu(rtd, 0); @@ -127,7 +127,7 @@ EXPORT_SYMBOL_GPL(tegra_pcm_open); int tegra_pcm_close(struct snd_soc_component *component, struct snd_pcm_substream *substream) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream); if (rtd->dai_link->no_pcm) return 0; @@ -142,7 +142,7 @@ int tegra_pcm_hw_params(struct snd_soc_component *component, struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream); struct snd_dmaengine_dai_dma_data *dmap; struct dma_slave_config slave_config; struct dma_chan *chan; -- cgit v1.2.3 From 72a666f47f958a57db16b6bdd9ed385674069693 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Tue, 30 Apr 2024 16:02:12 +0200 Subject: ASoC: ti: Use snd_soc_substream_to_rtd() for accessing private_data Do not open-code snd_soc_substream_to_rtd(). Signed-off-by: Krzysztof Kozlowski Link: https://lore.kernel.org/r/20240430-asoc-snd-substream-clean-v1-3-6f8a8902b479@linaro.org Signed-off-by: Mark Brown --- sound/soc/ti/omap-hdmi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/ti/omap-hdmi.c b/sound/soc/ti/omap-hdmi.c index 4513b527ab97..639bc83f4263 100644 --- a/sound/soc/ti/omap-hdmi.c +++ b/sound/soc/ti/omap-hdmi.c @@ -40,7 +40,7 @@ struct hdmi_audio_data { static struct hdmi_audio_data *card_drvdata_substream(struct snd_pcm_substream *ss) { - struct snd_soc_pcm_runtime *rtd = ss->private_data; + struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(ss); return snd_soc_card_get_drvdata(rtd->card); } -- cgit v1.2.3 From a80f2f8443a4ae10c568566f57fe704ea52c5bdb Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Tue, 30 Apr 2024 16:02:13 +0200 Subject: ASoC: arm: Use snd_soc_substream_to_rtd() for accessing private_data Do not open-code snd_soc_substream_to_rtd(). Signed-off-by: Krzysztof Kozlowski Link: https://lore.kernel.org/r/20240430-asoc-snd-substream-clean-v1-4-6f8a8902b479@linaro.org Signed-off-by: Mark Brown --- sound/arm/pxa2xx-pcm-lib.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/arm/pxa2xx-pcm-lib.c b/sound/arm/pxa2xx-pcm-lib.c index 51d2ff80df16..571e9d909cdf 100644 --- a/sound/arm/pxa2xx-pcm-lib.c +++ b/sound/arm/pxa2xx-pcm-lib.c @@ -33,7 +33,7 @@ int pxa2xx_pcm_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { struct dma_chan *chan = snd_dmaengine_pcm_get_chan(substream); - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream); struct snd_dmaengine_dai_dma_data *dma_params; struct dma_slave_config config; int ret; @@ -79,7 +79,7 @@ EXPORT_SYMBOL(pxa2xx_pcm_prepare); int pxa2xx_pcm_open(struct snd_pcm_substream *substream) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream); struct snd_pcm_runtime *runtime = substream->runtime; struct snd_dmaengine_dai_dma_data *dma_params; int ret; -- cgit v1.2.3 From a84d84077512fc64cf1fc2292a3638690a026737 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Tue, 30 Apr 2024 16:02:14 +0200 Subject: ASoC: amd: Use snd_soc_substream_to_rtd() for accessing private_data Do not open-code snd_soc_substream_to_rtd(). Signed-off-by: Krzysztof Kozlowski Link: https://lore.kernel.org/r/20240430-asoc-snd-substream-clean-v1-5-6f8a8902b479@linaro.org Signed-off-by: Mark Brown --- sound/soc/amd/acp/acp-mach-common.c | 2 +- sound/soc/amd/acp3x-rt5682-max9836.c | 2 +- sound/soc/amd/ps/ps-sdw-dma.c | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/sound/soc/amd/acp/acp-mach-common.c b/sound/soc/amd/acp/acp-mach-common.c index 665a6ea0a2a8..a36300a4ed8a 100644 --- a/sound/soc/amd/acp/acp-mach-common.c +++ b/sound/soc/amd/acp/acp-mach-common.c @@ -217,7 +217,7 @@ static void acp_card_shutdown(struct snd_pcm_substream *substream) static int acp_card_rt5682_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream); struct snd_soc_card *card = rtd->card; struct acp_card_drvdata *drvdata = card->drvdata; struct snd_soc_dai *codec_dai = snd_soc_rtd_to_codec(rtd, 0); diff --git a/sound/soc/amd/acp3x-rt5682-max9836.c b/sound/soc/amd/acp3x-rt5682-max9836.c index d6cdb6d9fdd6..357dfd016baf 100644 --- a/sound/soc/amd/acp3x-rt5682-max9836.c +++ b/sound/soc/amd/acp3x-rt5682-max9836.c @@ -143,7 +143,7 @@ static int rt5682_clk_enable(struct snd_pcm_substream *substream) static int acp3x_1015_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream); struct snd_soc_dai *codec_dai; int srate, i, ret; diff --git a/sound/soc/amd/ps/ps-sdw-dma.c b/sound/soc/amd/ps/ps-sdw-dma.c index 66b800962f8c..2f630753278d 100644 --- a/sound/soc/amd/ps/ps-sdw-dma.c +++ b/sound/soc/amd/ps/ps-sdw-dma.c @@ -218,7 +218,7 @@ static int acp63_sdw_dma_open(struct snd_soc_component *component, struct acp_sdw_dma_stream *stream; struct snd_soc_dai *cpu_dai; struct amd_sdw_manager *amd_manager; - struct snd_soc_pcm_runtime *prtd = substream->private_data; + struct snd_soc_pcm_runtime *prtd = snd_soc_substream_to_rtd(substream); int ret; runtime = substream->runtime; -- cgit v1.2.3 From b695d8be5bba9897ee670ec102ca608ecaf625c4 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Tue, 30 Apr 2024 16:02:15 +0200 Subject: ASoC: fsl: Use snd_soc_substream_to_rtd() for accessing private_data Do not open-code snd_soc_substream_to_rtd(). Signed-off-by: Krzysztof Kozlowski Link: https://lore.kernel.org/r/20240430-asoc-snd-substream-clean-v1-6-6f8a8902b479@linaro.org Signed-off-by: Mark Brown --- sound/soc/fsl/fsl-asoc-card.c | 2 +- sound/soc/fsl/imx-card.c | 6 +++--- sound/soc/fsl/imx-hdmi.c | 2 +- sound/soc/fsl/imx-pcm-rpmsg.c | 6 +++--- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/sound/soc/fsl/fsl-asoc-card.c b/sound/soc/fsl/fsl-asoc-card.c index f6d2564864c6..5ddc0c2fe53f 100644 --- a/sound/soc/fsl/fsl-asoc-card.c +++ b/sound/soc/fsl/fsl-asoc-card.c @@ -242,7 +242,7 @@ fail: static int fsl_asoc_card_hw_free(struct snd_pcm_substream *substream) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream); struct fsl_asoc_card_priv *priv = snd_soc_card_get_drvdata(rtd->card); struct codec_priv *codec_priv = &priv->codec_priv; struct device *dev = rtd->card->dev; diff --git a/sound/soc/fsl/imx-card.c b/sound/soc/fsl/imx-card.c index cb8723965f2f..0e18ccabe28c 100644 --- a/sound/soc/fsl/imx-card.c +++ b/sound/soc/fsl/imx-card.c @@ -252,7 +252,7 @@ static unsigned long akcodec_get_mclk_rate(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params, int slots, int slot_width) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream); struct imx_card_data *data = snd_soc_card_get_drvdata(rtd->card); const struct imx_card_plat_data *plat_data = data->plat_data; struct dai_link_data *link_data = &data->link_data[rtd->num]; @@ -289,7 +289,7 @@ static unsigned long akcodec_get_mclk_rate(struct snd_pcm_substream *substream, static int imx_aif_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream); struct snd_soc_dai *cpu_dai = snd_soc_rtd_to_cpu(rtd, 0); struct snd_soc_card *card = rtd->card; struct imx_card_data *data = snd_soc_card_get_drvdata(card); @@ -405,7 +405,7 @@ static int ak5558_hw_rule_rate(struct snd_pcm_hw_params *p, struct snd_pcm_hw_ru static int imx_aif_startup(struct snd_pcm_substream *substream) { struct snd_pcm_runtime *runtime = substream->runtime; - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream); struct snd_soc_card *card = rtd->card; struct imx_card_data *data = snd_soc_card_get_drvdata(card); struct dai_link_data *link_data = &data->link_data[rtd->num]; diff --git a/sound/soc/fsl/imx-hdmi.c b/sound/soc/fsl/imx-hdmi.c index e454085c6e5c..fe47b439a818 100644 --- a/sound/soc/fsl/imx-hdmi.c +++ b/sound/soc/fsl/imx-hdmi.c @@ -32,7 +32,7 @@ struct imx_hdmi_data { static int imx_hdmi_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream); struct imx_hdmi_data *data = snd_soc_card_get_drvdata(rtd->card); bool tx = substream->stream == SNDRV_PCM_STREAM_PLAYBACK; struct snd_soc_dai *cpu_dai = snd_soc_rtd_to_cpu(rtd, 0); diff --git a/sound/soc/fsl/imx-pcm-rpmsg.c b/sound/soc/fsl/imx-pcm-rpmsg.c index b84d1dfddba2..ba491cbb9930 100644 --- a/sound/soc/fsl/imx-pcm-rpmsg.c +++ b/sound/soc/fsl/imx-pcm-rpmsg.c @@ -316,7 +316,7 @@ static int imx_rpmsg_pcm_prepare(struct snd_soc_component *component, struct snd_pcm_substream *substream) { struct snd_pcm_runtime *runtime = substream->runtime; - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream); struct snd_soc_dai *cpu_dai = snd_soc_rtd_to_cpu(rtd, 0); struct fsl_rpmsg *rpmsg = dev_get_drvdata(cpu_dai->dev); @@ -461,7 +461,7 @@ static int imx_rpmsg_pcm_trigger(struct snd_soc_component *component, struct snd_pcm_substream *substream, int cmd) { struct snd_pcm_runtime *runtime = substream->runtime; - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream); struct snd_soc_dai *cpu_dai = snd_soc_rtd_to_cpu(rtd, 0); struct fsl_rpmsg *rpmsg = dev_get_drvdata(cpu_dai->dev); int ret = 0; @@ -515,7 +515,7 @@ static int imx_rpmsg_pcm_ack(struct snd_soc_component *component, struct snd_pcm_substream *substream) { struct snd_pcm_runtime *runtime = substream->runtime; - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream); struct snd_soc_dai *cpu_dai = snd_soc_rtd_to_cpu(rtd, 0); struct fsl_rpmsg *rpmsg = dev_get_drvdata(cpu_dai->dev); struct rpmsg_info *info = dev_get_drvdata(component->dev); -- cgit v1.2.3 From 3b62178720594e08bdf8a87515ccca0328fe41fe Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Tue, 30 Apr 2024 16:02:16 +0200 Subject: ASoC: img: Use snd_soc_substream_to_rtd() for accessing private_data Do not open-code snd_soc_substream_to_rtd(). Signed-off-by: Krzysztof Kozlowski Link: https://lore.kernel.org/r/20240430-asoc-snd-substream-clean-v1-7-6f8a8902b479@linaro.org Signed-off-by: Mark Brown --- sound/soc/img/img-i2s-in.c | 2 +- sound/soc/img/img-i2s-out.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/soc/img/img-i2s-in.c b/sound/soc/img/img-i2s-in.c index dacc29fcf24b..b69a364d619e 100644 --- a/sound/soc/img/img-i2s-in.c +++ b/sound/soc/img/img-i2s-in.c @@ -395,7 +395,7 @@ static int img_i2s_in_dma_prepare_slave_config(struct snd_pcm_substream *st, struct snd_pcm_hw_params *params, struct dma_slave_config *sc) { unsigned int i2s_channels = params_channels(params) / 2; - struct snd_soc_pcm_runtime *rtd = st->private_data; + struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(st); struct snd_dmaengine_dai_dma_data *dma_data; int ret; diff --git a/sound/soc/img/img-i2s-out.c b/sound/soc/img/img-i2s-out.c index f442d985ab87..6f9831c6d6e0 100644 --- a/sound/soc/img/img-i2s-out.c +++ b/sound/soc/img/img-i2s-out.c @@ -401,7 +401,7 @@ static int img_i2s_out_dma_prepare_slave_config(struct snd_pcm_substream *st, struct snd_pcm_hw_params *params, struct dma_slave_config *sc) { unsigned int i2s_channels = params_channels(params) / 2; - struct snd_soc_pcm_runtime *rtd = st->private_data; + struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(st); struct snd_dmaengine_dai_dma_data *dma_data; int ret; -- cgit v1.2.3 From fe42c3b75b93dee9a4010e2297f1783e48684af7 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Tue, 30 Apr 2024 16:02:17 +0200 Subject: ASoC: kirkwood: Use snd_soc_substream_to_rtd() for accessing private_data Do not open-code snd_soc_substream_to_rtd(). Signed-off-by: Krzysztof Kozlowski Link: https://lore.kernel.org/r/20240430-asoc-snd-substream-clean-v1-8-6f8a8902b479@linaro.org Signed-off-by: Mark Brown --- sound/soc/kirkwood/kirkwood-dma.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/kirkwood/kirkwood-dma.c b/sound/soc/kirkwood/kirkwood-dma.c index ef00792e1d49..036b42058272 100644 --- a/sound/soc/kirkwood/kirkwood-dma.c +++ b/sound/soc/kirkwood/kirkwood-dma.c @@ -19,7 +19,7 @@ static struct kirkwood_dma_data *kirkwood_priv(struct snd_pcm_substream *subs) { - struct snd_soc_pcm_runtime *soc_runtime = subs->private_data; + struct snd_soc_pcm_runtime *soc_runtime = snd_soc_substream_to_rtd(subs); return snd_soc_dai_get_drvdata(snd_soc_rtd_to_cpu(soc_runtime, 0)); } -- cgit v1.2.3 From ffad75cebb865fef6f8e40f921c08c79a8faf7e3 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Tue, 30 Apr 2024 16:02:18 +0200 Subject: ASoC: loongson: Use snd_soc_substream_to_rtd() for accessing private_data Do not open-code snd_soc_substream_to_rtd(). Signed-off-by: Krzysztof Kozlowski Link: https://lore.kernel.org/r/20240430-asoc-snd-substream-clean-v1-9-6f8a8902b479@linaro.org Signed-off-by: Mark Brown --- sound/soc/loongson/loongson_card.c | 2 +- sound/soc/loongson/loongson_dma.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/soc/loongson/loongson_card.c b/sound/soc/loongson/loongson_card.c index e8432d466f60..fae5e9312bf0 100644 --- a/sound/soc/loongson/loongson_card.c +++ b/sound/soc/loongson/loongson_card.c @@ -23,7 +23,7 @@ struct loongson_card_data { static int loongson_card_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream); struct snd_soc_dai *cpu_dai = snd_soc_rtd_to_cpu(rtd, 0); struct snd_soc_dai *codec_dai = snd_soc_rtd_to_codec(rtd, 0); struct loongson_card_data *ls_card = snd_soc_card_get_drvdata(rtd->card); diff --git a/sound/soc/loongson/loongson_dma.c b/sound/soc/loongson/loongson_dma.c index 8090662e8ff2..4fcc2868160b 100644 --- a/sound/soc/loongson/loongson_dma.c +++ b/sound/soc/loongson/loongson_dma.c @@ -226,7 +226,7 @@ static int loongson_pcm_open(struct snd_soc_component *component, struct snd_pcm_substream *substream) { struct snd_pcm_runtime *runtime = substream->runtime; - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream); struct snd_card *card = substream->pcm->card; struct loongson_runtime_data *prtd; struct loongson_dma_data *dma_data; -- cgit v1.2.3 From 410a45140fb76709cf2bbad84bc8a731acf632c8 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Tue, 30 Apr 2024 16:02:19 +0200 Subject: ASoC: mediatek: Use snd_soc_substream_to_rtd() for accessing private_data Do not open-code snd_soc_substream_to_rtd(). Signed-off-by: Krzysztof Kozlowski Link: https://lore.kernel.org/r/20240430-asoc-snd-substream-clean-v1-10-6f8a8902b479@linaro.org Signed-off-by: Mark Brown --- sound/soc/mediatek/mt7986/mt7986-afe-pcm.c | 4 ++-- sound/soc/mediatek/mt8186/mt8186-afe-pcm.c | 14 +++++++------- sound/soc/mediatek/mt8186/mt8186-mt6366.c | 2 +- sound/soc/mediatek/mt8188/mt8188-afe-pcm.c | 8 ++++---- sound/soc/mediatek/mt8188/mt8188-mt6359.c | 6 +++--- sound/soc/mediatek/mt8195/mt8195-afe-pcm.c | 10 +++++----- sound/soc/mediatek/mt8195/mt8195-mt6359.c | 4 ++-- 7 files changed, 24 insertions(+), 24 deletions(-) diff --git a/sound/soc/mediatek/mt7986/mt7986-afe-pcm.c b/sound/soc/mediatek/mt7986/mt7986-afe-pcm.c index c1c486e275b9..572ded279b53 100644 --- a/sound/soc/mediatek/mt7986/mt7986-afe-pcm.c +++ b/sound/soc/mediatek/mt7986/mt7986-afe-pcm.c @@ -106,7 +106,7 @@ static const struct snd_pcm_hardware mt7986_afe_hardware = { static int mt7986_memif_fs(struct snd_pcm_substream *substream, unsigned int rate) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream); struct snd_soc_component *component = snd_soc_rtdcom_lookup(rtd, AFE_PCM_NAME); struct mtk_base_afe *afe = snd_soc_component_get_drvdata(component); @@ -116,7 +116,7 @@ static int mt7986_memif_fs(struct snd_pcm_substream *substream, static int mt7986_irq_fs(struct snd_pcm_substream *substream, unsigned int rate) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream); struct snd_soc_component *component = snd_soc_rtdcom_lookup(rtd, AFE_PCM_NAME); struct mtk_base_afe *afe = snd_soc_component_get_drvdata(component); diff --git a/sound/soc/mediatek/mt8186/mt8186-afe-pcm.c b/sound/soc/mediatek/mt8186/mt8186-afe-pcm.c index bfcfc68ac64d..bafbef96a42d 100644 --- a/sound/soc/mediatek/mt8186/mt8186-afe-pcm.c +++ b/sound/soc/mediatek/mt8186/mt8186-afe-pcm.c @@ -40,7 +40,7 @@ static const struct snd_pcm_hardware mt8186_afe_hardware = { static int mt8186_fe_startup(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream); struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai); struct snd_pcm_runtime *runtime = substream->runtime; int id = snd_soc_rtd_to_cpu(rtd, 0)->id; @@ -82,7 +82,7 @@ static int mt8186_fe_startup(struct snd_pcm_substream *substream, static void mt8186_fe_shutdown(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream); struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai); struct mt8186_afe_private *afe_priv = afe->platform_priv; int id = snd_soc_rtd_to_cpu(rtd, 0)->id; @@ -104,7 +104,7 @@ static int mt8186_fe_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params, struct snd_soc_dai *dai) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream); struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai); int id = snd_soc_rtd_to_cpu(rtd, 0)->id; unsigned int channels = params_channels(params); @@ -153,7 +153,7 @@ static int mt8186_fe_hw_free(struct snd_pcm_substream *substream, static int mt8186_fe_trigger(struct snd_pcm_substream *substream, int cmd, struct snd_soc_dai *dai) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream); struct snd_pcm_runtime * const runtime = substream->runtime; struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai); struct mt8186_afe_private *afe_priv = afe->platform_priv; @@ -252,7 +252,7 @@ static int mt8186_fe_trigger(struct snd_pcm_substream *substream, int cmd, static int mt8186_memif_fs(struct snd_pcm_substream *substream, unsigned int rate) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream); struct snd_soc_component *component = snd_soc_rtdcom_lookup(rtd, AFE_PCM_NAME); struct mtk_base_afe *afe = snd_soc_component_get_drvdata(component); @@ -269,7 +269,7 @@ static int mt8186_get_dai_fs(struct mtk_base_afe *afe, static int mt8186_irq_fs(struct snd_pcm_substream *substream, unsigned int rate) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream); struct snd_soc_component *component = snd_soc_rtdcom_lookup(rtd, AFE_PCM_NAME); struct mtk_base_afe *afe = snd_soc_component_get_drvdata(component); @@ -290,7 +290,7 @@ static int mt8186_get_memif_pbuf_size(struct snd_pcm_substream *substream) static int mt8186_fe_prepare(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream); struct snd_pcm_runtime * const runtime = substream->runtime; struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai); int id = snd_soc_rtd_to_cpu(rtd, 0)->id; diff --git a/sound/soc/mediatek/mt8186/mt8186-mt6366.c b/sound/soc/mediatek/mt8186/mt8186-mt6366.c index 8fd31c52b077..771d53611c2a 100644 --- a/sound/soc/mediatek/mt8186/mt8186-mt6366.c +++ b/sound/soc/mediatek/mt8186/mt8186-mt6366.c @@ -297,7 +297,7 @@ static const struct snd_soc_ops mt8186_da7219_i2s_ops = { static int mt8186_rt5682s_i2s_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream); struct snd_soc_card *card = rtd->card; struct snd_soc_dai *cpu_dai = snd_soc_rtd_to_cpu(rtd, 0); struct snd_soc_dai *codec_dai = snd_soc_rtd_to_codec(rtd, 0); diff --git a/sound/soc/mediatek/mt8188/mt8188-afe-pcm.c b/sound/soc/mediatek/mt8188/mt8188-afe-pcm.c index 9647fe133dc8..ccb6c1f3adc7 100644 --- a/sound/soc/mediatek/mt8188/mt8188-afe-pcm.c +++ b/sound/soc/mediatek/mt8188/mt8188-afe-pcm.c @@ -91,7 +91,7 @@ int mt8188_afe_fs_timing(unsigned int rate) static int mt8188_memif_fs(struct snd_pcm_substream *substream, unsigned int rate) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream); struct snd_soc_component *component = NULL; struct mtk_base_afe *afe = NULL; struct mt8188_afe_private *afe_priv = NULL; @@ -300,7 +300,7 @@ static int mt8188_afe_enable_cm(struct mtk_base_afe *afe, static int mt8188_afe_fe_startup(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream); struct snd_pcm_runtime *runtime = substream->runtime; struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai); int id = snd_soc_rtd_to_cpu(rtd, 0)->id; @@ -334,7 +334,7 @@ static int mt8188_afe_fe_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params, struct snd_soc_dai *dai) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream); struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai); int id = snd_soc_rtd_to_cpu(rtd, 0)->id; struct mtk_base_afe_memif *memif = &afe->memif[id]; @@ -358,7 +358,7 @@ static int mt8188_afe_fe_trigger(struct snd_pcm_substream *substream, int cmd, { struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai); const struct mt8188_afe_channel_merge *cm = mt8188_afe_found_cm(dai); - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream); struct snd_pcm_runtime * const runtime = substream->runtime; int id = snd_soc_rtd_to_cpu(rtd, 0)->id; struct mtk_base_afe_memif *memif = &afe->memif[id]; diff --git a/sound/soc/mediatek/mt8188/mt8188-mt6359.c b/sound/soc/mediatek/mt8188/mt8188-mt6359.c index f629fc6bbb53..eba6f4c445ff 100644 --- a/sound/soc/mediatek/mt8188/mt8188-mt6359.c +++ b/sound/soc/mediatek/mt8188/mt8188-mt6359.c @@ -557,7 +557,7 @@ enum { static int mt8188_dptx_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream); unsigned int rate = params_rate(params); unsigned int mclk_fs_ratio = 256; unsigned int mclk_fs = rate * mclk_fs_ratio; @@ -658,7 +658,7 @@ static int mt8188_dumb_amp_init(struct snd_soc_pcm_runtime *rtd) static int mt8188_max98390_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream); unsigned int bit_width = params_width(params); struct snd_soc_dai *cpu_dai = snd_soc_rtd_to_cpu(rtd, 0); struct snd_soc_dai *codec_dai; @@ -821,7 +821,7 @@ static const struct snd_soc_ops mt8188_nau8825_ops = { static int mt8188_rt5682s_i2s_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream); struct snd_soc_card *card = rtd->card; struct snd_soc_dai *cpu_dai = snd_soc_rtd_to_cpu(rtd, 0); struct snd_soc_dai *codec_dai = snd_soc_rtd_to_codec(rtd, 0); diff --git a/sound/soc/mediatek/mt8195/mt8195-afe-pcm.c b/sound/soc/mediatek/mt8195/mt8195-afe-pcm.c index 64af9bf363fd..38891d1bd18a 100644 --- a/sound/soc/mediatek/mt8195/mt8195-afe-pcm.c +++ b/sound/soc/mediatek/mt8195/mt8195-afe-pcm.c @@ -84,7 +84,7 @@ int mt8195_afe_fs_timing(unsigned int rate) static int mt8195_memif_fs(struct snd_pcm_substream *substream, unsigned int rate) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream); struct snd_soc_component *component = snd_soc_rtdcom_lookup(rtd, AFE_PCM_NAME); struct mtk_base_afe *afe = snd_soc_component_get_drvdata(component); @@ -281,7 +281,7 @@ mt8195_afe_paired_memif_clk_prepare(struct snd_pcm_substream *substream, struct snd_soc_dai *dai, int enable) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream); struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai); struct mt8195_afe_private *afe_priv = afe->platform_priv; int id = snd_soc_rtd_to_cpu(rtd, 0)->id; @@ -310,7 +310,7 @@ mt8195_afe_paired_memif_clk_enable(struct snd_pcm_substream *substream, struct snd_soc_dai *dai, int enable) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream); struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai); struct mt8195_afe_private *afe_priv = afe->platform_priv; int id = snd_soc_rtd_to_cpu(rtd, 0)->id; @@ -342,7 +342,7 @@ mt8195_afe_paired_memif_clk_enable(struct snd_pcm_substream *substream, static int mt8195_afe_fe_startup(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream); struct snd_pcm_runtime *runtime = substream->runtime; struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai); int id = snd_soc_rtd_to_cpu(rtd, 0)->id; @@ -380,7 +380,7 @@ static int mt8195_afe_fe_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params, struct snd_soc_dai *dai) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream); struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai); int id = snd_soc_rtd_to_cpu(rtd, 0)->id; struct mtk_base_afe_memif *memif = &afe->memif[id]; diff --git a/sound/soc/mediatek/mt8195/mt8195-mt6359.c b/sound/soc/mediatek/mt8195/mt8195-mt6359.c index 62e4e34cffbb..ca8751190520 100644 --- a/sound/soc/mediatek/mt8195/mt8195-mt6359.c +++ b/sound/soc/mediatek/mt8195/mt8195-mt6359.c @@ -338,7 +338,7 @@ static const struct snd_soc_ops mt8195_hdmitx_dptx_playback_ops = { static int mt8195_dptx_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream); struct snd_soc_dai *cpu_dai = snd_soc_rtd_to_cpu(rtd, 0); return snd_soc_dai_set_sysclk(cpu_dai, 0, params_rate(params) * 256, @@ -394,7 +394,7 @@ static int mt8195_dptx_hw_params_fixup(struct snd_soc_pcm_runtime *rtd, static int mt8195_rt5682_etdm_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream); struct snd_soc_card *card = rtd->card; struct snd_soc_dai *cpu_dai = snd_soc_rtd_to_cpu(rtd, 0); struct snd_soc_dai *codec_dai = snd_soc_rtd_to_codec(rtd, 0); -- cgit v1.2.3 From 22f5680a9cbc7388f97e5386c15c325d6961b958 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Tue, 30 Apr 2024 16:02:20 +0200 Subject: ASoC: meson: Use snd_soc_substream_to_rtd() for accessing private_data Do not open-code snd_soc_substream_to_rtd(). Signed-off-by: Krzysztof Kozlowski Link: https://lore.kernel.org/r/20240430-asoc-snd-substream-clean-v1-11-6f8a8902b479@linaro.org Signed-off-by: Mark Brown --- sound/soc/meson/aiu-fifo.c | 2 +- sound/soc/meson/axg-fifo.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/soc/meson/aiu-fifo.c b/sound/soc/meson/aiu-fifo.c index 4041ff8e437f..b222bde1f61b 100644 --- a/sound/soc/meson/aiu-fifo.c +++ b/sound/soc/meson/aiu-fifo.c @@ -25,7 +25,7 @@ static struct snd_soc_dai *aiu_fifo_dai(struct snd_pcm_substream *ss) { - struct snd_soc_pcm_runtime *rtd = ss->private_data; + struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(ss); return snd_soc_rtd_to_cpu(rtd, 0); } diff --git a/sound/soc/meson/axg-fifo.c b/sound/soc/meson/axg-fifo.c index bebee0ca8e38..1ead5ebc84c4 100644 --- a/sound/soc/meson/axg-fifo.c +++ b/sound/soc/meson/axg-fifo.c @@ -46,7 +46,7 @@ static struct snd_pcm_hardware axg_fifo_hw = { static struct snd_soc_dai *axg_fifo_dai(struct snd_pcm_substream *ss) { - struct snd_soc_pcm_runtime *rtd = ss->private_data; + struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(ss); return snd_soc_rtd_to_cpu(rtd, 0); } -- cgit v1.2.3 From 3e726593107d134221f666b4f2be612b278c3ddb Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Tue, 30 Apr 2024 16:02:21 +0200 Subject: ASoC: samsung: Use snd_soc_substream_to_rtd() for accessing private_data Do not open-code snd_soc_substream_to_rtd(). Signed-off-by: Krzysztof Kozlowski Link: https://lore.kernel.org/r/20240430-asoc-snd-substream-clean-v1-12-6f8a8902b479@linaro.org Signed-off-by: Mark Brown --- sound/soc/samsung/midas_wm1811.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/samsung/midas_wm1811.c b/sound/soc/samsung/midas_wm1811.c index f31244156ff6..0841e2e6f8ce 100644 --- a/sound/soc/samsung/midas_wm1811.c +++ b/sound/soc/samsung/midas_wm1811.c @@ -127,7 +127,7 @@ static int midas_stop_fll1(struct snd_soc_pcm_runtime *rtd) static int midas_aif1_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream); unsigned int pll_out; /* AIF1CLK should be at least 3MHz for "optimal performance" */ -- cgit v1.2.3 From 47aa51677c975a5f66bc93d1c527e8878cf34d6c Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Tue, 30 Apr 2024 16:02:22 +0200 Subject: ASoC: sunxi: Use snd_soc_substream_to_rtd() for accessing private_data Do not open-code snd_soc_substream_to_rtd(). Signed-off-by: Krzysztof Kozlowski Reviewed-by: Jernej Skrabec Link: https://lore.kernel.org/r/20240430-asoc-snd-substream-clean-v1-13-6f8a8902b479@linaro.org Signed-off-by: Mark Brown --- sound/soc/sunxi/sun50i-dmic.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/sunxi/sun50i-dmic.c b/sound/soc/sunxi/sun50i-dmic.c index dd32780fb6a4..884394ddaf86 100644 --- a/sound/soc/sunxi/sun50i-dmic.c +++ b/sound/soc/sunxi/sun50i-dmic.c @@ -86,7 +86,7 @@ static const struct dmic_rate dmic_rate_s[] = { static int sun50i_dmic_startup(struct snd_pcm_substream *substream, struct snd_soc_dai *cpu_dai) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream); struct sun50i_dmic_dev *host = snd_soc_dai_get_drvdata(snd_soc_rtd_to_cpu(rtd, 0)); /* only support capture */ -- cgit v1.2.3 From cfcd957e63506273dc54f34b320172c8709244c7 Mon Sep 17 00:00:00 2001 From: Wolfram Sang Date: Tue, 30 Apr 2024 13:54:34 +0200 Subject: ASoC: codecs: wm8962: use 'time_left' variable with wait_for_completion_timeout() There is a confusing pattern in the kernel to use a variable named 'timeout' to store the result of wait_for_completion_timeout() causing patterns like: timeout = wait_for_completion_timeout(...) if (!timeout) return -ETIMEDOUT; with all kinds of permutations. Use 'time_left' as a variable to make the code self explaining. Signed-off-by: Wolfram Sang Link: https://lore.kernel.org/r/20240430115438.29134-2-wsa+renesas@sang-engineering.com Reviewed-by: Charles Keepax Signed-off-by: Mark Brown --- sound/soc/codecs/wm8962.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/sound/soc/codecs/wm8962.c b/sound/soc/codecs/wm8962.c index 3ef95b7dcbdb..08d164ce3e49 100644 --- a/sound/soc/codecs/wm8962.c +++ b/sound/soc/codecs/wm8962.c @@ -2886,7 +2886,7 @@ static int wm8962_set_fll(struct snd_soc_component *component, int fll_id, int s { struct wm8962_priv *wm8962 = snd_soc_component_get_drvdata(component); struct _fll_div fll_div; - unsigned long timeout; + unsigned long time_left; int ret; int fll1 = 0; @@ -2974,14 +2974,14 @@ static int wm8962_set_fll(struct snd_soc_component *component, int fll_id, int s * higher if we'll error out */ if (wm8962->irq) - timeout = msecs_to_jiffies(5); + time_left = msecs_to_jiffies(5); else - timeout = msecs_to_jiffies(1); + time_left = msecs_to_jiffies(1); - timeout = wait_for_completion_timeout(&wm8962->fll_lock, - timeout); + time_left = wait_for_completion_timeout(&wm8962->fll_lock, + time_left); - if (timeout == 0 && wm8962->irq) { + if (time_left == 0 && wm8962->irq) { dev_err(component->dev, "FLL lock timed out"); snd_soc_component_update_bits(component, WM8962_FLL_CONTROL_1, WM8962_FLL_ENA, 0); -- cgit v1.2.3 From 0800660d8c59539b628f5a6646bb63091d58152f Mon Sep 17 00:00:00 2001 From: Wolfram Sang Date: Tue, 30 Apr 2024 13:54:35 +0200 Subject: ASoC: codecs: wm8993: use 'time_left' variable with wait_for_completion_timeout() There is a confusing pattern in the kernel to use a variable named 'timeout' to store the result of wait_for_completion_timeout() causing patterns like: timeout = wait_for_completion_timeout(...) if (!timeout) return -ETIMEDOUT; with all kinds of permutations. Use 'time_left' as a variable to make the code self explaining. Fix to the proper variable type 'unsigned long' while here. Signed-off-by: Wolfram Sang Link: https://lore.kernel.org/r/20240430115438.29134-3-wsa+renesas@sang-engineering.com Reviewed-by: Charles Keepax Signed-off-by: Mark Brown --- sound/soc/codecs/wm8993.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/sound/soc/codecs/wm8993.c b/sound/soc/codecs/wm8993.c index 98a83f51ab26..f257980f9b56 100644 --- a/sound/soc/codecs/wm8993.c +++ b/sound/soc/codecs/wm8993.c @@ -470,7 +470,7 @@ static int _wm8993_set_fll(struct snd_soc_component *component, int fll_id, int struct i2c_client *i2c = to_i2c_client(component->dev); u16 reg1, reg4, reg5; struct _fll_div fll_div; - unsigned int timeout; + unsigned long time_left; int ret; /* Any change? */ @@ -543,19 +543,19 @@ static int _wm8993_set_fll(struct snd_soc_component *component, int fll_id, int /* If we've got an interrupt wired up make sure we get it */ if (i2c->irq) - timeout = msecs_to_jiffies(20); + time_left = msecs_to_jiffies(20); else if (Fref < 1000000) - timeout = msecs_to_jiffies(3); + time_left = msecs_to_jiffies(3); else - timeout = msecs_to_jiffies(1); + time_left = msecs_to_jiffies(1); try_wait_for_completion(&wm8993->fll_lock); /* Enable the FLL */ snd_soc_component_write(component, WM8993_FLL_CONTROL_1, reg1 | WM8993_FLL_ENA); - timeout = wait_for_completion_timeout(&wm8993->fll_lock, timeout); - if (i2c->irq && !timeout) + time_left = wait_for_completion_timeout(&wm8993->fll_lock, time_left); + if (i2c->irq && !time_left) dev_warn(component->dev, "Timed out waiting for FLL\n"); dev_dbg(component->dev, "FLL enabled at %dHz->%dHz\n", Fref, Fout); -- cgit v1.2.3 From 19c70b4668306632d3cbbecdf5fea98b528e873e Mon Sep 17 00:00:00 2001 From: Wolfram Sang Date: Tue, 30 Apr 2024 13:54:36 +0200 Subject: ASoC: codecs: wm8994: use 'time_left' variable with wait_for_completion_timeout() There is a confusing pattern in the kernel to use a variable named 'timeout' to store the result of wait_for_completion_timeout() causing patterns like: timeout = wait_for_completion_timeout(...) if (!timeout) return -ETIMEDOUT; with all kinds of permutations. Use 'time_left' as a variable to make the code self explaining. Signed-off-by: Wolfram Sang Link: https://lore.kernel.org/r/20240430115438.29134-4-wsa+renesas@sang-engineering.com Reviewed-by: Charles Keepax Signed-off-by: Mark Brown --- sound/soc/codecs/wm8994.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/sound/soc/codecs/wm8994.c b/sound/soc/codecs/wm8994.c index fc9894975a1d..a99908582a50 100644 --- a/sound/soc/codecs/wm8994.c +++ b/sound/soc/codecs/wm8994.c @@ -2210,7 +2210,7 @@ static int _wm8994_set_fll(struct snd_soc_component *component, int id, int src, int reg_offset, ret; struct fll_div fll; u16 reg, clk1, aif_reg, aif_src; - unsigned long timeout; + unsigned long time_left; bool was_enabled; struct clk *mclk; @@ -2403,9 +2403,9 @@ static int _wm8994_set_fll(struct snd_soc_component *component, int id, int src, WM8994_FLL1_FRAC, reg); if (wm8994->fll_locked_irq) { - timeout = wait_for_completion_timeout(&wm8994->fll_locked[id], - msecs_to_jiffies(10)); - if (timeout == 0) + time_left = wait_for_completion_timeout(&wm8994->fll_locked[id], + msecs_to_jiffies(10)); + if (time_left == 0) dev_warn(component->dev, "Timed out waiting for FLL lock\n"); } else { -- cgit v1.2.3 From 4e1f953a4a447b5e001655b453505c4c15904c61 Mon Sep 17 00:00:00 2001 From: Wolfram Sang Date: Tue, 30 Apr 2024 13:54:37 +0200 Subject: ASoC: codecs: wm8996: use 'time_left' variable with wait_for_completion_timeout() There is a confusing pattern in the kernel to use a variable named 'timeout' to store the result of wait_for_completion_timeout() causing patterns like: timeout = wait_for_completion_timeout(...) if (!timeout) return -ETIMEDOUT; with all kinds of permutations. Use 'time_left' as a variable to make the code self explaining. Signed-off-by: Wolfram Sang Link: https://lore.kernel.org/r/20240430115438.29134-5-wsa+renesas@sang-engineering.com Reviewed-by: Charles Keepax Signed-off-by: Mark Brown --- sound/soc/codecs/wm8996.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/sound/soc/codecs/wm8996.c b/sound/soc/codecs/wm8996.c index f6c5adce164e..5c06cea09bd1 100644 --- a/sound/soc/codecs/wm8996.c +++ b/sound/soc/codecs/wm8996.c @@ -655,28 +655,28 @@ static void wait_for_dc_servo(struct snd_soc_component *component, u16 mask) struct i2c_client *i2c = to_i2c_client(component->dev); struct wm8996_priv *wm8996 = snd_soc_component_get_drvdata(component); int ret; - unsigned long timeout = 200; + unsigned long time_left = 200; snd_soc_component_write(component, WM8996_DC_SERVO_2, mask); /* Use the interrupt if possible */ do { if (i2c->irq) { - timeout = wait_for_completion_timeout(&wm8996->dcs_done, - msecs_to_jiffies(200)); - if (timeout == 0) + time_left = wait_for_completion_timeout(&wm8996->dcs_done, + msecs_to_jiffies(200)); + if (time_left == 0) dev_err(component->dev, "DC servo timed out\n"); } else { msleep(1); - timeout--; + time_left--; } ret = snd_soc_component_read(component, WM8996_DC_SERVO_2); dev_dbg(component->dev, "DC servo state: %x\n", ret); - } while (timeout && ret & mask); + } while (time_left && ret & mask); - if (timeout == 0) + if (time_left == 0) dev_err(component->dev, "DC servo timed out for %x\n", mask); else dev_dbg(component->dev, "DC servo complete for %x\n", mask); -- cgit v1.2.3 From e6fa3509cb32df373b15212a99f69a6595efd1c3 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Mon, 29 Apr 2024 13:48:46 +0200 Subject: ASoC: qcom: Constify static snd_pcm_hardware Static 'struct snd_pcm_hardware' is not modified by the driver and its copy is passed to the core, so it can be made const for increased code safety. Signed-off-by: Krzysztof Kozlowski Link: https://lore.kernel.org/r/20240429-n-asoc-const-snd-pcm-hardware-v1-1-c6ce60989834@linaro.org Signed-off-by: Mark Brown --- sound/soc/qcom/qdsp6/q6apm-dai.c | 4 ++-- sound/soc/qcom/qdsp6/q6asm-dai.c | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/sound/soc/qcom/qdsp6/q6apm-dai.c b/sound/soc/qcom/qdsp6/q6apm-dai.c index 00bbd291be5c..3c78440a2f0f 100644 --- a/sound/soc/qcom/qdsp6/q6apm-dai.c +++ b/sound/soc/qcom/qdsp6/q6apm-dai.c @@ -85,7 +85,7 @@ struct q6apm_dai_data { long long sid; }; -static struct snd_pcm_hardware q6apm_dai_hardware_capture = { +static const struct snd_pcm_hardware q6apm_dai_hardware_capture = { .info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_BLOCK_TRANSFER | SNDRV_PCM_INFO_MMAP_VALID | SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_RESUME | @@ -104,7 +104,7 @@ static struct snd_pcm_hardware q6apm_dai_hardware_capture = { .fifo_size = 0, }; -static struct snd_pcm_hardware q6apm_dai_hardware_playback = { +static const struct snd_pcm_hardware q6apm_dai_hardware_playback = { .info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_BLOCK_TRANSFER | SNDRV_PCM_INFO_MMAP_VALID | SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_RESUME | diff --git a/sound/soc/qcom/qdsp6/q6asm-dai.c b/sound/soc/qcom/qdsp6/q6asm-dai.c index aeb6a9d479ab..3913706ccdc5 100644 --- a/sound/soc/qcom/qdsp6/q6asm-dai.c +++ b/sound/soc/qcom/qdsp6/q6asm-dai.c @@ -103,7 +103,7 @@ static const struct snd_pcm_hardware q6asm_dai_hardware_capture = { .fifo_size = 0, }; -static struct snd_pcm_hardware q6asm_dai_hardware_playback = { +static const struct snd_pcm_hardware q6asm_dai_hardware_playback = { .info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_BATCH | SNDRV_PCM_INFO_BLOCK_TRANSFER | SNDRV_PCM_INFO_MMAP_VALID | -- cgit v1.2.3 From ed90156037659473ee95eafe3f72d8498e5384ff Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Mon, 29 Apr 2024 13:48:47 +0200 Subject: ASoC: fsl: Constify static snd_pcm_hardware Static 'struct snd_pcm_hardware' is not modified by the driver and its copy is passed to the core, so it can be made const for increased code safety. Signed-off-by: Krzysztof Kozlowski Link: https://lore.kernel.org/r/20240429-n-asoc-const-snd-pcm-hardware-v1-2-c6ce60989834@linaro.org Signed-off-by: Mark Brown --- sound/soc/fsl/imx-pcm-rpmsg.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/fsl/imx-pcm-rpmsg.c b/sound/soc/fsl/imx-pcm-rpmsg.c index b84d1dfddba2..128728b65a3a 100644 --- a/sound/soc/fsl/imx-pcm-rpmsg.c +++ b/sound/soc/fsl/imx-pcm-rpmsg.c @@ -16,7 +16,7 @@ #include "fsl_rpmsg.h" #include "imx-pcm-rpmsg.h" -static struct snd_pcm_hardware imx_rpmsg_pcm_hardware = { +static const struct snd_pcm_hardware imx_rpmsg_pcm_hardware = { .info = SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_BLOCK_TRANSFER | SNDRV_PCM_INFO_BATCH | -- cgit v1.2.3 From 7b5ce9f0c52a5885d34d46bba62e9eaedc3dd459 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Mon, 29 Apr 2024 13:48:48 +0200 Subject: ASoC: meson: Constify static snd_pcm_hardware Static 'struct snd_pcm_hardware' is not modified by the driver and its copy is passed to the core, so it can be made const for increased code safety. Signed-off-by: Krzysztof Kozlowski Link: https://lore.kernel.org/r/20240429-n-asoc-const-snd-pcm-hardware-v1-3-c6ce60989834@linaro.org Signed-off-by: Mark Brown --- sound/soc/meson/aiu-fifo-i2s.c | 2 +- sound/soc/meson/aiu-fifo-spdif.c | 2 +- sound/soc/meson/aiu-fifo.h | 2 +- sound/soc/meson/axg-fifo.c | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/sound/soc/meson/aiu-fifo-i2s.c b/sound/soc/meson/aiu-fifo-i2s.c index 7d833500c799..eccbc16b293a 100644 --- a/sound/soc/meson/aiu-fifo-i2s.c +++ b/sound/soc/meson/aiu-fifo-i2s.c @@ -25,7 +25,7 @@ #define AIU_FIFO_I2S_BLOCK 256 -static struct snd_pcm_hardware fifo_i2s_pcm = { +static const struct snd_pcm_hardware fifo_i2s_pcm = { .info = (SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_MMAP_VALID | diff --git a/sound/soc/meson/aiu-fifo-spdif.c b/sound/soc/meson/aiu-fifo-spdif.c index fa91f3c53fa4..e0e00ec026dc 100644 --- a/sound/soc/meson/aiu-fifo-spdif.c +++ b/sound/soc/meson/aiu-fifo-spdif.c @@ -27,7 +27,7 @@ #define AIU_FIFO_SPDIF_BLOCK 8 -static struct snd_pcm_hardware fifo_spdif_pcm = { +static const struct snd_pcm_hardware fifo_spdif_pcm = { .info = (SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_MMAP_VALID | diff --git a/sound/soc/meson/aiu-fifo.h b/sound/soc/meson/aiu-fifo.h index 42ce266677cc..84ab4577815a 100644 --- a/sound/soc/meson/aiu-fifo.h +++ b/sound/soc/meson/aiu-fifo.h @@ -18,7 +18,7 @@ struct snd_pcm_hw_params; struct platform_device; struct aiu_fifo { - struct snd_pcm_hardware *pcm; + const struct snd_pcm_hardware *pcm; unsigned int mem_offset; unsigned int fifo_block; struct clk *pclk; diff --git a/sound/soc/meson/axg-fifo.c b/sound/soc/meson/axg-fifo.c index bebee0ca8e38..633fd971b444 100644 --- a/sound/soc/meson/axg-fifo.c +++ b/sound/soc/meson/axg-fifo.c @@ -23,7 +23,7 @@ * These differences are handled in the respective DAI drivers */ -static struct snd_pcm_hardware axg_fifo_hw = { +static const struct snd_pcm_hardware axg_fifo_hw = { .info = (SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_MMAP_VALID | -- cgit v1.2.3 From 74a15fabd271d0fd82ceecbbfa1b98ea0a4709dd Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Mon, 29 Apr 2024 13:48:49 +0200 Subject: ASoC: uniphier: Constify static snd_pcm_hardware Static 'struct snd_pcm_hardware' is not modified by the driver and its copy is passed to the core, so it can be made const for increased code safety. Signed-off-by: Krzysztof Kozlowski Link: https://lore.kernel.org/r/20240429-n-asoc-const-snd-pcm-hardware-v1-4-c6ce60989834@linaro.org Signed-off-by: Mark Brown --- sound/soc/uniphier/aio-dma.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/uniphier/aio-dma.c b/sound/soc/uniphier/aio-dma.c index fe272befd967..265d61723e99 100644 --- a/sound/soc/uniphier/aio-dma.c +++ b/sound/soc/uniphier/aio-dma.c @@ -14,7 +14,7 @@ #include "aio.h" -static struct snd_pcm_hardware uniphier_aiodma_hw = { +static const struct snd_pcm_hardware uniphier_aiodma_hw = { .info = SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_MMAP_VALID | SNDRV_PCM_INFO_INTERLEAVED, -- cgit v1.2.3 From bd381c9d151467e784988bbacf22bd7ca02455d6 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Tue, 30 Apr 2024 16:09:54 +0200 Subject: ASoC: qcom: q6apm-dai: drop unused 'q6apm_dai_rtd' fields Remove few unused fields from 'struct q6apm_dai_rtd'. Signed-off-by: Krzysztof Kozlowski Link: https://lore.kernel.org/r/20240430140954.328127-1-krzysztof.kozlowski@linaro.org Signed-off-by: Mark Brown --- sound/soc/qcom/qdsp6/q6apm-dai.c | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/sound/soc/qcom/qdsp6/q6apm-dai.c b/sound/soc/qcom/qdsp6/q6apm-dai.c index 00bbd291be5c..cee23d4bda6f 100644 --- a/sound/soc/qcom/qdsp6/q6apm-dai.c +++ b/sound/soc/qcom/qdsp6/q6apm-dai.c @@ -70,14 +70,10 @@ struct q6apm_dai_rtd { unsigned int bytes_received; unsigned int copied_total; uint16_t bits_per_sample; - uint16_t source; /* Encoding source bit mask */ - uint16_t session_id; bool next_track; enum stream_state state; struct q6apm_graph *graph; spinlock_t lock; - uint32_t initial_samples_drop; - uint32_t trailing_samples_drop; bool notify_on_drain; }; @@ -720,14 +716,12 @@ static int q6apm_dai_compr_set_metadata(struct snd_soc_component *component, switch (metadata->key) { case SNDRV_COMPRESS_ENCODER_PADDING: - prtd->trailing_samples_drop = metadata->value[0]; q6apm_remove_trailing_silence(component->dev, prtd->graph, - prtd->trailing_samples_drop); + metadata->value[0]); break; case SNDRV_COMPRESS_ENCODER_DELAY: - prtd->initial_samples_drop = metadata->value[0]; q6apm_remove_initial_silence(component->dev, prtd->graph, - prtd->initial_samples_drop); + metadata->value[0]); break; default: ret = -EINVAL; -- cgit v1.2.3 From fd25e1c1328f40c6eb0bfa5ebee757e0e1dfb308 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 7 May 2024 17:55:05 +0200 Subject: ASoC: core: Use *-y instead of *-objs in Makefile *-objs suffix is reserved rather for (user-space) host programs while usually *-y suffix is used for kernel drivers (although *-objs works for that purpose for now). Let's correct the old usages of *-objs in Makefiles. Signed-off-by: Takashi Iwai Link: https://lore.kernel.org/r/20240507155540.24815-2-tiwai@suse.de Signed-off-by: Mark Brown --- sound/soc/Makefile | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/sound/soc/Makefile b/sound/soc/Makefile index f90f5300b36e..fd61847dd1eb 100644 --- a/sound/soc/Makefile +++ b/sound/soc/Makefile @@ -1,14 +1,14 @@ # SPDX-License-Identifier: GPL-2.0 -snd-soc-core-objs := soc-core.o soc-dapm.o soc-jack.o soc-utils.o soc-dai.o soc-component.o -snd-soc-core-objs += soc-pcm.o soc-devres.o soc-ops.o soc-link.o soc-card.o +snd-soc-core-y := soc-core.o soc-dapm.o soc-jack.o soc-utils.o soc-dai.o soc-component.o +snd-soc-core-y += soc-pcm.o soc-devres.o soc-ops.o soc-link.o soc-card.o snd-soc-core-$(CONFIG_SND_SOC_COMPRESS) += soc-compress.o ifneq ($(CONFIG_SND_SOC_TOPOLOGY),) -snd-soc-core-objs += soc-topology.o +snd-soc-core-y += soc-topology.o endif ifneq ($(CONFIG_SND_SOC_TOPOLOGY_KUNIT_TEST),) -# snd-soc-test-objs := soc-topology-test.o +# snd-soc-test-y := soc-topology-test.o obj-$(CONFIG_SND_SOC_TOPOLOGY_KUNIT_TEST) += soc-topology-test.o endif @@ -17,20 +17,20 @@ obj-$(CONFIG_SND_SOC_CARD_KUNIT_TEST) += soc-card-test.o endif ifneq ($(CONFIG_SND_SOC_UTILS_KUNIT_TEST),) -# snd-soc-test-objs := soc-utils-test.o +# snd-soc-test-y := soc-utils-test.o obj-$(CONFIG_SND_SOC_UTILS_KUNIT_TEST) += soc-utils-test.o endif ifneq ($(CONFIG_SND_SOC_GENERIC_DMAENGINE_PCM),) -snd-soc-core-objs += soc-generic-dmaengine-pcm.o +snd-soc-core-y += soc-generic-dmaengine-pcm.o endif ifneq ($(CONFIG_SND_SOC_AC97_BUS),) -snd-soc-core-objs += soc-ac97.o +snd-soc-core-y += soc-ac97.o endif ifneq ($(CONFIG_SND_SOC_ACPI),) -snd-soc-acpi-objs := soc-acpi.o +snd-soc-acpi-y := soc-acpi.o endif obj-$(CONFIG_SND_SOC_ACPI) += snd-soc-acpi.o -- cgit v1.2.3 From 1c3fa6662832f1498b78817317796bc37df7da40 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 7 May 2024 17:55:06 +0200 Subject: ASoC: codecs: Use *-y instead of *-objs in Makefile *-objs suffix is reserved rather for (user-space) host programs while usually *-y suffix is used for kernel drivers (although *-objs works for that purpose for now). Let's correct the old usages of *-objs in Makefiles. Signed-off-by: Takashi Iwai Link: https://lore.kernel.org/r/20240507155540.24815-3-tiwai@suse.de Signed-off-by: Mark Brown --- sound/soc/codecs/Makefile | 784 +++++++++++++++++++++++----------------------- 1 file changed, 392 insertions(+), 392 deletions(-) diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile index cddb16cd6a4c..b4df22186e25 100644 --- a/sound/soc/codecs/Makefile +++ b/sound/soc/codecs/Makefile @@ -1,399 +1,399 @@ # SPDX-License-Identifier: GPL-2.0 -snd-soc-88pm860x-objs := 88pm860x-codec.o -snd-soc-ab8500-codec-objs := ab8500-codec.o -snd-soc-ac97-objs := ac97.o -snd-soc-ad1836-objs := ad1836.o -snd-soc-ad193x-objs := ad193x.o -snd-soc-ad193x-spi-objs := ad193x-spi.o -snd-soc-ad193x-i2c-objs := ad193x-i2c.o -snd-soc-ad1980-objs := ad1980.o -snd-soc-ad73311-objs := ad73311.o -snd-soc-adau-utils-objs := adau-utils.o -snd-soc-adau1372-objs := adau1372.o -snd-soc-adau1372-i2c-objs := adau1372-i2c.o -snd-soc-adau1372-spi-objs := adau1372-spi.o -snd-soc-adau1373-objs := adau1373.o -snd-soc-adau1701-objs := adau1701.o -snd-soc-adau17x1-objs := adau17x1.o -snd-soc-adau1761-objs := adau1761.o -snd-soc-adau1761-i2c-objs := adau1761-i2c.o -snd-soc-adau1761-spi-objs := adau1761-spi.o -snd-soc-adau1781-objs := adau1781.o -snd-soc-adau1781-i2c-objs := adau1781-i2c.o -snd-soc-adau1781-spi-objs := adau1781-spi.o -snd-soc-adau1977-objs := adau1977.o -snd-soc-adau1977-spi-objs := adau1977-spi.o -snd-soc-adau1977-i2c-objs := adau1977-i2c.o -snd-soc-adau7002-objs := adau7002.o -snd-soc-adau7118-objs := adau7118.o -snd-soc-adau7118-i2c-objs := adau7118-i2c.o -snd-soc-adau7118-hw-objs := adau7118-hw.o -snd-soc-adav80x-objs := adav80x.o -snd-soc-adav801-objs := adav801.o -snd-soc-adav803-objs := adav803.o -snd-soc-ads117x-objs := ads117x.o -snd-soc-ak4104-objs := ak4104.o -snd-soc-ak4118-objs := ak4118.o -snd-soc-ak4375-objs := ak4375.o -snd-soc-ak4458-objs := ak4458.o -snd-soc-ak4535-objs := ak4535.o -snd-soc-ak4554-objs := ak4554.o -snd-soc-ak4613-objs := ak4613.o -snd-soc-ak4641-objs := ak4641.o -snd-soc-ak4642-objs := ak4642.o -snd-soc-ak4671-objs := ak4671.o -snd-soc-ak5386-objs := ak5386.o -snd-soc-ak5558-objs := ak5558.o -snd-soc-arizona-objs := arizona.o arizona-jack.o -snd-soc-audio-iio-aux-objs := audio-iio-aux.o -snd-soc-aw8738-objs := aw8738.o -snd-soc-aw87390-objs := aw87390.o -snd-soc-aw88395-lib-objs := aw88395/aw88395_lib.o -snd-soc-aw88395-objs := aw88395/aw88395.o \ +snd-soc-88pm860x-y := 88pm860x-codec.o +snd-soc-ab8500-codec-y := ab8500-codec.o +snd-soc-ac97-y := ac97.o +snd-soc-ad1836-y := ad1836.o +snd-soc-ad193x-y := ad193x.o +snd-soc-ad193x-spi-y := ad193x-spi.o +snd-soc-ad193x-i2c-y := ad193x-i2c.o +snd-soc-ad1980-y := ad1980.o +snd-soc-ad73311-y := ad73311.o +snd-soc-adau-utils-y := adau-utils.o +snd-soc-adau1372-y := adau1372.o +snd-soc-adau1372-i2c-y := adau1372-i2c.o +snd-soc-adau1372-spi-y := adau1372-spi.o +snd-soc-adau1373-y := adau1373.o +snd-soc-adau1701-y := adau1701.o +snd-soc-adau17x1-y := adau17x1.o +snd-soc-adau1761-y := adau1761.o +snd-soc-adau1761-i2c-y := adau1761-i2c.o +snd-soc-adau1761-spi-y := adau1761-spi.o +snd-soc-adau1781-y := adau1781.o +snd-soc-adau1781-i2c-y := adau1781-i2c.o +snd-soc-adau1781-spi-y := adau1781-spi.o +snd-soc-adau1977-y := adau1977.o +snd-soc-adau1977-spi-y := adau1977-spi.o +snd-soc-adau1977-i2c-y := adau1977-i2c.o +snd-soc-adau7002-y := adau7002.o +snd-soc-adau7118-y := adau7118.o +snd-soc-adau7118-i2c-y := adau7118-i2c.o +snd-soc-adau7118-hw-y := adau7118-hw.o +snd-soc-adav80x-y := adav80x.o +snd-soc-adav801-y := adav801.o +snd-soc-adav803-y := adav803.o +snd-soc-ads117x-y := ads117x.o +snd-soc-ak4104-y := ak4104.o +snd-soc-ak4118-y := ak4118.o +snd-soc-ak4375-y := ak4375.o +snd-soc-ak4458-y := ak4458.o +snd-soc-ak4535-y := ak4535.o +snd-soc-ak4554-y := ak4554.o +snd-soc-ak4613-y := ak4613.o +snd-soc-ak4641-y := ak4641.o +snd-soc-ak4642-y := ak4642.o +snd-soc-ak4671-y := ak4671.o +snd-soc-ak5386-y := ak5386.o +snd-soc-ak5558-y := ak5558.o +snd-soc-arizona-y := arizona.o arizona-jack.o +snd-soc-audio-iio-aux-y := audio-iio-aux.o +snd-soc-aw8738-y := aw8738.o +snd-soc-aw87390-y := aw87390.o +snd-soc-aw88395-lib-y := aw88395/aw88395_lib.o +snd-soc-aw88395-y := aw88395/aw88395.o \ aw88395/aw88395_device.o -snd-soc-aw88261-objs := aw88261.o -snd-soc-aw88399-objs := aw88399.o -snd-soc-bd28623-objs := bd28623.o -snd-soc-bt-sco-objs := bt-sco.o -snd-soc-chv3-codec-objs := chv3-codec.o -snd-soc-cpcap-objs := cpcap.o -snd-soc-cq93vc-objs := cq93vc.o -snd-soc-cros-ec-codec-objs := cros_ec_codec.o -snd-soc-cs-amp-lib-objs := cs-amp-lib.o -snd-soc-cs-amp-lib-test-objs := cs-amp-lib-test.o -snd-soc-cs35l32-objs := cs35l32.o -snd-soc-cs35l33-objs := cs35l33.o -snd-soc-cs35l34-objs := cs35l34.o -snd-soc-cs35l35-objs := cs35l35.o -snd-soc-cs35l36-objs := cs35l36.o -snd-soc-cs35l41-lib-objs := cs35l41-lib.o -snd-soc-cs35l41-objs := cs35l41.o -snd-soc-cs35l41-spi-objs := cs35l41-spi.o -snd-soc-cs35l41-i2c-objs := cs35l41-i2c.o -snd-soc-cs35l45-objs := cs35l45.o cs35l45-tables.o -snd-soc-cs35l45-spi-objs := cs35l45-spi.o -snd-soc-cs35l45-i2c-objs := cs35l45-i2c.o -snd-soc-cs35l56-objs := cs35l56.o -snd-soc-cs35l56-shared-objs := cs35l56-shared.o -snd-soc-cs35l56-i2c-objs := cs35l56-i2c.o -snd-soc-cs35l56-spi-objs := cs35l56-spi.o -snd-soc-cs35l56-sdw-objs := cs35l56-sdw.o -snd-soc-cs42l42-objs := cs42l42.o -snd-soc-cs42l42-i2c-objs := cs42l42-i2c.o -snd-soc-cs42l42-sdw-objs := cs42l42-sdw.o -snd-soc-cs42l43-objs := cs42l43.o cs42l43-jack.o -snd-soc-cs42l43-sdw-objs := cs42l43-sdw.o -snd-soc-cs42l51-objs := cs42l51.o -snd-soc-cs42l51-i2c-objs := cs42l51-i2c.o -snd-soc-cs42l52-objs := cs42l52.o -snd-soc-cs42l56-objs := cs42l56.o -snd-soc-cs42l73-objs := cs42l73.o -snd-soc-cs42l83-i2c-objs := cs42l83-i2c.o -snd-soc-cs4234-objs := cs4234.o -snd-soc-cs4265-objs := cs4265.o -snd-soc-cs4270-objs := cs4270.o -snd-soc-cs4271-objs := cs4271.o -snd-soc-cs4271-i2c-objs := cs4271-i2c.o -snd-soc-cs4271-spi-objs := cs4271-spi.o -snd-soc-cs42xx8-objs := cs42xx8.o -snd-soc-cs42xx8-i2c-objs := cs42xx8-i2c.o -snd-soc-cs43130-objs := cs43130.o -snd-soc-cs4341-objs := cs4341.o -snd-soc-cs4349-objs := cs4349.o -snd-soc-cs47l15-objs := cs47l15.o -snd-soc-cs47l24-objs := cs47l24.o -snd-soc-cs47l35-objs := cs47l35.o -snd-soc-cs47l85-objs := cs47l85.o -snd-soc-cs47l90-objs := cs47l90.o -snd-soc-cs47l92-objs := cs47l92.o -snd-soc-cs53l30-objs := cs53l30.o -snd-soc-cx20442-objs := cx20442.o -snd-soc-cx2072x-objs := cx2072x.o -snd-soc-da7210-objs := da7210.o -snd-soc-da7213-objs := da7213.o -snd-soc-da7218-objs := da7218.o -snd-soc-da7219-objs := da7219.o da7219-aad.o -snd-soc-da732x-objs := da732x.o -snd-soc-da9055-objs := da9055.o -snd-soc-dmic-objs := dmic.o -snd-soc-es7134-objs := es7134.o -snd-soc-es7241-objs := es7241.o -snd-soc-es83xx-dsm-common-objs := es83xx-dsm-common.o -snd-soc-es8316-objs := es8316.o -snd-soc-es8326-objs := es8326.o -snd-soc-es8328-objs := es8328.o -snd-soc-es8328-i2c-objs := es8328-i2c.o -snd-soc-es8328-spi-objs := es8328-spi.o -snd-soc-framer-objs := framer-codec.o -snd-soc-gtm601-objs := gtm601.o -snd-soc-hdac-hdmi-objs := hdac_hdmi.o -snd-soc-hdac-hda-objs := hdac_hda.o -snd-soc-hda-codec-objs := hda.o hda-dai.o -snd-soc-ics43432-objs := ics43432.o -snd-soc-idt821034-objs := idt821034.o -snd-soc-inno-rk3036-objs := inno_rk3036.o -snd-soc-isabelle-objs := isabelle.o -snd-soc-jz4740-codec-objs := jz4740.o -snd-soc-jz4725b-codec-objs := jz4725b.o -snd-soc-jz4760-codec-objs := jz4760.o -snd-soc-jz4770-codec-objs := jz4770.o -snd-soc-lm4857-objs := lm4857.o -snd-soc-lm49453-objs := lm49453.o -snd-soc-lochnagar-sc-objs := lochnagar-sc.o -snd-soc-lpass-macro-common-objs := lpass-macro-common.o -snd-soc-lpass-rx-macro-objs := lpass-rx-macro.o -snd-soc-lpass-tx-macro-objs := lpass-tx-macro.o -snd-soc-lpass-wsa-macro-objs := lpass-wsa-macro.o -snd-soc-lpass-va-macro-objs := lpass-va-macro.o -snd-soc-madera-objs := madera.o -snd-soc-max9759-objs := max9759.o -snd-soc-max9768-objs := max9768.o -snd-soc-max98088-objs := max98088.o -snd-soc-max98090-objs := max98090.o -snd-soc-max98095-objs := max98095.o -snd-soc-max98357a-objs := max98357a.o -snd-soc-max98371-objs := max98371.o -snd-soc-max9867-objs := max9867.o -snd-soc-max98925-objs := max98925.o -snd-soc-max98926-objs := max98926.o -snd-soc-max98927-objs := max98927.o -snd-soc-max98520-objs := max98520.o -snd-soc-max98363-objs := max98363.o -snd-soc-max98373-objs := max98373.o -snd-soc-max98373-i2c-objs := max98373-i2c.o -snd-soc-max98373-sdw-objs := max98373-sdw.o -snd-soc-max98388-objs := max98388.o -snd-soc-max98390-objs := max98390.o -snd-soc-max98396-objs := max98396.o -snd-soc-max9850-objs := max9850.o -snd-soc-max9860-objs := max9860.o -snd-soc-mc13783-objs := mc13783.o -snd-soc-ml26124-objs := ml26124.o -snd-soc-msm8916-analog-objs := msm8916-wcd-analog.o -snd-soc-msm8916-digital-objs := msm8916-wcd-digital.o -snd-soc-mt6351-objs := mt6351.o -snd-soc-mt6358-objs := mt6358.o -snd-soc-mt6359-objs := mt6359.o -snd-soc-mt6359-accdet-objs := mt6359-accdet.o -snd-soc-mt6660-objs := mt6660.o -snd-soc-nau8315-objs := nau8315.o -snd-soc-nau8540-objs := nau8540.o -snd-soc-nau8810-objs := nau8810.o -snd-soc-nau8821-objs := nau8821.o -snd-soc-nau8822-objs := nau8822.o -snd-soc-nau8824-objs := nau8824.o -snd-soc-nau8825-objs := nau8825.o -snd-soc-hdmi-codec-objs := hdmi-codec.o -snd-soc-pcm1681-objs := pcm1681.o -snd-soc-pcm1789-codec-objs := pcm1789.o -snd-soc-pcm1789-i2c-objs := pcm1789-i2c.o -snd-soc-pcm179x-codec-objs := pcm179x.o -snd-soc-pcm179x-i2c-objs := pcm179x-i2c.o -snd-soc-pcm179x-spi-objs := pcm179x-spi.o -snd-soc-pcm186x-objs := pcm186x.o -snd-soc-pcm186x-i2c-objs := pcm186x-i2c.o -snd-soc-pcm186x-spi-objs := pcm186x-spi.o -snd-soc-pcm3008-objs := pcm3008.o -snd-soc-pcm3060-objs := pcm3060.o -snd-soc-pcm3060-i2c-objs := pcm3060-i2c.o -snd-soc-pcm3060-spi-objs := pcm3060-spi.o -snd-soc-pcm3168a-objs := pcm3168a.o -snd-soc-pcm3168a-i2c-objs := pcm3168a-i2c.o -snd-soc-pcm3168a-spi-objs := pcm3168a-spi.o -snd-soc-pcm5102a-objs := pcm5102a.o -snd-soc-pcm512x-objs := pcm512x.o -snd-soc-pcm512x-i2c-objs := pcm512x-i2c.o -snd-soc-pcm512x-spi-objs := pcm512x-spi.o -snd-soc-pcm6240-objs := pcm6240.o -snd-soc-peb2466-objs := peb2466.o -snd-soc-rk3308-objs := rk3308_codec.o -snd-soc-rk3328-objs := rk3328_codec.o -snd-soc-rk817-objs := rk817_codec.o -snd-soc-rl6231-objs := rl6231.o -snd-soc-rl6347a-objs := rl6347a.o -snd-soc-rt1011-objs := rt1011.o -snd-soc-rt1015-objs := rt1015.o -snd-soc-rt1015p-objs := rt1015p.o -snd-soc-rt1016-objs := rt1016.o -snd-soc-rt1017-sdca-objs := rt1017-sdca-sdw.o -snd-soc-rt1019-objs := rt1019.o -snd-soc-rt1305-objs := rt1305.o -snd-soc-rt1308-objs := rt1308.o -snd-soc-rt1308-sdw-objs := rt1308-sdw.o -snd-soc-rt1316-sdw-objs := rt1316-sdw.o -snd-soc-rt1318-sdw-objs := rt1318-sdw.o -snd-soc-rt274-objs := rt274.o -snd-soc-rt286-objs := rt286.o -snd-soc-rt298-objs := rt298.o -snd-soc-rt5514-objs := rt5514.o -snd-soc-rt5514-spi-objs := rt5514-spi.o -snd-soc-rt5616-objs := rt5616.o -snd-soc-rt5631-objs := rt5631.o -snd-soc-rt5640-objs := rt5640.o -snd-soc-rt5645-objs := rt5645.o -snd-soc-rt5651-objs := rt5651.o -snd-soc-rt5659-objs := rt5659.o -snd-soc-rt5660-objs := rt5660.o -snd-soc-rt5663-objs := rt5663.o -snd-soc-rt5665-objs := rt5665.o -snd-soc-rt5668-objs := rt5668.o -snd-soc-rt5670-objs := rt5670.o -snd-soc-rt5677-objs := rt5677.o -snd-soc-rt5677-spi-objs := rt5677-spi.o -snd-soc-rt5682-objs := rt5682.o -snd-soc-rt5682-sdw-objs := rt5682-sdw.o -snd-soc-rt5682-i2c-objs := rt5682-i2c.o -snd-soc-rt5682s-objs := rt5682s.o -snd-soc-rt700-objs := rt700.o rt700-sdw.o -snd-soc-rt711-objs := rt711.o rt711-sdw.o -snd-soc-rt711-sdca-objs := rt711-sdca.o rt711-sdca-sdw.o -snd-soc-rt712-sdca-objs := rt712-sdca.o rt712-sdca-sdw.o -snd-soc-rt712-sdca-dmic-objs := rt712-sdca-dmic.o -snd-soc-rt715-objs := rt715.o rt715-sdw.o -snd-soc-rt715-sdca-objs := rt715-sdca.o rt715-sdca-sdw.o -snd-soc-rt722-sdca-objs := rt722-sdca.o rt722-sdca-sdw.o -snd-soc-rt9120-objs := rt9120.o -snd-soc-rtq9128-objs := rtq9128.o -snd-soc-sdw-mockup-objs := sdw-mockup.o -snd-soc-sgtl5000-objs := sgtl5000.o -snd-soc-alc5623-objs := alc5623.o -snd-soc-alc5632-objs := alc5632.o -snd-soc-sigmadsp-objs := sigmadsp.o -snd-soc-sigmadsp-i2c-objs := sigmadsp-i2c.o -snd-soc-sigmadsp-regmap-objs := sigmadsp-regmap.o -snd-soc-si476x-objs := si476x.o -snd-soc-sma1303-objs := sma1303.o -snd-soc-spdif-tx-objs := spdif_transmitter.o -snd-soc-spdif-rx-objs := spdif_receiver.o -snd-soc-src4xxx-objs := src4xxx.o -snd-soc-src4xxx-i2c-objs := src4xxx-i2c.o -snd-soc-ssm2305-objs := ssm2305.o -snd-soc-ssm2518-objs := ssm2518.o -snd-soc-ssm2602-objs := ssm2602.o -snd-soc-ssm2602-spi-objs := ssm2602-spi.o -snd-soc-ssm2602-i2c-objs := ssm2602-i2c.o -snd-soc-ssm3515-objs := ssm3515.o -snd-soc-ssm4567-objs := ssm4567.o -snd-soc-sta32x-objs := sta32x.o -snd-soc-sta350-objs := sta350.o -snd-soc-sta529-objs := sta529.o -snd-soc-stac9766-objs := stac9766.o -snd-soc-sti-sas-objs := sti-sas.o -snd-soc-tas5086-objs := tas5086.o -snd-soc-tas571x-objs := tas571x.o -snd-soc-tas5720-objs := tas5720.o -snd-soc-tas5805m-objs := tas5805m.o -snd-soc-tas6424-objs := tas6424.o -snd-soc-tda7419-objs := tda7419.o -snd-soc-tas2770-objs := tas2770.o -snd-soc-tas2781-comlib-objs := tas2781-comlib.o -snd-soc-tas2781-fmwlib-objs := tas2781-fmwlib.o -snd-soc-tas2781-i2c-objs := tas2781-i2c.o -snd-soc-tfa9879-objs := tfa9879.o -snd-soc-tfa989x-objs := tfa989x.o -snd-soc-tlv320adc3xxx-objs := tlv320adc3xxx.o -snd-soc-tlv320aic23-objs := tlv320aic23.o -snd-soc-tlv320aic23-i2c-objs := tlv320aic23-i2c.o -snd-soc-tlv320aic23-spi-objs := tlv320aic23-spi.o -snd-soc-tlv320aic26-objs := tlv320aic26.o -snd-soc-tlv320aic31xx-objs := tlv320aic31xx.o -snd-soc-tlv320aic32x4-objs := tlv320aic32x4.o tlv320aic32x4-clk.o -snd-soc-tlv320aic32x4-i2c-objs := tlv320aic32x4-i2c.o -snd-soc-tlv320aic32x4-spi-objs := tlv320aic32x4-spi.o -snd-soc-tlv320aic3x-objs := tlv320aic3x.o -snd-soc-tlv320aic3x-i2c-objs := tlv320aic3x-i2c.o -snd-soc-tlv320aic3x-spi-objs := tlv320aic3x-spi.o -snd-soc-tlv320dac33-objs := tlv320dac33.o -snd-soc-tlv320adcx140-objs := tlv320adcx140.o -snd-soc-tscs42xx-objs := tscs42xx.o -snd-soc-tscs454-objs := tscs454.o -snd-soc-ts3a227e-objs := ts3a227e.o -snd-soc-twl4030-objs := twl4030.o -snd-soc-twl6040-objs := twl6040.o -snd-soc-uda1334-objs := uda1334.o -snd-soc-uda1380-objs := uda1380.o -snd-soc-wcd-classh-objs := wcd-clsh-v2.o -snd-soc-wcd-mbhc-objs := wcd-mbhc-v2.o -snd-soc-wcd9335-objs := wcd9335.o -snd-soc-wcd934x-objs := wcd934x.o -snd-soc-wcd938x-objs := wcd938x.o -snd-soc-wcd938x-sdw-objs := wcd938x-sdw.o -snd-soc-wcd939x-objs := wcd939x.o -snd-soc-wcd939x-sdw-objs := wcd939x-sdw.o -snd-soc-wl1273-objs := wl1273.o -snd-soc-wm-adsp-objs := wm_adsp.o -snd-soc-wm0010-objs := wm0010.o -snd-soc-wm1250-ev1-objs := wm1250-ev1.o -snd-soc-wm2000-objs := wm2000.o -snd-soc-wm2200-objs := wm2200.o -snd-soc-wm5100-objs := wm5100.o wm5100-tables.o -snd-soc-wm5102-objs := wm5102.o -snd-soc-wm5110-objs := wm5110.o -snd-soc-wm8350-objs := wm8350.o -snd-soc-wm8400-objs := wm8400.o -snd-soc-wm8510-objs := wm8510.o -snd-soc-wm8523-objs := wm8523.o -snd-soc-wm8524-objs := wm8524.o -snd-soc-wm8580-objs := wm8580.o -snd-soc-wm8711-objs := wm8711.o -snd-soc-wm8727-objs := wm8727.o -snd-soc-wm8728-objs := wm8728.o -snd-soc-wm8731-objs := wm8731.o -snd-soc-wm8731-i2c-objs := wm8731-i2c.o -snd-soc-wm8731-spi-objs := wm8731-spi.o -snd-soc-wm8737-objs := wm8737.o -snd-soc-wm8741-objs := wm8741.o -snd-soc-wm8750-objs := wm8750.o -snd-soc-wm8753-objs := wm8753.o -snd-soc-wm8770-objs := wm8770.o -snd-soc-wm8776-objs := wm8776.o -snd-soc-wm8782-objs := wm8782.o -snd-soc-wm8804-objs := wm8804.o -snd-soc-wm8804-i2c-objs := wm8804-i2c.o -snd-soc-wm8804-spi-objs := wm8804-spi.o -snd-soc-wm8900-objs := wm8900.o -snd-soc-wm8903-objs := wm8903.o -snd-soc-wm8904-objs := wm8904.o -snd-soc-wm8996-objs := wm8996.o -snd-soc-wm8940-objs := wm8940.o -snd-soc-wm8955-objs := wm8955.o -snd-soc-wm8960-objs := wm8960.o -snd-soc-wm8961-objs := wm8961.o -snd-soc-wm8962-objs := wm8962.o -snd-soc-wm8971-objs := wm8971.o -snd-soc-wm8974-objs := wm8974.o -snd-soc-wm8978-objs := wm8978.o -snd-soc-wm8983-objs := wm8983.o -snd-soc-wm8985-objs := wm8985.o -snd-soc-wm8988-objs := wm8988.o -snd-soc-wm8990-objs := wm8990.o -snd-soc-wm8991-objs := wm8991.o -snd-soc-wm8993-objs := wm8993.o -snd-soc-wm8994-objs := wm8994.o wm8958-dsp2.o -snd-soc-wm8995-objs := wm8995.o -snd-soc-wm8997-objs := wm8997.o -snd-soc-wm8998-objs := wm8998.o -snd-soc-wm9081-objs := wm9081.o -snd-soc-wm9090-objs := wm9090.o -snd-soc-wm9705-objs := wm9705.o -snd-soc-wm9712-objs := wm9712.o -snd-soc-wm9713-objs := wm9713.o -snd-soc-wm-hubs-objs := wm_hubs.o -snd-soc-wsa881x-objs := wsa881x.o -snd-soc-wsa883x-objs := wsa883x.o -snd-soc-wsa884x-objs := wsa884x.o -snd-soc-zl38060-objs := zl38060.o +snd-soc-aw88261-y := aw88261.o +snd-soc-aw88399-y := aw88399.o +snd-soc-bd28623-y := bd28623.o +snd-soc-bt-sco-y := bt-sco.o +snd-soc-chv3-codec-y := chv3-codec.o +snd-soc-cpcap-y := cpcap.o +snd-soc-cq93vc-y := cq93vc.o +snd-soc-cros-ec-codec-y := cros_ec_codec.o +snd-soc-cs-amp-lib-y := cs-amp-lib.o +snd-soc-cs-amp-lib-test-y := cs-amp-lib-test.o +snd-soc-cs35l32-y := cs35l32.o +snd-soc-cs35l33-y := cs35l33.o +snd-soc-cs35l34-y := cs35l34.o +snd-soc-cs35l35-y := cs35l35.o +snd-soc-cs35l36-y := cs35l36.o +snd-soc-cs35l41-lib-y := cs35l41-lib.o +snd-soc-cs35l41-y := cs35l41.o +snd-soc-cs35l41-spi-y := cs35l41-spi.o +snd-soc-cs35l41-i2c-y := cs35l41-i2c.o +snd-soc-cs35l45-y := cs35l45.o cs35l45-tables.o +snd-soc-cs35l45-spi-y := cs35l45-spi.o +snd-soc-cs35l45-i2c-y := cs35l45-i2c.o +snd-soc-cs35l56-y := cs35l56.o +snd-soc-cs35l56-shared-y := cs35l56-shared.o +snd-soc-cs35l56-i2c-y := cs35l56-i2c.o +snd-soc-cs35l56-spi-y := cs35l56-spi.o +snd-soc-cs35l56-sdw-y := cs35l56-sdw.o +snd-soc-cs42l42-y := cs42l42.o +snd-soc-cs42l42-i2c-y := cs42l42-i2c.o +snd-soc-cs42l42-sdw-y := cs42l42-sdw.o +snd-soc-cs42l43-y := cs42l43.o cs42l43-jack.o +snd-soc-cs42l43-sdw-y := cs42l43-sdw.o +snd-soc-cs42l51-y := cs42l51.o +snd-soc-cs42l51-i2c-y := cs42l51-i2c.o +snd-soc-cs42l52-y := cs42l52.o +snd-soc-cs42l56-y := cs42l56.o +snd-soc-cs42l73-y := cs42l73.o +snd-soc-cs42l83-i2c-y := cs42l83-i2c.o +snd-soc-cs4234-y := cs4234.o +snd-soc-cs4265-y := cs4265.o +snd-soc-cs4270-y := cs4270.o +snd-soc-cs4271-y := cs4271.o +snd-soc-cs4271-i2c-y := cs4271-i2c.o +snd-soc-cs4271-spi-y := cs4271-spi.o +snd-soc-cs42xx8-y := cs42xx8.o +snd-soc-cs42xx8-i2c-y := cs42xx8-i2c.o +snd-soc-cs43130-y := cs43130.o +snd-soc-cs4341-y := cs4341.o +snd-soc-cs4349-y := cs4349.o +snd-soc-cs47l15-y := cs47l15.o +snd-soc-cs47l24-y := cs47l24.o +snd-soc-cs47l35-y := cs47l35.o +snd-soc-cs47l85-y := cs47l85.o +snd-soc-cs47l90-y := cs47l90.o +snd-soc-cs47l92-y := cs47l92.o +snd-soc-cs53l30-y := cs53l30.o +snd-soc-cx20442-y := cx20442.o +snd-soc-cx2072x-y := cx2072x.o +snd-soc-da7210-y := da7210.o +snd-soc-da7213-y := da7213.o +snd-soc-da7218-y := da7218.o +snd-soc-da7219-y := da7219.o da7219-aad.o +snd-soc-da732x-y := da732x.o +snd-soc-da9055-y := da9055.o +snd-soc-dmic-y := dmic.o +snd-soc-es7134-y := es7134.o +snd-soc-es7241-y := es7241.o +snd-soc-es83xx-dsm-common-y := es83xx-dsm-common.o +snd-soc-es8316-y := es8316.o +snd-soc-es8326-y := es8326.o +snd-soc-es8328-y := es8328.o +snd-soc-es8328-i2c-y := es8328-i2c.o +snd-soc-es8328-spi-y := es8328-spi.o +snd-soc-framer-y := framer-codec.o +snd-soc-gtm601-y := gtm601.o +snd-soc-hdac-hdmi-y := hdac_hdmi.o +snd-soc-hdac-hda-y := hdac_hda.o +snd-soc-hda-codec-y := hda.o hda-dai.o +snd-soc-ics43432-y := ics43432.o +snd-soc-idt821034-y := idt821034.o +snd-soc-inno-rk3036-y := inno_rk3036.o +snd-soc-isabelle-y := isabelle.o +snd-soc-jz4740-codec-y := jz4740.o +snd-soc-jz4725b-codec-y := jz4725b.o +snd-soc-jz4760-codec-y := jz4760.o +snd-soc-jz4770-codec-y := jz4770.o +snd-soc-lm4857-y := lm4857.o +snd-soc-lm49453-y := lm49453.o +snd-soc-lochnagar-sc-y := lochnagar-sc.o +snd-soc-lpass-macro-common-y := lpass-macro-common.o +snd-soc-lpass-rx-macro-y := lpass-rx-macro.o +snd-soc-lpass-tx-macro-y := lpass-tx-macro.o +snd-soc-lpass-wsa-macro-y := lpass-wsa-macro.o +snd-soc-lpass-va-macro-y := lpass-va-macro.o +snd-soc-madera-y := madera.o +snd-soc-max9759-y := max9759.o +snd-soc-max9768-y := max9768.o +snd-soc-max98088-y := max98088.o +snd-soc-max98090-y := max98090.o +snd-soc-max98095-y := max98095.o +snd-soc-max98357a-y := max98357a.o +snd-soc-max98371-y := max98371.o +snd-soc-max9867-y := max9867.o +snd-soc-max98925-y := max98925.o +snd-soc-max98926-y := max98926.o +snd-soc-max98927-y := max98927.o +snd-soc-max98520-y := max98520.o +snd-soc-max98363-y := max98363.o +snd-soc-max98373-y := max98373.o +snd-soc-max98373-i2c-y := max98373-i2c.o +snd-soc-max98373-sdw-y := max98373-sdw.o +snd-soc-max98388-y := max98388.o +snd-soc-max98390-y := max98390.o +snd-soc-max98396-y := max98396.o +snd-soc-max9850-y := max9850.o +snd-soc-max9860-y := max9860.o +snd-soc-mc13783-y := mc13783.o +snd-soc-ml26124-y := ml26124.o +snd-soc-msm8916-analog-y := msm8916-wcd-analog.o +snd-soc-msm8916-digital-y := msm8916-wcd-digital.o +snd-soc-mt6351-y := mt6351.o +snd-soc-mt6358-y := mt6358.o +snd-soc-mt6359-y := mt6359.o +snd-soc-mt6359-accdet-y := mt6359-accdet.o +snd-soc-mt6660-y := mt6660.o +snd-soc-nau8315-y := nau8315.o +snd-soc-nau8540-y := nau8540.o +snd-soc-nau8810-y := nau8810.o +snd-soc-nau8821-y := nau8821.o +snd-soc-nau8822-y := nau8822.o +snd-soc-nau8824-y := nau8824.o +snd-soc-nau8825-y := nau8825.o +snd-soc-hdmi-codec-y := hdmi-codec.o +snd-soc-pcm1681-y := pcm1681.o +snd-soc-pcm1789-codec-y := pcm1789.o +snd-soc-pcm1789-i2c-y := pcm1789-i2c.o +snd-soc-pcm179x-codec-y := pcm179x.o +snd-soc-pcm179x-i2c-y := pcm179x-i2c.o +snd-soc-pcm179x-spi-y := pcm179x-spi.o +snd-soc-pcm186x-y := pcm186x.o +snd-soc-pcm186x-i2c-y := pcm186x-i2c.o +snd-soc-pcm186x-spi-y := pcm186x-spi.o +snd-soc-pcm3008-y := pcm3008.o +snd-soc-pcm3060-y := pcm3060.o +snd-soc-pcm3060-i2c-y := pcm3060-i2c.o +snd-soc-pcm3060-spi-y := pcm3060-spi.o +snd-soc-pcm3168a-y := pcm3168a.o +snd-soc-pcm3168a-i2c-y := pcm3168a-i2c.o +snd-soc-pcm3168a-spi-y := pcm3168a-spi.o +snd-soc-pcm5102a-y := pcm5102a.o +snd-soc-pcm512x-y := pcm512x.o +snd-soc-pcm512x-i2c-y := pcm512x-i2c.o +snd-soc-pcm512x-spi-y := pcm512x-spi.o +snd-soc-pcm6240-y := pcm6240.o +snd-soc-peb2466-y := peb2466.o +snd-soc-rk3308-y := rk3308_codec.o +snd-soc-rk3328-y := rk3328_codec.o +snd-soc-rk817-y := rk817_codec.o +snd-soc-rl6231-y := rl6231.o +snd-soc-rl6347a-y := rl6347a.o +snd-soc-rt1011-y := rt1011.o +snd-soc-rt1015-y := rt1015.o +snd-soc-rt1015p-y := rt1015p.o +snd-soc-rt1016-y := rt1016.o +snd-soc-rt1017-sdca-y := rt1017-sdca-sdw.o +snd-soc-rt1019-y := rt1019.o +snd-soc-rt1305-y := rt1305.o +snd-soc-rt1308-y := rt1308.o +snd-soc-rt1308-sdw-y := rt1308-sdw.o +snd-soc-rt1316-sdw-y := rt1316-sdw.o +snd-soc-rt1318-sdw-y := rt1318-sdw.o +snd-soc-rt274-y := rt274.o +snd-soc-rt286-y := rt286.o +snd-soc-rt298-y := rt298.o +snd-soc-rt5514-y := rt5514.o +snd-soc-rt5514-spi-y := rt5514-spi.o +snd-soc-rt5616-y := rt5616.o +snd-soc-rt5631-y := rt5631.o +snd-soc-rt5640-y := rt5640.o +snd-soc-rt5645-y := rt5645.o +snd-soc-rt5651-y := rt5651.o +snd-soc-rt5659-y := rt5659.o +snd-soc-rt5660-y := rt5660.o +snd-soc-rt5663-y := rt5663.o +snd-soc-rt5665-y := rt5665.o +snd-soc-rt5668-y := rt5668.o +snd-soc-rt5670-y := rt5670.o +snd-soc-rt5677-y := rt5677.o +snd-soc-rt5677-spi-y := rt5677-spi.o +snd-soc-rt5682-y := rt5682.o +snd-soc-rt5682-sdw-y := rt5682-sdw.o +snd-soc-rt5682-i2c-y := rt5682-i2c.o +snd-soc-rt5682s-y := rt5682s.o +snd-soc-rt700-y := rt700.o rt700-sdw.o +snd-soc-rt711-y := rt711.o rt711-sdw.o +snd-soc-rt711-sdca-y := rt711-sdca.o rt711-sdca-sdw.o +snd-soc-rt712-sdca-y := rt712-sdca.o rt712-sdca-sdw.o +snd-soc-rt712-sdca-dmic-y := rt712-sdca-dmic.o +snd-soc-rt715-y := rt715.o rt715-sdw.o +snd-soc-rt715-sdca-y := rt715-sdca.o rt715-sdca-sdw.o +snd-soc-rt722-sdca-y := rt722-sdca.o rt722-sdca-sdw.o +snd-soc-rt9120-y := rt9120.o +snd-soc-rtq9128-y := rtq9128.o +snd-soc-sdw-mockup-y := sdw-mockup.o +snd-soc-sgtl5000-y := sgtl5000.o +snd-soc-alc5623-y := alc5623.o +snd-soc-alc5632-y := alc5632.o +snd-soc-sigmadsp-y := sigmadsp.o +snd-soc-sigmadsp-i2c-y := sigmadsp-i2c.o +snd-soc-sigmadsp-regmap-y := sigmadsp-regmap.o +snd-soc-si476x-y := si476x.o +snd-soc-sma1303-y := sma1303.o +snd-soc-spdif-tx-y := spdif_transmitter.o +snd-soc-spdif-rx-y := spdif_receiver.o +snd-soc-src4xxx-y := src4xxx.o +snd-soc-src4xxx-i2c-y := src4xxx-i2c.o +snd-soc-ssm2305-y := ssm2305.o +snd-soc-ssm2518-y := ssm2518.o +snd-soc-ssm2602-y := ssm2602.o +snd-soc-ssm2602-spi-y := ssm2602-spi.o +snd-soc-ssm2602-i2c-y := ssm2602-i2c.o +snd-soc-ssm3515-y := ssm3515.o +snd-soc-ssm4567-y := ssm4567.o +snd-soc-sta32x-y := sta32x.o +snd-soc-sta350-y := sta350.o +snd-soc-sta529-y := sta529.o +snd-soc-stac9766-y := stac9766.o +snd-soc-sti-sas-y := sti-sas.o +snd-soc-tas5086-y := tas5086.o +snd-soc-tas571x-y := tas571x.o +snd-soc-tas5720-y := tas5720.o +snd-soc-tas5805m-y := tas5805m.o +snd-soc-tas6424-y := tas6424.o +snd-soc-tda7419-y := tda7419.o +snd-soc-tas2770-y := tas2770.o +snd-soc-tas2781-comlib-y := tas2781-comlib.o +snd-soc-tas2781-fmwlib-y := tas2781-fmwlib.o +snd-soc-tas2781-i2c-y := tas2781-i2c.o +snd-soc-tfa9879-y := tfa9879.o +snd-soc-tfa989x-y := tfa989x.o +snd-soc-tlv320adc3xxx-y := tlv320adc3xxx.o +snd-soc-tlv320aic23-y := tlv320aic23.o +snd-soc-tlv320aic23-i2c-y := tlv320aic23-i2c.o +snd-soc-tlv320aic23-spi-y := tlv320aic23-spi.o +snd-soc-tlv320aic26-y := tlv320aic26.o +snd-soc-tlv320aic31xx-y := tlv320aic31xx.o +snd-soc-tlv320aic32x4-y := tlv320aic32x4.o tlv320aic32x4-clk.o +snd-soc-tlv320aic32x4-i2c-y := tlv320aic32x4-i2c.o +snd-soc-tlv320aic32x4-spi-y := tlv320aic32x4-spi.o +snd-soc-tlv320aic3x-y := tlv320aic3x.o +snd-soc-tlv320aic3x-i2c-y := tlv320aic3x-i2c.o +snd-soc-tlv320aic3x-spi-y := tlv320aic3x-spi.o +snd-soc-tlv320dac33-y := tlv320dac33.o +snd-soc-tlv320adcx140-y := tlv320adcx140.o +snd-soc-tscs42xx-y := tscs42xx.o +snd-soc-tscs454-y := tscs454.o +snd-soc-ts3a227e-y := ts3a227e.o +snd-soc-twl4030-y := twl4030.o +snd-soc-twl6040-y := twl6040.o +snd-soc-uda1334-y := uda1334.o +snd-soc-uda1380-y := uda1380.o +snd-soc-wcd-classh-y := wcd-clsh-v2.o +snd-soc-wcd-mbhc-y := wcd-mbhc-v2.o +snd-soc-wcd9335-y := wcd9335.o +snd-soc-wcd934x-y := wcd934x.o +snd-soc-wcd938x-y := wcd938x.o +snd-soc-wcd938x-sdw-y := wcd938x-sdw.o +snd-soc-wcd939x-y := wcd939x.o +snd-soc-wcd939x-sdw-y := wcd939x-sdw.o +snd-soc-wl1273-y := wl1273.o +snd-soc-wm-adsp-y := wm_adsp.o +snd-soc-wm0010-y := wm0010.o +snd-soc-wm1250-ev1-y := wm1250-ev1.o +snd-soc-wm2000-y := wm2000.o +snd-soc-wm2200-y := wm2200.o +snd-soc-wm5100-y := wm5100.o wm5100-tables.o +snd-soc-wm5102-y := wm5102.o +snd-soc-wm5110-y := wm5110.o +snd-soc-wm8350-y := wm8350.o +snd-soc-wm8400-y := wm8400.o +snd-soc-wm8510-y := wm8510.o +snd-soc-wm8523-y := wm8523.o +snd-soc-wm8524-y := wm8524.o +snd-soc-wm8580-y := wm8580.o +snd-soc-wm8711-y := wm8711.o +snd-soc-wm8727-y := wm8727.o +snd-soc-wm8728-y := wm8728.o +snd-soc-wm8731-y := wm8731.o +snd-soc-wm8731-i2c-y := wm8731-i2c.o +snd-soc-wm8731-spi-y := wm8731-spi.o +snd-soc-wm8737-y := wm8737.o +snd-soc-wm8741-y := wm8741.o +snd-soc-wm8750-y := wm8750.o +snd-soc-wm8753-y := wm8753.o +snd-soc-wm8770-y := wm8770.o +snd-soc-wm8776-y := wm8776.o +snd-soc-wm8782-y := wm8782.o +snd-soc-wm8804-y := wm8804.o +snd-soc-wm8804-i2c-y := wm8804-i2c.o +snd-soc-wm8804-spi-y := wm8804-spi.o +snd-soc-wm8900-y := wm8900.o +snd-soc-wm8903-y := wm8903.o +snd-soc-wm8904-y := wm8904.o +snd-soc-wm8996-y := wm8996.o +snd-soc-wm8940-y := wm8940.o +snd-soc-wm8955-y := wm8955.o +snd-soc-wm8960-y := wm8960.o +snd-soc-wm8961-y := wm8961.o +snd-soc-wm8962-y := wm8962.o +snd-soc-wm8971-y := wm8971.o +snd-soc-wm8974-y := wm8974.o +snd-soc-wm8978-y := wm8978.o +snd-soc-wm8983-y := wm8983.o +snd-soc-wm8985-y := wm8985.o +snd-soc-wm8988-y := wm8988.o +snd-soc-wm8990-y := wm8990.o +snd-soc-wm8991-y := wm8991.o +snd-soc-wm8993-y := wm8993.o +snd-soc-wm8994-y := wm8994.o wm8958-dsp2.o +snd-soc-wm8995-y := wm8995.o +snd-soc-wm8997-y := wm8997.o +snd-soc-wm8998-y := wm8998.o +snd-soc-wm9081-y := wm9081.o +snd-soc-wm9090-y := wm9090.o +snd-soc-wm9705-y := wm9705.o +snd-soc-wm9712-y := wm9712.o +snd-soc-wm9713-y := wm9713.o +snd-soc-wm-hubs-y := wm_hubs.o +snd-soc-wsa881x-y := wsa881x.o +snd-soc-wsa883x-y := wsa883x.o +snd-soc-wsa884x-y := wsa884x.o +snd-soc-zl38060-y := zl38060.o # Amp -snd-soc-max9877-objs := max9877.o -snd-soc-max98504-objs := max98504.o -snd-soc-simple-amplifier-objs := simple-amplifier.o -snd-soc-tpa6130a2-objs := tpa6130a2.o -snd-soc-tas2552-objs := tas2552.o -snd-soc-tas2562-objs := tas2562.o -snd-soc-tas2764-objs := tas2764.o -snd-soc-tas2780-objs := tas2780.o +snd-soc-max9877-y := max9877.o +snd-soc-max98504-y := max98504.o +snd-soc-simple-amplifier-y := simple-amplifier.o +snd-soc-tpa6130a2-y := tpa6130a2.o +snd-soc-tas2552-y := tas2552.o +snd-soc-tas2562-y := tas2562.o +snd-soc-tas2764-y := tas2764.o +snd-soc-tas2780-y := tas2780.o # Mux -snd-soc-simple-mux-objs := simple-mux.o +snd-soc-simple-mux-y := simple-mux.o obj-$(CONFIG_SND_SOC_88PM860X) += snd-soc-88pm860x.o obj-$(CONFIG_SND_SOC_AB8500_CODEC) += snd-soc-ab8500-codec.o -- cgit v1.2.3 From 01e8f66b434f3cca0690f839c417324d7471aa9b Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 7 May 2024 17:55:07 +0200 Subject: ASoC: adi: Use *-y instead of *-objs in Makefile Signed-off-by: Takashi Iwai *-objs suffix is reserved rather for (user-space) host programs while usually *-y suffix is used for kernel drivers (although *-objs works for that purpose for now). Let's correct the old usages of *-objs in Makefiles. Link: https://lore.kernel.org/r/20240507155540.24815-4-tiwai@suse.de Signed-off-by: Mark Brown --- sound/soc/adi/Makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/soc/adi/Makefile b/sound/soc/adi/Makefile index 125f667b0e08..0d2db8d05806 100644 --- a/sound/soc/adi/Makefile +++ b/sound/soc/adi/Makefile @@ -1,6 +1,6 @@ # SPDX-License-Identifier: GPL-2.0-only -snd-soc-adi-axi-i2s-objs := axi-i2s.o -snd-soc-adi-axi-spdif-objs := axi-spdif.o +snd-soc-adi-axi-i2s-y := axi-i2s.o +snd-soc-adi-axi-spdif-y := axi-spdif.o obj-$(CONFIG_SND_SOC_ADI_AXI_I2S) += snd-soc-adi-axi-i2s.o obj-$(CONFIG_SND_SOC_ADI_AXI_SPDIF) += snd-soc-adi-axi-spdif.o -- cgit v1.2.3 From 07214013578b156d0fda288a0311d353ea149674 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 7 May 2024 17:55:08 +0200 Subject: ASoC: amd: Use *-y instead of *-objs in Makefile *-objs suffix is reserved rather for (user-space) host programs while usually *-y suffix is used for kernel drivers (although *-objs works for that purpose for now). Let's correct the old usages of *-objs in Makefiles. Signed-off-by: Takashi Iwai Link: https://lore.kernel.org/r/20240507155540.24815-5-tiwai@suse.de Signed-off-by: Mark Brown --- sound/soc/amd/Makefile | 12 ++++++------ sound/soc/amd/acp/Makefile | 26 +++++++++++++------------- sound/soc/amd/ps/Makefile | 8 ++++---- sound/soc/amd/raven/Makefile | 6 +++--- sound/soc/amd/renoir/Makefile | 6 +++--- sound/soc/amd/rpl/Makefile | 2 +- sound/soc/amd/vangogh/Makefile | 8 ++++---- sound/soc/amd/yc/Makefile | 6 +++--- 8 files changed, 37 insertions(+), 37 deletions(-) diff --git a/sound/soc/amd/Makefile b/sound/soc/amd/Makefile index ebbe49c2bbff..4f89d962cce2 100644 --- a/sound/soc/amd/Makefile +++ b/sound/soc/amd/Makefile @@ -1,10 +1,10 @@ # SPDX-License-Identifier: GPL-2.0-only -acp_audio_dma-objs := acp-pcm-dma.o -snd-soc-acp-da7219mx98357-mach-objs := acp-da7219-max98357a.o -snd-soc-acp-rt5645-mach-objs := acp-rt5645.o -snd-soc-acp-es8336-mach-objs := acp-es8336.o -snd-soc-acp-rt5682-mach-objs := acp3x-rt5682-max9836.o -snd-acp-config-objs := acp-config.o +acp_audio_dma-y := acp-pcm-dma.o +snd-soc-acp-da7219mx98357-mach-y := acp-da7219-max98357a.o +snd-soc-acp-rt5645-mach-y := acp-rt5645.o +snd-soc-acp-es8336-mach-y := acp-es8336.o +snd-soc-acp-rt5682-mach-y := acp3x-rt5682-max9836.o +snd-acp-config-y := acp-config.o obj-$(CONFIG_SND_SOC_AMD_ACP) += acp_audio_dma.o obj-$(CONFIG_SND_SOC_AMD_CZ_DA7219MX98357_MACH) += snd-soc-acp-da7219mx98357-mach.o diff --git a/sound/soc/amd/acp/Makefile b/sound/soc/amd/acp/Makefile index 1fd581a2aa33..b068bf1f920e 100644 --- a/sound/soc/amd/acp/Makefile +++ b/sound/soc/amd/acp/Makefile @@ -5,23 +5,23 @@ # Copyright(c) 2021 Advanced Micro Devices, Inc. All rights reserved. #common acp driver -snd-acp-pcm-objs := acp-platform.o -snd-acp-i2s-objs := acp-i2s.o -snd-acp-pdm-objs := acp-pdm.o -snd-acp-legacy-common-objs := acp-legacy-common.o -snd-acp-pci-objs := acp-pci.o -snd-amd-sdw-acpi-objs := amd-sdw-acpi.o +snd-acp-pcm-y := acp-platform.o +snd-acp-i2s-y := acp-i2s.o +snd-acp-pdm-y := acp-pdm.o +snd-acp-legacy-common-y := acp-legacy-common.o +snd-acp-pci-y := acp-pci.o +snd-amd-sdw-acpi-y := amd-sdw-acpi.o #platform specific driver -snd-acp-renoir-objs := acp-renoir.o -snd-acp-rembrandt-objs := acp-rembrandt.o -snd-acp63-objs := acp63.o -snd-acp70-objs := acp70.o +snd-acp-renoir-y := acp-renoir.o +snd-acp-rembrandt-y := acp-rembrandt.o +snd-acp63-y := acp63.o +snd-acp70-y := acp70.o #machine specific driver -snd-acp-mach-objs := acp-mach-common.o -snd-acp-legacy-mach-objs := acp-legacy-mach.o acp3x-es83xx/acp3x-es83xx.o -snd-acp-sof-mach-objs := acp-sof-mach.o +snd-acp-mach-y := acp-mach-common.o +snd-acp-legacy-mach-y := acp-legacy-mach.o acp3x-es83xx/acp3x-es83xx.o +snd-acp-sof-mach-y := acp-sof-mach.o obj-$(CONFIG_SND_SOC_AMD_ACP_PCM) += snd-acp-pcm.o obj-$(CONFIG_SND_SOC_AMD_ACP_I2S) += snd-acp-i2s.o diff --git a/sound/soc/amd/ps/Makefile b/sound/soc/amd/ps/Makefile index b3c254886fd9..b5efb1c5382c 100644 --- a/sound/soc/amd/ps/Makefile +++ b/sound/soc/amd/ps/Makefile @@ -1,9 +1,9 @@ # SPDX-License-Identifier: GPL-2.0-only # Pink Sardine platform Support -snd-pci-ps-objs := pci-ps.o -snd-ps-pdm-dma-objs := ps-pdm-dma.o -snd-soc-ps-mach-objs := ps-mach.o -snd-ps-sdw-dma-objs := ps-sdw-dma.o +snd-pci-ps-y := pci-ps.o +snd-ps-pdm-dma-y := ps-pdm-dma.o +snd-soc-ps-mach-y := ps-mach.o +snd-ps-sdw-dma-y := ps-sdw-dma.o obj-$(CONFIG_SND_SOC_AMD_PS) += snd-pci-ps.o obj-$(CONFIG_SND_SOC_AMD_PS) += snd-ps-pdm-dma.o diff --git a/sound/soc/amd/raven/Makefile b/sound/soc/amd/raven/Makefile index 62c22b6ed95a..b2ea030cbf25 100644 --- a/sound/soc/amd/raven/Makefile +++ b/sound/soc/amd/raven/Makefile @@ -1,8 +1,8 @@ # SPDX-License-Identifier: GPL-2.0+ # Raven Ridge platform Support -snd-pci-acp3x-objs := pci-acp3x.o -snd-acp3x-pcm-dma-objs := acp3x-pcm-dma.o -snd-acp3x-i2s-objs := acp3x-i2s.o +snd-pci-acp3x-y := pci-acp3x.o +snd-acp3x-pcm-dma-y := acp3x-pcm-dma.o +snd-acp3x-i2s-y := acp3x-i2s.o obj-$(CONFIG_SND_SOC_AMD_ACP3x) += snd-pci-acp3x.o obj-$(CONFIG_SND_SOC_AMD_ACP3x) += snd-acp3x-pcm-dma.o obj-$(CONFIG_SND_SOC_AMD_ACP3x) += snd-acp3x-i2s.o diff --git a/sound/soc/amd/renoir/Makefile b/sound/soc/amd/renoir/Makefile index 4a82690aec16..76b4a9c3e24f 100644 --- a/sound/soc/amd/renoir/Makefile +++ b/sound/soc/amd/renoir/Makefile @@ -1,8 +1,8 @@ # SPDX-License-Identifier: GPL-2.0+ # Renoir platform Support -snd-rn-pci-acp3x-objs := rn-pci-acp3x.o -snd-acp3x-pdm-dma-objs := acp3x-pdm-dma.o -snd-acp3x-rn-objs := acp3x-rn.o +snd-rn-pci-acp3x-y := rn-pci-acp3x.o +snd-acp3x-pdm-dma-y := acp3x-pdm-dma.o +snd-acp3x-rn-y := acp3x-rn.o obj-$(CONFIG_SND_SOC_AMD_RENOIR) += snd-rn-pci-acp3x.o obj-$(CONFIG_SND_SOC_AMD_RENOIR) += snd-acp3x-pdm-dma.o obj-$(CONFIG_SND_SOC_AMD_RENOIR_MACH) += snd-acp3x-rn.o diff --git a/sound/soc/amd/rpl/Makefile b/sound/soc/amd/rpl/Makefile index 11a33a05e94b..a3825c5be4e7 100644 --- a/sound/soc/amd/rpl/Makefile +++ b/sound/soc/amd/rpl/Makefile @@ -1,5 +1,5 @@ # SPDX-License-Identifier: GPL-2.0+ # RPL platform Support -snd-rpl-pci-acp6x-objs := rpl-pci-acp6x.o +snd-rpl-pci-acp6x-y := rpl-pci-acp6x.o obj-$(CONFIG_SND_SOC_AMD_RPL_ACP6x) += snd-rpl-pci-acp6x.o diff --git a/sound/soc/amd/vangogh/Makefile b/sound/soc/amd/vangogh/Makefile index c9e53e04e247..7eae82faa392 100644 --- a/sound/soc/amd/vangogh/Makefile +++ b/sound/soc/amd/vangogh/Makefile @@ -1,9 +1,9 @@ # SPDX-License-Identifier: GPL-2.0+ # Vangogh platform Support -snd-pci-acp5x-objs := pci-acp5x.o -snd-acp5x-i2s-objs := acp5x-i2s.o -snd-acp5x-pcm-dma-objs := acp5x-pcm-dma.o -snd-soc-acp5x-mach-objs := acp5x-mach.o +snd-pci-acp5x-y := pci-acp5x.o +snd-acp5x-i2s-y := acp5x-i2s.o +snd-acp5x-pcm-dma-y := acp5x-pcm-dma.o +snd-soc-acp5x-mach-y := acp5x-mach.o obj-$(CONFIG_SND_SOC_AMD_ACP5x) += snd-pci-acp5x.o obj-$(CONFIG_SND_SOC_AMD_ACP5x) += snd-acp5x-i2s.o diff --git a/sound/soc/amd/yc/Makefile b/sound/soc/amd/yc/Makefile index dc2974440388..7a0a3a410b2d 100644 --- a/sound/soc/amd/yc/Makefile +++ b/sound/soc/amd/yc/Makefile @@ -1,8 +1,8 @@ # SPDX-License-Identifier: GPL-2.0+ # Yellow Carp platform Support -snd-pci-acp6x-objs := pci-acp6x.o -snd-acp6x-pdm-dma-objs := acp6x-pdm-dma.o -snd-soc-acp6x-mach-objs := acp6x-mach.o +snd-pci-acp6x-y := pci-acp6x.o +snd-acp6x-pdm-dma-y := acp6x-pdm-dma.o +snd-soc-acp6x-mach-y := acp6x-mach.o obj-$(CONFIG_SND_SOC_AMD_ACP6x) += snd-pci-acp6x.o obj-$(CONFIG_SND_SOC_AMD_ACP6x) += snd-acp6x-pdm-dma.o -- cgit v1.2.3 From fa8e54828efee5002b5aed0e315097f7ca4171d8 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 7 May 2024 17:55:09 +0200 Subject: ASoC: apple: Use *-y instead of *-objs in Makefile *-objs suffix is reserved rather for (user-space) host programs while usually *-y suffix is used for kernel drivers (although *-objs works for that purpose for now). Let's correct the old usages of *-objs in Makefiles. Signed-off-by: Takashi Iwai Link: https://lore.kernel.org/r/20240507155540.24815-6-tiwai@suse.de Signed-off-by: Mark Brown --- sound/soc/apple/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/apple/Makefile b/sound/soc/apple/Makefile index 7a30bf452817..1eb8fbef60c6 100644 --- a/sound/soc/apple/Makefile +++ b/sound/soc/apple/Makefile @@ -1,3 +1,3 @@ -snd-soc-apple-mca-objs := mca.o +snd-soc-apple-mca-y := mca.o obj-$(CONFIG_SND_SOC_APPLE_MCA) += snd-soc-apple-mca.o -- cgit v1.2.3 From 907cb79d41a7bb54d2d69bbbdd6ebb159a1d1718 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 7 May 2024 17:55:10 +0200 Subject: ASoC: atmel: Use *-y instead of *-objs in Makefile *-objs suffix is reserved rather for (user-space) host programs while usually *-y suffix is used for kernel drivers (although *-objs works for that purpose for now). Let's correct the old usages of *-objs in Makefiles. Signed-off-by: Takashi Iwai Link: https://lore.kernel.org/r/20240507155540.24815-7-tiwai@suse.de Signed-off-by: Mark Brown --- sound/soc/atmel/Makefile | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/sound/soc/atmel/Makefile b/sound/soc/atmel/Makefile index 043097a08ea8..03d9c419c93f 100644 --- a/sound/soc/atmel/Makefile +++ b/sound/soc/atmel/Makefile @@ -1,13 +1,13 @@ # SPDX-License-Identifier: GPL-2.0 # AT91 Platform Support -snd-soc-atmel-pcm-pdc-objs := atmel-pcm-pdc.o -snd-soc-atmel-pcm-dma-objs := atmel-pcm-dma.o -snd-soc-atmel_ssc_dai-objs := atmel_ssc_dai.o -snd-soc-atmel-i2s-objs := atmel-i2s.o -snd-soc-mchp-i2s-mcc-objs := mchp-i2s-mcc.o -snd-soc-mchp-spdiftx-objs := mchp-spdiftx.o -snd-soc-mchp-spdifrx-objs := mchp-spdifrx.o -snd-soc-mchp-pdmc-objs := mchp-pdmc.o +snd-soc-atmel-pcm-pdc-y := atmel-pcm-pdc.o +snd-soc-atmel-pcm-dma-y := atmel-pcm-dma.o +snd-soc-atmel_ssc_dai-y := atmel_ssc_dai.o +snd-soc-atmel-i2s-y := atmel-i2s.o +snd-soc-mchp-i2s-mcc-y := mchp-i2s-mcc.o +snd-soc-mchp-spdiftx-y := mchp-spdiftx.o +snd-soc-mchp-spdifrx-y := mchp-spdifrx.o +snd-soc-mchp-pdmc-y := mchp-pdmc.o # pdc and dma need to both be built-in if any user of # ssc is built-in. @@ -25,13 +25,13 @@ obj-$(CONFIG_SND_MCHP_SOC_SPDIFRX) += snd-soc-mchp-spdifrx.o obj-$(CONFIG_SND_MCHP_SOC_PDMC) += snd-soc-mchp-pdmc.o # AT91 Machine Support -snd-soc-sam9g20-wm8731-objs := sam9g20_wm8731.o -snd-atmel-soc-wm8904-objs := atmel_wm8904.o -snd-soc-sam9x5-wm8731-objs := sam9x5_wm8731.o -snd-atmel-soc-classd-objs := atmel-classd.o -snd-atmel-soc-pdmic-objs := atmel-pdmic.o -snd-atmel-soc-tse850-pcm5142-objs := tse850-pcm5142.o -snd-soc-mikroe-proto-objs := mikroe-proto.o +snd-soc-sam9g20-wm8731-y := sam9g20_wm8731.o +snd-atmel-soc-wm8904-y := atmel_wm8904.o +snd-soc-sam9x5-wm8731-y := sam9x5_wm8731.o +snd-atmel-soc-classd-y := atmel-classd.o +snd-atmel-soc-pdmic-y := atmel-pdmic.o +snd-atmel-soc-tse850-pcm5142-y := tse850-pcm5142.o +snd-soc-mikroe-proto-y := mikroe-proto.o obj-$(CONFIG_SND_AT91_SOC_SAM9G20_WM8731) += snd-soc-sam9g20-wm8731.o obj-$(CONFIG_SND_ATMEL_SOC_WM8904) += snd-atmel-soc-wm8904.o -- cgit v1.2.3 From ef993723af434eb91923b39dcef1623bcfa89606 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 7 May 2024 17:55:11 +0200 Subject: ASoC: au1x: Use *-y instead of *-objs Makefile *-objs suffix is reserved rather for (user-space) host programs while usually *-y suffix is used for kernel drivers (although *-objs works for that purpose for now). Let's correct the old usages of *-objs in Makefiles. Signed-off-by: Takashi Iwai Link: https://lore.kernel.org/r/20240507155540.24815-8-tiwai@suse.de Signed-off-by: Mark Brown --- sound/soc/au1x/Makefile | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/sound/soc/au1x/Makefile b/sound/soc/au1x/Makefile index 33183d7fe057..9c6f5c38f92d 100644 --- a/sound/soc/au1x/Makefile +++ b/sound/soc/au1x/Makefile @@ -1,13 +1,13 @@ # SPDX-License-Identifier: GPL-2.0 # Au1200/Au1550 PSC audio -snd-soc-au1xpsc-dbdma-objs := dbdma2.o -snd-soc-au1xpsc-i2s-objs := psc-i2s.o -snd-soc-au1xpsc-ac97-objs := psc-ac97.o +snd-soc-au1xpsc-dbdma-y := dbdma2.o +snd-soc-au1xpsc-i2s-y := psc-i2s.o +snd-soc-au1xpsc-ac97-y := psc-ac97.o # Au1000/1500/1100 Audio units -snd-soc-au1x-dma-objs := dma.o -snd-soc-au1x-ac97c-objs := ac97c.o -snd-soc-au1x-i2sc-objs := i2sc.o +snd-soc-au1x-dma-y := dma.o +snd-soc-au1x-ac97c-y := ac97c.o +snd-soc-au1x-i2sc-y := i2sc.o obj-$(CONFIG_SND_SOC_AU1XPSC) += snd-soc-au1xpsc-dbdma.o obj-$(CONFIG_SND_SOC_AU1XPSC_I2S) += snd-soc-au1xpsc-i2s.o @@ -17,8 +17,8 @@ obj-$(CONFIG_SND_SOC_AU1XAC97C) += snd-soc-au1x-ac97c.o obj-$(CONFIG_SND_SOC_AU1XI2SC) += snd-soc-au1x-i2sc.o # Boards -snd-soc-db1000-objs := db1000.o -snd-soc-db1200-objs := db1200.o +snd-soc-db1000-y := db1000.o +snd-soc-db1200-y := db1200.o obj-$(CONFIG_SND_SOC_DB1000) += snd-soc-db1000.o obj-$(CONFIG_SND_SOC_DB1200) += snd-soc-db1200.o -- cgit v1.2.3 From 37f8d0d000b55038938e90d21aa987a6db1dd31a Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 7 May 2024 17:55:12 +0200 Subject: ASoC: bcm: Use *-y instead of *-objs in Makefile *-objs suffix is reserved rather for (user-space) host programs while usually *-y suffix is used for kernel drivers (although *-objs works for that purpose for now). Let's correct the old usages of *-objs in Makefiles. Signed-off-by: Takashi Iwai Link: https://lore.kernel.org/r/20240507155540.24815-9-tiwai@suse.de Signed-off-by: Mark Brown --- sound/soc/bcm/Makefile | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/sound/soc/bcm/Makefile b/sound/soc/bcm/Makefile index 7c2d7899603b..0c1325a97b70 100644 --- a/sound/soc/bcm/Makefile +++ b/sound/soc/bcm/Makefile @@ -1,15 +1,15 @@ # SPDX-License-Identifier: GPL-2.0-only # BCM2835 Platform Support -snd-soc-bcm2835-i2s-objs := bcm2835-i2s.o +snd-soc-bcm2835-i2s-y := bcm2835-i2s.o obj-$(CONFIG_SND_BCM2835_SOC_I2S) += snd-soc-bcm2835-i2s.o # CYGNUS Platform Support -snd-soc-cygnus-objs := cygnus-pcm.o cygnus-ssp.o +snd-soc-cygnus-y := cygnus-pcm.o cygnus-ssp.o obj-$(CONFIG_SND_SOC_CYGNUS) += snd-soc-cygnus.o # BCM63XX Platform Support -snd-soc-63xx-objs := bcm63xx-i2s-whistler.o bcm63xx-pcm-whistler.o +snd-soc-63xx-y := bcm63xx-i2s-whistler.o bcm63xx-pcm-whistler.o obj-$(CONFIG_SND_BCM63XX_I2S_WHISTLER) += snd-soc-63xx.o \ No newline at end of file -- cgit v1.2.3 From 591002b84a335f538879b44dff64568875da89b3 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 7 May 2024 17:55:13 +0200 Subject: ASoC: cirrus: Use *-y instead of *-objs in Makefile *-objs suffix is reserved rather for (user-space) host programs while usually *-y suffix is used for kernel drivers (although *-objs works for that purpose for now). Let's correct the old usages of *-objs in Makefiles. Signed-off-by: Takashi Iwai Link: https://lore.kernel.org/r/20240507155540.24815-10-tiwai@suse.de Signed-off-by: Mark Brown --- sound/soc/cirrus/Makefile | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/sound/soc/cirrus/Makefile b/sound/soc/cirrus/Makefile index 19a86daad660..ad606b293715 100644 --- a/sound/soc/cirrus/Makefile +++ b/sound/soc/cirrus/Makefile @@ -1,12 +1,12 @@ # SPDX-License-Identifier: GPL-2.0 # EP93xx Platform Support -snd-soc-ep93xx-objs := ep93xx-pcm.o -snd-soc-ep93xx-i2s-objs := ep93xx-i2s.o +snd-soc-ep93xx-y := ep93xx-pcm.o +snd-soc-ep93xx-i2s-y := ep93xx-i2s.o obj-$(CONFIG_SND_EP93XX_SOC) += snd-soc-ep93xx.o obj-$(CONFIG_SND_EP93XX_SOC_I2S) += snd-soc-ep93xx-i2s.o # EP93XX Machine Support -snd-soc-edb93xx-objs := edb93xx.o +snd-soc-edb93xx-y := edb93xx.o obj-$(CONFIG_SND_EP93XX_SOC_EDB93XX) += snd-soc-edb93xx.o -- cgit v1.2.3 From fe756e1e54c62ee691a3778b3e758808d0a41ab5 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 7 May 2024 17:55:14 +0200 Subject: ASoC: fsl: Use *-y instead of *-objs in Makefile *-objs suffix is reserved rather for (user-space) host programs while usually *-y suffix is used for kernel drivers (although *-objs works for that purpose for now). Let's correct the old usages of *-objs in Makefiles. Signed-off-by: Takashi Iwai Link: https://lore.kernel.org/r/20240507155540.24815-11-tiwai@suse.de Signed-off-by: Mark Brown --- sound/soc/fsl/Makefile | 52 +++++++++++++++++++++++++------------------------- 1 file changed, 26 insertions(+), 26 deletions(-) diff --git a/sound/soc/fsl/Makefile b/sound/soc/fsl/Makefile index b45eda80c196..2fe78eed3a48 100644 --- a/sound/soc/fsl/Makefile +++ b/sound/soc/fsl/Makefile @@ -1,30 +1,30 @@ # SPDX-License-Identifier: GPL-2.0 # P1022 DS Machine Support -snd-soc-p1022-ds-objs := p1022_ds.o +snd-soc-p1022-ds-y := p1022_ds.o obj-$(CONFIG_SND_SOC_P1022_DS) += snd-soc-p1022-ds.o # P1022 RDK Machine Support -snd-soc-p1022-rdk-objs := p1022_rdk.o +snd-soc-p1022-rdk-y := p1022_rdk.o obj-$(CONFIG_SND_SOC_P1022_RDK) += snd-soc-p1022-rdk.o # Freescale SSI/DMA/SAI/SPDIF Support -snd-soc-fsl-audmix-objs := fsl_audmix.o -snd-soc-fsl-asoc-card-objs := fsl-asoc-card.o -snd-soc-fsl-asrc-objs := fsl_asrc.o fsl_asrc_dma.o -snd-soc-fsl-sai-objs := fsl_sai.o +snd-soc-fsl-audmix-y := fsl_audmix.o +snd-soc-fsl-asoc-card-y := fsl-asoc-card.o +snd-soc-fsl-asrc-y := fsl_asrc.o fsl_asrc_dma.o +snd-soc-fsl-sai-y := fsl_sai.o snd-soc-fsl-ssi-y := fsl_ssi.o snd-soc-fsl-ssi-$(CONFIG_DEBUG_FS) += fsl_ssi_dbg.o -snd-soc-fsl-spdif-objs := fsl_spdif.o -snd-soc-fsl-esai-objs := fsl_esai.o -snd-soc-fsl-micfil-objs := fsl_micfil.o -snd-soc-fsl-utils-objs := fsl_utils.o -snd-soc-fsl-dma-objs := fsl_dma.o -snd-soc-fsl-mqs-objs := fsl_mqs.o -snd-soc-fsl-easrc-objs := fsl_easrc.o -snd-soc-fsl-xcvr-objs := fsl_xcvr.o -snd-soc-fsl-aud2htx-objs := fsl_aud2htx.o -snd-soc-fsl-rpmsg-objs := fsl_rpmsg.o -snd-soc-fsl-qmc-audio-objs := fsl_qmc_audio.o +snd-soc-fsl-spdif-y := fsl_spdif.o +snd-soc-fsl-esai-y := fsl_esai.o +snd-soc-fsl-micfil-y := fsl_micfil.o +snd-soc-fsl-utils-y := fsl_utils.o +snd-soc-fsl-dma-y := fsl_dma.o +snd-soc-fsl-mqs-y := fsl_mqs.o +snd-soc-fsl-easrc-y := fsl_easrc.o +snd-soc-fsl-xcvr-y := fsl_xcvr.o +snd-soc-fsl-aud2htx-y := fsl_aud2htx.o +snd-soc-fsl-rpmsg-y := fsl_rpmsg.o +snd-soc-fsl-qmc-audio-y := fsl_qmc_audio.o obj-$(CONFIG_SND_SOC_FSL_AUDMIX) += snd-soc-fsl-audmix.o obj-$(CONFIG_SND_SOC_FSL_ASOC_CARD) += snd-soc-fsl-asoc-card.o @@ -53,7 +53,7 @@ obj-$(CONFIG_SND_MPC52xx_SOC_PCM030) += pcm030-audio-fabric.o obj-$(CONFIG_SND_MPC52xx_SOC_EFIKA) += efika-audio-fabric.o # i.MX Platform Support -snd-soc-imx-audmux-objs := imx-audmux.o +snd-soc-imx-audmux-y := imx-audmux.o obj-$(CONFIG_SND_SOC_IMX_AUDMUX) += snd-soc-imx-audmux.o obj-$(CONFIG_SND_SOC_IMX_PCM_FIQ) += imx-pcm-fiq.o @@ -62,14 +62,14 @@ obj-$(CONFIG_SND_SOC_IMX_AUDIO_RPMSG) += imx-audio-rpmsg.o obj-$(CONFIG_SND_SOC_IMX_PCM_RPMSG) += imx-pcm-rpmsg.o # i.MX Machine Support -snd-soc-eukrea-tlv320-objs := eukrea-tlv320.o -snd-soc-imx-es8328-objs := imx-es8328.o -snd-soc-imx-sgtl5000-objs := imx-sgtl5000.o -snd-soc-imx-spdif-objs := imx-spdif.o -snd-soc-imx-audmix-objs := imx-audmix.o -snd-soc-imx-hdmi-objs := imx-hdmi.o -snd-soc-imx-rpmsg-objs := imx-rpmsg.o -snd-soc-imx-card-objs := imx-card.o +snd-soc-eukrea-tlv320-y := eukrea-tlv320.o +snd-soc-imx-es8328-y := imx-es8328.o +snd-soc-imx-sgtl5000-y := imx-sgtl5000.o +snd-soc-imx-spdif-y := imx-spdif.o +snd-soc-imx-audmix-y := imx-audmix.o +snd-soc-imx-hdmi-y := imx-hdmi.o +snd-soc-imx-rpmsg-y := imx-rpmsg.o +snd-soc-imx-card-y := imx-card.o obj-$(CONFIG_SND_SOC_EUKREA_TLV320) += snd-soc-eukrea-tlv320.o obj-$(CONFIG_SND_SOC_IMX_ES8328) += snd-soc-imx-es8328.o -- cgit v1.2.3 From 76560b808b41267cd08a538d2ad536f557c510f3 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 7 May 2024 17:55:15 +0200 Subject: ASoC: generic: Use *-y instead of *-objs in Makefile *-objs suffix is reserved rather for (user-space) host programs while usually *-y suffix is used for kernel drivers (although *-objs works for that purpose for now). Let's correct the old usages of *-objs in Makefiles. Signed-off-by: Takashi Iwai Link: https://lore.kernel.org/r/20240507155540.24815-12-tiwai@suse.de Signed-off-by: Mark Brown --- sound/soc/generic/Makefile | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/sound/soc/generic/Makefile b/sound/soc/generic/Makefile index 084862156506..d5abb3eed3df 100644 --- a/sound/soc/generic/Makefile +++ b/sound/soc/generic/Makefile @@ -1,10 +1,10 @@ # SPDX-License-Identifier: GPL-2.0 -snd-soc-simple-card-utils-objs := simple-card-utils.o -snd-soc-simple-card-objs := simple-card.o -snd-soc-audio-graph-card-objs := audio-graph-card.o -snd-soc-audio-graph-card2-objs := audio-graph-card2.o -snd-soc-audio-graph-card2-custom-sample-objs := audio-graph-card2-custom-sample.o -snd-soc-test-component-objs := test-component.o +snd-soc-simple-card-utils-y := simple-card-utils.o +snd-soc-simple-card-y := simple-card.o +snd-soc-audio-graph-card-y := audio-graph-card.o +snd-soc-audio-graph-card2-y := audio-graph-card2.o +snd-soc-audio-graph-card2-custom-sample-y := audio-graph-card2-custom-sample.o +snd-soc-test-component-y := test-component.o obj-$(CONFIG_SND_SIMPLE_CARD_UTILS) += snd-soc-simple-card-utils.o obj-$(CONFIG_SND_SIMPLE_CARD) += snd-soc-simple-card.o -- cgit v1.2.3 From 590d82e6e6284eba3e99d15264779c4369709291 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 7 May 2024 17:55:16 +0200 Subject: ASoC: intel: Use *-y instead of *-objs in Makefile *-objs suffix is reserved rather for (user-space) host programs while usually *-y suffix is used for kernel drivers (although *-objs works for that purpose for now). Let's correct the old usages of *-objs in Makefiles. Signed-off-by: Takashi Iwai Link: https://lore.kernel.org/r/20240507155540.24815-13-tiwai@suse.de Signed-off-by: Mark Brown --- sound/soc/intel/atom/Makefile | 2 +- sound/soc/intel/atom/sst/Makefile | 6 +-- sound/soc/intel/avs/Makefile | 10 ++--- sound/soc/intel/avs/boards/Makefile | 34 +++++++-------- sound/soc/intel/boards/Makefile | 84 ++++++++++++++++++------------------- sound/soc/intel/catpt/Makefile | 2 +- sound/soc/intel/common/Makefile | 8 ++-- sound/soc/intel/keembay/Makefile | 2 +- sound/soc/intel/skylake/Makefile | 6 +-- 9 files changed, 77 insertions(+), 77 deletions(-) diff --git a/sound/soc/intel/atom/Makefile b/sound/soc/intel/atom/Makefile index c66f03f5d8d6..38e4876025c7 100644 --- a/sound/soc/intel/atom/Makefile +++ b/sound/soc/intel/atom/Makefile @@ -1,5 +1,5 @@ # SPDX-License-Identifier: GPL-2.0-only -snd-soc-sst-atom-hifi2-platform-objs := sst-mfld-platform-pcm.o \ +snd-soc-sst-atom-hifi2-platform-y := sst-mfld-platform-pcm.o \ sst-mfld-platform-compress.o \ sst-atom-controls.o diff --git a/sound/soc/intel/atom/sst/Makefile b/sound/soc/intel/atom/sst/Makefile index 5761d30a5f9d..16be0463424d 100644 --- a/sound/soc/intel/atom/sst/Makefile +++ b/sound/soc/intel/atom/sst/Makefile @@ -1,7 +1,7 @@ # SPDX-License-Identifier: GPL-2.0-only -snd-intel-sst-core-objs := sst.o sst_ipc.o sst_stream.o sst_drv_interface.o sst_loader.o sst_pvt.o -snd-intel-sst-pci-objs += sst_pci.o -snd-intel-sst-acpi-objs += sst_acpi.o +snd-intel-sst-core-y := sst.o sst_ipc.o sst_stream.o sst_drv_interface.o sst_loader.o sst_pvt.o +snd-intel-sst-pci-y += sst_pci.o +snd-intel-sst-acpi-y += sst_acpi.o obj-$(CONFIG_SND_SST_ATOM_HIFI2_PLATFORM) += snd-intel-sst-core.o obj-$(CONFIG_SND_SST_ATOM_HIFI2_PLATFORM_PCI) += snd-intel-sst-pci.o diff --git a/sound/soc/intel/avs/Makefile b/sound/soc/intel/avs/Makefile index 5480500337f8..5139a019a4ad 100644 --- a/sound/soc/intel/avs/Makefile +++ b/sound/soc/intel/avs/Makefile @@ -1,17 +1,17 @@ # SPDX-License-Identifier: GPL-2.0-only -snd-soc-avs-objs := dsp.o ipc.o messages.o utils.o core.o loader.o \ +snd-soc-avs-y := dsp.o ipc.o messages.o utils.o core.o loader.o \ topology.o path.o pcm.o board_selection.o control.o \ sysfs.o -snd-soc-avs-objs += cldma.o -snd-soc-avs-objs += skl.o apl.o cnl.o icl.o tgl.o +snd-soc-avs-y += cldma.o +snd-soc-avs-y += skl.o apl.o cnl.o icl.o tgl.o -snd-soc-avs-objs += trace.o +snd-soc-avs-y += trace.o # tell define_trace.h where to find the trace header CFLAGS_trace.o := -I$(src) ifneq ($(CONFIG_DEBUG_FS),) -snd-soc-avs-objs += probes.o debugfs.o +snd-soc-avs-y += probes.o debugfs.o endif obj-$(CONFIG_SND_SOC_INTEL_AVS) += snd-soc-avs.o diff --git a/sound/soc/intel/avs/boards/Makefile b/sound/soc/intel/avs/boards/Makefile index 0ff21d55be24..4fbd936ffb3e 100644 --- a/sound/soc/intel/avs/boards/Makefile +++ b/sound/soc/intel/avs/boards/Makefile @@ -1,22 +1,22 @@ # SPDX-License-Identifier: GPL-2.0-only -snd-soc-avs-da7219-objs := da7219.o -snd-soc-avs-dmic-objs := dmic.o -snd-soc-avs-es8336-objs := es8336.o -snd-soc-avs-hdaudio-objs := hdaudio.o -snd-soc-avs-i2s-test-objs := i2s_test.o -snd-soc-avs-max98927-objs := max98927.o -snd-soc-avs-max98357a-objs := max98357a.o -snd-soc-avs-max98373-objs := max98373.o -snd-soc-avs-nau8825-objs := nau8825.o -snd-soc-avs-probe-objs := probe.o -snd-soc-avs-rt274-objs := rt274.o -snd-soc-avs-rt286-objs := rt286.o -snd-soc-avs-rt298-objs := rt298.o -snd-soc-avs-rt5514-objs := rt5514.o -snd-soc-avs-rt5663-objs := rt5663.o -snd-soc-avs-rt5682-objs := rt5682.o -snd-soc-avs-ssm4567-objs := ssm4567.o +snd-soc-avs-da7219-y := da7219.o +snd-soc-avs-dmic-y := dmic.o +snd-soc-avs-es8336-y := es8336.o +snd-soc-avs-hdaudio-y := hdaudio.o +snd-soc-avs-i2s-test-y := i2s_test.o +snd-soc-avs-max98927-y := max98927.o +snd-soc-avs-max98357a-y := max98357a.o +snd-soc-avs-max98373-y := max98373.o +snd-soc-avs-nau8825-y := nau8825.o +snd-soc-avs-probe-y := probe.o +snd-soc-avs-rt274-y := rt274.o +snd-soc-avs-rt286-y := rt286.o +snd-soc-avs-rt298-y := rt298.o +snd-soc-avs-rt5514-y := rt5514.o +snd-soc-avs-rt5663-y := rt5663.o +snd-soc-avs-rt5682-y := rt5682.o +snd-soc-avs-ssm4567-y := ssm4567.o obj-$(CONFIG_SND_SOC_INTEL_AVS_MACH_DA7219) += snd-soc-avs-da7219.o obj-$(CONFIG_SND_SOC_INTEL_AVS_MACH_DMIC) += snd-soc-avs-dmic.o diff --git a/sound/soc/intel/boards/Makefile b/sound/soc/intel/boards/Makefile index 963005055730..dc6fe110f279 100644 --- a/sound/soc/intel/boards/Makefile +++ b/sound/soc/intel/boards/Makefile @@ -1,40 +1,40 @@ # SPDX-License-Identifier: GPL-2.0-only -snd-soc-hsw-rt5640-objs := hsw_rt5640.o -snd-soc-sst-bdw-rt5650-mach-objs := bdw-rt5650.o -snd-soc-sst-bdw-rt5677-mach-objs := bdw-rt5677.o -snd-soc-bdw-rt286-objs := bdw_rt286.o -snd-soc-sst-bxt-da7219_max98357a-objs := bxt_da7219_max98357a.o -snd-soc-sst-bxt-rt298-objs := bxt_rt298.o -snd-soc-sst-sof-pcm512x-objs := sof_pcm512x.o -snd-soc-sst-sof-wm8804-objs := sof_wm8804.o -snd-soc-sst-bytcr-rt5640-objs := bytcr_rt5640.o -snd-soc-sst-bytcr-rt5651-objs := bytcr_rt5651.o -snd-soc-sst-bytcr-wm5102-objs := bytcr_wm5102.o -snd-soc-sst-cht-bsw-rt5672-objs := cht_bsw_rt5672.o -snd-soc-sst-cht-bsw-rt5645-objs := cht_bsw_rt5645.o -snd-soc-sst-cht-bsw-max98090_ti-objs := cht_bsw_max98090_ti.o -snd-soc-sst-cht-bsw-nau8824-objs := cht_bsw_nau8824.o -snd-soc-sst-byt-cht-cx2072x-objs := bytcht_cx2072x.o -snd-soc-sst-byt-cht-da7213-objs := bytcht_da7213.o -snd-soc-sst-byt-cht-es8316-objs := bytcht_es8316.o -snd-soc-sst-byt-cht-nocodec-objs := bytcht_nocodec.o -snd-soc-sof_rt5682-objs := sof_rt5682.o -snd-soc-sof_cs42l42-objs := sof_cs42l42.o -snd-soc-sof_es8336-objs := sof_es8336.o -snd-soc-sof_nau8825-objs := sof_nau8825.o -snd-soc-sof_da7219-objs := sof_da7219.o -snd-soc-kbl_da7219_max98357a-objs := kbl_da7219_max98357a.o -snd-soc-kbl_da7219_max98927-objs := kbl_da7219_max98927.o -snd-soc-kbl_rt5663_max98927-objs := kbl_rt5663_max98927.o -snd-soc-kbl_rt5663_rt5514_max98927-objs := kbl_rt5663_rt5514_max98927.o -snd-soc-kbl_rt5660-objs := kbl_rt5660.o -snd-soc-skl_rt286-objs := skl_rt286.o -snd-soc-skl_hda_dsp-objs := skl_hda_dsp_generic.o skl_hda_dsp_common.o -snd-skl_nau88l25_max98357a-objs := skl_nau88l25_max98357a.o -snd-soc-skl_nau88l25_ssm4567-objs := skl_nau88l25_ssm4567.o -snd-soc-ehl-rt5660-objs := ehl_rt5660.o -snd-soc-sof-ssp-amp-objs := sof_ssp_amp.o -snd-soc-sof-sdw-objs += sof_sdw.o \ +snd-soc-hsw-rt5640-y := hsw_rt5640.o +snd-soc-sst-bdw-rt5650-mach-y := bdw-rt5650.o +snd-soc-sst-bdw-rt5677-mach-y := bdw-rt5677.o +snd-soc-bdw-rt286-y := bdw_rt286.o +snd-soc-sst-bxt-da7219_max98357a-y := bxt_da7219_max98357a.o +snd-soc-sst-bxt-rt298-y := bxt_rt298.o +snd-soc-sst-sof-pcm512x-y := sof_pcm512x.o +snd-soc-sst-sof-wm8804-y := sof_wm8804.o +snd-soc-sst-bytcr-rt5640-y := bytcr_rt5640.o +snd-soc-sst-bytcr-rt5651-y := bytcr_rt5651.o +snd-soc-sst-bytcr-wm5102-y := bytcr_wm5102.o +snd-soc-sst-cht-bsw-rt5672-y := cht_bsw_rt5672.o +snd-soc-sst-cht-bsw-rt5645-y := cht_bsw_rt5645.o +snd-soc-sst-cht-bsw-max98090_ti-y := cht_bsw_max98090_ti.o +snd-soc-sst-cht-bsw-nau8824-y := cht_bsw_nau8824.o +snd-soc-sst-byt-cht-cx2072x-y := bytcht_cx2072x.o +snd-soc-sst-byt-cht-da7213-y := bytcht_da7213.o +snd-soc-sst-byt-cht-es8316-y := bytcht_es8316.o +snd-soc-sst-byt-cht-nocodec-y := bytcht_nocodec.o +snd-soc-sof_rt5682-y := sof_rt5682.o +snd-soc-sof_cs42l42-y := sof_cs42l42.o +snd-soc-sof_es8336-y := sof_es8336.o +snd-soc-sof_nau8825-y := sof_nau8825.o +snd-soc-sof_da7219-y := sof_da7219.o +snd-soc-kbl_da7219_max98357a-y := kbl_da7219_max98357a.o +snd-soc-kbl_da7219_max98927-y := kbl_da7219_max98927.o +snd-soc-kbl_rt5663_max98927-y := kbl_rt5663_max98927.o +snd-soc-kbl_rt5663_rt5514_max98927-y := kbl_rt5663_rt5514_max98927.o +snd-soc-kbl_rt5660-y := kbl_rt5660.o +snd-soc-skl_rt286-y := skl_rt286.o +snd-soc-skl_hda_dsp-y := skl_hda_dsp_generic.o skl_hda_dsp_common.o +snd-skl_nau88l25_max98357a-y := skl_nau88l25_max98357a.o +snd-soc-skl_nau88l25_ssm4567-y := skl_nau88l25_ssm4567.o +snd-soc-ehl-rt5660-y := ehl_rt5660.o +snd-soc-sof-ssp-amp-y := sof_ssp_amp.o +snd-soc-sof-sdw-y += sof_sdw.o \ sof_sdw_maxim.o sof_sdw_rt_amp.o \ bridge_cs35l56.o \ sof_sdw_rt5682.o sof_sdw_rt700.o \ @@ -83,20 +83,20 @@ obj-$(CONFIG_SND_SOC_INTEL_SOUNDWIRE_SOF_MACH) += snd-soc-sof-sdw.o obj-$(CONFIG_SND_SOC_INTEL_SOF_SSP_AMP_MACH) += snd-soc-sof-ssp-amp.o # common modules -snd-soc-intel-hda-dsp-common-objs := hda_dsp_common.o +snd-soc-intel-hda-dsp-common-y := hda_dsp_common.o obj-$(CONFIG_SND_SOC_INTEL_HDA_DSP_COMMON) += snd-soc-intel-hda-dsp-common.o -snd-soc-intel-sof-maxim-common-objs += sof_maxim_common.o +snd-soc-intel-sof-maxim-common-y += sof_maxim_common.o obj-$(CONFIG_SND_SOC_INTEL_SOF_MAXIM_COMMON) += snd-soc-intel-sof-maxim-common.o -snd-soc-intel-sof-realtek-common-objs += sof_realtek_common.o +snd-soc-intel-sof-realtek-common-y += sof_realtek_common.o obj-$(CONFIG_SND_SOC_INTEL_SOF_REALTEK_COMMON) += snd-soc-intel-sof-realtek-common.o -snd-soc-intel-sof-cirrus-common-objs += sof_cirrus_common.o +snd-soc-intel-sof-cirrus-common-y += sof_cirrus_common.o obj-$(CONFIG_SND_SOC_INTEL_SOF_CIRRUS_COMMON) += snd-soc-intel-sof-cirrus-common.o -snd-soc-intel-sof-nuvoton-common-objs += sof_nuvoton_common.o +snd-soc-intel-sof-nuvoton-common-y += sof_nuvoton_common.o obj-$(CONFIG_SND_SOC_INTEL_SOF_NUVOTON_COMMON) += snd-soc-intel-sof-nuvoton-common.o -snd-soc-intel-sof-board-helpers-objs += sof_board_helpers.o +snd-soc-intel-sof-board-helpers-y += sof_board_helpers.o obj-$(CONFIG_SND_SOC_INTEL_SOF_BOARD_HELPERS) += snd-soc-intel-sof-board-helpers.o diff --git a/sound/soc/intel/catpt/Makefile b/sound/soc/intel/catpt/Makefile index c393a45795da..f5f6a7e956ce 100644 --- a/sound/soc/intel/catpt/Makefile +++ b/sound/soc/intel/catpt/Makefile @@ -1,4 +1,4 @@ -snd-soc-catpt-objs := device.o dsp.o loader.o ipc.o messages.o pcm.o sysfs.o +snd-soc-catpt-y := device.o dsp.o loader.o ipc.o messages.o pcm.o sysfs.o # tell define_trace.h where to find the trace header CFLAGS_device.o := -I$(src) diff --git a/sound/soc/intel/common/Makefile b/sound/soc/intel/common/Makefile index a86457674726..40a74a19c508 100644 --- a/sound/soc/intel/common/Makefile +++ b/sound/soc/intel/common/Makefile @@ -1,7 +1,7 @@ # SPDX-License-Identifier: GPL-2.0-only -snd-soc-sst-dsp-objs := sst-dsp.o -snd-soc-sst-ipc-objs := sst-ipc.o -snd-soc-acpi-intel-match-objs := soc-acpi-intel-byt-match.o soc-acpi-intel-cht-match.o \ +snd-soc-sst-dsp-y := sst-dsp.o +snd-soc-sst-ipc-y := sst-ipc.o +snd-soc-acpi-intel-match-y := soc-acpi-intel-byt-match.o soc-acpi-intel-cht-match.o \ soc-acpi-intel-hsw-bdw-match.o \ soc-acpi-intel-skl-match.o soc-acpi-intel-kbl-match.o \ soc-acpi-intel-bxt-match.o soc-acpi-intel-glk-match.o \ @@ -15,7 +15,7 @@ snd-soc-acpi-intel-match-objs := soc-acpi-intel-byt-match.o soc-acpi-intel-cht-m soc-acpi-intel-hda-match.o \ soc-acpi-intel-sdw-mockup-match.o -snd-soc-acpi-intel-match-objs += soc-acpi-intel-ssp-common.o +snd-soc-acpi-intel-match-y += soc-acpi-intel-ssp-common.o obj-$(CONFIG_SND_SOC_INTEL_SST) += snd-soc-sst-dsp.o snd-soc-sst-ipc.o obj-$(CONFIG_SND_SOC_ACPI_INTEL_MATCH) += snd-soc-acpi-intel-match.o diff --git a/sound/soc/intel/keembay/Makefile b/sound/soc/intel/keembay/Makefile index 9084e8c63854..3da9a6f9ba2a 100644 --- a/sound/soc/intel/keembay/Makefile +++ b/sound/soc/intel/keembay/Makefile @@ -1,4 +1,4 @@ -snd-soc-kmb_platform-objs := \ +snd-soc-kmb_platform-y := \ kmb_platform.o obj-$(CONFIG_SND_SOC_INTEL_KEEMBAY) += snd-soc-kmb_platform.o diff --git a/sound/soc/intel/skylake/Makefile b/sound/soc/intel/skylake/Makefile index 1c4649bccec5..ad9be6168428 100644 --- a/sound/soc/intel/skylake/Makefile +++ b/sound/soc/intel/skylake/Makefile @@ -1,15 +1,15 @@ # SPDX-License-Identifier: GPL-2.0-only -snd-soc-skl-objs := skl.o skl-pcm.o skl-nhlt.o skl-messages.o skl-topology.o \ +snd-soc-skl-y := skl.o skl-pcm.o skl-nhlt.o skl-messages.o skl-topology.o \ skl-sst-ipc.o skl-sst-dsp.o cnl-sst-dsp.o skl-sst-cldma.o \ skl-sst.o bxt-sst.o cnl-sst.o skl-sst-utils.o ifdef CONFIG_DEBUG_FS - snd-soc-skl-objs += skl-debug.o + snd-soc-skl-y += skl-debug.o endif obj-$(CONFIG_SND_SOC_INTEL_SKYLAKE_COMMON) += snd-soc-skl.o #Skylake Clock device support -snd-soc-skl-ssp-clk-objs := skl-ssp-clk.o +snd-soc-skl-ssp-clk-y := skl-ssp-clk.o obj-$(CONFIG_SND_SOC_INTEL_SKYLAKE_SSP_CLK) += snd-soc-skl-ssp-clk.o -- cgit v1.2.3 From f7d09b7d4d709b34ccb0ca8fd626a499fa672a6d Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 7 May 2024 17:55:17 +0200 Subject: ASoC: jz4740: Use *-y instead of *-objs in Makefile *-objs suffix is reserved rather for (user-space) host programs while usually *-y suffix is used for kernel drivers (although *-objs works for that purpose for now). Let's correct the old usages of *-objs in Makefiles. Signed-off-by: Takashi Iwai Link: https://lore.kernel.org/r/20240507155540.24815-14-tiwai@suse.de Signed-off-by: Mark Brown --- sound/soc/jz4740/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/jz4740/Makefile b/sound/soc/jz4740/Makefile index f8701c9b09fe..1c7f3f375318 100644 --- a/sound/soc/jz4740/Makefile +++ b/sound/soc/jz4740/Makefile @@ -2,6 +2,6 @@ # # Jz4740 Platform Support # -snd-soc-jz4740-i2s-objs := jz4740-i2s.o +snd-soc-jz4740-i2s-y := jz4740-i2s.o obj-$(CONFIG_SND_JZ4740_SOC_I2S) += snd-soc-jz4740-i2s.o -- cgit v1.2.3 From 7ca27af84fc3cef3a8769bbef278e460d794c603 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 7 May 2024 17:55:18 +0200 Subject: ASoC: kirkwood: Use *-y instead of *-objs in Makefile *-objs suffix is reserved rather for (user-space) host programs while usually *-y suffix is used for kernel drivers (although *-objs works for that purpose for now). Let's correct the old usages of *-objs in Makefiles. Signed-off-by: Takashi Iwai Link: https://lore.kernel.org/r/20240507155540.24815-15-tiwai@suse.de Signed-off-by: Mark Brown --- sound/soc/kirkwood/Makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/soc/kirkwood/Makefile b/sound/soc/kirkwood/Makefile index e2d279f16a46..9be1eb8203a1 100644 --- a/sound/soc/kirkwood/Makefile +++ b/sound/soc/kirkwood/Makefile @@ -1,8 +1,8 @@ # SPDX-License-Identifier: GPL-2.0-only -snd-soc-kirkwood-objs := kirkwood-dma.o kirkwood-i2s.o +snd-soc-kirkwood-y := kirkwood-dma.o kirkwood-i2s.o obj-$(CONFIG_SND_KIRKWOOD_SOC) += snd-soc-kirkwood.o -snd-soc-armada-370-db-objs := armada-370-db.o +snd-soc-armada-370-db-y := armada-370-db.o obj-$(CONFIG_SND_KIRKWOOD_SOC_ARMADA370_DB) += snd-soc-armada-370-db.o -- cgit v1.2.3 From 3299aa652dee0d9e61cf7223a5e0bf131faec63f Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 7 May 2024 17:55:19 +0200 Subject: ASoC: loongson: Use *-y instead of *-objs in Makefile *-objs suffix is reserved rather for (user-space) host programs while usually *-y suffix is used for kernel drivers (although *-objs works for that purpose for now). Let's correct the old usages of *-objs in Makefiles. Signed-off-by: Takashi Iwai Link: https://lore.kernel.org/r/20240507155540.24815-16-tiwai@suse.de Signed-off-by: Mark Brown --- sound/soc/loongson/Makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/soc/loongson/Makefile b/sound/soc/loongson/Makefile index 601a905a4860..578030ad6563 100644 --- a/sound/soc/loongson/Makefile +++ b/sound/soc/loongson/Makefile @@ -1,8 +1,8 @@ # SPDX-License-Identifier: GPL-2.0 #Platform Support -snd-soc-loongson-i2s-pci-objs := loongson_i2s_pci.o loongson_i2s.o loongson_dma.o +snd-soc-loongson-i2s-pci-y := loongson_i2s_pci.o loongson_i2s.o loongson_dma.o obj-$(CONFIG_SND_SOC_LOONGSON_I2S_PCI) += snd-soc-loongson-i2s-pci.o #Machine Support -snd-soc-loongson-card-objs := loongson_card.o +snd-soc-loongson-card-y := loongson_card.o obj-$(CONFIG_SND_SOC_LOONGSON_CARD) += snd-soc-loongson-card.o -- cgit v1.2.3 From 9d819c244a478099828f76a92be4b71360073207 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 7 May 2024 17:55:20 +0200 Subject: ASoC: mediatek: Use *-y instead of *-objs in Makefile *-objs suffix is reserved rather for (user-space) host programs while usually *-y suffix is used for kernel drivers (although *-objs works for that purpose for now). Let's correct the old usages of *-objs in Makefiles. Signed-off-by: Takashi Iwai Link: https://lore.kernel.org/r/20240507155540.24815-17-tiwai@suse.de Signed-off-by: Mark Brown --- sound/soc/mediatek/common/Makefile | 4 ++-- sound/soc/mediatek/mt2701/Makefile | 2 +- sound/soc/mediatek/mt6797/Makefile | 2 +- sound/soc/mediatek/mt7986/Makefile | 2 +- sound/soc/mediatek/mt8183/Makefile | 2 +- sound/soc/mediatek/mt8186/Makefile | 2 +- sound/soc/mediatek/mt8188/Makefile | 2 +- sound/soc/mediatek/mt8192/Makefile | 2 +- sound/soc/mediatek/mt8195/Makefile | 2 +- 9 files changed, 10 insertions(+), 10 deletions(-) diff --git a/sound/soc/mediatek/common/Makefile b/sound/soc/mediatek/common/Makefile index 363cc258a3d5..c90d276cf4ed 100644 --- a/sound/soc/mediatek/common/Makefile +++ b/sound/soc/mediatek/common/Makefile @@ -1,7 +1,7 @@ # SPDX-License-Identifier: GPL-2.0 # platform driver -snd-soc-mtk-common-objs := mtk-afe-platform-driver.o mtk-afe-fe-dai.o mtk-dsp-sof-common.o mtk-soundcard-driver.o -snd-soc-mtk-common-objs += mtk-dai-adda-common.o +snd-soc-mtk-common-y := mtk-afe-platform-driver.o mtk-afe-fe-dai.o mtk-dsp-sof-common.o mtk-soundcard-driver.o +snd-soc-mtk-common-y += mtk-dai-adda-common.o obj-$(CONFIG_SND_SOC_MEDIATEK) += snd-soc-mtk-common.o diff --git a/sound/soc/mediatek/mt2701/Makefile b/sound/soc/mediatek/mt2701/Makefile index 21d5e697cfa7..507fa26c3945 100644 --- a/sound/soc/mediatek/mt2701/Makefile +++ b/sound/soc/mediatek/mt2701/Makefile @@ -1,6 +1,6 @@ # SPDX-License-Identifier: GPL-2.0 # platform driver -snd-soc-mt2701-afe-objs := mt2701-afe-pcm.o mt2701-afe-clock-ctrl.o +snd-soc-mt2701-afe-y := mt2701-afe-pcm.o mt2701-afe-clock-ctrl.o obj-$(CONFIG_SND_SOC_MT2701) += snd-soc-mt2701-afe.o # machine driver diff --git a/sound/soc/mediatek/mt6797/Makefile b/sound/soc/mediatek/mt6797/Makefile index bf6e179ea93f..150021495e94 100644 --- a/sound/soc/mediatek/mt6797/Makefile +++ b/sound/soc/mediatek/mt6797/Makefile @@ -1,7 +1,7 @@ # SPDX-License-Identifier: GPL-2.0 # platform driver -snd-soc-mt6797-afe-objs := \ +snd-soc-mt6797-afe-y := \ mt6797-afe-pcm.o \ mt6797-afe-clk.o \ mt6797-dai-pcm.o \ diff --git a/sound/soc/mediatek/mt7986/Makefile b/sound/soc/mediatek/mt7986/Makefile index fc4c82559b29..4b54bbe88683 100644 --- a/sound/soc/mediatek/mt7986/Makefile +++ b/sound/soc/mediatek/mt7986/Makefile @@ -1,7 +1,7 @@ # SPDX-License-Identifier: GPL-2.0 # platform driver -snd-soc-mt7986-afe-objs := \ +snd-soc-mt7986-afe-y := \ mt7986-afe-pcm.o \ mt7986-dai-etdm.o diff --git a/sound/soc/mediatek/mt8183/Makefile b/sound/soc/mediatek/mt8183/Makefile index c0a3bbc2c1f6..0d0dcdde00fc 100644 --- a/sound/soc/mediatek/mt8183/Makefile +++ b/sound/soc/mediatek/mt8183/Makefile @@ -1,7 +1,7 @@ # SPDX-License-Identifier: GPL-2.0 # platform driver -snd-soc-mt8183-afe-objs := \ +snd-soc-mt8183-afe-y := \ mt8183-afe-pcm.o \ mt8183-afe-clk.o \ mt8183-dai-i2s.o \ diff --git a/sound/soc/mediatek/mt8186/Makefile b/sound/soc/mediatek/mt8186/Makefile index fa2f0efce815..ab3f5b763df8 100644 --- a/sound/soc/mediatek/mt8186/Makefile +++ b/sound/soc/mediatek/mt8186/Makefile @@ -1,7 +1,7 @@ # SPDX-License-Identifier: GPL-2.0 # platform driver -snd-soc-mt8186-afe-objs := \ +snd-soc-mt8186-afe-y := \ mt8186-afe-pcm.o \ mt8186-audsys-clk.o \ mt8186-afe-clk.o \ diff --git a/sound/soc/mediatek/mt8188/Makefile b/sound/soc/mediatek/mt8188/Makefile index 781e61cbb22b..1178bce45c50 100644 --- a/sound/soc/mediatek/mt8188/Makefile +++ b/sound/soc/mediatek/mt8188/Makefile @@ -1,7 +1,7 @@ # SPDX-License-Identifier: GPL-2.0 # platform driver -snd-soc-mt8188-afe-objs := \ +snd-soc-mt8188-afe-y := \ mt8188-afe-clk.o \ mt8188-afe-pcm.o \ mt8188-audsys-clk.o \ diff --git a/sound/soc/mediatek/mt8192/Makefile b/sound/soc/mediatek/mt8192/Makefile index 8b27d82626ea..d60c36bcdcce 100644 --- a/sound/soc/mediatek/mt8192/Makefile +++ b/sound/soc/mediatek/mt8192/Makefile @@ -1,7 +1,7 @@ # SPDX-License-Identifier: GPL-2.0 # platform driver -snd-soc-mt8192-afe-objs := \ +snd-soc-mt8192-afe-y := \ mt8192-afe-pcm.o \ mt8192-afe-clk.o \ mt8192-afe-gpio.o \ diff --git a/sound/soc/mediatek/mt8195/Makefile b/sound/soc/mediatek/mt8195/Makefile index aae673ec751b..014e93dace26 100644 --- a/sound/soc/mediatek/mt8195/Makefile +++ b/sound/soc/mediatek/mt8195/Makefile @@ -1,7 +1,7 @@ # SPDX-License-Identifier: GPL-2.0 # platform driver -snd-soc-mt8195-afe-objs := \ +snd-soc-mt8195-afe-y := \ mt8195-audsys-clk.o \ mt8195-afe-clk.o \ mt8195-afe-pcm.o \ -- cgit v1.2.3 From bfc05938ebab6429543fcf1df1279b24953f1a7b Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 7 May 2024 17:55:21 +0200 Subject: ASoC: meson: Use *-y instead of *-objs in Makefile *-objs suffix is reserved rather for (user-space) host programs while usually *-y suffix is used for kernel drivers (although *-objs works for that purpose for now). Let's correct the old usages of *-objs in Makefiles. Signed-off-by: Takashi Iwai Link: https://lore.kernel.org/r/20240507155540.24815-18-tiwai@suse.de Signed-off-by: Mark Brown --- sound/soc/meson/Makefile | 50 ++++++++++++++++++++++++------------------------ 1 file changed, 25 insertions(+), 25 deletions(-) diff --git a/sound/soc/meson/Makefile b/sound/soc/meson/Makefile index e446bc980481..24078e4396b0 100644 --- a/sound/soc/meson/Makefile +++ b/sound/soc/meson/Makefile @@ -1,30 +1,30 @@ # SPDX-License-Identifier: (GPL-2.0 OR MIT) -snd-soc-meson-aiu-objs := aiu.o -snd-soc-meson-aiu-objs += aiu-acodec-ctrl.o -snd-soc-meson-aiu-objs += aiu-codec-ctrl.o -snd-soc-meson-aiu-objs += aiu-encoder-i2s.o -snd-soc-meson-aiu-objs += aiu-encoder-spdif.o -snd-soc-meson-aiu-objs += aiu-fifo.o -snd-soc-meson-aiu-objs += aiu-fifo-i2s.o -snd-soc-meson-aiu-objs += aiu-fifo-spdif.o -snd-soc-meson-axg-fifo-objs := axg-fifo.o -snd-soc-meson-axg-frddr-objs := axg-frddr.o -snd-soc-meson-axg-toddr-objs := axg-toddr.o -snd-soc-meson-axg-tdm-formatter-objs := axg-tdm-formatter.o -snd-soc-meson-axg-tdm-interface-objs := axg-tdm-interface.o -snd-soc-meson-axg-tdmin-objs := axg-tdmin.o -snd-soc-meson-axg-tdmout-objs := axg-tdmout.o -snd-soc-meson-axg-sound-card-objs := axg-card.o -snd-soc-meson-axg-spdifin-objs := axg-spdifin.o -snd-soc-meson-axg-spdifout-objs := axg-spdifout.o -snd-soc-meson-axg-pdm-objs := axg-pdm.o -snd-soc-meson-card-utils-objs := meson-card-utils.o -snd-soc-meson-codec-glue-objs := meson-codec-glue.o -snd-soc-meson-gx-sound-card-objs := gx-card.o -snd-soc-meson-g12a-toacodec-objs := g12a-toacodec.o -snd-soc-meson-g12a-tohdmitx-objs := g12a-tohdmitx.o -snd-soc-meson-t9015-objs := t9015.o +snd-soc-meson-aiu-y := aiu.o +snd-soc-meson-aiu-y += aiu-acodec-ctrl.o +snd-soc-meson-aiu-y += aiu-codec-ctrl.o +snd-soc-meson-aiu-y += aiu-encoder-i2s.o +snd-soc-meson-aiu-y += aiu-encoder-spdif.o +snd-soc-meson-aiu-y += aiu-fifo.o +snd-soc-meson-aiu-y += aiu-fifo-i2s.o +snd-soc-meson-aiu-y += aiu-fifo-spdif.o +snd-soc-meson-axg-fifo-y := axg-fifo.o +snd-soc-meson-axg-frddr-y := axg-frddr.o +snd-soc-meson-axg-toddr-y := axg-toddr.o +snd-soc-meson-axg-tdm-formatter-y := axg-tdm-formatter.o +snd-soc-meson-axg-tdm-interface-y := axg-tdm-interface.o +snd-soc-meson-axg-tdmin-y := axg-tdmin.o +snd-soc-meson-axg-tdmout-y := axg-tdmout.o +snd-soc-meson-axg-sound-card-y := axg-card.o +snd-soc-meson-axg-spdifin-y := axg-spdifin.o +snd-soc-meson-axg-spdifout-y := axg-spdifout.o +snd-soc-meson-axg-pdm-y := axg-pdm.o +snd-soc-meson-card-utils-y := meson-card-utils.o +snd-soc-meson-codec-glue-y := meson-codec-glue.o +snd-soc-meson-gx-sound-card-y := gx-card.o +snd-soc-meson-g12a-toacodec-y := g12a-toacodec.o +snd-soc-meson-g12a-tohdmitx-y := g12a-tohdmitx.o +snd-soc-meson-t9015-y := t9015.o obj-$(CONFIG_SND_MESON_AIU) += snd-soc-meson-aiu.o obj-$(CONFIG_SND_MESON_AXG_FIFO) += snd-soc-meson-axg-fifo.o -- cgit v1.2.3 From 62c6137ab2d0598603115f5bacff38c440a7d8c0 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 7 May 2024 17:55:22 +0200 Subject: ASoC: mxs: Use *-y instead of *-objs in Makefile *-objs suffix is reserved rather for (user-space) host programs while usually *-y suffix is used for kernel drivers (although *-objs works for that purpose for now). Let's correct the old usages of *-objs in Makefiles. Signed-off-by: Takashi Iwai Link: https://lore.kernel.org/r/20240507155540.24815-19-tiwai@suse.de Signed-off-by: Mark Brown --- sound/soc/mxs/Makefile | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/sound/soc/mxs/Makefile b/sound/soc/mxs/Makefile index ab0a9a553702..474bdd75513f 100644 --- a/sound/soc/mxs/Makefile +++ b/sound/soc/mxs/Makefile @@ -1,11 +1,11 @@ # SPDX-License-Identifier: GPL-2.0 # MXS Platform Support -snd-soc-mxs-objs := mxs-saif.o -snd-soc-mxs-pcm-objs := mxs-pcm.o +snd-soc-mxs-y := mxs-saif.o +snd-soc-mxs-pcm-y := mxs-pcm.o obj-$(CONFIG_SND_MXS_SOC) += snd-soc-mxs.o snd-soc-mxs-pcm.o # i.MX Machine Support -snd-soc-mxs-sgtl5000-objs := mxs-sgtl5000.o +snd-soc-mxs-sgtl5000-y := mxs-sgtl5000.o obj-$(CONFIG_SND_SOC_MXS_SGTL5000) += snd-soc-mxs-sgtl5000.o -- cgit v1.2.3 From 8a72584d0d7601699f7945ac84899e8a3c7cf617 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 7 May 2024 17:55:23 +0200 Subject: ASoC: pxa: Use *-y instead of *-objs in Makefile *-objs suffix is reserved rather for (user-space) host programs while usually *-y suffix is used for kernel drivers (although *-objs works for that purpose for now). Let's correct the old usages of *-objs in Makefiles. Signed-off-by: Takashi Iwai Link: https://lore.kernel.org/r/20240507155540.24815-20-tiwai@suse.de Signed-off-by: Mark Brown --- sound/soc/pxa/Makefile | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/sound/soc/pxa/Makefile b/sound/soc/pxa/Makefile index 406605fc7414..93b4e57eaa5c 100644 --- a/sound/soc/pxa/Makefile +++ b/sound/soc/pxa/Makefile @@ -1,10 +1,10 @@ # SPDX-License-Identifier: GPL-2.0 # PXA Platform Support -snd-soc-pxa2xx-objs := pxa2xx-pcm.o -snd-soc-pxa2xx-ac97-objs := pxa2xx-ac97.o -snd-soc-pxa2xx-i2s-objs := pxa2xx-i2s.o -snd-soc-pxa-ssp-objs := pxa-ssp.o -snd-soc-mmp-sspa-objs := mmp-sspa.o +snd-soc-pxa2xx-y := pxa2xx-pcm.o +snd-soc-pxa2xx-ac97-y := pxa2xx-ac97.o +snd-soc-pxa2xx-i2s-y := pxa2xx-i2s.o +snd-soc-pxa-ssp-y := pxa-ssp.o +snd-soc-mmp-sspa-y := mmp-sspa.o obj-$(CONFIG_SND_PXA2XX_SOC) += snd-soc-pxa2xx.o obj-$(CONFIG_SND_PXA2XX_SOC_AC97) += snd-soc-pxa2xx-ac97.o @@ -13,5 +13,5 @@ obj-$(CONFIG_SND_PXA_SOC_SSP) += snd-soc-pxa-ssp.o obj-$(CONFIG_SND_MMP_SOC_SSPA) += snd-soc-mmp-sspa.o # PXA Machine Support -snd-soc-spitz-objs := spitz.o +snd-soc-spitz-y := spitz.o obj-$(CONFIG_SND_PXA2XX_SOC_SPITZ) += snd-soc-spitz.o -- cgit v1.2.3 From 078f57bd555b092e85c02510a2cf8bd30773cc3b Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 7 May 2024 17:55:24 +0200 Subject: ASoC: qcom: Use *-y instead of *-objs in Makefile *-objs suffix is reserved rather for (user-space) host programs while usually *-y suffix is used for kernel drivers (although *-objs works for that purpose for now). Let's correct the old usages of *-objs in Makefiles. Signed-off-by: Takashi Iwai Link: https://lore.kernel.org/r/20240507155540.24815-21-tiwai@suse.de Signed-off-by: Mark Brown --- sound/soc/qcom/Makefile | 38 +++++++++++++++++++------------------- sound/soc/qcom/qdsp6/Makefile | 4 ++-- 2 files changed, 21 insertions(+), 21 deletions(-) diff --git a/sound/soc/qcom/Makefile b/sound/soc/qcom/Makefile index 34f3fcb8ee9a..16db7b53ddac 100644 --- a/sound/soc/qcom/Makefile +++ b/sound/soc/qcom/Makefile @@ -1,13 +1,13 @@ # SPDX-License-Identifier: GPL-2.0 # Platform -snd-soc-lpass-cpu-objs := lpass-cpu.o -snd-soc-lpass-cdc-dma-objs := lpass-cdc-dma.o -snd-soc-lpass-hdmi-objs := lpass-hdmi.o -snd-soc-lpass-platform-objs := lpass-platform.o -snd-soc-lpass-ipq806x-objs := lpass-ipq806x.o -snd-soc-lpass-apq8016-objs := lpass-apq8016.o -snd-soc-lpass-sc7180-objs := lpass-sc7180.o -snd-soc-lpass-sc7280-objs := lpass-sc7280.o +snd-soc-lpass-cpu-y := lpass-cpu.o +snd-soc-lpass-cdc-dma-y := lpass-cdc-dma.o +snd-soc-lpass-hdmi-y := lpass-hdmi.o +snd-soc-lpass-platform-y := lpass-platform.o +snd-soc-lpass-ipq806x-y := lpass-ipq806x.o +snd-soc-lpass-apq8016-y := lpass-apq8016.o +snd-soc-lpass-sc7180-y := lpass-sc7180.o +snd-soc-lpass-sc7280-y := lpass-sc7280.o obj-$(CONFIG_SND_SOC_LPASS_CPU) += snd-soc-lpass-cpu.o obj-$(CONFIG_SND_SOC_LPASS_CDC_DMA) += snd-soc-lpass-cdc-dma.o @@ -19,17 +19,17 @@ obj-$(CONFIG_SND_SOC_LPASS_SC7180) += snd-soc-lpass-sc7180.o obj-$(CONFIG_SND_SOC_LPASS_SC7280) += snd-soc-lpass-sc7280.o # Machine -snd-soc-storm-objs := storm.o -snd-soc-apq8016-sbc-objs := apq8016_sbc.o -snd-soc-apq8096-objs := apq8096.o -snd-soc-sc7180-objs := sc7180.o -snd-soc-sc7280-objs := sc7280.o -snd-soc-sdm845-objs := sdm845.o -snd-soc-sm8250-objs := sm8250.o -snd-soc-sc8280xp-objs := sc8280xp.o -snd-soc-qcom-common-objs := common.o -snd-soc-qcom-sdw-objs := sdw.o -snd-soc-x1e80100-objs := x1e80100.o +snd-soc-storm-y := storm.o +snd-soc-apq8016-sbc-y := apq8016_sbc.o +snd-soc-apq8096-y := apq8096.o +snd-soc-sc7180-y := sc7180.o +snd-soc-sc7280-y := sc7280.o +snd-soc-sdm845-y := sdm845.o +snd-soc-sm8250-y := sm8250.o +snd-soc-sc8280xp-y := sc8280xp.o +snd-soc-qcom-common-y := common.o +snd-soc-qcom-sdw-y := sdw.o +snd-soc-x1e80100-y := x1e80100.o obj-$(CONFIG_SND_SOC_STORM) += snd-soc-storm.o obj-$(CONFIG_SND_SOC_APQ8016_SBC) += snd-soc-apq8016-sbc.o diff --git a/sound/soc/qcom/qdsp6/Makefile b/sound/soc/qcom/qdsp6/Makefile index 3963bf234664..26b7c55c9c11 100644 --- a/sound/soc/qcom/qdsp6/Makefile +++ b/sound/soc/qcom/qdsp6/Makefile @@ -1,6 +1,6 @@ # SPDX-License-Identifier: GPL-2.0-only -snd-q6dsp-common-objs := q6dsp-common.o q6dsp-lpass-ports.o q6dsp-lpass-clocks.o -snd-q6apm-objs := q6apm.o audioreach.o topology.o +snd-q6dsp-common-y := q6dsp-common.o q6dsp-lpass-ports.o q6dsp-lpass-clocks.o +snd-q6apm-y := q6apm.o audioreach.o topology.o obj-$(CONFIG_SND_SOC_QDSP6_COMMON) += snd-q6dsp-common.o obj-$(CONFIG_SND_SOC_QDSP6_CORE) += q6core.o -- cgit v1.2.3 From 18db1c48515ed358a1c29e5dbda3e39a822b1864 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 7 May 2024 17:55:25 +0200 Subject: ASoC: rockchip: Use *-y instead of *-objs in Makefile *-objs suffix is reserved rather for (user-space) host programs while usually *-y suffix is used for kernel drivers (although *-objs works for that purpose for now). Let's correct the old usages of *-objs in Makefiles. Signed-off-by: Takashi Iwai Link: https://lore.kernel.org/r/20240507155540.24815-22-tiwai@suse.de Signed-off-by: Mark Brown --- sound/soc/rockchip/Makefile | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/sound/soc/rockchip/Makefile b/sound/soc/rockchip/Makefile index 30c57c0d7660..2ee9c08131d1 100644 --- a/sound/soc/rockchip/Makefile +++ b/sound/soc/rockchip/Makefile @@ -1,19 +1,19 @@ # SPDX-License-Identifier: GPL-2.0 # ROCKCHIP Platform Support -snd-soc-rockchip-i2s-objs := rockchip_i2s.o -snd-soc-rockchip-i2s-tdm-objs := rockchip_i2s_tdm.o -snd-soc-rockchip-pdm-objs := rockchip_pdm.o -snd-soc-rockchip-spdif-objs := rockchip_spdif.o +snd-soc-rockchip-i2s-y := rockchip_i2s.o +snd-soc-rockchip-i2s-tdm-y := rockchip_i2s_tdm.o +snd-soc-rockchip-pdm-y := rockchip_pdm.o +snd-soc-rockchip-spdif-y := rockchip_spdif.o obj-$(CONFIG_SND_SOC_ROCKCHIP_I2S) += snd-soc-rockchip-i2s.o obj-$(CONFIG_SND_SOC_ROCKCHIP_PDM) += snd-soc-rockchip-pdm.o obj-$(CONFIG_SND_SOC_ROCKCHIP_SPDIF) += snd-soc-rockchip-spdif.o obj-$(CONFIG_SND_SOC_ROCKCHIP_I2S_TDM) += snd-soc-rockchip-i2s-tdm.o -snd-soc-rockchip-max98090-objs := rockchip_max98090.o -snd-soc-rockchip-rt5645-objs := rockchip_rt5645.o -snd-soc-rk3288-hdmi-analog-objs := rk3288_hdmi_analog.o -snd-soc-rk3399-gru-sound-objs := rk3399_gru_sound.o +snd-soc-rockchip-max98090-y := rockchip_max98090.o +snd-soc-rockchip-rt5645-y := rockchip_rt5645.o +snd-soc-rk3288-hdmi-analog-y := rk3288_hdmi_analog.o +snd-soc-rk3399-gru-sound-y := rk3399_gru_sound.o obj-$(CONFIG_SND_SOC_ROCKCHIP_MAX98090) += snd-soc-rockchip-max98090.o obj-$(CONFIG_SND_SOC_ROCKCHIP_RT5645) += snd-soc-rockchip-rt5645.o -- cgit v1.2.3 From e93c3b9606d17344a17e061c51dc4ec0538b3345 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 7 May 2024 17:55:26 +0200 Subject: ASoC: samsung: Use *-y instead of *-objs in Makefile *-objs suffix is reserved rather for (user-space) host programs while usually *-y suffix is used for kernel drivers (although *-objs works for that purpose for now). Let's correct the old usages of *-objs in Makefiles. Signed-off-by: Takashi Iwai Link: https://lore.kernel.org/r/20240507155540.24815-23-tiwai@suse.de Signed-off-by: Mark Brown --- sound/soc/samsung/Makefile | 38 +++++++++++++++++++------------------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/sound/soc/samsung/Makefile b/sound/soc/samsung/Makefile index f5d327b90a4e..8d5f09147900 100644 --- a/sound/soc/samsung/Makefile +++ b/sound/soc/samsung/Makefile @@ -1,10 +1,10 @@ # SPDX-License-Identifier: GPL-2.0 # S3c24XX Platform Support -snd-soc-s3c-dma-objs := dmaengine.o -snd-soc-idma-objs := idma.o -snd-soc-samsung-spdif-objs := spdif.o -snd-soc-pcm-objs := pcm.o -snd-soc-i2s-objs := i2s.o +snd-soc-s3c-dma-y := dmaengine.o +snd-soc-idma-y := idma.o +snd-soc-samsung-spdif-y := spdif.o +snd-soc-pcm-y := pcm.o +snd-soc-i2s-y := i2s.o obj-$(CONFIG_SND_SOC_SAMSUNG) += snd-soc-s3c-dma.o obj-$(CONFIG_SND_SAMSUNG_SPDIF) += snd-soc-samsung-spdif.o @@ -13,20 +13,20 @@ obj-$(CONFIG_SND_SAMSUNG_I2S) += snd-soc-i2s.o obj-$(CONFIG_SND_SAMSUNG_I2S) += snd-soc-idma.o # S3C24XX Machine Support -snd-soc-smdk-wm8994-objs := smdk_wm8994.o -snd-soc-snow-objs := snow.o -snd-soc-smdk-spdif-objs := smdk_spdif.o -snd-soc-smdk-wm8994pcm-objs := smdk_wm8994pcm.o -snd-soc-speyside-objs := speyside.o -snd-soc-tobermory-objs := tobermory.o -snd-soc-lowland-objs := lowland.o -snd-soc-littlemill-objs := littlemill.o -snd-soc-bells-objs := bells.o -snd-soc-odroid-objs := odroid.o -snd-soc-arndale-objs := arndale.o -snd-soc-tm2-wm5110-objs := tm2_wm5110.o -snd-soc-aries-wm8994-objs := aries_wm8994.o -snd-soc-midas-wm1811-objs := midas_wm1811.o +snd-soc-smdk-wm8994-y := smdk_wm8994.o +snd-soc-snow-y := snow.o +snd-soc-smdk-spdif-y := smdk_spdif.o +snd-soc-smdk-wm8994pcm-y := smdk_wm8994pcm.o +snd-soc-speyside-y := speyside.o +snd-soc-tobermory-y := tobermory.o +snd-soc-lowland-y := lowland.o +snd-soc-littlemill-y := littlemill.o +snd-soc-bells-y := bells.o +snd-soc-odroid-y := odroid.o +snd-soc-arndale-y := arndale.o +snd-soc-tm2-wm5110-y := tm2_wm5110.o +snd-soc-aries-wm8994-y := aries_wm8994.o +snd-soc-midas-wm1811-y := midas_wm1811.o obj-$(CONFIG_SND_SOC_SAMSUNG_SMDK_WM8994) += snd-soc-smdk-wm8994.o obj-$(CONFIG_SND_SOC_SNOW) += snd-soc-snow.o -- cgit v1.2.3 From 8c26836f5bade6d8aef415bdbe8d290b8bb8a5d9 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 7 May 2024 17:55:27 +0200 Subject: ASoC: sh: Use *-y instead of *-objs in Makefile *-objs suffix is reserved rather for (user-space) host programs while usually *-y suffix is used for kernel drivers (although *-objs works for that purpose for now). Let's correct the old usages of *-objs in Makefiles. Signed-off-by: Takashi Iwai Link: https://lore.kernel.org/r/20240507155540.24815-24-tiwai@suse.de Signed-off-by: Mark Brown --- sound/soc/sh/Makefile | 16 ++++++++-------- sound/soc/sh/rcar/Makefile | 2 +- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/sound/soc/sh/Makefile b/sound/soc/sh/Makefile index f6fd79948f6a..f0e19cbd1581 100644 --- a/sound/soc/sh/Makefile +++ b/sound/soc/sh/Makefile @@ -1,13 +1,13 @@ # SPDX-License-Identifier: GPL-2.0 ## DMA engines -snd-soc-dma-sh7760-objs := dma-sh7760.o +snd-soc-dma-sh7760-y := dma-sh7760.o obj-$(CONFIG_SND_SOC_PCM_SH7760) += snd-soc-dma-sh7760.o ## audio units found on some SH-4 -snd-soc-hac-objs := hac.o -snd-soc-ssi-objs := ssi.o -snd-soc-fsi-objs := fsi.o -snd-soc-siu-objs := siu_pcm.o siu_dai.o +snd-soc-hac-y := hac.o +snd-soc-ssi-y := ssi.o +snd-soc-fsi-y := fsi.o +snd-soc-siu-y := siu_pcm.o siu_dai.o obj-$(CONFIG_SND_SOC_SH4_HAC) += snd-soc-hac.o obj-$(CONFIG_SND_SOC_SH4_SSI) += snd-soc-ssi.o obj-$(CONFIG_SND_SOC_SH4_FSI) += snd-soc-fsi.o @@ -17,12 +17,12 @@ obj-$(CONFIG_SND_SOC_SH4_SIU) += snd-soc-siu.o obj-$(CONFIG_SND_SOC_RCAR) += rcar/ ## boards -snd-soc-sh7760-ac97-objs := sh7760-ac97.o -snd-soc-migor-objs := migor.o +snd-soc-sh7760-ac97-y := sh7760-ac97.o +snd-soc-migor-y := migor.o obj-$(CONFIG_SND_SH7760_AC97) += snd-soc-sh7760-ac97.o obj-$(CONFIG_SND_SIU_MIGOR) += snd-soc-migor.o # RZ/G2L -snd-soc-rz-ssi-objs := rz-ssi.o +snd-soc-rz-ssi-y := rz-ssi.o obj-$(CONFIG_SND_SOC_RZ) += snd-soc-rz-ssi.o diff --git a/sound/soc/sh/rcar/Makefile b/sound/soc/sh/rcar/Makefile index d07eccfa3ac2..45eb875a912a 100644 --- a/sound/soc/sh/rcar/Makefile +++ b/sound/soc/sh/rcar/Makefile @@ -1,3 +1,3 @@ # SPDX-License-Identifier: GPL-2.0 -snd-soc-rcar-objs := core.o gen.o dma.o adg.o ssi.o ssiu.o src.o ctu.o mix.o dvc.o cmd.o debugfs.o +snd-soc-rcar-y := core.o gen.o dma.o adg.o ssi.o ssiu.o src.o ctu.o mix.o dvc.o cmd.o debugfs.o obj-$(CONFIG_SND_SOC_RCAR) += snd-soc-rcar.o -- cgit v1.2.3 From 9c2f5b6eb8b7da05e13cde60c32e0a8b1f5873b0 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 7 May 2024 17:55:28 +0200 Subject: ASoC: SOF: Use *-y instead of *-objs in Makefile *-objs suffix is reserved rather for (user-space) host programs while usually *-y suffix is used for kernel drivers (although *-objs works for that purpose for now). Let's correct the old usages of *-objs in Makefiles. Signed-off-by: Takashi Iwai Link: https://lore.kernel.org/r/20240507155540.24815-25-tiwai@suse.de Signed-off-by: Mark Brown --- sound/soc/sof/Makefile | 30 +++++++++++++++--------------- sound/soc/sof/amd/Makefile | 10 +++++----- sound/soc/sof/imx/Makefile | 8 ++++---- sound/soc/sof/intel/Makefile | 30 +++++++++++++++--------------- sound/soc/sof/mediatek/mt8186/Makefile | 2 +- sound/soc/sof/mediatek/mt8195/Makefile | 2 +- sound/soc/sof/xtensa/Makefile | 2 +- 7 files changed, 42 insertions(+), 42 deletions(-) diff --git a/sound/soc/sof/Makefile b/sound/soc/sof/Makefile index 3624124575af..b0b22e6ebc03 100644 --- a/sound/soc/sof/Makefile +++ b/sound/soc/sof/Makefile @@ -1,44 +1,44 @@ # SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause) -snd-sof-objs := core.o ops.o loader.o ipc.o pcm.o pm.o debug.o topology.o\ +snd-sof-y := core.o ops.o loader.o ipc.o pcm.o pm.o debug.o topology.o\ control.o trace.o iomem-utils.o sof-audio.o stream-ipc.o\ fw-file-profile.o # IPC implementations ifneq ($(CONFIG_SND_SOC_SOF_IPC3),) -snd-sof-objs += ipc3.o ipc3-loader.o ipc3-topology.o ipc3-control.o ipc3-pcm.o\ +snd-sof-y += ipc3.o ipc3-loader.o ipc3-topology.o ipc3-control.o ipc3-pcm.o\ ipc3-dtrace.o endif ifneq ($(CONFIG_SND_SOC_SOF_IPC4),) -snd-sof-objs += ipc4.o ipc4-loader.o ipc4-topology.o ipc4-control.o ipc4-pcm.o\ +snd-sof-y += ipc4.o ipc4-loader.o ipc4-topology.o ipc4-control.o ipc4-pcm.o\ ipc4-mtrace.o ipc4-telemetry.o endif # SOF client support ifneq ($(CONFIG_SND_SOC_SOF_CLIENT),) -snd-sof-objs += sof-client.o +snd-sof-y += sof-client.o endif snd-sof-$(CONFIG_SND_SOC_SOF_COMPRESS) += compress.o -snd-sof-pci-objs := sof-pci-dev.o -snd-sof-acpi-objs := sof-acpi-dev.o -snd-sof-of-objs := sof-of-dev.o +snd-sof-pci-y := sof-pci-dev.o +snd-sof-acpi-y := sof-acpi-dev.o +snd-sof-of-y := sof-of-dev.o -snd-sof-ipc-flood-test-objs := sof-client-ipc-flood-test.o -snd-sof-ipc-msg-injector-objs := sof-client-ipc-msg-injector.o -snd-sof-ipc-kernel-injector-objs := sof-client-ipc-kernel-injector.o -snd-sof-probes-objs := sof-client-probes.o +snd-sof-ipc-flood-test-y := sof-client-ipc-flood-test.o +snd-sof-ipc-msg-injector-y := sof-client-ipc-msg-injector.o +snd-sof-ipc-kernel-injector-y := sof-client-ipc-kernel-injector.o +snd-sof-probes-y := sof-client-probes.o ifneq ($(CONFIG_SND_SOC_SOF_IPC3),) -snd-sof-probes-objs += sof-client-probes-ipc3.o +snd-sof-probes-y += sof-client-probes-ipc3.o endif ifneq ($(CONFIG_SND_SOC_SOF_IPC4),) -snd-sof-probes-objs += sof-client-probes-ipc4.o +snd-sof-probes-y += sof-client-probes-ipc4.o endif -snd-sof-nocodec-objs := nocodec.o +snd-sof-nocodec-y := nocodec.o -snd-sof-utils-objs := sof-utils.o +snd-sof-utils-y := sof-utils.o obj-$(CONFIG_SND_SOC_SOF) += snd-sof.o obj-$(CONFIG_SND_SOC_SOF_NOCODEC) += snd-sof-nocodec.o diff --git a/sound/soc/sof/amd/Makefile b/sound/soc/sof/amd/Makefile index ad25f4206177..380a9769c321 100644 --- a/sound/soc/sof/amd/Makefile +++ b/sound/soc/sof/amd/Makefile @@ -4,12 +4,12 @@ # # Copyright(c) 2021, 2023 Advanced Micro Devices, Inc. All rights reserved. -snd-sof-amd-acp-objs := acp.o acp-loader.o acp-ipc.o acp-pcm.o acp-stream.o acp-trace.o acp-common.o +snd-sof-amd-acp-y := acp.o acp-loader.o acp-ipc.o acp-pcm.o acp-stream.o acp-trace.o acp-common.o snd-sof-amd-acp-$(CONFIG_SND_SOC_SOF_ACP_PROBES) = acp-probes.o -snd-sof-amd-renoir-objs := pci-rn.o renoir.o -snd-sof-amd-rembrandt-objs := pci-rmb.o rembrandt.o -snd-sof-amd-vangogh-objs := pci-vangogh.o vangogh.o -snd-sof-amd-acp63-objs := pci-acp63.o acp63.o +snd-sof-amd-renoir-y := pci-rn.o renoir.o +snd-sof-amd-rembrandt-y := pci-rmb.o rembrandt.o +snd-sof-amd-vangogh-y := pci-vangogh.o vangogh.o +snd-sof-amd-acp63-y := pci-acp63.o acp63.o obj-$(CONFIG_SND_SOC_SOF_AMD_COMMON) += snd-sof-amd-acp.o obj-$(CONFIG_SND_SOC_SOF_AMD_RENOIR) +=snd-sof-amd-renoir.o diff --git a/sound/soc/sof/imx/Makefile b/sound/soc/sof/imx/Makefile index 798b43a415bf..be0bf0736dfa 100644 --- a/sound/soc/sof/imx/Makefile +++ b/sound/soc/sof/imx/Makefile @@ -1,9 +1,9 @@ # SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause) -snd-sof-imx8-objs := imx8.o -snd-sof-imx8m-objs := imx8m.o -snd-sof-imx8ulp-objs := imx8ulp.o +snd-sof-imx8-y := imx8.o +snd-sof-imx8m-y := imx8m.o +snd-sof-imx8ulp-y := imx8ulp.o -snd-sof-imx-common-objs := imx-common.o +snd-sof-imx-common-y := imx-common.o obj-$(CONFIG_SND_SOC_SOF_IMX8) += snd-sof-imx8.o obj-$(CONFIG_SND_SOC_SOF_IMX8M) += snd-sof-imx8m.o diff --git a/sound/soc/sof/intel/Makefile b/sound/soc/sof/intel/Makefile index 806df08e3fd5..b56fa5530b8b 100644 --- a/sound/soc/sof/intel/Makefile +++ b/sound/soc/sof/intel/Makefile @@ -1,22 +1,22 @@ # SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause) -snd-sof-acpi-intel-byt-objs := byt.o -snd-sof-acpi-intel-bdw-objs := bdw.o +snd-sof-acpi-intel-byt-y := byt.o +snd-sof-acpi-intel-bdw-y := bdw.o -snd-sof-intel-hda-common-objs := hda-loader.o hda-stream.o hda-trace.o \ +snd-sof-intel-hda-common-y := hda-loader.o hda-stream.o hda-trace.o \ hda-dsp.o hda-ipc.o hda-ctrl.o hda-pcm.o \ hda-dai.o hda-dai-ops.o hda-bus.o \ telemetry.o tracepoints.o -snd-sof-intel-hda-generic-objs := hda.o hda-common-ops.o +snd-sof-intel-hda-generic-y := hda.o hda-common-ops.o -snd-sof-intel-hda-mlink-objs := hda-mlink.o +snd-sof-intel-hda-mlink-y := hda-mlink.o snd-sof-intel-hda-common-$(CONFIG_SND_SOC_SOF_HDA_PROBES) += hda-probes.o -snd-sof-intel-hda-objs := hda-codec.o +snd-sof-intel-hda-y := hda-codec.o -snd-sof-intel-atom-objs := atom.o +snd-sof-intel-atom-y := atom.o obj-$(CONFIG_SND_SOC_SOF_INTEL_ATOM_HIFI_EP) += snd-sof-intel-atom.o obj-$(CONFIG_SND_SOC_SOF_BAYTRAIL) += snd-sof-acpi-intel-byt.o @@ -26,14 +26,14 @@ obj-$(CONFIG_SND_SOC_SOF_HDA_GENERIC) += snd-sof-intel-hda-generic.o obj-$(CONFIG_SND_SOC_SOF_HDA_MLINK) += snd-sof-intel-hda-mlink.o obj-$(CONFIG_SND_SOC_SOF_HDA) += snd-sof-intel-hda.o -snd-sof-pci-intel-tng-objs := pci-tng.o -snd-sof-pci-intel-skl-objs := pci-skl.o skl.o hda-loader-skl.o -snd-sof-pci-intel-apl-objs := pci-apl.o apl.o -snd-sof-pci-intel-cnl-objs := pci-cnl.o cnl.o -snd-sof-pci-intel-icl-objs := pci-icl.o icl.o -snd-sof-pci-intel-tgl-objs := pci-tgl.o tgl.o -snd-sof-pci-intel-mtl-objs := pci-mtl.o mtl.o -snd-sof-pci-intel-lnl-objs := pci-lnl.o lnl.o +snd-sof-pci-intel-tng-y := pci-tng.o +snd-sof-pci-intel-skl-y := pci-skl.o skl.o hda-loader-skl.o +snd-sof-pci-intel-apl-y := pci-apl.o apl.o +snd-sof-pci-intel-cnl-y := pci-cnl.o cnl.o +snd-sof-pci-intel-icl-y := pci-icl.o icl.o +snd-sof-pci-intel-tgl-y := pci-tgl.o tgl.o +snd-sof-pci-intel-mtl-y := pci-mtl.o mtl.o +snd-sof-pci-intel-lnl-y := pci-lnl.o lnl.o obj-$(CONFIG_SND_SOC_SOF_MERRIFIELD) += snd-sof-pci-intel-tng.o obj-$(CONFIG_SND_SOC_SOF_INTEL_SKL) += snd-sof-pci-intel-skl.o diff --git a/sound/soc/sof/mediatek/mt8186/Makefile b/sound/soc/sof/mediatek/mt8186/Makefile index c1f5fc4e2495..022f415afac9 100644 --- a/sound/soc/sof/mediatek/mt8186/Makefile +++ b/sound/soc/sof/mediatek/mt8186/Makefile @@ -1,4 +1,4 @@ # SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause) -snd-sof-mt8186-objs := mt8186.o mt8186-clk.o mt8186-loader.o +snd-sof-mt8186-y := mt8186.o mt8186-clk.o mt8186-loader.o obj-$(CONFIG_SND_SOC_SOF_MT8186) += snd-sof-mt8186.o diff --git a/sound/soc/sof/mediatek/mt8195/Makefile b/sound/soc/sof/mediatek/mt8195/Makefile index afc4f21fccc5..f5eeda380b50 100644 --- a/sound/soc/sof/mediatek/mt8195/Makefile +++ b/sound/soc/sof/mediatek/mt8195/Makefile @@ -1,3 +1,3 @@ # SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause) -snd-sof-mt8195-objs := mt8195.o mt8195-clk.o mt8195-loader.o +snd-sof-mt8195-y := mt8195.o mt8195-clk.o mt8195-loader.o obj-$(CONFIG_SND_SOC_SOF_MT8195) += snd-sof-mt8195.o diff --git a/sound/soc/sof/xtensa/Makefile b/sound/soc/sof/xtensa/Makefile index b8376ea04bcf..b9e6e8f5a7f6 100644 --- a/sound/soc/sof/xtensa/Makefile +++ b/sound/soc/sof/xtensa/Makefile @@ -1,5 +1,5 @@ # SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause) -snd-sof-xtensa-dsp-objs := core.o +snd-sof-xtensa-dsp-y := core.o obj-$(CONFIG_SND_SOC_SOF_XTENSA) += snd-sof-xtensa-dsp.o -- cgit v1.2.3 From 50537c3fae4114dc71cf8b32c71881ca57fd3ad1 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 7 May 2024 17:55:29 +0200 Subject: ASoC: spear: Use *-y instead of *-objs in Makefile *-objs suffix is reserved rather for (user-space) host programs while usually *-y suffix is used for kernel drivers (although *-objs works for that purpose for now). Let's correct the old usages of *-objs in Makefiles. Signed-off-by: Takashi Iwai Link: https://lore.kernel.org/r/20240507155540.24815-26-tiwai@suse.de Signed-off-by: Mark Brown --- sound/soc/spear/Makefile | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/sound/soc/spear/Makefile b/sound/soc/spear/Makefile index 31d9dae280e7..61569d2e7606 100644 --- a/sound/soc/spear/Makefile +++ b/sound/soc/spear/Makefile @@ -1,8 +1,8 @@ # SPDX-License-Identifier: GPL-2.0 # SPEAR Platform Support -snd-soc-spear-pcm-objs := spear_pcm.o -snd-soc-spear-spdif-in-objs := spdif_in.o -snd-soc-spear-spdif-out-objs := spdif_out.o +snd-soc-spear-pcm-y := spear_pcm.o +snd-soc-spear-spdif-in-y := spdif_in.o +snd-soc-spear-spdif-out-y := spdif_out.o obj-$(CONFIG_SND_SPEAR_SOC) += snd-soc-spear-pcm.o obj-$(CONFIG_SND_SPEAR_SPDIF_IN) += snd-soc-spear-spdif-in.o -- cgit v1.2.3 From c4e93fd13235fdc339d087d4b1f491311f9e6a1d Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 7 May 2024 17:55:30 +0200 Subject: ASoC: sprd: Use *-y instead of *-objs in Makefile *-objs suffix is reserved rather for (user-space) host programs while usually *-y suffix is used for kernel drivers (although *-objs works for that purpose for now). Let's correct the old usages of *-objs in Makefiles. Signed-off-by: Takashi Iwai Link: https://lore.kernel.org/r/20240507155540.24815-27-tiwai@suse.de Signed-off-by: Mark Brown --- sound/soc/sprd/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/sprd/Makefile b/sound/soc/sprd/Makefile index a95fa56cd000..c36399414862 100644 --- a/sound/soc/sprd/Makefile +++ b/sound/soc/sprd/Makefile @@ -1,7 +1,7 @@ # SPDX-License-Identifier: GPL-2.0 # Spreadtrum Audio Support -snd-soc-sprd-platform-objs := sprd-pcm-dma.o sprd-pcm-compress.o +snd-soc-sprd-platform-y := sprd-pcm-dma.o sprd-pcm-compress.o obj-$(CONFIG_SND_SOC_SPRD) += snd-soc-sprd-platform.o -- cgit v1.2.3 From aa4a610309028d38b041cca899b772023178d112 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 7 May 2024 17:55:31 +0200 Subject: ASoC: sti: Use *-y instead of *-objs in Makefile *-objs suffix is reserved rather for (user-space) host programs while usually *-y suffix is used for kernel drivers (although *-objs works for that purpose for now). Let's correct the old usages of *-objs in Makefiles. Signed-off-by: Takashi Iwai Link: https://lore.kernel.org/r/20240507155540.24815-28-tiwai@suse.de Signed-off-by: Mark Brown --- sound/soc/sti/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/sti/Makefile b/sound/soc/sti/Makefile index 787ccb521298..dfd4f4dd36fc 100644 --- a/sound/soc/sti/Makefile +++ b/sound/soc/sti/Makefile @@ -1,5 +1,5 @@ # SPDX-License-Identifier: GPL-2.0-only # STI platform support -snd-soc-sti-objs := sti_uniperif.o uniperif_player.o uniperif_reader.o +snd-soc-sti-y := sti_uniperif.o uniperif_player.o uniperif_reader.o obj-$(CONFIG_SND_SOC_STI) += snd-soc-sti.o -- cgit v1.2.3 From f827d7a34bbc1922c36aae80ff30c9ef9fb3647d Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 7 May 2024 17:55:32 +0200 Subject: ASoC: stm: Use *-y instead of *-objs in Makefile *-objs suffix is reserved rather for (user-space) host programs while usually *-y suffix is used for kernel drivers (although *-objs works for that purpose for now). Let's correct the old usages of *-objs in Makefiles. Signed-off-by: Takashi Iwai Link: https://lore.kernel.org/r/20240507155540.24815-29-tiwai@suse.de Signed-off-by: Mark Brown --- sound/soc/stm/Makefile | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/sound/soc/stm/Makefile b/sound/soc/stm/Makefile index 3143c0b47042..3372432faa09 100644 --- a/sound/soc/stm/Makefile +++ b/sound/soc/stm/Makefile @@ -1,17 +1,17 @@ # SPDX-License-Identifier: GPL-2.0 # SAI -snd-soc-stm32-sai-sub-objs := stm32_sai_sub.o +snd-soc-stm32-sai-sub-y := stm32_sai_sub.o obj-$(CONFIG_SND_SOC_STM32_SAI) += snd-soc-stm32-sai-sub.o -snd-soc-stm32-sai-objs := stm32_sai.o +snd-soc-stm32-sai-y := stm32_sai.o obj-$(CONFIG_SND_SOC_STM32_SAI) += snd-soc-stm32-sai.o # I2S -snd-soc-stm32-i2s-objs := stm32_i2s.o +snd-soc-stm32-i2s-y := stm32_i2s.o obj-$(CONFIG_SND_SOC_STM32_I2S) += snd-soc-stm32-i2s.o # SPDIFRX -snd-soc-stm32-spdifrx-objs := stm32_spdifrx.o +snd-soc-stm32-spdifrx-y := stm32_spdifrx.o obj-$(CONFIG_SND_SOC_STM32_SPDIFRX) += snd-soc-stm32-spdifrx.o #DFSDM -- cgit v1.2.3 From 51a50d6ad72702dd8de352c5882a18001638dc30 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 7 May 2024 17:55:33 +0200 Subject: ASoC: tegra: Use *-y instead of *-objs in Makefile *-objs suffix is reserved rather for (user-space) host programs while usually *-y suffix is used for kernel drivers (although *-objs works for that purpose for now). Let's correct the old usages of *-objs in Makefiles. Signed-off-by: Takashi Iwai Link: https://lore.kernel.org/r/20240507155540.24815-30-tiwai@suse.de Signed-off-by: Mark Brown --- sound/soc/tegra/Makefile | 46 +++++++++++++++++++++++----------------------- 1 file changed, 23 insertions(+), 23 deletions(-) diff --git a/sound/soc/tegra/Makefile b/sound/soc/tegra/Makefile index b723c78e665d..cea4b0d54378 100644 --- a/sound/soc/tegra/Makefile +++ b/sound/soc/tegra/Makefile @@ -1,25 +1,25 @@ # SPDX-License-Identifier: GPL-2.0 # Tegra platform Support -snd-soc-tegra-pcm-objs := tegra_pcm.o -snd-soc-tegra-utils-objs += tegra_asoc_utils.o -snd-soc-tegra20-ac97-objs := tegra20_ac97.o -snd-soc-tegra20-das-objs := tegra20_das.o -snd-soc-tegra20-i2s-objs := tegra20_i2s.o -snd-soc-tegra20-spdif-objs := tegra20_spdif.o -snd-soc-tegra30-ahub-objs := tegra30_ahub.o -snd-soc-tegra30-i2s-objs := tegra30_i2s.o -snd-soc-tegra210-ahub-objs := tegra210_ahub.o -snd-soc-tegra210-dmic-objs := tegra210_dmic.o -snd-soc-tegra210-i2s-objs := tegra210_i2s.o -snd-soc-tegra186-asrc-objs := tegra186_asrc.o -snd-soc-tegra186-dspk-objs := tegra186_dspk.o -snd-soc-tegra210-admaif-objs := tegra210_admaif.o -snd-soc-tegra210-mvc-objs := tegra210_mvc.o -snd-soc-tegra210-sfc-objs := tegra210_sfc.o -snd-soc-tegra210-amx-objs := tegra210_amx.o -snd-soc-tegra210-adx-objs := tegra210_adx.o -snd-soc-tegra210-mixer-objs := tegra210_mixer.o -snd-soc-tegra210-ope-objs := tegra210_ope.o tegra210_mbdrc.o tegra210_peq.o +snd-soc-tegra-pcm-y := tegra_pcm.o +snd-soc-tegra-utils-y += tegra_asoc_utils.o +snd-soc-tegra20-ac97-y := tegra20_ac97.o +snd-soc-tegra20-das-y := tegra20_das.o +snd-soc-tegra20-i2s-y := tegra20_i2s.o +snd-soc-tegra20-spdif-y := tegra20_spdif.o +snd-soc-tegra30-ahub-y := tegra30_ahub.o +snd-soc-tegra30-i2s-y := tegra30_i2s.o +snd-soc-tegra210-ahub-y := tegra210_ahub.o +snd-soc-tegra210-dmic-y := tegra210_dmic.o +snd-soc-tegra210-i2s-y := tegra210_i2s.o +snd-soc-tegra186-asrc-y := tegra186_asrc.o +snd-soc-tegra186-dspk-y := tegra186_dspk.o +snd-soc-tegra210-admaif-y := tegra210_admaif.o +snd-soc-tegra210-mvc-y := tegra210_mvc.o +snd-soc-tegra210-sfc-y := tegra210_sfc.o +snd-soc-tegra210-amx-y := tegra210_amx.o +snd-soc-tegra210-adx-y := tegra210_adx.o +snd-soc-tegra210-mixer-y := tegra210_mixer.o +snd-soc-tegra210-ope-y := tegra210_ope.o tegra210_mbdrc.o tegra210_peq.o obj-$(CONFIG_SND_SOC_TEGRA) += snd-soc-tegra-pcm.o obj-$(CONFIG_SND_SOC_TEGRA20_AC97) += snd-soc-tegra20-ac97.o @@ -42,9 +42,9 @@ obj-$(CONFIG_SND_SOC_TEGRA210_MIXER) += snd-soc-tegra210-mixer.o obj-$(CONFIG_SND_SOC_TEGRA210_OPE) += snd-soc-tegra210-ope.o # Tegra machine Support -snd-soc-tegra-wm8903-objs := tegra_wm8903.o -snd-soc-tegra-machine-objs := tegra_asoc_machine.o -snd-soc-tegra-audio-graph-card-objs := tegra_audio_graph_card.o +snd-soc-tegra-wm8903-y := tegra_wm8903.o +snd-soc-tegra-machine-y := tegra_asoc_machine.o +snd-soc-tegra-audio-graph-card-y := tegra_audio_graph_card.o obj-$(CONFIG_SND_SOC_TEGRA_WM8903) += snd-soc-tegra-wm8903.o obj-$(CONFIG_SND_SOC_TEGRA_MACHINE_DRV) += snd-soc-tegra-machine.o -- cgit v1.2.3 From 72b28ec6de0a4dd27dfd89525c3e1efd75ad327b Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 7 May 2024 17:55:34 +0200 Subject: ASoC: ti: Use *-y instead of *-objs in Makefile *-objs suffix is reserved rather for (user-space) host programs while usually *-y suffix is used for kernel drivers (although *-objs works for that purpose for now). Let's correct the old usages of *-objs in Makefiles. Signed-off-by: Takashi Iwai Link: https://lore.kernel.org/r/20240507155540.24815-31-tiwai@suse.de Signed-off-by: Mark Brown --- sound/soc/ti/Makefile | 36 ++++++++++++++++++------------------ 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/sound/soc/ti/Makefile b/sound/soc/ti/Makefile index 41cdcaec770d..421e13bc04db 100644 --- a/sound/soc/ti/Makefile +++ b/sound/soc/ti/Makefile @@ -1,20 +1,20 @@ # SPDX-License-Identifier: GPL-2.0 # Platform drivers -snd-soc-ti-edma-objs := edma-pcm.o -snd-soc-ti-sdma-objs := sdma-pcm.o -snd-soc-ti-udma-objs := udma-pcm.o +snd-soc-ti-edma-y := edma-pcm.o +snd-soc-ti-sdma-y := sdma-pcm.o +snd-soc-ti-udma-y := udma-pcm.o obj-$(CONFIG_SND_SOC_TI_EDMA_PCM) += snd-soc-ti-edma.o obj-$(CONFIG_SND_SOC_TI_SDMA_PCM) += snd-soc-ti-sdma.o obj-$(CONFIG_SND_SOC_TI_UDMA_PCM) += snd-soc-ti-udma.o # CPU DAI drivers -snd-soc-davinci-asp-objs := davinci-i2s.o -snd-soc-davinci-mcasp-objs := davinci-mcasp.o -snd-soc-omap-dmic-objs := omap-dmic.o -snd-soc-omap-mcbsp-objs := omap-mcbsp.o omap-mcbsp-st.o -snd-soc-omap-mcpdm-objs := omap-mcpdm.o +snd-soc-davinci-asp-y := davinci-i2s.o +snd-soc-davinci-mcasp-y := davinci-mcasp.o +snd-soc-omap-dmic-y := omap-dmic.o +snd-soc-omap-mcbsp-y := omap-mcbsp.o omap-mcbsp-st.o +snd-soc-omap-mcpdm-y := omap-mcpdm.o obj-$(CONFIG_SND_SOC_DAVINCI_ASP) += snd-soc-davinci-asp.o obj-$(CONFIG_SND_SOC_DAVINCI_MCASP) += snd-soc-davinci-mcasp.o @@ -23,16 +23,16 @@ obj-$(CONFIG_SND_SOC_OMAP_MCBSP) += snd-soc-omap-mcbsp.o obj-$(CONFIG_SND_SOC_OMAP_MCPDM) += snd-soc-omap-mcpdm.o # Machine drivers -snd-soc-davinci-evm-objs := davinci-evm.o -snd-soc-n810-objs := n810.o -snd-soc-rx51-objs := rx51.o -snd-soc-omap3pandora-objs := omap3pandora.o -snd-soc-omap-twl4030-objs := omap-twl4030.o -snd-soc-omap-abe-twl6040-objs := omap-abe-twl6040.o -snd-soc-ams-delta-objs := ams-delta.o -snd-soc-omap-hdmi-objs := omap-hdmi.o -snd-soc-osk5912-objs := osk5912.o -snd-soc-j721e-evm-objs := j721e-evm.o +snd-soc-davinci-evm-y := davinci-evm.o +snd-soc-n810-y := n810.o +snd-soc-rx51-y := rx51.o +snd-soc-omap3pandora-y := omap3pandora.o +snd-soc-omap-twl4030-y := omap-twl4030.o +snd-soc-omap-abe-twl6040-y := omap-abe-twl6040.o +snd-soc-ams-delta-y := ams-delta.o +snd-soc-omap-hdmi-y := omap-hdmi.o +snd-soc-osk5912-y := osk5912.o +snd-soc-j721e-evm-y := j721e-evm.o obj-$(CONFIG_SND_SOC_DAVINCI_EVM) += snd-soc-davinci-evm.o obj-$(CONFIG_SND_SOC_NOKIA_N810) += snd-soc-n810.o -- cgit v1.2.3 From d5c337c5e3d54a98a1458942a4c1eb7a307b180c Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 7 May 2024 17:55:35 +0200 Subject: ASoC: uniphier: Use *-y instead of *-objs in Makefile *-objs suffix is reserved rather for (user-space) host programs while usually *-y suffix is used for kernel drivers (although *-objs works for that purpose for now). Let's correct the old usages of *-objs in Makefiles. Signed-off-by: Takashi Iwai Link: https://lore.kernel.org/r/20240507155540.24815-32-tiwai@suse.de Signed-off-by: Mark Brown --- sound/soc/uniphier/Makefile | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/sound/soc/uniphier/Makefile b/sound/soc/uniphier/Makefile index 88169395f68a..5fee21b6074c 100644 --- a/sound/soc/uniphier/Makefile +++ b/sound/soc/uniphier/Makefile @@ -1,11 +1,11 @@ # SPDX-License-Identifier: GPL-2.0 -snd-soc-uniphier-aio-cpu-objs := aio-core.o aio-dma.o aio-cpu.o aio-compress.o -snd-soc-uniphier-aio-ld11-objs := aio-ld11.o -snd-soc-uniphier-aio-pxs2-objs := aio-pxs2.o +snd-soc-uniphier-aio-cpu-y := aio-core.o aio-dma.o aio-cpu.o aio-compress.o +snd-soc-uniphier-aio-ld11-y := aio-ld11.o +snd-soc-uniphier-aio-pxs2-y := aio-pxs2.o obj-$(CONFIG_SND_SOC_UNIPHIER_AIO) += snd-soc-uniphier-aio-cpu.o obj-$(CONFIG_SND_SOC_UNIPHIER_LD11) += snd-soc-uniphier-aio-ld11.o obj-$(CONFIG_SND_SOC_UNIPHIER_PXS2) += snd-soc-uniphier-aio-pxs2.o -snd-soc-uniphier-evea-objs := evea.o +snd-soc-uniphier-evea-y := evea.o obj-$(CONFIG_SND_SOC_UNIPHIER_EVEA_CODEC) += snd-soc-uniphier-evea.o -- cgit v1.2.3 From c4850e856f9db799be4e5a211dc85bdfabbe210b Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 7 May 2024 17:55:36 +0200 Subject: ASoC: ux500: Use *-y instead of *-objs in Makefile *-objs suffix is reserved rather for (user-space) host programs while usually *-y suffix is used for kernel drivers (although *-objs works for that purpose for now). Let's correct the old usages of *-objs in Makefiles. Signed-off-by: Takashi Iwai Link: https://lore.kernel.org/r/20240507155540.24815-33-tiwai@suse.de Signed-off-by: Mark Brown --- sound/soc/ux500/Makefile | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/sound/soc/ux500/Makefile b/sound/soc/ux500/Makefile index e7d6de51b32b..a63787d9d664 100644 --- a/sound/soc/ux500/Makefile +++ b/sound/soc/ux500/Makefile @@ -1,11 +1,11 @@ # SPDX-License-Identifier: GPL-2.0 # Ux500 Platform Support -snd-soc-ux500-plat-msp-i2s-objs := ux500_msp_dai.o ux500_msp_i2s.o +snd-soc-ux500-plat-msp-i2s-y := ux500_msp_dai.o ux500_msp_i2s.o obj-$(CONFIG_SND_SOC_UX500_PLAT_MSP_I2S) += snd-soc-ux500-plat-msp-i2s.o -snd-soc-ux500-plat-dma-objs := ux500_pcm.o +snd-soc-ux500-plat-dma-y := ux500_pcm.o obj-$(CONFIG_SND_SOC_UX500_PLAT_DMA) += snd-soc-ux500-plat-dma.o -snd-soc-ux500-mach-mop500-objs := mop500.o mop500_ab8500.o +snd-soc-ux500-mach-mop500-y := mop500.o mop500_ab8500.o obj-$(CONFIG_SND_SOC_UX500_MACH_MOP500) += snd-soc-ux500-mach-mop500.o -- cgit v1.2.3 From a9732bf75785d5baa3259a59ed4cac80da138ed4 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 7 May 2024 17:55:37 +0200 Subject: ASoC: xilinx: Use *-y instead of *-objs in Makefile *-objs suffix is reserved rather for (user-space) host programs while usually *-y suffix is used for kernel drivers (although *-objs works for that purpose for now). Let's correct the old usages of *-objs in Makefiles. Signed-off-by: Takashi Iwai Link: https://lore.kernel.org/r/20240507155540.24815-34-tiwai@suse.de Signed-off-by: Mark Brown --- sound/soc/xilinx/Makefile | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/sound/soc/xilinx/Makefile b/sound/soc/xilinx/Makefile index be7652ce7c13..61cb47cf74dc 100644 --- a/sound/soc/xilinx/Makefile +++ b/sound/soc/xilinx/Makefile @@ -1,7 +1,7 @@ # SPDX-License-Identifier: GPL-2.0-only -snd-soc-xlnx-i2s-objs := xlnx_i2s.o +snd-soc-xlnx-i2s-y := xlnx_i2s.o obj-$(CONFIG_SND_SOC_XILINX_I2S) += snd-soc-xlnx-i2s.o -snd-soc-xlnx-formatter-pcm-objs := xlnx_formatter_pcm.o +snd-soc-xlnx-formatter-pcm-y := xlnx_formatter_pcm.o obj-$(CONFIG_SND_SOC_XILINX_AUDIO_FORMATTER) += snd-soc-xlnx-formatter-pcm.o -snd-soc-xlnx-spdif-objs := xlnx_spdif.o +snd-soc-xlnx-spdif-y := xlnx_spdif.o obj-$(CONFIG_SND_SOC_XILINX_SPDIF) += snd-soc-xlnx-spdif.o -- cgit v1.2.3 From 476d0a22bcc4d305080e3fc2d759010db23ccec1 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 7 May 2024 17:55:38 +0200 Subject: ASoC: xtensa: Use *-y instead of *-objs in Makefile *-objs suffix is reserved rather for (user-space) host programs while usually *-y suffix is used for kernel drivers (although *-objs works for that purpose for now). Let's correct the old usages of *-objs in Makefiles. Signed-off-by: Takashi Iwai Link: https://lore.kernel.org/r/20240507155540.24815-35-tiwai@suse.de Signed-off-by: Mark Brown --- sound/soc/xtensa/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/xtensa/Makefile b/sound/soc/xtensa/Makefile index b8707f63c4ae..be4e847d1b20 100644 --- a/sound/soc/xtensa/Makefile +++ b/sound/soc/xtensa/Makefile @@ -1,4 +1,4 @@ # SPDX-License-Identifier: GPL-2.0-only -snd-soc-xtfpga-i2s-objs := xtfpga-i2s.o +snd-soc-xtfpga-i2s-y := xtfpga-i2s.o obj-$(CONFIG_SND_SOC_XTFPGA_I2S) += snd-soc-xtfpga-i2s.o -- cgit v1.2.3 From d45ae45f328b6824966ab7dbf8b1c712f7d0e877 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Tue, 7 May 2024 23:56:59 +0300 Subject: ASoC: atmel: tse850-pcm5142: Remove unused of_gpio.h of_gpio.h is deprecated and subject to remove. The driver doesn't use it, simply remove the unused header. Signed-off-by: Andy Shevchenko Link: https://lore.kernel.org/r/20240507205659.690270-1-andriy.shevchenko@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/atmel/tse850-pcm5142.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/sound/soc/atmel/tse850-pcm5142.c b/sound/soc/atmel/tse850-pcm5142.c index 611da23325d3..5d208e0b4b90 100644 --- a/sound/soc/atmel/tse850-pcm5142.c +++ b/sound/soc/atmel/tse850-pcm5142.c @@ -35,10 +35,9 @@ // of the (filtered) output from the PCM5142 codec. #include -#include +#include #include #include -#include #include #include -- cgit v1.2.3 From 1dec672e8686b824aa8742cf9cc00748289de95b Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Wed, 8 May 2024 11:19:00 +0200 Subject: ASoC: ab8500: Add missing module description Now that make W=1 starts complaining the lack of MODULE_DESCRIPTION(), let's add the missing information. Suggested-by: Andy Shevchenko Link: https://lore.kernel.org/r/ZjpQm-hxLQtpgkUx@smile.fi.intel.com Signed-off-by: Takashi Iwai Reviewed-by: Andy Shevchenko Reviewed-by: Dragan Simic Link: https://lore.kernel.org/r/20240508091909.27062-2-tiwai@suse.de Signed-off-by: Mark Brown --- sound/soc/codecs/ab8500-codec.c | 1 + 1 file changed, 1 insertion(+) diff --git a/sound/soc/codecs/ab8500-codec.c b/sound/soc/codecs/ab8500-codec.c index 68342917419e..04b5e1d5a653 100644 --- a/sound/soc/codecs/ab8500-codec.c +++ b/sound/soc/codecs/ab8500-codec.c @@ -2571,4 +2571,5 @@ static struct platform_driver ab8500_codec_platform_driver = { }; module_platform_driver(ab8500_codec_platform_driver); +MODULE_DESCRIPTION("ASoC AB8500 codec driver"); MODULE_LICENSE("GPL v2"); -- cgit v1.2.3 From 1a7dc1cf9e46d2e4c732679775c3a06fba9d94a8 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Wed, 8 May 2024 11:19:01 +0200 Subject: ASoC: sigmadsp: Add missing module description Now that make W=1 starts complaining the lack of MODULE_DESCRIPTION(), let's add the missing information. Suggested-by: Andy Shevchenko Link: https://lore.kernel.org/r/ZjpQm-hxLQtpgkUx@smile.fi.intel.com Signed-off-by: Takashi Iwai Reviewed-by: Dragan Simic Link: https://lore.kernel.org/r/20240508091909.27062-3-tiwai@suse.de Signed-off-by: Mark Brown --- sound/soc/codecs/sigmadsp.c | 1 + 1 file changed, 1 insertion(+) diff --git a/sound/soc/codecs/sigmadsp.c b/sound/soc/codecs/sigmadsp.c index 56546e2394ab..201f74e3a7ae 100644 --- a/sound/soc/codecs/sigmadsp.c +++ b/sound/soc/codecs/sigmadsp.c @@ -805,4 +805,5 @@ int sigmadsp_restrict_params(struct sigmadsp *sigmadsp, } EXPORT_SYMBOL_GPL(sigmadsp_restrict_params); +MODULE_DESCRIPTION("Analog Devices SigmaStudio firmware helpers"); MODULE_LICENSE("GPL"); -- cgit v1.2.3 From 6d21f0a2be88d34e53fcbf66fb8e298787837c01 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Wed, 8 May 2024 11:19:02 +0200 Subject: ASoC: qcom: Add missing module descriptions Now that make W=1 starts complaining the lack of MODULE_DESCRIPTION(), let's add the missing information. Suggested-by: Andy Shevchenko Link: https://lore.kernel.org/r/ZjpQm-hxLQtpgkUx@smile.fi.intel.com Signed-off-by: Takashi Iwai Reviewed-by: Dragan Simic Link: https://lore.kernel.org/r/20240508091909.27062-4-tiwai@suse.de Signed-off-by: Mark Brown --- sound/soc/qcom/common.c | 2 ++ sound/soc/qcom/qdsp6/q6dsp-common.c | 2 ++ 2 files changed, 4 insertions(+) diff --git a/sound/soc/qcom/common.c b/sound/soc/qcom/common.c index 747041fa7866..3d02aa3844f2 100644 --- a/sound/soc/qcom/common.c +++ b/sound/soc/qcom/common.c @@ -239,4 +239,6 @@ int qcom_snd_wcd_jack_setup(struct snd_soc_pcm_runtime *rtd, return 0; } EXPORT_SYMBOL_GPL(qcom_snd_wcd_jack_setup); + +MODULE_DESCRIPTION("ASoC Qualcomm helper functions"); MODULE_LICENSE("GPL"); diff --git a/sound/soc/qcom/qdsp6/q6dsp-common.c b/sound/soc/qcom/qdsp6/q6dsp-common.c index 95585dea2b36..f74585d88bd6 100644 --- a/sound/soc/qcom/qdsp6/q6dsp-common.c +++ b/sound/soc/qcom/qdsp6/q6dsp-common.c @@ -98,4 +98,6 @@ int q6dsp_get_channel_allocation(int channels) return channel_allocation; } EXPORT_SYMBOL_GPL(q6dsp_get_channel_allocation); + +MODULE_DESCRIPTION("ASoC MSM QDSP6 helper functions"); MODULE_LICENSE("GPL v2"); -- cgit v1.2.3 From 2c846d7cc4ee3382aed6dfd322fcaaf309eb2c9a Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Wed, 8 May 2024 11:19:03 +0200 Subject: ASoC: dmaengine: Add missing module description Now that make W=1 starts complaining the lack of MODULE_DESCRIPTION(), let's add the missing information. Suggested-by: Andy Shevchenko Link: https://lore.kernel.org/r/ZjpQm-hxLQtpgkUx@smile.fi.intel.com Signed-off-by: Takashi Iwai Reviewed-by: Dragan Simic Link: https://lore.kernel.org/r/20240508091909.27062-5-tiwai@suse.de Signed-off-by: Mark Brown --- sound/soc/soc-generic-dmaengine-pcm.c | 1 + 1 file changed, 1 insertion(+) diff --git a/sound/soc/soc-generic-dmaengine-pcm.c b/sound/soc/soc-generic-dmaengine-pcm.c index 83db1a83d8ba..ea3bc9318412 100644 --- a/sound/soc/soc-generic-dmaengine-pcm.c +++ b/sound/soc/soc-generic-dmaengine-pcm.c @@ -494,4 +494,5 @@ void snd_dmaengine_pcm_unregister(struct device *dev) } EXPORT_SYMBOL_GPL(snd_dmaengine_pcm_unregister); +MODULE_DESCRIPTION("ASoC helpers for generic PCM dmaengine API"); MODULE_LICENSE("GPL"); -- cgit v1.2.3 From ea762d10b92a423b6e4980241a7bfa809c7cffd1 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Wed, 8 May 2024 11:19:04 +0200 Subject: ASoC: topology-test: Add missing module description Now that make W=1 starts complaining the lack of MODULE_DESCRIPTION(), let's add the missing information. Suggested-by: Andy Shevchenko Link: https://lore.kernel.org/r/ZjpQm-hxLQtpgkUx@smile.fi.intel.com Signed-off-by: Takashi Iwai Reviewed-by: Dragan Simic Link: https://lore.kernel.org/r/20240508091909.27062-6-tiwai@suse.de Signed-off-by: Mark Brown --- sound/soc/soc-topology-test.c | 1 + 1 file changed, 1 insertion(+) diff --git a/sound/soc/soc-topology-test.c b/sound/soc/soc-topology-test.c index 02aa2448f0e6..d62a02ec5896 100644 --- a/sound/soc/soc-topology-test.c +++ b/sound/soc/soc-topology-test.c @@ -819,4 +819,5 @@ static struct kunit_suite snd_soc_tplg_test_suite = { kunit_test_suites(&snd_soc_tplg_test_suite); +MODULE_DESCRIPTION("ASoC Topology Kernel Unit Tests"); MODULE_LICENSE("GPL"); -- cgit v1.2.3 From e85d8aeef23376ef10569c555819d301f3364f28 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Wed, 8 May 2024 11:19:05 +0200 Subject: ASoC: ux500: Add missing module description Now that make W=1 starts complaining the lack of MODULE_DESCRIPTION(), let's add the missing information. Suggested-by: Andy Shevchenko Link: https://lore.kernel.org/r/ZjpQm-hxLQtpgkUx@smile.fi.intel.com Signed-off-by: Takashi Iwai Reviewed-by: Dragan Simic Link: https://lore.kernel.org/r/20240508091909.27062-7-tiwai@suse.de Signed-off-by: Mark Brown --- sound/soc/ux500/ux500_msp_dai.c | 1 + 1 file changed, 1 insertion(+) diff --git a/sound/soc/ux500/ux500_msp_dai.c b/sound/soc/ux500/ux500_msp_dai.c index cde0dd8e2569..3fd13e8dd110 100644 --- a/sound/soc/ux500/ux500_msp_dai.c +++ b/sound/soc/ux500/ux500_msp_dai.c @@ -820,4 +820,5 @@ static struct platform_driver msp_i2s_driver = { }; module_platform_driver(msp_i2s_driver); +MODULE_DESCRIPTION("ASoC Ux500 I2S driver"); MODULE_LICENSE("GPL v2"); -- cgit v1.2.3 From 3423ad19ea912694a15ebbc48cbc8e1fcd8439da Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Wed, 8 May 2024 11:19:06 +0200 Subject: ASoC: xilinx: Add missing module descriptions Now that make W=1 starts complaining the lack of MODULE_DESCRIPTION(), let's add the missing information. Suggested-by: Andy Shevchenko Link: https://lore.kernel.org/r/ZjpQm-hxLQtpgkUx@smile.fi.intel.com Signed-off-by: Takashi Iwai Reviewed-by: Dragan Simic Link: https://lore.kernel.org/r/20240508091909.27062-8-tiwai@suse.de Signed-off-by: Mark Brown --- sound/soc/xilinx/xlnx_formatter_pcm.c | 2 ++ sound/soc/xilinx/xlnx_i2s.c | 1 + 2 files changed, 3 insertions(+) diff --git a/sound/soc/xilinx/xlnx_formatter_pcm.c b/sound/soc/xilinx/xlnx_formatter_pcm.c index 299cfb5e2022..158fc21a86c1 100644 --- a/sound/soc/xilinx/xlnx_formatter_pcm.c +++ b/sound/soc/xilinx/xlnx_formatter_pcm.c @@ -721,5 +721,7 @@ static struct platform_driver xlnx_formatter_pcm_driver = { }; module_platform_driver(xlnx_formatter_pcm_driver); + +MODULE_DESCRIPTION("ASoC driver for Xilinx audio formatter"); MODULE_AUTHOR("Maruthi Srinivas Bayyavarapu "); MODULE_LICENSE("GPL v2"); diff --git a/sound/soc/xilinx/xlnx_i2s.c b/sound/soc/xilinx/xlnx_i2s.c index 9de92d35e30e..ca915a001ad5 100644 --- a/sound/soc/xilinx/xlnx_i2s.c +++ b/sound/soc/xilinx/xlnx_i2s.c @@ -253,6 +253,7 @@ static struct platform_driver xlnx_i2s_aud_driver = { module_platform_driver(xlnx_i2s_aud_driver); +MODULE_DESCRIPTION("ASoC driver for Xilinx I2S audio"); MODULE_LICENSE("GPL v2"); MODULE_AUTHOR("Praveen Vuppala "); MODULE_AUTHOR("Maruthi Srinivas Bayyavarapu "); -- cgit v1.2.3 From c6f597bc598a8c3456fa017eb0c55e7a41bfce2c Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 9 May 2024 00:33:11 +0000 Subject: ASoC: audio-graph-card2: remove unneeded of_node_get() "lnk" is used as "port0", and it will be used to get "port1" by of_get_next_child(ports, lnk). It will call of_node_put() inside. This function is calling of_node_get() to make up for it, but it doesn't call paired of_node_put(port0) when it quit function. This of_node_get() itself is not needed, let's remove it. Reported-by: Dan Carpenter Signed-off-by: Kuninori Morimoto Link: https://lore.kernel.org/r/87jzk3akoo.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/generic/audio-graph-card2.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/sound/soc/generic/audio-graph-card2.c b/sound/soc/generic/audio-graph-card2.c index 62606e20be9a..c4d52fadebb6 100644 --- a/sound/soc/generic/audio-graph-card2.c +++ b/sound/soc/generic/audio-graph-card2.c @@ -1203,8 +1203,6 @@ static int graph_count_c2c(struct simple_util_priv *priv, struct device_node *codec0 = of_graph_get_remote_port(ep0); struct device_node *codec1 = of_graph_get_remote_port(ep1); - of_node_get(lnk); - /* * codec2codec { * ports { -- cgit v1.2.3 From 9a9d31b149f3a71ad0835ea295743482601dd322 Mon Sep 17 00:00:00 2001 From: Bard Liao Date: Thu, 9 May 2024 11:34:01 -0500 Subject: ASoC: Intel: sof_sdw_rt_sdca_jack_common: remove -sdca for new codecs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Realtek new SoundWire codecs are all -sdca version. No need to add -sdca to distinguish the non-sdca version. To be consistent with "spk:" and "mic:" components string, remove "-sdca" suffix from "hs:" components string. Reviewed-by: Péter Ujfalusi Signed-off-by: Bard Liao Signed-off-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20240509163418.67746-2-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- .../soc/intel/boards/sof_sdw_rt_sdca_jack_common.c | 23 +++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/sound/soc/intel/boards/sof_sdw_rt_sdca_jack_common.c b/sound/soc/intel/boards/sof_sdw_rt_sdca_jack_common.c index 85c09513bc35..69161ea5b290 100644 --- a/sound/soc/intel/boards/sof_sdw_rt_sdca_jack_common.c +++ b/sound/soc/intel/boards/sof_sdw_rt_sdca_jack_common.c @@ -88,6 +88,15 @@ static const char * const jack_codecs[] = { "rt711", "rt712", "rt713", "rt722" }; +/* + * The sdca suffix is required for rt711 since there are two generations of the same chip. + * RT713 is an SDCA device but the sdca suffix is required for backwards-compatibility with + * previous UCM definitions. + */ +static const char * const need_sdca_suffix[] = { + "rt711", "rt713" +}; + int rt_sdca_jack_rtd_init(struct snd_soc_pcm_runtime *rtd) { struct snd_soc_card *card = rtd->card; @@ -96,6 +105,7 @@ int rt_sdca_jack_rtd_init(struct snd_soc_pcm_runtime *rtd) struct snd_soc_component *component; struct snd_soc_jack *jack; int ret; + int i; codec_dai = get_codec_dai_by_name(rtd, jack_codecs, ARRAY_SIZE(jack_codecs)); if (!codec_dai) @@ -103,11 +113,22 @@ int rt_sdca_jack_rtd_init(struct snd_soc_pcm_runtime *rtd) component = codec_dai->component; card->components = devm_kasprintf(card->dev, GFP_KERNEL, - "%s hs:%s-sdca", + "%s hs:%s", card->components, component->name_prefix); if (!card->components) return -ENOMEM; + for (i = 0; i < ARRAY_SIZE(need_sdca_suffix); i++) { + if (strstr(codec_dai->name, need_sdca_suffix[i])) { + /* Add -sdca suffix for existing UCMs */ + card->components = devm_kasprintf(card->dev, GFP_KERNEL, + "%s-sdca", card->components); + if (!card->components) + return -ENOMEM; + break; + } + } + ret = snd_soc_add_card_controls(card, rt_sdca_jack_controls, ARRAY_SIZE(rt_sdca_jack_controls)); if (ret) { -- cgit v1.2.3 From 426c43ae9549559f5f5fd405bf464f9fa175e418 Mon Sep 17 00:00:00 2001 From: Brent Lu Date: Thu, 9 May 2024 11:34:02 -0500 Subject: ASoC: Intel: sof-rt5682: remove DMI quirk for hatch The quirk for cml chromebook hatch could be removed since we have cml_rt5682_def board id now. Reviewed-by: Bard Liao Signed-off-by: Brent Lu Signed-off-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20240509163418.67746-3-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/intel/boards/sof_rt5682.c | 9 --------- 1 file changed, 9 deletions(-) diff --git a/sound/soc/intel/boards/sof_rt5682.c b/sound/soc/intel/boards/sof_rt5682.c index e3a2ec6b4c7c..5a189c165e2d 100644 --- a/sound/soc/intel/boards/sof_rt5682.c +++ b/sound/soc/intel/boards/sof_rt5682.c @@ -67,15 +67,6 @@ static const struct dmi_system_id sof_rt5682_quirk_table[] = { .driver_data = (void *)(SOF_RT5682_MCLK_EN | SOF_SSP_PORT_CODEC(1)), }, - { - .callback = sof_rt5682_quirk_cb, - .matches = { - DMI_MATCH(DMI_PRODUCT_FAMILY, "Google_Hatch"), - }, - .driver_data = (void *)(SOF_RT5682_MCLK_EN | - SOF_SSP_PORT_CODEC(0) | - SOF_SSP_PORT_AMP(1)), - }, { .callback = sof_rt5682_quirk_cb, .matches = { -- cgit v1.2.3 From f1a5cb6a3bd2fc518dc21561dfc784530dab60b2 Mon Sep 17 00:00:00 2001 From: Brent Lu Date: Thu, 9 May 2024 11:34:03 -0500 Subject: ASoC: Intel: sof_rt5682: board id cleanup for mtl boards Since mtl chromebook is using DMI quirk for board config, changing the SSP port config of mtl_rt5682_def to RVP to simplify mtl board id and enumeration table. Reviewed-by: Bard Liao Signed-off-by: Brent Lu Signed-off-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20240509163418.67746-4-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/intel/boards/sof_rt5682.c | 16 +-------------- sound/soc/intel/common/soc-acpi-intel-mtl-match.c | 24 ----------------------- 2 files changed, 1 insertion(+), 39 deletions(-) diff --git a/sound/soc/intel/boards/sof_rt5682.c b/sound/soc/intel/boards/sof_rt5682.c index 5a189c165e2d..3dc373855a58 100644 --- a/sound/soc/intel/boards/sof_rt5682.c +++ b/sound/soc/intel/boards/sof_rt5682.c @@ -866,27 +866,13 @@ static const struct platform_device_id board_ids[] = { SOF_SSP_MASK_HDMI_CAPTURE(0x5)), }, { - .name = "mtl_mx98357_rt5682", + .name = "mtl_rt5682_def", .driver_data = (kernel_ulong_t)(SOF_RT5682_MCLK_EN | SOF_SSP_PORT_CODEC(0) | SOF_SSP_PORT_AMP(1) | SOF_SSP_PORT_BT_OFFLOAD(2) | SOF_BT_OFFLOAD_PRESENT), }, - { - .name = "mtl_mx98360_rt5682", - .driver_data = (kernel_ulong_t)(SOF_RT5682_MCLK_EN | - SOF_SSP_PORT_CODEC(0) | - SOF_SSP_PORT_AMP(1)), - }, - { - .name = "mtl_rt5682_def", - .driver_data = (kernel_ulong_t)(SOF_RT5682_MCLK_EN | - SOF_SSP_PORT_CODEC(2) | - SOF_SSP_PORT_AMP(0) | - SOF_SSP_PORT_BT_OFFLOAD(1) | - SOF_BT_OFFLOAD_PRESENT), - }, { } }; MODULE_DEVICE_TABLE(platform, board_ids); diff --git a/sound/soc/intel/common/soc-acpi-intel-mtl-match.c b/sound/soc/intel/common/soc-acpi-intel-mtl-match.c index 4eeec0bc92dc..0bff91317768 100644 --- a/sound/soc/intel/common/soc-acpi-intel-mtl-match.c +++ b/sound/soc/intel/common/soc-acpi-intel-mtl-match.c @@ -11,16 +11,6 @@ #include #include "soc-acpi-intel-sdw-mockup-match.h" -static const struct snd_soc_acpi_codecs mtl_max98357a_amp = { - .num_codecs = 1, - .codecs = {"MX98357A"} -}; - -static const struct snd_soc_acpi_codecs mtl_max98360a_amp = { - .num_codecs = 1, - .codecs = {"MX98360A"} -}; - static const struct snd_soc_acpi_codecs mtl_rt5682_rt5682s_hp = { .num_codecs = 2, .codecs = {RT5682_ACPI_HID, RT5682S_ACPI_HID}, @@ -37,20 +27,6 @@ static const struct snd_soc_acpi_codecs mtl_lt6911_hdmi = { }; struct snd_soc_acpi_mach snd_soc_acpi_intel_mtl_machines[] = { - { - .comp_ids = &mtl_rt5682_rt5682s_hp, - .drv_name = "mtl_mx98357_rt5682", - .machine_quirk = snd_soc_acpi_codec_list, - .quirk_data = &mtl_max98357a_amp, - .sof_tplg_filename = "sof-mtl-max98357a-rt5682.tplg", - }, - { - .comp_ids = &mtl_rt5682_rt5682s_hp, - .drv_name = "mtl_mx98360_rt5682", - .machine_quirk = snd_soc_acpi_codec_list, - .quirk_data = &mtl_max98360a_amp, - .sof_tplg_filename = "sof-mtl-max98360a-rt5682.tplg", - }, { .comp_ids = &mtl_essx_83x6, .drv_name = "mtl_es83x6_c1_h02", -- cgit v1.2.3 From eed867325e4b825a16946539275364699eed83d9 Mon Sep 17 00:00:00 2001 From: Brent Lu Date: Thu, 9 May 2024 11:34:04 -0500 Subject: ASoC: Intel: realtek-common: remove 2-spk rt1015p config The original code for rt1015p could support 1 or 2 rt1015p device instances in ACPI. However, all designs implement only 1 instance in ACPI table so we remove the code segment which is for 2 instances. Reviewed-by: Bard Liao Signed-off-by: Brent Lu Signed-off-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20240509163418.67746-5-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/intel/boards/sof_realtek_common.c | 57 +++-------------------------- sound/soc/intel/boards/sof_realtek_common.h | 1 - 2 files changed, 5 insertions(+), 53 deletions(-) diff --git a/sound/soc/intel/boards/sof_realtek_common.c b/sound/soc/intel/boards/sof_realtek_common.c index 6915ff8b8716..dda346e0f737 100644 --- a/sound/soc/intel/boards/sof_realtek_common.c +++ b/sound/soc/intel/boards/sof_realtek_common.c @@ -314,59 +314,21 @@ EXPORT_SYMBOL_NS(sof_rt1011_codec_conf, SND_SOC_INTEL_SOF_REALTEK_COMMON); * * For stereo output, there are always two amplifiers on the board. * However, the ACPI implements only one device instance (UID=0) if they - * are sharing the same enable pin. The code will detect the number of - * device instance and use corresponding DAPM structures for - * initialization. + * are sharing the same enable pin. This is the case of rt1015p. */ -static const struct snd_soc_dapm_route rt1015p_1dev_dapm_routes[] = { +static const struct snd_soc_dapm_route rt1015p_dapm_routes[] = { /* speaker */ { "Left Spk", NULL, "Speaker" }, { "Right Spk", NULL, "Speaker" }, }; -static const struct snd_soc_dapm_route rt1015p_2dev_dapm_routes[] = { - /* speaker */ - { "Left Spk", NULL, "Left Speaker" }, - { "Right Spk", NULL, "Right Speaker" }, -}; - -static struct snd_soc_codec_conf rt1015p_codec_confs[] = { - { - .dlc = COMP_CODEC_CONF(RT1015P_DEV0_NAME), - .name_prefix = "Left", - }, - { - .dlc = COMP_CODEC_CONF(RT1015P_DEV1_NAME), - .name_prefix = "Right", - }, -}; - static struct snd_soc_dai_link_component rt1015p_dai_link_components[] = { { .name = RT1015P_DEV0_NAME, .dai_name = RT1015P_CODEC_DAI, }, - { - .name = RT1015P_DEV1_NAME, - .dai_name = RT1015P_CODEC_DAI, - }, }; -static int rt1015p_get_num_codecs(void) -{ - static int dev_num; - - if (dev_num) - return dev_num; - - if (!acpi_dev_present("RTL1015", "1", -1)) - dev_num = 1; - else - dev_num = 2; - - return dev_num; -} - static int rt1015p_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { @@ -398,12 +360,8 @@ static int rt1015p_init(struct snd_soc_pcm_runtime *rtd) return ret; } - if (rt1015p_get_num_codecs() == 1) - ret = snd_soc_dapm_add_routes(&card->dapm, rt1015p_1dev_dapm_routes, - ARRAY_SIZE(rt1015p_1dev_dapm_routes)); - else - ret = snd_soc_dapm_add_routes(&card->dapm, rt1015p_2dev_dapm_routes, - ARRAY_SIZE(rt1015p_2dev_dapm_routes)); + ret = snd_soc_dapm_add_routes(&card->dapm, rt1015p_dapm_routes, + ARRAY_SIZE(rt1015p_dapm_routes)); if (ret) dev_err(rtd->dev, "Speaker map addition failed: %d\n", ret); return ret; @@ -412,7 +370,7 @@ static int rt1015p_init(struct snd_soc_pcm_runtime *rtd) void sof_rt1015p_dai_link(struct snd_soc_dai_link *link) { link->codecs = rt1015p_dai_link_components; - link->num_codecs = rt1015p_get_num_codecs(); + link->num_codecs = ARRAY_SIZE(rt1015p_dai_link_components); link->init = rt1015p_init; link->ops = &rt1015p_ops; } @@ -420,11 +378,6 @@ EXPORT_SYMBOL_NS(sof_rt1015p_dai_link, SND_SOC_INTEL_SOF_REALTEK_COMMON); void sof_rt1015p_codec_conf(struct snd_soc_card *card) { - if (rt1015p_get_num_codecs() == 1) - return; - - card->codec_conf = rt1015p_codec_confs; - card->num_configs = ARRAY_SIZE(rt1015p_codec_confs); } EXPORT_SYMBOL_NS(sof_rt1015p_codec_conf, SND_SOC_INTEL_SOF_REALTEK_COMMON); diff --git a/sound/soc/intel/boards/sof_realtek_common.h b/sound/soc/intel/boards/sof_realtek_common.h index d0e331530b39..876290555c22 100644 --- a/sound/soc/intel/boards/sof_realtek_common.h +++ b/sound/soc/intel/boards/sof_realtek_common.h @@ -31,7 +31,6 @@ void sof_rt1011_codec_conf(struct device *dev, struct snd_soc_card *card); */ #define RT1015P_CODEC_DAI "HiFi" #define RT1015P_DEV0_NAME RT1015P_ACPI_HID ":00" -#define RT1015P_DEV1_NAME RT1015P_ACPI_HID ":01" void sof_rt1015p_dai_link(struct snd_soc_dai_link *link); void sof_rt1015p_codec_conf(struct snd_soc_card *card); -- cgit v1.2.3 From f77ae7fcdc47630eb7653983f3c57ac44103aebc Mon Sep 17 00:00:00 2001 From: Bard Liao Date: Thu, 9 May 2024 11:34:05 -0500 Subject: ASoC: Intel: soc-acpi-intel-mtl-match: add cs42l43 only support cs42l43 is on link 0. No amp in this configuration, will use cs42l43 speaker or bridge. Signed-off-by: Bard Liao Signed-off-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20240509163418.67746-6-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/intel/common/soc-acpi-intel-mtl-match.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/sound/soc/intel/common/soc-acpi-intel-mtl-match.c b/sound/soc/intel/common/soc-acpi-intel-mtl-match.c index 0bff91317768..48252fa9e39e 100644 --- a/sound/soc/intel/common/soc-acpi-intel-mtl-match.c +++ b/sound/soc/intel/common/soc-acpi-intel-mtl-match.c @@ -668,6 +668,14 @@ static const struct snd_soc_acpi_link_adr cs42l42_link0_max98363_link2[] = { {} }; +static const struct snd_soc_acpi_link_adr mtl_cs42l43_l0[] = { + { + .mask = BIT(0), + .num_adr = ARRAY_SIZE(cs42l43_0_adr), + .adr_d = cs42l43_0_adr, + }, +}; + static const struct snd_soc_acpi_link_adr mtl_cs42l43_cs35l56[] = { { .mask = BIT(0), @@ -782,6 +790,12 @@ struct snd_soc_acpi_mach snd_soc_acpi_intel_mtl_sdw_machines[] = { .drv_name = "sof_sdw", .sof_tplg_filename = "sof-mtl-cs42l43-l0-cs35l56-l12.tplg", }, + { + .link_mask = BIT(0), + .links = mtl_cs42l43_l0, + .drv_name = "sof_sdw", + .sof_tplg_filename = "sof-mtl-cs42l43-l0.tplg", + }, { .link_mask = GENMASK(3, 0), .links = mtl_3_in_1_sdca, -- cgit v1.2.3 From dd3bd9dc47084195fcb3c1b371cb03046abb13ab Mon Sep 17 00:00:00 2001 From: Bard Liao Date: Thu, 9 May 2024 11:34:06 -0500 Subject: ASoC: Intel: soc-acpi-intel-lnl-match: add cs42l43 only support cs42l43 is on link 0. No amp in this configuration, will use cs42l43 speaker or bridge. Signed-off-by: Bard Liao Signed-off-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20240509163418.67746-7-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/intel/common/soc-acpi-intel-lnl-match.c | 50 +++++++++++++++++++++++ 1 file changed, 50 insertions(+) diff --git a/sound/soc/intel/common/soc-acpi-intel-lnl-match.c b/sound/soc/intel/common/soc-acpi-intel-lnl-match.c index 0c08859c4773..e6ffcd5be6c5 100644 --- a/sound/soc/intel/common/soc-acpi-intel-lnl-match.c +++ b/sound/soc/intel/common/soc-acpi-intel-lnl-match.c @@ -76,6 +76,42 @@ static const struct snd_soc_acpi_endpoint rt722_endpoints[] = { }, }; +static const struct snd_soc_acpi_endpoint cs42l43_endpoints[] = { + { /* Jack Playback Endpoint */ + .num = 0, + .aggregated = 0, + .group_position = 0, + .group_id = 0, + }, + { /* DMIC Capture Endpoint */ + .num = 1, + .aggregated = 0, + .group_position = 0, + .group_id = 0, + }, + { /* Jack Capture Endpoint */ + .num = 2, + .aggregated = 0, + .group_position = 0, + .group_id = 0, + }, + { /* Speaker Playback Endpoint */ + .num = 3, + .aggregated = 0, + .group_position = 0, + .group_id = 0, + }, +}; + +static const struct snd_soc_acpi_adr_device cs42l43_0_adr[] = { + { + .adr = 0x00003001FA424301ull, + .num_endpoints = ARRAY_SIZE(cs42l43_endpoints), + .endpoints = cs42l43_endpoints, + .name_prefix = "cs42l43" + } +}; + static const struct snd_soc_acpi_adr_device rt711_sdca_0_adr[] = { { .adr = 0x000030025D071101ull, @@ -166,6 +202,14 @@ static const struct snd_soc_acpi_adr_device rt714_1_adr[] = { } }; +static const struct snd_soc_acpi_link_adr lnl_cs42l43_l0[] = { + { + .mask = BIT(0), + .num_adr = ARRAY_SIZE(cs42l43_0_adr), + .adr_d = cs42l43_0_adr, + }, +}; + static const struct snd_soc_acpi_link_adr lnl_rvp[] = { { .mask = BIT(0), @@ -268,6 +312,12 @@ struct snd_soc_acpi_mach snd_soc_acpi_intel_lnl_sdw_machines[] = { .drv_name = "sof_sdw", .sof_tplg_filename = "sof-lnl-rt711-l0-rt1316-l23-rt714-l1.tplg", }, + { + .link_mask = BIT(0), + .links = lnl_cs42l43_l0, + .drv_name = "sof_sdw", + .sof_tplg_filename = "sof-lnl-cs42l43-l0.tplg", + }, { .link_mask = BIT(0), .links = lnl_rvp, -- cgit v1.2.3 From 3895aa82b665d43b24ba1ac307e20df3396a6b65 Mon Sep 17 00:00:00 2001 From: Brent Lu Date: Thu, 9 May 2024 11:34:07 -0500 Subject: ASoC: Intel: maxim-common: add max_98373_dai_link function Add a helper function, max_98373_dai_link(), for machine driver to initialize dai link of maxim max98373 speaker amplifier. Reviewed-by: Bard Liao Signed-off-by: Brent Lu Signed-off-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20240509163418.67746-8-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/intel/boards/sof_maxim_common.c | 9 +++++++++ sound/soc/intel/boards/sof_maxim_common.h | 1 + 2 files changed, 10 insertions(+) diff --git a/sound/soc/intel/boards/sof_maxim_common.c b/sound/soc/intel/boards/sof_maxim_common.c index 7e1f485dce7a..c38c5598d87f 100644 --- a/sound/soc/intel/boards/sof_maxim_common.c +++ b/sound/soc/intel/boards/sof_maxim_common.c @@ -188,6 +188,15 @@ int max_98373_spk_codec_init(struct snd_soc_pcm_runtime *rtd) } EXPORT_SYMBOL_NS(max_98373_spk_codec_init, SND_SOC_INTEL_SOF_MAXIM_COMMON); +void max_98373_dai_link(struct device *dev, struct snd_soc_dai_link *link) +{ + link->codecs = max_98373_components; + link->num_codecs = ARRAY_SIZE(max_98373_components); + link->init = max_98373_spk_codec_init; + link->ops = &max_98373_ops; +} +EXPORT_SYMBOL_NS(max_98373_dai_link, SND_SOC_INTEL_SOF_MAXIM_COMMON); + void max_98373_set_codec_conf(struct snd_soc_card *card) { card->codec_conf = max_98373_codec_conf; diff --git a/sound/soc/intel/boards/sof_maxim_common.h b/sound/soc/intel/boards/sof_maxim_common.h index 8886f985de68..2d8257cc5229 100644 --- a/sound/soc/intel/boards/sof_maxim_common.h +++ b/sound/soc/intel/boards/sof_maxim_common.h @@ -25,6 +25,7 @@ extern struct snd_soc_ops max_98373_ops; extern const struct snd_soc_dapm_route max_98373_dapm_routes[]; int max_98373_spk_codec_init(struct snd_soc_pcm_runtime *rtd); +void max_98373_dai_link(struct device *dev, struct snd_soc_dai_link *link); void max_98373_set_codec_conf(struct snd_soc_card *card); int max_98373_trigger(struct snd_pcm_substream *substream, int cmd); -- cgit v1.2.3 From b533ed0d85cb64f9323b4221fcaad41259b08556 Mon Sep 17 00:00:00 2001 From: Brent Lu Date: Thu, 9 May 2024 11:34:08 -0500 Subject: ASoC: Intel: sof_da7219: use max_98373_dai_link function Use max_98373_dai_link() function to initialize dai link of maxim max98373 speaker amplifier. No functional change. Reviewed-by: Bard Liao Signed-off-by: Brent Lu Signed-off-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20240509163418.67746-9-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/intel/boards/sof_da7219.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/sound/soc/intel/boards/sof_da7219.c b/sound/soc/intel/boards/sof_da7219.c index d7b605896f89..886771e9b9d6 100644 --- a/sound/soc/intel/boards/sof_da7219.c +++ b/sound/soc/intel/boards/sof_da7219.c @@ -275,9 +275,8 @@ sof_card_dai_links_create(struct device *dev, struct snd_soc_card *card, max_98360a_dai_link(ctx->amp_link); break; case CODEC_MAX98373: - ctx->amp_link->codecs = max_98373_components; - ctx->amp_link->num_codecs = ARRAY_SIZE(max_98373_components); - ctx->amp_link->init = max_98373_spk_codec_init; + max_98373_dai_link(dev, ctx->amp_link); + if (ctx->da7219.is_jsl_board) { ctx->amp_link->ops = &max98373_ops; /* use local ops */ } else { -- cgit v1.2.3 From d304ab5ecb758f76bd4eafa6d7e0fac4eba48e88 Mon Sep 17 00:00:00 2001 From: Brent Lu Date: Thu, 9 May 2024 11:34:09 -0500 Subject: ASoC: Intel: sof_nau8825: use max_98373_dai_link function Use max_98373_dai_link() function to initialize dai link of maxim max98373 speaker amplifier. No functional change. Reviewed-by: Bard Liao Signed-off-by: Brent Lu Signed-off-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20240509163418.67746-10-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/intel/boards/sof_nau8825.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/sound/soc/intel/boards/sof_nau8825.c b/sound/soc/intel/boards/sof_nau8825.c index dd4dc4ec4255..c08b4eef0bcb 100644 --- a/sound/soc/intel/boards/sof_nau8825.c +++ b/sound/soc/intel/boards/sof_nau8825.c @@ -213,10 +213,7 @@ sof_card_dai_links_create(struct device *dev, struct snd_soc_card *card, max_98360a_dai_link(ctx->amp_link); break; case CODEC_MAX98373: - ctx->amp_link->codecs = max_98373_components; - ctx->amp_link->num_codecs = ARRAY_SIZE(max_98373_components); - ctx->amp_link->init = max_98373_spk_codec_init; - ctx->amp_link->ops = &max_98373_ops; + max_98373_dai_link(dev, ctx->amp_link); break; case CODEC_NAU8318: nau8318_set_dai_link(ctx->amp_link); -- cgit v1.2.3 From 834c4f95673fdb4394c6cf26242d8763ee6ccf28 Mon Sep 17 00:00:00 2001 From: Brent Lu Date: Thu, 9 May 2024 11:34:10 -0500 Subject: ASoC: Intel: sof_rt5682: use max_98373_dai_link function Use max_98373_dai_link() function to initialize dai link of maxim max98373 speaker amplifier. No functional change. Reviewed-by: Bard Liao Signed-off-by: Brent Lu Signed-off-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20240509163418.67746-11-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/intel/boards/sof_rt5682.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/sound/soc/intel/boards/sof_rt5682.c b/sound/soc/intel/boards/sof_rt5682.c index 3dc373855a58..6fc6eb0c5172 100644 --- a/sound/soc/intel/boards/sof_rt5682.c +++ b/sound/soc/intel/boards/sof_rt5682.c @@ -591,10 +591,7 @@ sof_card_dai_links_create(struct device *dev, struct snd_soc_card *card, max_98360a_dai_link(ctx->amp_link); break; case CODEC_MAX98373: - ctx->amp_link->codecs = max_98373_components; - ctx->amp_link->num_codecs = ARRAY_SIZE(max_98373_components); - ctx->amp_link->init = max_98373_spk_codec_init; - ctx->amp_link->ops = &max_98373_ops; + max_98373_dai_link(dev, ctx->amp_link); break; case CODEC_MAX98390: max_98390_dai_link(dev, ctx->amp_link); -- cgit v1.2.3 From 15ce635f396bdb416a41840bfb5e911128585e4d Mon Sep 17 00:00:00 2001 From: Brent Lu Date: Thu, 9 May 2024 11:34:11 -0500 Subject: ASoC: Intel: sof_sdw: add max98373 dapm routes Add dapm routes of max98373 to sdw driver and remove dependency of maxim-common module. Reviewed-by: Bard Liao Signed-off-by: Brent Lu Signed-off-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20240509163418.67746-12-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/intel/boards/Kconfig | 1 - sound/soc/intel/boards/sof_sdw.c | 1 - sound/soc/intel/boards/sof_sdw_maxim.c | 6 +++++- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/sound/soc/intel/boards/Kconfig b/sound/soc/intel/boards/Kconfig index 17bd0f883b9e..3ed81ab649c5 100644 --- a/sound/soc/intel/boards/Kconfig +++ b/sound/soc/intel/boards/Kconfig @@ -681,7 +681,6 @@ config SND_SOC_INTEL_SOUNDWIRE_SOF_MACH select SND_SOC_CS35L56_SDW select SND_SOC_DMIC select SND_SOC_INTEL_HDA_DSP_COMMON - select SND_SOC_INTEL_SOF_MAXIM_COMMON imply SND_SOC_SDW_MOCKUP help Add support for Intel SoundWire-based platforms connected to diff --git a/sound/soc/intel/boards/sof_sdw.c b/sound/soc/intel/boards/sof_sdw.c index b1595fdb500d..2b97972f85ef 100644 --- a/sound/soc/intel/boards/sof_sdw.c +++ b/sound/soc/intel/boards/sof_sdw.c @@ -2067,4 +2067,3 @@ MODULE_AUTHOR("Rander Wang "); MODULE_AUTHOR("Pierre-Louis Bossart "); MODULE_LICENSE("GPL v2"); MODULE_IMPORT_NS(SND_SOC_INTEL_HDA_DSP_COMMON); -MODULE_IMPORT_NS(SND_SOC_INTEL_SOF_MAXIM_COMMON); diff --git a/sound/soc/intel/boards/sof_sdw_maxim.c b/sound/soc/intel/boards/sof_sdw_maxim.c index 432e5112415a..57c1a5fb17a9 100644 --- a/sound/soc/intel/boards/sof_sdw_maxim.c +++ b/sound/soc/intel/boards/sof_sdw_maxim.c @@ -11,7 +11,6 @@ #include #include #include "sof_sdw_common.h" -#include "sof_maxim_common.h" static int maxim_part_id; #define SOF_SDW_PART_ID_MAX98363 0x8363 @@ -27,6 +26,11 @@ static const struct snd_kcontrol_new maxim_controls[] = { SOC_DAPM_PIN_SWITCH("Right Spk"), }; +static const struct snd_soc_dapm_route max_98373_dapm_routes[] = { + { "Left Spk", NULL, "Left BE_OUT" }, + { "Right Spk", NULL, "Right BE_OUT" }, +}; + int maxim_spk_rtd_init(struct snd_soc_pcm_runtime *rtd) { struct snd_soc_card *card = rtd->card; -- cgit v1.2.3 From 2bb765f053910339126626d49ae851b937d06206 Mon Sep 17 00:00:00 2001 From: Brent Lu Date: Thu, 9 May 2024 11:34:12 -0500 Subject: ASoC: Intel: maxim-common: change max98373 data to static Since there is dai link helper max_98373_dai_link, we could change all functions and data of max98373 to static. Reviewed-by: Bard Liao Signed-off-by: Brent Lu Signed-off-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20240509163418.67746-13-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/intel/boards/sof_maxim_common.c | 18 ++++++++---------- sound/soc/intel/boards/sof_maxim_common.h | 6 ------ 2 files changed, 8 insertions(+), 16 deletions(-) diff --git a/sound/soc/intel/boards/sof_maxim_common.c b/sound/soc/intel/boards/sof_maxim_common.c index c38c5598d87f..6c40ecc04723 100644 --- a/sound/soc/intel/boards/sof_maxim_common.c +++ b/sound/soc/intel/boards/sof_maxim_common.c @@ -39,14 +39,16 @@ static unsigned int get_num_codecs(const char *hid) return dev_num; } +/* + * Maxim MAX98373 + */ #define MAX_98373_PIN_NAME 16 -const struct snd_soc_dapm_route max_98373_dapm_routes[] = { +static const struct snd_soc_dapm_route max_98373_dapm_routes[] = { /* speaker */ { "Left Spk", NULL, "Left BE_OUT" }, { "Right Spk", NULL, "Right BE_OUT" }, }; -EXPORT_SYMBOL_NS(max_98373_dapm_routes, SND_SOC_INTEL_SOF_MAXIM_COMMON); static struct snd_soc_codec_conf max_98373_codec_conf[] = { { @@ -59,7 +61,7 @@ static struct snd_soc_codec_conf max_98373_codec_conf[] = { }, }; -struct snd_soc_dai_link_component max_98373_components[] = { +static struct snd_soc_dai_link_component max_98373_components[] = { { /* For Right */ .name = MAX_98373_DEV0_NAME, .dai_name = MAX_98373_CODEC_DAI, @@ -69,7 +71,6 @@ struct snd_soc_dai_link_component max_98373_components[] = { .dai_name = MAX_98373_CODEC_DAI, }, }; -EXPORT_SYMBOL_NS(max_98373_components, SND_SOC_INTEL_SOF_MAXIM_COMMON); static int max_98373_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) @@ -96,7 +97,7 @@ static int max_98373_hw_params(struct snd_pcm_substream *substream, return 0; } -int max_98373_trigger(struct snd_pcm_substream *substream, int cmd) +static int max_98373_trigger(struct snd_pcm_substream *substream, int cmd) { struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream); struct snd_soc_dai *codec_dai; @@ -139,15 +140,13 @@ int max_98373_trigger(struct snd_pcm_substream *substream, int cmd) return ret; } -EXPORT_SYMBOL_NS(max_98373_trigger, SND_SOC_INTEL_SOF_MAXIM_COMMON); -struct snd_soc_ops max_98373_ops = { +static const struct snd_soc_ops max_98373_ops = { .hw_params = max_98373_hw_params, .trigger = max_98373_trigger, }; -EXPORT_SYMBOL_NS(max_98373_ops, SND_SOC_INTEL_SOF_MAXIM_COMMON); -int max_98373_spk_codec_init(struct snd_soc_pcm_runtime *rtd) +static int max_98373_spk_codec_init(struct snd_soc_pcm_runtime *rtd) { struct snd_soc_card *card = rtd->card; unsigned int num_codecs = get_num_codecs(MAX_98373_ACPI_HID); @@ -186,7 +185,6 @@ int max_98373_spk_codec_init(struct snd_soc_pcm_runtime *rtd) return ret; } -EXPORT_SYMBOL_NS(max_98373_spk_codec_init, SND_SOC_INTEL_SOF_MAXIM_COMMON); void max_98373_dai_link(struct device *dev, struct snd_soc_dai_link *link) { diff --git a/sound/soc/intel/boards/sof_maxim_common.h b/sound/soc/intel/boards/sof_maxim_common.h index 2d8257cc5229..3d34c7dae6f5 100644 --- a/sound/soc/intel/boards/sof_maxim_common.h +++ b/sound/soc/intel/boards/sof_maxim_common.h @@ -20,14 +20,8 @@ #define MAX_98373_DEV0_NAME "i2c-" MAX_98373_ACPI_HID ":00" #define MAX_98373_DEV1_NAME "i2c-" MAX_98373_ACPI_HID ":01" -extern struct snd_soc_dai_link_component max_98373_components[2]; -extern struct snd_soc_ops max_98373_ops; -extern const struct snd_soc_dapm_route max_98373_dapm_routes[]; - -int max_98373_spk_codec_init(struct snd_soc_pcm_runtime *rtd); void max_98373_dai_link(struct device *dev, struct snd_soc_dai_link *link); void max_98373_set_codec_conf(struct snd_soc_card *card); -int max_98373_trigger(struct snd_pcm_substream *substream, int cmd); /* * Maxim MAX98390 -- cgit v1.2.3 From 1628e1c8f6f1446460fc33a06f52e5ce52ac587a Mon Sep 17 00:00:00 2001 From: Bard Liao Date: Thu, 9 May 2024 11:34:13 -0500 Subject: ASoC: Intel: sof_sdw_cs_amp: rename Speakers to Speaker MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit To be consistent to other amps that used in the machine driver. Reviewed-by: Péter Ujfalusi Signed-off-by: Bard Liao Signed-off-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20240509163418.67746-14-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/intel/boards/sof_sdw_cs_amp.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/soc/intel/boards/sof_sdw_cs_amp.c b/sound/soc/intel/boards/sof_sdw_cs_amp.c index e29a586ce7c0..3538d3c752b7 100644 --- a/sound/soc/intel/boards/sof_sdw_cs_amp.c +++ b/sound/soc/intel/boards/sof_sdw_cs_amp.c @@ -15,7 +15,7 @@ #define CODEC_NAME_SIZE 8 static const struct snd_soc_dapm_widget sof_widgets[] = { - SND_SOC_DAPM_SPK("Speakers", NULL), + SND_SOC_DAPM_SPK("Speaker", NULL), }; int cs_spk_rtd_init(struct snd_soc_pcm_runtime *rtd) @@ -24,7 +24,7 @@ int cs_spk_rtd_init(struct snd_soc_pcm_runtime *rtd) struct snd_soc_card *card = rtd->card; char codec_name[CODEC_NAME_SIZE]; char widget_name[16]; - struct snd_soc_dapm_route route = { "Speakers", NULL, widget_name }; + struct snd_soc_dapm_route route = { "Speaker", NULL, widget_name }; struct snd_soc_dai *codec_dai; int i, ret; -- cgit v1.2.3 From 01c266af92f4d24d44939e7d21c36e898caaa18f Mon Sep 17 00:00:00 2001 From: Bard Liao Date: Thu, 9 May 2024 11:34:14 -0500 Subject: ASoC: Intel: sof_sdw: use generic name for controls/widgets MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Some controls and widgets have exactly the same items. Rename them to be generic. This is a preparation for further cleanup. No function change. Reviewed-by: Péter Ujfalusi Signed-off-by: Bard Liao Signed-off-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20240509163418.67746-15-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/intel/boards/sof_sdw_cs42l42.c | 12 ++++++------ sound/soc/intel/boards/sof_sdw_cs42l43.c | 18 +++++++++--------- sound/soc/intel/boards/sof_sdw_cs_amp.c | 6 +++--- sound/soc/intel/boards/sof_sdw_rt5682.c | 12 ++++++------ sound/soc/intel/boards/sof_sdw_rt711.c | 12 ++++++------ sound/soc/intel/boards/sof_sdw_rt712_sdca.c | 12 ++++++------ sound/soc/intel/boards/sof_sdw_rt722_sdca.c | 12 ++++++------ sound/soc/intel/boards/sof_sdw_rt_amp.c | 16 ++++++++-------- sound/soc/intel/boards/sof_sdw_rt_sdca_jack_common.c | 12 ++++++------ 9 files changed, 56 insertions(+), 56 deletions(-) diff --git a/sound/soc/intel/boards/sof_sdw_cs42l42.c b/sound/soc/intel/boards/sof_sdw_cs42l42.c index b999f4e7901a..82555c53a9c9 100644 --- a/sound/soc/intel/boards/sof_sdw_cs42l42.c +++ b/sound/soc/intel/boards/sof_sdw_cs42l42.c @@ -17,7 +17,7 @@ #include #include "sof_sdw_common.h" -static const struct snd_soc_dapm_widget cs42l42_widgets[] = { +static const struct snd_soc_dapm_widget generic_jack_widgets[] = { SND_SOC_DAPM_HP("Headphone", NULL), SND_SOC_DAPM_MIC("Headset Mic", NULL), }; @@ -30,7 +30,7 @@ static const struct snd_soc_dapm_route cs42l42_map[] = { {"cs42l42 HS", NULL, "Headset Mic"}, }; -static const struct snd_kcontrol_new cs42l42_controls[] = { +static const struct snd_kcontrol_new generic_jack_controls[] = { SOC_DAPM_PIN_SWITCH("Headphone"), SOC_DAPM_PIN_SWITCH("Headset Mic"), }; @@ -70,15 +70,15 @@ int cs42l42_rtd_init(struct snd_soc_pcm_runtime *rtd) if (!card->components) return -ENOMEM; - ret = snd_soc_add_card_controls(card, cs42l42_controls, - ARRAY_SIZE(cs42l42_controls)); + ret = snd_soc_add_card_controls(card, generic_jack_controls, + ARRAY_SIZE(generic_jack_controls)); if (ret) { dev_err(card->dev, "cs42l42 control addition failed: %d\n", ret); return ret; } - ret = snd_soc_dapm_new_controls(&card->dapm, cs42l42_widgets, - ARRAY_SIZE(cs42l42_widgets)); + ret = snd_soc_dapm_new_controls(&card->dapm, generic_jack_widgets, + ARRAY_SIZE(generic_jack_widgets)); if (ret) { dev_err(card->dev, "cs42l42 widgets addition failed: %d\n", ret); return ret; diff --git a/sound/soc/intel/boards/sof_sdw_cs42l43.c b/sound/soc/intel/boards/sof_sdw_cs42l43.c index 0fd5e099bb1a..f76a16795fda 100644 --- a/sound/soc/intel/boards/sof_sdw_cs42l43.c +++ b/sound/soc/intel/boards/sof_sdw_cs42l43.c @@ -18,7 +18,7 @@ #include #include "sof_sdw_common.h" -static const struct snd_soc_dapm_widget cs42l43_hs_widgets[] = { +static const struct snd_soc_dapm_widget generic_jack_widgets[] = { SND_SOC_DAPM_HP("Headphone", NULL), SND_SOC_DAPM_MIC("Headset Mic", NULL), }; @@ -30,7 +30,7 @@ static const struct snd_soc_dapm_route cs42l43_hs_map[] = { { "cs42l43 ADC1_IN1_N", NULL, "Headset Mic" }, }; -static const struct snd_soc_dapm_widget cs42l43_spk_widgets[] = { +static const struct snd_soc_dapm_widget generic_spk_widgets[] = { SND_SOC_DAPM_SPK("Speaker", NULL), }; @@ -41,7 +41,7 @@ static const struct snd_soc_dapm_route cs42l43_spk_map[] = { { "Speaker", NULL, "cs42l43 AMP2_OUT_N", }, }; -static const struct snd_soc_dapm_widget cs42l43_dmic_widgets[] = { +static const struct snd_soc_dapm_widget generic_dmic_widgets[] = { SND_SOC_DAPM_MIC("DMIC", NULL), }; @@ -74,8 +74,8 @@ int cs42l43_hs_rtd_init(struct snd_soc_pcm_runtime *rtd) if (!card->components) return -ENOMEM; - ret = snd_soc_dapm_new_controls(&card->dapm, cs42l43_hs_widgets, - ARRAY_SIZE(cs42l43_hs_widgets)); + ret = snd_soc_dapm_new_controls(&card->dapm, generic_jack_widgets, + ARRAY_SIZE(generic_jack_widgets)); if (ret) { dev_err(card->dev, "cs42l43 hs widgets addition failed: %d\n", ret); return ret; @@ -133,8 +133,8 @@ int cs42l43_spk_rtd_init(struct snd_soc_pcm_runtime *rtd) return -ENOMEM; } - ret = snd_soc_dapm_new_controls(&card->dapm, cs42l43_spk_widgets, - ARRAY_SIZE(cs42l43_spk_widgets)); + ret = snd_soc_dapm_new_controls(&card->dapm, generic_spk_widgets, + ARRAY_SIZE(generic_spk_widgets)); if (ret) { dev_err(card->dev, "cs42l43 speaker widgets addition failed: %d\n", ret); return ret; @@ -172,8 +172,8 @@ int cs42l43_dmic_rtd_init(struct snd_soc_pcm_runtime *rtd) if (!card->components) return -ENOMEM; - ret = snd_soc_dapm_new_controls(&card->dapm, cs42l43_dmic_widgets, - ARRAY_SIZE(cs42l43_dmic_widgets)); + ret = snd_soc_dapm_new_controls(&card->dapm, generic_dmic_widgets, + ARRAY_SIZE(generic_dmic_widgets)); if (ret) { dev_err(card->dev, "cs42l43 dmic widgets addition failed: %d\n", ret); return ret; diff --git a/sound/soc/intel/boards/sof_sdw_cs_amp.c b/sound/soc/intel/boards/sof_sdw_cs_amp.c index 3538d3c752b7..e15a4753f103 100644 --- a/sound/soc/intel/boards/sof_sdw_cs_amp.c +++ b/sound/soc/intel/boards/sof_sdw_cs_amp.c @@ -14,7 +14,7 @@ #define CODEC_NAME_SIZE 8 -static const struct snd_soc_dapm_widget sof_widgets[] = { +static const struct snd_soc_dapm_widget generic_spk_widgets[] = { SND_SOC_DAPM_SPK("Speaker", NULL), }; @@ -35,8 +35,8 @@ int cs_spk_rtd_init(struct snd_soc_pcm_runtime *rtd) if (!card->components) return -ENOMEM; - ret = snd_soc_dapm_new_controls(&card->dapm, sof_widgets, - ARRAY_SIZE(sof_widgets)); + ret = snd_soc_dapm_new_controls(&card->dapm, generic_spk_widgets, + ARRAY_SIZE(generic_spk_widgets)); if (ret) { dev_err(card->dev, "widgets addition failed: %d\n", ret); return ret; diff --git a/sound/soc/intel/boards/sof_sdw_rt5682.c b/sound/soc/intel/boards/sof_sdw_rt5682.c index f812aea64322..9fbe36322a83 100644 --- a/sound/soc/intel/boards/sof_sdw_rt5682.c +++ b/sound/soc/intel/boards/sof_sdw_rt5682.c @@ -17,7 +17,7 @@ #include #include "sof_sdw_common.h" -static const struct snd_soc_dapm_widget rt5682_widgets[] = { +static const struct snd_soc_dapm_widget generic_jack_widgets[] = { SND_SOC_DAPM_HP("Headphone", NULL), SND_SOC_DAPM_MIC("Headset Mic", NULL), }; @@ -29,7 +29,7 @@ static const struct snd_soc_dapm_route rt5682_map[] = { { "rt5682 IN1P", NULL, "Headset Mic" }, }; -static const struct snd_kcontrol_new rt5682_controls[] = { +static const struct snd_kcontrol_new generic_jack_controls[] = { SOC_DAPM_PIN_SWITCH("Headphone"), SOC_DAPM_PIN_SWITCH("Headset Mic"), }; @@ -69,15 +69,15 @@ int rt5682_rtd_init(struct snd_soc_pcm_runtime *rtd) if (!card->components) return -ENOMEM; - ret = snd_soc_add_card_controls(card, rt5682_controls, - ARRAY_SIZE(rt5682_controls)); + ret = snd_soc_add_card_controls(card, generic_jack_controls, + ARRAY_SIZE(generic_jack_controls)); if (ret) { dev_err(card->dev, "rt5682 control addition failed: %d\n", ret); return ret; } - ret = snd_soc_dapm_new_controls(&card->dapm, rt5682_widgets, - ARRAY_SIZE(rt5682_widgets)); + ret = snd_soc_dapm_new_controls(&card->dapm, generic_jack_widgets, + ARRAY_SIZE(generic_jack_widgets)); if (ret) { dev_err(card->dev, "rt5682 widgets addition failed: %d\n", ret); return ret; diff --git a/sound/soc/intel/boards/sof_sdw_rt711.c b/sound/soc/intel/boards/sof_sdw_rt711.c index 7e54fc5cbe09..1a0f6692034a 100644 --- a/sound/soc/intel/boards/sof_sdw_rt711.c +++ b/sound/soc/intel/boards/sof_sdw_rt711.c @@ -42,7 +42,7 @@ static int rt711_add_codec_device_props(struct device *sdw_dev) return ret; } -static const struct snd_soc_dapm_widget rt711_widgets[] = { +static const struct snd_soc_dapm_widget generic_jack_widgets[] = { SND_SOC_DAPM_HP("Headphone", NULL), SND_SOC_DAPM_MIC("Headset Mic", NULL), }; @@ -53,7 +53,7 @@ static const struct snd_soc_dapm_route rt711_map[] = { { "rt711 MIC2", NULL, "Headset Mic" }, }; -static const struct snd_kcontrol_new rt711_controls[] = { +static const struct snd_kcontrol_new generic_jack_controls[] = { SOC_DAPM_PIN_SWITCH("Headphone"), SOC_DAPM_PIN_SWITCH("Headset Mic"), }; @@ -93,15 +93,15 @@ int rt711_rtd_init(struct snd_soc_pcm_runtime *rtd) if (!card->components) return -ENOMEM; - ret = snd_soc_add_card_controls(card, rt711_controls, - ARRAY_SIZE(rt711_controls)); + ret = snd_soc_add_card_controls(card, generic_jack_controls, + ARRAY_SIZE(generic_jack_controls)); if (ret) { dev_err(card->dev, "rt711 controls addition failed: %d\n", ret); return ret; } - ret = snd_soc_dapm_new_controls(&card->dapm, rt711_widgets, - ARRAY_SIZE(rt711_widgets)); + ret = snd_soc_dapm_new_controls(&card->dapm, generic_jack_widgets, + ARRAY_SIZE(generic_jack_widgets)); if (ret) { dev_err(card->dev, "rt711 widgets addition failed: %d\n", ret); return ret; diff --git a/sound/soc/intel/boards/sof_sdw_rt712_sdca.c b/sound/soc/intel/boards/sof_sdw_rt712_sdca.c index 0c4cd4cdbd45..42308228c634 100644 --- a/sound/soc/intel/boards/sof_sdw_rt712_sdca.c +++ b/sound/soc/intel/boards/sof_sdw_rt712_sdca.c @@ -15,7 +15,7 @@ #include #include "sof_sdw_common.h" -static const struct snd_soc_dapm_widget rt712_spk_widgets[] = { +static const struct snd_soc_dapm_widget generic_spk_widgets[] = { SND_SOC_DAPM_SPK("Speaker", NULL), }; @@ -30,7 +30,7 @@ static const struct snd_soc_dapm_route rt712_spk_map[] = { { "Speaker", NULL, "rt712 SPOR" }, }; -static const struct snd_kcontrol_new rt712_spk_controls[] = { +static const struct snd_kcontrol_new generic_spk_controls[] = { SOC_DAPM_PIN_SWITCH("Speaker"), }; @@ -45,15 +45,15 @@ int rt712_spk_rtd_init(struct snd_soc_pcm_runtime *rtd) if (!card->components) return -ENOMEM; - ret = snd_soc_add_card_controls(card, rt712_spk_controls, - ARRAY_SIZE(rt712_spk_controls)); + ret = snd_soc_add_card_controls(card, generic_spk_controls, + ARRAY_SIZE(generic_spk_controls)); if (ret) { dev_err(card->dev, "rt712 spk controls addition failed: %d\n", ret); return ret; } - ret = snd_soc_dapm_new_controls(&card->dapm, rt712_spk_widgets, - ARRAY_SIZE(rt712_spk_widgets)); + ret = snd_soc_dapm_new_controls(&card->dapm, generic_spk_widgets, + ARRAY_SIZE(generic_spk_widgets)); if (ret) { dev_err(card->dev, "rt712 spk widgets addition failed: %d\n", ret); return ret; diff --git a/sound/soc/intel/boards/sof_sdw_rt722_sdca.c b/sound/soc/intel/boards/sof_sdw_rt722_sdca.c index e5c2a36e400b..1653e45a0f7d 100644 --- a/sound/soc/intel/boards/sof_sdw_rt722_sdca.c +++ b/sound/soc/intel/boards/sof_sdw_rt722_sdca.c @@ -15,7 +15,7 @@ #include #include "sof_sdw_common.h" -static const struct snd_soc_dapm_widget rt722_spk_widgets[] = { +static const struct snd_soc_dapm_widget generic_spk_widgets[] = { SND_SOC_DAPM_SPK("Speaker", NULL), }; @@ -23,7 +23,7 @@ static const struct snd_soc_dapm_route rt722_spk_map[] = { { "Speaker", NULL, "rt722 SPK" }, }; -static const struct snd_kcontrol_new rt722_spk_controls[] = { +static const struct snd_kcontrol_new generic_spk_controls[] = { SOC_DAPM_PIN_SWITCH("Speaker"), }; @@ -38,15 +38,15 @@ int rt722_spk_rtd_init(struct snd_soc_pcm_runtime *rtd) if (!card->components) return -ENOMEM; - ret = snd_soc_add_card_controls(card, rt722_spk_controls, - ARRAY_SIZE(rt722_spk_controls)); + ret = snd_soc_add_card_controls(card, generic_spk_controls, + ARRAY_SIZE(generic_spk_controls)); if (ret) { dev_err(card->dev, "failed to add rt722 spk controls: %d\n", ret); return ret; } - ret = snd_soc_dapm_new_controls(&card->dapm, rt722_spk_widgets, - ARRAY_SIZE(rt722_spk_widgets)); + ret = snd_soc_dapm_new_controls(&card->dapm, generic_spk_widgets, + ARRAY_SIZE(generic_spk_widgets)); if (ret) { dev_err(card->dev, "failed to add rt722 spk widgets: %d\n", ret); return ret; diff --git a/sound/soc/intel/boards/sof_sdw_rt_amp.c b/sound/soc/intel/boards/sof_sdw_rt_amp.c index 1b415708500e..03e0978e6a88 100644 --- a/sound/soc/intel/boards/sof_sdw_rt_amp.c +++ b/sound/soc/intel/boards/sof_sdw_rt_amp.c @@ -131,12 +131,12 @@ static int rt_amp_add_device_props(struct device *sdw_dev) return ret; } -static const struct snd_kcontrol_new rt_amp_controls[] = { - SOC_DAPM_PIN_SWITCH("Speaker"), +static const struct snd_soc_dapm_widget generic_spk_widgets[] = { + SND_SOC_DAPM_SPK("Speaker", NULL), }; -static const struct snd_soc_dapm_widget rt_amp_widgets[] = { - SND_SOC_DAPM_SPK("Speaker", NULL), +static const struct snd_kcontrol_new generic_spk_controls[] = { + SOC_DAPM_PIN_SWITCH("Speaker"), }; /* @@ -202,15 +202,15 @@ int rt_amp_spk_rtd_init(struct snd_soc_pcm_runtime *rtd) if (!card->components) return -ENOMEM; - ret = snd_soc_add_card_controls(card, rt_amp_controls, - ARRAY_SIZE(rt_amp_controls)); + ret = snd_soc_add_card_controls(card, generic_spk_controls, + ARRAY_SIZE(generic_spk_controls)); if (ret) { dev_err(card->dev, "%s controls addition failed: %d\n", codec_name, ret); return ret; } - ret = snd_soc_dapm_new_controls(&card->dapm, rt_amp_widgets, - ARRAY_SIZE(rt_amp_widgets)); + ret = snd_soc_dapm_new_controls(&card->dapm, generic_spk_widgets, + ARRAY_SIZE(generic_spk_widgets)); if (ret) { dev_err(card->dev, "%s widgets addition failed: %d\n", codec_name, ret); return ret; diff --git a/sound/soc/intel/boards/sof_sdw_rt_sdca_jack_common.c b/sound/soc/intel/boards/sof_sdw_rt_sdca_jack_common.c index 69161ea5b290..932fba8ccf9a 100644 --- a/sound/soc/intel/boards/sof_sdw_rt_sdca_jack_common.c +++ b/sound/soc/intel/boards/sof_sdw_rt_sdca_jack_common.c @@ -43,7 +43,7 @@ static int rt_sdca_jack_add_codec_device_props(struct device *sdw_dev) return ret; } -static const struct snd_soc_dapm_widget rt_sdca_jack_widgets[] = { +static const struct snd_soc_dapm_widget generic_jack_widgets[] = { SND_SOC_DAPM_HP("Headphone", NULL), SND_SOC_DAPM_MIC("Headset Mic", NULL), }; @@ -68,7 +68,7 @@ static const struct snd_soc_dapm_route rt722_sdca_map[] = { { "rt722 MIC2", NULL, "Headset Mic" }, }; -static const struct snd_kcontrol_new rt_sdca_jack_controls[] = { +static const struct snd_kcontrol_new generic_jack_controls[] = { SOC_DAPM_PIN_SWITCH("Headphone"), SOC_DAPM_PIN_SWITCH("Headset Mic"), }; @@ -129,15 +129,15 @@ int rt_sdca_jack_rtd_init(struct snd_soc_pcm_runtime *rtd) } } - ret = snd_soc_add_card_controls(card, rt_sdca_jack_controls, - ARRAY_SIZE(rt_sdca_jack_controls)); + ret = snd_soc_add_card_controls(card, generic_jack_controls, + ARRAY_SIZE(generic_jack_controls)); if (ret) { dev_err(card->dev, "rt sdca jack controls addition failed: %d\n", ret); return ret; } - ret = snd_soc_dapm_new_controls(&card->dapm, rt_sdca_jack_widgets, - ARRAY_SIZE(rt_sdca_jack_widgets)); + ret = snd_soc_dapm_new_controls(&card->dapm, generic_jack_widgets, + ARRAY_SIZE(generic_jack_widgets)); if (ret) { dev_err(card->dev, "rt sdca jack widgets addition failed: %d\n", ret); return ret; -- cgit v1.2.3 From 70d470f05f0b5bb8dea67915cac6ed6308120a89 Mon Sep 17 00:00:00 2001 From: Bard Liao Date: Thu, 9 May 2024 11:34:15 -0500 Subject: ASoC: Intel: sof_sdw: add controls and dapm widgets in codec_info MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Currently, we add card controls and dapm widgets one by one in the codec_info->dais->rtd_init callback. Duplicated controls and dapm widgets will be added if there are more than one types of amps in the dai link. Moving it to sof_sdw_rtd_init() and only add the controls/widgets of the first codec dai can avoid the duplications. Reviewed-by: Péter Ujfalusi Signed-off-by: Bard Liao Signed-off-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20240509163418.67746-16-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/intel/boards/sof_sdw.c | 31 +++++++++++++++++++++++++++++++ sound/soc/intel/boards/sof_sdw_common.h | 4 ++++ 2 files changed, 35 insertions(+) diff --git a/sound/soc/intel/boards/sof_sdw.c b/sound/soc/intel/boards/sof_sdw.c index 2b97972f85ef..3acc2db61b35 100644 --- a/sound/soc/intel/boards/sof_sdw.c +++ b/sound/soc/intel/boards/sof_sdw.c @@ -1248,6 +1248,7 @@ static const char *get_codec_name(struct device *dev, static int sof_sdw_rtd_init(struct snd_soc_pcm_runtime *rtd) { + struct snd_soc_card *card = rtd->card; struct sof_sdw_codec_info *codec_info; struct snd_soc_dai *dai; int dai_index; @@ -1267,6 +1268,36 @@ static int sof_sdw_rtd_init(struct snd_soc_pcm_runtime *rtd) */ if (codec_info->dais[dai_index].rtd_init_done) continue; + + /* + * Add card controls and dapm widgets for the first codec dai. + * The controls and widgets will be used for all codec dais. + */ + + if (i > 0) + goto skip_add_controls_widgets; + + if (codec_info->dais[dai_index].controls) { + ret = snd_soc_add_card_controls(card, codec_info->dais[dai_index].controls, + codec_info->dais[dai_index].num_controls); + if (ret) { + dev_err(card->dev, "%#x controls addition failed: %d\n", + codec_info->part_id, ret); + return ret; + } + } + if (codec_info->dais[dai_index].widgets) { + ret = snd_soc_dapm_new_controls(&card->dapm, + codec_info->dais[dai_index].widgets, + codec_info->dais[dai_index].num_widgets); + if (ret) { + dev_err(card->dev, "%#x widgets addition failed: %d\n", + codec_info->part_id, ret); + return ret; + } + } + +skip_add_controls_widgets: if (codec_info->dais[dai_index].rtd_init) { ret = codec_info->dais[dai_index].rtd_init(rtd); if (ret) diff --git a/sound/soc/intel/boards/sof_sdw_common.h b/sound/soc/intel/boards/sof_sdw_common.h index 94657dd210f5..a8ba39bd5fd8 100644 --- a/sound/soc/intel/boards/sof_sdw_common.h +++ b/sound/soc/intel/boards/sof_sdw_common.h @@ -86,6 +86,10 @@ struct sof_sdw_dai_info { const char *dai_name; const int dai_type; const int dailink[2]; /* dailink id for each direction */ + const struct snd_kcontrol_new *controls; + const int num_controls; + const struct snd_soc_dapm_widget *widgets; + const int num_widgets; int (*init)(struct snd_soc_card *card, struct snd_soc_dai_link *dai_links, struct sof_sdw_codec_info *info, -- cgit v1.2.3 From 2e3bc94796776e2695054183e7324d1a6ac27837 Mon Sep 17 00:00:00 2001 From: Bard Liao Date: Thu, 9 May 2024 11:34:16 -0500 Subject: ASoC: Intel: sof_sdw: use .controls/.widgets to add controls/widgets MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit sof_sdw_rtd_init() will add the controls and widgets if we set them in the codec_info. Move the additions from .rtd_init callback to sof_sdw_rtd_init(). Reviewed-by: Péter Ujfalusi Signed-off-by: Bard Liao Signed-off-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20240509163418.67746-17-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/intel/boards/sof_sdw.c | 112 +++++++++++++++++++++ sound/soc/intel/boards/sof_sdw_cs42l42.c | 24 ----- sound/soc/intel/boards/sof_sdw_cs42l43.c | 34 ------- sound/soc/intel/boards/sof_sdw_cs_amp.c | 11 -- sound/soc/intel/boards/sof_sdw_maxim.c | 24 ----- sound/soc/intel/boards/sof_sdw_rt5682.c | 24 ----- sound/soc/intel/boards/sof_sdw_rt700.c | 26 ----- sound/soc/intel/boards/sof_sdw_rt711.c | 24 ----- sound/soc/intel/boards/sof_sdw_rt712_sdca.c | 22 ---- sound/soc/intel/boards/sof_sdw_rt722_sdca.c | 22 ---- sound/soc/intel/boards/sof_sdw_rt_amp.c | 22 ---- .../soc/intel/boards/sof_sdw_rt_sdca_jack_common.c | 24 ----- 12 files changed, 112 insertions(+), 257 deletions(-) diff --git a/sound/soc/intel/boards/sof_sdw.c b/sound/soc/intel/boards/sof_sdw.c index 3acc2db61b35..8c1497bab2ef 100644 --- a/sound/soc/intel/boards/sof_sdw.c +++ b/sound/soc/intel/boards/sof_sdw.c @@ -515,6 +515,50 @@ static struct snd_soc_dai_link_component platform_component[] = { } }; +static const struct snd_soc_dapm_widget generic_dmic_widgets[] = { + SND_SOC_DAPM_MIC("DMIC", NULL), +}; + +static const struct snd_soc_dapm_widget generic_jack_widgets[] = { + SND_SOC_DAPM_HP("Headphone", NULL), + SND_SOC_DAPM_MIC("Headset Mic", NULL), +}; + +static const struct snd_kcontrol_new generic_jack_controls[] = { + SOC_DAPM_PIN_SWITCH("Headphone"), + SOC_DAPM_PIN_SWITCH("Headset Mic"), +}; + +static const struct snd_soc_dapm_widget generic_spk_widgets[] = { + SND_SOC_DAPM_SPK("Speaker", NULL), +}; + +static const struct snd_kcontrol_new generic_spk_controls[] = { + SOC_DAPM_PIN_SWITCH("Speaker"), +}; + +static const struct snd_soc_dapm_widget maxim_widgets[] = { + SND_SOC_DAPM_SPK("Left Spk", NULL), + SND_SOC_DAPM_SPK("Right Spk", NULL), +}; + +static const struct snd_kcontrol_new maxim_controls[] = { + SOC_DAPM_PIN_SWITCH("Left Spk"), + SOC_DAPM_PIN_SWITCH("Right Spk"), +}; + +static const struct snd_soc_dapm_widget rt700_widgets[] = { + SND_SOC_DAPM_HP("Headphones", NULL), + SND_SOC_DAPM_MIC("AMIC", NULL), + SND_SOC_DAPM_SPK("Speaker", NULL), +}; + +static const struct snd_kcontrol_new rt700_controls[] = { + SOC_DAPM_PIN_SWITCH("Headphones"), + SOC_DAPM_PIN_SWITCH("AMIC"), + SOC_DAPM_PIN_SWITCH("Speaker"), +}; + struct snd_soc_dai *get_codec_dai_by_name(struct snd_soc_pcm_runtime *rtd, const char * const dai_name[], int num_dais) @@ -681,6 +725,10 @@ static struct sof_sdw_codec_info codec_info_list[] = { .dai_type = SOF_SDW_DAI_TYPE_JACK, .dailink = {SDW_JACK_OUT_DAI_ID, SDW_JACK_IN_DAI_ID}, .rtd_init = rt700_rtd_init, + .controls = rt700_controls, + .num_controls = ARRAY_SIZE(rt700_controls), + .widgets = rt700_widgets, + .num_widgets = ARRAY_SIZE(rt700_widgets), }, }, .dai_num = 1, @@ -697,6 +745,10 @@ static struct sof_sdw_codec_info codec_info_list[] = { .init = sof_sdw_rt_sdca_jack_init, .exit = sof_sdw_rt_sdca_jack_exit, .rtd_init = rt_sdca_jack_rtd_init, + .controls = generic_jack_controls, + .num_controls = ARRAY_SIZE(generic_jack_controls), + .widgets = generic_jack_widgets, + .num_widgets = ARRAY_SIZE(generic_jack_widgets), }, }, .dai_num = 1, @@ -713,6 +765,10 @@ static struct sof_sdw_codec_info codec_info_list[] = { .init = sof_sdw_rt711_init, .exit = sof_sdw_rt711_exit, .rtd_init = rt711_rtd_init, + .controls = generic_jack_controls, + .num_controls = ARRAY_SIZE(generic_jack_controls), + .widgets = generic_jack_widgets, + .num_widgets = ARRAY_SIZE(generic_jack_widgets), }, }, .dai_num = 1, @@ -729,6 +785,10 @@ static struct sof_sdw_codec_info codec_info_list[] = { .init = sof_sdw_rt_sdca_jack_init, .exit = sof_sdw_rt_sdca_jack_exit, .rtd_init = rt_sdca_jack_rtd_init, + .controls = generic_jack_controls, + .num_controls = ARRAY_SIZE(generic_jack_controls), + .widgets = generic_jack_widgets, + .num_widgets = ARRAY_SIZE(generic_jack_widgets), }, { .direction = {true, false}, @@ -738,6 +798,10 @@ static struct sof_sdw_codec_info codec_info_list[] = { .init = sof_sdw_rt_amp_init, .exit = sof_sdw_rt_amp_exit, .rtd_init = rt712_spk_rtd_init, + .controls = generic_spk_controls, + .num_controls = ARRAY_SIZE(generic_spk_controls), + .widgets = generic_spk_widgets, + .num_widgets = ARRAY_SIZE(generic_spk_widgets), }, }, .dai_num = 2, @@ -768,6 +832,10 @@ static struct sof_sdw_codec_info codec_info_list[] = { .init = sof_sdw_rt_sdca_jack_init, .exit = sof_sdw_rt_sdca_jack_exit, .rtd_init = rt_sdca_jack_rtd_init, + .controls = generic_jack_controls, + .num_controls = ARRAY_SIZE(generic_jack_controls), + .widgets = generic_jack_widgets, + .num_widgets = ARRAY_SIZE(generic_jack_widgets), }, }, .dai_num = 1, @@ -798,6 +866,10 @@ static struct sof_sdw_codec_info codec_info_list[] = { .init = sof_sdw_rt_amp_init, .exit = sof_sdw_rt_amp_exit, .rtd_init = rt_amp_spk_rtd_init, + .controls = generic_spk_controls, + .num_controls = ARRAY_SIZE(generic_spk_controls), + .widgets = generic_spk_widgets, + .num_widgets = ARRAY_SIZE(generic_spk_widgets), }, }, .dai_num = 1, @@ -814,6 +886,10 @@ static struct sof_sdw_codec_info codec_info_list[] = { .init = sof_sdw_rt_amp_init, .exit = sof_sdw_rt_amp_exit, .rtd_init = rt_amp_spk_rtd_init, + .controls = generic_spk_controls, + .num_controls = ARRAY_SIZE(generic_spk_controls), + .widgets = generic_spk_widgets, + .num_widgets = ARRAY_SIZE(generic_spk_widgets), }, }, .dai_num = 1, @@ -829,6 +905,10 @@ static struct sof_sdw_codec_info codec_info_list[] = { .init = sof_sdw_rt_amp_init, .exit = sof_sdw_rt_amp_exit, .rtd_init = rt_amp_spk_rtd_init, + .controls = generic_spk_controls, + .num_controls = ARRAY_SIZE(generic_spk_controls), + .widgets = generic_spk_widgets, + .num_widgets = ARRAY_SIZE(generic_spk_widgets), }, }, .dai_num = 1, @@ -905,6 +985,10 @@ static struct sof_sdw_codec_info codec_info_list[] = { .init = sof_sdw_rt_sdca_jack_init, .exit = sof_sdw_rt_sdca_jack_exit, .rtd_init = rt_sdca_jack_rtd_init, + .controls = generic_jack_controls, + .num_controls = ARRAY_SIZE(generic_jack_controls), + .widgets = generic_jack_widgets, + .num_widgets = ARRAY_SIZE(generic_jack_widgets), }, { .direction = {true, false}, @@ -915,6 +999,10 @@ static struct sof_sdw_codec_info codec_info_list[] = { .init = sof_sdw_rt_amp_init, .exit = sof_sdw_rt_amp_exit, .rtd_init = rt722_spk_rtd_init, + .controls = generic_spk_controls, + .num_controls = ARRAY_SIZE(generic_spk_controls), + .widgets = generic_spk_widgets, + .num_widgets = ARRAY_SIZE(generic_spk_widgets), }, { .direction = {false, true}, @@ -936,6 +1024,10 @@ static struct sof_sdw_codec_info codec_info_list[] = { .dailink = {SDW_AMP_OUT_DAI_ID, SDW_AMP_IN_DAI_ID}, .init = sof_sdw_maxim_init, .rtd_init = maxim_spk_rtd_init, + .controls = maxim_controls, + .num_controls = ARRAY_SIZE(maxim_controls), + .widgets = maxim_widgets, + .num_widgets = ARRAY_SIZE(maxim_widgets), }, }, .dai_num = 1, @@ -950,6 +1042,10 @@ static struct sof_sdw_codec_info codec_info_list[] = { .dailink = {SDW_AMP_OUT_DAI_ID, SDW_UNUSED_DAI_ID}, .init = sof_sdw_maxim_init, .rtd_init = maxim_spk_rtd_init, + .controls = maxim_controls, + .num_controls = ARRAY_SIZE(maxim_controls), + .widgets = maxim_widgets, + .num_widgets = ARRAY_SIZE(maxim_widgets), }, }, .dai_num = 1, @@ -963,6 +1059,10 @@ static struct sof_sdw_codec_info codec_info_list[] = { .dai_type = SOF_SDW_DAI_TYPE_JACK, .dailink = {SDW_JACK_OUT_DAI_ID, SDW_JACK_IN_DAI_ID}, .rtd_init = rt5682_rtd_init, + .controls = generic_jack_controls, + .num_controls = ARRAY_SIZE(generic_jack_controls), + .widgets = generic_jack_widgets, + .num_widgets = ARRAY_SIZE(generic_jack_widgets), }, }, .dai_num = 1, @@ -977,6 +1077,8 @@ static struct sof_sdw_codec_info codec_info_list[] = { .dailink = {SDW_AMP_OUT_DAI_ID, SDW_AMP_IN_DAI_ID}, .init = sof_sdw_cs_amp_init, .rtd_init = cs_spk_rtd_init, + .widgets = generic_spk_widgets, + .num_widgets = ARRAY_SIZE(generic_spk_widgets), }, }, .dai_num = 1, @@ -990,6 +1092,10 @@ static struct sof_sdw_codec_info codec_info_list[] = { .dai_type = SOF_SDW_DAI_TYPE_JACK, .dailink = {SDW_JACK_OUT_DAI_ID, SDW_JACK_IN_DAI_ID}, .rtd_init = cs42l42_rtd_init, + .controls = generic_jack_controls, + .num_controls = ARRAY_SIZE(generic_jack_controls), + .widgets = generic_jack_widgets, + .num_widgets = ARRAY_SIZE(generic_jack_widgets), }, }, .dai_num = 1, @@ -1006,6 +1112,8 @@ static struct sof_sdw_codec_info codec_info_list[] = { .dai_type = SOF_SDW_DAI_TYPE_JACK, .dailink = {SDW_JACK_OUT_DAI_ID, SDW_UNUSED_DAI_ID}, .rtd_init = cs42l43_hs_rtd_init, + .widgets = generic_jack_widgets, + .num_widgets = ARRAY_SIZE(generic_jack_widgets), }, { .direction = {false, true}, @@ -1013,6 +1121,8 @@ static struct sof_sdw_codec_info codec_info_list[] = { .dai_type = SOF_SDW_DAI_TYPE_MIC, .dailink = {SDW_UNUSED_DAI_ID, SDW_DMIC_DAI_ID}, .rtd_init = cs42l43_dmic_rtd_init, + .widgets = generic_dmic_widgets, + .num_widgets = ARRAY_SIZE(generic_dmic_widgets), }, { .direction = {false, true}, @@ -1027,6 +1137,8 @@ static struct sof_sdw_codec_info codec_info_list[] = { .dailink = {SDW_AMP_OUT_DAI_ID, SDW_UNUSED_DAI_ID}, .init = sof_sdw_cs42l43_spk_init, .rtd_init = cs42l43_spk_rtd_init, + .widgets = generic_spk_widgets, + .num_widgets = ARRAY_SIZE(generic_spk_widgets), .quirk = SOF_CODEC_SPKR | SOF_SIDECAR_AMPS, }, }, diff --git a/sound/soc/intel/boards/sof_sdw_cs42l42.c b/sound/soc/intel/boards/sof_sdw_cs42l42.c index 82555c53a9c9..9783d5fb2d91 100644 --- a/sound/soc/intel/boards/sof_sdw_cs42l42.c +++ b/sound/soc/intel/boards/sof_sdw_cs42l42.c @@ -17,11 +17,6 @@ #include #include "sof_sdw_common.h" -static const struct snd_soc_dapm_widget generic_jack_widgets[] = { - SND_SOC_DAPM_HP("Headphone", NULL), - SND_SOC_DAPM_MIC("Headset Mic", NULL), -}; - static const struct snd_soc_dapm_route cs42l42_map[] = { /* HP jack connectors - unknown if we have jack detection */ {"Headphone", NULL, "cs42l42 HP"}, @@ -30,11 +25,6 @@ static const struct snd_soc_dapm_route cs42l42_map[] = { {"cs42l42 HS", NULL, "Headset Mic"}, }; -static const struct snd_kcontrol_new generic_jack_controls[] = { - SOC_DAPM_PIN_SWITCH("Headphone"), - SOC_DAPM_PIN_SWITCH("Headset Mic"), -}; - static struct snd_soc_jack_pin cs42l42_jack_pins[] = { { .pin = "Headphone", @@ -70,20 +60,6 @@ int cs42l42_rtd_init(struct snd_soc_pcm_runtime *rtd) if (!card->components) return -ENOMEM; - ret = snd_soc_add_card_controls(card, generic_jack_controls, - ARRAY_SIZE(generic_jack_controls)); - if (ret) { - dev_err(card->dev, "cs42l42 control addition failed: %d\n", ret); - return ret; - } - - ret = snd_soc_dapm_new_controls(&card->dapm, generic_jack_widgets, - ARRAY_SIZE(generic_jack_widgets)); - if (ret) { - dev_err(card->dev, "cs42l42 widgets addition failed: %d\n", ret); - return ret; - } - ret = snd_soc_dapm_add_routes(&card->dapm, cs42l42_map, ARRAY_SIZE(cs42l42_map)); diff --git a/sound/soc/intel/boards/sof_sdw_cs42l43.c b/sound/soc/intel/boards/sof_sdw_cs42l43.c index f76a16795fda..2dd0f085fe60 100644 --- a/sound/soc/intel/boards/sof_sdw_cs42l43.c +++ b/sound/soc/intel/boards/sof_sdw_cs42l43.c @@ -18,11 +18,6 @@ #include #include "sof_sdw_common.h" -static const struct snd_soc_dapm_widget generic_jack_widgets[] = { - SND_SOC_DAPM_HP("Headphone", NULL), - SND_SOC_DAPM_MIC("Headset Mic", NULL), -}; - static const struct snd_soc_dapm_route cs42l43_hs_map[] = { { "Headphone", NULL, "cs42l43 AMP3_OUT" }, { "Headphone", NULL, "cs42l43 AMP4_OUT" }, @@ -30,10 +25,6 @@ static const struct snd_soc_dapm_route cs42l43_hs_map[] = { { "cs42l43 ADC1_IN1_N", NULL, "Headset Mic" }, }; -static const struct snd_soc_dapm_widget generic_spk_widgets[] = { - SND_SOC_DAPM_SPK("Speaker", NULL), -}; - static const struct snd_soc_dapm_route cs42l43_spk_map[] = { { "Speaker", NULL, "cs42l43 AMP1_OUT_P", }, { "Speaker", NULL, "cs42l43 AMP1_OUT_N", }, @@ -41,10 +32,6 @@ static const struct snd_soc_dapm_route cs42l43_spk_map[] = { { "Speaker", NULL, "cs42l43 AMP2_OUT_N", }, }; -static const struct snd_soc_dapm_widget generic_dmic_widgets[] = { - SND_SOC_DAPM_MIC("DMIC", NULL), -}; - static const struct snd_soc_dapm_route cs42l43_dmic_map[] = { { "cs42l43 PDM1_DIN", NULL, "DMIC" }, { "cs42l43 PDM2_DIN", NULL, "DMIC" }, @@ -74,13 +61,6 @@ int cs42l43_hs_rtd_init(struct snd_soc_pcm_runtime *rtd) if (!card->components) return -ENOMEM; - ret = snd_soc_dapm_new_controls(&card->dapm, generic_jack_widgets, - ARRAY_SIZE(generic_jack_widgets)); - if (ret) { - dev_err(card->dev, "cs42l43 hs widgets addition failed: %d\n", ret); - return ret; - } - ret = snd_soc_dapm_add_routes(&card->dapm, cs42l43_hs_map, ARRAY_SIZE(cs42l43_hs_map)); if (ret) { @@ -133,13 +113,6 @@ int cs42l43_spk_rtd_init(struct snd_soc_pcm_runtime *rtd) return -ENOMEM; } - ret = snd_soc_dapm_new_controls(&card->dapm, generic_spk_widgets, - ARRAY_SIZE(generic_spk_widgets)); - if (ret) { - dev_err(card->dev, "cs42l43 speaker widgets addition failed: %d\n", ret); - return ret; - } - ret = snd_soc_dapm_add_routes(&card->dapm, cs42l43_spk_map, ARRAY_SIZE(cs42l43_spk_map)); if (ret) @@ -172,13 +145,6 @@ int cs42l43_dmic_rtd_init(struct snd_soc_pcm_runtime *rtd) if (!card->components) return -ENOMEM; - ret = snd_soc_dapm_new_controls(&card->dapm, generic_dmic_widgets, - ARRAY_SIZE(generic_dmic_widgets)); - if (ret) { - dev_err(card->dev, "cs42l43 dmic widgets addition failed: %d\n", ret); - return ret; - } - ret = snd_soc_dapm_add_routes(&card->dapm, cs42l43_dmic_map, ARRAY_SIZE(cs42l43_dmic_map)); if (ret) diff --git a/sound/soc/intel/boards/sof_sdw_cs_amp.c b/sound/soc/intel/boards/sof_sdw_cs_amp.c index e15a4753f103..663c0e1d2c56 100644 --- a/sound/soc/intel/boards/sof_sdw_cs_amp.c +++ b/sound/soc/intel/boards/sof_sdw_cs_amp.c @@ -14,10 +14,6 @@ #define CODEC_NAME_SIZE 8 -static const struct snd_soc_dapm_widget generic_spk_widgets[] = { - SND_SOC_DAPM_SPK("Speaker", NULL), -}; - int cs_spk_rtd_init(struct snd_soc_pcm_runtime *rtd) { const char *dai_name = rtd->dai_link->codecs->dai_name; @@ -35,13 +31,6 @@ int cs_spk_rtd_init(struct snd_soc_pcm_runtime *rtd) if (!card->components) return -ENOMEM; - ret = snd_soc_dapm_new_controls(&card->dapm, generic_spk_widgets, - ARRAY_SIZE(generic_spk_widgets)); - if (ret) { - dev_err(card->dev, "widgets addition failed: %d\n", ret); - return ret; - } - for_each_rtd_codec_dais(rtd, i, codec_dai) { if (!strstr(codec_dai->name, "cs35l56")) continue; diff --git a/sound/soc/intel/boards/sof_sdw_maxim.c b/sound/soc/intel/boards/sof_sdw_maxim.c index 57c1a5fb17a9..a7a8db624818 100644 --- a/sound/soc/intel/boards/sof_sdw_maxim.c +++ b/sound/soc/intel/boards/sof_sdw_maxim.c @@ -16,16 +16,6 @@ static int maxim_part_id; #define SOF_SDW_PART_ID_MAX98363 0x8363 #define SOF_SDW_PART_ID_MAX98373 0x8373 -static const struct snd_soc_dapm_widget maxim_widgets[] = { - SND_SOC_DAPM_SPK("Left Spk", NULL), - SND_SOC_DAPM_SPK("Right Spk", NULL), -}; - -static const struct snd_kcontrol_new maxim_controls[] = { - SOC_DAPM_PIN_SWITCH("Left Spk"), - SOC_DAPM_PIN_SWITCH("Right Spk"), -}; - static const struct snd_soc_dapm_route max_98373_dapm_routes[] = { { "Left Spk", NULL, "Left BE_OUT" }, { "Right Spk", NULL, "Right BE_OUT" }, @@ -45,20 +35,6 @@ int maxim_spk_rtd_init(struct snd_soc_pcm_runtime *rtd) dev_dbg(card->dev, "soundwire maxim card components assigned : %s\n", card->components); - ret = snd_soc_add_card_controls(card, maxim_controls, - ARRAY_SIZE(maxim_controls)); - if (ret) { - dev_err(card->dev, "mx%04x ctrls addition failed: %d\n", maxim_part_id, ret); - return ret; - } - - ret = snd_soc_dapm_new_controls(&card->dapm, maxim_widgets, - ARRAY_SIZE(maxim_widgets)); - if (ret) { - dev_err(card->dev, "mx%04x widgets addition failed: %d\n", maxim_part_id, ret); - return ret; - } - ret = snd_soc_dapm_add_routes(&card->dapm, max_98373_dapm_routes, 2); if (ret) dev_err(rtd->dev, "failed to add first SPK map: %d\n", ret); diff --git a/sound/soc/intel/boards/sof_sdw_rt5682.c b/sound/soc/intel/boards/sof_sdw_rt5682.c index 9fbe36322a83..1741226fe052 100644 --- a/sound/soc/intel/boards/sof_sdw_rt5682.c +++ b/sound/soc/intel/boards/sof_sdw_rt5682.c @@ -17,11 +17,6 @@ #include #include "sof_sdw_common.h" -static const struct snd_soc_dapm_widget generic_jack_widgets[] = { - SND_SOC_DAPM_HP("Headphone", NULL), - SND_SOC_DAPM_MIC("Headset Mic", NULL), -}; - static const struct snd_soc_dapm_route rt5682_map[] = { /*Headphones*/ { "Headphone", NULL, "rt5682 HPOL" }, @@ -29,11 +24,6 @@ static const struct snd_soc_dapm_route rt5682_map[] = { { "rt5682 IN1P", NULL, "Headset Mic" }, }; -static const struct snd_kcontrol_new generic_jack_controls[] = { - SOC_DAPM_PIN_SWITCH("Headphone"), - SOC_DAPM_PIN_SWITCH("Headset Mic"), -}; - static struct snd_soc_jack_pin rt5682_jack_pins[] = { { .pin = "Headphone", @@ -69,20 +59,6 @@ int rt5682_rtd_init(struct snd_soc_pcm_runtime *rtd) if (!card->components) return -ENOMEM; - ret = snd_soc_add_card_controls(card, generic_jack_controls, - ARRAY_SIZE(generic_jack_controls)); - if (ret) { - dev_err(card->dev, "rt5682 control addition failed: %d\n", ret); - return ret; - } - - ret = snd_soc_dapm_new_controls(&card->dapm, generic_jack_widgets, - ARRAY_SIZE(generic_jack_widgets)); - if (ret) { - dev_err(card->dev, "rt5682 widgets addition failed: %d\n", ret); - return ret; - } - ret = snd_soc_dapm_add_routes(&card->dapm, rt5682_map, ARRAY_SIZE(rt5682_map)); diff --git a/sound/soc/intel/boards/sof_sdw_rt700.c b/sound/soc/intel/boards/sof_sdw_rt700.c index a2648c900e74..58677a8968ab 100644 --- a/sound/soc/intel/boards/sof_sdw_rt700.c +++ b/sound/soc/intel/boards/sof_sdw_rt700.c @@ -15,12 +15,6 @@ #include #include "sof_sdw_common.h" -static const struct snd_soc_dapm_widget rt700_widgets[] = { - SND_SOC_DAPM_HP("Headphones", NULL), - SND_SOC_DAPM_MIC("AMIC", NULL), - SND_SOC_DAPM_SPK("Speaker", NULL), -}; - static const struct snd_soc_dapm_route rt700_map[] = { /* Headphones */ { "Headphones", NULL, "rt700 HP" }, @@ -28,12 +22,6 @@ static const struct snd_soc_dapm_route rt700_map[] = { { "rt700 MIC2", NULL, "AMIC" }, }; -static const struct snd_kcontrol_new rt700_controls[] = { - SOC_DAPM_PIN_SWITCH("Headphones"), - SOC_DAPM_PIN_SWITCH("AMIC"), - SOC_DAPM_PIN_SWITCH("Speaker"), -}; - static struct snd_soc_jack_pin rt700_jack_pins[] = { { .pin = "Headphones", @@ -69,20 +57,6 @@ int rt700_rtd_init(struct snd_soc_pcm_runtime *rtd) if (!card->components) return -ENOMEM; - ret = snd_soc_add_card_controls(card, rt700_controls, - ARRAY_SIZE(rt700_controls)); - if (ret) { - dev_err(card->dev, "rt700 controls addition failed: %d\n", ret); - return ret; - } - - ret = snd_soc_dapm_new_controls(&card->dapm, rt700_widgets, - ARRAY_SIZE(rt700_widgets)); - if (ret) { - dev_err(card->dev, "rt700 widgets addition failed: %d\n", ret); - return ret; - } - ret = snd_soc_dapm_add_routes(&card->dapm, rt700_map, ARRAY_SIZE(rt700_map)); diff --git a/sound/soc/intel/boards/sof_sdw_rt711.c b/sound/soc/intel/boards/sof_sdw_rt711.c index 1a0f6692034a..4cff48a37e3c 100644 --- a/sound/soc/intel/boards/sof_sdw_rt711.c +++ b/sound/soc/intel/boards/sof_sdw_rt711.c @@ -42,22 +42,12 @@ static int rt711_add_codec_device_props(struct device *sdw_dev) return ret; } -static const struct snd_soc_dapm_widget generic_jack_widgets[] = { - SND_SOC_DAPM_HP("Headphone", NULL), - SND_SOC_DAPM_MIC("Headset Mic", NULL), -}; - static const struct snd_soc_dapm_route rt711_map[] = { /* Headphones */ { "Headphone", NULL, "rt711 HP" }, { "rt711 MIC2", NULL, "Headset Mic" }, }; -static const struct snd_kcontrol_new generic_jack_controls[] = { - SOC_DAPM_PIN_SWITCH("Headphone"), - SOC_DAPM_PIN_SWITCH("Headset Mic"), -}; - static struct snd_soc_jack_pin rt711_jack_pins[] = { { .pin = "Headphone", @@ -93,20 +83,6 @@ int rt711_rtd_init(struct snd_soc_pcm_runtime *rtd) if (!card->components) return -ENOMEM; - ret = snd_soc_add_card_controls(card, generic_jack_controls, - ARRAY_SIZE(generic_jack_controls)); - if (ret) { - dev_err(card->dev, "rt711 controls addition failed: %d\n", ret); - return ret; - } - - ret = snd_soc_dapm_new_controls(&card->dapm, generic_jack_widgets, - ARRAY_SIZE(generic_jack_widgets)); - if (ret) { - dev_err(card->dev, "rt711 widgets addition failed: %d\n", ret); - return ret; - } - ret = snd_soc_dapm_add_routes(&card->dapm, rt711_map, ARRAY_SIZE(rt711_map)); diff --git a/sound/soc/intel/boards/sof_sdw_rt712_sdca.c b/sound/soc/intel/boards/sof_sdw_rt712_sdca.c index 42308228c634..ee2c57a50f0d 100644 --- a/sound/soc/intel/boards/sof_sdw_rt712_sdca.c +++ b/sound/soc/intel/boards/sof_sdw_rt712_sdca.c @@ -15,10 +15,6 @@ #include #include "sof_sdw_common.h" -static const struct snd_soc_dapm_widget generic_spk_widgets[] = { - SND_SOC_DAPM_SPK("Speaker", NULL), -}; - /* * dapm routes for rt712 spk will be registered dynamically according * to the number of rt712 spk used. The first two entries will be registered @@ -30,10 +26,6 @@ static const struct snd_soc_dapm_route rt712_spk_map[] = { { "Speaker", NULL, "rt712 SPOR" }, }; -static const struct snd_kcontrol_new generic_spk_controls[] = { - SOC_DAPM_PIN_SWITCH("Speaker"), -}; - int rt712_spk_rtd_init(struct snd_soc_pcm_runtime *rtd) { struct snd_soc_card *card = rtd->card; @@ -45,20 +37,6 @@ int rt712_spk_rtd_init(struct snd_soc_pcm_runtime *rtd) if (!card->components) return -ENOMEM; - ret = snd_soc_add_card_controls(card, generic_spk_controls, - ARRAY_SIZE(generic_spk_controls)); - if (ret) { - dev_err(card->dev, "rt712 spk controls addition failed: %d\n", ret); - return ret; - } - - ret = snd_soc_dapm_new_controls(&card->dapm, generic_spk_widgets, - ARRAY_SIZE(generic_spk_widgets)); - if (ret) { - dev_err(card->dev, "rt712 spk widgets addition failed: %d\n", ret); - return ret; - } - ret = snd_soc_dapm_add_routes(&card->dapm, rt712_spk_map, ARRAY_SIZE(rt712_spk_map)); if (ret) dev_err(rtd->dev, "failed to add SPK map: %d\n", ret); diff --git a/sound/soc/intel/boards/sof_sdw_rt722_sdca.c b/sound/soc/intel/boards/sof_sdw_rt722_sdca.c index 1653e45a0f7d..02ee8e33a99a 100644 --- a/sound/soc/intel/boards/sof_sdw_rt722_sdca.c +++ b/sound/soc/intel/boards/sof_sdw_rt722_sdca.c @@ -15,18 +15,10 @@ #include #include "sof_sdw_common.h" -static const struct snd_soc_dapm_widget generic_spk_widgets[] = { - SND_SOC_DAPM_SPK("Speaker", NULL), -}; - static const struct snd_soc_dapm_route rt722_spk_map[] = { { "Speaker", NULL, "rt722 SPK" }, }; -static const struct snd_kcontrol_new generic_spk_controls[] = { - SOC_DAPM_PIN_SWITCH("Speaker"), -}; - int rt722_spk_rtd_init(struct snd_soc_pcm_runtime *rtd) { struct snd_soc_card *card = rtd->card; @@ -38,20 +30,6 @@ int rt722_spk_rtd_init(struct snd_soc_pcm_runtime *rtd) if (!card->components) return -ENOMEM; - ret = snd_soc_add_card_controls(card, generic_spk_controls, - ARRAY_SIZE(generic_spk_controls)); - if (ret) { - dev_err(card->dev, "failed to add rt722 spk controls: %d\n", ret); - return ret; - } - - ret = snd_soc_dapm_new_controls(&card->dapm, generic_spk_widgets, - ARRAY_SIZE(generic_spk_widgets)); - if (ret) { - dev_err(card->dev, "failed to add rt722 spk widgets: %d\n", ret); - return ret; - } - ret = snd_soc_dapm_add_routes(&card->dapm, rt722_spk_map, ARRAY_SIZE(rt722_spk_map)); if (ret) dev_err(rtd->dev, "failed to add rt722 spk map: %d\n", ret); diff --git a/sound/soc/intel/boards/sof_sdw_rt_amp.c b/sound/soc/intel/boards/sof_sdw_rt_amp.c index 03e0978e6a88..218f6c4efe38 100644 --- a/sound/soc/intel/boards/sof_sdw_rt_amp.c +++ b/sound/soc/intel/boards/sof_sdw_rt_amp.c @@ -131,14 +131,6 @@ static int rt_amp_add_device_props(struct device *sdw_dev) return ret; } -static const struct snd_soc_dapm_widget generic_spk_widgets[] = { - SND_SOC_DAPM_SPK("Speaker", NULL), -}; - -static const struct snd_kcontrol_new generic_spk_controls[] = { - SOC_DAPM_PIN_SWITCH("Speaker"), -}; - /* * dapm routes for rt1308/rt1316/rt1318 will be registered dynamically * according to the number of rt1308/rt1316/rt1318 used. The first two @@ -202,20 +194,6 @@ int rt_amp_spk_rtd_init(struct snd_soc_pcm_runtime *rtd) if (!card->components) return -ENOMEM; - ret = snd_soc_add_card_controls(card, generic_spk_controls, - ARRAY_SIZE(generic_spk_controls)); - if (ret) { - dev_err(card->dev, "%s controls addition failed: %d\n", codec_name, ret); - return ret; - } - - ret = snd_soc_dapm_new_controls(&card->dapm, generic_spk_widgets, - ARRAY_SIZE(generic_spk_widgets)); - if (ret) { - dev_err(card->dev, "%s widgets addition failed: %d\n", codec_name, ret); - return ret; - } - for_each_rtd_codec_dais(rtd, i, dai) { if (strstr(dai->component->name_prefix, "-1")) ret = snd_soc_dapm_add_routes(&card->dapm, rt_amp_map, 2); diff --git a/sound/soc/intel/boards/sof_sdw_rt_sdca_jack_common.c b/sound/soc/intel/boards/sof_sdw_rt_sdca_jack_common.c index 932fba8ccf9a..c24a5707fb6c 100644 --- a/sound/soc/intel/boards/sof_sdw_rt_sdca_jack_common.c +++ b/sound/soc/intel/boards/sof_sdw_rt_sdca_jack_common.c @@ -43,11 +43,6 @@ static int rt_sdca_jack_add_codec_device_props(struct device *sdw_dev) return ret; } -static const struct snd_soc_dapm_widget generic_jack_widgets[] = { - SND_SOC_DAPM_HP("Headphone", NULL), - SND_SOC_DAPM_MIC("Headset Mic", NULL), -}; - static const struct snd_soc_dapm_route rt711_sdca_map[] = { { "Headphone", NULL, "rt711 HP" }, { "rt711 MIC2", NULL, "Headset Mic" }, @@ -68,11 +63,6 @@ static const struct snd_soc_dapm_route rt722_sdca_map[] = { { "rt722 MIC2", NULL, "Headset Mic" }, }; -static const struct snd_kcontrol_new generic_jack_controls[] = { - SOC_DAPM_PIN_SWITCH("Headphone"), - SOC_DAPM_PIN_SWITCH("Headset Mic"), -}; - static struct snd_soc_jack_pin rt_sdca_jack_pins[] = { { .pin = "Headphone", @@ -129,20 +119,6 @@ int rt_sdca_jack_rtd_init(struct snd_soc_pcm_runtime *rtd) } } - ret = snd_soc_add_card_controls(card, generic_jack_controls, - ARRAY_SIZE(generic_jack_controls)); - if (ret) { - dev_err(card->dev, "rt sdca jack controls addition failed: %d\n", ret); - return ret; - } - - ret = snd_soc_dapm_new_controls(&card->dapm, generic_jack_widgets, - ARRAY_SIZE(generic_jack_widgets)); - if (ret) { - dev_err(card->dev, "rt sdca jack widgets addition failed: %d\n", ret); - return ret; - } - if (strstr(component->name_prefix, "rt711")) { ret = snd_soc_dapm_add_routes(&card->dapm, rt711_sdca_map, ARRAY_SIZE(rt711_sdca_map)); -- cgit v1.2.3 From 84e0a19adb73d7cec5a43e02f9e2d2aafc5c7176 Mon Sep 17 00:00:00 2001 From: Bard Liao Date: Thu, 9 May 2024 11:34:17 -0500 Subject: ASoC: Intel: sof_sdw: add dai parameter to rtd_init callback MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit A generic .rtd_init() callback could be used by different dais. It is useful to pass dai parameter to the callback. The dai parameter will be used in the follow up commit. No functional change here. Reviewed-by: Péter Ujfalusi Signed-off-by: Bard Liao Signed-off-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20240509163418.67746-18-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/intel/boards/sof_sdw.c | 2 +- sound/soc/intel/boards/sof_sdw_common.h | 30 +++++++++++----------- sound/soc/intel/boards/sof_sdw_cs42l42.c | 2 +- sound/soc/intel/boards/sof_sdw_cs42l43.c | 6 ++--- sound/soc/intel/boards/sof_sdw_cs_amp.c | 2 +- sound/soc/intel/boards/sof_sdw_maxim.c | 2 +- sound/soc/intel/boards/sof_sdw_rt5682.c | 2 +- sound/soc/intel/boards/sof_sdw_rt700.c | 2 +- sound/soc/intel/boards/sof_sdw_rt711.c | 2 +- sound/soc/intel/boards/sof_sdw_rt712_sdca.c | 2 +- sound/soc/intel/boards/sof_sdw_rt722_sdca.c | 2 +- sound/soc/intel/boards/sof_sdw_rt_amp.c | 10 ++++---- sound/soc/intel/boards/sof_sdw_rt_dmic.c | 2 +- .../soc/intel/boards/sof_sdw_rt_sdca_jack_common.c | 2 +- 14 files changed, 34 insertions(+), 34 deletions(-) diff --git a/sound/soc/intel/boards/sof_sdw.c b/sound/soc/intel/boards/sof_sdw.c index 8c1497bab2ef..e41b0d95e0ff 100644 --- a/sound/soc/intel/boards/sof_sdw.c +++ b/sound/soc/intel/boards/sof_sdw.c @@ -1411,7 +1411,7 @@ static int sof_sdw_rtd_init(struct snd_soc_pcm_runtime *rtd) skip_add_controls_widgets: if (codec_info->dais[dai_index].rtd_init) { - ret = codec_info->dais[dai_index].rtd_init(rtd); + ret = codec_info->dais[dai_index].rtd_init(rtd, dai); if (ret) return ret; } diff --git a/sound/soc/intel/boards/sof_sdw_common.h b/sound/soc/intel/boards/sof_sdw_common.h index a8ba39bd5fd8..3dfba6f6b95d 100644 --- a/sound/soc/intel/boards/sof_sdw_common.h +++ b/sound/soc/intel/boards/sof_sdw_common.h @@ -95,7 +95,7 @@ struct sof_sdw_dai_info { struct sof_sdw_codec_info *info, bool playback); int (*exit)(struct snd_soc_card *card, struct snd_soc_dai_link *dai_link); - int (*rtd_init)(struct snd_soc_pcm_runtime *rtd); + int (*rtd_init)(struct snd_soc_pcm_runtime *rtd, struct snd_soc_dai *dai); bool rtd_init_done; /* Indicate that the rtd_init callback is done */ unsigned long quirk; }; @@ -208,19 +208,19 @@ int sof_sdw_cs_amp_init(struct snd_soc_card *card, /* dai_link init callbacks */ -int cs42l42_rtd_init(struct snd_soc_pcm_runtime *rtd); -int cs42l43_hs_rtd_init(struct snd_soc_pcm_runtime *rtd); -int cs42l43_spk_rtd_init(struct snd_soc_pcm_runtime *rtd); -int cs42l43_dmic_rtd_init(struct snd_soc_pcm_runtime *rtd); -int cs_spk_rtd_init(struct snd_soc_pcm_runtime *rtd); -int maxim_spk_rtd_init(struct snd_soc_pcm_runtime *rtd); -int rt5682_rtd_init(struct snd_soc_pcm_runtime *rtd); -int rt700_rtd_init(struct snd_soc_pcm_runtime *rtd); -int rt711_rtd_init(struct snd_soc_pcm_runtime *rtd); -int rt712_spk_rtd_init(struct snd_soc_pcm_runtime *rtd); -int rt722_spk_rtd_init(struct snd_soc_pcm_runtime *rtd); -int rt_dmic_rtd_init(struct snd_soc_pcm_runtime *rtd); -int rt_amp_spk_rtd_init(struct snd_soc_pcm_runtime *rtd); -int rt_sdca_jack_rtd_init(struct snd_soc_pcm_runtime *rtd); +int cs42l42_rtd_init(struct snd_soc_pcm_runtime *rtd, struct snd_soc_dai *dai); +int cs42l43_hs_rtd_init(struct snd_soc_pcm_runtime *rtd, struct snd_soc_dai *dai); +int cs42l43_spk_rtd_init(struct snd_soc_pcm_runtime *rtd, struct snd_soc_dai *dai); +int cs42l43_dmic_rtd_init(struct snd_soc_pcm_runtime *rtd, struct snd_soc_dai *dai); +int cs_spk_rtd_init(struct snd_soc_pcm_runtime *rtd, struct snd_soc_dai *dai); +int maxim_spk_rtd_init(struct snd_soc_pcm_runtime *rtd, struct snd_soc_dai *dai); +int rt5682_rtd_init(struct snd_soc_pcm_runtime *rtd, struct snd_soc_dai *dai); +int rt700_rtd_init(struct snd_soc_pcm_runtime *rtd, struct snd_soc_dai *dai); +int rt711_rtd_init(struct snd_soc_pcm_runtime *rtd, struct snd_soc_dai *dai); +int rt712_spk_rtd_init(struct snd_soc_pcm_runtime *rtd, struct snd_soc_dai *dai); +int rt722_spk_rtd_init(struct snd_soc_pcm_runtime *rtd, struct snd_soc_dai *dai); +int rt_dmic_rtd_init(struct snd_soc_pcm_runtime *rtd, struct snd_soc_dai *dai); +int rt_amp_spk_rtd_init(struct snd_soc_pcm_runtime *rtd, struct snd_soc_dai *dai); +int rt_sdca_jack_rtd_init(struct snd_soc_pcm_runtime *rtd, struct snd_soc_dai *dai); #endif diff --git a/sound/soc/intel/boards/sof_sdw_cs42l42.c b/sound/soc/intel/boards/sof_sdw_cs42l42.c index 9783d5fb2d91..fdb75fc71c26 100644 --- a/sound/soc/intel/boards/sof_sdw_cs42l42.c +++ b/sound/soc/intel/boards/sof_sdw_cs42l42.c @@ -40,7 +40,7 @@ static const char * const jack_codecs[] = { "cs42l42" }; -int cs42l42_rtd_init(struct snd_soc_pcm_runtime *rtd) +int cs42l42_rtd_init(struct snd_soc_pcm_runtime *rtd, struct snd_soc_dai *dai) { struct snd_soc_card *card = rtd->card; struct mc_private *ctx = snd_soc_card_get_drvdata(card); diff --git a/sound/soc/intel/boards/sof_sdw_cs42l43.c b/sound/soc/intel/boards/sof_sdw_cs42l43.c index 2dd0f085fe60..b7e2750c1074 100644 --- a/sound/soc/intel/boards/sof_sdw_cs42l43.c +++ b/sound/soc/intel/boards/sof_sdw_cs42l43.c @@ -48,7 +48,7 @@ static struct snd_soc_jack_pin sof_jack_pins[] = { }, }; -int cs42l43_hs_rtd_init(struct snd_soc_pcm_runtime *rtd) +int cs42l43_hs_rtd_init(struct snd_soc_pcm_runtime *rtd, struct snd_soc_dai *dai) { struct snd_soc_component *component = snd_soc_rtd_to_codec(rtd, 0)->component; struct mc_private *ctx = snd_soc_card_get_drvdata(rtd->card); @@ -99,7 +99,7 @@ int cs42l43_hs_rtd_init(struct snd_soc_pcm_runtime *rtd) return ret; } -int cs42l43_spk_rtd_init(struct snd_soc_pcm_runtime *rtd) +int cs42l43_spk_rtd_init(struct snd_soc_pcm_runtime *rtd, struct snd_soc_dai *dai) { struct snd_soc_card *card = rtd->card; int ret; @@ -135,7 +135,7 @@ int sof_sdw_cs42l43_spk_init(struct snd_soc_card *card, return bridge_cs35l56_spk_init(card, dai_links, info, playback); } -int cs42l43_dmic_rtd_init(struct snd_soc_pcm_runtime *rtd) +int cs42l43_dmic_rtd_init(struct snd_soc_pcm_runtime *rtd, struct snd_soc_dai *dai) { struct snd_soc_card *card = rtd->card; int ret; diff --git a/sound/soc/intel/boards/sof_sdw_cs_amp.c b/sound/soc/intel/boards/sof_sdw_cs_amp.c index 663c0e1d2c56..10e08207619a 100644 --- a/sound/soc/intel/boards/sof_sdw_cs_amp.c +++ b/sound/soc/intel/boards/sof_sdw_cs_amp.c @@ -14,7 +14,7 @@ #define CODEC_NAME_SIZE 8 -int cs_spk_rtd_init(struct snd_soc_pcm_runtime *rtd) +int cs_spk_rtd_init(struct snd_soc_pcm_runtime *rtd, struct snd_soc_dai *dai) { const char *dai_name = rtd->dai_link->codecs->dai_name; struct snd_soc_card *card = rtd->card; diff --git a/sound/soc/intel/boards/sof_sdw_maxim.c b/sound/soc/intel/boards/sof_sdw_maxim.c index a7a8db624818..b7f73177867f 100644 --- a/sound/soc/intel/boards/sof_sdw_maxim.c +++ b/sound/soc/intel/boards/sof_sdw_maxim.c @@ -21,7 +21,7 @@ static const struct snd_soc_dapm_route max_98373_dapm_routes[] = { { "Right Spk", NULL, "Right BE_OUT" }, }; -int maxim_spk_rtd_init(struct snd_soc_pcm_runtime *rtd) +int maxim_spk_rtd_init(struct snd_soc_pcm_runtime *rtd, struct snd_soc_dai *dai) { struct snd_soc_card *card = rtd->card; int ret; diff --git a/sound/soc/intel/boards/sof_sdw_rt5682.c b/sound/soc/intel/boards/sof_sdw_rt5682.c index 1741226fe052..96f193798540 100644 --- a/sound/soc/intel/boards/sof_sdw_rt5682.c +++ b/sound/soc/intel/boards/sof_sdw_rt5682.c @@ -39,7 +39,7 @@ static const char * const jack_codecs[] = { "rt5682" }; -int rt5682_rtd_init(struct snd_soc_pcm_runtime *rtd) +int rt5682_rtd_init(struct snd_soc_pcm_runtime *rtd, struct snd_soc_dai *dai) { struct snd_soc_card *card = rtd->card; struct mc_private *ctx = snd_soc_card_get_drvdata(card); diff --git a/sound/soc/intel/boards/sof_sdw_rt700.c b/sound/soc/intel/boards/sof_sdw_rt700.c index 58677a8968ab..f9575db9d99c 100644 --- a/sound/soc/intel/boards/sof_sdw_rt700.c +++ b/sound/soc/intel/boards/sof_sdw_rt700.c @@ -37,7 +37,7 @@ static const char * const jack_codecs[] = { "rt700" }; -int rt700_rtd_init(struct snd_soc_pcm_runtime *rtd) +int rt700_rtd_init(struct snd_soc_pcm_runtime *rtd, struct snd_soc_dai *dai) { struct snd_soc_card *card = rtd->card; struct mc_private *ctx = snd_soc_card_get_drvdata(card); diff --git a/sound/soc/intel/boards/sof_sdw_rt711.c b/sound/soc/intel/boards/sof_sdw_rt711.c index 4cff48a37e3c..d49e5aa786c3 100644 --- a/sound/soc/intel/boards/sof_sdw_rt711.c +++ b/sound/soc/intel/boards/sof_sdw_rt711.c @@ -63,7 +63,7 @@ static const char * const jack_codecs[] = { "rt711" }; -int rt711_rtd_init(struct snd_soc_pcm_runtime *rtd) +int rt711_rtd_init(struct snd_soc_pcm_runtime *rtd, struct snd_soc_dai *dai) { struct snd_soc_card *card = rtd->card; struct mc_private *ctx = snd_soc_card_get_drvdata(card); diff --git a/sound/soc/intel/boards/sof_sdw_rt712_sdca.c b/sound/soc/intel/boards/sof_sdw_rt712_sdca.c index ee2c57a50f0d..788796461885 100644 --- a/sound/soc/intel/boards/sof_sdw_rt712_sdca.c +++ b/sound/soc/intel/boards/sof_sdw_rt712_sdca.c @@ -26,7 +26,7 @@ static const struct snd_soc_dapm_route rt712_spk_map[] = { { "Speaker", NULL, "rt712 SPOR" }, }; -int rt712_spk_rtd_init(struct snd_soc_pcm_runtime *rtd) +int rt712_spk_rtd_init(struct snd_soc_pcm_runtime *rtd, struct snd_soc_dai *dai) { struct snd_soc_card *card = rtd->card; int ret; diff --git a/sound/soc/intel/boards/sof_sdw_rt722_sdca.c b/sound/soc/intel/boards/sof_sdw_rt722_sdca.c index 02ee8e33a99a..083d281bd052 100644 --- a/sound/soc/intel/boards/sof_sdw_rt722_sdca.c +++ b/sound/soc/intel/boards/sof_sdw_rt722_sdca.c @@ -19,7 +19,7 @@ static const struct snd_soc_dapm_route rt722_spk_map[] = { { "Speaker", NULL, "rt722 SPK" }, }; -int rt722_spk_rtd_init(struct snd_soc_pcm_runtime *rtd) +int rt722_spk_rtd_init(struct snd_soc_pcm_runtime *rtd, struct snd_soc_dai *dai) { struct snd_soc_card *card = rtd->card; int ret; diff --git a/sound/soc/intel/boards/sof_sdw_rt_amp.c b/sound/soc/intel/boards/sof_sdw_rt_amp.c index 218f6c4efe38..df03441ab364 100644 --- a/sound/soc/intel/boards/sof_sdw_rt_amp.c +++ b/sound/soc/intel/boards/sof_sdw_rt_amp.c @@ -177,12 +177,12 @@ static const struct snd_soc_dapm_route *get_codec_name_and_route(struct snd_soc_ return rt1318_map; } -int rt_amp_spk_rtd_init(struct snd_soc_pcm_runtime *rtd) +int rt_amp_spk_rtd_init(struct snd_soc_pcm_runtime *rtd, struct snd_soc_dai *dai) { struct snd_soc_card *card = rtd->card; const struct snd_soc_dapm_route *rt_amp_map; char codec_name[CODEC_NAME_SIZE]; - struct snd_soc_dai *dai; + struct snd_soc_dai *codec_dai; int ret; int i; @@ -194,10 +194,10 @@ int rt_amp_spk_rtd_init(struct snd_soc_pcm_runtime *rtd) if (!card->components) return -ENOMEM; - for_each_rtd_codec_dais(rtd, i, dai) { - if (strstr(dai->component->name_prefix, "-1")) + for_each_rtd_codec_dais(rtd, i, codec_dai) { + if (strstr(codec_dai->component->name_prefix, "-1")) ret = snd_soc_dapm_add_routes(&card->dapm, rt_amp_map, 2); - else if (strstr(dai->component->name_prefix, "-2")) + else if (strstr(codec_dai->component->name_prefix, "-2")) ret = snd_soc_dapm_add_routes(&card->dapm, rt_amp_map + 2, 2); } diff --git a/sound/soc/intel/boards/sof_sdw_rt_dmic.c b/sound/soc/intel/boards/sof_sdw_rt_dmic.c index 2f7ed9b31e79..b8b493d5c6ec 100644 --- a/sound/soc/intel/boards/sof_sdw_rt_dmic.c +++ b/sound/soc/intel/boards/sof_sdw_rt_dmic.c @@ -19,7 +19,7 @@ static const char * const dmics[] = { "rt722-sdca", }; -int rt_dmic_rtd_init(struct snd_soc_pcm_runtime *rtd) +int rt_dmic_rtd_init(struct snd_soc_pcm_runtime *rtd, struct snd_soc_dai *dai) { struct snd_soc_card *card = rtd->card; struct snd_soc_component *component; diff --git a/sound/soc/intel/boards/sof_sdw_rt_sdca_jack_common.c b/sound/soc/intel/boards/sof_sdw_rt_sdca_jack_common.c index c24a5707fb6c..701b0372f59e 100644 --- a/sound/soc/intel/boards/sof_sdw_rt_sdca_jack_common.c +++ b/sound/soc/intel/boards/sof_sdw_rt_sdca_jack_common.c @@ -87,7 +87,7 @@ static const char * const need_sdca_suffix[] = { "rt711", "rt713" }; -int rt_sdca_jack_rtd_init(struct snd_soc_pcm_runtime *rtd) +int rt_sdca_jack_rtd_init(struct snd_soc_pcm_runtime *rtd, struct snd_soc_dai *dai) { struct snd_soc_card *card = rtd->card; struct mc_private *ctx = snd_soc_card_get_drvdata(card); -- cgit v1.2.3 From 4c11132a886ea93865e205e2d92d810722237b48 Mon Sep 17 00:00:00 2001 From: Bard Liao Date: Thu, 9 May 2024 11:34:18 -0500 Subject: ASoC: Intel: sof_sdw_rt_amp: use dai parameter MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit get_codec_name_and_route() get dai name from the first codec dai in a dai link. However, the dai may not always be the first codec dai. Use the dai parameter to make sure get_codec_name_and_route() refers to the correct dai. Reviewed-by: Péter Ujfalusi Signed-off-by: Bard Liao Signed-off-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20240509163418.67746-19-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/intel/boards/sof_sdw_rt_amp.c | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/sound/soc/intel/boards/sof_sdw_rt_amp.c b/sound/soc/intel/boards/sof_sdw_rt_amp.c index df03441ab364..797ea9ffa77a 100644 --- a/sound/soc/intel/boards/sof_sdw_rt_amp.c +++ b/sound/soc/intel/boards/sof_sdw_rt_amp.c @@ -158,15 +158,11 @@ static const struct snd_soc_dapm_route rt1318_map[] = { { "Speaker", NULL, "rt1318-2 SPOR" }, }; -static const struct snd_soc_dapm_route *get_codec_name_and_route(struct snd_soc_pcm_runtime *rtd, +static const struct snd_soc_dapm_route *get_codec_name_and_route(struct snd_soc_dai *dai, char *codec_name) { - const char *dai_name; - - dai_name = rtd->dai_link->codecs->dai_name; - /* get the codec name */ - snprintf(codec_name, CODEC_NAME_SIZE, "%s", dai_name); + snprintf(codec_name, CODEC_NAME_SIZE, "%s", dai->name); /* choose the right codec's map */ if (strcmp(codec_name, "rt1308") == 0) @@ -186,7 +182,7 @@ int rt_amp_spk_rtd_init(struct snd_soc_pcm_runtime *rtd, struct snd_soc_dai *dai int ret; int i; - rt_amp_map = get_codec_name_and_route(rtd, codec_name); + rt_amp_map = get_codec_name_and_route(dai, codec_name); card->components = devm_kasprintf(card->dev, GFP_KERNEL, "%s spk:%s", -- cgit v1.2.3 From c8bdf9e727acb6e1b37febf422ef1751e5a2c7d1 Mon Sep 17 00:00:00 2001 From: Bard Liao Date: Thu, 9 May 2024 11:36:58 -0500 Subject: ASoC: rt715-sdca-sdw: Fix wrong complete waiting in rt715_dev_resume() enumeration_complete will be completed when a peripheral is attached. And initialization_complete will be completed when a peripheral is initialized. rt715_dev_resume() should wait for initialization_complete instead of enumeration_complete. the issue exists since commit 20d17057f0a8 ("ASoC: rt715-sdca: Add RT715 sdca vendor-specific driver"), but the commit can only apply to commit f892e66fcabc ("ASoC: rt-sdw*: add __func__ to all error logs"). Fixes: f892e66fcabc ("ASoC: rt-sdw*: add __func__ to all error logs") Signed-off-by: Bard Liao Signed-off-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20240509163658.68062-1-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/codecs/rt715-sdca-sdw.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/soc/codecs/rt715-sdca-sdw.c b/sound/soc/codecs/rt715-sdca-sdw.c index d3fb02e8f31a..c8dabb9b16b5 100644 --- a/sound/soc/codecs/rt715-sdca-sdw.c +++ b/sound/soc/codecs/rt715-sdca-sdw.c @@ -234,10 +234,10 @@ static int __maybe_unused rt715_dev_resume(struct device *dev) if (!slave->unattach_request) goto regmap_sync; - time = wait_for_completion_timeout(&slave->enumeration_complete, + time = wait_for_completion_timeout(&slave->initialization_complete, msecs_to_jiffies(RT715_PROBE_TIMEOUT)); if (!time) { - dev_err(&slave->dev, "%s: Enumeration not complete, timed out\n", __func__); + dev_err(&slave->dev, "%s: Initialization not complete, timed out\n", __func__); sdw_show_ping_status(slave->bus, true); return -ETIMEDOUT; -- cgit v1.2.3