Re: [PATCH 86/87] fs: switch timespec64 fields in inode to discrete integers
On Fri, Sep 29, 2023 at 3:19 AM Linus Torvalds wrote: ... > So yes, real programs to cache stat information, and it matters for > performance. > > But I don't think any actual reasonable program will have > *correctness* issues, though - I beg to disagree. > because there are certainly filesystems > out there that don't do nanosecond resolution (and other operations > like copying trees around will obviously also change times). > > Anybody doing steganography in the timestamps is already not going to > have a great time, really. > Your thesis implies that all applications are portable across different filesystems and all applications are expected to cope with copying trees around. There are applications that work on specific filesystems and those applications are very much within sanity if they expect that past observed values of nsec will not to change if the file was not changed. But even if we agree that will "only" hurt performance, your example of performance hit (10s of git diff) is nowhere close to the performance hit of invalidating the mtime cache of billions of files at once (i.e. after kernel upgrade), which means that rsync-like programs need to re-read all the data from remote locations. I am not saying that filesystems cannot decide to *stop storing nsec granularity* from this day forth, but like btrfs pre-historic timestamps, those fs have an obligation to preserve existing metadata, unless users opted to throw it away. OTOH, it is perfectly fine if the vfs wants to stop providing sub 100ns services to filesystems. It's just going to be the fs problem and the preserved pre-historic/fine-grained time on existing files would only need to be provided in getattr(). It does not need to be in __i_mtime. Thanks, Amir.
Re: [PATCH 86/87] fs: switch timespec64 fields in inode to discrete integers
On Thu, Sep 28, 2023 at 8:19 PM Darrick J. Wong wrote: > > On Thu, Sep 28, 2023 at 01:06:03PM -0400, Jeff Layton wrote: > > On Thu, 2023-09-28 at 11:48 -0400, Arnd Bergmann wrote: > > > On Thu, Sep 28, 2023, at 07:05, Jeff Layton wrote: > > > > This shaves 8 bytes off struct inode, according to pahole. > > > > > > > > Signed-off-by: Jeff Layton > > > > > > FWIW, this is similar to the approach that Deepa suggested > > > back in 2016: > > > > > > https://lore.kernel.org/lkml/1452144972-15802-3-git-send-email-deepa.ker...@gmail.com/ > > > > > > It was NaKed at the time because of the added complexity, > > > though it would have been much easier to do it then, > > > as we had to touch all the timespec references anyway. > > > > > > The approach still seems ok to me, but I'm not sure it's worth > > > doing it now if we didn't do it then. > > > > > > > I remember seeing those patches go by. I don't remember that change > > being NaK'ed, but I wasn't paying close attention at the time > > > > Looking at it objectively now, I think it's worth it to recover 8 bytes > > per inode and open a 4 byte hole that Amir can use to grow the > > i_fsnotify_mask. We might even able to shave off another 12 bytes > > eventually if we can move to a single 64-bit word per timestamp. > > I don't think you can, since btrfs timestamps utilize s64 seconds > counting in both directions from the Unix epoch. They also support ns > resolution: > > struct btrfs_timespec { > __le64 sec; > __le32 nsec; > } __attribute__ ((__packed__)); > > --D > Sure we can. That's what btrfs_inode is for. vfs inode also does not store i_otime (birth time) and there is even a precedent of vfs/btrfs variable size mismatch: /* full 64 bit generation number, struct vfs_inode doesn't have a big * enough field for this. */ u64 generation; If we decide that vfs should use "bigtime", btrfs pre-historic timestamps are not a show stopper. Thanks, Amir.
Re: [PATCH V4 2/2] tools/perf/tests: Fix object code reading to skip address that falls out of text section
> On 27-Sep-2023, at 8:25 PM, Athira Rajeev wrote: > > > >> On 27-Sep-2023, at 5:45 AM, Namhyung Kim wrote: >> >> On Thu, Sep 14, 2023 at 10:40 PM Athira Rajeev >> wrote: >>> >>> The testcase "Object code reading" fails in somecases >>> for "fs_something" sub test as below: >>> >>> Reading object code for memory address: 0xc00807f0142c >>> File is: /lib/modules/6.5.0-rc3+/kernel/fs/xfs/xfs.ko >>> On file address is: 0x1114cc >>> Objdump command is: objdump -z -d --start-address=0x11142c >>> --stop-address=0x1114ac /lib/modules/6.5.0-rc3+/kernel/fs/xfs/xfs.ko >>> objdump read too few bytes: 128 >>> test child finished with -1 >>> >>> This can alo be reproduced when running perf record with >>> workload that exercises fs_something() code. In the test >>> setup, this is exercising xfs code since root is xfs. >>> >>> # perf record ./a.out >>> # perf report -v |grep "xfs.ko" >>> 0.76% a.out /lib/modules/6.5.0-rc3+/kernel/fs/xfs/xfs.ko >>> 0xc00807de5efc B [k] xlog_cil_commit >>> 0.74% a.out /lib/modules/6.5.0-rc3+/kernel/fs/xfs/xfs.ko >>> 0xc00807d5ae18 B [k] xfs_btree_key_offset >>> 0.74% a.out /lib/modules/6.5.0-rc3+/kernel/fs/xfs/xfs.ko >>> 0xc00807e11fd4 B [k] 0x00112074 >>> >>> Here addr "0xc00807e11fd4" is not resolved. since this is a >>> kernel module, its offset is from the DSO. Xfs module is loaded >>> at 0xc00807d0 >>> >>> # cat /proc/modules | grep xfs >>> xfs 2228224 3 - Live 0xc00807d0 >>> >>> And size is 0x22. So its loaded between 0xc00807d0 >>> and 0xc00807f2. From objdump, text section is: >>> text 0010f7bc 00a0 2**4 >>> >>> Hence perf captured ip maps to 0x112074 which is: >>> ( ip - start of module ) + a0 >>> >>> This offset 0x112074 falls out .text section which is up to 0x10f7bc >>> In this case for module, the address 0xc00807e11fd4 is pointing >>> to stub instructions. This address range represents the module stubs >>> which is allocated on module load and hence is not part of DSO offset. >>> >>> To address this issue in "object code reading", skip the sample if >>> address falls out of text section and is within the module end. >>> Use the "text_end" member of "struct dso" to do this check. >>> >>> To address this issue in "perf report", exploring an option of >>> having stubs range as part of the /proc/kallsyms, so that perf >>> report can resolve addresses in stubs range >>> >>> However this patch uses text_end to skip the stub range for >>> Object code reading testcase. >>> >>> Reported-by: Disha Goel >>> Signed-off-by: Athira Rajeev >>> Tested-by: Disha Goel >>> Reviewed-by: Adrian Hunter >>> --- >>> Changelog: >>> v3 -> v4: >>> Fixed indent in V3 >>> >>> v2 -> v3: >>> Used strtailcmp in comparison for module check and added Reviewed-by >>> from Adrian, Tested-by from Disha. >>> >>> v1 -> v2: >>> Updated comment to add description on which arch has stub and >>> reason for skipping as suggested by Adrian >>> >>> tools/perf/tests/code-reading.c | 10 ++ >>> 1 file changed, 10 insertions(+) >>> >>> diff --git a/tools/perf/tests/code-reading.c >>> b/tools/perf/tests/code-reading.c >>> index ed3815163d1b..9e6e6c985840 100644 >>> --- a/tools/perf/tests/code-reading.c >>> +++ b/tools/perf/tests/code-reading.c >>> @@ -269,6 +269,16 @@ static int read_object_code(u64 addr, size_t len, u8 >>> cpumode, >>> if (addr + len > map__end(al.map)) >>> len = map__end(al.map) - addr; >>> >>> + /* >>> +* Some architectures (ex: powerpc) have stubs (trampolines) in >>> kernel >>> +* modules to manage long jumps. Check if the ip offset falls in >>> stubs >>> +* sections for kernel modules. And skip module address after text >>> end >>> +*/ >>> + if (!strtailcmp(dso->long_name, ".ko") && al.addr > dso->text_end) { >> >> There's a is_kernel_module() that can check compressed modules >> too but I think we need a simpler way to check it like dso->kernel. >> >> Thanks, >> Namhyung > > Thanks for the comment Namhyung. I will add similar to dso->kernel, another > field check in next version of patchset > > Athira Hi Namhyung, I have posted a V5 for this: https://lore.kernel.org/linux-perf-users/20230928075213.84392-1-atraj...@linux.vnet.ibm.com/T/#t Thanks Athira >> >> >>> + pr_debug("skipping the module address %#"PRIx64" after text >>> end\n", al.addr); >>> + goto out; >>> + } >>> + >>> /* Read the object code using perf */ >>> ret_len = dso__data_read_offset(dso, >>> maps__machine(thread__maps(thread)), >>> al.addr, buf1, len); >>> -- >>> 2.31.1
Re: [PATCH 2/2] tools/perf: Add perf binary dependent rule for shellcheck log in Makefile.perf
> On 27-Sep-2023, at 9:55 AM, Athira Rajeev wrote: > > > >> On 27-Sep-2023, at 5:25 AM, Namhyung Kim wrote: >> >> On Thu, Sep 14, 2023 at 10:18 AM Athira Rajeev >> wrote: >>> >>> Add rule in new Makefile "tests/Makefile.tests" for running >>> shellcheck on shell test scripts. This automates below shellcheck >>> into the build. >>> >>> $ for F in $(find tests/shell/ -perm -o=x -name '*.sh'); do >>> shellcheck -S warning $F; done >> >> I think you can do it if $(shell command -v shellcheck) returns >> non-empty string (the path to the shellcheck). Then the feature >> test logic can be gone. > > Ok, I will try this. >> >>> >>> CONFIG_SHELLCHECK check is added to avoid build breakage in >>> the absence of shellcheck binary. Update Makefile.perf to contain >>> new rule for "SHELLCHECK_TEST" which is for making shellcheck >>> test as a dependency on perf binary. Added "tests/Makefile.tests" >>> to run shellcheck on shellscripts in tests/shell. The make rule >>> "SHLLCHECK_RUN" ensures that, every time during make, shellcheck >>> will be run only on modified files during subsequent invocations. >>> By this, if any newly added shell scripts or fixes in existing >>> scripts breaks coding/formatting style, it will get captured >>> during the perf build. >> >> Can you show me the example output? > > Sure, I will add it. >> >>> >>> Signed-off-by: Athira Rajeev >>> --- >>> tools/perf/Makefile.perf| 12 +++- >>> tools/perf/tests/Makefile.tests | 24 >>> 2 files changed, 35 insertions(+), 1 deletion(-) >>> create mode 100644 tools/perf/tests/Makefile.tests >>> >>> diff --git a/tools/perf/Makefile.perf b/tools/perf/Makefile.perf >>> index f6fdc2d5a92f..c27f54771e90 100644 >>> --- a/tools/perf/Makefile.perf >>> +++ b/tools/perf/Makefile.perf >>> @@ -667,7 +667,16 @@ $(PERF_IN): prepare FORCE >>> $(PMU_EVENTS_IN): FORCE prepare >>> $(Q)$(MAKE) -f $(srctree)/tools/build/Makefile.build dir=pmu-events >>> obj=pmu-events >>> >>> -$(OUTPUT)perf: $(PERFLIBS) $(PERF_IN) $(PMU_EVENTS_IN) >>> +# Runs shellcheck on perf test shell scripts >>> +ifeq ($(CONFIG_SHELLCHECK),y) >>> +SHELLCHECK_TEST: FORCE prepare >>> + $(Q)$(MAKE) -f $(srctree)/tools/perf/tests/Makefile.tests >>> +else >>> +SHELLCHECK_TEST: >>> + @: >>> +endif >>> + >>> +$(OUTPUT)perf: $(PERFLIBS) $(PERF_IN) $(PMU_EVENTS_IN) SHELLCHECK_TEST >>> $(QUIET_LINK)$(CC) $(CFLAGS) $(LDFLAGS) \ >>> $(PERF_IN) $(PMU_EVENTS_IN) $(LIBS) -o $@ >>> >>> @@ -1129,6 +1138,7 @@ bpf-skel-clean: >>> $(call QUIET_CLEAN, bpf-skel) $(RM) -r $(SKEL_TMP_OUT) $(SKELETONS) >>> >>> clean:: $(LIBAPI)-clean $(LIBBPF)-clean $(LIBSUBCMD)-clean >>> $(LIBSYMBOL)-clean $(LIBPERF)-clean fixdep-clean python-clean >>> bpf-skel-clean tests-coresight-targets-clean >>> + $(Q)$(MAKE) -f $(srctree)/tools/perf/tests/Makefile.tests clean >>> $(call QUIET_CLEAN, core-objs) $(RM) $(LIBPERF_A) >>> $(OUTPUT)perf-archive $(OUTPUT)perf-iostat $(LANG_BINDINGS) >>> $(Q)find $(or $(OUTPUT),.) -name '*.o' -delete -o -name '\.*.cmd' >>> -delete -o -name '\.*.d' -delete >>> $(Q)$(RM) $(OUTPUT).config-detected >>> diff --git a/tools/perf/tests/Makefile.tests >>> b/tools/perf/tests/Makefile.tests >>> new file mode 100644 >>> index ..e74575559e83 >>> --- /dev/null >>> +++ b/tools/perf/tests/Makefile.tests >>> @@ -0,0 +1,24 @@ >>> +# SPDX-License-Identifier: GPL-2.0 >>> +# Athira Rajeev , 2023 >>> +-include $(OUTPUT).config-detected >>> + >>> +log_file = $(OUTPUT)shellcheck_test.log >>> +PROGS = $(subst ./,,$(shell find tests/shell -perm -o=x -type f -name >>> '*.sh')) >>> +DEPS = $(addprefix output/,$(addsuffix .dep,$(basename $(PROGS >>> +DIRS = $(shell echo $(dir $(DEPS)) | xargs -n1 | sort -u | xargs) >>> + >>> +.PHONY: all >>> +all: SHELLCHECK_RUN >>> + @: >>> + >>> +SHELLCHECK_RUN: $(DEPS) $(DIRS) >>> + >>> +output/%.dep: %.sh | $(DIRS) >>> + $(call rule_mkdir) >>> + $(Q)$(call frecho-cmd,test)@touch $@ >>> + $(Q)$(call frecho-cmd,test)@shellcheck -S warning $(subst >>> output/,./,$(patsubst %.dep, %.sh, $@)) 1> ${log_file} && ([[ ! -s >>> ${log_file} ]]) >> >> This line is too long, please wrap it with some backslashes. > Ok > > I will address all the comments in next version Hi Namhyung, While working on V2 for the Makefile changes and testing, came across three issues with latest scripts in perf-tools-next. I have addressed those in below patchset: https://lore.kernel.org/linux-perf-users/20230929041133.95355-1-atraj...@linux.vnet.ibm.com/T/#m7b3dc8a96467058e1b392183190baed47ae0eb75 [PATCH 0/3] Fix for shellcheck issues with latest scripts in tests/shell For the Makefile.perf changes, I will send V2 separately addressing review comments Thanks Athira > > Thanks > Athira >> >> Thanks, >> Namhyung >> >> >>> +$(DIRS): >>> + @mkdir -p $@ >>> + >>> +clean: >>> + @rm -rf $(log_file) output >>> -- >>> 2.31.1
[PATCH 3/3] tools/perf/tests: Fix shellcheck warning in record_sideband.sh test
Running shellcheck on record_sideband.sh throws below warning: In tests/shell/record_sideband.sh line 25: if ! perf record -o ${perfdata} -BN --no-bpf-event -C $1 true 2>&1 >/dev/null ^--^ SC2069: To redirect stdout+stderr, 2>&1 must be last (or use '{ cmd > file; } 2>&1' to clarify). This shows shellcheck warning SC2069 where the redirection order needs to be fixed. Use { cmd > file; } 2>&1 to fix the redirection of perf record output Fixes: 23b97c7ee963 ("perf test: Add test case for record sideband events") Signed-off-by: Athira Rajeev --- tools/perf/tests/shell/record_sideband.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/perf/tests/shell/record_sideband.sh b/tools/perf/tests/shell/record_sideband.sh index 5024a7ce0c51..7e036763a43c 100755 --- a/tools/perf/tests/shell/record_sideband.sh +++ b/tools/perf/tests/shell/record_sideband.sh @@ -22,7 +22,7 @@ trap trap_cleanup EXIT TERM INT can_cpu_wide() { -if ! perf record -o ${perfdata} -BN --no-bpf-event -C $1 true 2>&1 >/dev/null +if ! { perf record -o ${perfdata} -BN --no-bpf-event -C $1 true > /dev/null; } 2>&1 then echo "record sideband test [Skipped cannot record cpu$1]" err=2 -- 2.31.1
[PATCH 2/3] tools/perf/tests Ignore the shellcheck SC2046 warning in lock_contentio
Running shellcheck on lock_contention.sh generates below warning In tests/shell/lock_contention.sh line 36: if [ `nproc` -lt 4 ]; then ^-^ SC2046: Quote this to prevent word splitting. Here since nproc will generate a single word output and there is no possibility of word splitting, this warning can be ignored. Use exception for this with "disable" option in shellcheck. This warning is observed after commit: "commit 29441ab3a30a ("perf test lock_contention.sh: Skip test if not enough CPUs")" Fixes: 29441ab3a30a ("perf test lock_contention.sh: Skip test if not enough CPUs") Signed-off-by: Athira Rajeev --- tools/perf/tests/shell/lock_contention.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/tools/perf/tests/shell/lock_contention.sh b/tools/perf/tests/shell/lock_contention.sh index d5a191d3d090..c1ec5762215b 100755 --- a/tools/perf/tests/shell/lock_contention.sh +++ b/tools/perf/tests/shell/lock_contention.sh @@ -33,6 +33,7 @@ check() { exit fi + # shellcheck disable=SC2046 if [ `nproc` -lt 4 ]; then echo "[Skip] Low number of CPUs (`nproc`), lock event cannot be triggered certainly" err=2 -- 2.31.1
[PATCH 1/3] perf tests test_arm_coresight: Fix the shellcheck warning in latest test_arm_coresight.sh
Running shellcheck on tests/shell/test_arm_coresight.sh throws below warnings: In tests/shell/test_arm_coresight.sh line 15: cs_etm_path=$(find /sys/bus/event_source/devices/cs_etm/ -name cpu* -print -quit) ^--^ SC2061: Quote the parameter to -name so the shell won't interpret it. In tests/shell/test_arm_coresight.sh line 20: if [ $archhver -eq 5 -a "$(printf "0x%X\n" $archpart)" = "0xA13" ] ; then ^-- SC2166: Prefer [ p ] && [ q ] as [ p -a q ] is not well defined This warning is observed after commit: "commit bb350847965d ("perf test: Update cs_etm testcase for Arm ETE")" Fixed this issue by using quoting 'cpu*' for SC2061 and using "&&" in line number 20 for SC2166 warning Fixes: bb350847965d ("perf test: Update cs_etm testcase for Arm ETE") Signed-off-by: Athira Rajeev --- tools/perf/tests/shell/test_arm_coresight.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/perf/tests/shell/test_arm_coresight.sh b/tools/perf/tests/shell/test_arm_coresight.sh index fe78c4626e45..f2115dfa24a5 100755 --- a/tools/perf/tests/shell/test_arm_coresight.sh +++ b/tools/perf/tests/shell/test_arm_coresight.sh @@ -12,12 +12,12 @@ glb_err=0 cs_etm_dev_name() { - cs_etm_path=$(find /sys/bus/event_source/devices/cs_etm/ -name cpu* -print -quit) + cs_etm_path=$(find /sys/bus/event_source/devices/cs_etm/ -name 'cpu*' -print -quit) trcdevarch=$(cat ${cs_etm_path}/mgmt/trcdevarch) archhver=$((($trcdevarch >> 12) & 0xf)) archpart=$(($trcdevarch & 0xfff)) - if [ $archhver -eq 5 -a "$(printf "0x%X\n" $archpart)" = "0xA13" ] ; then + if [ $archhver -eq 5 ] && [ "$(printf "0x%X\n" $archpart)" = "0xA13" ] ; then echo "ete" else echo "etm" -- 2.31.1
[PATCH 0/3] Fix for shellcheck issues with latest scripts in tests/shell
shellcheck was run on perf tool shell scripts as a pre-requisite to include a build option for shellcheck discussed here: https://www.spinics.net/lists/linux-perf-users/msg25553.html And fixes were added for the coding/formatting issues in two patchsets: https://lore.kernel.org/linux-perf-users/20230613164145.50488-1-atraj...@linux.vnet.ibm.com/ https://lore.kernel.org/linux-perf-users/20230709182800.53002-1-atraj...@linux.vnet.ibm.com/ Three additional issues were observed and fixes are part of: https://git.kernel.org/pub/scm/linux/kernel/git/perf/perf-tools-next.git/log/?h=perf-tools-next With recent commits in perf, other three issues are observed. shellcheck version: 0.6.0 With this patchset: for F in $(find tests/shell/ -perm -o=x -name '*.sh'); do shellcheck -S warning $F; done echo $? 0 The changes are with recent commits ( which is mentioned in each patch) for ock_contention, record_sideband and test_arm_coresight testcases. The changes are made on top of: https://git.kernel.org/pub/scm/linux/kernel/git/perf/perf-tools-next.git/log/?h=perf-tools-next Athira Rajeev (3): perf tests test_arm_coresight: Fix the shellcheck warning in latest test_arm_coresight.sh tools/perf/tests Ignore the shellcheck SC2046 warning in lock_contentio tools/perf/tests: Fix shellcheck warning in record_sideband.sh test tools/perf/tests/shell/lock_contention.sh| 1 + tools/perf/tests/shell/record_sideband.sh| 2 +- tools/perf/tests/shell/test_arm_coresight.sh | 4 ++-- 3 files changed, 4 insertions(+), 3 deletions(-) -- 2.31.1
Re: [PATCHv7 2/4] powerpc/setup: Loosen the mapping between cpu logical id and its seq in dt
On Fri, Sep 29, 2023 at 4:36 AM Wen Xiong wrote: > > Hi Pingfan, > > + avail = intserv_node->avail; > + nthreads = intserv_node->len / sizeof(int); > + for (j = 0; j < nthreads && cpu < nr_cpu_ids; j++) { > set_cpu_present(cpu, avail); > set_cpu_possible(cpu, true); > - cpu_to_phys_id[cpu] = be32_to_cpu(intserv[j]); > + cpu_to_phys_id[cpu] = > be32_to_cpu(intserv_node->intserv[j]); > + DBG("thread %d -> cpu %d (hard id %d)\n", > + j, cpu, be32_to_cpu(intserv[j])); > > Intserv is not defined. Should "be32_to_cpu(intserv_node->intserv[j])? Yes, thanks. Sorry that I did not turn on the DBG macro and not catch this bug. Thanks, Pingfan > cpu++; > } > + } > > -Original Message- > From: Pingfan Liu > Sent: Monday, September 25, 2023 2:54 AM > To: linuxppc-dev@lists.ozlabs.org > Cc: Pingfan Liu ; Michael Ellerman ; > Nicholas Piggin ; Christophe Leroy > ; Mahesh Salgaonkar ; Wen > Xiong ; Baoquan He ; Ming Lei > ; ke...@lists.infradead.org > Subject: [EXTERNAL] [PATCHv7 2/4] powerpc/setup: Loosen the mapping between > cpu logical id and its seq in dt > > *** Idea *** > For kexec -p, the boot cpu can be not the cpu0, this causes the problem of > allocating memory for paca_ptrs[]. However, in theory, there is no > requirement to assign cpu's logical id as its present sequence in the device > tree. But there is something like cpu_first_thread_sibling(), which makes > assumption on the mapping inside a core. Hence partially loosening the > mapping, i.e. unbind the mapping of core while keep the mapping inside a core. > > *** Implement *** > At this early stage, there are plenty of memory to utilize. Hence, this patch > allocates interim memory to link the cpu info on a list, then reorder cpus by > changing the list head. As a result, there is a rotate shift between the > sequence number in dt and the cpu logical number. > > *** Result *** > After this patch, a boot-cpu's logical id will always be mapped into the > range [0,threads_per_core). > > Besides this, at this phase, all threads in the boot core are forced to be > onlined. This restriction will be lifted in a later patch with extra effort. > > Signed-off-by: Pingfan Liu > Cc: Michael Ellerman > Cc: Nicholas Piggin > Cc: Christophe Leroy > Cc: Mahesh Salgaonkar > Cc: Wen Xiong > Cc: Baoquan He > Cc: Ming Lei > Cc: ke...@lists.infradead.org > To: linuxppc-dev@lists.ozlabs.org > --- > arch/powerpc/kernel/prom.c | 25 + > arch/powerpc/kernel/setup-common.c | 87 +++--- > 2 files changed, 85 insertions(+), 27 deletions(-) > > diff --git a/arch/powerpc/kernel/prom.c b/arch/powerpc/kernel/prom.c index > ec82f5bda908..87272a2d8c10 100644 > --- a/arch/powerpc/kernel/prom.c > +++ b/arch/powerpc/kernel/prom.c > @@ -76,7 +76,9 @@ u64 ppc64_rma_size; > unsigned int boot_cpu_node_count __ro_after_init; #endif static > phys_addr_t first_memblock_size; > +#ifdef CONFIG_SMP > static int __initdata boot_cpu_count; > +#endif > > static int __init early_parse_mem(char *p) { @@ -331,8 +333,7 @@ static int > __init early_init_dt_scan_cpus(unsigned long node, > const __be32 *intserv; > int i, nthreads; > int len; > - int found = -1; > - int found_thread = 0; > + bool found = false; > > /* We are scanning "cpu" nodes only */ > if (type == NULL || strcmp(type, "cpu") != 0) @@ -355,8 +356,15 @@ > static int __init early_init_dt_scan_cpus(unsigned long node, > for (i = 0; i < nthreads; i++) { > if (be32_to_cpu(intserv[i]) == > fdt_boot_cpuid_phys(initial_boot_params)) { > - found = boot_cpu_count; > - found_thread = i; > + /* > +* always map the boot-cpu logical id into the > +* range of [0, thread_per_core) > +*/ > + boot_cpuid = i; > + found = true; > + /* This works around the hole in paca_ptrs[]. */ > + if (nr_cpu_ids < nthreads) > + set_nr_cpu_ids(nthreads); > } > #ifdef CONFIG_SMP > /* logical cpu id is always 0 on UP kernels */ @@ -365,14 > +373,13 @@ static int __init early_init_dt_scan_cpus(unsigned long node, > } > > /* Not the boot CPU */ > - if (found < 0) > + if (!found) > return 0; > > - DBG("boot cpu: logical %d physical %d\n", found, > - be32_to_cpu(intserv[found_thread])); > - boot_cpuid = found; > + DBG("boot cpu: logical %d physical %d\n", boot_cpuid, > +
Re: [PATCH 86/87] fs: switch timespec64 fields in inode to discrete integers
On Thu, 28 Sept 2023 at 14:28, Theodore Ts'o wrote: > > I don't think anyone will complain about breaking the userspace API > --- especially since if, say, the CIA was using this for their spies' > drop boxes, they probably wouldn't want to admit it. :-) Well, you will find that real apps do kind of of care. Just to take a very real example, "git" will very much notice time granularity issues and care - because git will cache the 'stat' times in the index. So if you get a different stat time (because the vfs layer has changed some granularity), git will then have to check the files carefully again and update the index. You can simulate this "re-check all files" with something like this: $ time git diff real 0m0.040s user 0m0.035s sys 0m0.264s $ rm .git/index && git read-tree HEAD $ time git diff real 0m9.595s user 0m7.287s sys 0m2.810s so the difference between just doing a "look, index information matches current 'stat' information" and "oops, index does not have the stat data" is "40 milliseconds" vs "10 seconds". That's a big difference, and you'd see that each time the granularity changes. But then once the index file has been updated, it's back to the good case. So yes, real programs to cache stat information, and it matters for performance. But I don't think any actual reasonable program will have *correctness* issues, though - because there are certainly filesystems out there that don't do nanosecond resolution (and other operations like copying trees around will obviously also change times). Anybody doing steganography in the timestamps is already not going to have a great time, really. Linus
Re: [PATCH 86/87] fs: switch timespec64 fields in inode to discrete integers
On Thu, Sep 28, 2023 at 01:40:55PM -0400, Jeff Layton wrote: > > Correct. We'd lose some fidelity in currently stored timestamps, but as > Linus and Ted pointed out, anything below ~100ns granularity is > effectively just noise, as that's the floor overhead for calling into > the kernel. It's hard to argue that any application needs that sort of > timestamp resolution, at least with contemporary hardware. > > Doing that would mean that tests that store specific values in the > atime/mtime and expect to be able to fetch exactly that value back would > break though, so we'd have to be OK with that if we want to try it. The > good news is that it's relatively easy to experiment with new ways to > store timestamps with these wrappers in place. The reason why we store 1ns granularity in ext4's on-disk format (and accept that we only support times only a couple of centuries into the future, as opposed shooting for an on-disk format good for several millennia :-), was in case there was userspace that might try to store a very fine-grained timestamp and want to be able to get it back bit-for-bit identical. For example, what if someone was trying to implement some kind of steganographic scheme where they going store a secret message (or more likely, a 256-bit AES key) in the nanosecond fields of the file's {c,m,a,cr}time timestamps, "hiding in plain sight". Not that I think that we have to support something like that, since the field is for *timestamps* not cryptographic bits, so if we break someone who is doing that, do we care? I don't think anyone will complain about breaking the userspace API --- especially since if, say, the CIA was using this for their spies' drop boxes, they probably wouldn't want to admit it. :-) - Ted
Re: [PATCH 86/87] fs: switch timespec64 fields in inode to discrete integers
On Thu, Sep 28, 2023, at 13:40, Jeff Layton wrote: > On Thu, 2023-09-28 at 10:19 -0700, Darrick J. Wong wrote: >> >> > I remember seeing those patches go by. I don't remember that change >> > being NaK'ed, but I wasn't paying close attention at the time >> > >> > Looking at it objectively now, I think it's worth it to recover 8 bytes >> > per inode and open a 4 byte hole that Amir can use to grow the >> > i_fsnotify_mask. We might even able to shave off another 12 bytes >> > eventually if we can move to a single 64-bit word per timestamp. >> >> I don't think you can, since btrfs timestamps utilize s64 seconds >> counting in both directions from the Unix epoch. They also support ns >> resolution: >> >> struct btrfs_timespec { >> __le64 sec; >> __le32 nsec; >> } __attribute__ ((__packed__)); >> > > Correct. We'd lose some fidelity in currently stored timestamps, but as > Linus and Ted pointed out, anything below ~100ns granularity is > effectively just noise, as that's the floor overhead for calling into > the kernel. It's hard to argue that any application needs that sort of > timestamp resolution, at least with contemporary hardware. There are probably applications that have come up with creative ways to use the timestamp fields of file systems that 94 bits of data, with both the MSB of the seconds and the LSB of the nanoseconds carrying information that they expect to be preserved. Dropping any information in the nanoseconds other than the top two bits would trivially change the 'ls -t' output when two files have the same timestamp in one kernel but slightly different timestamps in another one. For large values of 'tv_sec', there are fewer obvious things that break, but if current kernels are able to retrieve arbitrary times that were stored with utimensat(), then we should probably make sure future kernels can see the same. Arnd
Re: [PATCH 11/15] sgi-xp: Remove the now superfluous sentinel element from ctl_table array
On Thu, Sep 28, 2023 at 03:21:36PM +0200, Joel Granados via B4 Relay wrote: > From: Joel Granados > > This commit comes at the tail end of a greater effort to remove the > empty elements at the end of the ctl_table arrays (sentinels) which > will reduce the overall build time size of the kernel and run time > memory bloat by ~64 bytes per sentinel (further information Link : > https://lore.kernel.org/all/zo5yx5jfoggi%2f...@bombadil.infradead.org/) > > Remove sentinel from xpc_sys_xpc_hb and xpc_sys_xpc > > Signed-off-by: Joel Granados > --- > drivers/misc/sgi-xp/xpc_main.c | 6 ++ > 1 file changed, 2 insertions(+), 4 deletions(-) > > diff --git a/drivers/misc/sgi-xp/xpc_main.c b/drivers/misc/sgi-xp/xpc_main.c > index 6da509d692bb..c898092ff3ac 100644 > --- a/drivers/misc/sgi-xp/xpc_main.c > +++ b/drivers/misc/sgi-xp/xpc_main.c > @@ -109,8 +109,7 @@ static struct ctl_table xpc_sys_xpc_hb[] = { >.mode = 0644, >.proc_handler = proc_dointvec_minmax, >.extra1 = _hb_check_min_interval, > - .extra2 = _hb_check_max_interval}, > - {} > + .extra2 = _hb_check_max_interval} > }; > static struct ctl_table xpc_sys_xpc[] = { > { > @@ -120,8 +119,7 @@ static struct ctl_table xpc_sys_xpc[] = { >.mode = 0644, >.proc_handler = proc_dointvec_minmax, >.extra1 = _disengage_min_timelimit, > - .extra2 = _disengage_max_timelimit}, > - {} > + .extra2 = _disengage_max_timelimit} > }; > > static struct ctl_table_header *xpc_sysctl; > > -- > 2.30.2 > I assume you'll match the rest of the changes with regards to the trailing comma. Reviewed-by: Steve Wahl -- Steve Wahl, Hewlett Packard Enterprise
Re: [PATCH 87/87] fs: move i_blocks up a few places in struct inode
On Thu, 28 Sept 2023 at 04:06, Jeff Layton wrote: > > Move i_blocks up above the i_lock, which moves the new 4 byte hole to > just after the timestamps, without changing the size of the structure. I'm sure others have mentioned this, but 'struct inode' is marked with __randomize_layout, so the actual layout may end up being very different. I'm personally not convinced the whole structure randomization is worth it - it's easy enough to figure out for any distro kernel since the seed has to be the same across machines for modules to work, so even if the seed isn't "public", any layout is bound to be fairly easily discoverable. So the whole randomization only really works for private kernel builds, and it adds this kind of pain where "optimizing" the structure layout is kind of pointless depending on various options. I certainly *hope* no distro enables that pointless thing, but it's a worry. Linus
Re: [PATCH 87/87] fs: move i_blocks up a few places in struct inode
On Thu, 2023-09-28 at 10:41 -0700, Linus Torvalds wrote: > On Thu, 28 Sept 2023 at 04:06, Jeff Layton wrote: > > > > Move i_blocks up above the i_lock, which moves the new 4 byte hole to > > just after the timestamps, without changing the size of the structure. > > I'm sure others have mentioned this, but 'struct inode' is marked with > __randomize_layout, so the actual layout may end up being very > different. > > I'm personally not convinced the whole structure randomization is > worth it - it's easy enough to figure out for any distro kernel since > the seed has to be the same across machines for modules to work, so > even if the seed isn't "public", any layout is bound to be fairly > easily discoverable. > > So the whole randomization only really works for private kernel > builds, and it adds this kind of pain where "optimizing" the structure > layout is kind of pointless depending on various options. > > I certainly *hope* no distro enables that pointless thing, but it's a worry. > I've never enabled struct randomization and don't know anyone who does. I figure if you turn that on, you get to keep all of the pieces when you start seeing weird performance problems. I think that we have to optimize for that being disabled. Even without that though, turning on and off options can change the layout...and then there are different arches, etc. I'm using a config derived from the Fedora x86_64 kernel images and hope that represents a reasonably common configuration. The only conditional members before the timestamps are based on CONFIG_FS_POSIX_ACL and CONFIG_SECURITY, which are almost always turned on with most distros. -- Jeff Layton
Re: [PATCH 86/87] fs: switch timespec64 fields in inode to discrete integers
On Thu, 2023-09-28 at 10:19 -0700, Darrick J. Wong wrote: > On Thu, Sep 28, 2023 at 01:06:03PM -0400, Jeff Layton wrote: > > On Thu, 2023-09-28 at 11:48 -0400, Arnd Bergmann wrote: > > > On Thu, Sep 28, 2023, at 07:05, Jeff Layton wrote: > > > > This shaves 8 bytes off struct inode, according to pahole. > > > > > > > > Signed-off-by: Jeff Layton > > > > > > FWIW, this is similar to the approach that Deepa suggested > > > back in 2016: > > > > > > https://lore.kernel.org/lkml/1452144972-15802-3-git-send-email-deepa.ker...@gmail.com/ > > > > > > It was NaKed at the time because of the added complexity, > > > though it would have been much easier to do it then, > > > as we had to touch all the timespec references anyway. > > > > > > The approach still seems ok to me, but I'm not sure it's worth > > > doing it now if we didn't do it then. > > > > > > > I remember seeing those patches go by. I don't remember that change > > being NaK'ed, but I wasn't paying close attention at the time > > > > Looking at it objectively now, I think it's worth it to recover 8 bytes > > per inode and open a 4 byte hole that Amir can use to grow the > > i_fsnotify_mask. We might even able to shave off another 12 bytes > > eventually if we can move to a single 64-bit word per timestamp. > > I don't think you can, since btrfs timestamps utilize s64 seconds > counting in both directions from the Unix epoch. They also support ns > resolution: > > struct btrfs_timespec { > __le64 sec; > __le32 nsec; > } __attribute__ ((__packed__)); > Correct. We'd lose some fidelity in currently stored timestamps, but as Linus and Ted pointed out, anything below ~100ns granularity is effectively just noise, as that's the floor overhead for calling into the kernel. It's hard to argue that any application needs that sort of timestamp resolution, at least with contemporary hardware. Doing that would mean that tests that store specific values in the atime/mtime and expect to be able to fetch exactly that value back would break though, so we'd have to be OK with that if we want to try it. The good news is that it's relatively easy to experiment with new ways to store timestamps with these wrappers in place. -- Jeff Layton
Re: [PATCH 86/87] fs: switch timespec64 fields in inode to discrete integers
On Thu, Sep 28, 2023 at 01:06:03PM -0400, Jeff Layton wrote: > On Thu, 2023-09-28 at 11:48 -0400, Arnd Bergmann wrote: > > On Thu, Sep 28, 2023, at 07:05, Jeff Layton wrote: > > > This shaves 8 bytes off struct inode, according to pahole. > > > > > > Signed-off-by: Jeff Layton > > > > FWIW, this is similar to the approach that Deepa suggested > > back in 2016: > > > > https://lore.kernel.org/lkml/1452144972-15802-3-git-send-email-deepa.ker...@gmail.com/ > > > > It was NaKed at the time because of the added complexity, > > though it would have been much easier to do it then, > > as we had to touch all the timespec references anyway. > > > > The approach still seems ok to me, but I'm not sure it's worth > > doing it now if we didn't do it then. > > > > I remember seeing those patches go by. I don't remember that change > being NaK'ed, but I wasn't paying close attention at the time > > Looking at it objectively now, I think it's worth it to recover 8 bytes > per inode and open a 4 byte hole that Amir can use to grow the > i_fsnotify_mask. We might even able to shave off another 12 bytes > eventually if we can move to a single 64-bit word per timestamp. I don't think you can, since btrfs timestamps utilize s64 seconds counting in both directions from the Unix epoch. They also support ns resolution: struct btrfs_timespec { __le64 sec; __le32 nsec; } __attribute__ ((__packed__)); --D > It is a lot of churn though. > -- > Jeff Layton
Re: [PATCH 86/87] fs: switch timespec64 fields in inode to discrete integers
On Thu, 2023-09-28 at 07:05 -0400, Jeff Layton wrote: > This shaves 8 bytes off struct inode, according to pahole. > > Signed-off-by: Jeff Layton > --- > include/linux/fs.h | 32 +++- > 1 file changed, 23 insertions(+), 9 deletions(-) > > diff --git a/include/linux/fs.h b/include/linux/fs.h > index 831657011036..de902ff2938b 100644 > --- a/include/linux/fs.h > +++ b/include/linux/fs.h > @@ -671,9 +671,12 @@ struct inode { > }; > dev_t i_rdev; > loff_t i_size; > - struct timespec64 __i_atime; /* use inode_*_atime accessors */ > - struct timespec64 __i_mtime; /* use inode_*_mtime accessors */ > - struct timespec64 __i_ctime; /* use inode_*_ctime accessors */ > + time64_ti_atime_sec; > + time64_ti_mtime_sec; > + time64_ti_ctime_sec; > + u32 i_atime_nsec; > + u32 i_mtime_nsec; > + u32 i_ctime_nsec; > spinlock_t i_lock; /* i_blocks, i_bytes, maybe i_size */ > unsigned short i_bytes; > u8 i_blkbits; > @@ -1519,7 +1522,9 @@ struct timespec64 inode_set_ctime_current(struct inode > *inode); > */ > static inline struct timespec64 inode_get_ctime(const struct inode *inode) > { > - return inode->__i_ctime; > + struct timespec64 ts = { .tv_sec = inode->i_ctime_sec, > + .tv_nsec = inode->i_ctime_nsec }; > + return ts; > } > > > > /** > @@ -1532,7 +1537,8 @@ static inline struct timespec64 inode_get_ctime(const > struct inode *inode) > static inline struct timespec64 inode_set_ctime_to_ts(struct inode *inode, > struct timespec64 ts) > { > - inode->__i_ctime = ts; > + inode->i_ctime_sec = ts.tv_sec; > + inode->i_ctime_nsec = ts.tv_sec; Bug above and in the other inode_set_?time_to_ts() functions. This isn't setting the nsec field correctly. > return ts; > } > > > > @@ -1555,13 +1561,17 @@ static inline struct timespec64 > inode_set_ctime(struct inode *inode, > > static inline struct timespec64 inode_get_atime(const struct inode *inode) > { > - return inode->__i_atime; > + struct timespec64 ts = { .tv_sec = inode->i_atime_sec, > + .tv_nsec = inode->i_atime_nsec }; > + > + return ts; > } > > static inline struct timespec64 inode_set_atime_to_ts(struct inode *inode, > struct timespec64 ts) > { > - inode->__i_atime = ts; > + inode->i_atime_sec = ts.tv_sec; > + inode->i_atime_nsec = ts.tv_sec; > return ts; > } > > @@ -1575,13 +1585,17 @@ static inline struct timespec64 > inode_set_atime(struct inode *inode, > > static inline struct timespec64 inode_get_mtime(const struct inode *inode) > { > - return inode->__i_mtime; > + struct timespec64 ts = { .tv_sec = inode->i_mtime_sec, > + .tv_nsec = inode->i_mtime_nsec }; > + > + return ts; > } > > static inline struct timespec64 inode_set_mtime_to_ts(struct inode *inode, > struct timespec64 ts) > { > - inode->__i_mtime = ts; > + inode->i_atime_sec = ts.tv_sec; > + inode->i_atime_nsec = ts.tv_sec; Doh! s/atime/mtime/ in the above lines. > return ts; > } > Both bugs are fixed in my tree. -- Jeff Layton
Re: [PATCH 86/87] fs: switch timespec64 fields in inode to discrete integers
On Thu, 2023-09-28 at 11:48 -0400, Arnd Bergmann wrote: > On Thu, Sep 28, 2023, at 07:05, Jeff Layton wrote: > > This shaves 8 bytes off struct inode, according to pahole. > > > > Signed-off-by: Jeff Layton > > FWIW, this is similar to the approach that Deepa suggested > back in 2016: > > https://lore.kernel.org/lkml/1452144972-15802-3-git-send-email-deepa.ker...@gmail.com/ > > It was NaKed at the time because of the added complexity, > though it would have been much easier to do it then, > as we had to touch all the timespec references anyway. > > The approach still seems ok to me, but I'm not sure it's worth > doing it now if we didn't do it then. > I remember seeing those patches go by. I don't remember that change being NaK'ed, but I wasn't paying close attention at the time Looking at it objectively now, I think it's worth it to recover 8 bytes per inode and open a 4 byte hole that Amir can use to grow the i_fsnotify_mask. We might even able to shave off another 12 bytes eventually if we can move to a single 64-bit word per timestamp. It is a lot of churn though. -- Jeff Layton
Re: [PATCH 86/87] fs: switch timespec64 fields in inode to discrete integers
On Thu, Sep 28, 2023, at 07:05, Jeff Layton wrote: > This shaves 8 bytes off struct inode, according to pahole. > > Signed-off-by: Jeff Layton FWIW, this is similar to the approach that Deepa suggested back in 2016: https://lore.kernel.org/lkml/1452144972-15802-3-git-send-email-deepa.ker...@gmail.com/ It was NaKed at the time because of the added complexity, though it would have been much easier to do it then, as we had to touch all the timespec references anyway. The approach still seems ok to me, but I'm not sure it's worth doing it now if we didn't do it then. Arnd
Kernel Panic 6.5.0-1 PPC
Hi, I'm running Debian on an old Powermac (32-bit PPC G4). I'm seeing kernel panics with 6.5.0-1. Everything seems to be fine with: Linux powermac-g4 6.4.0-4-powerpc #1 Debian 6.4.13-1 (2023-08-31) ppc GNU/Linux 0.00] MSR:9032 CR: 48024242 XER: 0.00] 0.00] GPR00: c0b29234 c13fde60 c12f3580 c12f3580 c12f3580 c13fde74 cc0 0.00] GPR08: 9032 28024242 000 0004 0.00] GPR16: 02d159f4 02d1515c c00f6d38 0004 cc0 0.00] GPR24: c12f398c c0b29704 0001 0003 c12f3580 c1305080 c12f 5cc c12f3580 0.00] NIP [c0b28e4c] __schedule+0x364/0x920 0.00] LR [c0b29234] __schedule+0x74c/0x920 0.00] --- interrupt: 900 0.00] [c13fdeb0] [c0b29704] __cond_resched+0x40/060 0.00] [c13fdec0] [c0b2b5f0] mutex_lock_killable+0x24/0x74 0.00] [c13fdee0] [c02c3930] pcpu_alloc+0x54c/0x798 0.00] [c13fdf50] [c00f6d38] alloc_desc.irsa.0+0x60/0x174 0.00] [c13fdf80] [c1199c58] early_irq_init+0x70/0x9c 0.00] [c13fdfa0] [c1183abc] start_kernel+0x4e4/0x640 0.00] [c13fdff0] [3540] 0x3540 0.00] Code: 7d2a01a4 4c00012c 4b28 7c0802a6 90010004 6000 9421f e0 7c0802a6 3d20c141 93e1001c 90010024 83e9c294 <943f1ff0> 7fe1fb78 48b24909 80 1 0.00] ---[ end trace ]--- 0.00] 0.00] Kernel panic - not syncing: Attempted to kill the idle task! 0.00] ---[ end Kernel panic - not syncing: Attempted to kill the idle t ask! ]--- -- Dan Whitehouse GPG: 3AA4 369C 86E1 4939 D420 AB25 D0DC 7BDD CA92 AD2E Telephone: +44(0)203 0955088
Re: [PATCH 02/26] vfio: Move KVM get/put helpers to colocate it with other KVM related code
On Fri, 15 Sep 2023 17:30:54 -0700 Sean Christopherson wrote: > Move the definitions of vfio_device_get_kvm_safe() and vfio_device_put_kvm() > down in vfio_main.c to colocate them with other KVM-specific functions, > e.g. to allow wrapping them all with a single CONFIG_KVM check. > > Signed-off-by: Sean Christopherson > --- > drivers/vfio/vfio_main.c | 104 +++ > 1 file changed, 52 insertions(+), 52 deletions(-) Reviewed-by: Alex Williamson > diff --git a/drivers/vfio/vfio_main.c b/drivers/vfio/vfio_main.c > index 80e39f7a6d8f..6368eed7b7b2 100644 > --- a/drivers/vfio/vfio_main.c > +++ b/drivers/vfio/vfio_main.c > @@ -381,58 +381,6 @@ void vfio_unregister_group_dev(struct vfio_device > *device) > } > EXPORT_SYMBOL_GPL(vfio_unregister_group_dev); > > -#if IS_ENABLED(CONFIG_KVM) > -void vfio_device_get_kvm_safe(struct vfio_device *device, struct kvm *kvm) > -{ > - void (*pfn)(struct kvm *kvm); > - bool (*fn)(struct kvm *kvm); > - bool ret; > - > - lockdep_assert_held(>dev_set->lock); > - > - if (!kvm) > - return; > - > - pfn = symbol_get(kvm_put_kvm); > - if (WARN_ON(!pfn)) > - return; > - > - fn = symbol_get(kvm_get_kvm_safe); > - if (WARN_ON(!fn)) { > - symbol_put(kvm_put_kvm); > - return; > - } > - > - ret = fn(kvm); > - symbol_put(kvm_get_kvm_safe); > - if (!ret) { > - symbol_put(kvm_put_kvm); > - return; > - } > - > - device->put_kvm = pfn; > - device->kvm = kvm; > -} > - > -void vfio_device_put_kvm(struct vfio_device *device) > -{ > - lockdep_assert_held(>dev_set->lock); > - > - if (!device->kvm) > - return; > - > - if (WARN_ON(!device->put_kvm)) > - goto clear; > - > - device->put_kvm(device->kvm); > - device->put_kvm = NULL; > - symbol_put(kvm_put_kvm); > - > -clear: > - device->kvm = NULL; > -} > -#endif > - > /* true if the vfio_device has open_device() called but not close_device() */ > static bool vfio_assert_device_open(struct vfio_device *device) > { > @@ -1354,6 +1302,58 @@ bool vfio_file_enforced_coherent(struct file *file) > } > EXPORT_SYMBOL_GPL(vfio_file_enforced_coherent); > > +#if IS_ENABLED(CONFIG_KVM) > +void vfio_device_get_kvm_safe(struct vfio_device *device, struct kvm *kvm) > +{ > + void (*pfn)(struct kvm *kvm); > + bool (*fn)(struct kvm *kvm); > + bool ret; > + > + lockdep_assert_held(>dev_set->lock); > + > + if (!kvm) > + return; > + > + pfn = symbol_get(kvm_put_kvm); > + if (WARN_ON(!pfn)) > + return; > + > + fn = symbol_get(kvm_get_kvm_safe); > + if (WARN_ON(!fn)) { > + symbol_put(kvm_put_kvm); > + return; > + } > + > + ret = fn(kvm); > + symbol_put(kvm_get_kvm_safe); > + if (!ret) { > + symbol_put(kvm_put_kvm); > + return; > + } > + > + device->put_kvm = pfn; > + device->kvm = kvm; > +} > + > +void vfio_device_put_kvm(struct vfio_device *device) > +{ > + lockdep_assert_held(>dev_set->lock); > + > + if (!device->kvm) > + return; > + > + if (WARN_ON(!device->put_kvm)) > + goto clear; > + > + device->put_kvm(device->kvm); > + device->put_kvm = NULL; > + symbol_put(kvm_put_kvm); > + > +clear: > + device->kvm = NULL; > +} > +#endif > + > static void vfio_device_file_set_kvm(struct file *file, struct kvm *kvm) > { > struct vfio_device_file *df = file->private_data;
Re: [PATCH 05/26] vfio: KVM: Pass get/put helpers from KVM to VFIO, don't do circular lookup
On Fri, 15 Sep 2023 17:30:57 -0700 Sean Christopherson wrote: > Explicitly pass KVM's get/put helpers to VFIO when attaching a VM to > VFIO instead of having VFIO do a symbol lookup back into KVM. Having both > KVM and VFIO do symbol lookups increases the overall complexity and places > an unnecessary dependency on KVM (from VFIO) without adding any value. > > Signed-off-by: Sean Christopherson > --- > drivers/vfio/vfio.h | 2 ++ > drivers/vfio/vfio_main.c | 74 +++- > include/linux/vfio.h | 4 ++- > virt/kvm/vfio.c | 9 +++-- > 4 files changed, 47 insertions(+), 42 deletions(-) Reviewed-by: Alex Williamson > diff --git a/drivers/vfio/vfio.h b/drivers/vfio/vfio.h > index a1f741365075..eec51c7ee822 100644 > --- a/drivers/vfio/vfio.h > +++ b/drivers/vfio/vfio.h > @@ -19,6 +19,8 @@ struct vfio_container; > > struct vfio_kvm_reference { > struct kvm *kvm; > + bool(*get_kvm)(struct kvm *kvm); > + void(*put_kvm)(struct kvm *kvm); > spinlock_t lock; > }; > > diff --git a/drivers/vfio/vfio_main.c b/drivers/vfio/vfio_main.c > index e77e8c6aae2f..1f58ab6dbcd2 100644 > --- a/drivers/vfio/vfio_main.c > +++ b/drivers/vfio/vfio_main.c > @@ -16,7 +16,6 @@ > #include > #include > #include > -#include > #include > #include > #include > @@ -1306,38 +1305,22 @@ EXPORT_SYMBOL_GPL(vfio_file_enforced_coherent); > void vfio_device_get_kvm_safe(struct vfio_device *device, > struct vfio_kvm_reference *ref) > { > - void (*pfn)(struct kvm *kvm); > - bool (*fn)(struct kvm *kvm); > - bool ret; > - > lockdep_assert_held(>dev_set->lock); > > + /* > + * Note! The "kvm" and "put_kvm" pointers *must* be transferred to the > + * device so that the device can put its reference to KVM. KVM can > + * invoke vfio_device_set_kvm() to detach from VFIO, i.e. nullify all > + * pointers in @ref, even if a device holds a reference to KVM! That > + * also means that detaching KVM from VFIO only prevents "new" devices > + * from using KVM, it doesn't invalidate KVM references in existing > + * devices. > + */ > spin_lock(>lock); > - > - if (!ref->kvm) > - goto out; > - > - pfn = symbol_get(kvm_put_kvm); > - if (WARN_ON(!pfn)) > - goto out; > - > - fn = symbol_get(kvm_get_kvm_safe); > - if (WARN_ON(!fn)) { > - symbol_put(kvm_put_kvm); > - goto out; > + if (ref->kvm && ref->get_kvm(ref->kvm)) { > + device->kvm = ref->kvm; > + device->put_kvm = ref->put_kvm; > } > - > - ret = fn(ref->kvm); > - symbol_put(kvm_get_kvm_safe); > - if (!ret) { > - symbol_put(kvm_put_kvm); > - goto out; > - } > - > - device->put_kvm = pfn; > - device->kvm = ref->kvm; > - > -out: > spin_unlock(>lock); > } > > @@ -1353,28 +1336,37 @@ void vfio_device_put_kvm(struct vfio_device *device) > > device->put_kvm(device->kvm); > device->put_kvm = NULL; > - symbol_put(kvm_put_kvm); > - > clear: > device->kvm = NULL; > } > > static void vfio_device_set_kvm(struct vfio_kvm_reference *ref, > - struct kvm *kvm) > + struct kvm *kvm, > + bool (*get_kvm)(struct kvm *kvm), > + void (*put_kvm)(struct kvm *kvm)) > { > + if (WARN_ON_ONCE(kvm && (!get_kvm || !put_kvm))) > + return; > + > spin_lock(>lock); > ref->kvm = kvm; > + ref->get_kvm = get_kvm; > + ref->put_kvm = put_kvm; > spin_unlock(>lock); > } > > -static void vfio_group_set_kvm(struct vfio_group *group, struct kvm *kvm) > +static void vfio_group_set_kvm(struct vfio_group *group, struct kvm *kvm, > +bool (*get_kvm)(struct kvm *kvm), > +void (*put_kvm)(struct kvm *kvm)) > { > #if IS_ENABLED(CONFIG_VFIO_GROUP) > - vfio_device_set_kvm(>kvm_ref, kvm); > + vfio_device_set_kvm(>kvm_ref, kvm, get_kvm, put_kvm); > #endif > } > > -static void vfio_device_file_set_kvm(struct file *file, struct kvm *kvm) > +static void vfio_device_file_set_kvm(struct file *file, struct kvm *kvm, > + bool (*get_kvm)(struct kvm *kvm), > + void (*put_kvm)(struct kvm *kvm)) > { > struct vfio_device_file *df = file->private_data; > > @@ -1383,27 +1375,31 @@ static void vfio_device_file_set_kvm(struct file > *file, struct kvm *kvm) >* be propagated to vfio_device::kvm when the file is bound to >* iommufd successfully in the vfio device cdev path. >*/ > - vfio_device_set_kvm(>kvm_ref, kvm); > + vfio_device_set_kvm(>kvm_ref, kvm, get_kvm, put_kvm); > } >
Re: [PATCH 03/26] virt: Declare and define vfio_file_set_kvm() iff CONFIG_KVM is enabled
On Fri, 15 Sep 2023 17:30:55 -0700 Sean Christopherson wrote: > Hide vfio_file_set_kvm() and its unique helpers if KVM is not enabled, > nothing else in the kernel (or out of the kernel) should be using a > KVM specific helper. > > Signed-off-by: Sean Christopherson > --- > drivers/vfio/vfio_main.c | 2 +- > include/linux/vfio.h | 2 ++ > 2 files changed, 3 insertions(+), 1 deletion(-) As Jason noted, s/virt/vfio/ in title. Reviewed-by: Alex Williamson > diff --git a/drivers/vfio/vfio_main.c b/drivers/vfio/vfio_main.c > index 6368eed7b7b2..124cc88966a7 100644 > --- a/drivers/vfio/vfio_main.c > +++ b/drivers/vfio/vfio_main.c > @@ -1352,7 +1352,6 @@ void vfio_device_put_kvm(struct vfio_device *device) > clear: > device->kvm = NULL; > } > -#endif > > static void vfio_device_file_set_kvm(struct file *file, struct kvm *kvm) > { > @@ -1388,6 +1387,7 @@ void vfio_file_set_kvm(struct file *file, struct kvm > *kvm) > vfio_device_file_set_kvm(file, kvm); > } > EXPORT_SYMBOL_GPL(vfio_file_set_kvm); > +#endif > > /* > * Sub-module support > diff --git a/include/linux/vfio.h b/include/linux/vfio.h > index 454e9295970c..e80955de266c 100644 > --- a/include/linux/vfio.h > +++ b/include/linux/vfio.h > @@ -311,7 +311,9 @@ static inline bool vfio_file_has_dev(struct file *file, > struct vfio_device *devi > #endif > bool vfio_file_is_valid(struct file *file); > bool vfio_file_enforced_coherent(struct file *file); > +#if IS_ENABLED(CONFIG_KVM) > void vfio_file_set_kvm(struct file *file, struct kvm *kvm); > +#endif > > #define VFIO_PIN_PAGES_MAX_ENTRIES (PAGE_SIZE/sizeof(unsigned long)) >
Re: [PATCH 01/26] vfio: Wrap KVM helpers with CONFIG_KVM instead of CONFIG_HAVE_KVM
On Fri, 15 Sep 2023 17:30:53 -0700 Sean Christopherson wrote: > Wrap the helpers for getting references to KVM instances with a check on > CONFIG_KVM being enabled, not on CONFIG_HAVE_KVM being defined. PPC does > NOT select HAVE_KVM, despite obviously supporting KVM, and guarding code > to get references to KVM based on whether or not the architecture supports > KVM is nonsensical. > > Drop the guard around linux/kvm_host.h entirely, conditionally including a > generic headers is completely unnecessary. > > Signed-off-by: Sean Christopherson > --- > drivers/vfio/vfio.h | 2 +- > drivers/vfio/vfio_main.c | 4 +--- > 2 files changed, 2 insertions(+), 4 deletions(-) Reviewed-by: Alex Williamson > diff --git a/drivers/vfio/vfio.h b/drivers/vfio/vfio.h > index 307e3f29b527..c26d1ad68105 100644 > --- a/drivers/vfio/vfio.h > +++ b/drivers/vfio/vfio.h > @@ -434,7 +434,7 @@ static inline void vfio_virqfd_exit(void) > } > #endif > > -#ifdef CONFIG_HAVE_KVM > +#if IS_ENABLED(CONFIG_KVM) > void vfio_device_get_kvm_safe(struct vfio_device *device, struct kvm *kvm); > void vfio_device_put_kvm(struct vfio_device *device); > #else > diff --git a/drivers/vfio/vfio_main.c b/drivers/vfio/vfio_main.c > index 40732e8ed4c6..80e39f7a6d8f 100644 > --- a/drivers/vfio/vfio_main.c > +++ b/drivers/vfio/vfio_main.c > @@ -16,9 +16,7 @@ > #include > #include > #include > -#ifdef CONFIG_HAVE_KVM > #include > -#endif > #include > #include > #include > @@ -383,7 +381,7 @@ void vfio_unregister_group_dev(struct vfio_device *device) > } > EXPORT_SYMBOL_GPL(vfio_unregister_group_dev); > > -#ifdef CONFIG_HAVE_KVM > +#if IS_ENABLED(CONFIG_KVM) > void vfio_device_get_kvm_safe(struct vfio_device *device, struct kvm *kvm) > { > void (*pfn)(struct kvm *kvm);
Re: [PATCH 04/26] vfio: Add struct to hold KVM assets and dedup group vs. iommufd code
On Fri, 15 Sep 2023 17:30:56 -0700 Sean Christopherson wrote: > Add a struct to hold the KVM assets need to manage and pass along KVM > references to VFIO devices. Providing a common struct deduplicates the > group vs. iommufd code, and will make it easier to rework the attachment > logic so that VFIO doesn't have to do a symbol lookup to retrieve the > get/put helpers from KVM. > > Signed-off-by: Sean Christopherson > --- > drivers/vfio/device_cdev.c | 9 +--- > drivers/vfio/group.c | 18 ++-- > drivers/vfio/vfio.h| 22 +-- > drivers/vfio/vfio_main.c | 43 +++--- > 4 files changed, 45 insertions(+), 47 deletions(-) Reviewed-by: Alex Williamson > diff --git a/drivers/vfio/device_cdev.c b/drivers/vfio/device_cdev.c > index e75da0a70d1f..e484d6d6400a 100644 > --- a/drivers/vfio/device_cdev.c > +++ b/drivers/vfio/device_cdev.c > @@ -46,13 +46,6 @@ int vfio_device_fops_cdev_open(struct inode *inode, struct > file *filep) > return ret; > } > > -static void vfio_df_get_kvm_safe(struct vfio_device_file *df) > -{ > - spin_lock(>kvm_ref_lock); > - vfio_device_get_kvm_safe(df->device, df->kvm); > - spin_unlock(>kvm_ref_lock); > -} > - > long vfio_df_ioctl_bind_iommufd(struct vfio_device_file *df, > struct vfio_device_bind_iommufd __user *arg) > { > @@ -99,7 +92,7 @@ long vfio_df_ioctl_bind_iommufd(struct vfio_device_file *df, >* a reference. This reference is held until device closed. >* Save the pointer in the device for use by drivers. >*/ > - vfio_df_get_kvm_safe(df); > + vfio_device_get_kvm_safe(df->device, >kvm_ref); > > ret = vfio_df_open(df); > if (ret) > diff --git a/drivers/vfio/group.c b/drivers/vfio/group.c > index 610a429c6191..756e47ff4cf0 100644 > --- a/drivers/vfio/group.c > +++ b/drivers/vfio/group.c > @@ -157,13 +157,6 @@ static int vfio_group_ioctl_set_container(struct > vfio_group *group, > return ret; > } > > -static void vfio_device_group_get_kvm_safe(struct vfio_device *device) > -{ > - spin_lock(>group->kvm_ref_lock); > - vfio_device_get_kvm_safe(device, device->group->kvm); > - spin_unlock(>group->kvm_ref_lock); > -} > - > static int vfio_df_group_open(struct vfio_device_file *df) > { > struct vfio_device *device = df->device; > @@ -184,7 +177,7 @@ static int vfio_df_group_open(struct vfio_device_file *df) >* the pointer in the device for use by drivers. >*/ > if (device->open_count == 0) > - vfio_device_group_get_kvm_safe(device); > + vfio_device_get_kvm_safe(device, >group->kvm_ref); > > df->iommufd = device->group->iommufd; > if (df->iommufd && vfio_device_is_noiommu(device) && device->open_count > == 0) { > @@ -560,7 +553,7 @@ static struct vfio_group *vfio_group_alloc(struct > iommu_group *iommu_group, > > refcount_set(>drivers, 1); > mutex_init(>group_lock); > - spin_lock_init(>kvm_ref_lock); > + spin_lock_init(>kvm_ref.lock); > INIT_LIST_HEAD(>device_list); > mutex_init(>device_lock); > group->iommu_group = iommu_group; > @@ -884,13 +877,6 @@ bool vfio_group_enforced_coherent(struct vfio_group > *group) > return ret; > } > > -void vfio_group_set_kvm(struct vfio_group *group, struct kvm *kvm) > -{ > - spin_lock(>kvm_ref_lock); > - group->kvm = kvm; > - spin_unlock(>kvm_ref_lock); > -} > - > /** > * vfio_file_has_dev - True if the VFIO file is a handle for device > * @file: VFIO file to check > diff --git a/drivers/vfio/vfio.h b/drivers/vfio/vfio.h > index c26d1ad68105..a1f741365075 100644 > --- a/drivers/vfio/vfio.h > +++ b/drivers/vfio/vfio.h > @@ -12,18 +12,23 @@ > #include > #include > > +struct kvm; > struct iommufd_ctx; > struct iommu_group; > struct vfio_container; > > +struct vfio_kvm_reference { > + struct kvm *kvm; > + spinlock_t lock; > +}; > + > struct vfio_device_file { > struct vfio_device *device; > struct vfio_group *group; > > u8 access_granted; > u32 devid; /* only valid when iommufd is valid */ > - spinlock_t kvm_ref_lock; /* protect kvm field */ > - struct kvm *kvm; > + struct vfio_kvm_reference kvm_ref; > struct iommufd_ctx *iommufd; /* protected by struct > vfio_device_set::lock */ > }; > > @@ -88,11 +93,10 @@ struct vfio_group { > #endif > enum vfio_group_typetype; > struct mutexgroup_lock; > - struct kvm *kvm; > + struct vfio_kvm_reference kvm_ref; > struct file *opened_file; > struct blocking_notifier_head notifier; > struct iommufd_ctx *iommufd; > - spinlock_t kvm_ref_lock; > unsigned intcdev_device_open_cnt; > }; > > @@
Re: [PATCH 06/26] KVM: Drop CONFIG_KVM_VFIO and just look at KVM+VFIO
On Fri, 15 Sep 2023 17:30:58 -0700 Sean Christopherson wrote: > Drop KVM's KVM_VFIO Kconfig, and instead compile in VFIO support if > and only if VFIO itself is enabled. Similar to the recent change to have > VFIO stop looking at HAVE_KVM, compiling in support for talking to VFIO > just because the architecture supports VFIO is nonsensical. > > This fixes a bug where RISC-V doesn't select KVM_VFIO, i.e. would silently > fail to do connect KVM and VFIO, even though RISC-V supports VFIO. The > bug is benign as the only driver in all of Linux that actually uses the > KVM reference provided by VFIO is KVM-GT, which is x86/Intel specific. > > Signed-off-by: Sean Christopherson > --- > arch/arm64/kvm/Kconfig | 1 - > arch/powerpc/kvm/Kconfig | 1 - > arch/s390/kvm/Kconfig| 1 - > arch/x86/kvm/Kconfig | 1 - > virt/kvm/Kconfig | 3 --- > virt/kvm/Makefile.kvm| 4 +++- > virt/kvm/vfio.h | 2 +- > 7 files changed, 4 insertions(+), 9 deletions(-) Reviewed-by: Alex Williamson > diff --git a/arch/arm64/kvm/Kconfig b/arch/arm64/kvm/Kconfig > index 83c1e09be42e..2b5c332f157d 100644 > --- a/arch/arm64/kvm/Kconfig > +++ b/arch/arm64/kvm/Kconfig > @@ -28,7 +28,6 @@ menuconfig KVM > select KVM_MMIO > select KVM_GENERIC_DIRTYLOG_READ_PROTECT > select KVM_XFER_TO_GUEST_WORK > - select KVM_VFIO > select HAVE_KVM_EVENTFD > select HAVE_KVM_IRQFD > select HAVE_KVM_DIRTY_RING_ACQ_REL > diff --git a/arch/powerpc/kvm/Kconfig b/arch/powerpc/kvm/Kconfig > index 902611954200..c4beb49c0eb2 100644 > --- a/arch/powerpc/kvm/Kconfig > +++ b/arch/powerpc/kvm/Kconfig > @@ -22,7 +22,6 @@ config KVM > select PREEMPT_NOTIFIERS > select HAVE_KVM_EVENTFD > select HAVE_KVM_VCPU_ASYNC_IOCTL > - select KVM_VFIO > select IRQ_BYPASS_MANAGER > select HAVE_KVM_IRQ_BYPASS > select INTERVAL_TREE > diff --git a/arch/s390/kvm/Kconfig b/arch/s390/kvm/Kconfig > index 45fdf2a9b2e3..459d536116a6 100644 > --- a/arch/s390/kvm/Kconfig > +++ b/arch/s390/kvm/Kconfig > @@ -31,7 +31,6 @@ config KVM > select HAVE_KVM_IRQ_ROUTING > select HAVE_KVM_INVALID_WAKEUPS > select HAVE_KVM_NO_POLL > - select KVM_VFIO > select INTERVAL_TREE > select MMU_NOTIFIER > help > diff --git a/arch/x86/kvm/Kconfig b/arch/x86/kvm/Kconfig > index ed90f148140d..0f01e5600b5f 100644 > --- a/arch/x86/kvm/Kconfig > +++ b/arch/x86/kvm/Kconfig > @@ -45,7 +45,6 @@ config KVM > select HAVE_KVM_NO_POLL > select KVM_XFER_TO_GUEST_WORK > select KVM_GENERIC_DIRTYLOG_READ_PROTECT > - select KVM_VFIO > select INTERVAL_TREE > select HAVE_KVM_PM_NOTIFIER if PM > select KVM_GENERIC_HARDWARE_ENABLING > diff --git a/virt/kvm/Kconfig b/virt/kvm/Kconfig > index 484d0873061c..f0be3b55cea6 100644 > --- a/virt/kvm/Kconfig > +++ b/virt/kvm/Kconfig > @@ -59,9 +59,6 @@ config HAVE_KVM_MSI > config HAVE_KVM_CPU_RELAX_INTERCEPT > bool > > -config KVM_VFIO > - bool > - > config HAVE_KVM_INVALID_WAKEUPS > bool > > diff --git a/virt/kvm/Makefile.kvm b/virt/kvm/Makefile.kvm > index 2c27d5d0c367..29373b59d89a 100644 > --- a/virt/kvm/Makefile.kvm > +++ b/virt/kvm/Makefile.kvm > @@ -6,7 +6,9 @@ > KVM ?= ../../../virt/kvm > > kvm-y := $(KVM)/kvm_main.o $(KVM)/eventfd.o $(KVM)/binary_stats.o > -kvm-$(CONFIG_KVM_VFIO) += $(KVM)/vfio.o > +ifdef CONFIG_VFIO > +kvm-y += $(KVM)/vfio.o > +endif > kvm-$(CONFIG_KVM_MMIO) += $(KVM)/coalesced_mmio.o > kvm-$(CONFIG_KVM_ASYNC_PF) += $(KVM)/async_pf.o > kvm-$(CONFIG_HAVE_KVM_IRQ_ROUTING) += $(KVM)/irqchip.o > diff --git a/virt/kvm/vfio.h b/virt/kvm/vfio.h > index e130a4a03530..af475a323965 100644 > --- a/virt/kvm/vfio.h > +++ b/virt/kvm/vfio.h > @@ -2,7 +2,7 @@ > #ifndef __KVM_VFIO_H > #define __KVM_VFIO_H > > -#ifdef CONFIG_KVM_VFIO > +#if IS_ENABLED(CONFIG_KVM) && IS_ENABLED(CONFIG_VFIO) > int kvm_vfio_ops_init(void); > void kvm_vfio_ops_exit(void); > #else
Re: [PATCH v5 5/5] powerpc/bpf: use bpf_jit_binary_pack_[alloc|finalize|free]
On Thu, Sep 28, 2023 at 12:49 PM Hari Bathini wrote: > > Use bpf_jit_binary_pack_alloc in powerpc jit. The jit engine first > writes the program to the rw buffer. When the jit is done, the program > is copied to the final location with bpf_jit_binary_pack_finalize. > With multiple jit_subprogs, bpf_jit_free is called on some subprograms > that haven't got bpf_jit_binary_pack_finalize() yet. Implement custom > bpf_jit_free() like in commit 1d5f82d9dd47 ("bpf, x86: fix freeing of > not-finalized bpf_prog_pack") to call bpf_jit_binary_pack_finalize(), > if necessary. As bpf_flush_icache() is not needed anymore, remove it. > > Signed-off-by: Hari Bathini Acked-by: Song Liu
Re: [PATCH v5 4/5] powerpc/bpf: rename powerpc64_jit_data to powerpc_jit_data
On Thu, Sep 28, 2023 at 12:48 PM Hari Bathini wrote: > > powerpc64_jit_data is a misnomer as it is meant for both ppc32 and > ppc64. Rename it to powerpc_jit_data. > > Signed-off-by: Hari Bathini Acked-by: Song Liu
Re: [PATCH v5 3/5] powerpc/bpf: implement bpf_arch_text_invalidate for bpf_prog_pack
On Thu, Sep 28, 2023 at 12:49 PM Hari Bathini wrote: > > Implement bpf_arch_text_invalidate and use it to fill unused part of > the bpf_prog_pack with trap instructions when a BPF program is freed. > > Signed-off-by: Hari Bathini Acked-by: Song Liu
Re: [PATCH v5 2/5] powerpc/bpf: implement bpf_arch_text_copy
On Thu, Sep 28, 2023 at 12:48 PM Hari Bathini wrote: > > bpf_arch_text_copy is used to dump JITed binary to RX page, allowing > multiple BPF programs to share the same page. Use the newly introduced > patch_instructions() to implement it. > > Signed-off-by: Hari Bathini Acked-by: Song Liu
Re: [PATCH v5 1/5] powerpc/code-patching: introduce patch_instructions()
On Thu, Sep 28, 2023 at 12:48 PM Hari Bathini wrote: > > patch_instruction() entails setting up pte, patching the instruction, > clearing the pte and flushing the tlb. If multiple instructions need > to be patched, every instruction would have to go through the above > drill unnecessarily. Instead, introduce function patch_instructions() > that sets up the pte, clears the pte and flushes the tlb only once per > page range of instructions to be patched. This adds a slight overhead > to patch_instruction() call while improving the patching time for > scenarios where more than one instruction needs to be patched. > > Signed-off-by: Hari Bathini Acked-by: Song Liu With a nit below. [...] > +/* > + * A page is mapped and instructions that fit the page are patched. > + * Assumes 'len' to be (PAGE_SIZE - offset_in_page(addr)) or below. > + */ > +static int __do_patch_instructions_mm(u32 *addr, void *code, size_t len, > bool repeat_instr) > { > int err; > u32 *patch_addr; > @@ -307,11 +336,15 @@ static int __do_patch_instruction_mm(u32 *addr, > ppc_inst_t instr) > > orig_mm = start_using_temp_mm(patching_mm); > > - err = __patch_instruction(addr, instr, patch_addr); > + /* Single instruction case. */ > + if (len == 0) { > + err = __patch_instruction(addr, *(ppc_inst_t *)code, > patch_addr); len == 0 for single instruction is a little weird to me. How about we just use len == 4 or 8 depending on the instruction to patch? Thanks, Song [...]
RE: [PATCHv7 2/4] powerpc/setup: Loosen the mapping between cpu logical id and its seq in dt
Hi Pingfan, + avail = intserv_node->avail; + nthreads = intserv_node->len / sizeof(int); + for (j = 0; j < nthreads && cpu < nr_cpu_ids; j++) { set_cpu_present(cpu, avail); set_cpu_possible(cpu, true); - cpu_to_phys_id[cpu] = be32_to_cpu(intserv[j]); + cpu_to_phys_id[cpu] = be32_to_cpu(intserv_node->intserv[j]); + DBG("thread %d -> cpu %d (hard id %d)\n", + j, cpu, be32_to_cpu(intserv[j])); Intserv is not defined. Should "be32_to_cpu(intserv_node->intserv[j])? cpu++; } + } -Original Message- From: Pingfan Liu Sent: Monday, September 25, 2023 2:54 AM To: linuxppc-dev@lists.ozlabs.org Cc: Pingfan Liu ; Michael Ellerman ; Nicholas Piggin ; Christophe Leroy ; Mahesh Salgaonkar ; Wen Xiong ; Baoquan He ; Ming Lei ; ke...@lists.infradead.org Subject: [EXTERNAL] [PATCHv7 2/4] powerpc/setup: Loosen the mapping between cpu logical id and its seq in dt *** Idea *** For kexec -p, the boot cpu can be not the cpu0, this causes the problem of allocating memory for paca_ptrs[]. However, in theory, there is no requirement to assign cpu's logical id as its present sequence in the device tree. But there is something like cpu_first_thread_sibling(), which makes assumption on the mapping inside a core. Hence partially loosening the mapping, i.e. unbind the mapping of core while keep the mapping inside a core. *** Implement *** At this early stage, there are plenty of memory to utilize. Hence, this patch allocates interim memory to link the cpu info on a list, then reorder cpus by changing the list head. As a result, there is a rotate shift between the sequence number in dt and the cpu logical number. *** Result *** After this patch, a boot-cpu's logical id will always be mapped into the range [0,threads_per_core). Besides this, at this phase, all threads in the boot core are forced to be onlined. This restriction will be lifted in a later patch with extra effort. Signed-off-by: Pingfan Liu Cc: Michael Ellerman Cc: Nicholas Piggin Cc: Christophe Leroy Cc: Mahesh Salgaonkar Cc: Wen Xiong Cc: Baoquan He Cc: Ming Lei Cc: ke...@lists.infradead.org To: linuxppc-dev@lists.ozlabs.org --- arch/powerpc/kernel/prom.c | 25 + arch/powerpc/kernel/setup-common.c | 87 +++--- 2 files changed, 85 insertions(+), 27 deletions(-) diff --git a/arch/powerpc/kernel/prom.c b/arch/powerpc/kernel/prom.c index ec82f5bda908..87272a2d8c10 100644 --- a/arch/powerpc/kernel/prom.c +++ b/arch/powerpc/kernel/prom.c @@ -76,7 +76,9 @@ u64 ppc64_rma_size; unsigned int boot_cpu_node_count __ro_after_init; #endif static phys_addr_t first_memblock_size; +#ifdef CONFIG_SMP static int __initdata boot_cpu_count; +#endif static int __init early_parse_mem(char *p) { @@ -331,8 +333,7 @@ static int __init early_init_dt_scan_cpus(unsigned long node, const __be32 *intserv; int i, nthreads; int len; - int found = -1; - int found_thread = 0; + bool found = false; /* We are scanning "cpu" nodes only */ if (type == NULL || strcmp(type, "cpu") != 0) @@ -355,8 +356,15 @@ static int __init early_init_dt_scan_cpus(unsigned long node, for (i = 0; i < nthreads; i++) { if (be32_to_cpu(intserv[i]) == fdt_boot_cpuid_phys(initial_boot_params)) { - found = boot_cpu_count; - found_thread = i; + /* +* always map the boot-cpu logical id into the +* range of [0, thread_per_core) +*/ + boot_cpuid = i; + found = true; + /* This works around the hole in paca_ptrs[]. */ + if (nr_cpu_ids < nthreads) + set_nr_cpu_ids(nthreads); } #ifdef CONFIG_SMP /* logical cpu id is always 0 on UP kernels */ @@ -365,14 +373,13 @@ static int __init early_init_dt_scan_cpus(unsigned long node, } /* Not the boot CPU */ - if (found < 0) + if (!found) return 0; - DBG("boot cpu: logical %d physical %d\n", found, - be32_to_cpu(intserv[found_thread])); - boot_cpuid = found; + DBG("boot cpu: logical %d physical %d\n", boot_cpuid, + be32_to_cpu(intserv[boot_cpuid])); - boot_cpu_hwid = be32_to_cpu(intserv[found_thread]); + boot_cpu_hwid = be32_to_cpu(intserv[boot_cpuid]); /* * PAPR defines "logical" PVR values for cpus that diff --git a/arch/powerpc/kernel/setup-common.c b/arch/powerpc/kernel/setup-common.c index 1b19a9815672..f6d32324b5a5 100644 --- a/arch/powerpc/kernel/setup-common.c +++
Re: [PATCH v4 4/5] powerpc/code-patching: introduce patch_instructions()
On 26/09/23 12:21 pm, Christophe Leroy wrote: Le 26/09/2023 à 00:50, Song Liu a écrit : On Fri, Sep 8, 2023 at 6:28 AM Hari Bathini wrote: patch_instruction() entails setting up pte, patching the instruction, clearing the pte and flushing the tlb. If multiple instructions need to be patched, every instruction would have to go through the above drill unnecessarily. Instead, introduce function patch_instructions() that sets up the pte, clears the pte and flushes the tlb only once per page range of instructions to be patched. This adds a slight overhead to patch_instruction() call while improving the patching time for scenarios where more than one instruction needs to be patched. Signed-off-by: Hari Bathini I didn't see this one when I reviewed 1/5. Please ignore that comment. If I remember correctry, patch 1 introduces a huge performance degradation, which gets then improved with this patch. As I said before, I'd expect patch 4 to go first then get bpf_arch_text_copy() be implemented with patch_instructions() directly. Thanks for the reviews, Christophe & Song. Posted v5 based on your inputs. - Hari
[PATCH v5 5/5] powerpc/bpf: use bpf_jit_binary_pack_[alloc|finalize|free]
Use bpf_jit_binary_pack_alloc in powerpc jit. The jit engine first writes the program to the rw buffer. When the jit is done, the program is copied to the final location with bpf_jit_binary_pack_finalize. With multiple jit_subprogs, bpf_jit_free is called on some subprograms that haven't got bpf_jit_binary_pack_finalize() yet. Implement custom bpf_jit_free() like in commit 1d5f82d9dd47 ("bpf, x86: fix freeing of not-finalized bpf_prog_pack") to call bpf_jit_binary_pack_finalize(), if necessary. As bpf_flush_icache() is not needed anymore, remove it. Signed-off-by: Hari Bathini --- arch/powerpc/net/bpf_jit.h| 18 ++--- arch/powerpc/net/bpf_jit_comp.c | 106 ++ arch/powerpc/net/bpf_jit_comp32.c | 13 ++-- arch/powerpc/net/bpf_jit_comp64.c | 10 +-- 4 files changed, 96 insertions(+), 51 deletions(-) diff --git a/arch/powerpc/net/bpf_jit.h b/arch/powerpc/net/bpf_jit.h index 72b7bb34fade..cdea5dccaefe 100644 --- a/arch/powerpc/net/bpf_jit.h +++ b/arch/powerpc/net/bpf_jit.h @@ -36,9 +36,6 @@ EMIT(PPC_RAW_BRANCH(offset)); \ } while (0) -/* bl (unconditional 'branch' with link) */ -#define PPC_BL(dest) EMIT(PPC_RAW_BL((dest) - (unsigned long)(image + ctx->idx))) - /* "cond" here covers BO:BI fields. */ #define PPC_BCC_SHORT(cond, dest)\ do { \ @@ -147,12 +144,6 @@ struct codegen_context { #define BPF_FIXUP_LEN 2 /* Two instructions => 8 bytes */ #endif -static inline void bpf_flush_icache(void *start, void *end) -{ - smp_wmb(); /* smp write barrier */ - flush_icache_range((unsigned long)start, (unsigned long)end); -} - static inline bool bpf_is_seen_register(struct codegen_context *ctx, int i) { return ctx->seen & (1 << (31 - i)); @@ -169,16 +160,17 @@ static inline void bpf_clear_seen_register(struct codegen_context *ctx, int i) } void bpf_jit_init_reg_mapping(struct codegen_context *ctx); -int bpf_jit_emit_func_call_rel(u32 *image, struct codegen_context *ctx, u64 func); -int bpf_jit_build_body(struct bpf_prog *fp, u32 *image, struct codegen_context *ctx, +int bpf_jit_emit_func_call_rel(u32 *image, u32 *fimage, struct codegen_context *ctx, u64 func); +int bpf_jit_build_body(struct bpf_prog *fp, u32 *image, u32 *fimage, struct codegen_context *ctx, u32 *addrs, int pass, bool extra_pass); void bpf_jit_build_prologue(u32 *image, struct codegen_context *ctx); void bpf_jit_build_epilogue(u32 *image, struct codegen_context *ctx); void bpf_jit_realloc_regs(struct codegen_context *ctx); int bpf_jit_emit_exit_insn(u32 *image, struct codegen_context *ctx, int tmp_reg, long exit_addr); -int bpf_add_extable_entry(struct bpf_prog *fp, u32 *image, int pass, struct codegen_context *ctx, - int insn_idx, int jmp_off, int dst_reg); +int bpf_add_extable_entry(struct bpf_prog *fp, u32 *image, u32 *fimage, int pass, + struct codegen_context *ctx, int insn_idx, + int jmp_off, int dst_reg); #endif diff --git a/arch/powerpc/net/bpf_jit_comp.c b/arch/powerpc/net/bpf_jit_comp.c index e7ca270a39d5..a79d7c478074 100644 --- a/arch/powerpc/net/bpf_jit_comp.c +++ b/arch/powerpc/net/bpf_jit_comp.c @@ -44,9 +44,12 @@ int bpf_jit_emit_exit_insn(u32 *image, struct codegen_context *ctx, int tmp_reg, } struct powerpc_jit_data { - struct bpf_binary_header *header; + /* address of rw header */ + struct bpf_binary_header *hdr; + /* address of ro final header */ + struct bpf_binary_header *fhdr; u32 *addrs; - u8 *image; + u8 *fimage; u32 proglen; struct codegen_context ctx; }; @@ -67,11 +70,14 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *fp) struct codegen_context cgctx; int pass; int flen; - struct bpf_binary_header *bpf_hdr; + struct bpf_binary_header *fhdr = NULL; + struct bpf_binary_header *hdr = NULL; struct bpf_prog *org_fp = fp; struct bpf_prog *tmp_fp; bool bpf_blinded = false; bool extra_pass = false; + u8 *fimage = NULL; + u32 *fcode_base; u32 extable_len; u32 fixup_len; @@ -101,9 +107,16 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *fp) addrs = jit_data->addrs; if (addrs) { cgctx = jit_data->ctx; - image = jit_data->image; - bpf_hdr = jit_data->header; + /* +* JIT compiled to a writable location (image/code_base) first. +* It is then moved to the readonly final location (fimage/fcode_base) +* using instruction patching. +*/ + fimage = jit_data->fimage; + fhdr = jit_data->fhdr; proglen =
[PATCH v5 4/5] powerpc/bpf: rename powerpc64_jit_data to powerpc_jit_data
powerpc64_jit_data is a misnomer as it is meant for both ppc32 and ppc64. Rename it to powerpc_jit_data. Signed-off-by: Hari Bathini --- arch/powerpc/net/bpf_jit_comp.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/powerpc/net/bpf_jit_comp.c b/arch/powerpc/net/bpf_jit_comp.c index ecd7cffbbe28..e7ca270a39d5 100644 --- a/arch/powerpc/net/bpf_jit_comp.c +++ b/arch/powerpc/net/bpf_jit_comp.c @@ -43,7 +43,7 @@ int bpf_jit_emit_exit_insn(u32 *image, struct codegen_context *ctx, int tmp_reg, return 0; } -struct powerpc64_jit_data { +struct powerpc_jit_data { struct bpf_binary_header *header; u32 *addrs; u8 *image; @@ -63,7 +63,7 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *fp) u8 *image = NULL; u32 *code_base; u32 *addrs; - struct powerpc64_jit_data *jit_data; + struct powerpc_jit_data *jit_data; struct codegen_context cgctx; int pass; int flen; -- 2.41.0
[PATCH v5 3/5] powerpc/bpf: implement bpf_arch_text_invalidate for bpf_prog_pack
Implement bpf_arch_text_invalidate and use it to fill unused part of the bpf_prog_pack with trap instructions when a BPF program is freed. Signed-off-by: Hari Bathini --- arch/powerpc/net/bpf_jit_comp.c | 15 +++ 1 file changed, 15 insertions(+) diff --git a/arch/powerpc/net/bpf_jit_comp.c b/arch/powerpc/net/bpf_jit_comp.c index c740eac8d584..ecd7cffbbe28 100644 --- a/arch/powerpc/net/bpf_jit_comp.c +++ b/arch/powerpc/net/bpf_jit_comp.c @@ -292,3 +292,18 @@ void *bpf_arch_text_copy(void *dst, void *src, size_t len) return err ? ERR_PTR(err) : dst; } + +int bpf_arch_text_invalidate(void *dst, size_t len) +{ + u32 insn = BREAKPOINT_INSTRUCTION; + int ret; + + if (WARN_ON_ONCE(core_kernel_text((unsigned long)dst))) + return -EINVAL; + + mutex_lock(_mutex); + ret = patch_instructions(dst, , len, true); + mutex_unlock(_mutex); + + return ret; +} -- 2.41.0
[PATCH v5 2/5] powerpc/bpf: implement bpf_arch_text_copy
bpf_arch_text_copy is used to dump JITed binary to RX page, allowing multiple BPF programs to share the same page. Use the newly introduced patch_instructions() to implement it. Signed-off-by: Hari Bathini --- arch/powerpc/net/bpf_jit_comp.c | 20 +++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/arch/powerpc/net/bpf_jit_comp.c b/arch/powerpc/net/bpf_jit_comp.c index 37043dfc1add..c740eac8d584 100644 --- a/arch/powerpc/net/bpf_jit_comp.c +++ b/arch/powerpc/net/bpf_jit_comp.c @@ -13,9 +13,13 @@ #include #include #include -#include +#include +#include #include +#include +#include + #include "bpf_jit.h" static void bpf_jit_fill_ill_insns(void *area, unsigned int size) @@ -274,3 +278,17 @@ int bpf_add_extable_entry(struct bpf_prog *fp, u32 *image, int pass, struct code ctx->exentry_idx++; return 0; } + +void *bpf_arch_text_copy(void *dst, void *src, size_t len) +{ + int err; + + if (WARN_ON_ONCE(core_kernel_text((unsigned long)dst))) + return ERR_PTR(-EINVAL); + + mutex_lock(_mutex); + err = patch_instructions(dst, src, len, false); + mutex_unlock(_mutex); + + return err ? ERR_PTR(err) : dst; +} -- 2.41.0
[PATCH v5 1/5] powerpc/code-patching: introduce patch_instructions()
patch_instruction() entails setting up pte, patching the instruction, clearing the pte and flushing the tlb. If multiple instructions need to be patched, every instruction would have to go through the above drill unnecessarily. Instead, introduce function patch_instructions() that sets up the pte, clears the pte and flushes the tlb only once per page range of instructions to be patched. This adds a slight overhead to patch_instruction() call while improving the patching time for scenarios where more than one instruction needs to be patched. Signed-off-by: Hari Bathini --- arch/powerpc/include/asm/code-patching.h | 1 + arch/powerpc/lib/code-patching.c | 93 +--- 2 files changed, 85 insertions(+), 9 deletions(-) diff --git a/arch/powerpc/include/asm/code-patching.h b/arch/powerpc/include/asm/code-patching.h index 3f881548fb61..43a4aedfa703 100644 --- a/arch/powerpc/include/asm/code-patching.h +++ b/arch/powerpc/include/asm/code-patching.h @@ -74,6 +74,7 @@ int create_cond_branch(ppc_inst_t *instr, const u32 *addr, int patch_branch(u32 *addr, unsigned long target, int flags); int patch_instruction(u32 *addr, ppc_inst_t instr); int raw_patch_instruction(u32 *addr, ppc_inst_t instr); +int patch_instructions(void *addr, void *code, size_t len, bool repeat_instr); static inline unsigned long patch_site_addr(s32 *site) { diff --git a/arch/powerpc/lib/code-patching.c b/arch/powerpc/lib/code-patching.c index b00112d7ad46..4ff002bc41f6 100644 --- a/arch/powerpc/lib/code-patching.c +++ b/arch/powerpc/lib/code-patching.c @@ -278,7 +278,36 @@ static void unmap_patch_area(unsigned long addr) flush_tlb_kernel_range(addr, addr + PAGE_SIZE); } -static int __do_patch_instruction_mm(u32 *addr, ppc_inst_t instr) +static int __patch_instructions(u32 *patch_addr, void *code, size_t len, bool repeat_instr) +{ + unsigned long start = (unsigned long)patch_addr; + + /* Repeat instruction */ + if (repeat_instr) { + ppc_inst_t instr = ppc_inst_read(code); + + if (ppc_inst_prefixed(instr)) { + u64 val = ppc_inst_as_ulong(instr); + + memset64((uint64_t *)patch_addr, val, len / 8); + } else { + u32 val = ppc_inst_val(instr); + + memset32(patch_addr, val, len / 4); + } + } else + memcpy(patch_addr, code, len); + + smp_wmb(); /* smp write barrier */ + flush_icache_range(start, start + len); + return 0; +} + +/* + * A page is mapped and instructions that fit the page are patched. + * Assumes 'len' to be (PAGE_SIZE - offset_in_page(addr)) or below. + */ +static int __do_patch_instructions_mm(u32 *addr, void *code, size_t len, bool repeat_instr) { int err; u32 *patch_addr; @@ -307,11 +336,15 @@ static int __do_patch_instruction_mm(u32 *addr, ppc_inst_t instr) orig_mm = start_using_temp_mm(patching_mm); - err = __patch_instruction(addr, instr, patch_addr); + /* Single instruction case. */ + if (len == 0) { + err = __patch_instruction(addr, *(ppc_inst_t *)code, patch_addr); - /* hwsync performed by __patch_instruction (sync) if successful */ - if (err) - mb(); /* sync */ + /* hwsync performed by __patch_instruction (sync) if successful */ + if (err) + mb(); /* sync */ + } else + err = __patch_instructions(patch_addr, code, len, repeat_instr); /* context synchronisation performed by __patch_instruction (isync or exception) */ stop_using_temp_mm(patching_mm, orig_mm); @@ -328,7 +361,11 @@ static int __do_patch_instruction_mm(u32 *addr, ppc_inst_t instr) return err; } -static int __do_patch_instruction(u32 *addr, ppc_inst_t instr) +/* + * A page is mapped and instructions that fit the page are patched. + * Assumes 'len' to be (PAGE_SIZE - offset_in_page(addr)) or below. + */ +static int __do_patch_instructions(u32 *addr, void *code, size_t len, bool repeat_instr) { int err; u32 *patch_addr; @@ -345,7 +382,11 @@ static int __do_patch_instruction(u32 *addr, ppc_inst_t instr) if (radix_enabled()) asm volatile("ptesync": : :"memory"); - err = __patch_instruction(addr, instr, patch_addr); + /* Single instruction case. */ + if (len == 0) + err = __patch_instruction(addr, *(ppc_inst_t *)code, patch_addr); + else + err = __patch_instructions(patch_addr, code, len, repeat_instr); pte_clear(_mm, text_poke_addr, pte); flush_tlb_kernel_range(text_poke_addr, text_poke_addr + PAGE_SIZE); @@ -369,15 +410,49 @@ int patch_instruction(u32 *addr, ppc_inst_t instr) local_irq_save(flags); if (mm_patch_enabled()) - err = __do_patch_instruction_mm(addr, instr); +
[PATCH v5 0/5] powerpc/bpf: use BPF prog pack allocator
Most BPF programs are small, but they consume a page each. For systems with busy traffic and many BPF programs, this may also add significant pressure on instruction TLB. High iTLB pressure usually slows down the whole system causing visible performance degradation for production workloads. bpf_prog_pack, a customized allocator that packs multiple bpf programs into preallocated memory chunks, was proposed [1] to address it. This series extends this support on powerpc. Both bpf_arch_text_copy() & bpf_arch_text_invalidate() functions, needed for this support depend on instruction patching in text area. Currently, patch_instruction() supports patching only one instruction at a time. The first patch introduces patch_instructions() function to enable patching more than one instruction at a time. This helps in avoiding performance degradation while JITing bpf programs. Patches 2 & 3 implement the above mentioned arch specific functions using patch_instructions(). Patch 4 fixes a misnomer in bpf JITing code. The last patch enables the use of BPF prog pack allocator on powerpc and also, ensures cleanup is handled gracefully. [1] https://lore.kernel.org/bpf/20220204185742.271030-1-s...@kernel.org/ Changes in v5: * Moved introduction of patch_instructions() as 1st patch in series. * Improved patch_instructions() to use memset & memcpy. * Fixed the misnomer in JITing code as a separate patch. * Removed unused bpf_flush_icache() function. Changes in v4: * Updated bpf_patch_instructions() definition in patch 1/5 so that it doesn't have to be updated again in patch 2/5. * Addressed Christophe's comment on bpf_arch_text_invalidate() return value in patch 2/5. Changes in v3: * Fixed segfault issue observed on ppc32 due to inaccurate offset calculation for branching. * Tried to minimize the performance impact for patch_instruction() with the introduction of patch_instructions(). * Corrected uses of u32* vs ppc_instr_t. * Moved the change that introduces patch_instructions() to after enabling bpf_prog_pack support. * Added few comments to improve code readability. Hari Bathini (5): powerpc/code-patching: introduce patch_instructions() powerpc/bpf: implement bpf_arch_text_copy powerpc/bpf: implement bpf_arch_text_invalidate for bpf_prog_pack powerpc/bpf: rename powerpc64_jit_data to powerpc_jit_data powerpc/bpf: use bpf_jit_binary_pack_[alloc|finalize|free] arch/powerpc/include/asm/code-patching.h | 1 + arch/powerpc/lib/code-patching.c | 93 +-- arch/powerpc/net/bpf_jit.h | 18 +-- arch/powerpc/net/bpf_jit_comp.c | 145 ++- arch/powerpc/net/bpf_jit_comp32.c| 13 +- arch/powerpc/net/bpf_jit_comp64.c| 10 +- 6 files changed, 217 insertions(+), 63 deletions(-) -- 2.41.0
Re: [PATCH 00/15] sysctl: Remove sentinel elements from drivers
Le 28/09/2023 à 15:21, Joel Granados via B4 Relay a écrit : > From: Joel Granados Automatic test fails on powerpc, see https://patchwork.ozlabs.org/project/linuxppc-dev/patch/20230928-jag-sysctl_remove_empty_elem_drivers-v1-15-e59120fca...@samsung.com/ Kernel attempted to read user page (1a111316) - exploit attempt? (uid: 0) BUG: Unable to handle kernel data access on read at 0x1a111316 Faulting instruction address: 0xc0545338 Oops: Kernel access of bad area, sig: 11 [#1] BE PAGE_SIZE=4K PowerPC 44x Platform Modules linked in: CPU: 0 PID: 1 Comm: swapper Not tainted 6.5.0-rc6-gdef13277bacb #1 Hardware name: amcc,bamboo 440GR Rev. B 0x422218d3 PowerPC 44x Platform NIP: c0545338 LR: c0548468 CTR: REGS: c084fae0 TRAP: 0300 Not tainted (6.5.0-rc6-gdef13277bacb) MSR: 00021000 CR: 84004288 XER: DEAR: 1a111316 ESR: GPR00: c0548468 c084fbd0 c0888000 c084fc99 c084fc7c 1a110316 000a GPR08: c084fd18 1a111316 04ff 22000282 c00027c0 GPR16: c004 c003d544 0001 c003eb2c 096023d4 GPR24: c0636502 c0636502 c084fc74 c0588510 c084fc68 c084fc7c c084fc99 0002 NIP [c0545338] string+0x78/0x148 LR [c0548468] vsnprintf+0x3d8/0x824 Call Trace: [c084fbd0] [c084fc7c] 0xc084fc7c (unreliable) [c084fbe0] [c0548468] vsnprintf+0x3d8/0x824 [c084fc30] [c0072dec] vprintk_store+0x17c/0x4c8 [c084fcc0] [c007322c] vprintk_emit+0xf4/0x2a0 [c084fd00] [c0073d04] _printk+0x60/0x88 [c084fd40] [c01ab63c] sysctl_err+0x78/0xa4 [c084fd80] [c01ab404] __register_sysctl_table+0x6a0/0x6c4 [c084fde0] [c06a585c] __register_sysctl_init+0x30/0x78 [c084fe00] [c06a8cc8] tty_init+0x44/0x168 [c084fe30] [c00023c4] do_one_initcall+0x64/0x2a0 [c084fea0] [c068f060] kernel_init_freeable+0x184/0x230 [c084fee0] [c00027e4] kernel_init+0x24/0x124 [c084ff00] [c000f1fc] ret_from_kernel_user_thread+0x14/0x1c --- interrupt: 0 at 0x0 NIP: LR: CTR: REGS: c084ff10 TRAP: Not tainted (6.5.0-rc6-gdef13277bacb) MSR: <> CR: XER: GPR00: GPR08: GPR16: GPR24: NIP [] 0x0 LR [] 0x0 --- interrupt: 0 Code: 91610008 90e1000c 4bffd0b5 80010014 38210010 7c0803a6 4e800020 409d0008 9923 38630001 38840001 4240ffd0 <7d2a20ae> 7f851840 5528063e 2c08 ---[ end trace ]--- note: swapper[1] exited with irqs disabled Kernel panic - not syncing: Attempted to kill init! exitcode=0x000b > > What? > These commits remove the sentinel element (last empty element) from the > sysctl arrays of all the files under the "drivers/" directory that use a > sysctl array for registration. The merging of the preparation patches > (in https://lore.kernel.org/all/zo5yx5jfoggi%2f...@bombadil.infradead.org/) > to mainline allows us to just remove sentinel elements without changing > behavior (more info here [1]). > > These commits are part of a bigger set (here > https://github.com/Joelgranados/linux/tree/tag/sysctl_remove_empty_elem_V4) > that remove the ctl_table sentinel. Make the review process easier by > chunking the commits into manageable pieces. Each chunk can be reviewed > separately without noise from parallel sets. > > Now that the architecture chunk has been mostly reviewed [6], we send > the "drivers/" directory. Once this one is done, it will be follwed by > "fs/*", "kernel/*", "net/*" and miscellaneous. The final set will remove > the unneeded check for ->procname == NULL. > > Why? > By removing the sysctl sentinel elements we avoid kernel bloat as > ctl_table arrays get moved out of kernel/sysctl.c into their own > respective subsystems. This move was started long ago to avoid merge > conflicts; the sentinel removal bit came after Mathew Wilcox suggested > it to avoid bloating the kernel by one element as arrays moved out. This > patchset will reduce the overall build time size of the kernel and run > time memory bloat by about ~64 bytes per declared ctl_table array. I > have consolidated some links that shed light on the history of this > effort [2]. > > Testing: > * Ran sysctl selftests (./tools/testing/selftests/sysctl/sysctl.sh) > * Ran this through 0-day with no errors or warnings > > Size saving after removing all sentinels: >These are the bytes that we save after removing all the sentinels >(this plus all the other chunks). I included them to get an idea of >how much memory we are talking about. > * bloat-o-meter: > - The "yesall" configuration
Re: [PATCH 14/15] hyper-v/azure: Remove now superfluous sentinel element from ctl_table array
Please change the prefix to "Drivers: hv:" in the subject line in the two patches. On Thu, Sep 28, 2023 at 03:21:39PM +0200, Joel Granados via B4 Relay wrote: > From: Joel Granados > > This commit comes at the tail end of a greater effort to remove the > empty elements at the end of the ctl_table arrays (sentinels) which > will reduce the overall build time size of the kernel and run time > memory bloat by ~64 bytes per sentinel (further information Link : > https://lore.kernel.org/all/zo5yx5jfoggi%2f...@bombadil.infradead.org/) > > Remove sentinel from hv_ctl_table > > Signed-off-by: Joel Granados > --- > drivers/hv/hv_common.c | 3 +-- > 1 file changed, 1 insertion(+), 2 deletions(-) > > diff --git a/drivers/hv/hv_common.c b/drivers/hv/hv_common.c > index ccad7bca3fd3..bc7d678030aa 100644 > --- a/drivers/hv/hv_common.c > +++ b/drivers/hv/hv_common.c > @@ -147,8 +147,7 @@ static struct ctl_table hv_ctl_table[] = { > .proc_handler = proc_dointvec_minmax, > .extra1 = SYSCTL_ZERO, > .extra2 = SYSCTL_ONE > - }, > - {} > + } Please keep the comma at the end. > }; > > static int hv_die_panic_notify_crash(struct notifier_block *self, > > -- > 2.30.2 >
Re: [PATCH 13/15] raid: Remove now superfluous sentinel element from ctl_table array
On Thu, Sep 28, 2023 at 6:20 AM Joel Granados via B4 Relay wrote: > > From: Joel Granados > > This commit comes at the tail end of a greater effort to remove the > empty elements at the end of the ctl_table arrays (sentinels) which > will reduce the overall build time size of the kernel and run time > memory bloat by ~64 bytes per sentinel (further information Link : > https://lore.kernel.org/all/zo5yx5jfoggi%2f...@bombadil.infradead.org/) > > Remove sentinel from raid_table > > Signed-off-by: Joel Granados > --- > drivers/md/md.c | 3 +-- > 1 file changed, 1 insertion(+), 2 deletions(-) > > diff --git a/drivers/md/md.c b/drivers/md/md.c > index a104a025084d..3866d8f754a0 100644 > --- a/drivers/md/md.c > +++ b/drivers/md/md.c > @@ -304,8 +304,7 @@ static struct ctl_table raid_table[] = { > .maxlen = sizeof(int), > .mode = S_IRUGO|S_IWUSR, > .proc_handler = proc_dointvec, > - }, > - { } > + } > }; Please keep "}," as Greg suggested. Otherwise, Acked-by: Song Liu Thanks, Song
Re: [PATCH 01/15] cdrom: Remove now superfluous sentinel element from ctl_table array
On Thu, Sep 28, 2023 at 03:21:26PM +0200, Joel Granados via B4 Relay wrote: > From: Joel Granados > > This commit comes at the tail end of a greater effort to remove the > empty elements at the end of the ctl_table arrays (sentinels) which > will reduce the overall build time size of the kernel and run time > memory bloat by ~64 bytes per sentinel (further information Link : > https://lore.kernel.org/all/zo5yx5jfoggi%2f...@bombadil.infradead.org/) > > Remove sentinel element from cdrom_table > > Signed-off-by: Joel Granados > --- > drivers/cdrom/cdrom.c | 3 +-- > 1 file changed, 1 insertion(+), 2 deletions(-) > > diff --git a/drivers/cdrom/cdrom.c b/drivers/cdrom/cdrom.c > index cc2839805983..451907ade389 100644 > --- a/drivers/cdrom/cdrom.c > +++ b/drivers/cdrom/cdrom.c > @@ -3654,8 +3654,7 @@ static struct ctl_table cdrom_table[] = { > .maxlen = sizeof(int), > .mode = 0644, > .proc_handler = cdrom_sysctl_handler > - }, > - { } > + } You should have the final entry as "}," so as to make any future additions to the list to only contain that entry, that's long been the kernel style for lists like this. So your patches will just remove one line, not 2 and add 1, making it a smaller diff. thanks, greg k-h
[PATCH 06/15] parport: Remove the now superfluous sentinel element from ctl_table array
From: Joel Granados This commit comes at the tail end of a greater effort to remove the empty elements at the end of the ctl_table arrays (sentinels) which will reduce the overall build time size of the kernel and run time memory bloat by ~64 bytes per sentinel (further information Link : https://lore.kernel.org/all/zo5yx5jfoggi%2f...@bombadil.infradead.org/) Remove the unneeded ctl_tables that were used to register intermediate parport directories; only the path is needed at this point. From parport_device_sysctl_table we removed: devices_root_dir, port_dir, parport_dir and dev_dir. From parport_default_sysctl_table we removed: default_dir, parport_dir and dev_dir. Reduce the size by one of the ctl_table arrays that were not removed Assign different sizes to the vars array in parport_sysctl_table depending on CONFIG_PARPORT_1284; this is necessary now that the sysctl register function uses ARRAY_SIZE to calculate the elements within. Remove the sentinel element from parport_sysctl_template, parport_device_sysctl_table and parport_default_sysctl_table. Signed-off-by: Joel Granados --- drivers/parport/procfs.c | 42 ++ 1 file changed, 18 insertions(+), 24 deletions(-) diff --git a/drivers/parport/procfs.c b/drivers/parport/procfs.c index 4e5b972c3e26..4118b3e52223 100644 --- a/drivers/parport/procfs.c +++ b/drivers/parport/procfs.c @@ -259,8 +259,12 @@ PARPORT_MAX_SPINTIME_VALUE; struct parport_sysctl_table { struct ctl_table_header *port_header; struct ctl_table_header *devices_header; - struct ctl_table vars[12]; - struct ctl_table device_dir[2]; +#ifdef CONFIG_PARPORT_1284 + struct ctl_table vars[10]; +#else + struct ctl_table vars[5]; +#endif /* IEEE 1284 support */ + struct ctl_table device_dir[1]; }; static const struct parport_sysctl_table parport_sysctl_template = { @@ -303,9 +307,9 @@ static const struct parport_sysctl_table parport_sysctl_template = { .maxlen = 0, .mode = 0444, .proc_handler = do_hardware_modes - }, + } #ifdef CONFIG_PARPORT_1284 - { + , { .procname = "autoprobe", .data = NULL, .maxlen = 0, @@ -339,9 +343,8 @@ static const struct parport_sysctl_table parport_sysctl_template = { .maxlen = 0, .mode = 0444, .proc_handler = do_autoprobe - }, + } #endif /* IEEE 1284 support */ - {} }, { { @@ -350,20 +353,15 @@ static const struct parport_sysctl_table parport_sysctl_template = { .maxlen = 0, .mode = 0444, .proc_handler = do_active_device - }, - {} + } }, }; struct parport_device_sysctl_table { struct ctl_table_header *sysctl_header; - struct ctl_table vars[2]; - struct ctl_table device_dir[2]; - struct ctl_table devices_root_dir[2]; - struct ctl_table port_dir[2]; - struct ctl_table parport_dir[2]; - struct ctl_table dev_dir[2]; + struct ctl_table vars[1]; + struct ctl_table device_dir[1]; }; static const struct parport_device_sysctl_table @@ -378,8 +376,7 @@ parport_device_sysctl_template = { .proc_handler = proc_doulongvec_ms_jiffies_minmax, .extra1 = (void*) _min_timeslice_value, .extra2 = (void*) _max_timeslice_value - }, - {} + } }, { { @@ -387,18 +384,14 @@ parport_device_sysctl_template = { .data = NULL, .maxlen = 0, .mode = 0555, - }, - {} + } } }; struct parport_default_sysctl_table { struct ctl_table_header *sysctl_header; - struct ctl_table vars[3]; - struct ctl_table default_dir[2]; - struct ctl_table parport_dir[2]; - struct ctl_table dev_dir[2]; + struct ctl_table vars[2]; }; static struct parport_default_sysctl_table @@ -422,8 +415,7 @@ parport_default_sysctl_table = { .proc_handler = proc_dointvec_minmax, .extra1 = (void*) _min_spintime_value, .extra2 = (void*) _max_spintime_value - }, - {} + } } }; @@ -443,7 +435,9 @@ int parport_proc_register(struct parport *port) t->vars[0].data = >spintime; for (i = 0; i < 5; i++) { t->vars[i].extra1
[PATCH 02/15] hpet: Remove now superfluous sentinel element from ctl_table array
From: Joel Granados This commit comes at the tail end of a greater effort to remove the empty elements at the end of the ctl_table arrays (sentinels) which will reduce the overall build time size of the kernel and run time memory bloat by ~64 bytes per sentinel (further information Link : https://lore.kernel.org/all/zo5yx5jfoggi%2f...@bombadil.infradead.org/) Remove the last empty element from hpet_table. Signed-off-by: Joel Granados --- drivers/char/hpet.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/char/hpet.c b/drivers/char/hpet.c index ee71376f174b..11f466fea5ed 100644 --- a/drivers/char/hpet.c +++ b/drivers/char/hpet.c @@ -727,8 +727,7 @@ static struct ctl_table hpet_table[] = { .maxlen = sizeof(int), .mode = 0644, .proc_handler = proc_dointvec, -}, - {} + } }; static struct ctl_table_header *sysctl_header; -- 2.30.2
[PATCH 08/15] infiniband: Remove the now superfluous sentinel element from ctl_table array
From: Joel Granados This commit comes at the tail end of a greater effort to remove the empty elements at the end of the ctl_table arrays (sentinels) which will reduce the overall build time size of the kernel and run time memory bloat by ~64 bytes per sentinel (further information Link : https://lore.kernel.org/all/zo5yx5jfoggi%2f...@bombadil.infradead.org/) Remove sentinel from iwcm_ctl_table and ucma_ctl_table Signed-off-by: Joel Granados --- drivers/infiniband/core/iwcm.c | 3 +-- drivers/infiniband/core/ucma.c | 3 +-- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/drivers/infiniband/core/iwcm.c b/drivers/infiniband/core/iwcm.c index 2b47073c61a6..fefb9ae75789 100644 --- a/drivers/infiniband/core/iwcm.c +++ b/drivers/infiniband/core/iwcm.c @@ -110,8 +110,7 @@ static struct ctl_table iwcm_ctl_table[] = { .maxlen = sizeof(default_backlog), .mode = 0644, .proc_handler = proc_dointvec, - }, - { } + } }; /* diff --git a/drivers/infiniband/core/ucma.c b/drivers/infiniband/core/ucma.c index bf42650f125b..92ad24ddf12a 100644 --- a/drivers/infiniband/core/ucma.c +++ b/drivers/infiniband/core/ucma.c @@ -70,8 +70,7 @@ static struct ctl_table ucma_ctl_table[] = { .maxlen = sizeof max_backlog, .mode = 0644, .proc_handler = proc_dointvec, - }, - { } + } }; struct ucma_file { -- 2.30.2
[PATCH 15/15] intel drm: Remove now superfluous sentinel element from ctl_table array
From: Joel Granados This commit comes at the tail end of a greater effort to remove the empty elements at the end of the ctl_table arrays (sentinels) which will reduce the overall build time size of the kernel and run time memory bloat by ~64 bytes per sentinel (further information Link : https://lore.kernel.org/all/zo5yx5jfoggi%2f...@bombadil.infradead.org/) Remove sentinel from oa_table Signed-off-by: Joel Granados --- drivers/gpu/drm/i915/i915_perf.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_perf.c b/drivers/gpu/drm/i915/i915_perf.c index 04bc1f4a1115..97ef6d2ad037 100644 --- a/drivers/gpu/drm/i915/i915_perf.c +++ b/drivers/gpu/drm/i915/i915_perf.c @@ -4895,8 +4895,7 @@ static struct ctl_table oa_table[] = { .proc_handler = proc_dointvec_minmax, .extra1 = SYSCTL_ZERO, .extra2 = _sample_rate_hard_limit, -}, - {} + } }; static u32 num_perf_groups_per_gt(struct intel_gt *gt) -- 2.30.2
[PATCH 12/15] fw loader: Remove the now superfluous sentinel element from ctl_table array
From: Joel Granados This commit comes at the tail end of a greater effort to remove the empty elements at the end of the ctl_table arrays (sentinels) which will reduce the overall build time size of the kernel and run time memory bloat by ~64 bytes per sentinel (further information Link : https://lore.kernel.org/all/zo5yx5jfoggi%2f...@bombadil.infradead.org/) Remove sentinel from firmware_config_table Signed-off-by: Joel Granados --- drivers/base/firmware_loader/fallback_table.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/base/firmware_loader/fallback_table.c b/drivers/base/firmware_loader/fallback_table.c index e5ac098d0742..968aef19e118 100644 --- a/drivers/base/firmware_loader/fallback_table.c +++ b/drivers/base/firmware_loader/fallback_table.c @@ -43,8 +43,7 @@ static struct ctl_table firmware_config_table[] = { .proc_handler = proc_douintvec_minmax, .extra1 = SYSCTL_ZERO, .extra2 = SYSCTL_ONE, - }, - { } + } }; static struct ctl_table_header *firmware_config_sysct_table_header; -- 2.30.2
[PATCH 10/15] vrf: Remove the now superfluous sentinel element from ctl_table array
From: Joel Granados This commit comes at the tail end of a greater effort to remove the empty elements at the end of the ctl_table arrays (sentinels) which will reduce the overall build time size of the kernel and run time memory bloat by ~64 bytes per sentinel (further information Link : https://lore.kernel.org/all/zo5yx5jfoggi%2f...@bombadil.infradead.org/) Remove sentinel from vrf_table Signed-off-by: Joel Granados --- drivers/net/vrf.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/net/vrf.c b/drivers/net/vrf.c index a3408e4e1491..94eed8708467 100644 --- a/drivers/net/vrf.c +++ b/drivers/net/vrf.c @@ -1962,8 +1962,7 @@ static const struct ctl_table vrf_table[] = { .proc_handler = vrf_shared_table_handler, /* set by the vrf_netns_init */ .extra1 = NULL, - }, - { }, + } }; static int vrf_netns_init_sysctl(struct net *net, struct netns_vrf *nn_vrf) -- 2.30.2
[PATCH 13/15] raid: Remove now superfluous sentinel element from ctl_table array
From: Joel Granados This commit comes at the tail end of a greater effort to remove the empty elements at the end of the ctl_table arrays (sentinels) which will reduce the overall build time size of the kernel and run time memory bloat by ~64 bytes per sentinel (further information Link : https://lore.kernel.org/all/zo5yx5jfoggi%2f...@bombadil.infradead.org/) Remove sentinel from raid_table Signed-off-by: Joel Granados --- drivers/md/md.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/md/md.c b/drivers/md/md.c index a104a025084d..3866d8f754a0 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c @@ -304,8 +304,7 @@ static struct ctl_table raid_table[] = { .maxlen = sizeof(int), .mode = S_IRUGO|S_IWUSR, .proc_handler = proc_dointvec, - }, - { } + } }; static int start_readonly; -- 2.30.2
[PATCH 11/15] sgi-xp: Remove the now superfluous sentinel element from ctl_table array
From: Joel Granados This commit comes at the tail end of a greater effort to remove the empty elements at the end of the ctl_table arrays (sentinels) which will reduce the overall build time size of the kernel and run time memory bloat by ~64 bytes per sentinel (further information Link : https://lore.kernel.org/all/zo5yx5jfoggi%2f...@bombadil.infradead.org/) Remove sentinel from xpc_sys_xpc_hb and xpc_sys_xpc Signed-off-by: Joel Granados --- drivers/misc/sgi-xp/xpc_main.c | 6 ++ 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/drivers/misc/sgi-xp/xpc_main.c b/drivers/misc/sgi-xp/xpc_main.c index 6da509d692bb..c898092ff3ac 100644 --- a/drivers/misc/sgi-xp/xpc_main.c +++ b/drivers/misc/sgi-xp/xpc_main.c @@ -109,8 +109,7 @@ static struct ctl_table xpc_sys_xpc_hb[] = { .mode = 0644, .proc_handler = proc_dointvec_minmax, .extra1 = _hb_check_min_interval, -.extra2 = _hb_check_max_interval}, - {} +.extra2 = _hb_check_max_interval} }; static struct ctl_table xpc_sys_xpc[] = { { @@ -120,8 +119,7 @@ static struct ctl_table xpc_sys_xpc[] = { .mode = 0644, .proc_handler = proc_dointvec_minmax, .extra1 = _disengage_min_timelimit, -.extra2 = _disengage_max_timelimit}, - {} +.extra2 = _disengage_max_timelimit} }; static struct ctl_table_header *xpc_sysctl; -- 2.30.2
[PATCH 14/15] hyper-v/azure: Remove now superfluous sentinel element from ctl_table array
From: Joel Granados This commit comes at the tail end of a greater effort to remove the empty elements at the end of the ctl_table arrays (sentinels) which will reduce the overall build time size of the kernel and run time memory bloat by ~64 bytes per sentinel (further information Link : https://lore.kernel.org/all/zo5yx5jfoggi%2f...@bombadil.infradead.org/) Remove sentinel from hv_ctl_table Signed-off-by: Joel Granados --- drivers/hv/hv_common.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/hv/hv_common.c b/drivers/hv/hv_common.c index ccad7bca3fd3..bc7d678030aa 100644 --- a/drivers/hv/hv_common.c +++ b/drivers/hv/hv_common.c @@ -147,8 +147,7 @@ static struct ctl_table hv_ctl_table[] = { .proc_handler = proc_dointvec_minmax, .extra1 = SYSCTL_ZERO, .extra2 = SYSCTL_ONE - }, - {} + } }; static int hv_die_panic_notify_crash(struct notifier_block *self, -- 2.30.2
[PATCH 05/15] scsi: Remove now superfluous sentinel element from ctl_table array
From: Joel Granados This commit comes at the tail end of a greater effort to remove the empty elements at the end of the ctl_table arrays (sentinels) which will reduce the overall build time size of the kernel and run time memory bloat by ~64 bytes per sentinel (further information Link : https://lore.kernel.org/all/zo5yx5jfoggi%2f...@bombadil.infradead.org/) Remove sentinel from scsi_table and sg_sysctls. Signed-off-by: Joel Granados --- drivers/scsi/scsi_sysctl.c | 3 +-- drivers/scsi/sg.c | 3 +-- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/drivers/scsi/scsi_sysctl.c b/drivers/scsi/scsi_sysctl.c index 7f0914ea168f..c74da88b20d3 100644 --- a/drivers/scsi/scsi_sysctl.c +++ b/drivers/scsi/scsi_sysctl.c @@ -17,8 +17,7 @@ static struct ctl_table scsi_table[] = { .data = _logging_level, .maxlen = sizeof(scsi_logging_level), .mode = 0644, - .proc_handler = proc_dointvec }, - { } + .proc_handler = proc_dointvec } }; static struct ctl_table_header *scsi_table_header; diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c index 0d8afffd1683..22a59c5e22eb 100644 --- a/drivers/scsi/sg.c +++ b/drivers/scsi/sg.c @@ -1649,8 +1649,7 @@ static struct ctl_table sg_sysctls[] = { .maxlen = sizeof(int), .mode = 0444, .proc_handler = proc_dointvec, - }, - {} + } }; static struct ctl_table_header *hdr; -- 2.30.2
[PATCH 04/15] tty: Remove now superfluous sentinel element from ctl_table array
From: Joel Granados This commit comes at the tail end of a greater effort to remove the empty elements at the end of the ctl_table arrays (sentinels) which will reduce the overall build time size of the kernel and run time memory bloat by ~64 bytes per sentinel (further information Link : https://lore.kernel.org/all/zo5yx5jfoggi%2f...@bombadil.infradead.org/) Remove sentinel from tty_table Signed-off-by: Joel Granados --- drivers/tty/tty_io.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/tty/tty_io.c b/drivers/tty/tty_io.c index 8a94e5a43c6d..2f925dc54a20 100644 --- a/drivers/tty/tty_io.c +++ b/drivers/tty/tty_io.c @@ -3607,8 +3607,7 @@ static struct ctl_table tty_table[] = { .proc_handler = proc_dointvec, .extra1 = SYSCTL_ZERO, .extra2 = SYSCTL_ONE, - }, - { } + } }; /* -- 2.30.2
[PATCH 09/15] char-misc: Remove the now superfluous sentinel element from ctl_table array
From: Joel Granados This commit comes at the tail end of a greater effort to remove the empty elements at the end of the ctl_table arrays (sentinels) which will reduce the overall build time size of the kernel and run time memory bloat by ~64 bytes per sentinel (further information Link : https://lore.kernel.org/all/zo5yx5jfoggi%2f...@bombadil.infradead.org/) Remove sentinel from impi_table and random_table Signed-off-by: Joel Granados --- drivers/char/ipmi/ipmi_poweroff.c | 3 +-- drivers/char/random.c | 3 +-- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/drivers/char/ipmi/ipmi_poweroff.c b/drivers/char/ipmi/ipmi_poweroff.c index 870659d91db2..b65ab51bf9fa 100644 --- a/drivers/char/ipmi/ipmi_poweroff.c +++ b/drivers/char/ipmi/ipmi_poweroff.c @@ -655,8 +655,7 @@ static struct ctl_table ipmi_table[] = { .data = _powercycle, .maxlen = sizeof(poweroff_powercycle), .mode = 0644, - .proc_handler = proc_dointvec }, - { } + .proc_handler = proc_dointvec } }; static struct ctl_table_header *ipmi_table_header; diff --git a/drivers/char/random.c b/drivers/char/random.c index 3cb37760dfec..4040715cba19 100644 --- a/drivers/char/random.c +++ b/drivers/char/random.c @@ -1682,8 +1682,7 @@ static struct ctl_table random_table[] = { .procname = "uuid", .mode = 0444, .proc_handler = proc_do_uuid, - }, - { } + } }; /* -- 2.30.2
[PATCH 07/15] macintosh: Remove the now superfluous sentinel element from ctl_table array
From: Joel Granados This commit comes at the tail end of a greater effort to remove the empty elements at the end of the ctl_table arrays (sentinels) which will reduce the overall build time size of the kernel and run time memory bloat by ~64 bytes per sentinel (further information Link : https://lore.kernel.org/all/zo5yx5jfoggi%2f...@bombadil.infradead.org/) Remove sentinel from mac_hid_files Signed-off-by: Joel Granados --- drivers/macintosh/mac_hid.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/macintosh/mac_hid.c b/drivers/macintosh/mac_hid.c index d8c4d5664145..5a228c7d9aeb 100644 --- a/drivers/macintosh/mac_hid.c +++ b/drivers/macintosh/mac_hid.c @@ -235,8 +235,7 @@ static struct ctl_table mac_hid_files[] = { .maxlen = sizeof(int), .mode = 0644, .proc_handler = proc_dointvec, - }, - { } + } }; static struct ctl_table_header *mac_hid_sysctl_header; -- 2.30.2
[PATCH 03/15] xen: Remove now superfluous sentinel element from ctl_table array
From: Joel Granados This commit comes at the tail end of a greater effort to remove the empty elements at the end of the ctl_table arrays (sentinels) which will reduce the overall build time size of the kernel and run time memory bloat by ~64 bytes per sentinel (further information Link : https://lore.kernel.org/all/zo5yx5jfoggi%2f...@bombadil.infradead.org/) Remove sentinel from balloon_table Signed-off-by: Joel Granados --- drivers/xen/balloon.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/xen/balloon.c b/drivers/xen/balloon.c index 586a1673459e..091eb2931ac4 100644 --- a/drivers/xen/balloon.c +++ b/drivers/xen/balloon.c @@ -93,8 +93,7 @@ static struct ctl_table balloon_table[] = { .proc_handler = proc_dointvec_minmax, .extra1 = SYSCTL_ZERO, .extra2 = SYSCTL_ONE, - }, - { } + } }; #else -- 2.30.2
[PATCH 00/15] sysctl: Remove sentinel elements from drivers
From: Joel Granados What? These commits remove the sentinel element (last empty element) from the sysctl arrays of all the files under the "drivers/" directory that use a sysctl array for registration. The merging of the preparation patches (in https://lore.kernel.org/all/zo5yx5jfoggi%2f...@bombadil.infradead.org/) to mainline allows us to just remove sentinel elements without changing behavior (more info here [1]). These commits are part of a bigger set (here https://github.com/Joelgranados/linux/tree/tag/sysctl_remove_empty_elem_V4) that remove the ctl_table sentinel. Make the review process easier by chunking the commits into manageable pieces. Each chunk can be reviewed separately without noise from parallel sets. Now that the architecture chunk has been mostly reviewed [6], we send the "drivers/" directory. Once this one is done, it will be follwed by "fs/*", "kernel/*", "net/*" and miscellaneous. The final set will remove the unneeded check for ->procname == NULL. Why? By removing the sysctl sentinel elements we avoid kernel bloat as ctl_table arrays get moved out of kernel/sysctl.c into their own respective subsystems. This move was started long ago to avoid merge conflicts; the sentinel removal bit came after Mathew Wilcox suggested it to avoid bloating the kernel by one element as arrays moved out. This patchset will reduce the overall build time size of the kernel and run time memory bloat by about ~64 bytes per declared ctl_table array. I have consolidated some links that shed light on the history of this effort [2]. Testing: * Ran sysctl selftests (./tools/testing/selftests/sysctl/sysctl.sh) * Ran this through 0-day with no errors or warnings Size saving after removing all sentinels: These are the bytes that we save after removing all the sentinels (this plus all the other chunks). I included them to get an idea of how much memory we are talking about. * bloat-o-meter: - The "yesall" configuration results save 9158 bytes https://lore.kernel.org/all/20230621091000.424843-1-j.grana...@samsung.com/ - The "tiny" config + CONFIG_SYSCTL save 1215 bytes https://lore.kernel.org/all/20230809105006.1198165-1-j.grana...@samsung.com/ * memory usage: In memory savings are measured to be 7296 bytes. (here is how to measure [3]) Size saving after this patchset: * bloat-o-meter - The "yesall" config saves 2432 bytes [4] - The "tiny" config saves 64 bytes [5] * memory usage: In this case there were no bytes saved because I do not have any of the drivers in the patch. To measure it comment the printk in `new_dir` and uncomment the if conditional in `new_links` [3]. Comments/feedback greatly appreciated Best Joel [1] We are able to remove a sentinel table without behavioral change by introducing a table_size argument in the same place where procname is checked for NULL. The idea is for it to keep stopping when it hits ->procname == NULL, while the sentinel is still present. And when the sentinel is removed, it will stop on the table_size. You can go to (https://lore.kernel.org/all/20230809105006.1198165-1-j.grana...@samsung.com/) for more information. [2] Links Related to the ctl_table sentinel removal: * Good summary from Luis sent with the "pull request" for the preparation patches. https://lore.kernel.org/all/zo5yx5jfoggi%2f...@bombadil.infradead.org/ * Another very good summary from Luis. https://lore.kernel.org/all/zmfizkfkvxuft...@bombadil.infradead.org/ * This is a patch set that replaces register_sysctl_table with register_sysctl https://lore.kernel.org/all/20230302204612.782387-1-mcg...@kernel.org/ * Patch set to deprecate register_sysctl_paths() https://lore.kernel.org/all/20230302202826.776286-1-mcg...@kernel.org/ * Here there is an explicit expectation for the removal of the sentinel element. https://lore.kernel.org/all/20230321130908.6972-1-frank...@vivo.com * The "ARRAY_SIZE" approach was mentioned (proposed?) in this thread https://lore.kernel.org/all/20220220060626.15885-1-tangm...@uniontech.com [3] To measure the in memory savings apply this on top of this patchset. " diff --git a/fs/proc/proc_sysctl.c b/fs/proc/proc_sysctl.c index c88854df0b62..e0073a627bac 100644 --- a/fs/proc/proc_sysctl.c +++ b/fs/proc/proc_sysctl.c @@ -976,6 +976,8 @@ static struct ctl_dir *new_dir(struct ctl_table_set *set, table[0].procname = new_name; table[0].mode = S_IFDIR|S_IRUGO|S_IXUGO; init_header(>header, set->dir.header.root, set, node, table, 1); + // Counts additional sentinel used for each new dir. + printk("%ld sysctl saved mem kzalloc \n", sizeof(struct ctl_table)); return new; } @@ -1199,6 +1201,9 @@ static struct ctl_table_header *new_links(struct ctl_dir *dir, struct ctl_table_ link_name += len; link++; } + // Counts additional sentinel used for each new registration +
[PATCH 01/15] cdrom: Remove now superfluous sentinel element from ctl_table array
From: Joel Granados This commit comes at the tail end of a greater effort to remove the empty elements at the end of the ctl_table arrays (sentinels) which will reduce the overall build time size of the kernel and run time memory bloat by ~64 bytes per sentinel (further information Link : https://lore.kernel.org/all/zo5yx5jfoggi%2f...@bombadil.infradead.org/) Remove sentinel element from cdrom_table Signed-off-by: Joel Granados --- drivers/cdrom/cdrom.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/cdrom/cdrom.c b/drivers/cdrom/cdrom.c index cc2839805983..451907ade389 100644 --- a/drivers/cdrom/cdrom.c +++ b/drivers/cdrom/cdrom.c @@ -3654,8 +3654,7 @@ static struct ctl_table cdrom_table[] = { .maxlen = sizeof(int), .mode = 0644, .proc_handler = cdrom_sysctl_handler - }, - { } + } }; static struct ctl_table_header *cdrom_sysctl_header; -- 2.30.2
Re: [PATCH 87/87] fs: move i_blocks up a few places in struct inode
On Thu, 2023-09-28 at 14:35 +0300, Amir Goldstein wrote: > On Thu, Sep 28, 2023 at 2:06 PM Jeff Layton wrote: > > > > The recent change to use discrete integers instead of struct timespec64 > > in struct inode shaved 8 bytes off of it, but it also moves the i_lock > > into the previous cacheline, away from the fields that it protects. > > > > Move i_blocks up above the i_lock, which moves the new 4 byte hole to > > just after the timestamps, without changing the size of the structure. > > > > Instead of creating an implicit hole, can you please move i_generation > to fill the 4 bytes hole. > > It makes sense in the same cache line with i_ino and I could > use the vacant 4 bytes hole above i_fsnotify_mask to expand the > mask to 64bit (the 32bit event mask space is running out). > > Thanks, > Amir. > Sounds like a plan. Resulting struct inode size is the same (616 bytes with my kdevops kconfig). BTW: all of these changes are in my "amtime" branch if anyone wants to pull them down. -- Jeff Layton
Re: [PATCH 87/87] fs: move i_blocks up a few places in struct inode
On Thu, Sep 28, 2023 at 2:06 PM Jeff Layton wrote: > > The recent change to use discrete integers instead of struct timespec64 > in struct inode shaved 8 bytes off of it, but it also moves the i_lock > into the previous cacheline, away from the fields that it protects. > > Move i_blocks up above the i_lock, which moves the new 4 byte hole to > just after the timestamps, without changing the size of the structure. > Instead of creating an implicit hole, can you please move i_generation to fill the 4 bytes hole. It makes sense in the same cache line with i_ino and I could use the vacant 4 bytes hole above i_fsnotify_mask to expand the mask to 64bit (the 32bit event mask space is running out). Thanks, Amir. > Signed-off-by: Jeff Layton > --- > include/linux/fs.h | 2 +- > 1 file changed, 1 insertion(+), 1 deletion(-) > > diff --git a/include/linux/fs.h b/include/linux/fs.h > index de902ff2938b..3e0fe0f52e7c 100644 > --- a/include/linux/fs.h > +++ b/include/linux/fs.h > @@ -677,11 +677,11 @@ struct inode { > u32 i_atime_nsec; > u32 i_mtime_nsec; > u32 i_ctime_nsec; > + blkcnt_ti_blocks; > spinlock_t i_lock; /* i_blocks, i_bytes, maybe i_size */ > unsigned short i_bytes; > u8 i_blkbits; > u8 i_write_hint; > - blkcnt_ti_blocks; > > #ifdef __NEED_I_SIZE_ORDERED > seqcount_t i_size_seqcount; > -- > 2.41.0 >
[PATCH 87/87] fs: move i_blocks up a few places in struct inode
The recent change to use discrete integers instead of struct timespec64 in struct inode shaved 8 bytes off of it, but it also moves the i_lock into the previous cacheline, away from the fields that it protects. Move i_blocks up above the i_lock, which moves the new 4 byte hole to just after the timestamps, without changing the size of the structure. Signed-off-by: Jeff Layton --- include/linux/fs.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/linux/fs.h b/include/linux/fs.h index de902ff2938b..3e0fe0f52e7c 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -677,11 +677,11 @@ struct inode { u32 i_atime_nsec; u32 i_mtime_nsec; u32 i_ctime_nsec; + blkcnt_ti_blocks; spinlock_t i_lock; /* i_blocks, i_bytes, maybe i_size */ unsigned short i_bytes; u8 i_blkbits; u8 i_write_hint; - blkcnt_ti_blocks; #ifdef __NEED_I_SIZE_ORDERED seqcount_t i_size_seqcount; -- 2.41.0
[PATCH 86/87] fs: switch timespec64 fields in inode to discrete integers
This shaves 8 bytes off struct inode, according to pahole. Signed-off-by: Jeff Layton --- include/linux/fs.h | 32 +++- 1 file changed, 23 insertions(+), 9 deletions(-) diff --git a/include/linux/fs.h b/include/linux/fs.h index 831657011036..de902ff2938b 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -671,9 +671,12 @@ struct inode { }; dev_t i_rdev; loff_t i_size; - struct timespec64 __i_atime; /* use inode_*_atime accessors */ - struct timespec64 __i_mtime; /* use inode_*_mtime accessors */ - struct timespec64 __i_ctime; /* use inode_*_ctime accessors */ + time64_ti_atime_sec; + time64_ti_mtime_sec; + time64_ti_ctime_sec; + u32 i_atime_nsec; + u32 i_mtime_nsec; + u32 i_ctime_nsec; spinlock_t i_lock; /* i_blocks, i_bytes, maybe i_size */ unsigned short i_bytes; u8 i_blkbits; @@ -1519,7 +1522,9 @@ struct timespec64 inode_set_ctime_current(struct inode *inode); */ static inline struct timespec64 inode_get_ctime(const struct inode *inode) { - return inode->__i_ctime; + struct timespec64 ts = { .tv_sec = inode->i_ctime_sec, +.tv_nsec = inode->i_ctime_nsec }; + return ts; } /** @@ -1532,7 +1537,8 @@ static inline struct timespec64 inode_get_ctime(const struct inode *inode) static inline struct timespec64 inode_set_ctime_to_ts(struct inode *inode, struct timespec64 ts) { - inode->__i_ctime = ts; + inode->i_ctime_sec = ts.tv_sec; + inode->i_ctime_nsec = ts.tv_sec; return ts; } @@ -1555,13 +1561,17 @@ static inline struct timespec64 inode_set_ctime(struct inode *inode, static inline struct timespec64 inode_get_atime(const struct inode *inode) { - return inode->__i_atime; + struct timespec64 ts = { .tv_sec = inode->i_atime_sec, +.tv_nsec = inode->i_atime_nsec }; + + return ts; } static inline struct timespec64 inode_set_atime_to_ts(struct inode *inode, struct timespec64 ts) { - inode->__i_atime = ts; + inode->i_atime_sec = ts.tv_sec; + inode->i_atime_nsec = ts.tv_sec; return ts; } @@ -1575,13 +1585,17 @@ static inline struct timespec64 inode_set_atime(struct inode *inode, static inline struct timespec64 inode_get_mtime(const struct inode *inode) { - return inode->__i_mtime; + struct timespec64 ts = { .tv_sec = inode->i_mtime_sec, +.tv_nsec = inode->i_mtime_nsec }; + + return ts; } static inline struct timespec64 inode_set_mtime_to_ts(struct inode *inode, struct timespec64 ts) { - inode->__i_mtime = ts; + inode->i_atime_sec = ts.tv_sec; + inode->i_atime_nsec = ts.tv_sec; return ts; } -- 2.41.0
[PATCH 85/87] fs: rename i_atime and i_mtime fields to __i_atime and __i_mtime
Make it clear that these fields are private now, and that the accessors should be used instead. Signed-off-by: Jeff Layton --- include/linux/fs.h | 14 +++--- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/include/linux/fs.h b/include/linux/fs.h index 12d247b82aa0..831657011036 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -671,9 +671,9 @@ struct inode { }; dev_t i_rdev; loff_t i_size; - struct timespec64 i_atime; - struct timespec64 i_mtime; - struct timespec64 __i_ctime; /* use inode_*_ctime accessors! */ + struct timespec64 __i_atime; /* use inode_*_atime accessors */ + struct timespec64 __i_mtime; /* use inode_*_mtime accessors */ + struct timespec64 __i_ctime; /* use inode_*_ctime accessors */ spinlock_t i_lock; /* i_blocks, i_bytes, maybe i_size */ unsigned short i_bytes; u8 i_blkbits; @@ -1555,13 +1555,13 @@ static inline struct timespec64 inode_set_ctime(struct inode *inode, static inline struct timespec64 inode_get_atime(const struct inode *inode) { - return inode->i_atime; + return inode->__i_atime; } static inline struct timespec64 inode_set_atime_to_ts(struct inode *inode, struct timespec64 ts) { - inode->i_atime = ts; + inode->__i_atime = ts; return ts; } @@ -1575,13 +1575,13 @@ static inline struct timespec64 inode_set_atime(struct inode *inode, static inline struct timespec64 inode_get_mtime(const struct inode *inode) { - return inode->i_mtime; + return inode->__i_mtime; } static inline struct timespec64 inode_set_mtime_to_ts(struct inode *inode, struct timespec64 ts) { - inode->i_mtime = ts; + inode->__i_mtime = ts; return ts; } -- 2.41.0
[PATCH 01/87] fs: new accessor methods for atime and mtime
Recently, we converted the ctime accesses in the kernel to use new accessor functions. Linus recently pointed out though that if we add accessors for the atime and mtime, then that would allow us to seamlessly change how these timestamps are stored in the inode. Add new accessor functions for the atime and mtime that mirror the accessors for the ctime. Signed-off-by: Jeff Layton --- fs/libfs.c | 13 + include/linux/fs.h | 42 ++ 2 files changed, 55 insertions(+) diff --git a/fs/libfs.c b/fs/libfs.c index 37f2d34ee090..f5cdc7f7f5b5 100644 --- a/fs/libfs.c +++ b/fs/libfs.c @@ -1912,3 +1912,16 @@ ssize_t direct_write_fallback(struct kiocb *iocb, struct iov_iter *iter, return direct_written + buffered_written; } EXPORT_SYMBOL_GPL(direct_write_fallback); + +/** + * simple_inode_init_ts - initialize the timestamps for a new inode + * @inode: inode to be initialized + * + * When a new inode is created, most filesystems set the timestamps to the + * current time. Add a helper to do this. + */ +struct timespec64 simple_inode_init_ts(struct inode *inode); +{ + return inode->i_atime = inode->i_mtime = inode_set_ctime_current(inode); +} +EXPORT_SYMBOL(simple_inode_init_ts); diff --git a/include/linux/fs.h b/include/linux/fs.h index b528f063e8ff..12d247b82aa0 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -1553,6 +1553,48 @@ static inline struct timespec64 inode_set_ctime(struct inode *inode, return inode_set_ctime_to_ts(inode, ts); } +static inline struct timespec64 inode_get_atime(const struct inode *inode) +{ + return inode->i_atime; +} + +static inline struct timespec64 inode_set_atime_to_ts(struct inode *inode, + struct timespec64 ts) +{ + inode->i_atime = ts; + return ts; +} + +static inline struct timespec64 inode_set_atime(struct inode *inode, + time64_t sec, long nsec) +{ + struct timespec64 ts = { .tv_sec = sec, +.tv_nsec = nsec }; + return inode_set_atime_to_ts(inode, ts); +} + +static inline struct timespec64 inode_get_mtime(const struct inode *inode) +{ + return inode->i_mtime; +} + +static inline struct timespec64 inode_set_mtime_to_ts(struct inode *inode, + struct timespec64 ts) +{ + inode->i_mtime = ts; + return ts; +} + +static inline struct timespec64 inode_set_mtime(struct inode *inode, + time64_t sec, long nsec) +{ + struct timespec64 ts = { .tv_sec = sec, +.tv_nsec = nsec }; + return inode_set_mtime_to_ts(inode, ts); +} + +struct timespec64 simple_inode_init_ts(struct inode *inode); + /* * Snapshotting support. */ -- 2.41.0
[PATCH 00/87] fs: new accessor methods for atime and mtime
While working on the multigrain timestamp changes, Linus suggested adding some similar wrappers for accessing the atime and mtime that we have for the ctime. With that, we could then move to using discrete integers instead of timespec64 in struct inode, and shrink it. Linus suggested using macros for the new accessors, but the existing ctime wrappers were static inlines and since there are only 3 different timestamps, I didn't see that trying to fiddle with macros would gain us anything. The first patches start with some new infrastructure, and then we move to converting different subsystems to use it. The second to last patch makes the conversion to discrete integers, which shaves 8 bytes off of struct inode on my x86_64 kernel. The last patch reshuffles things a bit more, to keep the i_lock in the same cacheline as the fields it protects (at least on x86_64). About 75% of this conversion was done with coccinelle, with the rest done by hand with vim. Jeff Layton (87): fs: new accessor methods for atime and mtime fs: convert core infrastructure to new {a,m}time accessors arch/powerpc/platforms/cell/spufs: convert to new inode {a,m}time accessors arch/s390/hypfs: convert to new inode {a,m}time accessors drivers/android: convert to new inode {a,m}time accessors drivers/char: convert to new inode {a,m}time accessors drivers/infiniband/hw/qib: convert to new inode {a,m}time accessors drivers/misc/ibmasm: convert to new inode {a,m}time accessors drivers/misc: convert to new inode {a,m}time accessors drivers/platform/x86: convert to new inode {a,m}time accessors drivers/tty: convert to new inode {a,m}time accessors drivers/usb/core: convert to new inode {a,m}time accessors drivers/usb/gadget/function: convert to new inode {a,m}time accessors drivers/usb/gadget/legacy: convert to new inode {a,m}time accessors fs/9p: convert to new inode {a,m}time accessors fs/adfs: convert to new inode {a,m}time accessors fs/affs: convert to new inode {a,m}time accessors fs/afs: convert to new inode {a,m}time accessors fs/autofs: convert to new inode {a,m}time accessors fs/befs: convert to new inode {a,m}time accessors fs/bfs: convert to new inode {a,m}time accessors fs/btrfs: convert to new inode {a,m}time accessors fs/ceph: convert to new inode {a,m}time accessors fs/coda: convert to new inode {a,m}time accessors fs/configfs: convert to new inode {a,m}time accessors fs/cramfs: convert to new inode {a,m}time accessors fs/debugfs: convert to new inode {a,m}time accessors fs/devpts: convert to new inode {a,m}time accessors fs/efivarfs: convert to new inode {a,m}time accessors fs/efs: convert to new inode {a,m}time accessors fs/erofs: convert to new inode {a,m}time accessors fs/exfat: convert to new inode {a,m}time accessors fs/ext2: convert to new inode {a,m}time accessors fs/ext4: convert to new inode {a,m}time accessors fs/f2fs: convert to new inode {a,m}time accessors fs/fat: convert to new inode {a,m}time accessors fs/freevxfs: convert to new inode {a,m}time accessors fs/fuse: convert to new inode {a,m}time accessors fs/gfs2: convert to new inode {a,m}time accessors fs/hfs: convert to new inode {a,m}time accessors fs/hfsplus: convert to new inode {a,m}time accessors fs/hostfs: convert to new inode {a,m}time accessors fs/hpfs: convert to new inode {a,m}time accessors fs/hugetlbfs: convert to new inode {a,m}time accessors fs/isofs: convert to new inode {a,m}time accessors fs/jffs2: convert to new inode {a,m}time accessors fs/jfs: convert to new inode {a,m}time accessors fs/kernfs: convert to new inode {a,m}time accessors fs/minix: convert to new inode {a,m}time accessors fs/nfs: convert to new inode {a,m}time accessors fs/nfsd: convert to new inode {a,m}time accessors fs/nilfs2: convert to new inode {a,m}time accessors fs/ntfs: convert to new inode {a,m}time accessors fs/ntfs3: convert to new inode {a,m}time accessors fs/ocfs2: convert to new inode {a,m}time accessors fs/omfs: convert to new inode {a,m}time accessors fs/openpromfs: convert to new inode {a,m}time accessors fs/orangefs: convert to new inode {a,m}time accessors fs/overlayfs: convert to new inode {a,m}time accessors fs/proc: convert to new inode {a,m}time accessors fs/pstore: convert to new inode {a,m}time accessors fs/qnx4: convert to new inode {a,m}time accessors fs/qnx6: convert to new inode {a,m}time accessors fs/ramfs: convert to new inode {a,m}time accessors fs/reiserfs: convert to new inode {a,m}time accessors fs/romfs: convert to new inode {a,m}time accessors fs/smb/client: convert to new inode {a,m}time accessors fs/smb/server: convert to new inode {a,m}time accessors fs/squashfs: convert to new inode {a,m}time accessors fs/sysv: convert to new inode {a,m}time accessors fs/tracefs: convert to new inode {a,m}time accessors fs/ubifs: convert to new inode {a,m}time accessors fs/udf: convert to new inode
[PATCH 03/87] arch/powerpc/platforms/cell/spufs: convert to new inode {a,m}time accessors
Signed-off-by: Jeff Layton --- arch/powerpc/platforms/cell/spufs/inode.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/powerpc/platforms/cell/spufs/inode.c b/arch/powerpc/platforms/cell/spufs/inode.c index 38c5be34c895..10c1320adfd0 100644 --- a/arch/powerpc/platforms/cell/spufs/inode.c +++ b/arch/powerpc/platforms/cell/spufs/inode.c @@ -86,7 +86,7 @@ spufs_new_inode(struct super_block *sb, umode_t mode) inode->i_mode = mode; inode->i_uid = current_fsuid(); inode->i_gid = current_fsgid(); - inode->i_atime = inode->i_mtime = inode_set_ctime_current(inode); + simple_inode_init_ts(inode); out: return inode; } -- 2.41.0
Re: [PATCH 00/59] dma: Convert to platform remove callback returning void
On 19-09-23, 15:31, Uwe Kleine-König wrote: > Hello, > > this series convert nearly all platform drivers below drivers/dma to use > .remove_new(). The motivation is to get rid of an integer return code > that is (mostly) ignored by the platform driver core and error prone on > the driver side. I have applied this, with change of subsystem to dmaengine: xxx > > See commit 5c5a7680e67b ("platform: Provide a remove callback that > returns no value") for an extended explanation and the eventual goal. > > There are 4 drivers I didn't convert in this series: > > drivers/dma/milbeaut-hdmac.c > drivers/dma/milbeaut-xdmac.c > drivers/dma/uniphier-mdmac.c > drivers/dma/uniphier-xdmac.c > > These all might return early in .remove() if dmaengine_terminate_sync() > fails. I only looked deeper into the first one, and this shows exactly > the error that is easy to make with .remove() returning an int: When > returning early from .remove(), some cleanup (here: > dma_async_device_unregister()) is skipped. So the dma device stays > known, but the device is still unregistered and the devm allocated stuff > (here e.g. *mdev) is freed. So it can probably easily happen, that > something tries to use the dma device and this will likely result in an > oops. We should convert these too, thanks for your work for the conversion -- ~Vinod
Re: [PATCH 00/59] dma: Convert to platform remove callback returning void
On Tue, 19 Sep 2023 15:31:08 +0200, Uwe Kleine-König wrote: > this series convert nearly all platform drivers below drivers/dma to use > .remove_new(). The motivation is to get rid of an integer return code > that is (mostly) ignored by the platform driver core and error prone on > the driver side. > > See commit 5c5a7680e67b ("platform: Provide a remove callback that > returns no value") for an extended explanation and the eventual goal. > > [...] Applied, thanks! [01/59] dma: altera-msgdma: Convert to platform remove callback returning void commit: 8876762f285fff08b1aefeba52c7157a2c9beec1 [02/59] dma: apple-admac: Convert to platform remove callback returning void commit: e7d5aa30c8a19e6d9c4ec19d3b9e501df22e1d1a [03/59] dma: at_hdmac: Convert to platform remove callback returning void commit: ae3f38e495b42494414cbace3b3bd3cb6dc10506 [04/59] dma: at_xdmac: Convert to platform remove callback returning void commit: b13af3c41bad5f4e45a73d6978f31ad48ffc2dee [05/59] dma: bcm-sba-raid: Convert to platform remove callback returning void commit: 017df796a3635edee5169a0700634da6dac92f6a [06/59] dma: bcm2835-dma: Convert to platform remove callback returning void commit: 8f63a2da288454e9228f6b438b86627f6ceae36b [07/59] dma: bestcomm: bestcomm: Convert to platform remove callback returning void commit: 7689bca111997e0d7a12cf6457fc26a52b8c800f [08/59] dma: dma-axi-dmac: Convert to platform remove callback returning void commit: b5f095a70117629c3abb49bcb07dfa954d275e99 [09/59] dma: dma-jz4780: Convert to platform remove callback returning void commit: a8c85540bee12d492904a430c0c1105a4b7b101c [10/59] dma: dw-axi-dmac: dw-axi-dmac-platform: Convert to platform remove callback returning void commit: c689a2fd2a3f2a0a9e775c59c0f02ea64677c254 [11/59] dma: dw: platform: Convert to platform remove callback returning void commit: 67572bfe2e35c232c3497b3fc8babbfe62600ce0 [12/59] dma: fsl-edma-main: Convert to platform remove callback returning void commit: fa13c3ef3f45bca5a1474755dac57bfaf28ef61b [13/59] dma: fsl-qdma: Convert to platform remove callback returning void commit: fe3d44cdaea41173e50833440db84982e2a8d2a7 [14/59] dma: fsl_raid: Convert to platform remove callback returning void commit: 37b24b50c5f8ad9037fbe81f1ee43f5e16fb5334 [15/59] dma: fsldma: Convert to platform remove callback returning void commit: d69f80110da5d0e665d7f2872bf2185fe7f14409 [16/59] dma: idma64: Convert to platform remove callback returning void commit: e8da277fbb8701308cfd2337afb13d34cc233349 [17/59] dma: img-mdc-dma: Convert to platform remove callback returning void commit: 6e1b4a907e860071d957baee688a30a0bff102ef [18/59] dma: imx-dma: Convert to platform remove callback returning void commit: 14c49dd0c34e457d71494b04290c27d7a14584d7 [19/59] dma: imx-sdma: Convert to platform remove callback returning void commit: 06e4f653fafdeec7b13958b771226efa1cdf76d2 [20/59] dma: k3dma: Convert to platform remove callback returning void commit: 3faf902cb808163e9e65bf568c235a272215aed2 [21/59] dma: mcf-edma-main: Convert to platform remove callback returning void commit: 48236cb8314238917788f73353290dd1afb9a7c6 [22/59] dma: mediatek: mtk-cqdma: Convert to platform remove callback returning void commit: bdeb61f5180efc920cf55b966a2a30bc2336d6d4 [23/59] dma: mediatek: mtk-hsdma: Convert to platform remove callback returning void commit: 97283173effa6e53ea698726ea5d07f7ca06e5cf [24/59] dma: mediatek: mtk-uart-apdma: Convert to platform remove callback returning void commit: 4db30945a001ac97b5044db2aa2990b8e7df9452 [25/59] dma: mmp_pdma: Convert to platform remove callback returning void commit: c0f0d93fc1da36de564da9b3f0462b5bdc4b1948 [26/59] dma: mmp_tdma: Convert to platform remove callback returning void commit: f543b251500a0de589bc4c97da45b88410bf7c56 [27/59] dma: moxart-dma: Convert to platform remove callback returning void commit: 1a65831fa037457114ca75ea262d87fbde3158f0 [28/59] dma: mpc512x_dma: Convert to platform remove callback returning void commit: 80d0159bbe80d8de6f64c0a8554b4066c66eb378 [29/59] dma: mv_xor_v2: Convert to platform remove callback returning void commit: 733dbb8d62f33448c0d7470ba06ce39bdd790ddd [30/59] dma: nbpfaxi: Convert to platform remove callback returning void commit: 44d5338c4a5d7f3f1ef07d502b9db22a29a8756a [31/59] dma: owl-dma: Convert to platform remove callback returning void commit: 1260486a347567c33e0118626bb8778e342e6080 [32/59] dma: ppc4xx: adma: Convert to platform remove callback returning void commit: 5f8f212fb416dc3600046955fb008732a512fa5c [33/59] dma: pxa_dma: Convert to platform remove callback returning void commit: 44ea88715d37dc31145b7712b5474808258bab5f [34/59] dma: qcom: bam_dma: Convert to platform remove callback returning void
[RFC PATCH v5 11/11] media: audm2m: add virtual driver for audio memory to memory
Audio memory to memory virtual driver use video memory to memory virtual driver vim2m.c as example. The main difference is device type is VFL_TYPE_AUDIO and device cap type is V4L2_CAP_AUDIO_M2M. The device_run function is a dummy function, which is simply copy the data from input buffer to output buffer. Signed-off-by: Shengjiu Wang --- drivers/media/test-drivers/Kconfig | 9 + drivers/media/test-drivers/Makefile | 1 + drivers/media/test-drivers/audm2m.c | 808 3 files changed, 818 insertions(+) create mode 100644 drivers/media/test-drivers/audm2m.c diff --git a/drivers/media/test-drivers/Kconfig b/drivers/media/test-drivers/Kconfig index 459b433e9fae..be60d73cbf97 100644 --- a/drivers/media/test-drivers/Kconfig +++ b/drivers/media/test-drivers/Kconfig @@ -17,6 +17,15 @@ config VIDEO_VIM2M This is a virtual test device for the memory-to-memory driver framework. +config VIDEO_AUDM2M + tristate "Virtual Memory-to-Memory Driver For Audio" + depends on VIDEO_DEV + select VIDEOBUF2_VMALLOC + select V4L2_MEM2MEM_DEV + help + This is a virtual audio test device for the memory-to-memory driver + framework. + source "drivers/media/test-drivers/vicodec/Kconfig" source "drivers/media/test-drivers/vimc/Kconfig" source "drivers/media/test-drivers/vivid/Kconfig" diff --git a/drivers/media/test-drivers/Makefile b/drivers/media/test-drivers/Makefile index 740714a4584d..b53ed7e6eaf1 100644 --- a/drivers/media/test-drivers/Makefile +++ b/drivers/media/test-drivers/Makefile @@ -10,6 +10,7 @@ obj-$(CONFIG_DVB_VIDTV) += vidtv/ obj-$(CONFIG_VIDEO_VICODEC) += vicodec/ obj-$(CONFIG_VIDEO_VIM2M) += vim2m.o +obj-$(CONFIG_VIDEO_AUDM2M) += audm2m.o obj-$(CONFIG_VIDEO_VIMC) += vimc/ obj-$(CONFIG_VIDEO_VIVID) += vivid/ obj-$(CONFIG_VIDEO_VISL) += visl/ diff --git a/drivers/media/test-drivers/audm2m.c b/drivers/media/test-drivers/audm2m.c new file mode 100644 index ..566cfc48748b --- /dev/null +++ b/drivers/media/test-drivers/audm2m.c @@ -0,0 +1,808 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * A virtual v4l2-mem2mem example for audio device. + */ + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +MODULE_DESCRIPTION("Virtual device for audio mem2mem testing"); +MODULE_LICENSE("GPL"); +MODULE_VERSION("0.1"); +MODULE_ALIAS("audio_mem2mem_testdev"); + +static unsigned int debug; +module_param(debug, uint, 0644); +MODULE_PARM_DESC(debug, "debug level"); + +/* Flags that indicate a format can be used for capture/output */ +#define MEM2MEM_CAPTUREBIT(0) +#define MEM2MEM_OUTPUT BIT(1) + +#define MEM2MEM_NAME "audm2m" + +#define dprintk(dev, lvl, fmt, arg...) \ + v4l2_dbg(lvl, debug, &(dev)->v4l2_dev, "%s: " fmt, __func__, ## arg) + +#define SAMPLE_NUM 4096 + +static void audm2m_dev_release(struct device *dev) +{} + +static struct platform_device audm2m_pdev = { + .name = MEM2MEM_NAME, + .dev.release= audm2m_dev_release, +}; + +struct audm2m_fmt { + u32 fourcc; + snd_pcm_format_t format; + u32 types; +}; + +static struct audm2m_fmt formats[] = { + { + .fourcc = V4L2_AUDIO_FMT_S8, + .format = SNDRV_PCM_FORMAT_S8, + .types = MEM2MEM_CAPTURE | MEM2MEM_OUTPUT, + }, + { + .fourcc = V4L2_AUDIO_FMT_S16_LE, + .format = SNDRV_PCM_FORMAT_S16_LE, + .types = MEM2MEM_CAPTURE | MEM2MEM_OUTPUT, + }, + { + .fourcc = V4L2_AUDIO_FMT_U16_LE, + .format = SNDRV_PCM_FORMAT_U16_LE, + .types = MEM2MEM_CAPTURE | MEM2MEM_OUTPUT, + }, + { + .fourcc = V4L2_AUDIO_FMT_S24_LE, + .format = SNDRV_PCM_FORMAT_S24_LE, + .types = MEM2MEM_CAPTURE | MEM2MEM_OUTPUT, + }, + { + .fourcc = V4L2_AUDIO_FMT_S24_3LE, + .format = SNDRV_PCM_FORMAT_S24_3LE, + .types = MEM2MEM_CAPTURE | MEM2MEM_OUTPUT, + }, + { + .fourcc = V4L2_AUDIO_FMT_U24_LE, + .format = SNDRV_PCM_FORMAT_U24_LE, + .types = MEM2MEM_CAPTURE | MEM2MEM_OUTPUT, + }, + { + .fourcc = V4L2_AUDIO_FMT_U24_3LE, + .format = SNDRV_PCM_FORMAT_U24_3LE, + .types = MEM2MEM_CAPTURE | MEM2MEM_OUTPUT, + }, + { + .fourcc = V4L2_AUDIO_FMT_S32_LE, + .format = SNDRV_PCM_FORMAT_S32_LE, + .types = MEM2MEM_CAPTURE | MEM2MEM_OUTPUT, + }, + { + .fourcc = V4L2_AUDIO_FMT_U32_LE, + .format = SNDRV_PCM_FORMAT_U32_LE, + .types = MEM2MEM_CAPTURE | MEM2MEM_OUTPUT, + }, + { + .fourcc = V4L2_AUDIO_FMT_S20_3LE, + .format =
[RFC PATCH v5 10/11] media: imx-asrc: Add memory to memory driver
Implement the ASRC memory to memory function using the v4l2 framework, user can use this function with v4l2 ioctl interface. User send the output and capture buffer to driver and driver store the converted data to the capture buffer. This feature can be shared by ASRC and EASRC drivers Signed-off-by: Shengjiu Wang --- drivers/media/platform/nxp/Kconfig| 12 + drivers/media/platform/nxp/Makefile |1 + drivers/media/platform/nxp/imx-asrc.c | 1251 + 3 files changed, 1264 insertions(+) create mode 100644 drivers/media/platform/nxp/imx-asrc.c diff --git a/drivers/media/platform/nxp/Kconfig b/drivers/media/platform/nxp/Kconfig index 40e3436669e2..8234644ee341 100644 --- a/drivers/media/platform/nxp/Kconfig +++ b/drivers/media/platform/nxp/Kconfig @@ -67,3 +67,15 @@ config VIDEO_MX2_EMMAPRP source "drivers/media/platform/nxp/dw100/Kconfig" source "drivers/media/platform/nxp/imx-jpeg/Kconfig" + +config VIDEO_IMX_ASRC + tristate "NXP i.MX ASRC M2M support" + depends on V4L_MEM2MEM_DRIVERS + depends on MEDIA_SUPPORT + select VIDEOBUF2_DMA_CONTIG + select V4L2_MEM2MEM_DEV + help + Say Y if you want to add ASRC M2M support for NXP CPUs. + It is a complement for ASRC M2P and ASRC P2M features. + This option is only useful for out-of-tree drivers since + in-tree drivers select it automatically. diff --git a/drivers/media/platform/nxp/Makefile b/drivers/media/platform/nxp/Makefile index 4d90eb713652..1325675e34f5 100644 --- a/drivers/media/platform/nxp/Makefile +++ b/drivers/media/platform/nxp/Makefile @@ -9,3 +9,4 @@ obj-$(CONFIG_VIDEO_IMX8MQ_MIPI_CSI2) += imx8mq-mipi-csi2.o obj-$(CONFIG_VIDEO_IMX_MIPI_CSIS) += imx-mipi-csis.o obj-$(CONFIG_VIDEO_IMX_PXP) += imx-pxp.o obj-$(CONFIG_VIDEO_MX2_EMMAPRP) += mx2_emmaprp.o +obj-$(CONFIG_VIDEO_IMX_ASRC) += imx-asrc.o diff --git a/drivers/media/platform/nxp/imx-asrc.c b/drivers/media/platform/nxp/imx-asrc.c new file mode 100644 index ..dd0be1761e0a --- /dev/null +++ b/drivers/media/platform/nxp/imx-asrc.c @@ -0,0 +1,1251 @@ +// SPDX-License-Identifier: GPL-2.0 +// +// Copyright (C) 2014-2016 Freescale Semiconductor, Inc. +// Copyright (C) 2019-2023 NXP +// +// Freescale ASRC Memory to Memory (M2M) driver + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define V4L_CAP OUT +#define V4L_OUT IN + +#define ASRC_xPUT_DMA_CALLBACK(dir) \ + (((dir) == V4L_OUT) ? asrc_input_dma_callback \ + : asrc_output_dma_callback) + +#define DIR_STR(dir) (dir) == V4L_OUT ? "out" : "cap" + +#define ASRC_M2M_BUFFER_SIZE (512 * 1024) +#define ASRC_M2M_PERIOD_SIZE (48 * 1024) +#define ASRC_M2M_SG_NUM (20) + +struct asrc_fmt { + u32 fourcc; + snd_pcm_format_t format; +}; + +struct asrc_pair_m2m { + struct fsl_asrc_pair *pair; + struct asrc_m2m *m2m; + struct v4l2_fh fh; + struct v4l2_ctrl_handler ctrl_handler; + int channels[2]; + struct v4l2_ctrl_asrc_rate src_rate; + struct v4l2_ctrl_asrc_rate dst_rate; + +}; + +struct asrc_m2m { + struct fsl_asrc_m2m_pdata pdata; + struct v4l2_device v4l2_dev; + struct v4l2_m2m_dev *m2m_dev; + struct video_device *dec_vdev; + struct mutex mlock; /* v4l2 ioctls serialization */ + struct platform_device *pdev; +}; + +static struct asrc_fmt formats[] = { + { + .fourcc = V4L2_AUDIO_FMT_S8, + .format = SNDRV_PCM_FORMAT_S8, + }, + { + .fourcc = V4L2_AUDIO_FMT_S16_LE, + .format = SNDRV_PCM_FORMAT_S16_LE, + }, + { + .fourcc = V4L2_AUDIO_FMT_U16_LE, + .format = SNDRV_PCM_FORMAT_U16_LE, + }, + { + .fourcc = V4L2_AUDIO_FMT_S24_LE, + .format = SNDRV_PCM_FORMAT_S24_LE, + }, + { + .fourcc = V4L2_AUDIO_FMT_S24_3LE, + .format = SNDRV_PCM_FORMAT_S24_3LE, + }, + { + .fourcc = V4L2_AUDIO_FMT_U24_LE, + .format = SNDRV_PCM_FORMAT_U24_LE, + }, + { + .fourcc = V4L2_AUDIO_FMT_U24_3LE, + .format = SNDRV_PCM_FORMAT_U24_3LE, + }, + { + .fourcc = V4L2_AUDIO_FMT_S32_LE, + .format = SNDRV_PCM_FORMAT_S32_LE, + }, + { + .fourcc = V4L2_AUDIO_FMT_U32_LE, + .format = SNDRV_PCM_FORMAT_U32_LE, + }, + { + .fourcc = V4L2_AUDIO_FMT_S20_3LE, + .format = SNDRV_PCM_FORMAT_S20_3LE, + }, + { + .fourcc = V4L2_AUDIO_FMT_U20_3LE, + .format = SNDRV_PCM_FORMAT_U20_3LE, + }, + { + .fourcc = V4L2_AUDIO_FMT_FLOAT_LE, + .format = SNDRV_PCM_FORMAT_FLOAT_LE, + }, + { + .fourcc =
[RFC PATCH v5 09/11] media: uapi: define audio sample format fourcc type
The audio sample format definition is from alsa, the header file is include/uapi/sound/asound.h, but don't include this header file directly, because in user space, there is another copy in alsa-lib. There will be conflict in userspace for include videodev2.h & asound.h and asoundlib.h Here still use the fourcc format. Signed-off-by: Shengjiu Wang --- .../userspace-api/media/v4l/pixfmt-audio.rst | 277 ++ .../userspace-api/media/v4l/pixfmt.rst| 1 + drivers/media/v4l2-core/v4l2-ioctl.c | 51 include/uapi/linux/videodev2.h| 56 4 files changed, 385 insertions(+) create mode 100644 Documentation/userspace-api/media/v4l/pixfmt-audio.rst diff --git a/Documentation/userspace-api/media/v4l/pixfmt-audio.rst b/Documentation/userspace-api/media/v4l/pixfmt-audio.rst new file mode 100644 index ..6ff114dfc2d1 --- /dev/null +++ b/Documentation/userspace-api/media/v4l/pixfmt-audio.rst @@ -0,0 +1,277 @@ +.. SPDX-License-Identifier: GFDL-1.1-no-invariants-or-later + +.. _pixfmt-audio: + +* +Audio Formats +* + +These formats are used for :ref:`audiomem2mem` interface only. + +.. tabularcolumns:: |p{5.8cm}|p{1.2cm}|p{10.3cm}| + +.. cssclass:: longtable + +.. flat-table:: Audio Format +:header-rows: 1 +:stub-columns: 0 +:widths: 3 1 4 + +* - Identifier + - Code + - Details +* .. _V4L2-AUDIO-FMT-S8: + + - ``V4L2_AUDIO_FMT_S8`` + - 'S8' + - Correspond to SNDRV_PCM_FORMAT_S8 in ALSA +* .. _V4L2-AUDIO-FMT-U8: + + - ``V4L2_AUDIO_FMT_U8`` + - 'U8' + - Correspond to SNDRV_PCM_FORMAT_U8 in ALSA +* .. _V4L2-AUDIO-FMT-S16-LE: + + - ``V4L2_AUDIO_FMT_S16_LE`` + - 'S16_LE' + - Correspond to SNDRV_PCM_FORMAT_S16_LE in ALSA +* .. _V4L2-AUDIO-FMT-S16-BE: + + - ``V4L2_AUDIO_FMT_S16_BE`` + - 'S16_BE' + - Correspond to SNDRV_PCM_FORMAT_S16_BE in ALSA +* .. _V4L2-AUDIO-FMT-U16-LE: + + - ``V4L2_AUDIO_FMT_U16_LE`` + - 'U16_LE' + - Correspond to SNDRV_PCM_FORMAT_U16_LE in ALSA +* .. _V4L2-AUDIO-FMT-U16-BE: + + - ``V4L2_AUDIO_FMT_U16_BE`` + - 'U16_BE' + - Correspond to SNDRV_PCM_FORMAT_U16_BE in ALSA +* .. _V4L2-AUDIO-FMT-S24-LE: + + - ``V4L2_AUDIO_FMT_S24_LE`` + - 'S24_LE' + - Correspond to SNDRV_PCM_FORMAT_S24_LE in ALSA +* .. _V4L2-AUDIO-FMT-S24-BE: + + - ``V4L2_AUDIO_FMT_S24_BE`` + - 'S24_BE' + - Correspond to SNDRV_PCM_FORMAT_S24_BE in ALSA +* .. _V4L2-AUDIO-FMT-U24-LE: + + - ``V4L2_AUDIO_FMT_U24_LE`` + - 'U24_LE' + - Correspond to SNDRV_PCM_FORMAT_U24_LE in ALSA +* .. _V4L2-AUDIO-FMT-U24-BE: + + - ``V4L2_AUDIO_FMT_U24_BE`` + - 'U24_BE' + - Correspond to SNDRV_PCM_FORMAT_U24_BE in ALSA +* .. _V4L2-AUDIO-FMT-S32-LE: + + - ``V4L2_AUDIO_FMT_S32_LE`` + - 'S32_LE' + - Correspond to SNDRV_PCM_FORMAT_S32_LE in ALSA +* .. _V4L2-AUDIO-FMT-S32-BE: + + - ``V4L2_AUDIO_FMT_S32_BE`` + - 'S32_BE' + - Correspond to SNDRV_PCM_FORMAT_S32_BE in ALSA +* .. _V4L2-AUDIO-FMT-U32-LE: + + - ``V4L2_AUDIO_FMT_U32_LE`` + - 'U32_LE' + - Correspond to SNDRV_PCM_FORMAT_U32_LE in ALSA +* .. _V4L2-AUDIO-FMT-U32-BE: + + - ``V4L2_AUDIO_FMT_U32_BE`` + - 'U32_BE' + - Correspond to SNDRV_PCM_FORMAT_U32_BE in ALSA +* .. _V4L2-AUDIO-FMT-FLOAT-LE: + + - ``V4L2_AUDIO_FMT_FLOAT_LE`` + - 'FLOAT_LE' + - Correspond to SNDRV_PCM_FORMAT_FLOAT_LE in ALSA +* .. _V4L2-AUDIO-FMT-FLOAT-BE: + + - ``V4L2_AUDIO_FMT_FLOAT_BE`` + - 'FLOAT_BE' + - Correspond to SNDRV_PCM_FORMAT_FLOAT_BE in ALSA +* .. _V4L2-AUDIO-FMT-FLOAT64-LE: + + - ``V4L2_AUDIO_FMT_FLOAT64_LE`` + - 'FLOAT64_LE' + - Correspond to SNDRV_PCM_FORMAT_FLOAT64_LE in ALSA +* .. _V4L2-AUDIO-FMT-FLOAT64-BE: + + - ``V4L2_AUDIO_FMT_FLOAT64_BE`` + - 'FLOAT64_BE' + - Correspond to SNDRV_PCM_FORMAT_FLOAT64_BE in ALSA +* .. _V4L2-AUDIO-FMT-IEC958-SUBFRAME-LE: + + - ``V4L2_AUDIO_FMT_IEC958_SUBFRAME_LE`` + - 'IEC958_SUBFRAME_LE' + - Correspond to SNDRV_PCM_FORMAT_IEC958_SUBFRAME_LE in ALSA +* .. _V4L2-AUDIO-FMT-IEC958-SUBFRAME-BE: + + - ``V4L2_AUDIO_FMT_IEC958_SUBFRAME_BE`` + - 'IEC958_SUBFRAME_BE' + - Correspond to SNDRV_PCM_FORMAT_IEC958_SUBFRAME_BE in ALSA +* .. _V4L2-AUDIO-FMT-MU-LAW: + + - ``V4L2_AUDIO_FMT_MU_LAW`` + - 'MU_LAW' + - Correspond to SNDRV_PCM_FORMAT_MU_LAW in ALSA +* .. _V4L2-AUDIO-FMT-A-LAW: + + - ``V4L2_AUDIO_FMT_A_LAW`` + - 'A_LAW' + - Correspond to SNDRV_PCM_FORMAT_A_LAW in ALSA +* .. _V4L2-AUDIO-FMT-IMA-ADPCM: + + - ``V4L2_AUDIO_FMT_IMA_ADPCM`` + - 'IMA_ADPCM' + - Correspond to SNDRV_PCM_FORMAT_IMA_ADPCM in ALSA +* .. _V4L2-AUDIO-FMT-MPEG: + + - ``V4L2_AUDIO_FMT_MPEG`` + - 'MPEG' + - Correspond to SNDRV_PCM_FORMAT_MPEG in ALSA +* ..
[RFC PATCH v5 08/11] media: uapi: Add audio rate controls support
Audio rate controls is used for user to configure the audio sample rate to driver. Add V4L2_CID_ASRC_SOURCE_RATE and V4L2_CID_ASRC_DEST_RATE new ID for ASRC rate control. Signed-off-by: Shengjiu Wang --- .../userspace-api/media/v4l/common.rst| 1 + .../media/v4l/ext-ctrls-asrc-rate.rst | 36 +++ .../media/v4l/vidioc-g-ext-ctrls.rst | 4 +++ .../media/v4l/vidioc-queryctrl.rst| 7 .../media/videodev2.h.rst.exceptions | 1 + drivers/media/v4l2-core/v4l2-ctrls-core.c | 5 +++ drivers/media/v4l2-core/v4l2-ctrls-defs.c | 4 +++ include/media/v4l2-ctrls.h| 1 + include/uapi/linux/v4l2-controls.h| 13 +++ include/uapi/linux/videodev2.h| 1 + 10 files changed, 73 insertions(+) create mode 100644 Documentation/userspace-api/media/v4l/ext-ctrls-asrc-rate.rst diff --git a/Documentation/userspace-api/media/v4l/common.rst b/Documentation/userspace-api/media/v4l/common.rst index ea0435182e44..fe6cd7ae60e4 100644 --- a/Documentation/userspace-api/media/v4l/common.rst +++ b/Documentation/userspace-api/media/v4l/common.rst @@ -52,6 +52,7 @@ applicable to all devices. ext-ctrls-fm-rx ext-ctrls-detect ext-ctrls-colorimetry +ext-ctrls-asrc-rate fourcc format planar-apis diff --git a/Documentation/userspace-api/media/v4l/ext-ctrls-asrc-rate.rst b/Documentation/userspace-api/media/v4l/ext-ctrls-asrc-rate.rst new file mode 100644 index ..28bf9e1628e1 --- /dev/null +++ b/Documentation/userspace-api/media/v4l/ext-ctrls-asrc-rate.rst @@ -0,0 +1,36 @@ +.. SPDX-License-Identifier: GFDL-1.1-no-invariants-or-later + +.. _asrc-rate-controls: + +*** +ASRC RATE Control Reference +*** + +These controls is intended to support asynchronous sample +rate converter. + +.. _v4l2-audio-asrc: + +``V4L2_CID_ASRC_SOURCE_RATE`` +sets the rasampler source rate. + +``V4L2_CID_ASRC_DEST_RATE`` +sets the rasampler destination rate. + +.. c:type:: v4l2_ctrl_asrc_rate + +.. cssclass:: longtable + +.. tabularcolumns:: |p{1.5cm}|p{5.8cm}|p{10.0cm}| + +.. flat-table:: struct v4l2_ctrl_asrc_rate +:header-rows: 0 +:stub-columns: 0 +:widths: 1 1 2 + +* - __u32 + - ``rate_integer`` + - integer part of sample rate. +* - __s32 + - ``rate_fractional`` + - fractional part of sample rate, which is Q31. diff --git a/Documentation/userspace-api/media/v4l/vidioc-g-ext-ctrls.rst b/Documentation/userspace-api/media/v4l/vidioc-g-ext-ctrls.rst index f9f73530a6be..93ce15330490 100644 --- a/Documentation/userspace-api/media/v4l/vidioc-g-ext-ctrls.rst +++ b/Documentation/userspace-api/media/v4l/vidioc-g-ext-ctrls.rst @@ -295,6 +295,10 @@ still cause this situation. - ``p_av1_film_grain`` - A pointer to a struct :c:type:`v4l2_ctrl_av1_film_grain`. Valid if this control is of type ``V4L2_CTRL_TYPE_AV1_FILM_GRAIN``. +* - struct :c:type:`v4l2_ctrl_asrc_rate` * + - ``p_asrc_rate`` + - A pointer to a struct :c:type:`v4l2_ctrl_asrc_rate`. Valid if this control is +of type ``V4L2_CTRL_TYPE_ASRC_RATE``. * - void * - ``ptr`` - A pointer to a compound type which can be an N-dimensional array diff --git a/Documentation/userspace-api/media/v4l/vidioc-queryctrl.rst b/Documentation/userspace-api/media/v4l/vidioc-queryctrl.rst index 4d38acafe8e1..8c15a0bb0fbc 100644 --- a/Documentation/userspace-api/media/v4l/vidioc-queryctrl.rst +++ b/Documentation/userspace-api/media/v4l/vidioc-queryctrl.rst @@ -549,6 +549,13 @@ See also the examples in :ref:`control`. - n/a - A struct :c:type:`v4l2_ctrl_av1_film_grain`, containing AV1 Film Grain parameters for stateless video decoders. +* - ``V4L2_CTRL_TYPE_ASRC_RATE`` + - n/a + - n/a + - n/a + - A struct :c:type:`v4l2_ctrl_asrc_rate`, containing audio +parameters for asrc component. + .. raw:: latex diff --git a/Documentation/userspace-api/media/videodev2.h.rst.exceptions b/Documentation/userspace-api/media/videodev2.h.rst.exceptions index e61152bb80d1..769e333a2b75 100644 --- a/Documentation/userspace-api/media/videodev2.h.rst.exceptions +++ b/Documentation/userspace-api/media/videodev2.h.rst.exceptions @@ -167,6 +167,7 @@ replace symbol V4L2_CTRL_TYPE_AV1_SEQUENCE :c:type:`v4l2_ctrl_type` replace symbol V4L2_CTRL_TYPE_AV1_TILE_GROUP_ENTRY :c:type:`v4l2_ctrl_type` replace symbol V4L2_CTRL_TYPE_AV1_FRAME :c:type:`v4l2_ctrl_type` replace symbol V4L2_CTRL_TYPE_AV1_FILM_GRAIN :c:type:`v4l2_ctrl_type` +replace symbol V4L2_CTRL_TYPE_ASRC_RATE :c:type:`v4l2_ctrl_type` # V4L2 capability defines replace define V4L2_CAP_VIDEO_CAPTURE device-capabilities diff --git a/drivers/media/v4l2-core/v4l2-ctrls-core.c b/drivers/media/v4l2-core/v4l2-ctrls-core.c index a662fb60f73f..2a72779f3508 100644 --- a/drivers/media/v4l2-core/v4l2-ctrls-core.c +++
[RFC PATCH v5 07/11] media: v4l2: Add audio capture and output support
Audio signal processing has the requirement for memory to memory similar as Video. This patch is to add this support in v4l2 framework, defined new buffer type V4L2_BUF_TYPE_AUDIO_CAPTURE and V4L2_BUF_TYPE_AUDIO_OUTPUT, defined new format v4l2_audio_format for audio case usage. The created audio device is named "/dev/v4l-audioX". Signed-off-by: Shengjiu Wang --- .../userspace-api/media/v4l/buffer.rst| 6 ++ .../media/v4l/dev-audio-mem2mem.rst | 71 +++ .../userspace-api/media/v4l/devices.rst | 1 + .../media/v4l/vidioc-enum-fmt.rst | 2 + .../userspace-api/media/v4l/vidioc-g-fmt.rst | 4 ++ .../media/videodev2.h.rst.exceptions | 2 + .../media/common/videobuf2/videobuf2-v4l2.c | 4 ++ drivers/media/v4l2-core/v4l2-dev.c| 17 + drivers/media/v4l2-core/v4l2-ioctl.c | 53 ++ include/media/v4l2-dev.h | 2 + include/media/v4l2-ioctl.h| 34 + include/uapi/linux/videodev2.h| 19 + 12 files changed, 215 insertions(+) create mode 100644 Documentation/userspace-api/media/v4l/dev-audio-mem2mem.rst diff --git a/Documentation/userspace-api/media/v4l/buffer.rst b/Documentation/userspace-api/media/v4l/buffer.rst index 04dec3e570ed..80cf2cb20dfe 100644 --- a/Documentation/userspace-api/media/v4l/buffer.rst +++ b/Documentation/userspace-api/media/v4l/buffer.rst @@ -438,6 +438,12 @@ enum v4l2_buf_type * - ``V4L2_BUF_TYPE_META_OUTPUT`` - 14 - Buffer for metadata output, see :ref:`metadata`. +* - ``V4L2_BUF_TYPE_AUDIO_CAPTURE`` + - 15 + - Buffer for audio capture, see :ref:`audio`. +* - ``V4L2_BUF_TYPE_AUDIO_OUTPUT`` + - 16 + - Buffer for audio output, see :ref:`audio`. .. _buffer-flags: diff --git a/Documentation/userspace-api/media/v4l/dev-audio-mem2mem.rst b/Documentation/userspace-api/media/v4l/dev-audio-mem2mem.rst new file mode 100644 index ..e24efd2c5140 --- /dev/null +++ b/Documentation/userspace-api/media/v4l/dev-audio-mem2mem.rst @@ -0,0 +1,71 @@ +.. SPDX-License-Identifier: GFDL-1.1-no-invariants-or-later + +.. _audiomem2mem: + + +Audio Memory-To-Memory Interface + + +A audio memory-to-memory device can compress, decompress, transform, or +otherwise convert audio data from one format into another format, in memory. +Such memory-to-memory devices set the ``V4L2_CAP_AUDIO_M2M`` capability. +Examples of memory-to-memory devices are codecs, audio preprocessing, +audio postprocessing. + +A memory-to-memory audio node supports both output (sending frames from +memory to the hardware) and capture (receiving the processed frames +from the hardware into memory) stream I/O. An application will have to +setup the stream I/O for both sides and finally call +:ref:`VIDIOC_STREAMON ` for both capture and output to +start the hardware. + +Memory-to-memory devices function as a shared resource: you can +open the audio node multiple times, each application setting up their +own properties that are local to the file handle, and each can use +it independently from the others. The driver will arbitrate access to +the hardware and reprogram it whenever another file handler gets access. + +Audio memory-to-memory devices are accessed through character device +special files named ``/dev/v4l-audio`` + +Querying Capabilities += + +Device nodes supporting the audio capture and output interface set the +``V4L2_CAP_AUDIO_M2M`` flag in the ``device_caps`` field of the +:c:type:`v4l2_capability` structure returned by the :c:func:`VIDIOC_QUERYCAP` +ioctl. + +Data Format Negotiation +=== + +The audio device uses the :ref:`format` ioctls to select the capture format. +The audio buffer content format is bound to that selected format. In addition +to the basic :ref:`format` ioctls, the :c:func:`VIDIOC_ENUM_FMT` ioctl must be +supported as well. + +To use the :ref:`format` ioctls applications set the ``type`` field of the +:c:type:`v4l2_format` structure to ``V4L2_BUF_TYPE_AUDIO_CAPTURE`` or to +``V4L2_BUF_TYPE_AUDIO_OUTPUT``. Both drivers and applications must set the +remainder of the :c:type:`v4l2_format` structure to 0. + +.. c:type:: v4l2_audio_format + +.. tabularcolumns:: |p{1.4cm}|p{2.4cm}|p{13.5cm}| + +.. flat-table:: struct v4l2_audio_format +:header-rows: 0 +:stub-columns: 0 +:widths: 1 1 2 + +* - __u32 + - ``pixelformat`` + - The sample format, set by the application. see :ref:`pixfmt-audio` +* - __u32 + - ``channels`` + - The channel number, set by the application. channel number range is +[1, 32]. +* - __u32 + - ``buffersize`` + - Maximum buffer size in bytes required for data. The value is set by the +driver. diff --git a/Documentation/userspace-api/media/v4l/devices.rst
[RFC PATCH v5 06/11] media: uapi: Add V4L2_CAP_AUDIO_M2M capability flag
V4L2_CAP_AUDIO_M2M is similar to V4L2_CAP_VIDEO_M2M flag. It is used for audio memory to memory case. Signed-off-by: Shengjiu Wang --- Documentation/userspace-api/media/v4l/vidioc-querycap.rst| 3 +++ Documentation/userspace-api/media/videodev2.h.rst.exceptions | 1 + include/uapi/linux/videodev2.h | 1 + 3 files changed, 5 insertions(+) diff --git a/Documentation/userspace-api/media/v4l/vidioc-querycap.rst b/Documentation/userspace-api/media/v4l/vidioc-querycap.rst index 6c57b8428356..0b3cefefc86b 100644 --- a/Documentation/userspace-api/media/v4l/vidioc-querycap.rst +++ b/Documentation/userspace-api/media/v4l/vidioc-querycap.rst @@ -259,6 +259,9 @@ specification the ioctl returns an ``EINVAL`` error code. video topology configuration, including which I/O entity is routed to the input/output, is configured by userspace via the Media Controller. See :ref:`media_controller`. +* - ``V4L2_CAP_AUDIO_M2M`` + - 0x4000 + - The device supports the audio Memory-To-Memory interface. * - ``V4L2_CAP_DEVICE_CAPS`` - 0x8000 - The driver fills the ``device_caps`` field. This capability can diff --git a/Documentation/userspace-api/media/videodev2.h.rst.exceptions b/Documentation/userspace-api/media/videodev2.h.rst.exceptions index 3e58aac4ef0b..da6d0b8e4c2c 100644 --- a/Documentation/userspace-api/media/videodev2.h.rst.exceptions +++ b/Documentation/userspace-api/media/videodev2.h.rst.exceptions @@ -197,6 +197,7 @@ replace define V4L2_CAP_META_OUTPUT device-capabilities replace define V4L2_CAP_DEVICE_CAPS device-capabilities replace define V4L2_CAP_TOUCH device-capabilities replace define V4L2_CAP_IO_MC device-capabilities +replace define V4L2_CAP_AUDIO_M2M device-capabilities # V4L2 pix flags replace define V4L2_PIX_FMT_PRIV_MAGIC :c:type:`v4l2_pix_format` diff --git a/include/uapi/linux/videodev2.h b/include/uapi/linux/videodev2.h index 78260e5d9985..3decf7d73870 100644 --- a/include/uapi/linux/videodev2.h +++ b/include/uapi/linux/videodev2.h @@ -508,6 +508,7 @@ struct v4l2_capability { #define V4L2_CAP_TOUCH 0x1000 /* Is a touch device */ #define V4L2_CAP_IO_MC 0x2000 /* Is input/output controlled by the media controller */ +#define V4L2_CAP_AUDIO_M2M 0x4000 /* audio memory to memory */ #define V4L2_CAP_DEVICE_CAPS0x8000 /* sets device capabilities field */ -- 2.34.1
[RFC PATCH v5 05/11] ASoC: fsl_easrc: register m2m platform device
Register m2m platform device,that user can use M2M feature. Signed-off-by: Shengjiu Wang --- sound/soc/fsl/fsl_easrc.c | 19 +++ 1 file changed, 19 insertions(+) diff --git a/sound/soc/fsl/fsl_easrc.c b/sound/soc/fsl/fsl_easrc.c index 50aee04e7915..cf1f559e825c 100644 --- a/sound/soc/fsl/fsl_easrc.c +++ b/sound/soc/fsl/fsl_easrc.c @@ -2056,6 +2056,7 @@ MODULE_DEVICE_TABLE(of, fsl_easrc_dt_ids); static int fsl_easrc_probe(struct platform_device *pdev) { struct fsl_easrc_priv *easrc_priv; + struct fsl_asrc_m2m_pdata m2m_pdata; struct device *dev = >dev; struct fsl_asrc *easrc; struct resource *res; @@ -2171,11 +2172,29 @@ static int fsl_easrc_probe(struct platform_device *pdev) return ret; } + m2m_pdata.asrc = easrc; + m2m_pdata.fmt_in = FSL_EASRC_FORMATS; + m2m_pdata.fmt_out = FSL_EASRC_FORMATS | SNDRV_PCM_FMTBIT_IEC958_SUBFRAME_LE; + m2m_pdata.rate_min = 8000; + m2m_pdata.rate_max = 768000; + m2m_pdata.chan_min = 1; + m2m_pdata.chan_max = 32; + easrc->m2m_pdev = platform_device_register_data(>dev, + M2M_DRV_NAME, + PLATFORM_DEVID_AUTO, + _pdata, + sizeof(m2m_pdata)); + return 0; } static void fsl_easrc_remove(struct platform_device *pdev) { + struct fsl_asrc *easrc = dev_get_drvdata(>dev); + + if (easrc->m2m_pdev && !IS_ERR(easrc->m2m_pdev)) + platform_device_unregister(easrc->m2m_pdev); + pm_runtime_disable(>dev); } -- 2.34.1
[RFC PATCH v5 04/11] ASoC: fsl_asrc: register m2m platform device
Register m2m platform device, that user can use M2M feature. Defined platform data structure and platform driver name. Signed-off-by: Shengjiu Wang --- include/sound/fsl_asrc_common.h | 23 +++ sound/soc/fsl/fsl_asrc.c| 18 ++ 2 files changed, 41 insertions(+) diff --git a/include/sound/fsl_asrc_common.h b/include/sound/fsl_asrc_common.h index 8a1ac88aedac..9a8209b698f2 100644 --- a/include/sound/fsl_asrc_common.h +++ b/include/sound/fsl_asrc_common.h @@ -69,6 +69,7 @@ struct fsl_asrc_pair { * @dma_params_rx: DMA parameters for receive channel * @dma_params_tx: DMA parameters for transmit channel * @pdev: platform device pointer + * @m2m_pdev: m2m platform device pointer * @regmap: regmap handler * @paddr: physical address to the base address of registers * @mem_clk: clock source to access register @@ -101,6 +102,7 @@ struct fsl_asrc { struct snd_dmaengine_dai_dma_data dma_params_rx; struct snd_dmaengine_dai_dma_data dma_params_tx; struct platform_device *pdev; + struct platform_device *m2m_pdev; struct regmap *regmap; unsigned long paddr; struct clk *mem_clk; @@ -137,6 +139,27 @@ struct fsl_asrc { void *private; }; +/** + * struct fsl_asrc_m2m_pdata - platform data + * @asrc: pointer to struct fsl_asrc + * @fmt_in: input sample format + * @fmt_out: output sample format + * @chan_min: minimum channel number + * @chan_max: maximum channel number + * @rate_min: minimum rate + * @rate_max: maximum rete + */ +struct fsl_asrc_m2m_pdata { + struct fsl_asrc *asrc; + u64 fmt_in; + u64 fmt_out; + int chan_min; + int chan_max; + int rate_min; + int rate_max; +}; + +#define M2M_DRV_NAME "fsl_asrc_m2m" #define DRV_NAME "fsl-asrc-dai" extern struct snd_soc_component_driver fsl_asrc_component; diff --git a/sound/soc/fsl/fsl_asrc.c b/sound/soc/fsl/fsl_asrc.c index 47db476ac47a..a9837d5d9124 100644 --- a/sound/soc/fsl/fsl_asrc.c +++ b/sound/soc/fsl/fsl_asrc.c @@ -1179,6 +1179,7 @@ static int fsl_asrc_runtime_suspend(struct device *dev); static int fsl_asrc_probe(struct platform_device *pdev) { struct device_node *np = pdev->dev.of_node; + struct fsl_asrc_m2m_pdata m2m_pdata; struct fsl_asrc_priv *asrc_priv; struct fsl_asrc *asrc; struct resource *res; @@ -1360,6 +1361,18 @@ static int fsl_asrc_probe(struct platform_device *pdev) goto err_pm_get_sync; } + m2m_pdata.asrc = asrc; + m2m_pdata.fmt_in = FSL_ASRC_FORMATS; + m2m_pdata.fmt_out = FSL_ASRC_FORMATS | SNDRV_PCM_FMTBIT_S8; + m2m_pdata.rate_min = 5512; + m2m_pdata.rate_max = 192000; + m2m_pdata.chan_min = 1; + m2m_pdata.chan_max = 10; + asrc->m2m_pdev = platform_device_register_data(>dev, + M2M_DRV_NAME, + PLATFORM_DEVID_AUTO, + _pdata, + sizeof(m2m_pdata)); return 0; err_pm_get_sync: @@ -1372,6 +1385,11 @@ static int fsl_asrc_probe(struct platform_device *pdev) static void fsl_asrc_remove(struct platform_device *pdev) { + struct fsl_asrc *asrc = dev_get_drvdata(>dev); + + if (asrc->m2m_pdev && !IS_ERR(asrc->m2m_pdev)) + platform_device_unregister(asrc->m2m_pdev); + pm_runtime_disable(>dev); if (!pm_runtime_status_suspended(>dev)) fsl_asrc_runtime_suspend(>dev); -- 2.34.1
[RFC PATCH v5 03/11] ASoC: fsl_asrc: move fsl_asrc_common.h to include/sound
Move fsl_asrc_common.h to include/sound that it can be included from other drivers. Signed-off-by: Shengjiu Wang --- {sound/soc/fsl => include/sound}/fsl_asrc_common.h | 0 sound/soc/fsl/fsl_asrc.h | 2 +- sound/soc/fsl/fsl_asrc_dma.c | 2 +- sound/soc/fsl/fsl_easrc.h | 2 +- 4 files changed, 3 insertions(+), 3 deletions(-) rename {sound/soc/fsl => include/sound}/fsl_asrc_common.h (100%) diff --git a/sound/soc/fsl/fsl_asrc_common.h b/include/sound/fsl_asrc_common.h similarity index 100% rename from sound/soc/fsl/fsl_asrc_common.h rename to include/sound/fsl_asrc_common.h diff --git a/sound/soc/fsl/fsl_asrc.h b/sound/soc/fsl/fsl_asrc.h index 1c492eb237f5..66544624de7b 100644 --- a/sound/soc/fsl/fsl_asrc.h +++ b/sound/soc/fsl/fsl_asrc.h @@ -10,7 +10,7 @@ #ifndef _FSL_ASRC_H #define _FSL_ASRC_H -#include "fsl_asrc_common.h" +#include #define ASRC_M2M_INPUTFIFO_WML 0x4 #define ASRC_M2M_OUTPUTFIFO_WML0x2 diff --git a/sound/soc/fsl/fsl_asrc_dma.c b/sound/soc/fsl/fsl_asrc_dma.c index 05a7d1588d20..b034fee3f1f4 100644 --- a/sound/soc/fsl/fsl_asrc_dma.c +++ b/sound/soc/fsl/fsl_asrc_dma.c @@ -12,7 +12,7 @@ #include #include -#include "fsl_asrc_common.h" +#include #define FSL_ASRC_DMABUF_SIZE (256 * 1024) diff --git a/sound/soc/fsl/fsl_easrc.h b/sound/soc/fsl/fsl_easrc.h index bee887c8b4f2..f571647c508f 100644 --- a/sound/soc/fsl/fsl_easrc.h +++ b/sound/soc/fsl/fsl_easrc.h @@ -9,7 +9,7 @@ #include #include -#include "fsl_asrc_common.h" +#include /* EASRC Register Map */ -- 2.34.1
[RFC PATCH v5 02/11] ASoC: fsl_easrc: define functions for memory to memory usage
ASRC can be used on memory to memory case, define several functions for m2m usage and export them as function pointer. Signed-off-by: Shengjiu Wang --- sound/soc/fsl/fsl_easrc.c | 195 ++ sound/soc/fsl/fsl_easrc.h | 6 ++ 2 files changed, 201 insertions(+) diff --git a/sound/soc/fsl/fsl_easrc.c b/sound/soc/fsl/fsl_easrc.c index ba62995c909a..50aee04e7915 100644 --- a/sound/soc/fsl/fsl_easrc.c +++ b/sound/soc/fsl/fsl_easrc.c @@ -1861,6 +1861,192 @@ static int fsl_easrc_get_fifo_addr(u8 dir, enum asrc_pair_index index) return REG_EASRC_FIFO(dir, index); } +/* Get sample numbers in FIFO */ +static unsigned int fsl_easrc_get_output_fifo_size(struct fsl_asrc_pair *pair) +{ + struct fsl_asrc *asrc = pair->asrc; + enum asrc_pair_index index = pair->index; + u32 val; + + regmap_read(asrc->regmap, REG_EASRC_SFS(index), ); + val &= EASRC_SFS_NSGO_MASK; + + return val >> EASRC_SFS_NSGO_SHIFT; +} + +static int fsl_easrc_m2m_start_part_one(struct fsl_asrc_pair *pair) +{ + struct fsl_easrc_ctx_priv *ctx_priv = pair->private; + struct fsl_asrc *asrc = pair->asrc; + struct device *dev = >pdev->dev; + int ret; + + ctx_priv->in_params.sample_rate = pair->rate[IN]; + ctx_priv->in_params.sample_format = pair->sample_format[IN]; + ctx_priv->out_params.sample_rate = pair->rate[OUT]; + ctx_priv->out_params.sample_format = pair->sample_format[OUT]; + + ctx_priv->in_params.fifo_wtmk = FSL_EASRC_INPUTFIFO_WML; + ctx_priv->out_params.fifo_wtmk = FSL_EASRC_OUTPUTFIFO_WML; + /* Fill the right half of the re-sampler with zeros */ + ctx_priv->rs_init_mode = 0x2; + /* Zero fill the right half of the prefilter */ + ctx_priv->pf_init_mode = 0x2; + + ret = fsl_easrc_set_ctx_format(pair, + _priv->in_params.sample_format, + _priv->out_params.sample_format); + if (ret) { + dev_err(dev, "failed to set context format: %d\n", ret); + return ret; + } + + ret = fsl_easrc_config_context(asrc, pair->index); + if (ret) { + dev_err(dev, "failed to config context %d\n", ret); + return ret; + } + + ctx_priv->in_params.iterations = 1; + ctx_priv->in_params.group_len = pair->channels; + ctx_priv->in_params.access_len = pair->channels; + ctx_priv->out_params.iterations = 1; + ctx_priv->out_params.group_len = pair->channels; + ctx_priv->out_params.access_len = pair->channels; + + ret = fsl_easrc_set_ctx_organziation(pair); + if (ret) { + dev_err(dev, "failed to set fifo organization\n"); + return ret; + } + + /* The context start flag */ + ctx_priv->first_convert = 1; + return 0; +} + +static int fsl_easrc_m2m_start_part_two(struct fsl_asrc_pair *pair) +{ + struct fsl_easrc_ctx_priv *ctx_priv = pair->private; + /* start context once */ + if (ctx_priv->first_convert) { + fsl_easrc_start_context(pair); + ctx_priv->first_convert = 0; + } + + return 0; +} + +static int fsl_easrc_m2m_stop_part_two(struct fsl_asrc_pair *pair) +{ + struct fsl_easrc_ctx_priv *ctx_priv = pair->private; + /* Stop pair/context */ + if (!ctx_priv->first_convert) { + fsl_easrc_stop_context(pair); + ctx_priv->first_convert = 1; + } + + return 0; +} + +/* calculate capture data length according to output data length and sample rate */ +static int fsl_easrc_m2m_calc_out_len(struct fsl_asrc_pair *pair, int input_buffer_length) +{ + struct fsl_asrc *easrc = pair->asrc; + struct fsl_easrc_priv *easrc_priv = easrc->private; + struct fsl_easrc_ctx_priv *ctx_priv = pair->private; + unsigned int in_rate = ctx_priv->in_params.norm_rate; + unsigned int out_rate = ctx_priv->out_params.norm_rate; + unsigned int channels = pair->channels; + unsigned int in_samples, out_samples; + unsigned int in_width, out_width; + unsigned int out_length; + unsigned int frac_bits; + u64 val1, val2; + + switch (easrc_priv->rs_num_taps) { + case EASRC_RS_32_TAPS: + /* integer bits = 5; */ + frac_bits = 39; + break; + case EASRC_RS_64_TAPS: + /* integer bits = 6; */ + frac_bits = 38; + break; + case EASRC_RS_128_TAPS: + /* integer bits = 7; */ + frac_bits = 37; + break; + default: + return -EINVAL; + } + + val1 = (u64)in_rate << frac_bits; + do_div(val1, out_rate); + val1 = val1 + (ctx_priv->ratio_mod << (frac_bits - 31)); + + in_width = snd_pcm_format_physical_width(ctx_priv->in_params.sample_format) / 8; +
[RFC PATCH v5 01/11] ASoC: fsl_asrc: define functions for memory to memory usage
ASRC can be used on memory to memory case, define several functions for m2m usage. m2m_start_part_one: first part of the start steps m2m_start_part_two: second part of the start steps m2m_stop_part_one: first part of stop steps m2m_stop_part_two: second part of stop steps, optional m2m_check_format: check format is supported or not m2m_calc_out_len: calculate output length according to input length m2m_get_maxburst: burst size for dma m2m_pair_suspend: suspend function of pair, optional. m2m_pair_resume: resume function of pair get_output_fifo_size: get remaining data size in FIFO Signed-off-by: Shengjiu Wang --- sound/soc/fsl/fsl_asrc.c| 118 sound/soc/fsl/fsl_asrc.h| 2 + sound/soc/fsl/fsl_asrc_common.h | 35 ++ 3 files changed, 155 insertions(+) diff --git a/sound/soc/fsl/fsl_asrc.c b/sound/soc/fsl/fsl_asrc.c index b793263291dc..47db476ac47a 100644 --- a/sound/soc/fsl/fsl_asrc.c +++ b/sound/soc/fsl/fsl_asrc.c @@ -1063,6 +1063,116 @@ static int fsl_asrc_get_fifo_addr(u8 dir, enum asrc_pair_index index) return REG_ASRDx(dir, index); } +/* Get sample numbers in FIFO */ +static unsigned int fsl_asrc_get_output_fifo_size(struct fsl_asrc_pair *pair) +{ + struct fsl_asrc *asrc = pair->asrc; + enum asrc_pair_index index = pair->index; + u32 val; + + regmap_read(asrc->regmap, REG_ASRFST(index), ); + + val &= ASRFSTi_OUTPUT_FIFO_MASK; + + return val >> ASRFSTi_OUTPUT_FIFO_SHIFT; +} + +static int fsl_asrc_m2m_start_part_one(struct fsl_asrc_pair *pair) +{ + struct fsl_asrc_pair_priv *pair_priv = pair->private; + struct fsl_asrc *asrc = pair->asrc; + struct device *dev = >pdev->dev; + struct asrc_config config; + int ret; + + /* fill config */ + config.pair = pair->index; + config.channel_num = pair->channels; + config.input_sample_rate = pair->rate[IN]; + config.output_sample_rate = pair->rate[OUT]; + config.input_format = pair->sample_format[IN]; + config.output_format = pair->sample_format[OUT]; + config.inclk = INCLK_NONE; + config.outclk = OUTCLK_ASRCK1_CLK; + + pair_priv->config = + ret = fsl_asrc_config_pair(pair, true); + if (ret) { + dev_err(dev, "failed to config pair: %d\n", ret); + return ret; + } + + fsl_asrc_start_pair(pair); + + return 0; +} + +static int fsl_asrc_m2m_start_part_two(struct fsl_asrc_pair *pair) +{ + /* +* Clear DMA request during the stall state of ASRC: +* During STALL state, the remaining in input fifo would never be +* smaller than the input threshold while the output fifo would not +* be bigger than output one. Thus the DMA request would be cleared. +*/ + fsl_asrc_set_watermarks(pair, ASRC_FIFO_THRESHOLD_MIN, + ASRC_FIFO_THRESHOLD_MAX); + + /* Update the real input threshold to raise DMA request */ + fsl_asrc_set_watermarks(pair, ASRC_M2M_INPUTFIFO_WML, + ASRC_M2M_OUTPUTFIFO_WML); + + return 0; +} + +static int fsl_asrc_m2m_stop_part_one(struct fsl_asrc_pair *pair) +{ + fsl_asrc_stop_pair(pair); + + return 0; +} + +/* calculate capture data length according to output data length and sample rate */ +static int fsl_asrc_m2m_calc_out_len(struct fsl_asrc_pair *pair, int input_buffer_length) +{ + unsigned int in_width, out_width; + unsigned int channels = pair->channels; + unsigned int in_samples, out_samples; + unsigned int out_length; + + in_width = snd_pcm_format_physical_width(pair->sample_format[IN]) / 8; + out_width = snd_pcm_format_physical_width(pair->sample_format[OUT]) / 8; + + in_samples = input_buffer_length / in_width / channels; + out_samples = pair->rate[OUT] * in_samples / pair->rate[IN]; + out_length = (out_samples - ASRC_OUTPUT_LAST_SAMPLE) * out_width * channels; + + return out_length; +} + +static int fsl_asrc_m2m_get_maxburst(u8 dir, struct fsl_asrc_pair *pair) +{ + struct fsl_asrc *asrc = pair->asrc; + struct fsl_asrc_priv *asrc_priv = asrc->private; + int wml = (dir == IN) ? ASRC_M2M_INPUTFIFO_WML : ASRC_M2M_OUTPUTFIFO_WML; + + if (!asrc_priv->soc->use_edma) + return wml * pair->channels; + else + return 1; +} + +static int fsl_asrc_m2m_pair_resume(struct fsl_asrc_pair *pair) +{ + struct fsl_asrc *asrc = pair->asrc; + int i; + + for (i = 0; i < pair->channels * 4; i++) + regmap_write(asrc->regmap, REG_ASRDI(pair->index), 0); + + return 0; +} + static int fsl_asrc_runtime_resume(struct device *dev); static int fsl_asrc_runtime_suspend(struct device *dev); @@ -1147,6 +1257,14 @@ static int fsl_asrc_probe(struct platform_device *pdev) asrc->get_fifo_addr = fsl_asrc_get_fifo_addr;
[RFC PATCH v5 00/11] Add audio support in v4l2 framework
Audio signal processing also has the requirement for memory to memory similar as Video. This asrc memory to memory (memory ->asrc->memory) case is a non real time use case. User fills the input buffer to the asrc module, after conversion, then asrc sends back the output buffer to user. So it is not a traditional ALSA playback and capture case. It is a specific use case, there is no reference in current kernel. v4l2 memory to memory is the closed implementation, v4l2 current support video, image, radio, tuner, touch devices, so it is not complicated to add support for this specific audio case. Because we had implemented the "memory -> asrc ->i2s device-> codec" use case in ALSA. Now the "memory->asrc->memory" needs to reuse the code in asrc driver, so the first 3 patches is for refining the code to make it can be shared by the "memory->asrc->memory" driver. The main change is in the v4l2 side, A /dev/vl4-audioX will be created, user applications only use the ioctl of v4l2 framework. Other change is to add memory to memory support for two kinds of i.MX ASRC module. changes in v5: - remove V4L2_AUDIO_FMT_LPCM - define audio pixel format like V4L2_AUDIO_FMT_S8... - remove rate and format in struct v4l2_audio_format. - Add V4L2_CID_ASRC_SOURCE_RATE and V4L2_CID_ASRC_DEST_RATE controls - updata document accordingly. changes in v4: - update document style - separate V4L2_AUDIO_FMT_LPCM and V4L2_CAP_AUDIO_M2M in separate commit changes in v3: - Modify documents for adding audio m2m support - Add audio virtual m2m driver - Defined V4L2_AUDIO_FMT_LPCM format type for audio. - Defined V4L2_CAP_AUDIO_M2M capability type for audio m2m case. - with modification in v4l-utils, pass v4l2-compliance test. changes in v2: - decouple the implementation in v4l2 and ALSA - implement the memory to memory driver as a platfrom driver and move it to driver/media - move fsl_asrc_common.h to include/sound folder Shengjiu Wang (11): ASoC: fsl_asrc: define functions for memory to memory usage ASoC: fsl_easrc: define functions for memory to memory usage ASoC: fsl_asrc: move fsl_asrc_common.h to include/sound ASoC: fsl_asrc: register m2m platform device ASoC: fsl_easrc: register m2m platform device media: uapi: Add V4L2_CAP_AUDIO_M2M capability flag media: v4l2: Add audio capture and output support media: uapi: Add audio rate controls support media: uapi: define audio sample format fourcc type media: imx-asrc: Add memory to memory driver media: audm2m: add virtual driver for audio memory to memory .../userspace-api/media/v4l/buffer.rst|6 + .../userspace-api/media/v4l/common.rst|1 + .../media/v4l/dev-audio-mem2mem.rst | 71 + .../userspace-api/media/v4l/devices.rst |1 + .../media/v4l/ext-ctrls-asrc-rate.rst | 36 + .../userspace-api/media/v4l/pixfmt-audio.rst | 277 .../userspace-api/media/v4l/pixfmt.rst|1 + .../media/v4l/vidioc-enum-fmt.rst |2 + .../media/v4l/vidioc-g-ext-ctrls.rst |4 + .../userspace-api/media/v4l/vidioc-g-fmt.rst |4 + .../media/v4l/vidioc-querycap.rst |3 + .../media/v4l/vidioc-queryctrl.rst|7 + .../media/videodev2.h.rst.exceptions |4 + .../media/common/videobuf2/videobuf2-v4l2.c |4 + drivers/media/platform/nxp/Kconfig| 12 + drivers/media/platform/nxp/Makefile |1 + drivers/media/platform/nxp/imx-asrc.c | 1251 + drivers/media/test-drivers/Kconfig|9 + drivers/media/test-drivers/Makefile |1 + drivers/media/test-drivers/audm2m.c | 808 +++ drivers/media/v4l2-core/v4l2-ctrls-core.c |5 + drivers/media/v4l2-core/v4l2-ctrls-defs.c |4 + drivers/media/v4l2-core/v4l2-dev.c| 17 + drivers/media/v4l2-core/v4l2-ioctl.c | 104 ++ include/media/v4l2-ctrls.h|1 + include/media/v4l2-dev.h |2 + include/media/v4l2-ioctl.h| 34 + .../fsl => include/sound}/fsl_asrc_common.h | 58 + include/uapi/linux/v4l2-controls.h| 13 + include/uapi/linux/videodev2.h| 77 + sound/soc/fsl/fsl_asrc.c | 136 ++ sound/soc/fsl/fsl_asrc.h |4 +- sound/soc/fsl/fsl_asrc_dma.c |2 +- sound/soc/fsl/fsl_easrc.c | 214 +++ sound/soc/fsl/fsl_easrc.h |8 +- 35 files changed, 3179 insertions(+), 3 deletions(-) create mode 100644 Documentation/userspace-api/media/v4l/dev-audio-mem2mem.rst create mode 100644 Documentation/userspace-api/media/v4l/ext-ctrls-asrc-rate.rst create mode 100644 Documentation/userspace-api/media/v4l/pixfmt-audio.rst create mode 100644 drivers/media/platform/nxp/imx-asrc.c create mode 100644 drivers/media/test-drivers/audm2m.c rename {sound/soc/fsl =>
[PATCH V5 3/3] tools/perf/tests: Fix object code reading to skip address that falls out of text section
The testcase "Object code reading" fails in somecases for "fs_something" sub test as below: Reading object code for memory address: 0xc00807f0142c File is: /lib/modules/6.5.0-rc3+/kernel/fs/xfs/xfs.ko On file address is: 0x1114cc Objdump command is: objdump -z -d --start-address=0x11142c --stop-address=0x1114ac /lib/modules/6.5.0-rc3+/kernel/fs/xfs/xfs.ko objdump read too few bytes: 128 test child finished with -1 This can alo be reproduced when running perf record with workload that exercises fs_something() code. In the test setup, this is exercising xfs code since root is xfs. # perf record ./a.out # perf report -v |grep "xfs.ko" 0.76% a.out /lib/modules/6.5.0-rc3+/kernel/fs/xfs/xfs.ko 0xc00807de5efc B [k] xlog_cil_commit 0.74% a.out /lib/modules/6.5.0-rc3+/kernel/fs/xfs/xfs.ko 0xc00807d5ae18 B [k] xfs_btree_key_offset 0.74% a.out /lib/modules/6.5.0-rc3+/kernel/fs/xfs/xfs.ko 0xc00807e11fd4 B [k] 0x00112074 Here addr "0xc00807e11fd4" is not resolved. since this is a kernel module, its offset is from the DSO. Xfs module is loaded at 0xc00807d0 # cat /proc/modules | grep xfs xfs 2228224 3 - Live 0xc00807d0 And size is 0x22. So its loaded between 0xc00807d0 and 0xc00807f2. From objdump, text section is: text 0010f7bc 00a0 2**4 Hence perf captured ip maps to 0x112074 which is: ( ip - start of module ) + a0 This offset 0x112074 falls out .text section which is up to 0x10f7bc In this case for module, the address 0xc00807e11fd4 is pointing to stub instructions. This address range represents the module stubs which is allocated on module load and hence is not part of DSO offset. To address this issue in "object code reading", skip the sample if address falls out of text section and is within the module end. Use the "text_end" member of "struct dso" to do this check. To address this issue in "perf report", exploring an option of having stubs range as part of the /proc/kallsyms, so that perf report can resolve addresses in stubs range However this patch uses text_end to skip the stub range for Object code reading testcase. Reported-by: Disha Goel Signed-off-by: Athira Rajeev Tested-by: Disha Goel Reviewed-by: Adrian Hunter Reviewed-by: Kajol Jain --- Changelog: v4 -> v5: Used dso->is_kmod to check if the dso is a kernel module v3 -> v4: Fixed indent in V3 v2 -> v3: Used strtailcmp in comparison for module check and added Reviewed-by from Adrian, Tested-by from Disha. v1 -> v2: Updated comment to add description on which arch has stub and reason for skipping as suggested by Adrian tools/perf/tests/code-reading.c | 10 ++ 1 file changed, 10 insertions(+) diff --git a/tools/perf/tests/code-reading.c b/tools/perf/tests/code-reading.c index ed3815163d1b..3af81012014e 100644 --- a/tools/perf/tests/code-reading.c +++ b/tools/perf/tests/code-reading.c @@ -269,6 +269,16 @@ static int read_object_code(u64 addr, size_t len, u8 cpumode, if (addr + len > map__end(al.map)) len = map__end(al.map) - addr; + /* +* Some architectures (ex: powerpc) have stubs (trampolines) in kernel +* modules to manage long jumps. Check if the ip offset falls in stubs +* sections for kernel modules. And skip module address after text end +*/ + if (dso->is_kmod && al.addr > dso->text_end) { + pr_debug("skipping the module address %#"PRIx64" after text end\n", al.addr); + goto out; + } + /* Read the object code using perf */ ret_len = dso__data_read_offset(dso, maps__machine(thread__maps(thread)), al.addr, buf1, len); -- 2.31.1
[PATCH V5 2/3] tools/perf: Add "is_kmod" to struct dso to check if it is kernel module
Update "struct dso" to include new member "is_kmod". This new field will determine if the file is a kernel module or not. To resolve the address from a sample, perf looks at the DSO maps. In case of address from a kernel module, there were some address found to be not resolved. This was observed while running perf test for "Object code reading". Though the ip falls beteen the start address of the loaded module (perf map->start ) and end address ( perf map->end), it was unresolved. This was happening because in some cases for kernel modules, address from sample points to stub instructions. To identify if the DSO is a kernel module, the new field "is_kmod" is added to "struct dso". Reported-by: Disha Goel Signed-off-by: Athira Rajeev --- Changelog: v5: This patch adds is_kmod field to dso to detect if the dso is a kernel module tools/perf/util/dso.c | 2 ++ tools/perf/util/dso.h | 1 + 2 files changed, 3 insertions(+) diff --git a/tools/perf/util/dso.c b/tools/perf/util/dso.c index bdfead36b83a..1f629b6fb7cf 100644 --- a/tools/perf/util/dso.c +++ b/tools/perf/util/dso.c @@ -477,6 +477,7 @@ void dso__set_module_info(struct dso *dso, struct kmod_path *m, dso->comp = m->comp; } + dso->is_kmod = 1; dso__set_short_name(dso, strdup(m->name), true); } @@ -1338,6 +1339,7 @@ struct dso *dso__new_id(const char *name, struct dso_id *id) dso->has_srcline = 1; dso->a2l_fails = 1; dso->kernel = DSO_SPACE__USER; + dso->is_kmod = 0; dso->needs_swap = DSO_SWAP__UNSET; dso->comp = COMP_ID__NONE; RB_CLEAR_NODE(>rb_node); diff --git a/tools/perf/util/dso.h b/tools/perf/util/dso.h index 70fe0fe69bef..3759de8c2267 100644 --- a/tools/perf/util/dso.h +++ b/tools/perf/util/dso.h @@ -162,6 +162,7 @@ struct dso { char *symsrc_filename; unsigned int a2l_fails; enum dso_space_type kernel; + boolis_kmod; enum dso_swap_type needs_swap; enum dso_binary_typesymtab_type; enum dso_binary_typebinary_type; -- 2.31.1
[PATCH V5 1/3] tools/perf: Add text_end to "struct dso" to save .text section size
Update "struct dso" to include new member "text_end". This new field will represent the offset for end of text section for a dso. For elf, this value is derived as: sh_size (Size of section in byes) + sh_offset (Section file offst) of the elf header for text. For bfd, this value is derived as: 1. For PE file, section->size + ( section->vma - dso->text_offset) 2. Other cases: section->filepos (file position) + section->size (size of section) To resolve the address from a sample, perf looks at the DSO maps. In case of address from a kernel module, there were some address found to be not resolved. This was observed while running perf test for "Object code reading". Though the ip falls beteen the start address of the loaded module (perf map->start ) and end address ( perf map->end), it was unresolved. Example: Reading object code for memory address: 0xc00807f0142c File is: /lib/modules/6.5.0-rc3+/kernel/fs/xfs/xfs.ko On file address is: 0x1114cc Objdump command is: objdump -z -d --start-address=0x11142c --stop-address=0x1114ac /lib/modules/6.5.0-rc3+/kernel/fs/xfs/xfs.ko objdump read too few bytes: 128 test child finished with -1 Here, module is loaded at: # cat /proc/modules | grep xfs xfs 2228224 3 - Live 0xc00807d0 >From objdump for xfs module, text section is: text 0010f7bc 00a0 2**4 Here the offset for 0xc00807f0142c ie 0x112074 falls out .text section which is up to 0x10f7bc. In this case for module, the address 0xc00807e11fd4 is pointing to stub instructions. This address range represents the module stubs which is allocated on module load and hence is not part of DSO offset. To identify such address, which falls out of text section and within module end, added the new field "text_end" to "struct dso". Reported-by: Disha Goel Signed-off-by: Athira Rajeev Reviewed-by: Adrian Hunter Reviewed-by: Kajol Jain --- Changelog: v2 -> v3: Added Reviewed-by from Adrian v1 -> v2: Added text_end for bfd also by updating dso__load_bfd_symbols as suggested by Adrian. tools/perf/util/dso.h| 1 + tools/perf/util/symbol-elf.c | 4 +++- tools/perf/util/symbol.c | 2 ++ 3 files changed, 6 insertions(+), 1 deletion(-) diff --git a/tools/perf/util/dso.h b/tools/perf/util/dso.h index b41c9782c754..70fe0fe69bef 100644 --- a/tools/perf/util/dso.h +++ b/tools/perf/util/dso.h @@ -181,6 +181,7 @@ struct dso { u8 rel; struct build_id bid; u64 text_offset; + u64 text_end; const char *short_name; const char *long_name; u16 long_name_len; diff --git a/tools/perf/util/symbol-elf.c b/tools/perf/util/symbol-elf.c index 95e99c332d7e..9e7eeaf616b8 100644 --- a/tools/perf/util/symbol-elf.c +++ b/tools/perf/util/symbol-elf.c @@ -1514,8 +1514,10 @@ dso__load_sym_internal(struct dso *dso, struct map *map, struct symsrc *syms_ss, } if (elf_section_by_name(runtime_ss->elf, _ss->ehdr, , - ".text", NULL)) + ".text", NULL)) { dso->text_offset = tshdr.sh_addr - tshdr.sh_offset; + dso->text_end = tshdr.sh_offset + tshdr.sh_size; + } if (runtime_ss->opdsec) opddata = elf_rawdata(runtime_ss->opdsec, NULL); diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c index 3f36675b7c8f..f25e4e62cf25 100644 --- a/tools/perf/util/symbol.c +++ b/tools/perf/util/symbol.c @@ -1733,8 +1733,10 @@ int dso__load_bfd_symbols(struct dso *dso, const char *debugfile) /* PE symbols can only have 4 bytes, so use .text high bits */ dso->text_offset = section->vma - (u32)section->vma; dso->text_offset += (u32)bfd_asymbol_value(symbols[i]); + dso->text_end = (section->vma - dso->text_offset) + section->size; } else { dso->text_offset = section->vma - section->filepos; + dso->text_end = section->filepos + section->size; } } -- 2.31.1
[PATCH v7 30/30] net: wan: fsl_qmc_hdlc: Add framer support
Add framer support in the fsl_qmc_hdlc driver in order to be able to signal carrier changes to the network stack based on the framer status Also use this framer to provide information related to the E1/T1 line interface on IF_GET_IFACE and configure the line interface according to IF_IFACE_{E1,T1} information. Signed-off-by: Herve Codina Reviewed-by: Christophe Leroy --- drivers/net/wan/fsl_qmc_hdlc.c | 239 - 1 file changed, 235 insertions(+), 4 deletions(-) diff --git a/drivers/net/wan/fsl_qmc_hdlc.c b/drivers/net/wan/fsl_qmc_hdlc.c index 24f466fa48b1..e5982766ff71 100644 --- a/drivers/net/wan/fsl_qmc_hdlc.c +++ b/drivers/net/wan/fsl_qmc_hdlc.c @@ -8,6 +8,7 @@ */ #include +#include #include #include #include @@ -27,6 +28,9 @@ struct qmc_hdlc { struct device *dev; struct qmc_chan *qmc_chan; struct net_device *netdev; + struct framer *framer; + spinlock_t carrier_lock; /* Protect carrier detection */ + struct notifier_block nb; bool is_crc32; spinlock_t tx_lock; /* Protect tx descriptors */ struct qmc_hdlc_desc tx_descs[8]; @@ -40,6 +44,195 @@ static inline struct qmc_hdlc *netdev_to_qmc_hdlc(struct net_device *netdev) return dev_to_hdlc(netdev)->priv; } +static int qmc_hdlc_framer_set_carrier(struct qmc_hdlc *qmc_hdlc) +{ + struct framer_status framer_status; + unsigned long flags; + int ret; + + if (!qmc_hdlc->framer) + return 0; + + spin_lock_irqsave(_hdlc->carrier_lock, flags); + + ret = framer_get_status(qmc_hdlc->framer, _status); + if (ret) { + dev_err(qmc_hdlc->dev, "get framer status failed (%d)\n", ret); + goto end; + } + if (framer_status.link_is_on) + netif_carrier_on(qmc_hdlc->netdev); + else + netif_carrier_off(qmc_hdlc->netdev); + +end: + spin_unlock_irqrestore(_hdlc->carrier_lock, flags); + return ret; +} + +static int qmc_hdlc_framer_notifier(struct notifier_block *nb, unsigned long action, + void *data) +{ + struct qmc_hdlc *qmc_hdlc = container_of(nb, struct qmc_hdlc, nb); + int ret; + + if (action != FRAMER_EVENT_STATUS) + return NOTIFY_DONE; + + ret = qmc_hdlc_framer_set_carrier(qmc_hdlc); + return ret ? NOTIFY_DONE : NOTIFY_OK; +} + +static int qmc_hdlc_framer_start(struct qmc_hdlc *qmc_hdlc) +{ + struct framer_status framer_status; + int ret; + + if (!qmc_hdlc->framer) + return 0; + + ret = framer_power_on(qmc_hdlc->framer); + if (ret) { + dev_err(qmc_hdlc->dev, "framer power-on failed (%d)\n", ret); + return ret; + } + + /* Be sure that get_status is supported */ + ret = framer_get_status(qmc_hdlc->framer, _status); + if (ret) { + dev_err(qmc_hdlc->dev, "get framer status failed (%d)\n", ret); + goto framer_power_off; + } + + qmc_hdlc->nb.notifier_call = qmc_hdlc_framer_notifier; + ret = framer_notifier_register(qmc_hdlc->framer, _hdlc->nb); + if (ret) { + dev_err(qmc_hdlc->dev, "framer notifier register failed (%d)\n", ret); + goto framer_power_off; + } + + return 0; + +framer_power_off: + framer_power_off(qmc_hdlc->framer); + return ret; +} + +static void qmc_hdlc_framer_stop(struct qmc_hdlc *qmc_hdlc) +{ + if (!qmc_hdlc->framer) + return; + + framer_notifier_unregister(qmc_hdlc->framer, _hdlc->nb); + framer_power_off(qmc_hdlc->framer); +} + +static int qmc_hdlc_framer_set_iface(struct qmc_hdlc *qmc_hdlc, int if_iface, +const te1_settings *te1) +{ + struct framer_config config; + int ret; + + if (!qmc_hdlc->framer) + return 0; + + ret = framer_get_config(qmc_hdlc->framer, ); + if (ret) + return ret; + + switch (if_iface) { + case IF_IFACE_E1: + config.iface = FRAMER_IFACE_E1; + break; + case IF_IFACE_T1: + config.iface = FRAMER_IFACE_T1; + break; + default: + return -EINVAL; + } + + switch (te1->clock_type) { + case CLOCK_DEFAULT: + /* Keep current value */ + break; + case CLOCK_EXT: + config.clock_type = FRAMER_CLOCK_EXT; + break; + case CLOCK_INT: + config.clock_type = FRAMER_CLOCK_INT; + break; + default: + return -EINVAL; + } + config.line_clock_rate = te1->clock_rate; + + return framer_set_config(qmc_hdlc->framer, ); +} + +static int qmc_hdlc_framer_get_iface(struct qmc_hdlc *qmc_hdlc, int *if_iface, te1_settings *te1) +{ + struct framer_config config; + int
[PATCH v7 29/30] ASoC: codecs: Add support for the framer codec
The framer codec interacts with a framer. It allows to use some of the framer timeslots as audio channels to transport audio data over the framer E1/T1/J1 lines. It also reports line carrier detection events through the ALSA jack detection feature. Signed-off-by: Herve Codina Reviewed-by: Christophe Leroy --- sound/soc/codecs/Kconfig| 15 ++ sound/soc/codecs/Makefile | 2 + sound/soc/codecs/framer-codec.c | 413 3 files changed, 430 insertions(+) create mode 100644 sound/soc/codecs/framer-codec.c diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig index f1e1dbc509f6..abb89796fd45 100644 --- a/sound/soc/codecs/Kconfig +++ b/sound/soc/codecs/Kconfig @@ -112,6 +112,7 @@ config SND_SOC_ALL_CODECS imply SND_SOC_ES8328_I2C imply SND_SOC_ES7134 imply SND_SOC_ES7241 + imply SND_SOC_FRAMER imply SND_SOC_GTM601 imply SND_SOC_HDAC_HDMI imply SND_SOC_HDAC_HDA @@ -1071,6 +1072,20 @@ config SND_SOC_ES8328_SPI depends on SPI_MASTER select SND_SOC_ES8328 +config SND_SOC_FRAMER + tristate "Framer codec" + depends on GENERIC_FRAMER + help + Enable support for the framer codec. + The framer codec uses the generic framer infrastructure to transport + some audio data over an analog E1/T1/J1 line. + This codec allows to use some of the time slots available on the TDM + bus on which the framer is connected to transport the audio data. + + To compile this driver as a module, choose M here: the module + will be called snd-soc-framer. + + config SND_SOC_GTM601 tristate 'GTM601 UMTS modem audio codec' diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile index a87e56938ce5..c6bb88cd687a 100644 --- a/sound/soc/codecs/Makefile +++ b/sound/soc/codecs/Makefile @@ -119,6 +119,7 @@ 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 @@ -505,6 +506,7 @@ obj-$(CONFIG_SND_SOC_ES8326)+= snd-soc-es8326.o obj-$(CONFIG_SND_SOC_ES8328) += snd-soc-es8328.o obj-$(CONFIG_SND_SOC_ES8328_I2C)+= snd-soc-es8328-i2c.o obj-$(CONFIG_SND_SOC_ES8328_SPI)+= snd-soc-es8328-spi.o +obj-$(CONFIG_SND_SOC_FRAMER) += snd-soc-framer.o obj-$(CONFIG_SND_SOC_GTM601)+= snd-soc-gtm601.o obj-$(CONFIG_SND_SOC_HDAC_HDMI) += snd-soc-hdac-hdmi.o obj-$(CONFIG_SND_SOC_HDAC_HDA) += snd-soc-hdac-hda.o diff --git a/sound/soc/codecs/framer-codec.c b/sound/soc/codecs/framer-codec.c new file mode 100644 index ..e5fcde9ee308 --- /dev/null +++ b/sound/soc/codecs/framer-codec.c @@ -0,0 +1,413 @@ +// SPDX-License-Identifier: GPL-2.0 +// +// Framer ALSA SoC driver +// +// Copyright 2023 CS GROUP France +// +// Author: Herve Codina + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define FRAMER_NB_CHANNEL 32 +#define FRAMER_JACK_MASK (SND_JACK_LINEIN | SND_JACK_LINEOUT) + +struct framer_codec { + struct framer *framer; + struct device *dev; + struct snd_soc_jack jack; + struct notifier_block nb; + struct work_struct carrier_work; + int max_chan_playback; + int max_chan_capture; +}; + +static int framer_dai_set_tdm_slot(struct snd_soc_dai *dai, unsigned int tx_mask, + unsigned int rx_mask, int slots, int width) +{ + struct framer_codec *framer = snd_soc_component_get_drvdata(dai->component); + + switch (width) { + case 0: + /* Not set -> default 8 */ + case 8: + break; + default: + dev_err(dai->dev, "tdm slot width %d not supported\n", width); + return -EINVAL; + } + + framer->max_chan_playback = hweight32(tx_mask); + if (framer->max_chan_playback > FRAMER_NB_CHANNEL) { + dev_err(dai->dev, "too many tx slots defined (mask = 0x%x) supported max %d\n", + tx_mask, FRAMER_NB_CHANNEL); + return -EINVAL; + } + + framer->max_chan_capture = hweight32(rx_mask); + if (framer->max_chan_capture > FRAMER_NB_CHANNEL) { + dev_err(dai->dev, "too many rx slots defined (mask = 0x%x) supported max %d\n", + rx_mask, FRAMER_NB_CHANNEL); + return -EINVAL; + } + + return 0; +} + +/* + * The constraints for format/channel is to match with the number of 8bit + * time-slots available. + */ +static int framer_dai_hw_rule_channels_by_format(struct snd_soc_dai *dai, +struct snd_pcm_hw_params *params, +unsigned int nb_ts) +{ + struct
[PATCH v7 28/30] MAINTAINERS: Add the Lantiq PEF2256 driver entry
After contributing the driver, add myself as the maintainer for the Lantiq PEF2256 driver. Signed-off-by: Herve Codina Reviewed-by: Christophe Leroy --- MAINTAINERS | 8 1 file changed, 8 insertions(+) diff --git a/MAINTAINERS b/MAINTAINERS index 8b987f2c8633..d8f2433e326e 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -11876,6 +11876,14 @@ S: Maintained F: arch/mips/lantiq F: drivers/soc/lantiq +LANTIQ PEF2256 DRIVER +M: Herve Codina +S: Maintained +F: Documentation/devicetree/bindings/net/lantiq,pef2256.yaml +F: drivers/net/wan/framer/pef2256/ +F: drivers/pinctrl/pinctrl-pef2256.c +F: include/linux/framer/pef2256.h + LASI 53c700 driver for PARISC M: "James E.J. Bottomley" L: linux-s...@vger.kernel.org -- 2.41.0
[PATCH v7 27/30] pinctrl: Add support for the Lantic PEF2256 pinmux
The Lantiq PEF2256 is a framer and line interface component designed to fulfill all required interfacing between an analog E1/T1/J1 line and the digital PCM system highway/H.100 bus. This kind of component can be found in old telecommunication system. It was used to digital transmission of many simultaneous telephone calls by time-division multiplexing. Also using HDLC protocol, WAN networks can be reached through the framer. This pinmux support handles the pin muxing part (pins RP(A..D) and pins XP(A..D)) of the PEF2256. Signed-off-by: Herve Codina Reviewed-by: Christophe Leroy Reviewed-by: Linus Walleij --- drivers/pinctrl/Kconfig | 15 ++ drivers/pinctrl/Makefile | 1 + drivers/pinctrl/pinctrl-pef2256.c | 358 ++ 3 files changed, 374 insertions(+) create mode 100644 drivers/pinctrl/pinctrl-pef2256.c diff --git a/drivers/pinctrl/Kconfig b/drivers/pinctrl/Kconfig index 7dfb7190580e..32728d73e0d1 100644 --- a/drivers/pinctrl/Kconfig +++ b/drivers/pinctrl/Kconfig @@ -366,6 +366,21 @@ config PINCTRL_PALMAS open drain configuration for the Palmas series devices like TPS65913, TPS80036 etc. +config PINCTRL_PEF2256 + tristate "Lantiq PEF2256 (FALC56) pin controller driver" + depends on OF && FRAMER_PEF2256 + select PINMUX + select PINCONF + select GENERIC_PINCONF + help + This option enables the pin controller support for the Lantiq PEF2256 + framer, also known as FALC56. + + If unsure, say N. + + To compile this driver as a module, choose M here: the + module will be called pinctrl-pef2256. + config PINCTRL_PIC32 bool "Microchip PIC32 pin controller driver" depends on OF diff --git a/drivers/pinctrl/Makefile b/drivers/pinctrl/Makefile index dd6cda270294..800c4219fcc1 100644 --- a/drivers/pinctrl/Makefile +++ b/drivers/pinctrl/Makefile @@ -39,6 +39,7 @@ obj-$(CONFIG_PINCTRL_MICROCHIP_SGPIO) += pinctrl-microchip-sgpio.o obj-$(CONFIG_PINCTRL_MLXBF3) += pinctrl-mlxbf3.o obj-$(CONFIG_PINCTRL_OCELOT) += pinctrl-ocelot.o obj-$(CONFIG_PINCTRL_PALMAS) += pinctrl-palmas.o +obj-$(CONFIG_PINCTRL_PEF2256) += pinctrl-pef2256.o obj-$(CONFIG_PINCTRL_PIC32)+= pinctrl-pic32.o obj-$(CONFIG_PINCTRL_PISTACHIO)+= pinctrl-pistachio.o obj-$(CONFIG_PINCTRL_RK805)+= pinctrl-rk805.o diff --git a/drivers/pinctrl/pinctrl-pef2256.c b/drivers/pinctrl/pinctrl-pef2256.c new file mode 100644 index ..868ea33bec3c --- /dev/null +++ b/drivers/pinctrl/pinctrl-pef2256.c @@ -0,0 +1,358 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * PEF2256 also known as FALC56 driver + * + * Copyright 2023 CS GROUP France + * + * Author: Herve Codina + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* Port Configuration 1..4 */ +#define PEF2256_PC1 0x80 +#define PEF2256_PC2 0x81 +#define PEF2256_PC3 0x82 +#define PEF2256_PC4 0x83 +#define PEF2256_12_PC_RPC_MASK GENMASK(6, 4) +#define PEF2256_12_PC_RPC_SYPR FIELD_PREP_CONST(PEF2256_12_PC_RPC_MASK, 0x0) +#define PEF2256_12_PC_RPC_RFMFIELD_PREP_CONST(PEF2256_12_PC_RPC_MASK, 0x1) +#define PEF2256_12_PC_RPC_RFMB FIELD_PREP_CONST(PEF2256_12_PC_RPC_MASK, 0x2) +#define PEF2256_12_PC_RPC_RSIGM FIELD_PREP_CONST(PEF2256_12_PC_RPC_MASK, 0x3) +#define PEF2256_12_PC_RPC_RSIG FIELD_PREP_CONST(PEF2256_12_PC_RPC_MASK, 0x4) +#define PEF2256_12_PC_RPC_DLRFIELD_PREP_CONST(PEF2256_12_PC_RPC_MASK, 0x5) +#define PEF2256_12_PC_RPC_FREEZE FIELD_PREP_CONST(PEF2256_12_PC_RPC_MASK, 0x6) +#define PEF2256_12_PC_RPC_RFSP FIELD_PREP_CONST(PEF2256_12_PC_RPC_MASK, 0x7) +#define PEF2256_12_PC_XPC_MASKGENMASK(4, 0) +#define PEF2256_12_PC_XPC_SYPX FIELD_PREP_CONST(PEF2256_12_PC_XPC_MASK, 0x0) +#define PEF2256_12_PC_XPC_XFMS FIELD_PREP_CONST(PEF2256_12_PC_XPC_MASK, 0x1) +#define PEF2256_12_PC_XPC_XSIG FIELD_PREP_CONST(PEF2256_12_PC_XPC_MASK, 0x2) +#define PEF2256_12_PC_XPC_TCLK FIELD_PREP_CONST(PEF2256_12_PC_XPC_MASK, 0x3) +#define PEF2256_12_PC_XPC_XMFB FIELD_PREP_CONST(PEF2256_12_PC_XPC_MASK, 0x4) +#define PEF2256_12_PC_XPC_XSIGM FIELD_PREP_CONST(PEF2256_12_PC_XPC_MASK, 0x5) +#define PEF2256_12_PC_XPC_DLXFIELD_PREP_CONST(PEF2256_12_PC_XPC_MASK, 0x6) +#define PEF2256_12_PC_XPC_XCLK FIELD_PREP_CONST(PEF2256_12_PC_XPC_MASK, 0x7) +#define PEF2256_12_PC_XPC_XLTFIELD_PREP_CONST(PEF2256_12_PC_XPC_MASK, 0x8) +#define PEF2256_2X_PC_RPC_MASK GENMASK(7, 4) +#define PEF2256_2X_PC_RPC_SYPR FIELD_PREP_CONST(PEF2256_2X_PC_RPC_MASK, 0x0) +#define PEF2256_2X_PC_RPC_RFMFIELD_PREP_CONST(PEF2256_2X_PC_RPC_MASK, 0x1) +#define PEF2256_2X_PC_RPC_RFMB FIELD_PREP_CONST(PEF2256_2X_PC_RPC_MASK, 0x2) +#define PEF2256_2X_PC_RPC_RSIGM FIELD_PREP_CONST(PEF2256_2X_PC_RPC_MASK, 0x3) +#define PEF2256_2X_PC_RPC_RSIG FIELD_PREP_CONST(PEF2256_2X_PC_RPC_MASK, 0x4)
[PATCH v7 26/30] net: wan: framer: Add support for the Lantiq PEF2256 framer
The Lantiq PEF2256 is a framer and line interface component designed to fulfill all required interfacing between an analog E1/T1/J1 line and the digital PCM system highway/H.100 bus. Signed-off-by: Herve Codina Reviewed-by: Christophe Leroy Reviewed-by: Linus Walleij --- drivers/net/wan/framer/Kconfig| 16 + drivers/net/wan/framer/Makefile | 1 + drivers/net/wan/framer/pef2256/Makefile | 8 + drivers/net/wan/framer/pef2256/pef2256-regs.h | 250 + drivers/net/wan/framer/pef2256/pef2256.c | 880 ++ include/linux/framer/pef2256.h| 31 + 6 files changed, 1186 insertions(+) create mode 100644 drivers/net/wan/framer/pef2256/Makefile create mode 100644 drivers/net/wan/framer/pef2256/pef2256-regs.h create mode 100644 drivers/net/wan/framer/pef2256/pef2256.c create mode 100644 include/linux/framer/pef2256.h diff --git a/drivers/net/wan/framer/Kconfig b/drivers/net/wan/framer/Kconfig index 37df9a96ab42..482761d280fb 100644 --- a/drivers/net/wan/framer/Kconfig +++ b/drivers/net/wan/framer/Kconfig @@ -20,4 +20,20 @@ config GENERIC_FRAMER framework and framer users can obtain reference to the framer. All the users of this framework should select this config. +config FRAMER_PEF2256 + tristate "Lantiq PEF2256" + depends on OF + select GENERIC_FRAMER + select MFD_CORE + select REGMAP_MMIO + help + Enable support for the Lantiq PEF2256 (FALC56) framer. + The PEF2256 is a framer and line interface between analog E1/T1/J1 + line and a digital PCM bus. + + If unsure, say N. + + To compile this driver as a module, choose M here: the + module will be called framer-pef2256. + endmenu diff --git a/drivers/net/wan/framer/Makefile b/drivers/net/wan/framer/Makefile index 78dbd8e563d0..3403f2b14534 100644 --- a/drivers/net/wan/framer/Makefile +++ b/drivers/net/wan/framer/Makefile @@ -4,3 +4,4 @@ # obj-$(CONFIG_GENERIC_FRAMER) += framer-core.o +obj-$(CONFIG_FRAMER_PEF2256) += pef2256/ diff --git a/drivers/net/wan/framer/pef2256/Makefile b/drivers/net/wan/framer/pef2256/Makefile new file mode 100644 index ..f4d1208dd8a4 --- /dev/null +++ b/drivers/net/wan/framer/pef2256/Makefile @@ -0,0 +1,8 @@ +# SPDX-License-Identifier: GPL-2.0 +# +# Makefile for the pef2256 driver. +# + +obj-$(CONFIG_FRAMER_PEF2256) += framer-pef2256.o + +framer-pef2256-objs:= pef2256.o diff --git a/drivers/net/wan/framer/pef2256/pef2256-regs.h b/drivers/net/wan/framer/pef2256/pef2256-regs.h new file mode 100644 index ..5d3183c91714 --- /dev/null +++ b/drivers/net/wan/framer/pef2256/pef2256-regs.h @@ -0,0 +1,250 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * PEF2256 registers definition + * + * Copyright 2023 CS GROUP France + * + * Author: Herve Codina + */ +#ifndef __PEF2256_REGS_H__ +#define __PEF2256_REGS_H__ + +#include "linux/bitfield.h" + +/* Command Register */ +#define PEF2256_CMDR 0x02 +#define PEF2256_CMDR_RRES BIT(6) +#define PEF2256_CMDR_XRES BIT(4) +#define PEF2256_CMDR_SRES BIT(0) + +/* Interrupt Mask Register 0..5 */ +#define PEF2256_IMR0 0x14 +#define PEF2256_IMR1 0x15 +#define PEF2256_IMR2 0x16 +#define PEF2256_IMR3 0x17 +#define PEF2256_IMR4 0x18 +#define PEF2256_IMR5 0x19 + +/* Framer Mode Register 0 */ +#define PEF2256_FMR0 0x1C +#define PEF2256_FMR0_XC_MASK GENMASK(7, 6) +#define PEF2256_FMR0_XC_NRZFIELD_PREP_CONST(PEF2256_FMR0_XC_MASK, 0x0) +#define PEF2256_FMR0_XC_CMIFIELD_PREP_CONST(PEF2256_FMR0_XC_MASK, 0x1) +#define PEF2256_FMR0_XC_AMIFIELD_PREP_CONST(PEF2256_FMR0_XC_MASK, 0x2) +#define PEF2256_FMR0_XC_HDB3 FIELD_PREP_CONST(PEF2256_FMR0_XC_MASK, 0x3) +#define PEF2256_FMR0_RC_MASK GENMASK(5, 4) +#define PEF2256_FMR0_RC_NRZFIELD_PREP_CONST(PEF2256_FMR0_RC_MASK, 0x0) +#define PEF2256_FMR0_RC_CMIFIELD_PREP_CONST(PEF2256_FMR0_RC_MASK, 0x1) +#define PEF2256_FMR0_RC_AMIFIELD_PREP_CONST(PEF2256_FMR0_RC_MASK, 0x2) +#define PEF2256_FMR0_RC_HDB3 FIELD_PREP_CONST(PEF2256_FMR0_RC_MASK, 0x3) + +/* Framer Mode Register 1 */ +#define PEF2256_FMR1 0x1D +#define PEF2256_FMR1_XFS BIT(3) +#define PEF2256_FMR1_ECM BIT(2) +/* SSD is defined on 2 bits. The other bit is on SIC1 register */ +#define PEF2256_FMR1_SSD_MASK GENMASK(1, 1) +#define PEF2256_FMR1_SSD_2048 FIELD_PREP_CONST(PEF2256_FMR1_SSD_MASK, 0x0) +#define PEF2256_FMR1_SSD_4096 FIELD_PREP_CONST(PEF2256_FMR1_SSD_MASK, 0x1) +#define PEF2256_FMR1_SSD_8192 FIELD_PREP_CONST(PEF2256_FMR1_SSD_MASK, 0x0) +#define PEF2256_FMR1_SSD_16384 FIELD_PREP_CONST(PEF2256_FMR1_SSD_MASK, 0x1) + +/* Framer Mode Register 2 */ +#define PEF2256_FMR2 0x1E +#define PEF2256_FMR2_RFS_MASKGENMASK(7, 6) +#define PEF2256_FMR2_RFS_DOUBLEFRAME
[PATCH v7 25/30] dt-bindings: net: Add the Lantiq PEF2256 E1/T1/J1 framer
The Lantiq PEF2256 is a framer and line interface component designed to fulfill all required interfacing between an analog E1/T1/J1 line and the digital PCM system highway/H.100 bus. Signed-off-by: Herve Codina Reviewed-by: Christophe Leroy --- .../bindings/net/lantiq,pef2256.yaml | 213 ++ 1 file changed, 213 insertions(+) create mode 100644 Documentation/devicetree/bindings/net/lantiq,pef2256.yaml diff --git a/Documentation/devicetree/bindings/net/lantiq,pef2256.yaml b/Documentation/devicetree/bindings/net/lantiq,pef2256.yaml new file mode 100644 index ..7da8370e2468 --- /dev/null +++ b/Documentation/devicetree/bindings/net/lantiq,pef2256.yaml @@ -0,0 +1,213 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/net/lantiq,pef2256.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Lantiq PEF2256 + +maintainers: + - Herve Codina + +description: + The Lantiq PEF2256, also known as Infineon PEF2256 or FALC56, is a framer and + line interface component designed to fulfill all required interfacing between + an analog E1/T1/J1 line and the digital PCM system highway/H.100 bus. + +properties: + compatible: +items: + - const: lantiq,pef2256 + + reg: +maxItems: 1 + + clocks: +items: + - description: Master Clock + - description: System Clock Receive + - description: System Clock Transmit + + clock-names: +items: + - const: mclk + - const: sclkr + - const: sclkx + + interrupts: +maxItems: 1 + + reset-gpios: +description: + GPIO used to reset the device. +maxItems: 1 + + pinctrl: +$ref: /schemas/pinctrl/pinctrl.yaml# +additionalProperties: false + +patternProperties: + '-pins$': +type: object +$ref: /schemas/pinctrl/pinmux-node.yaml# +additionalProperties: false + +properties: + pins: +enum: [ RPA, RPB, RPC, RPD, XPA, XPB, XPC, XPD ] + + function: +enum: [ SYPR, RFM, RFMB, RSIGM, RSIG, DLR, FREEZE, RFSP, LOS, +SYPX, XFMS, XSIG, TCLK, XMFB, XSIGM, DLX, XCLK, XLT, +GPI, GPOH, GPOL ] + +required: + - pins + - function + + lantiq,data-rate-bps: +enum: [2048000, 4096000, 8192000, 16384000] +default: 2048000 +description: + Data rate (bit per seconds) on the system highway. + + lantiq,clock-falling-edge: +$ref: /schemas/types.yaml#/definitions/flag +description: + Data is sent on falling edge of the clock (and received on the rising + edge). If 'clock-falling-edge' is not present, data is sent on the + rising edge (and received on the falling edge). + + lantiq,channel-phase: +$ref: /schemas/types.yaml#/definitions/uint32 +enum: [0, 1, 2, 3, 4, 5, 6, 7] +default: 0 +description: | + The pef2256 delivers a full frame (32 8-bit time-slots in E1 and 24 8-bit + time-slots 8 8-bit signaling in E1/J1) every 125us. This lead to a data + rate of 2048000 bit/s. When lantiq,data-rate-bps is more than 2048000 + bit/s, the data (all 32 8-bit) present in the frame are interleave with + unused time-slots. The lantiq,channel-phase property allows to set the + correct alignment of the interleave mechanism. + For instance, suppose lantiq,data-rate-bps = 8192000 (ie 4*2048000), and + lantiq,channel-phase = 2, the interleave schema with unused time-slots + (nu) and used time-slots (XX) for TSi is +nu nu XX nu nu nu XX nu nu nu XX nu +<-- TSi --> <- TSi+1 -> <- TSi+2 -> + With lantiq,data-rate-bps = 8192000, and lantiq,channel-phase = 1, the + interleave schema is +nu XX nu nu nu XX nu nu nu XX nu nu +<-- TSi --> <- TSi+1 -> <- TSi+2 -> + With lantiq,data-rate-bps = 4096000 (ie 2*2048000), and + lantiq,channel-phase = 1, the interleave schema is +nuXXnuXXnuXX +<-- TSi --> <- TSi+1 -> <- TSi+2 -> + +patternProperties: + '^codec(-([0-9]|[1-2][0-9]|3[0-1]))?$': +type: object +$ref: /schemas/sound/dai-common.yaml +unevaluatedProperties: false +description: + Codec provided by the pef2256. This codec allows to use some of the PCM + system highway time-slots as audio channels to transport audio data over + the E1/T1/J1 lines. + The time-slots used by the codec must be set and so, the properties + 'dai-tdm-slot-num', 'dai-tdm-slot-width', 'dai-tdm-slot-tx-mask' and + 'dai-tdm-slot-rx-mask' must be present in the sound card node for + sub-nodes that involve the codec. The codec uses 8-bit time-slots. + 'dai-tdm-tdm-slot-with' must be set to 8. + The tx and rx masks define the pef2256 time-slots assigned to the codec. + +properties: + compatible: +const: lantiq,pef2256-codec + + '#sound-dai-cells': +const: 0 + +
[PATCH v7 24/30] net: wan: Add framer framework support
A framer is a component in charge of an E1/T1 line interface. Connected usually to a TDM bus, it converts TDM frames to/from E1/T1 frames. It also provides information related to the E1/T1 line. The framer framework provides a set of APIs for the framer drivers (framer provider) to create/destroy a framer and APIs for the framer users (framer consumer) to obtain a reference to the framer, and use the framer. This basic implementation provides a framer abstraction for: - power on/off the framer - get the framer status (line state) - be notified on framer status changes - get/set the framer configuration Signed-off-by: Herve Codina Reviewed-by: Christophe Leroy --- drivers/net/wan/Kconfig| 2 + drivers/net/wan/Makefile | 2 + drivers/net/wan/framer/Kconfig | 23 + drivers/net/wan/framer/Makefile| 6 + drivers/net/wan/framer/framer-core.c | 887 + include/linux/framer/framer-provider.h | 194 ++ include/linux/framer/framer.h | 205 ++ 7 files changed, 1319 insertions(+) create mode 100644 drivers/net/wan/framer/Kconfig create mode 100644 drivers/net/wan/framer/Makefile create mode 100644 drivers/net/wan/framer/framer-core.c create mode 100644 include/linux/framer/framer-provider.h create mode 100644 include/linux/framer/framer.h diff --git a/drivers/net/wan/Kconfig b/drivers/net/wan/Kconfig index 8de99f4b647b..31ab2136cdf1 100644 --- a/drivers/net/wan/Kconfig +++ b/drivers/net/wan/Kconfig @@ -95,6 +95,8 @@ config HDLC_X25 comment "X.25/LAPB support is disabled" depends on HDLC && (LAPB!=m || HDLC!=m) && LAPB!=y +source "drivers/net/wan/framer/Kconfig" + config PCI200SYN tristate "Goramo PCI200SYN support" depends on HDLC && PCI diff --git a/drivers/net/wan/Makefile b/drivers/net/wan/Makefile index f338f4830626..00e9b7ee1e01 100644 --- a/drivers/net/wan/Makefile +++ b/drivers/net/wan/Makefile @@ -14,6 +14,8 @@ obj-$(CONFIG_HDLC_FR) += hdlc_fr.o obj-$(CONFIG_HDLC_PPP) += hdlc_ppp.o obj-$(CONFIG_HDLC_X25) += hdlc_x25.o +obj-y += framer/ + obj-$(CONFIG_FARSYNC) += farsync.o obj-$(CONFIG_LAPBETHER)+= lapbether.o diff --git a/drivers/net/wan/framer/Kconfig b/drivers/net/wan/framer/Kconfig new file mode 100644 index ..37df9a96ab42 --- /dev/null +++ b/drivers/net/wan/framer/Kconfig @@ -0,0 +1,23 @@ +# SPDX-License-Identifier: GPL-2.0-only +# +# FRAMER +# + +menu "Framer Subsystem" + +config GENERIC_FRAMER + bool "Framer Core" + help + Generic Framer support. + A framer is a component in charge of an E1/T1 line interface. + Connected usually to a TDM bus, it converts TDM frames to/from E1/T1 + frames. It also provides information related to the E1/T1 line. + Used with HDLC, the network can be reached through the E1/T1 line. + + This framework is designed to provide a generic interface for framer + devices present in the kernel. This layer will have the generic + API by which framer drivers can create framer using the framer + framework and framer users can obtain reference to the framer. + All the users of this framework should select this config. + +endmenu diff --git a/drivers/net/wan/framer/Makefile b/drivers/net/wan/framer/Makefile new file mode 100644 index ..78dbd8e563d0 --- /dev/null +++ b/drivers/net/wan/framer/Makefile @@ -0,0 +1,6 @@ +# SPDX-License-Identifier: GPL-2.0 +# +# Makefile for the framer drivers. +# + +obj-$(CONFIG_GENERIC_FRAMER) += framer-core.o diff --git a/drivers/net/wan/framer/framer-core.c b/drivers/net/wan/framer/framer-core.c new file mode 100644 index ..a8f34ba993e4 --- /dev/null +++ b/drivers/net/wan/framer/framer-core.c @@ -0,0 +1,887 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Generic Framer framework. + * + * Copyright 2023 CS GROUP France + * + * Author: Herve Codina + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static struct class *framer_class; +static DEFINE_MUTEX(framer_provider_mutex); +static LIST_HEAD(framer_provider_list); +static DEFINE_IDA(framer_ida); + +#define dev_to_framer(a) (container_of((a), struct framer, dev)) + +int framer_pm_runtime_get(struct framer *framer) +{ + int ret; + + if (!pm_runtime_enabled(>dev)) + return -EOPNOTSUPP; + + ret = pm_runtime_get(>dev); + if (ret < 0 && ret != -EINPROGRESS) + pm_runtime_put_noidle(>dev); + + return ret; +} +EXPORT_SYMBOL_GPL(framer_pm_runtime_get); + +int framer_pm_runtime_get_sync(struct framer *framer) +{ + int ret; + + if (!pm_runtime_enabled(>dev)) + return -EOPNOTSUPP; + + ret = pm_runtime_get_sync(>dev); + if (ret < 0) + pm_runtime_put_sync(>dev); + +
[PATCH v7 23/30] wan: qmc_hdlc: Add runtime timeslots changes support
QMC channels support runtime timeslots changes but nothing is done at the QMC HDLC driver to handle these changes. Use existing IFACE ioctl in order to configure the timeslots to use. Signed-off-by: Herve Codina Reviewed-by: Christophe Leroy --- drivers/net/wan/fsl_qmc_hdlc.c | 169 - 1 file changed, 168 insertions(+), 1 deletion(-) diff --git a/drivers/net/wan/fsl_qmc_hdlc.c b/drivers/net/wan/fsl_qmc_hdlc.c index 15e102547ff2..24f466fa48b1 100644 --- a/drivers/net/wan/fsl_qmc_hdlc.c +++ b/drivers/net/wan/fsl_qmc_hdlc.c @@ -32,6 +32,7 @@ struct qmc_hdlc { struct qmc_hdlc_desc tx_descs[8]; unsigned int tx_out; struct qmc_hdlc_desc rx_descs[4]; + u32 slot_map; }; static inline struct qmc_hdlc *netdev_to_qmc_hdlc(struct net_device *netdev) @@ -202,6 +203,162 @@ static netdev_tx_t qmc_hdlc_xmit(struct sk_buff *skb, struct net_device *netdev) return NETDEV_TX_OK; } +static int qmc_hdlc_xlate_slot_map(struct qmc_hdlc *qmc_hdlc, + u32 slot_map, struct qmc_chan_ts_info *ts_info) +{ + u64 ts_mask_avail; + unsigned int bit; + unsigned int i; + u64 ts_mask; + u64 map; + + /* Tx and Rx masks must be identical */ + if (ts_info->rx_ts_mask_avail != ts_info->tx_ts_mask_avail) { + dev_err(qmc_hdlc->dev, "tx and rx available timeslots mismatch (0x%llx, 0x%llx)\n", + ts_info->rx_ts_mask_avail, ts_info->tx_ts_mask_avail); + return -EINVAL; + } + + ts_mask_avail = ts_info->rx_ts_mask_avail; + ts_mask = 0; + map = slot_map; + bit = 0; + for (i = 0; i < 64; i++) { + if (ts_mask_avail & BIT_ULL(i)) { + if (map & BIT_ULL(bit)) + ts_mask |= BIT_ULL(i); + bit++; + } + } + + if (hweight64(ts_mask) != hweight64(map)) { + dev_err(qmc_hdlc->dev, "Cannot translate timeslots 0x%llx -> (0x%llx,0x%llx)\n", + map, ts_mask_avail, ts_mask); + return -EINVAL; + } + + ts_info->tx_ts_mask = ts_mask; + ts_info->rx_ts_mask = ts_mask; + return 0; +} + +static int qmc_hdlc_xlate_ts_info(struct qmc_hdlc *qmc_hdlc, + const struct qmc_chan_ts_info *ts_info, u32 *slot_map) +{ + u64 ts_mask_avail; + unsigned int bit; + unsigned int i; + u64 ts_mask; + u64 map; + + /* Tx and Rx masks must be identical */ + if (ts_info->rx_ts_mask_avail != ts_info->tx_ts_mask_avail) { + dev_err(qmc_hdlc->dev, "tx and rx available timeslots mismatch (0x%llx, 0x%llx)\n", + ts_info->rx_ts_mask_avail, ts_info->tx_ts_mask_avail); + return -EINVAL; + } + if (ts_info->rx_ts_mask != ts_info->tx_ts_mask) { + dev_err(qmc_hdlc->dev, "tx and rx timeslots mismatch (0x%llx, 0x%llx)\n", + ts_info->rx_ts_mask, ts_info->tx_ts_mask); + return -EINVAL; + } + + ts_mask_avail = ts_info->rx_ts_mask_avail; + ts_mask = ts_info->rx_ts_mask; + map = 0; + bit = 0; + for (i = 0; i < 64; i++) { + if (ts_mask_avail & BIT_ULL(i)) { + if (ts_mask & BIT_ULL(i)) + map |= BIT_ULL(bit); + bit++; + } + } + + if (hweight64(ts_mask) != hweight64(map)) { + dev_err(qmc_hdlc->dev, "Cannot translate timeslots (0x%llx,0x%llx) -> 0x%llx\n", + ts_mask_avail, ts_mask, map); + return -EINVAL; + } + + if (map >= BIT_ULL(32)) { + dev_err(qmc_hdlc->dev, "Slot map out of 32bit (0x%llx,0x%llx) -> 0x%llx\n", + ts_mask_avail, ts_mask, map); + return -EINVAL; + } + + *slot_map = map; + return 0; +} + +static int qmc_hdlc_set_iface(struct qmc_hdlc *qmc_hdlc, int if_iface, const te1_settings *te1) +{ + struct qmc_chan_ts_info ts_info; + int ret; + + ret = qmc_chan_get_ts_info(qmc_hdlc->qmc_chan, _info); + if (ret) { + dev_err(qmc_hdlc->dev, "get QMC channel ts info failed %d\n", ret); + return ret; + } + ret = qmc_hdlc_xlate_slot_map(qmc_hdlc, te1->slot_map, _info); + if (ret) + return ret; + + ret = qmc_chan_set_ts_info(qmc_hdlc->qmc_chan, _info); + if (ret) { + dev_err(qmc_hdlc->dev, "set QMC channel ts info failed %d\n", ret); + return ret; + } + + qmc_hdlc->slot_map = te1->slot_map; + + return 0; +} + +static int qmc_hdlc_ioctl(struct net_device *netdev, struct if_settings *ifs) +{ + struct qmc_hdlc *qmc_hdlc = netdev_to_qmc_hdlc(netdev); + te1_settings te1; + + switch
[PATCH v7 22/30] soc: fsl: cpm1: qmc: Introduce functions to change timeslots at runtime
Introduce qmc_chan_{get,set}_ts_info() function to allow timeslots modification at runtime. The modification is provided using qmc_chan_set_ts_info() and will be applied on next qmc_chan_start(). qmc_chan_set_ts_info() must be called with the channel rx and/or tx stopped. Signed-off-by: Herve Codina Reviewed-by: Christophe Leroy --- drivers/soc/fsl/qe/qmc.c | 51 include/soc/fsl/qe/qmc.h | 10 2 files changed, 61 insertions(+) diff --git a/drivers/soc/fsl/qe/qmc.c b/drivers/soc/fsl/qe/qmc.c index b63b54ec0a3a..6e22b96b4e7a 100644 --- a/drivers/soc/fsl/qe/qmc.c +++ b/drivers/soc/fsl/qe/qmc.c @@ -290,6 +290,57 @@ int qmc_chan_get_info(struct qmc_chan *chan, struct qmc_chan_info *info) } EXPORT_SYMBOL(qmc_chan_get_info); +int qmc_chan_get_ts_info(struct qmc_chan *chan, struct qmc_chan_ts_info *ts_info) +{ + unsigned long flags; + + spin_lock_irqsave(>ts_lock, flags); + + ts_info->rx_ts_mask_avail = chan->rx_ts_mask_avail; + ts_info->tx_ts_mask_avail = chan->tx_ts_mask_avail; + ts_info->rx_ts_mask = chan->rx_ts_mask; + ts_info->tx_ts_mask = chan->tx_ts_mask; + + spin_unlock_irqrestore(>ts_lock, flags); + + return 0; +} +EXPORT_SYMBOL(qmc_chan_get_ts_info); + +int qmc_chan_set_ts_info(struct qmc_chan *chan, const struct qmc_chan_ts_info *ts_info) +{ + unsigned long flags; + int ret; + + /* Only a subset of available timeslots is allowed */ + if ((ts_info->rx_ts_mask & chan->rx_ts_mask_avail) != ts_info->rx_ts_mask) + return -EINVAL; + if ((ts_info->tx_ts_mask & chan->tx_ts_mask_avail) != ts_info->tx_ts_mask) + return -EINVAL; + + /* In case of common rx/tx table, rx/tx masks must be identical */ + if (chan->qmc->is_tsa_64rxtx) { + if (ts_info->rx_ts_mask != ts_info->tx_ts_mask) + return -EINVAL; + } + + spin_lock_irqsave(>ts_lock, flags); + + if ((chan->tx_ts_mask != ts_info->tx_ts_mask && !chan->is_tx_stopped) || + (chan->rx_ts_mask != ts_info->rx_ts_mask && !chan->is_rx_stopped)) { + dev_err(chan->qmc->dev, "Channel rx and/or tx not stopped\n"); + ret = -EBUSY; + } else { + chan->tx_ts_mask = ts_info->tx_ts_mask; + chan->rx_ts_mask = ts_info->rx_ts_mask; + ret = 0; + } + spin_unlock_irqrestore(>ts_lock, flags); + + return ret; +} +EXPORT_SYMBOL(qmc_chan_set_ts_info); + int qmc_chan_set_param(struct qmc_chan *chan, const struct qmc_chan_param *param) { if (param->mode != chan->mode) diff --git a/include/soc/fsl/qe/qmc.h b/include/soc/fsl/qe/qmc.h index 166484bb4294..2a333fc1ea81 100644 --- a/include/soc/fsl/qe/qmc.h +++ b/include/soc/fsl/qe/qmc.h @@ -40,6 +40,16 @@ struct qmc_chan_info { int qmc_chan_get_info(struct qmc_chan *chan, struct qmc_chan_info *info); +struct qmc_chan_ts_info { + u64 rx_ts_mask_avail; + u64 tx_ts_mask_avail; + u64 rx_ts_mask; + u64 tx_ts_mask; +}; + +int qmc_chan_get_ts_info(struct qmc_chan *chan, struct qmc_chan_ts_info *ts_info); +int qmc_chan_set_ts_info(struct qmc_chan *chan, const struct qmc_chan_ts_info *ts_info); + struct qmc_chan_param { enum qmc_mode mode; union { -- 2.41.0
[PATCH v7 21/30] soc: fsl: cpm1: qmc: Remove timeslots handling from setup_chan()
Timeslots setting is done at channel start() and stop(). There is no more need to do that during setup_chan(). Simply remove timeslot setting from setup_chan(). Signed-off-by: Herve Codina Reviewed-by: Christophe Leroy --- drivers/soc/fsl/qe/qmc.c | 28 1 file changed, 28 deletions(-) diff --git a/drivers/soc/fsl/qe/qmc.c b/drivers/soc/fsl/qe/qmc.c index 185e6e87a83f..b63b54ec0a3a 100644 --- a/drivers/soc/fsl/qe/qmc.c +++ b/drivers/soc/fsl/qe/qmc.c @@ -723,30 +723,6 @@ static int qmc_chan_setup_tsa_rx(struct qmc_chan *chan, bool enable) return qmc_chan_setup_tsa_32rx(chan, , enable); } -static int qmc_chan_setup_tsa(struct qmc_chan *chan, bool enable) -{ - struct tsa_serial_info info; - int ret; - - /* Retrieve info from the TSA related serial */ - ret = tsa_serial_get_info(chan->qmc->tsa_serial, ); - if (ret) - return ret; - - /* -* Setup one common 64 entries table or two 32 entries (one for Tx -* and one for Tx) according to assigned TS numbers. -*/ - if (chan->qmc->is_tsa_64rxtx) - return qmc_chan_setup_tsa_64rxtx(chan, , enable); - - ret = qmc_chan_setup_tsa_32rx(chan, , enable); - if (ret) - return ret; - - return qmc_chan_setup_tsa_32tx(chan, , enable); -} - static int qmc_chan_command(struct qmc_chan *chan, u8 qmc_opcode) { return cpm_command(chan->id << 2, (qmc_opcode << 4) | 0x0E); @@ -1323,10 +1299,6 @@ static int qmc_setup_chan(struct qmc *qmc, struct qmc_chan *chan) chan->qmc = qmc; - ret = qmc_chan_setup_tsa(chan, true); - if (ret) - return ret; - /* Set channel specific parameter base address */ chan->s_param = qmc->dpram + (chan->id * 64); /* 16 bd per channel (8 rx and 8 tx) */ -- 2.41.0
[PATCH v7 20/30] soc: fsl: cpm1: qmc: Handle timeslot entries at channel start() and stop()
In order to support runtime timeslot route changes, enable the channel timeslot entries at channel start() and disable them at channel stop(). Signed-off-by: Herve Codina Reviewed-by: Christophe Leroy --- drivers/soc/fsl/qe/qmc.c | 175 --- 1 file changed, 163 insertions(+), 12 deletions(-) diff --git a/drivers/soc/fsl/qe/qmc.c b/drivers/soc/fsl/qe/qmc.c index 19acfcded9bc..185e6e87a83f 100644 --- a/drivers/soc/fsl/qe/qmc.c +++ b/drivers/soc/fsl/qe/qmc.c @@ -177,6 +177,7 @@ struct qmc_chan { struct qmc *qmc; void __iomem *s_param; enum qmc_mode mode; + spinlock_t ts_lock; /* Protect timeslots */ u64 tx_ts_mask_avail; u64 tx_ts_mask; u64 rx_ts_mask_avail; @@ -265,6 +266,7 @@ static void qmc_setbits32(void __iomem *addr, u32 set) int qmc_chan_get_info(struct qmc_chan *chan, struct qmc_chan_info *info) { struct tsa_serial_info tsa_info; + unsigned long flags; int ret; /* Retrieve info from the TSA related serial */ @@ -272,6 +274,8 @@ int qmc_chan_get_info(struct qmc_chan *chan, struct qmc_chan_info *info) if (ret) return ret; + spin_lock_irqsave(>ts_lock, flags); + info->mode = chan->mode; info->rx_fs_rate = tsa_info.rx_fs_rate; info->rx_bit_rate = tsa_info.rx_bit_rate; @@ -280,6 +284,8 @@ int qmc_chan_get_info(struct qmc_chan *chan, struct qmc_chan_info *info) info->tx_bit_rate = tsa_info.tx_bit_rate; info->nb_rx_ts = hweight64(chan->rx_ts_mask); + spin_unlock_irqrestore(>ts_lock, flags); + return 0; } EXPORT_SYMBOL(qmc_chan_get_info); @@ -683,6 +689,40 @@ static int qmc_chan_setup_tsa_32tx(struct qmc_chan *chan, const struct tsa_seria return 0; } +static int qmc_chan_setup_tsa_tx(struct qmc_chan *chan, bool enable) +{ + struct tsa_serial_info info; + int ret; + + /* Retrieve info from the TSA related serial */ + ret = tsa_serial_get_info(chan->qmc->tsa_serial, ); + if (ret) + return ret; + + /* Setup entries */ + if (chan->qmc->is_tsa_64rxtx) + return qmc_chan_setup_tsa_64rxtx(chan, , enable); + + return qmc_chan_setup_tsa_32tx(chan, , enable); +} + +static int qmc_chan_setup_tsa_rx(struct qmc_chan *chan, bool enable) +{ + struct tsa_serial_info info; + int ret; + + /* Retrieve info from the TSA related serial */ + ret = tsa_serial_get_info(chan->qmc->tsa_serial, ); + if (ret) + return ret; + + /* Setup entries */ + if (chan->qmc->is_tsa_64rxtx) + return qmc_chan_setup_tsa_64rxtx(chan, , enable); + + return qmc_chan_setup_tsa_32rx(chan, , enable); +} + static int qmc_chan_setup_tsa(struct qmc_chan *chan, bool enable) { struct tsa_serial_info info; @@ -719,6 +759,12 @@ static int qmc_chan_stop_rx(struct qmc_chan *chan) spin_lock_irqsave(>rx_lock, flags); + if (chan->is_rx_stopped) { + /* The channel is already stopped -> simply return ok */ + ret = 0; + goto end; + } + /* Send STOP RECEIVE command */ ret = qmc_chan_command(chan, 0x0); if (ret) { @@ -729,6 +775,15 @@ static int qmc_chan_stop_rx(struct qmc_chan *chan) chan->is_rx_stopped = true; + if (!chan->qmc->is_tsa_64rxtx || chan->is_tx_stopped) { + ret = qmc_chan_setup_tsa_rx(chan, false); + if (ret) { + dev_err(chan->qmc->dev, "chan %u: Disable tsa entries failed (%d)\n", + chan->id, ret); + goto end; + } + } + end: spin_unlock_irqrestore(>rx_lock, flags); return ret; @@ -741,6 +796,12 @@ static int qmc_chan_stop_tx(struct qmc_chan *chan) spin_lock_irqsave(>tx_lock, flags); + if (chan->is_tx_stopped) { + /* The channel is already stopped -> simply return ok */ + ret = 0; + goto end; + } + /* Send STOP TRANSMIT command */ ret = qmc_chan_command(chan, 0x1); if (ret) { @@ -751,37 +812,82 @@ static int qmc_chan_stop_tx(struct qmc_chan *chan) chan->is_tx_stopped = true; + if (!chan->qmc->is_tsa_64rxtx || chan->is_rx_stopped) { + ret = qmc_chan_setup_tsa_tx(chan, false); + if (ret) { + dev_err(chan->qmc->dev, "chan %u: Disable tsa entries failed (%d)\n", + chan->id, ret); + goto end; + } + } + end: spin_unlock_irqrestore(>tx_lock, flags); return ret; } +static int qmc_chan_start_rx(struct qmc_chan *chan); + int qmc_chan_stop(struct qmc_chan *chan, int direction) { - int ret; + bool is_rx_rollback_needed = false; + unsigned long flags; +
[PATCH v7 19/30] soc: fsl: cpm1: qmc: Introduce is_tsa_64rxtx flag
In order to support runtime timeslot route changes, some operations will be different according the routing table used (common Rx and Tx table or one table for Rx and one for Tx). The is_tsa_64rxtx flag is introduced to avoid extra computation to determine the table format each time we need it. It is set once at initialization. Signed-off-by: Herve Codina Reviewed-by: Christophe Leroy --- drivers/soc/fsl/qe/qmc.c | 5 - 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/soc/fsl/qe/qmc.c b/drivers/soc/fsl/qe/qmc.c index eeceb81bf107..19acfcded9bc 100644 --- a/drivers/soc/fsl/qe/qmc.c +++ b/drivers/soc/fsl/qe/qmc.c @@ -216,6 +216,7 @@ struct qmc { u16 __iomem *int_curr; dma_addr_t int_dma_addr; size_t int_size; + bool is_tsa_64rxtx; struct list_head chan_head; struct qmc_chan *chans[64]; }; @@ -696,7 +697,7 @@ static int qmc_chan_setup_tsa(struct qmc_chan *chan, bool enable) * Setup one common 64 entries table or two 32 entries (one for Tx * and one for Tx) according to assigned TS numbers. */ - if (info.nb_tx_ts > 32 || info.nb_rx_ts > 32) + if (chan->qmc->is_tsa_64rxtx) return qmc_chan_setup_tsa_64rxtx(chan, , enable); ret = qmc_chan_setup_tsa_32rx(chan, , enable); @@ -1053,6 +1054,7 @@ static int qmc_init_tsa_64rxtx(struct qmc *qmc, const struct tsa_serial_info *in * Everything was previously checked, Tx and Rx related stuffs are * identical -> Used Rx related stuff to build the table */ + qmc->is_tsa_64rxtx = true; /* Invalidate all entries */ for (i = 0; i < 64; i++) @@ -1081,6 +1083,7 @@ static int qmc_init_tsa_32rx_32tx(struct qmc *qmc, const struct tsa_serial_info * Use a Tx 32 entries table and a Rx 32 entries table. * Everything was previously checked. */ + qmc->is_tsa_64rxtx = false; /* Invalidate all entries */ for (i = 0; i < 32; i++) { -- 2.41.0
[PATCH v7 18/30] soc: fsl: cpm1: qmc: Split Tx and Rx TSA entries setup
The Tx and Rx entries for a given channel are set in one function. In order to modify Rx entries and Tx entries independently of one other, split this function in one for the Rx part and one for the Tx part. Signed-off-by: Herve Codina Reviewed-by: Christophe Leroy --- drivers/soc/fsl/qe/qmc.c | 49 1 file changed, 35 insertions(+), 14 deletions(-) diff --git a/drivers/soc/fsl/qe/qmc.c b/drivers/soc/fsl/qe/qmc.c index 26cd7e1ccafc..eeceb81bf107 100644 --- a/drivers/soc/fsl/qe/qmc.c +++ b/drivers/soc/fsl/qe/qmc.c @@ -610,14 +610,14 @@ static int qmc_chan_setup_tsa_64rxtx(struct qmc_chan *chan, const struct tsa_ser return 0; } -static int qmc_chan_setup_tsa_32rx_32tx(struct qmc_chan *chan, const struct tsa_serial_info *info, - bool enable) +static int qmc_chan_setup_tsa_32rx(struct qmc_chan *chan, const struct tsa_serial_info *info, + bool enable) { unsigned int i; u16 curr; u16 val; - /* Use a Tx 32 entries table and a Rx 32 entries table */ + /* Use a Rx 32 entries table */ val = QMC_TSA_VALID | QMC_TSA_MASK | QMC_TSA_CHANNEL(chan->id); @@ -633,6 +633,30 @@ static int qmc_chan_setup_tsa_32rx_32tx(struct qmc_chan *chan, const struct tsa_ return -EBUSY; } } + + /* Set entries based on Rx stuff */ + for (i = 0; i < info->nb_rx_ts; i++) { + if (!(chan->rx_ts_mask & (((u64)1) << i))) + continue; + + qmc_clrsetbits16(chan->qmc->scc_pram + QMC_GBL_TSATRX + (i * 2), +~QMC_TSA_WRAP, enable ? val : 0x); + } + + return 0; +} + +static int qmc_chan_setup_tsa_32tx(struct qmc_chan *chan, const struct tsa_serial_info *info, + bool enable) +{ + unsigned int i; + u16 curr; + u16 val; + + /* Use a Tx 32 entries table */ + + val = QMC_TSA_VALID | QMC_TSA_MASK | QMC_TSA_CHANNEL(chan->id); + /* Check entries based on Tx stuff */ for (i = 0; i < info->nb_tx_ts; i++) { if (!(chan->tx_ts_mask & (((u64)1) << i))) @@ -646,14 +670,6 @@ static int qmc_chan_setup_tsa_32rx_32tx(struct qmc_chan *chan, const struct tsa_ } } - /* Set entries based on Rx stuff */ - for (i = 0; i < info->nb_rx_ts; i++) { - if (!(chan->rx_ts_mask & (((u64)1) << i))) - continue; - - qmc_clrsetbits16(chan->qmc->scc_pram + QMC_GBL_TSATRX + (i * 2), -~QMC_TSA_WRAP, enable ? val : 0x); - } /* Set entries based on Tx stuff */ for (i = 0; i < info->nb_tx_ts; i++) { if (!(chan->tx_ts_mask & (((u64)1) << i))) @@ -680,9 +696,14 @@ static int qmc_chan_setup_tsa(struct qmc_chan *chan, bool enable) * Setup one common 64 entries table or two 32 entries (one for Tx * and one for Tx) according to assigned TS numbers. */ - return ((info.nb_tx_ts > 32) || (info.nb_rx_ts > 32)) ? - qmc_chan_setup_tsa_64rxtx(chan, , enable) : - qmc_chan_setup_tsa_32rx_32tx(chan, , enable); + if (info.nb_tx_ts > 32 || info.nb_rx_ts > 32) + return qmc_chan_setup_tsa_64rxtx(chan, , enable); + + ret = qmc_chan_setup_tsa_32rx(chan, , enable); + if (ret) + return ret; + + return qmc_chan_setup_tsa_32tx(chan, , enable); } static int qmc_chan_command(struct qmc_chan *chan, u8 qmc_opcode) -- 2.41.0
[PATCH v7 17/30] soc: fsl: cpm1: qmc: Add support for disabling channel TSA entries
In order to allow runtime timeslot route changes, disabling channel TSA entries needs to be supported. Add support for this new feature. Signed-off-by: Herve Codina Reviewed-by: Christophe Leroy --- drivers/soc/fsl/qe/qmc.c | 20 +++- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/drivers/soc/fsl/qe/qmc.c b/drivers/soc/fsl/qe/qmc.c index 269d10cd3c7a..26cd7e1ccafc 100644 --- a/drivers/soc/fsl/qe/qmc.c +++ b/drivers/soc/fsl/qe/qmc.c @@ -567,7 +567,8 @@ static void qmc_chan_read_done(struct qmc_chan *chan) spin_unlock_irqrestore(>rx_lock, flags); } -static int qmc_chan_setup_tsa_64rxtx(struct qmc_chan *chan, const struct tsa_serial_info *info) +static int qmc_chan_setup_tsa_64rxtx(struct qmc_chan *chan, const struct tsa_serial_info *info, +bool enable) { unsigned int i; u16 curr; @@ -603,13 +604,14 @@ static int qmc_chan_setup_tsa_64rxtx(struct qmc_chan *chan, const struct tsa_ser continue; qmc_clrsetbits16(chan->qmc->scc_pram + QMC_GBL_TSATRX + (i * 2), -~QMC_TSA_WRAP, val); +~QMC_TSA_WRAP, enable ? val : 0x); } return 0; } -static int qmc_chan_setup_tsa_32rx_32tx(struct qmc_chan *chan, const struct tsa_serial_info *info) +static int qmc_chan_setup_tsa_32rx_32tx(struct qmc_chan *chan, const struct tsa_serial_info *info, + bool enable) { unsigned int i; u16 curr; @@ -650,7 +652,7 @@ static int qmc_chan_setup_tsa_32rx_32tx(struct qmc_chan *chan, const struct tsa_ continue; qmc_clrsetbits16(chan->qmc->scc_pram + QMC_GBL_TSATRX + (i * 2), -~QMC_TSA_WRAP, val); +~QMC_TSA_WRAP, enable ? val : 0x); } /* Set entries based on Tx stuff */ for (i = 0; i < info->nb_tx_ts; i++) { @@ -658,13 +660,13 @@ static int qmc_chan_setup_tsa_32rx_32tx(struct qmc_chan *chan, const struct tsa_ continue; qmc_clrsetbits16(chan->qmc->scc_pram + QMC_GBL_TSATTX + (i * 2), -~QMC_TSA_WRAP, val); +~QMC_TSA_WRAP, enable ? val : 0x); } return 0; } -static int qmc_chan_setup_tsa(struct qmc_chan *chan) +static int qmc_chan_setup_tsa(struct qmc_chan *chan, bool enable) { struct tsa_serial_info info; int ret; @@ -679,8 +681,8 @@ static int qmc_chan_setup_tsa(struct qmc_chan *chan) * and one for Tx) according to assigned TS numbers. */ return ((info.nb_tx_ts > 32) || (info.nb_rx_ts > 32)) ? - qmc_chan_setup_tsa_64rxtx(chan, ) : - qmc_chan_setup_tsa_32rx_32tx(chan, ); + qmc_chan_setup_tsa_64rxtx(chan, , enable) : + qmc_chan_setup_tsa_32rx_32tx(chan, , enable); } static int qmc_chan_command(struct qmc_chan *chan, u8 qmc_opcode) @@ -1146,7 +1148,7 @@ static int qmc_setup_chan(struct qmc *qmc, struct qmc_chan *chan) chan->qmc = qmc; - ret = qmc_chan_setup_tsa(chan); + ret = qmc_chan_setup_tsa(chan, true); if (ret) return ret; -- 2.41.0
[PATCH v7 16/30] soc: fsl: cpm1: qmc: Check available timeslots in qmc_check_chans()
The timeslots checked in qmc_check_chans() are the timeslots used. With the introduction of the available timeslots, the used timeslots are a subset of the available timeslots. The timeslots checked during the qmc_check_chans() call should be the available ones. Simply update and check the available timeslots instead of the used timeslots in qmc_check_chans(). Signed-off-by: Herve Codina Reviewed-by: Christophe Leroy --- drivers/soc/fsl/qe/qmc.c | 8 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/soc/fsl/qe/qmc.c b/drivers/soc/fsl/qe/qmc.c index 1189e6076e37..269d10cd3c7a 100644 --- a/drivers/soc/fsl/qe/qmc.c +++ b/drivers/soc/fsl/qe/qmc.c @@ -914,13 +914,13 @@ static int qmc_check_chans(struct qmc *qmc) rx_ts_assigned_mask = info.nb_rx_ts == 64 ? U64_MAX : (((u64)1) << info.nb_rx_ts) - 1; list_for_each_entry(chan, >chan_head, list) { - if (chan->tx_ts_mask > tx_ts_assigned_mask) { - dev_err(qmc->dev, "chan %u uses TSA unassigned Tx TS\n", chan->id); + if (chan->tx_ts_mask_avail > tx_ts_assigned_mask) { + dev_err(qmc->dev, "chan %u can use TSA unassigned Tx TS\n", chan->id); return -EINVAL; } - if (chan->rx_ts_mask > rx_ts_assigned_mask) { - dev_err(qmc->dev, "chan %u uses TSA unassigned Rx TS\n", chan->id); + if (chan->rx_ts_mask_avail > rx_ts_assigned_mask) { + dev_err(qmc->dev, "chan %u can use TSA unassigned Rx TS\n", chan->id); return -EINVAL; } } -- 2.41.0