Re: [PATCH 86/87] fs: switch timespec64 fields in inode to discrete integers

2023-09-28 Thread Amir Goldstein
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

2023-09-28 Thread Amir Goldstein
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

2023-09-28 Thread Athira Rajeev



> 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

2023-09-28 Thread Athira Rajeev



> 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

2023-09-28 Thread Athira Rajeev
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

2023-09-28 Thread Athira Rajeev
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

2023-09-28 Thread Athira Rajeev
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

2023-09-28 Thread Athira Rajeev
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

2023-09-28 Thread Pingfan Liu
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

2023-09-28 Thread Linus Torvalds
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

2023-09-28 Thread Theodore Ts'o
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

2023-09-28 Thread Arnd Bergmann
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

2023-09-28 Thread Steve Wahl
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

2023-09-28 Thread Linus Torvalds
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

2023-09-28 Thread Jeff Layton
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

2023-09-28 Thread Jeff Layton
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

2023-09-28 Thread Darrick J. Wong
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

2023-09-28 Thread Jeff Layton
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

2023-09-28 Thread Jeff Layton
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

2023-09-28 Thread Arnd Bergmann
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

2023-09-28 Thread Dan Whitehouse
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

2023-09-28 Thread Alex Williamson
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

2023-09-28 Thread Alex Williamson
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

2023-09-28 Thread Alex Williamson
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

2023-09-28 Thread Alex Williamson
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

2023-09-28 Thread Alex Williamson
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

2023-09-28 Thread Alex Williamson
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]

2023-09-28 Thread Song Liu
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

2023-09-28 Thread Song Liu
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

2023-09-28 Thread Song Liu
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

2023-09-28 Thread Song Liu
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()

2023-09-28 Thread Song Liu
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

2023-09-28 Thread Wen Xiong
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()

2023-09-28 Thread Hari Bathini




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]

2023-09-28 Thread Hari Bathini
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

2023-09-28 Thread Hari Bathini
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

2023-09-28 Thread Hari Bathini
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

2023-09-28 Thread Hari Bathini
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()

2023-09-28 Thread Hari Bathini
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

2023-09-28 Thread Hari Bathini
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

2023-09-28 Thread Christophe Leroy


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

2023-09-28 Thread Wei Liu
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

2023-09-28 Thread Song Liu
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

2023-09-28 Thread Greg Kroah-Hartman
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

2023-09-28 Thread Joel Granados via B4 Relay
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

2023-09-28 Thread Joel Granados via B4 Relay
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

2023-09-28 Thread Joel Granados via B4 Relay
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

2023-09-28 Thread Joel Granados via B4 Relay
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

2023-09-28 Thread Joel Granados via B4 Relay
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

2023-09-28 Thread Joel Granados via B4 Relay
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

2023-09-28 Thread Joel Granados via B4 Relay
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

2023-09-28 Thread Joel Granados via B4 Relay
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

2023-09-28 Thread Joel Granados via B4 Relay
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

2023-09-28 Thread Joel Granados via B4 Relay
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

2023-09-28 Thread Joel Granados via B4 Relay
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

2023-09-28 Thread Joel Granados via B4 Relay
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

2023-09-28 Thread Joel Granados via B4 Relay
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

2023-09-28 Thread Joel Granados via B4 Relay
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

2023-09-28 Thread Joel Granados via B4 Relay
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

2023-09-28 Thread Joel Granados via B4 Relay
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

2023-09-28 Thread Jeff Layton
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

2023-09-28 Thread Amir Goldstein
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

2023-09-28 Thread Jeff Layton
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

2023-09-28 Thread Jeff Layton
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

2023-09-28 Thread Jeff Layton
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

2023-09-28 Thread Jeff Layton
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

2023-09-28 Thread Jeff Layton
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

2023-09-28 Thread Jeff Layton
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

2023-09-28 Thread Vinod Koul
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

2023-09-28 Thread Vinod Koul


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

2023-09-28 Thread Shengjiu Wang
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

2023-09-28 Thread Shengjiu Wang
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

2023-09-28 Thread Shengjiu Wang
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

2023-09-28 Thread Shengjiu Wang
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

2023-09-28 Thread Shengjiu Wang
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

2023-09-28 Thread Shengjiu Wang
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

2023-09-28 Thread Shengjiu Wang
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

2023-09-28 Thread Shengjiu Wang
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

2023-09-28 Thread Shengjiu Wang
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

2023-09-28 Thread Shengjiu Wang
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

2023-09-28 Thread Shengjiu Wang
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

2023-09-28 Thread Shengjiu Wang
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

2023-09-28 Thread Athira Rajeev
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

2023-09-28 Thread Athira Rajeev
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

2023-09-28 Thread Athira Rajeev
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

2023-09-28 Thread Herve Codina
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

2023-09-28 Thread Herve Codina
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

2023-09-28 Thread Herve Codina
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

2023-09-28 Thread Herve Codina
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

2023-09-28 Thread Herve Codina
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

2023-09-28 Thread Herve Codina
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

2023-09-28 Thread Herve Codina
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

2023-09-28 Thread Herve Codina
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

2023-09-28 Thread Herve Codina
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()

2023-09-28 Thread Herve Codina
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()

2023-09-28 Thread Herve Codina
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

2023-09-28 Thread Herve Codina
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

2023-09-28 Thread Herve Codina
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

2023-09-28 Thread Herve Codina
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()

2023-09-28 Thread Herve Codina
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



  1   2   >