Re: [PATCH v6 00/13] Add support for DAX vmemmap optimization for ppc64

2023-07-25 Thread Aneesh Kumar K V
On 7/26/23 12:59 AM, Andrew Morton wrote:
> On Tue, 25 Jul 2023 00:37:46 +0530 "Aneesh Kumar K.V" 
>  wrote:
> 
>> This patch series implements changes required to support DAX vmemmap
>> optimization for ppc64.
> 
> Do we have any measurements to help us understand the magnitude
> of this optimization?
> 
> And any documentation which helps users understand whether and
> why they should enable this feature?

That is memory space optimization due to kernel reusing the tail page struct 
pages. The details
of the optimization is documented in patch 11. We document there the impact 
with both 4k and
64K page size.

-aneesh


Re: [PATCH v5 4/7] mm/hotplug: Support memmap_on_memory when memmap is not aligned to pageblocks

2023-07-25 Thread Aneesh Kumar K.V
David Hildenbrand  writes:

> On 25.07.23 12:02, Aneesh Kumar K.V wrote:
>> Currently, memmap_on_memory feature is only supported with memory block
>> sizes that result in vmemmap pages covering full page blocks. This is
>> because memory onlining/offlining code requires applicable ranges to be
>> pageblock-aligned, for example, to set the migratetypes properly.
>> 
>> This patch helps to lift that restriction by reserving more pages than
>> required for vmemmap space. This helps the start address to be page
>> block aligned with different memory block sizes. Using this facility
>> implies the kernel will be reserving some pages for every memoryblock.
>> This allows the memmap on memory feature to be widely useful with
>> different memory block size values.
>> 
>> For ex: with 64K page size and 256MiB memory block size, we require 4
>> pages to map vmemmap pages, To align things correctly we end up adding a
>> reserve of 28 pages. ie, for every 4096 pages 28 pages get reserved.
>> 
>> Signed-off-by: Aneesh Kumar K.V 
>> ---
>>   .../admin-guide/mm/memory-hotplug.rst |  12 ++
>>   mm/memory_hotplug.c   | 121 --
>>   2 files changed, 119 insertions(+), 14 deletions(-)
>> 
>> diff --git a/Documentation/admin-guide/mm/memory-hotplug.rst 
>> b/Documentation/admin-guide/mm/memory-hotplug.rst
>> index bd77841041af..2994958c7ce8 100644
>> --- a/Documentation/admin-guide/mm/memory-hotplug.rst
>> +++ b/Documentation/admin-guide/mm/memory-hotplug.rst
>> @@ -433,6 +433,18 @@ The following module parameters are currently defined:
>>   memory in a way that huge pages in bigger
>>   granularity cannot be formed on hotplugged
>>   memory.
>> +
>> + With value "force" it could result in memory
>> + wastage due to memmap size limitations. For
>> + example, if the memmap for a memory block
>> + requires 1 MiB, but the pageblock size is 2
>> + MiB, 1 MiB of hotplugged memory will be wasted.
>> + Note that there are still cases where the
>> + feature cannot be enforced: for example, if the
>> + memmap is smaller than a single page, or if the
>> + architecture does not support the forced mode
>> + in all configurations.
>> +
>>   ``online_policy``   read-write: Set the basic policy used for
>>   automatic zone selection when onlining memory
>>   blocks without specifying a target zone.
>> diff --git a/mm/memory_hotplug.c b/mm/memory_hotplug.c
>> index 457824a6ecb8..5b472e137898 100644
>> --- a/mm/memory_hotplug.c
>> +++ b/mm/memory_hotplug.c
>> @@ -41,17 +41,89 @@
>>   #include "internal.h"
>>   #include "shuffle.h"
>>   
>> +enum {
>> +MEMMAP_ON_MEMORY_DISABLE = 0,
>> +MEMMAP_ON_MEMORY_ENABLE,
>> +MEMMAP_ON_MEMORY_FORCE,
>> +};
>> +
>> +static int memmap_mode __read_mostly = MEMMAP_ON_MEMORY_DISABLE;
>> +
>> +static inline unsigned long memory_block_memmap_pages(void)
>> +{
>> +unsigned long memmap_size;
>> +
>> +memmap_size = PHYS_PFN(memory_block_size_bytes()) * sizeof(struct page);
>> +return memmap_size >> PAGE_SHIFT;
>
> I'd really move a !page variant (memory_block_memmap_size()) to the 
> previous patch and use it in mhp_supports_memmap_on_memory() and 
> arch_supports_memmap_on_memory().
>
> Then, in this patch, reuse that function in 
> memory_block_memmap_on_memory_pages() and ...
>
>> +}
>> +
>> +static inline unsigned long memory_block_memmap_on_memory_pages(void)
>> +{
>> +unsigned long nr_pages = memory_block_memmap_pages();
>
> ... do here a
>
> nr_pages = PHYS_PFN(memory_block_memmap_size());
>
>
> Conceptually, it would be even cleaner to have here
>
> nr_pages = PFN_UP(memory_block_memmap_size());
>
> even though one can argue that mhp_supports_memmap_on_memory() will make 
> sure that the unaligned value (memory_block_memmap_size()) covers full 
> pages, but at least to me it looks cleaner that way. No strong opinion.
>
>
>> +
>> +/*
>> + * In "forced" memmap_on_memory mode, we add extra pages to align the
>> + * vmemmap size to cover full pageblocks. That way, we can add memory
>> + * even if the vmemmap size is not properly aligned, however, we might 
>> waste
>> + * memory.
>> + */
>> +if (memmap_mode == MEMMAP_ON_MEMORY_FORCE)
>> +return pageblock_align(nr_pages);
>> +return nr_pages;
>> +}
>> +
>>   #ifdef CONFIG_MHP_MEMMAP_ON_MEMORY
>>   /*
>>* memory_hotplug.memmap_on_memory parameter
>>*/
>> -static bool memmap_on_memory __ro_after_init;
>> -module_param(memmap_on_memory, bool, 0444);
>> -MODULE_PARM_DESC(memmap_on_memory, "Enable memmap on memory for 

Re: [PATCH 00/26] Add support for QMC HDLC, framer infrastruture and PEF2256 framer

2023-07-25 Thread Jakub Kicinski
On Tue, 25 Jul 2023 11:23:36 +0200 Herve Codina wrote:
> I have a system where I need to handle an HDLC interface and some audio
> data.

The new code must build cleanly with C=1 W=1, after every individual
patch.
-- 
pw-bot: cr


RE: [RFC PATCH v11 12/29] KVM: Add KVM_CREATE_GUEST_MEMFD ioctl() for guest-specific backing memory

2023-07-25 Thread Wang, Wei W
On Wednesday, July 26, 2023 12:04 AM,  Sean Christopherson wrote:
> On Tue, Jul 25, 2023, Wei W Wang wrote:
> > On Wednesday, July 19, 2023 7:45 AM, Sean Christopherson wrote:
> > > +int kvm_gmem_get_pfn(struct kvm *kvm, struct kvm_memory_slot *slot,
> > > +  gfn_t gfn, kvm_pfn_t *pfn, int *max_order) {
> > > + pgoff_t index = gfn - slot->base_gfn + slot->gmem.pgoff;
> > > + struct kvm_gmem *gmem;
> > > + struct folio *folio;
> > > + struct page *page;
> > > + struct file *file;
> > > +
> > > + file = kvm_gmem_get_file(slot);
> > > + if (!file)
> > > + return -EFAULT;
> > > +
> > > + gmem = file->private_data;
> > > +
> > > + if (WARN_ON_ONCE(xa_load(>bindings, index) != slot)) {
> > > + fput(file);
> > > + return -EIO;
> > > + }
> > > +
> > > + folio = kvm_gmem_get_folio(file_inode(file), index);
> > > + if (!folio) {
> > > + fput(file);
> > > + return -ENOMEM;
> > > + }
> > > +
> > > + page = folio_file_page(folio, index);
> > > +
> > > + *pfn = page_to_pfn(page);
> > > + *max_order = compound_order(compound_head(page));
> >
> > Maybe better to check if caller provided a buffer to get the max_order:
> > if (max_order)
> > *max_order = compound_order(compound_head(page));
> >
> > This is what the previous version did (restrictedmem_get_page), so
> > that callers who only want to get a pfn don't need to define an unused
> > "order" param.
> 
> My preference would be to require @max_order.  I can kinda sorta see why a
> generic implementation (restrictedmem) would make the param optional, but
> with gmem being KVM-internal I think it makes sense to require the param.
> Even if pKVM doesn't _currently_ need/want the order of the backing
> allocation, presumably that's because hugepage support is still on the TODO
> list, not because pKVM fundamentally doesn't need to know the order of the
> backing allocation.

Another usage is live migration. The migration flow works with 4KB pages only,
and we only need to get the pfn from the given gfn. "order" doesn't seem to be
useful for this case.


Re: [PATCH v2] net: Explicitly include correct DT includes

2023-07-25 Thread Rob Herring
On Tue, Jul 25, 2023 at 11:18 AM Simon Horman  wrote:
>
> On Mon, Jul 24, 2023 at 03:22:16PM -0600, Rob Herring wrote:
>
> ...
>
> >  90 files changed, 88 insertions(+), 92 deletions(-)
>
> Hi Rob,
>
> I suppose that it's reasonable to take this patch through netdev.
> But it does have a pretty wide surface, and netdev moves a lot.
>
> As it stands the patch doesn't apply due to a conflict
> in dwmac-qcom-ethqos.c

It did yesterday... Anyways, looks like 0-day decided to find something else.

Rob


Re: [PATCH v2] net: Explicitly include correct DT includes

2023-07-25 Thread Simon Horman
On Mon, Jul 24, 2023 at 03:22:16PM -0600, Rob Herring wrote:

...

>  90 files changed, 88 insertions(+), 92 deletions(-)

Hi Rob,

I suppose that it's reasonable to take this patch through netdev.
But it does have a pretty wide surface, and netdev moves a lot.

As it stands the patch doesn't apply due to a conflict
in dwmac-qcom-ethqos.c

-- 
pw-bot: changes-requested


RE: [RFC PATCH v11 12/29] KVM: Add KVM_CREATE_GUEST_MEMFD ioctl() for guest-specific backing memory

2023-07-25 Thread Wang, Wei W
On Wednesday, July 19, 2023 7:45 AM, Sean Christopherson wrote:
> +int kvm_gmem_get_pfn(struct kvm *kvm, struct kvm_memory_slot *slot,
> +  gfn_t gfn, kvm_pfn_t *pfn, int *max_order) {
> + pgoff_t index = gfn - slot->base_gfn + slot->gmem.pgoff;
> + struct kvm_gmem *gmem;
> + struct folio *folio;
> + struct page *page;
> + struct file *file;
> +
> + file = kvm_gmem_get_file(slot);
> + if (!file)
> + return -EFAULT;
> +
> + gmem = file->private_data;
> +
> + if (WARN_ON_ONCE(xa_load(>bindings, index) != slot)) {
> + fput(file);
> + return -EIO;
> + }
> +
> + folio = kvm_gmem_get_folio(file_inode(file), index);
> + if (!folio) {
> + fput(file);
> + return -ENOMEM;
> + }
> +
> + page = folio_file_page(folio, index);
> +
> + *pfn = page_to_pfn(page);
> + *max_order = compound_order(compound_head(page));

Maybe better to check if caller provided a buffer to get the max_order:
if (max_order)
*max_order = compound_order(compound_head(page));

This is what the previous version did (restrictedmem_get_page),
so that callers who only want to get a pfn don't need to define
an unused "order" param.


Re: [PATCH v2] syscalls: Cleanup references to sys_lookup_dcookie()

2023-07-25 Thread Russell King (Oracle)
On Mon, Jul 10, 2023 at 06:51:24PM +, Sohil Mehta wrote:
> diff --git a/arch/arm/tools/syscall.tbl b/arch/arm/tools/syscall.tbl
> index 8ebed8a13874..cb7ea3bf18cf 100644
> --- a/arch/arm/tools/syscall.tbl
> +++ b/arch/arm/tools/syscall.tbl
> @@ -263,7 +263,7 @@
>  246  common  io_submit   sys_io_submit
>  247  common  io_cancel   sys_io_cancel
>  248  common  exit_group  sys_exit_group
> -249  common  lookup_dcookie  sys_lookup_dcookie
> +249  common  lookup_dcookie  sys_ni_syscall

Acked-by: Russell King (Oracle) 

Thanks!

-- 
RMK's Patch system: https://www.armlinux.org.uk/developer/patches/
FTTP is here! 80Mbps down 10Mbps up. Decent connectivity at last!


Re: [PATCH mm-unstable v7 12/31] powerpc: Convert various functions to use ptdescs

2023-07-25 Thread kernel test robot
Hi Vishal,

kernel test robot noticed the following build errors:

[auto build test ERROR on akpm-mm/mm-everything]
[also build test ERROR on next-20230725]
[cannot apply to powerpc/next powerpc/fixes s390/features geert-m68k/for-next 
geert-m68k/for-linus linus/master v6.5-rc3]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]

url:
https://github.com/intel-lab-lkp/linux/commits/Vishal-Moola-Oracle/mm-Add-PAGE_TYPE_OP-folio-functions/20230725-122458
base:   https://git.kernel.org/pub/scm/linux/kernel/git/akpm/mm.git 
mm-everything
patch link:
https://lore.kernel.org/r/20230725042051.36691-13-vishal.moola%40gmail.com
patch subject: [PATCH mm-unstable v7 12/31] powerpc: Convert various functions 
to use ptdescs
config: powerpc-randconfig-r034-20230725 
(https://download.01.org/0day-ci/archive/20230726/202307260706.qnpjsnjr-...@intel.com/config)
compiler: clang version 17.0.0 (https://github.com/llvm/llvm-project.git 
4a5ac14ee968ff0ad5d2cc1ffa0299048db4c88a)
reproduce: 
(https://download.01.org/0day-ci/archive/20230726/202307260706.qnpjsnjr-...@intel.com/reproduce)

If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot 
| Closes: 
https://lore.kernel.org/oe-kbuild-all/202307260706.qnpjsnjr-...@intel.com/

All errors (new ones prefixed by >>):

   In file included from arch/powerpc/mm/pgtable-frag.c:12:
   In file included from include/linux/hardirq.h:11:
   In file included from arch/powerpc/include/asm/hardirq.h:6:
   In file included from include/linux/irq.h:20:
   In file included from include/linux/io.h:13:
   In file included from arch/powerpc/include/asm/io.h:672:
   arch/powerpc/include/asm/io-defs.h:45:1: error: performing pointer 
arithmetic on a null pointer has undefined behavior 
[-Werror,-Wnull-pointer-arithmetic]
  45 | DEF_PCI_AC_NORET(insw, (unsigned long p, void *b, unsigned long c),
 | ^~~
  46 |  (p, b, c), pio, p)
 |  ~~
   arch/powerpc/include/asm/io.h:669:3: note: expanded from macro 
'DEF_PCI_AC_NORET'
 669 | __do_##name al; \
 | ^~
   :40:1: note: expanded from here
  40 | __do_insw
 | ^
   arch/powerpc/include/asm/io.h:610:56: note: expanded from macro '__do_insw'
 610 | #define __do_insw(p, b, n)  readsw((PCI_IO_ADDR)_IO_BASE+(p), 
(b), (n))
 |~^
   In file included from arch/powerpc/mm/pgtable-frag.c:12:
   In file included from include/linux/hardirq.h:11:
   In file included from arch/powerpc/include/asm/hardirq.h:6:
   In file included from include/linux/irq.h:20:
   In file included from include/linux/io.h:13:
   In file included from arch/powerpc/include/asm/io.h:672:
   arch/powerpc/include/asm/io-defs.h:47:1: error: performing pointer 
arithmetic on a null pointer has undefined behavior 
[-Werror,-Wnull-pointer-arithmetic]
  47 | DEF_PCI_AC_NORET(insl, (unsigned long p, void *b, unsigned long c),
 | ^~~
  48 |  (p, b, c), pio, p)
 |  ~~
   arch/powerpc/include/asm/io.h:669:3: note: expanded from macro 
'DEF_PCI_AC_NORET'
 669 | __do_##name al; \
 | ^~
   :42:1: note: expanded from here
  42 | __do_insl
 | ^
   arch/powerpc/include/asm/io.h:611:56: note: expanded from macro '__do_insl'
 611 | #define __do_insl(p, b, n)  readsl((PCI_IO_ADDR)_IO_BASE+(p), 
(b), (n))
 |~^
   In file included from arch/powerpc/mm/pgtable-frag.c:12:
   In file included from include/linux/hardirq.h:11:
   In file included from arch/powerpc/include/asm/hardirq.h:6:
   In file included from include/linux/irq.h:20:
   In file included from include/linux/io.h:13:
   In file included from arch/powerpc/include/asm/io.h:672:
   arch/powerpc/include/asm/io-defs.h:49:1: error: performing pointer 
arithmetic on a null pointer has undefined behavior 
[-Werror,-Wnull-pointer-arithmetic]
  49 | DEF_PCI_AC_NORET(outsb, (unsigned long p, const void *b, unsigned 
long c),
 | 
^~
  50 |  (p, b, c), pio, p)
 |  ~~
   arch/powerpc/include/asm/io.h:669:3: note: expanded from macro 
'DEF_PCI_AC_NORET'
 669 | __do_##n

Re: [PATCH] Documentation: devices.txt: reconcile serial/ucc_uart minor numers

2023-07-25 Thread Randy Dunlap



On 7/25/23 13:38, Timur Tabi wrote:
> On Mon, Jul 24, 2023 at 1:33 AM Randy Dunlap  wrote:
>>
>> Reconcile devices.txt with serial/ucc_uart.c regarding device number
>> assignments. ucc_uart.c supports 4 ports and uses minor devnums
>> 46-49, so update devices.txt with that info.
>> Then update ucc_uart.c's reference to the location of the devices.txt
>> list in the kernel source tree.
>>
>> Fixes: d7584ed2b994 ("[POWERPC] qe-uart: add support for Freescale 
>> QUICCEngine UART")
>> Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
>> Signed-off-by: Randy Dunlap 
>> Cc: Timur Tabi 
>> Cc: Kumar Gala 
>> Cc: linuxppc-dev@lists.ozlabs.org
>> Cc: Greg Kroah-Hartman 
>> Cc: Jiri Slaby 
>> Cc: linux-ser...@vger.kernel.org
>> Cc: Jonathan Corbet 
>> Cc: linux-...@vger.kernel.org
> 
> Acked-by: Timur Tabi 
> 
> One thing does concern me.  The UCC UART driver piggy-backs on the CPM
> driver's layout (see cpm_uart.h), but apparently CPM UART supports 6
> devices, not four:
> 
> #define UART_NRfs_uart_nr
> 
> where fs_uart_nr is defined in enum fs_uart_id.
> 
> Unfortunately, it's been so long since I've touched this code, I'm not
> sure whether this means anything.

If CPM UART code ever worked with > 4 ports, it probably just used minor devnums
that were not allocated to it.

Also, it looks like the CPU UART part of Documentation/admin-guide/devices.txt
needs to be updated:

 46 = /dev/cucpm0   Callout device for ttyCPM0
...
 49 = /dev/cucpm5   Callout device for ttyCPM5

The driver must use some tricks to get 6 ports into 4 devnums. :)


-- 
~Randy


Re: [PATCH] Documentation: devices.txt: reconcile serial/ucc_uart minor numers

2023-07-25 Thread Timur Tabi
On Mon, Jul 24, 2023 at 1:33 AM Randy Dunlap  wrote:
>
> Reconcile devices.txt with serial/ucc_uart.c regarding device number
> assignments. ucc_uart.c supports 4 ports and uses minor devnums
> 46-49, so update devices.txt with that info.
> Then update ucc_uart.c's reference to the location of the devices.txt
> list in the kernel source tree.
>
> Fixes: d7584ed2b994 ("[POWERPC] qe-uart: add support for Freescale 
> QUICCEngine UART")
> Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
> Signed-off-by: Randy Dunlap 
> Cc: Timur Tabi 
> Cc: Kumar Gala 
> Cc: linuxppc-dev@lists.ozlabs.org
> Cc: Greg Kroah-Hartman 
> Cc: Jiri Slaby 
> Cc: linux-ser...@vger.kernel.org
> Cc: Jonathan Corbet 
> Cc: linux-...@vger.kernel.org

Acked-by: Timur Tabi 

One thing does concern me.  The UCC UART driver piggy-backs on the CPM
driver's layout (see cpm_uart.h), but apparently CPM UART supports 6
devices, not four:

#define UART_NRfs_uart_nr

where fs_uart_nr is defined in enum fs_uart_id.

Unfortunately, it's been so long since I've touched this code, I'm not
sure whether this means anything.


Re: [PATCH] powerpc: Use shared font data

2023-07-25 Thread Sam Ravnborg
Hi David,

On Tue, Jul 25, 2023 at 01:01:41AM +0100, li...@treblig.org wrote:
> From: "Dr. David Alan Gilbert" 
> 
> PowerPC has a 'btext' font used for the console which is almost identical
> to the shared font_sun8x16, so use it rather than duplicating the data.
> 
> They were actually identical until about a decade ago when
>commit bcfbeecea11c ("drivers: console: font_: Change a glyph from
> "broken bar" to "vertical line"")
> 
> which changed the | in the shared font to be a solid
> bar rather than a broken bar.  That's the only difference.
> 
> This was originally spotted by PMD which noticed that sparc does
> the same thing with the same data, and they also share a bunch
> of functions to manipulate the data.  I've previously posted a near
> identical patch for sparc.
> 
> One difference I notice in PowerPC is that there are a bunch of compile
> options for the .c files for the early code to avoid a bunch of security
> compilation features;  it's not clear to me if this is a problem for
> this font data.
> 
> Tested very lightly with a boot without FS in qemu.
> 
> Signed-off-by: Dr. David Alan Gilbert 

Yep, looks very similar to sparc, so

Reviewed-by: Sam Ravnborg 


Re: [PATCH v6 00/13] Add support for DAX vmemmap optimization for ppc64

2023-07-25 Thread Andrew Morton
On Tue, 25 Jul 2023 00:37:46 +0530 "Aneesh Kumar K.V" 
 wrote:

> This patch series implements changes required to support DAX vmemmap
> optimization for ppc64.

Do we have any measurements to help us understand the magnitude
of this optimization?

And any documentation which helps users understand whether and
why they should enable this feature?


Re: Add fchmodat2() - or add a more general syscall?

2023-07-25 Thread Rich Felker
On Tue, Jul 25, 2023 at 07:39:51PM +0100, David Howells wrote:
> Florian Weimer  wrote:
> 
> > > Rather than adding a fchmodat2() syscall, should we add a
> > > "set_file_attrs()" syscall that takes a mask and allows you to set a bunch
> > > of stuff all in one go?  Basically, an interface to notify_change() in the
> > > kernel that would allow several stats to be set atomically.  This might be
> > > of particular interest to network filesystems.
> > 
> > Do you mean atomically as in compare-and-swap (update only if old values
> > match), or just a way to update multiple file attributes with a single
> > system call?
> 
> I was thinking more in terms of the latter.  AFAIK, there aren't any network
> filesystems support a CAS interface on file attributes like that.  To be able
> to do a CAS operation, we'd need to pass in the old values as well as the new.
> 
> Another thing we could look at is doing "create_and_set_attrs()", possibly
> allowing it to take a list of xattrs also.

Can we please not let " hey let's invent a new interface to do
something that will be hard for underlying filesystems to even provide
and that nothing needs because there's no standard API to do it" be
the enemy of "fixing a known problem implementing an existing standard
API that just requires a simple, clearly-scoped syscall to do it"?

Rich


Re: Add fchmodat2() - or add a more general syscall?

2023-07-25 Thread David Howells
Florian Weimer  wrote:

> > Rather than adding a fchmodat2() syscall, should we add a
> > "set_file_attrs()" syscall that takes a mask and allows you to set a bunch
> > of stuff all in one go?  Basically, an interface to notify_change() in the
> > kernel that would allow several stats to be set atomically.  This might be
> > of particular interest to network filesystems.
> 
> Do you mean atomically as in compare-and-swap (update only if old values
> match), or just a way to update multiple file attributes with a single
> system call?

I was thinking more in terms of the latter.  AFAIK, there aren't any network
filesystems support a CAS interface on file attributes like that.  To be able
to do a CAS operation, we'd need to pass in the old values as well as the new.

Another thing we could look at is doing "create_and_set_attrs()", possibly
allowing it to take a list of xattrs also.

David



Re: [PATCH v5 4/7] mm/hotplug: Support memmap_on_memory when memmap is not aligned to pageblocks

2023-07-25 Thread David Hildenbrand

On 25.07.23 12:02, Aneesh Kumar K.V wrote:

Currently, memmap_on_memory feature is only supported with memory block
sizes that result in vmemmap pages covering full page blocks. This is
because memory onlining/offlining code requires applicable ranges to be
pageblock-aligned, for example, to set the migratetypes properly.

This patch helps to lift that restriction by reserving more pages than
required for vmemmap space. This helps the start address to be page
block aligned with different memory block sizes. Using this facility
implies the kernel will be reserving some pages for every memoryblock.
This allows the memmap on memory feature to be widely useful with
different memory block size values.

For ex: with 64K page size and 256MiB memory block size, we require 4
pages to map vmemmap pages, To align things correctly we end up adding a
reserve of 28 pages. ie, for every 4096 pages 28 pages get reserved.

Signed-off-by: Aneesh Kumar K.V 
---
  .../admin-guide/mm/memory-hotplug.rst |  12 ++
  mm/memory_hotplug.c   | 121 --
  2 files changed, 119 insertions(+), 14 deletions(-)

diff --git a/Documentation/admin-guide/mm/memory-hotplug.rst 
b/Documentation/admin-guide/mm/memory-hotplug.rst
index bd77841041af..2994958c7ce8 100644
--- a/Documentation/admin-guide/mm/memory-hotplug.rst
+++ b/Documentation/admin-guide/mm/memory-hotplug.rst
@@ -433,6 +433,18 @@ The following module parameters are currently defined:
 memory in a way that huge pages in bigger
 granularity cannot be formed on hotplugged
 memory.
+
+With value "force" it could result in memory
+wastage due to memmap size limitations. For
+example, if the memmap for a memory block
+requires 1 MiB, but the pageblock size is 2
+MiB, 1 MiB of hotplugged memory will be wasted.
+Note that there are still cases where the
+feature cannot be enforced: for example, if the
+memmap is smaller than a single page, or if the
+architecture does not support the forced mode
+in all configurations.
+
  ``online_policy``  read-write: Set the basic policy used for
 automatic zone selection when onlining memory
 blocks without specifying a target zone.
diff --git a/mm/memory_hotplug.c b/mm/memory_hotplug.c
index 457824a6ecb8..5b472e137898 100644
--- a/mm/memory_hotplug.c
+++ b/mm/memory_hotplug.c
@@ -41,17 +41,89 @@
  #include "internal.h"
  #include "shuffle.h"
  
+enum {

+   MEMMAP_ON_MEMORY_DISABLE = 0,
+   MEMMAP_ON_MEMORY_ENABLE,
+   MEMMAP_ON_MEMORY_FORCE,
+};
+
+static int memmap_mode __read_mostly = MEMMAP_ON_MEMORY_DISABLE;
+
+static inline unsigned long memory_block_memmap_pages(void)
+{
+   unsigned long memmap_size;
+
+   memmap_size = PHYS_PFN(memory_block_size_bytes()) * sizeof(struct page);
+   return memmap_size >> PAGE_SHIFT;


I'd really move a !page variant (memory_block_memmap_size()) to the 
previous patch and use it in mhp_supports_memmap_on_memory() and 
arch_supports_memmap_on_memory().


Then, in this patch, reuse that function in 
memory_block_memmap_on_memory_pages() and ...



+}
+
+static inline unsigned long memory_block_memmap_on_memory_pages(void)
+{
+   unsigned long nr_pages = memory_block_memmap_pages();


... do here a

nr_pages = PHYS_PFN(memory_block_memmap_size());


Conceptually, it would be even cleaner to have here

nr_pages = PFN_UP(memory_block_memmap_size());

even though one can argue that mhp_supports_memmap_on_memory() will make 
sure that the unaligned value (memory_block_memmap_size()) covers full 
pages, but at least to me it looks cleaner that way. No strong opinion.




+
+   /*
+* In "forced" memmap_on_memory mode, we add extra pages to align the
+* vmemmap size to cover full pageblocks. That way, we can add memory
+* even if the vmemmap size is not properly aligned, however, we might 
waste
+* memory.
+*/
+   if (memmap_mode == MEMMAP_ON_MEMORY_FORCE)
+   return pageblock_align(nr_pages);
+   return nr_pages;
+}
+
  #ifdef CONFIG_MHP_MEMMAP_ON_MEMORY
  /*
   * memory_hotplug.memmap_on_memory parameter
   */
-static bool memmap_on_memory __ro_after_init;
-module_param(memmap_on_memory, bool, 0444);
-MODULE_PARM_DESC(memmap_on_memory, "Enable memmap on memory for memory 
hotplug");
+static int set_memmap_mode(const char *val, const struct kernel_param *kp)
+{
+   int ret, mode;
+   bool enabled;
+
+   if (sysfs_streq(val, "force") ||  sysfs_streq(val, "FORCE")) {
+   mode =  

Re: [RFC PATCH v11 01/29] KVM: Wrap kvm_gfn_range.pte in a per-action union

2023-07-25 Thread Sean Christopherson
On Fri, Jul 21, 2023, Xu Yilun wrote:
> On 2023-07-21 at 14:26:11 +0800, Yan Zhao wrote:
> > On Tue, Jul 18, 2023 at 04:44:44PM -0700, Sean Christopherson wrote:
> > 
> > May I know why KVM now needs to register to callback .change_pte()?
> 
> I can see the original purpose is to "setting a pte in the shadow page
> table directly, instead of flushing the shadow page table entry and then
> getting vmexit to set it"[1].
> 
> IIUC, KVM is expected to directly make the new pte present for new
> pages in this callback, like for COW.

Yes.

> > As also commented in kvm_mmu_notifier_change_pte(), .change_pte() must be
> > surrounded by .invalidate_range_{start,end}().
> > 
> > While kvm_mmu_notifier_invalidate_range_start() has called 
> > kvm_unmap_gfn_range()
> > to zap all leaf SPTEs, and page fault path will not install new SPTEs
> > successfully before kvm_mmu_notifier_invalidate_range_end(),
> > kvm_set_spte_gfn() should not be able to find any shadow present leaf 
> > entries to
> > update PFN.
> 
> I also failed to figure out how the kvm_set_spte_gfn() could pass
> several !is_shadow_present_pte(iter.old_spte) check then write the new
> pte.

It can't.  .change_pte() has been dead code on x86 for 10+ years at this point,
and if my assessment from a few years back still holds true, it's dead code on
all architectures.

The only reason I haven't formally proposed dropping the hook is that I don't 
want
to risk the patch backfiring, i.e. I don't want to prompt someone to care enough
to try and fix it.

commit c13fda237f08a388ba8a0849785045944bf39834
Author: Sean Christopherson 
Date:   Fri Apr 2 02:56:49 2021 +0200

KVM: Assert that notifier count is elevated in .change_pte()

In KVM's .change_pte() notification callback, replace the notifier
sequence bump with a WARN_ON assertion that the notifier count is
elevated.  An elevated count provides stricter protections than bumping
the sequence, and the sequence is guarnateed to be bumped before the
count hits zero.

When .change_pte() was added by commit 828502d30073 ("ksm: add
mmu_notifier set_pte_at_notify()"), bumping the sequence was necessary
as .change_pte() would be invoked without any surrounding notifications.

However, since commit 6bdb913f0a70 ("mm: wrap calls to set_pte_at_notify
with invalidate_range_start and invalidate_range_end"), all calls to
.change_pte() are guaranteed to be surrounded by start() and end(), and
so are guaranteed to run with an elevated notifier count.

Note, wrapping .change_pte() with .invalidate_range_{start,end}() is a
bug of sorts, as invalidating the secondary MMU's (KVM's) PTE defeats
the purpose of .change_pte().  Every arch's kvm_set_spte_hva() assumes
.change_pte() is called when the relevant SPTE is present in KVM's MMU,
as the original goal was to accelerate Kernel Samepage Merging (KSM) by
updating KVM's SPTEs without requiring a VM-Exit (due to invalidating
the SPTE).  I.e. it means that .change_pte() is effectively dead code
on _all_ architectures.

x86 and MIPS are clearcut nops if the old SPTE is not-present, and that
is guaranteed due to the prior invalidation.  PPC simply unmaps the SPTE,
which again should be a nop due to the invalidation.  arm64 is a bit
murky, but it's also likely a nop because kvm_pgtable_stage2_map() is
called without a cache pointer, which means it will map an entry if and
only if an existing PTE was found.

For now, take advantage of the bug to simplify future consolidation of
KVMs's MMU notifier code.   Doing so will not greatly complicate fixing
.change_pte(), assuming it's even worth fixing.  .change_pte() has been
broken for 8+ years and no one has complained.  Even if there are
KSM+KVM users that care deeply about its performance, the benefits of
avoiding VM-Exits via .change_pte() need to be reevaluated to justify
the added complexity and testing burden.  Ripping out .change_pte()
entirely would be a lot easier.


Re: [PATCH v5 7/7] mm/hotplug: Enable runtime update of memmap_on_memory parameter

2023-07-25 Thread David Hildenbrand

On 25.07.23 12:02, Aneesh Kumar K.V wrote:

Signed-off-by: Aneesh Kumar K.V 
---
  mm/memory_hotplug.c | 27 +++
  1 file changed, 15 insertions(+), 12 deletions(-)

diff --git a/mm/memory_hotplug.c b/mm/memory_hotplug.c
index 96e794f39313..6cb6eac1aee5 100644
--- a/mm/memory_hotplug.c
+++ b/mm/memory_hotplug.c
@@ -95,7 +95,12 @@ static int set_memmap_mode(const char *val, const struct 
kernel_param *kp)
mode =  MEMMAP_ON_MEMORY_DISABLE;
  
  matched:

+   /*
+* Avoid changing memmap mode during hotplug.
+*/
+   get_online_mems();
*((int *)kp->arg) =  mode;
+   put_online_mems();
if (mode == MEMMAP_ON_MEMORY_FORCE) {
unsigned long memmap_pages = 
memory_block_memmap_on_memory_pages();
  
@@ -116,7 +121,7 @@ static const struct kernel_param_ops memmap_mode_ops = {

.set = set_memmap_mode,
.get = get_memmap_mode,
  };
-module_param_cb(memmap_on_memory, _mode_ops, _mode, 0444);
+module_param_cb(memmap_on_memory, _mode_ops, _mode, 0644);
  MODULE_PARM_DESC(memmap_on_memory, "Enable memmap on memory for memory 
hotplug\n"
 "With value \"force\" it could result in memory wastage due "
 "to memmap size limitations (Y/N/force)");
@@ -2175,18 +2180,16 @@ static int __ref try_remove_memory(u64 start, u64 size)
 * We only support removing memory added with MHP_MEMMAP_ON_MEMORY in
 * the same granularity it was added - a single memory block.
 */
-   if (mhp_memmap_on_memory()) {
-   ret = walk_memory_blocks(start, size, _altmap,
-get_vmemmap_altmap_cb);
-   if (ret) {
-   if (size != memory_block_size_bytes()) {
-   pr_warn("Refuse to remove %#llx - %#llx,"
-   "wrong granularity\n",
-   start, start + size);
-   return -EINVAL;
-   }
-   altmap = _altmap;
+   ret = walk_memory_blocks(start, size, _altmap,
+get_vmemmap_altmap_cb);
+   if (ret) {
+   if (size != memory_block_size_bytes()) {
+   pr_warn("Refuse to remove %#llx - %#llx,"
+   "wrong granularity\n",
+   start, start + size);
+   return -EINVAL;
}
+   altmap = _altmap;
}
  
  	/* remove memmap entry */



Acked-by: David Hildenbrand 

--
Cheers,

David / dhildenb



Re: [PATCH] Documentation: devices.txt: reconcile serial/ucc_uart minor numers

2023-07-25 Thread Randy Dunlap



On 7/25/23 10:27, Greg Kroah-Hartman wrote:
> On Sun, Jul 23, 2023 at 11:33:41PM -0700, Randy Dunlap wrote:
>> Reconcile devices.txt with serial/ucc_uart.c regarding device number
>> assignments. ucc_uart.c supports 4 ports and uses minor devnums
>> 46-49, so update devices.txt with that info.
>> Then update ucc_uart.c's reference to the location of the devices.txt
>> list in the kernel source tree.
>>
>> Fixes: d7584ed2b994 ("[POWERPC] qe-uart: add support for Freescale 
>> QUICCEngine UART")
>> Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
>> Signed-off-by: Randy Dunlap 
>> Cc: Timur Tabi 
>> Cc: Kumar Gala 
>> Cc: linuxppc-dev@lists.ozlabs.org
>> Cc: Greg Kroah-Hartman 
>> Cc: Jiri Slaby 
>> Cc: linux-ser...@vger.kernel.org
>> Cc: Jonathan Corbet 
>> Cc: linux-...@vger.kernel.org
>> ---
>>  Documentation/admin-guide/devices.txt |2 +-
>>  drivers/tty/serial/ucc_uart.c |2 +-
>>  2 files changed, 2 insertions(+), 2 deletions(-)
> 
> Very nice, thanks for catching this, I'll go queue it up.
> 
> Actually, how did you notice this?  I don't think the devices.txt file
> is up to date at all anymore, and odds are, other things are wrong in it
> too.

I accidentally! saw some reference to lanana.org in the kernel source code
and just grepped for that and saw this...

-- 
~Randy


Re: [PATCH] powerpc: Use shared font data

2023-07-25 Thread Dr. David Alan Gilbert
* Sam Ravnborg (s...@ravnborg.org) wrote:
> Hi David,
> 
> On Tue, Jul 25, 2023 at 01:01:41AM +0100, li...@treblig.org wrote:
> > From: "Dr. David Alan Gilbert" 
> > 
> > PowerPC has a 'btext' font used for the console which is almost identical
> > to the shared font_sun8x16, so use it rather than duplicating the data.
> > 
> > They were actually identical until about a decade ago when
> >commit bcfbeecea11c ("drivers: console: font_: Change a glyph from
> > "broken bar" to "vertical line"")
> > 
> > which changed the | in the shared font to be a solid
> > bar rather than a broken bar.  That's the only difference.
> > 
> > This was originally spotted by PMD which noticed that sparc does
> > the same thing with the same data, and they also share a bunch
> > of functions to manipulate the data.  I've previously posted a near
> > identical patch for sparc.
> > 
> > One difference I notice in PowerPC is that there are a bunch of compile
> > options for the .c files for the early code to avoid a bunch of security
> > compilation features;  it's not clear to me if this is a problem for
> > this font data.
> > 
> > Tested very lightly with a boot without FS in qemu.
> > 
> > Signed-off-by: Dr. David Alan Gilbert 
> 
> Yep, looks very similar to sparc, so
> 
> Reviewed-by: Sam Ravnborg 

Thanks!

Dave

-- 
 -Open up your eyes, open up your mind, open up your code ---   
/ Dr. David Alan Gilbert|   Running GNU/Linux   | Happy  \ 
\dave @ treblig.org |   | In Hex /
 \ _|_ http://www.treblig.org   |___/


Re: [PATCH] Documentation: devices.txt: reconcile serial/ucc_uart minor numers

2023-07-25 Thread Greg Kroah-Hartman
On Sun, Jul 23, 2023 at 11:33:41PM -0700, Randy Dunlap wrote:
> Reconcile devices.txt with serial/ucc_uart.c regarding device number
> assignments. ucc_uart.c supports 4 ports and uses minor devnums
> 46-49, so update devices.txt with that info.
> Then update ucc_uart.c's reference to the location of the devices.txt
> list in the kernel source tree.
> 
> Fixes: d7584ed2b994 ("[POWERPC] qe-uart: add support for Freescale 
> QUICCEngine UART")
> Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
> Signed-off-by: Randy Dunlap 
> Cc: Timur Tabi 
> Cc: Kumar Gala 
> Cc: linuxppc-dev@lists.ozlabs.org
> Cc: Greg Kroah-Hartman 
> Cc: Jiri Slaby 
> Cc: linux-ser...@vger.kernel.org
> Cc: Jonathan Corbet 
> Cc: linux-...@vger.kernel.org
> ---
>  Documentation/admin-guide/devices.txt |2 +-
>  drivers/tty/serial/ucc_uart.c |2 +-
>  2 files changed, 2 insertions(+), 2 deletions(-)

Very nice, thanks for catching this, I'll go queue it up.

Actually, how did you notice this?  I don't think the devices.txt file
is up to date at all anymore, and odds are, other things are wrong in it
too.

thanks,

greg k-h


Re: Add fchmodat2() - or add a more general syscall?

2023-07-25 Thread Aleksa Sarai
On 2023-07-25, David Howells  wrote:
> Rather than adding a fchmodat2() syscall, should we add a "set_file_attrs()"
> syscall that takes a mask and allows you to set a bunch of stuff all in one
> go?  Basically, an interface to notify_change() in the kernel that would allow
> several stats to be set atomically.  This might be of particular interest to
> network filesystems.

Presumably looking something like statx(2) (except hopefully with
extensible structs this time :P)? I think that could also be useful, but
given this is a fairly straight-forward syscall addition (and it also
would resolve the AT_EMPTY_PATH issue for chmod as well as simplify the
glibc wrapper), I think it makes sense to take this and we can do
set_statx(2) separately?

-- 
Aleksa Sarai
Senior Software Engineer (Containers)
SUSE Linux GmbH



signature.asc
Description: PGP signature


Re: [PATCH v4 2/5] fs: Add fchmodat2()

2023-07-25 Thread Aleksa Sarai
On 2023-07-11, Alexey Gladkov  wrote:
> On the userspace side fchmodat(3) is implemented as a wrapper
> function which implements the POSIX-specified interface. This
> interface differs from the underlying kernel system call, which does not
> have a flags argument. Most implementations require procfs [1][2].
> 
> There doesn't appear to be a good userspace workaround for this issue
> but the implementation in the kernel is pretty straight-forward.
> 
> The new fchmodat2() syscall allows to pass the AT_SYMLINK_NOFOLLOW flag,
> unlike existing fchmodat.
> 
> [1] 
> https://sourceware.org/git/?p=glibc.git;a=blob;f=sysdeps/unix/sysv/linux/fchmodat.c;h=17eca54051ee28ba1ec3f9aed170a62630959143;hb=a492b1e5ef7ab50c6fdd4e4e9879ea5569ab0a6c#l35
> [2] 
> https://git.musl-libc.org/cgit/musl/tree/src/stat/fchmodat.c?id=718f363bc2067b6487900eddc9180c84e7739f80#n28
> 
> Co-developed-by: Palmer Dabbelt 
> Signed-off-by: Palmer Dabbelt 
> Signed-off-by: Alexey Gladkov 
> Acked-by: Arnd Bergmann 
> ---
>  fs/open.c| 18 ++
>  include/linux/syscalls.h |  2 ++
>  2 files changed, 16 insertions(+), 4 deletions(-)
> 
> diff --git a/fs/open.c b/fs/open.c
> index 0c55c8e7f837..39a7939f0d00 100644
> --- a/fs/open.c
> +++ b/fs/open.c
> @@ -671,11 +671,11 @@ SYSCALL_DEFINE2(fchmod, unsigned int, fd, umode_t, mode)
>   return err;
>  }
>  
> -static int do_fchmodat(int dfd, const char __user *filename, umode_t mode)
> +static int do_fchmodat(int dfd, const char __user *filename, umode_t mode, 
> int lookup_flags)

I think it'd be much neater to do the conversion of AT_ flags here and
pass 0 as a flags argument for all of the wrappers (this is how most of
the other xyz(), fxyz(), fxyzat() syscall wrappers are done IIRC).

>  {
>   struct path path;
>   int error;
> - unsigned int lookup_flags = LOOKUP_FOLLOW;
> +
>  retry:
>   error = user_path_at(dfd, filename, lookup_flags, );
>   if (!error) {
> @@ -689,15 +689,25 @@ static int do_fchmodat(int dfd, const char __user 
> *filename, umode_t mode)
>   return error;
>  }
>  
> +SYSCALL_DEFINE4(fchmodat2, int, dfd, const char __user *, filename,
> + umode_t, mode, int, flags)
> +{
> + if (unlikely(flags & ~AT_SYMLINK_NOFOLLOW))
> + return -EINVAL;

We almost certainly want to support AT_EMPTY_PATH at the same time.
Otherwise userspace will still need to go through /proc when trying to
chmod a file handle they have.

> +
> + return do_fchmodat(dfd, filename, mode,
> + flags & AT_SYMLINK_NOFOLLOW ? 0 : LOOKUP_FOLLOW);
> +}
> +
>  SYSCALL_DEFINE3(fchmodat, int, dfd, const char __user *, filename,
>   umode_t, mode)
>  {
> - return do_fchmodat(dfd, filename, mode);
> + return do_fchmodat(dfd, filename, mode, LOOKUP_FOLLOW);
>  }
>  
>  SYSCALL_DEFINE2(chmod, const char __user *, filename, umode_t, mode)
>  {
> - return do_fchmodat(AT_FDCWD, filename, mode);
> + return do_fchmodat(AT_FDCWD, filename, mode, LOOKUP_FOLLOW);
>  }
>  
>  /*
> diff --git a/include/linux/syscalls.h b/include/linux/syscalls.h
> index 584f404bf868..6e852279fbc3 100644
> --- a/include/linux/syscalls.h
> +++ b/include/linux/syscalls.h
> @@ -440,6 +440,8 @@ asmlinkage long sys_chroot(const char __user *filename);
>  asmlinkage long sys_fchmod(unsigned int fd, umode_t mode);
>  asmlinkage long sys_fchmodat(int dfd, const char __user *filename,
>umode_t mode);
> +asmlinkage long sys_fchmodat2(int dfd, const char __user *filename,
> +  umode_t mode, int flags);
>  asmlinkage long sys_fchownat(int dfd, const char __user *filename, uid_t 
> user,
>gid_t group, int flag);
>  asmlinkage long sys_fchown(unsigned int fd, uid_t user, gid_t group);
> -- 
> 2.33.8
> 

-- 
Aleksa Sarai
Senior Software Engineer (Containers)
SUSE Linux GmbH



signature.asc
Description: PGP signature


Re: [PATCH v4 3/5] arch: Register fchmodat2, usually as syscall 452

2023-07-25 Thread Aleksa Sarai
On 2023-07-11, Alexey Gladkov  wrote:
> From: Palmer Dabbelt 
> 
> This registers the new fchmodat2 syscall in most places as nuber 452,
> with alpha being the exception where it's 562.  I found all these sites
> by grepping for fspick, which I assume has found me everything.

Shouldn't this patch be squashed with the patch that adds the syscall?
At least, that's how I've usually seen it done...

> Signed-off-by: Palmer Dabbelt 
> Signed-off-by: Alexey Gladkov 
> ---
>  arch/alpha/kernel/syscalls/syscall.tbl  | 1 +
>  arch/arm/tools/syscall.tbl  | 1 +
>  arch/arm64/include/asm/unistd.h | 2 +-
>  arch/arm64/include/asm/unistd32.h   | 2 ++
>  arch/ia64/kernel/syscalls/syscall.tbl   | 1 +
>  arch/m68k/kernel/syscalls/syscall.tbl   | 1 +
>  arch/microblaze/kernel/syscalls/syscall.tbl | 1 +
>  arch/mips/kernel/syscalls/syscall_n32.tbl   | 1 +
>  arch/mips/kernel/syscalls/syscall_n64.tbl   | 1 +
>  arch/mips/kernel/syscalls/syscall_o32.tbl   | 1 +
>  arch/parisc/kernel/syscalls/syscall.tbl | 1 +
>  arch/powerpc/kernel/syscalls/syscall.tbl| 1 +
>  arch/s390/kernel/syscalls/syscall.tbl   | 1 +
>  arch/sh/kernel/syscalls/syscall.tbl | 1 +
>  arch/sparc/kernel/syscalls/syscall.tbl  | 1 +
>  arch/x86/entry/syscalls/syscall_32.tbl  | 1 +
>  arch/x86/entry/syscalls/syscall_64.tbl  | 1 +
>  arch/xtensa/kernel/syscalls/syscall.tbl | 1 +
>  include/uapi/asm-generic/unistd.h   | 5 -
>  19 files changed, 23 insertions(+), 2 deletions(-)
> 
> diff --git a/arch/alpha/kernel/syscalls/syscall.tbl 
> b/arch/alpha/kernel/syscalls/syscall.tbl
> index 1f13995d00d7..ad37569d0507 100644
> --- a/arch/alpha/kernel/syscalls/syscall.tbl
> +++ b/arch/alpha/kernel/syscalls/syscall.tbl
> @@ -491,3 +491,4 @@
>  559  common  futex_waitv sys_futex_waitv
>  560  common  set_mempolicy_home_node sys_ni_syscall
>  561  common  cachestat   sys_cachestat
> +562  common  fchmodat2   sys_fchmodat2
> diff --git a/arch/arm/tools/syscall.tbl b/arch/arm/tools/syscall.tbl
> index 8ebed8a13874..c572d6c3dee0 100644
> --- a/arch/arm/tools/syscall.tbl
> +++ b/arch/arm/tools/syscall.tbl
> @@ -465,3 +465,4 @@
>  449  common  futex_waitv sys_futex_waitv
>  450  common  set_mempolicy_home_node sys_set_mempolicy_home_node
>  451  common  cachestat   sys_cachestat
> +452  common  fchmodat2   sys_fchmodat2
> diff --git a/arch/arm64/include/asm/unistd.h b/arch/arm64/include/asm/unistd.h
> index 64a514f90131..bd77253b62e0 100644
> --- a/arch/arm64/include/asm/unistd.h
> +++ b/arch/arm64/include/asm/unistd.h
> @@ -39,7 +39,7 @@
>  #define __ARM_NR_compat_set_tls  (__ARM_NR_COMPAT_BASE + 5)
>  #define __ARM_NR_COMPAT_END  (__ARM_NR_COMPAT_BASE + 0x800)
>  
> -#define __NR_compat_syscalls 452
> +#define __NR_compat_syscalls 453
>  #endif
>  
>  #define __ARCH_WANT_SYS_CLONE
> diff --git a/arch/arm64/include/asm/unistd32.h 
> b/arch/arm64/include/asm/unistd32.h
> index d952a28463e0..78b68311ec81 100644
> --- a/arch/arm64/include/asm/unistd32.h
> +++ b/arch/arm64/include/asm/unistd32.h
> @@ -909,6 +909,8 @@ __SYSCALL(__NR_futex_waitv, sys_futex_waitv)
>  __SYSCALL(__NR_set_mempolicy_home_node, sys_set_mempolicy_home_node)
>  #define __NR_cachestat 451
>  __SYSCALL(__NR_cachestat, sys_cachestat)
> +#define __NR_fchmodat2 452
> +__SYSCALL(__NR_fchmodat2, sys_fchmodat2)
>  
>  /*
>   * Please add new compat syscalls above this comment and update
> diff --git a/arch/ia64/kernel/syscalls/syscall.tbl 
> b/arch/ia64/kernel/syscalls/syscall.tbl
> index f8c74ffeeefb..83d8609aec03 100644
> --- a/arch/ia64/kernel/syscalls/syscall.tbl
> +++ b/arch/ia64/kernel/syscalls/syscall.tbl
> @@ -372,3 +372,4 @@
>  449  common  futex_waitv sys_futex_waitv
>  450  common  set_mempolicy_home_node sys_set_mempolicy_home_node
>  451  common  cachestat   sys_cachestat
> +452  common  fchmodat2   sys_fchmodat2
> diff --git a/arch/m68k/kernel/syscalls/syscall.tbl 
> b/arch/m68k/kernel/syscalls/syscall.tbl
> index 4f504783371f..259ceb125367 100644
> --- a/arch/m68k/kernel/syscalls/syscall.tbl
> +++ b/arch/m68k/kernel/syscalls/syscall.tbl
> @@ -451,3 +451,4 @@
>  449  common  futex_waitv sys_futex_waitv
>  450  common  set_mempolicy_home_node sys_set_mempolicy_home_node
>  451  common  cachestat   sys_cachestat
> +452  common  fchmodat2   sys_fchmodat2
> diff --git a/arch/microblaze/kernel/syscalls/syscall.tbl 
> b/arch/microblaze/kernel/syscalls/syscall.tbl
> index 858d22bf275c..a3798c2637fd 100644
> --- a/arch/microblaze/kernel/syscalls/syscall.tbl
> +++ b/arch/microblaze/kernel/syscalls/syscall.tbl
> @@ -457,3 +457,4 @@
>  449  common  futex_waitv sys_futex_waitv
>  450  common  

Re: [PATCH 24/26] ASoC: codecs: Add support for the framer codec

2023-07-25 Thread Randy Dunlap



On 7/25/23 02:24, Herve Codina wrote:
> +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 with the framer is connected to transport the audio data.

  on which

> +
> +   To compile this driver as a module, choose M here: the module
> +   will be called snd-soc-framer.

-- 
~Randy


Re: Add fchmodat2() - or add a more general syscall?

2023-07-25 Thread Florian Weimer
* David Howells:

> Rather than adding a fchmodat2() syscall, should we add a "set_file_attrs()"
> syscall that takes a mask and allows you to set a bunch of stuff all in one
> go?  Basically, an interface to notify_change() in the kernel that would allow
> several stats to be set atomically.  This might be of particular interest to
> network filesystems.

Do you mean atomically as in compare-and-swap (update only if old values
match), or just a way to update multiple file attributes with a single
system call?

Thanks,
Florian



Re: [RFC PATCH v11 12/29] KVM: Add KVM_CREATE_GUEST_MEMFD ioctl() for guest-specific backing memory

2023-07-25 Thread Sean Christopherson
On Tue, Jul 25, 2023, Wei W Wang wrote:
> On Wednesday, July 19, 2023 7:45 AM, Sean Christopherson wrote:
> > +int kvm_gmem_get_pfn(struct kvm *kvm, struct kvm_memory_slot *slot,
> > +gfn_t gfn, kvm_pfn_t *pfn, int *max_order) {
> > +   pgoff_t index = gfn - slot->base_gfn + slot->gmem.pgoff;
> > +   struct kvm_gmem *gmem;
> > +   struct folio *folio;
> > +   struct page *page;
> > +   struct file *file;
> > +
> > +   file = kvm_gmem_get_file(slot);
> > +   if (!file)
> > +   return -EFAULT;
> > +
> > +   gmem = file->private_data;
> > +
> > +   if (WARN_ON_ONCE(xa_load(>bindings, index) != slot)) {
> > +   fput(file);
> > +   return -EIO;
> > +   }
> > +
> > +   folio = kvm_gmem_get_folio(file_inode(file), index);
> > +   if (!folio) {
> > +   fput(file);
> > +   return -ENOMEM;
> > +   }
> > +
> > +   page = folio_file_page(folio, index);
> > +
> > +   *pfn = page_to_pfn(page);
> > +   *max_order = compound_order(compound_head(page));
> 
> Maybe better to check if caller provided a buffer to get the max_order:
> if (max_order)
>   *max_order = compound_order(compound_head(page));
> 
> This is what the previous version did (restrictedmem_get_page),
> so that callers who only want to get a pfn don't need to define
> an unused "order" param.

My preference would be to require @max_order.  I can kinda sorta see why a 
generic
implementation (restrictedmem) would make the param optional, but with gmem 
being
KVM-internal I think it makes sense to require the param.  Even if pKVM doesn't
_currently_ need/want the order of the backing allocation, presumably that's 
because
hugepage support is still on the TODO list, not because pKVM fundamentally 
doesn't
need to know the order of the backing allocation.


Add fchmodat2() - or add a more general syscall?

2023-07-25 Thread David Howells
Rather than adding a fchmodat2() syscall, should we add a "set_file_attrs()"
syscall that takes a mask and allows you to set a bunch of stuff all in one
go?  Basically, an interface to notify_change() in the kernel that would allow
several stats to be set atomically.  This might be of particular interest to
network filesystems.

David



[PATCH v4 5/5] mmu_notifiers: Rename invalidate_range notifier

2023-07-25 Thread Alistair Popple
There are two main use cases for mmu notifiers. One is by KVM which
uses mmu_notifier_invalidate_range_start()/end() to manage a software
TLB.

The other is to manage hardware TLBs which need to use the
invalidate_range() callback because HW can establish new TLB entries
at any time. Hence using start/end() can lead to memory corruption as
these callbacks happen too soon/late during page unmap.

mmu notifier users should therefore either use the start()/end()
callbacks or the invalidate_range() callbacks. To make this usage
clearer rename the invalidate_range() callback to
arch_invalidate_secondary_tlbs() and update documention.

Signed-off-by: Alistair Popple 
Suggested-by: Jason Gunthorpe 
Acked-by: Catalin Marinas 
Reviewed-by: Jason Gunthorpe 
---
 arch/arm64/include/asm/tlbflush.h   |  6 +-
 arch/powerpc/mm/book3s64/radix_hugetlbpage.c|  2 +-
 arch/powerpc/mm/book3s64/radix_tlb.c|  8 +--
 arch/x86/include/asm/tlbflush.h |  2 +-
 arch/x86/mm/tlb.c   |  2 +-
 drivers/iommu/amd/iommu_v2.c| 10 ++--
 drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-sva.c | 13 ++---
 drivers/iommu/intel/svm.c   |  8 +--
 drivers/misc/ocxl/link.c|  8 +--
 include/linux/mmu_notifier.h| 48 +-
 mm/huge_memory.c|  4 +-
 mm/hugetlb.c|  7 +--
 mm/mmu_notifier.c   | 21 ++--
 13 files changed, 76 insertions(+), 63 deletions(-)

diff --git a/arch/arm64/include/asm/tlbflush.h 
b/arch/arm64/include/asm/tlbflush.h
index a99349d..84a05a0 100644
--- a/arch/arm64/include/asm/tlbflush.h
+++ b/arch/arm64/include/asm/tlbflush.h
@@ -253,7 +253,7 @@ static inline void flush_tlb_mm(struct mm_struct *mm)
__tlbi(aside1is, asid);
__tlbi_user(aside1is, asid);
dsb(ish);
-   mmu_notifier_invalidate_range(mm, 0, -1UL);
+   mmu_notifier_arch_invalidate_secondary_tlbs(mm, 0, -1UL);
 }
 
 static inline void __flush_tlb_page_nosync(struct mm_struct *mm,
@@ -265,7 +265,7 @@ static inline void __flush_tlb_page_nosync(struct mm_struct 
*mm,
addr = __TLBI_VADDR(uaddr, ASID(mm));
__tlbi(vale1is, addr);
__tlbi_user(vale1is, addr);
-   mmu_notifier_invalidate_range(mm, uaddr & PAGE_MASK,
+   mmu_notifier_arch_invalidate_secondary_tlbs(mm, uaddr & PAGE_MASK,
(uaddr & PAGE_MASK) + 
PAGE_SIZE);
 }
 
@@ -400,7 +400,7 @@ static inline void __flush_tlb_range(struct vm_area_struct 
*vma,
scale++;
}
dsb(ish);
-   mmu_notifier_invalidate_range(vma->vm_mm, start, end);
+   mmu_notifier_arch_invalidate_secondary_tlbs(vma->vm_mm, start, end);
 }
 
 static inline void flush_tlb_range(struct vm_area_struct *vma,
diff --git a/arch/powerpc/mm/book3s64/radix_hugetlbpage.c 
b/arch/powerpc/mm/book3s64/radix_hugetlbpage.c
index f3fb49f..17075c7 100644
--- a/arch/powerpc/mm/book3s64/radix_hugetlbpage.c
+++ b/arch/powerpc/mm/book3s64/radix_hugetlbpage.c
@@ -39,7 +39,7 @@ void radix__flush_hugetlb_tlb_range(struct vm_area_struct 
*vma, unsigned long st
radix__flush_tlb_pwc_range_psize(vma->vm_mm, start, end, psize);
else
radix__flush_tlb_range_psize(vma->vm_mm, start, end, psize);
-   mmu_notifier_invalidate_range(vma->vm_mm, start, end);
+   mmu_notifier_arch_invalidate_secondary_tlbs(vma->vm_mm, start, end);
 }
 
 void radix__huge_ptep_modify_prot_commit(struct vm_area_struct *vma,
diff --git a/arch/powerpc/mm/book3s64/radix_tlb.c 
b/arch/powerpc/mm/book3s64/radix_tlb.c
index 4d44902..06e647e 100644
--- a/arch/powerpc/mm/book3s64/radix_tlb.c
+++ b/arch/powerpc/mm/book3s64/radix_tlb.c
@@ -987,7 +987,7 @@ void radix__flush_tlb_mm(struct mm_struct *mm)
}
}
preempt_enable();
-   mmu_notifier_invalidate_range(mm, 0, -1UL);
+   mmu_notifier_arch_invalidate_secondary_tlbs(mm, 0, -1UL);
 }
 EXPORT_SYMBOL(radix__flush_tlb_mm);
 
@@ -1021,7 +1021,7 @@ static void __flush_all_mm(struct mm_struct *mm, bool 
fullmm)
_tlbiel_pid_multicast(mm, pid, RIC_FLUSH_ALL);
}
preempt_enable();
-   mmu_notifier_invalidate_range(mm, 0, -1UL);
+   mmu_notifier_arch_invalidate_secondary_tlbs(mm, 0, -1UL);
 }
 
 void radix__flush_all_mm(struct mm_struct *mm)
@@ -1230,7 +1230,7 @@ static inline void __radix__flush_tlb_range(struct 
mm_struct *mm,
}
 out:
preempt_enable();
-   mmu_notifier_invalidate_range(mm, start, end);
+   mmu_notifier_arch_invalidate_secondary_tlbs(mm, start, end);
 }
 
 void radix__flush_tlb_range(struct vm_area_struct *vma, unsigned long start,
@@ -1395,7 +1395,7 @@ static void __radix__flush_tlb_range_psize(struct 
mm_struct *mm,
}
 out:
preempt_enable();
-   mmu_notifier_invalidate_range(mm, start, 

[PATCH v4 4/5] mmu_notifiers: Don't invalidate secondary TLBs as part of mmu_notifier_invalidate_range_end()

2023-07-25 Thread Alistair Popple
Secondary TLBs are now invalidated from the architecture specific TLB
invalidation functions. Therefore there is no need to explicitly
notify or invalidate as part of the range end functions. This means we
can remove mmu_notifier_invalidate_range_end_only() and some of the
ptep_*_notify() functions.

Signed-off-by: Alistair Popple 
Reviewed-by: Jason Gunthorpe 
---
 include/linux/mmu_notifier.h | 56 +
 kernel/events/uprobes.c  |  2 +-
 mm/huge_memory.c | 25 ++---
 mm/hugetlb.c |  1 +-
 mm/memory.c  |  8 +
 mm/migrate_device.c  |  9 +-
 mm/mmu_notifier.c| 25 ++---
 mm/rmap.c| 40 +--
 8 files changed, 14 insertions(+), 152 deletions(-)

diff --git a/include/linux/mmu_notifier.h b/include/linux/mmu_notifier.h
index 64a3e05..f2e9edc 100644
--- a/include/linux/mmu_notifier.h
+++ b/include/linux/mmu_notifier.h
@@ -395,8 +395,7 @@ extern int __mmu_notifier_test_young(struct mm_struct *mm,
 extern void __mmu_notifier_change_pte(struct mm_struct *mm,
  unsigned long address, pte_t pte);
 extern int __mmu_notifier_invalidate_range_start(struct mmu_notifier_range *r);
-extern void __mmu_notifier_invalidate_range_end(struct mmu_notifier_range *r,
- bool only_end);
+extern void __mmu_notifier_invalidate_range_end(struct mmu_notifier_range *r);
 extern void __mmu_notifier_invalidate_range(struct mm_struct *mm,
  unsigned long start, unsigned long end);
 extern bool
@@ -481,14 +480,7 @@ mmu_notifier_invalidate_range_end(struct 
mmu_notifier_range *range)
might_sleep();
 
if (mm_has_notifiers(range->mm))
-   __mmu_notifier_invalidate_range_end(range, false);
-}
-
-static inline void
-mmu_notifier_invalidate_range_only_end(struct mmu_notifier_range *range)
-{
-   if (mm_has_notifiers(range->mm))
-   __mmu_notifier_invalidate_range_end(range, true);
+   __mmu_notifier_invalidate_range_end(range);
 }
 
 static inline void mmu_notifier_invalidate_range(struct mm_struct *mm,
@@ -582,45 +574,6 @@ static inline void mmu_notifier_range_init_owner(
__young;\
 })
 
-#defineptep_clear_flush_notify(__vma, __address, __ptep)   
\
-({ \
-   unsigned long ___addr = __address & PAGE_MASK;  \
-   struct mm_struct *___mm = (__vma)->vm_mm;   \
-   pte_t ___pte;   \
-   \
-   ___pte = ptep_clear_flush(__vma, __address, __ptep);\
-   mmu_notifier_invalidate_range(___mm, ___addr,   \
-   ___addr + PAGE_SIZE);   \
-   \
-   ___pte; \
-})
-
-#define pmdp_huge_clear_flush_notify(__vma, __haddr, __pmd)\
-({ \
-   unsigned long ___haddr = __haddr & HPAGE_PMD_MASK;  \
-   struct mm_struct *___mm = (__vma)->vm_mm;   \
-   pmd_t ___pmd;   \
-   \
-   ___pmd = pmdp_huge_clear_flush(__vma, __haddr, __pmd);  \
-   mmu_notifier_invalidate_range(___mm, ___haddr,  \
- ___haddr + HPAGE_PMD_SIZE);   \
-   \
-   ___pmd; \
-})
-
-#define pudp_huge_clear_flush_notify(__vma, __haddr, __pud)\
-({ \
-   unsigned long ___haddr = __haddr & HPAGE_PUD_MASK;  \
-   struct mm_struct *___mm = (__vma)->vm_mm;   \
-   pud_t ___pud;   \
-   \
-   ___pud = pudp_huge_clear_flush(__vma, __haddr, __pud);  \
-   mmu_notifier_invalidate_range(___mm, ___haddr,  \
- ___haddr + HPAGE_PUD_SIZE);   \
-   \
-   ___pud; \
-})
-
 /*
  * set_pte_at_notify() sets the pte _after_ running the notifier.
  * This is safe to start by updating the secondary MMUs, because the 

[PATCH v4 3/5] mmu_notifiers: Call invalidate_range() when invalidating TLBs

2023-07-25 Thread Alistair Popple
The invalidate_range() is going to become an architecture specific mmu
notifier used to keep the TLB of secondary MMUs such as an IOMMU in
sync with the CPU page tables. Currently it is called from separate
code paths to the main CPU TLB invalidations. This can lead to a
secondary TLB not getting invalidated when required and makes it hard
to reason about when exactly the secondary TLB is invalidated.

To fix this move the notifier call to the architecture specific TLB
maintenance functions for architectures that have secondary MMUs
requiring explicit software invalidations.

This fixes a SMMU bug on ARM64. On ARM64 PTE permission upgrades
require a TLB invalidation. This invalidation is done by the
architecture specific ptep_set_access_flags() which calls
flush_tlb_page() if required. However this doesn't call the notifier
resulting in infinite faults being generated by devices using the SMMU
if it has previously cached a read-only PTE in it's TLB.

Moving the invalidations into the TLB invalidation functions ensures
all invalidations happen at the same time as the CPU invalidation. The
architecture specific flush_tlb_all() routines do not call the
notifier as none of the IOMMUs require this.

Signed-off-by: Alistair Popple 
Suggested-by: Jason Gunthorpe 
Tested-by: SeongJae Park 
Acked-by: Catalin Marinas 
Reviewed-by: Jason Gunthorpe 
---
 arch/arm64/include/asm/tlbflush.h | 5 +
 arch/powerpc/include/asm/book3s/64/tlbflush.h | 1 +
 arch/powerpc/mm/book3s64/radix_hugetlbpage.c  | 1 +
 arch/powerpc/mm/book3s64/radix_tlb.c  | 4 
 arch/x86/include/asm/tlbflush.h   | 2 ++
 arch/x86/mm/tlb.c | 2 ++
 include/asm-generic/tlb.h | 1 -
 7 files changed, 15 insertions(+), 1 deletion(-)

diff --git a/arch/arm64/include/asm/tlbflush.h 
b/arch/arm64/include/asm/tlbflush.h
index 3456866..a99349d 100644
--- a/arch/arm64/include/asm/tlbflush.h
+++ b/arch/arm64/include/asm/tlbflush.h
@@ -13,6 +13,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 
@@ -252,6 +253,7 @@ static inline void flush_tlb_mm(struct mm_struct *mm)
__tlbi(aside1is, asid);
__tlbi_user(aside1is, asid);
dsb(ish);
+   mmu_notifier_invalidate_range(mm, 0, -1UL);
 }
 
 static inline void __flush_tlb_page_nosync(struct mm_struct *mm,
@@ -263,6 +265,8 @@ static inline void __flush_tlb_page_nosync(struct mm_struct 
*mm,
addr = __TLBI_VADDR(uaddr, ASID(mm));
__tlbi(vale1is, addr);
__tlbi_user(vale1is, addr);
+   mmu_notifier_invalidate_range(mm, uaddr & PAGE_MASK,
+   (uaddr & PAGE_MASK) + 
PAGE_SIZE);
 }
 
 static inline void flush_tlb_page_nosync(struct vm_area_struct *vma,
@@ -396,6 +400,7 @@ static inline void __flush_tlb_range(struct vm_area_struct 
*vma,
scale++;
}
dsb(ish);
+   mmu_notifier_invalidate_range(vma->vm_mm, start, end);
 }
 
 static inline void flush_tlb_range(struct vm_area_struct *vma,
diff --git a/arch/powerpc/include/asm/book3s/64/tlbflush.h 
b/arch/powerpc/include/asm/book3s/64/tlbflush.h
index 0d0c144..dca0477 100644
--- a/arch/powerpc/include/asm/book3s/64/tlbflush.h
+++ b/arch/powerpc/include/asm/book3s/64/tlbflush.h
@@ -5,6 +5,7 @@
 #define MMU_NO_CONTEXT ~0UL
 
 #include 
+#include 
 #include 
 #include 
 
diff --git a/arch/powerpc/mm/book3s64/radix_hugetlbpage.c 
b/arch/powerpc/mm/book3s64/radix_hugetlbpage.c
index 5e31955..f3fb49f 100644
--- a/arch/powerpc/mm/book3s64/radix_hugetlbpage.c
+++ b/arch/powerpc/mm/book3s64/radix_hugetlbpage.c
@@ -39,6 +39,7 @@ void radix__flush_hugetlb_tlb_range(struct vm_area_struct 
*vma, unsigned long st
radix__flush_tlb_pwc_range_psize(vma->vm_mm, start, end, psize);
else
radix__flush_tlb_range_psize(vma->vm_mm, start, end, psize);
+   mmu_notifier_invalidate_range(vma->vm_mm, start, end);
 }
 
 void radix__huge_ptep_modify_prot_commit(struct vm_area_struct *vma,
diff --git a/arch/powerpc/mm/book3s64/radix_tlb.c 
b/arch/powerpc/mm/book3s64/radix_tlb.c
index 0bd4866..4d44902 100644
--- a/arch/powerpc/mm/book3s64/radix_tlb.c
+++ b/arch/powerpc/mm/book3s64/radix_tlb.c
@@ -987,6 +987,7 @@ void radix__flush_tlb_mm(struct mm_struct *mm)
}
}
preempt_enable();
+   mmu_notifier_invalidate_range(mm, 0, -1UL);
 }
 EXPORT_SYMBOL(radix__flush_tlb_mm);
 
@@ -1020,6 +1021,7 @@ static void __flush_all_mm(struct mm_struct *mm, bool 
fullmm)
_tlbiel_pid_multicast(mm, pid, RIC_FLUSH_ALL);
}
preempt_enable();
+   mmu_notifier_invalidate_range(mm, 0, -1UL);
 }
 
 void radix__flush_all_mm(struct mm_struct *mm)
@@ -1228,6 +1230,7 @@ static inline void __radix__flush_tlb_range(struct 
mm_struct *mm,
}
 out:
preempt_enable();
+   mmu_notifier_invalidate_range(mm, start, end);
 }
 
 void radix__flush_tlb_range(struct vm_area_struct *vma, 

[PATCH v4 2/5] mmu_notifiers: Fixup comment in mmu_interval_read_begin()

2023-07-25 Thread Alistair Popple
The comment in mmu_interval_read_begin() refers to a function that
doesn't exist and uses the wrong call-back name. The op for mmu
interval notifiers is mmu_interval_notifier_ops->invalidate() so fix
the comment up to reflect that.

Signed-off-by: Alistair Popple 
Reviewed-by: Jason Gunthorpe 
---
 mm/mmu_notifier.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/mm/mmu_notifier.c b/mm/mmu_notifier.c
index 50c0dde..b7ad155 100644
--- a/mm/mmu_notifier.c
+++ b/mm/mmu_notifier.c
@@ -199,7 +199,7 @@ mmu_interval_read_begin(struct mmu_interval_notifier 
*interval_sub)
 * invalidate_start/end and is colliding.
 *
 * The locking looks broadly like this:
-*   mn_tree_invalidate_start():  mmu_interval_read_begin():
+*   mn_itree_inv_start(): mmu_interval_read_begin():
 * spin_lock
 *  seq = 
READ_ONCE(interval_sub->invalidate_seq);
 *  seq == subs->invalidate_seq
@@ -207,7 +207,7 @@ mmu_interval_read_begin(struct mmu_interval_notifier 
*interval_sub)
 *spin_lock
 * seq = ++subscriptions->invalidate_seq
 *spin_unlock
-* op->invalidate_range():
+* op->invalidate():
 *   user_lock
 *mmu_interval_set_seq()
 * interval_sub->invalidate_seq = seq
-- 
git-series 0.9.1


[PATCH v4 1/5] arm64/smmu: Use TLBI ASID when invalidating entire range

2023-07-25 Thread Alistair Popple
The ARM SMMU has a specific command for invalidating the TLB for an
entire ASID. Currently this is used for the IO_PGTABLE API but not for
ATS when called from the MMU notifier.

The current implementation of notifiers does not attempt to invalidate
such a large address range, instead walking each VMA and invalidating
each range individually during mmap removal. However in future SMMU
TLB invalidations are going to be sent as part of the normal
flush_tlb_*() kernel calls. To better deal with that add handling to
use TLBI ASID when invalidating the entire address space.

Signed-off-by: Alistair Popple 
Reviewed-by: Jason Gunthorpe 
---
 drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-sva.c | 16 +---
 1 file changed, 13 insertions(+), 3 deletions(-)

diff --git a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-sva.c 
b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-sva.c
index a5a63b1..2a19784 100644
--- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-sva.c
+++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-sva.c
@@ -200,10 +200,20 @@ static void arm_smmu_mm_invalidate_range(struct 
mmu_notifier *mn,
 * range. So do a simple translation here by calculating size correctly.
 */
size = end - start;
+   if (size == ULONG_MAX)
+   size = 0;
+
+   if (!(smmu_domain->smmu->features & ARM_SMMU_FEAT_BTM)) {
+   if (!size)
+   arm_smmu_tlb_inv_asid(smmu_domain->smmu,
+ smmu_mn->cd->asid);
+   else
+   arm_smmu_tlb_inv_range_asid(start, size,
+   smmu_mn->cd->asid,
+   PAGE_SIZE, false,
+   smmu_domain);
+   }
 
-   if (!(smmu_domain->smmu->features & ARM_SMMU_FEAT_BTM))
-   arm_smmu_tlb_inv_range_asid(start, size, smmu_mn->cd->asid,
-   PAGE_SIZE, false, smmu_domain);
arm_smmu_atc_inv_domain(smmu_domain, mm->pasid, start, size);
 }
 
-- 
git-series 0.9.1


[PATCH v4 0/5] Invalidate secondary IOMMU TLB on permission upgrade

2023-07-25 Thread Alistair Popple
The main change is to move secondary TLB invalidation mmu notifier
callbacks into the architecture specific TLB flushing functions. This
makes secondary TLB invalidation mostly match CPU invalidation while
still allowing efficient range based invalidations based on the
existing TLB batching code.

Changes for v4:

 - Fixed a NULL pointer dereference when registering the first
   notifier with mmu_interval_notifier_insert() instead of
   mmu_notifier_register() - Thanks Dan and Chaitanya for the bug
   reports.

 - Collected Acked/Reviewed tags.

 - Don't call the notifier from radix__local_flush_tlb_page() on
   PowerPC.

Changes for v3:

 - On x86 call the invalidation when adding pending TLB invalidates
   rather than when flushing the batch. This is because the mm is
   required. It also matches what happens on ARM64. Fixes a bug
   reported by SeongJae Park (thanks!)

Changes for v2:

 - Rebased on linux-next commit 906fa30154ef ("mm/rmap: correct stale
   comment of rmap_walk_anon and rmap_walk_file") to fix a minor
   integration conflict with "arm64: support batched/deferred tlb
   shootdown during page reclamation/migration". This series will need
   to be applied after the conflicting patch.

 - Reordered the function rename until the end of the series as many
   places that were getting renamed ended up being removed anyway.

 - Fixed a couple of build issues which broke bisection.

 - Added a minor patch to fix up a stale/incorrect comment.

==
Background
==

The arm64 architecture specifies TLB permission bits may be cached and
therefore the TLB must be invalidated during permission upgrades. For
the CPU this currently occurs in the architecture specific
ptep_set_access_flags() routine.

Secondary TLBs such as implemented by the SMMU IOMMU match the CPU
architecture specification and may also cache permission bits and
require the same TLB invalidations. This may be achieved in one of two
ways.

Some SMMU implementations implement broadcast TLB maintenance
(BTM). This snoops CPU TLB invalidates and will invalidate any
secondary TLB at the same time as the CPU. However implementations are
not required to implement BTM.

Implementations without BTM rely on mmu notifier callbacks to send
explicit TLB invalidation commands to invalidate SMMU TLB. Therefore
either generic kernel code or architecture specific code needs to call
the mmu notifier on permission upgrade.

Currently that doesn't happen so devices will fault indefinitely when
writing to a PTE that was previously read-only as nothing invalidates
the SMMU TLB.


Solution


To fix this the series first renames the .invalidate_range() callback
to .arch_invalidate_secondary_tlbs() as suggested by Jason and Sean to
make it clear this callback is only used for secondary TLBs. That was
made possible thanks to Sean's series [1] to remove KVM's incorrect
usage.

Based on feedback from Jason [2] the proposed solution to the bug is
to move the calls to mmu_notifier_arch_invalidate_secondary_tlbs()
closer to the architecture specific TLB invalidation code. This
ensures the secondary TLB won't miss invalidations, including the
existing invalidation in the ARM64 code to deal with permission
upgrade.

Currently only ARM64, PowerPC and x86 have IOMMU with secondary TLBs
requiring SW invalidation so the notifier is only called for those
architectures. It is also not called for invalidation of kernel
mappings as no secondary IOMMU implementations can access those and
hence it is not required.

[1] - https://lore.kernel.org/all/20230602011518.787006-1-sea...@google.com/
[2] - https://lore.kernel.org/linux-mm/zjmr5bw8l+bbz...@ziepe.ca/

Alistair Popple (5):
  arm64/smmu: Use TLBI ASID when invalidating entire range
  mmu_notifiers: Fixup comment in mmu_interval_read_begin()
  mmu_notifiers: Call invalidate_range() when invalidating TLBs
  mmu_notifiers: Don't invalidate secondary TLBs as part of 
mmu_notifier_invalidate_range_end()
  mmu_notifiers: Rename invalidate_range notifier

 arch/arm64/include/asm/tlbflush.h   |   5 +-
 arch/powerpc/include/asm/book3s/64/tlbflush.h   |   1 +-
 arch/powerpc/mm/book3s64/radix_hugetlbpage.c|   1 +-
 arch/powerpc/mm/book3s64/radix_tlb.c|   4 +-
 arch/x86/include/asm/tlbflush.h |   2 +-
 arch/x86/mm/tlb.c   |   2 +-
 drivers/iommu/amd/iommu_v2.c|  10 +-
 drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-sva.c |  29 +++--
 drivers/iommu/intel/svm.c   |   8 +-
 drivers/misc/ocxl/link.c|   8 +-
 include/asm-generic/tlb.h   |   1 +-
 include/linux/mmu_notifier.h| 104 -
 kernel/events/uprobes.c |   2 +-
 mm/huge_memory.c|  29 +
 mm/hugetlb.c|   8 +-
 mm/memory.c |   8 +-
 

[PATCH] powerpc/kexec: fix minor typo

2023-07-25 Thread Laurent Dufour
Function name in the descriptor was not correct.

Reported-by: kernel test robot 
Closes: 
https://lore.kernel.org/oe-kbuild-all/202307251721.bugcsceq-...@intel.com/
Signed-off-by: Laurent Dufour 
---
 arch/powerpc/kexec/file_load_64.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/arch/powerpc/kexec/file_load_64.c 
b/arch/powerpc/kexec/file_load_64.c
index 110d28bede2a..73e492d18804 100644
--- a/arch/powerpc/kexec/file_load_64.c
+++ b/arch/powerpc/kexec/file_load_64.c
@@ -933,9 +933,9 @@ int setup_purgatory_ppc64(struct kimage *image, const void 
*slave_code,
 }
 
 /**
- * get_cpu_node_size - Compute the size of a CPU node in the FDT.
- * This should be done only once and the value is stored in
- * a static variable.
+ * cpu_node_size - Compute the size of a CPU node in the FDT.
+ * This should be done only once and the value is stored in
+ * a static variable.
  * Returns the max size of a CPU node in the FDT.
  */
 static unsigned int cpu_node_size(void)
-- 
2.41.0



Re: [RFC PATCH v11 10/29] mm: Add AS_UNMOVABLE to mark mapping as completely unmovable

2023-07-25 Thread Matthew Wilcox
On Tue, Jul 25, 2023 at 01:24:03PM +0300, Kirill A . Shutemov wrote:
> On Tue, Jul 18, 2023 at 04:44:53PM -0700, Sean Christopherson wrote:
> > diff --git a/mm/compaction.c b/mm/compaction.c
> > index dbc9f86b1934..a3d2b132df52 100644
> > --- a/mm/compaction.c
> > +++ b/mm/compaction.c
> > @@ -1047,6 +1047,10 @@ isolate_migratepages_block(struct compact_control 
> > *cc, unsigned long low_pfn,
> > if (!mapping && (folio_ref_count(folio) - 1) > 
> > folio_mapcount(folio))
> > goto isolate_fail_put;
> >  
> > +   /* The mapping truly isn't movable. */
> > +   if (mapping && mapping_unmovable(mapping))
> > +   goto isolate_fail_put;
> > +
> 
> I doubt that it is safe to dereference mapping here. I believe the folio
> can be truncated from under us and the mapping freed with the inode.
> 
> The folio has to be locked to dereference mapping safely (given that the
> mapping is still tied to the folio).

There's even a comment to that effect later on in the function:

/*
 * Only pages without mappings or that have a
 * ->migrate_folio callback are possible to migrate
 * without blocking. However, we can be racing with
 * truncation so it's necessary to lock the page
 * to stabilise the mapping as truncation holds
 * the page lock until after the page is removed
 * from the page cache.
 */

(that could be reworded to make it clear how dangerous dereferencing
->mapping is without the lock ... and it does need to be changed to say
"folio lock" instead of "page lock", so ...)

How does this look?

/*
 * Only folios without mappings or that have
 * a ->migrate_folio callback are possible to
 * migrate without blocking. However, we can
 * be racing with truncation, which can free
 * the mapping.  Truncation holds the folio lock
 * until after the folio is removed from the page
 * cache so holding it ourselves is sufficient.
 */



Re: [PATCH v3 0/5] Add a new fchmodat4() syscall

2023-07-25 Thread Christian Brauner
On Tue, Jul 25, 2023 at 01:05:40PM +0200, Alexey Gladkov wrote:
> On Tue, Jul 11, 2023 at 05:14:24PM +0200, Christian Brauner wrote:
> > On Tue, Jul 11, 2023 at 02:24:51PM +0200, Florian Weimer wrote:
> > > * Alexey Gladkov:
> > > 
> > > > This patch set adds fchmodat4(), a new syscall. The actual
> > > > implementation is super simple: essentially it's just the same as
> > > > fchmodat(), but LOOKUP_FOLLOW is conditionally set based on the flags.
> > > > I've attempted to make this match "man 2 fchmodat" as closely as
> > > > possible, which says EINVAL is returned for invalid flags (as opposed to
> > > > ENOTSUPP, which is currently returned by glibc for AT_SYMLINK_NOFOLLOW).
> > > > I have a sketch of a glibc patch that I haven't even compiled yet, but
> > > > seems fairly straight-forward:
> > > >
> > > > diff --git a/sysdeps/unix/sysv/linux/fchmodat.c 
> > > > b/sysdeps/unix/sysv/linux/fchmodat.c
> > > > index 6d9cbc1ce9e0..b1beab76d56c 100644
> > > > --- a/sysdeps/unix/sysv/linux/fchmodat.c
> > > > +++ b/sysdeps/unix/sysv/linux/fchmodat.c
> > > > @@ -29,12 +29,36 @@
> > > >  int
> > > >  fchmodat (int fd, const char *file, mode_t mode, int flag)
> > > >  {
> > > > -  if (flag & ~AT_SYMLINK_NOFOLLOW)
> > > > -return INLINE_SYSCALL_ERROR_RETURN_VALUE (EINVAL);
> > > > -#ifndef __NR_lchmod/* Linux so far has no lchmod 
> > > > syscall.  */
> > > > +  /* There are four paths through this code:
> > > > +  - The flags are zero.  In this case it's fine to call 
> > > > fchmodat.
> > > > +  - The flags are non-zero and glibc doesn't have access to
> > > > +   __NR_fchmodat4.  In this case all we can do is emulate the 
> > > > error codes
> > > > +   defined by the glibc interface from userspace.
> > > > +  - The flags are non-zero, glibc has __NR_fchmodat4, and the 
> > > > kernel has
> > > > +   fchmodat4.  This is the simplest case, as the fchmodat4 syscall 
> > > > exactly
> > > > +   matches glibc's library interface so it can be called directly.
> > > > +  - The flags are non-zero, glibc has __NR_fchmodat4, but the 
> > > > kernel does
> > > 
> > > If you define __NR_fchmodat4 on all architectures, we can use these
> > > constants directly in glibc.  We no longer depend on the UAPI
> > > definitions of those constants, to cut down the number of code variants,
> > > and to make glibc's system call profile independent of the kernel header
> > > version at build time.
> > > 
> > > Your version is based on 2.31, more recent versions have some reasonable
> > > emulation for fchmodat based on /proc/self/fd.  I even wrote a comment
> > > describing the same buggy behavior that you witnessed:
> > > 
> > > +  /* Some Linux versions with some file systems can actually
> > > +change symbolic link permissions via /proc, but this is not
> > > +intentional, and it gives inconsistent results (e.g., error
> > > +return despite mode change).  The expected behavior is that
> > > +symbolic link modes cannot be changed at all, and this check
> > > +enforces that.  */
> > > +  if (S_ISLNK (st.st_mode))
> > > +   {
> > > + __close_nocancel (pathfd);
> > > + __set_errno (EOPNOTSUPP);
> > > + return -1;
> > > +   }
> > > 
> > > I think there was some kernel discussion about that behavior before, but
> > > apparently, it hasn't led to fixes.
> > 
> > I think I've explained this somewhere else a couple of months ago but
> > just in case you weren't on that thread or don't remember and apologies
> > if you should already know.
> > 
> > A lot of filesystem will happily update the mode of a symlink. The VFS
> > doesn't do anything to prevent this from happening. This is filesystem
> > specific.
> > 
> > The EOPNOTSUPP you're seeing very likely comes from POSIX ACLs.
> > Specifically it comes from filesystems that call posix_acl_chmod(),
> > e.g., btrfs via
> > 
> > if (!err && attr->ia_valid & ATTR_MODE)
> > err = posix_acl_chmod(idmap, dentry, inode->i_mode);
> > 
> > Most filesystems don't implement i_op->set_acl() for POSIX ACLs.
> > So posix_acl_chmod() will report EOPNOTSUPP. By the time
> > posix_acl_chmod() is called, most filesystems will have finished
> > updating the inode. POSIX ACLs also often aren't integrated into
> > transactions so a rollback wouldn't even be possible on some
> > filesystems.
> > 
> > Any filesystem that doesn't implement POSIX ACLs at all will obviously
> > never fail unless it blocks mode changes on symlinks. Or filesystems
> > that do have a way to rollback failures from posix_acl_chmod(), or
> > filesystems that do return an error on chmod() on symlinks such as 9p,
> > ntfs, ocfs2.
> > 
> > > 
> > > I wonder if it makes sense to add a similar error return to the system
> > > call implementation?
> > 
> > Hm, blocking symlink mode changes is pretty regression prone. And just
> > 

Re: [PATCH v3 0/5] Add a new fchmodat4() syscall

2023-07-25 Thread Alexey Gladkov
On Tue, Jul 11, 2023 at 05:14:24PM +0200, Christian Brauner wrote:
> On Tue, Jul 11, 2023 at 02:24:51PM +0200, Florian Weimer wrote:
> > * Alexey Gladkov:
> > 
> > > This patch set adds fchmodat4(), a new syscall. The actual
> > > implementation is super simple: essentially it's just the same as
> > > fchmodat(), but LOOKUP_FOLLOW is conditionally set based on the flags.
> > > I've attempted to make this match "man 2 fchmodat" as closely as
> > > possible, which says EINVAL is returned for invalid flags (as opposed to
> > > ENOTSUPP, which is currently returned by glibc for AT_SYMLINK_NOFOLLOW).
> > > I have a sketch of a glibc patch that I haven't even compiled yet, but
> > > seems fairly straight-forward:
> > >
> > > diff --git a/sysdeps/unix/sysv/linux/fchmodat.c 
> > > b/sysdeps/unix/sysv/linux/fchmodat.c
> > > index 6d9cbc1ce9e0..b1beab76d56c 100644
> > > --- a/sysdeps/unix/sysv/linux/fchmodat.c
> > > +++ b/sysdeps/unix/sysv/linux/fchmodat.c
> > > @@ -29,12 +29,36 @@
> > >  int
> > >  fchmodat (int fd, const char *file, mode_t mode, int flag)
> > >  {
> > > -  if (flag & ~AT_SYMLINK_NOFOLLOW)
> > > -return INLINE_SYSCALL_ERROR_RETURN_VALUE (EINVAL);
> > > -#ifndef __NR_lchmod  /* Linux so far has no lchmod syscall.  
> > > */
> > > +  /* There are four paths through this code:
> > > +  - The flags are zero.  In this case it's fine to call fchmodat.
> > > +  - The flags are non-zero and glibc doesn't have access to
> > > + __NR_fchmodat4.  In this case all we can do is emulate the 
> > > error codes
> > > + defined by the glibc interface from userspace.
> > > +  - The flags are non-zero, glibc has __NR_fchmodat4, and the 
> > > kernel has
> > > + fchmodat4.  This is the simplest case, as the fchmodat4 syscall 
> > > exactly
> > > + matches glibc's library interface so it can be called directly.
> > > +  - The flags are non-zero, glibc has __NR_fchmodat4, but the 
> > > kernel does
> > 
> > If you define __NR_fchmodat4 on all architectures, we can use these
> > constants directly in glibc.  We no longer depend on the UAPI
> > definitions of those constants, to cut down the number of code variants,
> > and to make glibc's system call profile independent of the kernel header
> > version at build time.
> > 
> > Your version is based on 2.31, more recent versions have some reasonable
> > emulation for fchmodat based on /proc/self/fd.  I even wrote a comment
> > describing the same buggy behavior that you witnessed:
> > 
> > +  /* Some Linux versions with some file systems can actually
> > +change symbolic link permissions via /proc, but this is not
> > +intentional, and it gives inconsistent results (e.g., error
> > +return despite mode change).  The expected behavior is that
> > +symbolic link modes cannot be changed at all, and this check
> > +enforces that.  */
> > +  if (S_ISLNK (st.st_mode))
> > +   {
> > + __close_nocancel (pathfd);
> > + __set_errno (EOPNOTSUPP);
> > + return -1;
> > +   }
> > 
> > I think there was some kernel discussion about that behavior before, but
> > apparently, it hasn't led to fixes.
> 
> I think I've explained this somewhere else a couple of months ago but
> just in case you weren't on that thread or don't remember and apologies
> if you should already know.
> 
> A lot of filesystem will happily update the mode of a symlink. The VFS
> doesn't do anything to prevent this from happening. This is filesystem
> specific.
> 
> The EOPNOTSUPP you're seeing very likely comes from POSIX ACLs.
> Specifically it comes from filesystems that call posix_acl_chmod(),
> e.g., btrfs via
> 
> if (!err && attr->ia_valid & ATTR_MODE)
> err = posix_acl_chmod(idmap, dentry, inode->i_mode);
> 
> Most filesystems don't implement i_op->set_acl() for POSIX ACLs.
> So posix_acl_chmod() will report EOPNOTSUPP. By the time
> posix_acl_chmod() is called, most filesystems will have finished
> updating the inode. POSIX ACLs also often aren't integrated into
> transactions so a rollback wouldn't even be possible on some
> filesystems.
> 
> Any filesystem that doesn't implement POSIX ACLs at all will obviously
> never fail unless it blocks mode changes on symlinks. Or filesystems
> that do have a way to rollback failures from posix_acl_chmod(), or
> filesystems that do return an error on chmod() on symlinks such as 9p,
> ntfs, ocfs2.
> 
> > 
> > I wonder if it makes sense to add a similar error return to the system
> > call implementation?
> 
> Hm, blocking symlink mode changes is pretty regression prone. And just
> blocking it through one interface seems weird and makes things even more
> inconsistent.
> 
> So two options I see:
> (1) minimally invasive:
> Filesystems that do call posix_acl_chmod() on symlinks need to be
> changed to stop doing that.
> (2) might hit us on 

Re: [PATCH v2] syscalls: Cleanup references to sys_lookup_dcookie()

2023-07-25 Thread Geert Uytterhoeven
On Mon, Jul 10, 2023 at 8:52 PM Sohil Mehta  wrote:
> commit 'be65de6b03aa ("fs: Remove dcookies support")' removed the
> syscall definition for lookup_dcookie.  However, syscall tables still
> point to the old sys_lookup_dcookie() definition. Update syscall tables
> of all architectures to directly point to sys_ni_syscall() instead.
>
> Signed-off-by: Sohil Mehta 
> Reviewed-by: Randy Dunlap 
> Acked-by: Namhyung Kim  # for perf
> ---
> v2:
> - Rebased to v6.5-rc1. No other dependencies.
> - Added acquired tags.

>  arch/m68k/kernel/syscalls/syscall.tbl   | 2 +-

Acked-by: Geert Uytterhoeven 

Gr{oetje,eeting}s,

Geert

-- 
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- ge...@linux-m68k.org

In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
-- Linus Torvalds


[PATCH] docs: move powerpc under arch

2023-07-25 Thread Costa Shulyupin
and fix all in-tree references.

Architecture-specific documentation is being moved into Documentation/arch/
as a way of cleaning up the top-level documentation directory and making
the docs hierarchy more closely match the source hierarchy.

Signed-off-by: Costa Shulyupin 
---
 Documentation/ABI/testing/sysfs-bus-papr-pmem | 2 +-
 Documentation/PCI/pci-error-recovery.rst  | 4 ++--
 Documentation/arch/index.rst  | 2 +-
 Documentation/{ => arch}/powerpc/associativity.rst| 0
 Documentation/{ => arch}/powerpc/booting.rst  | 0
 Documentation/{ => arch}/powerpc/bootwrapper.rst  | 0
 Documentation/{ => arch}/powerpc/cpu_families.rst | 0
 Documentation/{ => arch}/powerpc/cpu_features.rst | 0
 Documentation/{ => arch}/powerpc/cxl.rst  | 0
 Documentation/{ => arch}/powerpc/cxlflash.rst | 2 +-
 Documentation/{ => arch}/powerpc/dawr-power9.rst  | 0
 Documentation/{ => arch}/powerpc/dexcr.rst| 0
 Documentation/{ => arch}/powerpc/dscr.rst | 0
 .../{ => arch}/powerpc/eeh-pci-error-recovery.rst | 0
 Documentation/{ => arch}/powerpc/elf_hwcaps.rst   | 6 +++---
 Documentation/{ => arch}/powerpc/elfnote.rst  | 0
 Documentation/{ => arch}/powerpc/features.rst | 0
 .../{ => arch}/powerpc/firmware-assisted-dump.rst | 0
 Documentation/{ => arch}/powerpc/hvcs.rst | 0
 Documentation/{ => arch}/powerpc/imc.rst  | 0
 Documentation/{ => arch}/powerpc/index.rst| 0
 Documentation/{ => arch}/powerpc/isa-versions.rst | 0
 Documentation/{ => arch}/powerpc/kasan.txt| 0
 Documentation/{ => arch}/powerpc/kaslr-booke32.rst| 0
 Documentation/{ => arch}/powerpc/mpc52xx.rst  | 0
 Documentation/{ => arch}/powerpc/papr_hcalls.rst  | 0
 .../{ => arch}/powerpc/pci_iov_resource_on_powernv.rst| 0
 Documentation/{ => arch}/powerpc/pmu-ebb.rst  | 0
 Documentation/{ => arch}/powerpc/ptrace.rst   | 0
 Documentation/{ => arch}/powerpc/qe_firmware.rst  | 0
 Documentation/{ => arch}/powerpc/syscall64-abi.rst| 0
 Documentation/{ => arch}/powerpc/transactional_memory.rst | 0
 Documentation/{ => arch}/powerpc/ultravisor.rst   | 0
 Documentation/{ => arch}/powerpc/vas-api.rst  | 0
 Documentation/{ => arch}/powerpc/vcpudispatch_stats.rst   | 0
 MAINTAINERS   | 8 
 arch/powerpc/kernel/exceptions-64s.S  | 6 +++---
 arch/powerpc/kernel/paca.c| 2 +-
 arch/powerpc/kvm/book3s_64_entry.S| 2 +-
 drivers/soc/fsl/qe/qe.c   | 2 +-
 drivers/tty/hvc/hvcs.c| 2 +-
 include/soc/fsl/qe/qe.h   | 2 +-
 42 files changed, 20 insertions(+), 20 deletions(-)
 rename Documentation/{ => arch}/powerpc/associativity.rst (100%)
 rename Documentation/{ => arch}/powerpc/booting.rst (100%)
 rename Documentation/{ => arch}/powerpc/bootwrapper.rst (100%)
 rename Documentation/{ => arch}/powerpc/cpu_families.rst (100%)
 rename Documentation/{ => arch}/powerpc/cpu_features.rst (100%)
 rename Documentation/{ => arch}/powerpc/cxl.rst (100%)
 rename Documentation/{ => arch}/powerpc/cxlflash.rst (99%)
 rename Documentation/{ => arch}/powerpc/dawr-power9.rst (100%)
 rename Documentation/{ => arch}/powerpc/dexcr.rst (100%)
 rename Documentation/{ => arch}/powerpc/dscr.rst (100%)
 rename Documentation/{ => arch}/powerpc/eeh-pci-error-recovery.rst (100%)
 rename Documentation/{ => arch}/powerpc/elf_hwcaps.rst (97%)
 rename Documentation/{ => arch}/powerpc/elfnote.rst (100%)
 rename Documentation/{ => arch}/powerpc/features.rst (100%)
 rename Documentation/{ => arch}/powerpc/firmware-assisted-dump.rst (100%)
 rename Documentation/{ => arch}/powerpc/hvcs.rst (100%)
 rename Documentation/{ => arch}/powerpc/imc.rst (100%)
 rename Documentation/{ => arch}/powerpc/index.rst (100%)
 rename Documentation/{ => arch}/powerpc/isa-versions.rst (100%)
 rename Documentation/{ => arch}/powerpc/kasan.txt (100%)
 rename Documentation/{ => arch}/powerpc/kaslr-booke32.rst (100%)
 rename Documentation/{ => arch}/powerpc/mpc52xx.rst (100%)
 rename Documentation/{ => arch}/powerpc/papr_hcalls.rst (100%)
 rename Documentation/{ => arch}/powerpc/pci_iov_resource_on_powernv.rst (100%)
 rename Documentation/{ => arch}/powerpc/pmu-ebb.rst (100%)
 rename Documentation/{ => arch}/powerpc/ptrace.rst (100%)
 rename Documentation/{ => arch}/powerpc/qe_firmware.rst (100%)
 rename Documentation/{ => arch}/powerpc/syscall64-abi.rst (100%)
 rename Documentation/{ => arch}/powerpc/transactional_memory.rst (100%)
 rename Documentation/{ => arch}/powerpc/ultravisor.rst (100%)
 rename Documentation/{ => arch}/powerpc/vas-api.rst (100%)
 rename 

[PATCH 5.4 110/313] crypto: nx - fix build warnings when DEBUG_FS is not enabled

2023-07-25 Thread Greg Kroah-Hartman
From: Randy Dunlap 

[ Upstream commit b04b076fb56560b39d695ac3744db457e12278fd ]

Fix build warnings when DEBUG_FS is not enabled by using an empty
do-while loop instead of a value:

In file included from ../drivers/crypto/nx/nx.c:27:
../drivers/crypto/nx/nx.c: In function 'nx_register_algs':
../drivers/crypto/nx/nx.h:173:33: warning: statement with no effect 
[-Wunused-value]
  173 | #define NX_DEBUGFS_INIT(drv)(0)
../drivers/crypto/nx/nx.c:573:9: note: in expansion of macro 'NX_DEBUGFS_INIT'
  573 | NX_DEBUGFS_INIT(_driver);
../drivers/crypto/nx/nx.c: In function 'nx_remove':
../drivers/crypto/nx/nx.h:174:33: warning: statement with no effect 
[-Wunused-value]
  174 | #define NX_DEBUGFS_FINI(drv)(0)
../drivers/crypto/nx/nx.c:793:17: note: in expansion of macro 'NX_DEBUGFS_FINI'
  793 | NX_DEBUGFS_FINI(_driver);

Also, there is no need to build nx_debugfs.o when DEBUG_FS is not
enabled, so change the Makefile to accommodate that.

Fixes: ae0222b7289d ("powerpc/crypto: nx driver code supporting nx encryption")
Fixes: aef7b31c8833 ("powerpc/crypto: Build files for the nx device driver")
Signed-off-by: Randy Dunlap 
Cc: Breno Leitão 
Cc: Nayna Jain 
Cc: Paulo Flabiano Smorigo 
Cc: Herbert Xu 
Cc: "David S. Miller" 
Cc: linux-cry...@vger.kernel.org
Cc: Michael Ellerman 
Cc: Nicholas Piggin 
Cc: Christophe Leroy 
Cc: linuxppc-dev@lists.ozlabs.org
Signed-off-by: Herbert Xu 
Signed-off-by: Sasha Levin 
---
 drivers/crypto/nx/Makefile | 2 +-
 drivers/crypto/nx/nx.h | 4 ++--
 2 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/drivers/crypto/nx/Makefile b/drivers/crypto/nx/Makefile
index 015155da59c29..76139865d7fa1 100644
--- a/drivers/crypto/nx/Makefile
+++ b/drivers/crypto/nx/Makefile
@@ -1,7 +1,6 @@
 # SPDX-License-Identifier: GPL-2.0
 obj-$(CONFIG_CRYPTO_DEV_NX_ENCRYPT) += nx-crypto.o
 nx-crypto-objs := nx.o \
- nx_debugfs.o \
  nx-aes-cbc.o \
  nx-aes-ecb.o \
  nx-aes-gcm.o \
@@ -11,6 +10,7 @@ nx-crypto-objs := nx.o \
  nx-sha256.o \
  nx-sha512.o
 
+nx-crypto-$(CONFIG_DEBUG_FS) += nx_debugfs.o
 obj-$(CONFIG_CRYPTO_DEV_NX_COMPRESS_PSERIES) += nx-compress-pseries.o 
nx-compress.o
 obj-$(CONFIG_CRYPTO_DEV_NX_COMPRESS_POWERNV) += nx-compress-powernv.o 
nx-compress.o
 nx-compress-objs := nx-842.o
diff --git a/drivers/crypto/nx/nx.h b/drivers/crypto/nx/nx.h
index 7ecca168f8c48..5c77aba450cf8 100644
--- a/drivers/crypto/nx/nx.h
+++ b/drivers/crypto/nx/nx.h
@@ -169,8 +169,8 @@ struct nx_sg *nx_walk_and_build(struct nx_sg *, unsigned 
int,
 void nx_debugfs_init(struct nx_crypto_driver *);
 void nx_debugfs_fini(struct nx_crypto_driver *);
 #else
-#define NX_DEBUGFS_INIT(drv)   (0)
-#define NX_DEBUGFS_FINI(drv)   (0)
+#define NX_DEBUGFS_INIT(drv)   do {} while (0)
+#define NX_DEBUGFS_FINI(drv)   do {} while (0)
 #endif
 
 #define NX_PAGE_NUM(x) ((u64)(x) & 0xf000ULL)
-- 
2.39.2





[PATCH 5.4 084/313] soc/fsl/qe: fix usb.c build errors

2023-07-25 Thread Greg Kroah-Hartman
From: Randy Dunlap 

[ Upstream commit 7b1a78babd0d2cd27aa07255dee0c2d7ac0f31e3 ]

Fix build errors in soc/fsl/qe/usb.c when QUICC_ENGINE is not set.
This happens when PPC_EP88XC is set, which selects CPM1 & CPM.
When CPM is set, USB_FSL_QE can be set without QUICC_ENGINE
being set. When USB_FSL_QE is set, QE_USB deafults to y, which
causes build errors when QUICC_ENGINE is not set. Making
QE_USB depend on QUICC_ENGINE prevents QE_USB from defaulting to y.

Fixes these build errors:

drivers/soc/fsl/qe/usb.o: in function `qe_usb_clock_set':
usb.c:(.text+0x1e): undefined reference to `qe_immr'
powerpc-linux-ld: usb.c:(.text+0x2a): undefined reference to `qe_immr'
powerpc-linux-ld: usb.c:(.text+0xbc): undefined reference to `qe_setbrg'
powerpc-linux-ld: usb.c:(.text+0xca): undefined reference to `cmxgcr_lock'
powerpc-linux-ld: usb.c:(.text+0xce): undefined reference to `cmxgcr_lock'

Fixes: 5e41486c408e ("powerpc/QE: add support for QE USB clocks routing")
Signed-off-by: Randy Dunlap 
Reported-by: kernel test robot 
Link: https://lore.kernel.org/all/202301101500.pillnv6r-...@intel.com/
Suggested-by: Michael Ellerman 
Cc: Christophe Leroy 
Cc: Leo Li 
Cc: Masahiro Yamada 
Cc: Nicolas Schier 
Cc: Qiang Zhao 
Cc: linuxppc-dev 
Cc: linux-arm-ker...@lists.infradead.org
Cc: Kumar Gala 
Acked-by: Nicolas Schier 
Signed-off-by: Li Yang 
Signed-off-by: Sasha Levin 
---
 drivers/soc/fsl/qe/Kconfig | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/soc/fsl/qe/Kconfig b/drivers/soc/fsl/qe/Kconfig
index cfa4b2939992c..3ed0838607647 100644
--- a/drivers/soc/fsl/qe/Kconfig
+++ b/drivers/soc/fsl/qe/Kconfig
@@ -38,6 +38,7 @@ config QE_TDM
 
 config QE_USB
bool
+   depends on QUICC_ENGINE
default y if USB_FSL_QE
help
  QE USB Controller support
-- 
2.39.2





[PATCH 5.10 201/509] crypto: nx - fix build warnings when DEBUG_FS is not enabled

2023-07-25 Thread Greg Kroah-Hartman
From: Randy Dunlap 

[ Upstream commit b04b076fb56560b39d695ac3744db457e12278fd ]

Fix build warnings when DEBUG_FS is not enabled by using an empty
do-while loop instead of a value:

In file included from ../drivers/crypto/nx/nx.c:27:
../drivers/crypto/nx/nx.c: In function 'nx_register_algs':
../drivers/crypto/nx/nx.h:173:33: warning: statement with no effect 
[-Wunused-value]
  173 | #define NX_DEBUGFS_INIT(drv)(0)
../drivers/crypto/nx/nx.c:573:9: note: in expansion of macro 'NX_DEBUGFS_INIT'
  573 | NX_DEBUGFS_INIT(_driver);
../drivers/crypto/nx/nx.c: In function 'nx_remove':
../drivers/crypto/nx/nx.h:174:33: warning: statement with no effect 
[-Wunused-value]
  174 | #define NX_DEBUGFS_FINI(drv)(0)
../drivers/crypto/nx/nx.c:793:17: note: in expansion of macro 'NX_DEBUGFS_FINI'
  793 | NX_DEBUGFS_FINI(_driver);

Also, there is no need to build nx_debugfs.o when DEBUG_FS is not
enabled, so change the Makefile to accommodate that.

Fixes: ae0222b7289d ("powerpc/crypto: nx driver code supporting nx encryption")
Fixes: aef7b31c8833 ("powerpc/crypto: Build files for the nx device driver")
Signed-off-by: Randy Dunlap 
Cc: Breno Leitão 
Cc: Nayna Jain 
Cc: Paulo Flabiano Smorigo 
Cc: Herbert Xu 
Cc: "David S. Miller" 
Cc: linux-cry...@vger.kernel.org
Cc: Michael Ellerman 
Cc: Nicholas Piggin 
Cc: Christophe Leroy 
Cc: linuxppc-dev@lists.ozlabs.org
Signed-off-by: Herbert Xu 
Signed-off-by: Sasha Levin 
---
 drivers/crypto/nx/Makefile | 2 +-
 drivers/crypto/nx/nx.h | 4 ++--
 2 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/drivers/crypto/nx/Makefile b/drivers/crypto/nx/Makefile
index bc89a20e5d9d8..351822a598f97 100644
--- a/drivers/crypto/nx/Makefile
+++ b/drivers/crypto/nx/Makefile
@@ -1,7 +1,6 @@
 # SPDX-License-Identifier: GPL-2.0
 obj-$(CONFIG_CRYPTO_DEV_NX_ENCRYPT) += nx-crypto.o
 nx-crypto-objs := nx.o \
- nx_debugfs.o \
  nx-aes-cbc.o \
  nx-aes-ecb.o \
  nx-aes-gcm.o \
@@ -11,6 +10,7 @@ nx-crypto-objs := nx.o \
  nx-sha256.o \
  nx-sha512.o
 
+nx-crypto-$(CONFIG_DEBUG_FS) += nx_debugfs.o
 obj-$(CONFIG_CRYPTO_DEV_NX_COMPRESS_PSERIES) += nx-compress-pseries.o 
nx-compress.o
 obj-$(CONFIG_CRYPTO_DEV_NX_COMPRESS_POWERNV) += nx-compress-powernv.o 
nx-compress.o
 nx-compress-objs := nx-842.o
diff --git a/drivers/crypto/nx/nx.h b/drivers/crypto/nx/nx.h
index c6233173c612e..2697baebb6a35 100644
--- a/drivers/crypto/nx/nx.h
+++ b/drivers/crypto/nx/nx.h
@@ -170,8 +170,8 @@ struct nx_sg *nx_walk_and_build(struct nx_sg *, unsigned 
int,
 void nx_debugfs_init(struct nx_crypto_driver *);
 void nx_debugfs_fini(struct nx_crypto_driver *);
 #else
-#define NX_DEBUGFS_INIT(drv)   (0)
-#define NX_DEBUGFS_FINI(drv)   (0)
+#define NX_DEBUGFS_INIT(drv)   do {} while (0)
+#define NX_DEBUGFS_FINI(drv)   do {} while (0)
 #endif
 
 #define NX_PAGE_NUM(x) ((u64)(x) & 0xf000ULL)
-- 
2.39.2





[PATCH 5.10 132/509] soc/fsl/qe: fix usb.c build errors

2023-07-25 Thread Greg Kroah-Hartman
From: Randy Dunlap 

[ Upstream commit 7b1a78babd0d2cd27aa07255dee0c2d7ac0f31e3 ]

Fix build errors in soc/fsl/qe/usb.c when QUICC_ENGINE is not set.
This happens when PPC_EP88XC is set, which selects CPM1 & CPM.
When CPM is set, USB_FSL_QE can be set without QUICC_ENGINE
being set. When USB_FSL_QE is set, QE_USB deafults to y, which
causes build errors when QUICC_ENGINE is not set. Making
QE_USB depend on QUICC_ENGINE prevents QE_USB from defaulting to y.

Fixes these build errors:

drivers/soc/fsl/qe/usb.o: in function `qe_usb_clock_set':
usb.c:(.text+0x1e): undefined reference to `qe_immr'
powerpc-linux-ld: usb.c:(.text+0x2a): undefined reference to `qe_immr'
powerpc-linux-ld: usb.c:(.text+0xbc): undefined reference to `qe_setbrg'
powerpc-linux-ld: usb.c:(.text+0xca): undefined reference to `cmxgcr_lock'
powerpc-linux-ld: usb.c:(.text+0xce): undefined reference to `cmxgcr_lock'

Fixes: 5e41486c408e ("powerpc/QE: add support for QE USB clocks routing")
Signed-off-by: Randy Dunlap 
Reported-by: kernel test robot 
Link: https://lore.kernel.org/all/202301101500.pillnv6r-...@intel.com/
Suggested-by: Michael Ellerman 
Cc: Christophe Leroy 
Cc: Leo Li 
Cc: Masahiro Yamada 
Cc: Nicolas Schier 
Cc: Qiang Zhao 
Cc: linuxppc-dev 
Cc: linux-arm-ker...@lists.infradead.org
Cc: Kumar Gala 
Acked-by: Nicolas Schier 
Signed-off-by: Li Yang 
Signed-off-by: Sasha Levin 
---
 drivers/soc/fsl/qe/Kconfig | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/soc/fsl/qe/Kconfig b/drivers/soc/fsl/qe/Kconfig
index 357c5800b112f..7afa796dbbb89 100644
--- a/drivers/soc/fsl/qe/Kconfig
+++ b/drivers/soc/fsl/qe/Kconfig
@@ -39,6 +39,7 @@ config QE_TDM
 
 config QE_USB
bool
+   depends on QUICC_ENGINE
default y if USB_FSL_QE
help
  QE USB Controller support
-- 
2.39.2





Re: [PATCH] tools/perf: Fix addr location init during arch_skip_callchain_idx function

2023-07-25 Thread Athira Rajeev



> On 25-Jul-2023, at 2:33 AM, Arnaldo Carvalho de Melo  wrote:
> 
> Em Mon, Jul 24, 2023 at 10:28:15PM +0530, Athira Rajeev escreveu:
>> perf record with callchain recording fails as below
>> in powerpc:
>> 
>>   ./perf record -a -gR sleep 10
>>   ./perf report
>>   perf: Segmentation fault
>> 
>> gdb trace points to thread__find_map
>> 
>>   0  0x101df314 in atomic_cmpxchg (newval=1818846826, 
>> oldval=1818846827, v=0x1001a8f3) at 
>> /home/athira/linux/tools/include/asm-generic/atomic-gcc.h:70
>>   1  refcount_sub_and_test (i=1, r=0x1001a8f3) at 
>> /home/athira/linux/tools/include/linux/refcount.h:135
>>   2  refcount_dec_and_test (r=0x1001a8f3) at 
>> /home/athira/linux/tools/include/linux/refcount.h:148
>>   3  map__put (map=0x1001a8b3) at util/map.c:311
>>   4  0x1016842c in __map__zput (map=0x7fffa368) at util/map.h:190
>>   5  thread__find_map (thread=0x105b92f0, cpumode=, 
>> addr=13835058055283572736, al=al@entry=0x7fffa358) at util/event.c:582
>>   6  0x1016882c in thread__find_symbol (thread=, 
>> cpumode=, addr=, al=0x7fffa358) at 
>> util/event.c:656
>>   7  0x102e12b4 in arch_skip_callchain_idx (thread=, 
>> chain=) at arch/powerpc/util/skip-callchain-idx.c:255
>>   8  0x101d3bf4 in thread__resolve_callchain_sample 
>> (thread=0x105b92f0, cursor=0x1053d160, evsel=, 
>> sample=0x7fffa908, parent=0x7fffa778, root_al=0x7fffa710,
>>   max_stack=) at util/machine.c:2940
>>   9  0x101cd210 in sample__resolve_callchain (sample=> out>, cursor=, parent=, evsel=, 
>> al=, max_stack=)
>>   at util/callchain.c:1112
>>   10 0x1022a9d8 in hist_entry_iter__add (iter=0x7fffa750, 
>> al=0x7fffa710, max_stack_depth=, arg=0x7fffbbd0) at 
>> util/hist.c:1232
>>   11 0x10056d98 in process_sample_event (tool=0x7fffbbd0, 
>> event=0x76223c38, sample=0x7fffa908, evsel=, 
>> machine=0x10524ef8) at builtin-report.c:332
>> 
>> Here arch_skip_callchain_idx calls thread__find_symbol and which
>> invokes thread__find_map with uninitialised "addr_location".
>> Snippet:
>> 
>> thread__find_symbol(thread, PERF_RECORD_MISC_USER, ip, );
>> 
>> Recent change with commit 0dd5041c9a0ea ("perf addr_location:
>> Add init/exit/copy functions"), introduced "maps__zput" in the
>> function thread__find_map. This could result in segfault while
>> accessing uninitialised map from "struct addr_location". Fix this
>> by adding addr_location__init and addr_location__exit in
>> arch_skip_callchain_idx.
> 
> Thanks, applied.

Hi Arnaldo,

Thanks for picking the fix 

Athira
> 
>> Fixes: 0dd5041c9a0ea ("perf addr_location: Add init/exit/copy functions")
> 
>> Reported-by: Aneesh Kumar K.V 
>> Signed-off-by: Athira Rajeev 
> 
> I'll also do a audit of all calls to thread__find_map() and its callers
> to check for other such cases :-\
> 
> For instance, this one seem buggy as well, Adrian?
> 
> diff --git a/tools/perf/util/dlfilter.c b/tools/perf/util/dlfilter.c
> index 46f74b2344dbb34c..798a53d7e6c9dfc5 100644
> --- a/tools/perf/util/dlfilter.c
> +++ b/tools/perf/util/dlfilter.c
> @@ -166,6 +166,7 @@ static __s32 dlfilter__resolve_address(void *ctx, __u64 
> address, struct perf_dlf
> if (!thread)
> return -1;
> 
> + addr_location__init();
> thread__find_symbol_fb(thread, d->sample->cpumode, address, );
> 
> al_to_d_al(, _al);




Re: [RFC PATCH v11 10/29] mm: Add AS_UNMOVABLE to mark mapping as completely unmovable

2023-07-25 Thread Kirill A . Shutemov
On Tue, Jul 18, 2023 at 04:44:53PM -0700, Sean Christopherson wrote:
> diff --git a/mm/compaction.c b/mm/compaction.c
> index dbc9f86b1934..a3d2b132df52 100644
> --- a/mm/compaction.c
> +++ b/mm/compaction.c
> @@ -1047,6 +1047,10 @@ isolate_migratepages_block(struct compact_control *cc, 
> unsigned long low_pfn,
>   if (!mapping && (folio_ref_count(folio) - 1) > 
> folio_mapcount(folio))
>   goto isolate_fail_put;
>  
> + /* The mapping truly isn't movable. */
> + if (mapping && mapping_unmovable(mapping))
> + goto isolate_fail_put;
> +

I doubt that it is safe to dereference mapping here. I believe the folio
can be truncated from under us and the mapping freed with the inode.

The folio has to be locked to dereference mapping safely (given that the
mapping is still tied to the folio).

Vlastimil, any comments?

-- 
  Kiryl Shutsemau / Kirill A. Shutemov


Re: [PATCH v5 5/7] powerpc/book3s64/memhotplug: Enable memmap on memory for radix

2023-07-25 Thread David Hildenbrand

  #endif /* CONFIG_PPC64 */
  
  #endif /* __ASSEMBLY__ */

diff --git a/arch/powerpc/platforms/pseries/hotplug-memory.c 
b/arch/powerpc/platforms/pseries/hotplug-memory.c
index 9c62c2c3b3d0..1447509357a7 100644
--- a/arch/powerpc/platforms/pseries/hotplug-memory.c
+++ b/arch/powerpc/platforms/pseries/hotplug-memory.c
@@ -617,6 +617,7 @@ static int dlpar_memory_remove_by_ic(u32 lmbs_to_remove, 
u32 drc_index)
  
  static int dlpar_add_lmb(struct drmem_lmb *lmb)

  {
+   mhp_t mhp_flags = MHP_NONE | MHP_MEMMAP_ON_MEMORY;


MHP_NONE is a placeholder, so no need for that and ...


unsigned long block_sz;
int nid, rc;
  
@@ -637,7 +638,7 @@ static int dlpar_add_lmb(struct drmem_lmb *lmb)

nid = first_online_node;
  
  	/* Add the memory */

-   rc = __add_memory(nid, lmb->base_addr, block_sz, MHP_NONE);
+   rc = __add_memory(nid, lmb->base_addr, block_sz, mhp_flags);

... this becomes

rc = __add_memory(nid, lmb->base_addr, block_sz, MHP_MEMMAP_ON_MEMORY);

With that

Reviewed-by: David Hildenbrand 

--
Cheers,

David / dhildenb



Re: [PATCH v5 0/7] Add support for memmap on memory feature on ppc64

2023-07-25 Thread David Hildenbrand

On 25.07.23 12:02, Aneesh Kumar K.V wrote:

This patch series update memmap on memory feature to fall back to
memmap allocation outside the memory block if the alignment rules are
not met. This makes the feature more useful on architectures like
ppc64 where alignment rules are different with 64K page size.

This patch series is dependent on dax vmemmap optimization series
posted here
https://lore.kernel.org/linux-mm/20230718022934.90447-1-aneesh.ku...@linux.ibm.com/

Changes from v4:
* Use altmap.free instead of altmap.reserve
* Address review feedback

Changes from v3:
* Extend the module parameter memmap_on_memory to force allocation even
   though we can waste hotplug memory.

Changes from v2:
* Rebase to latest linus tree
* Redo the series based on review feedback. Multiple changes to the patchset.

Changes from v1:
* update the memblock to store vmemmap_altmap details. This is required
so that when we remove the memory we can find the altmap details which
is needed on some architectures.
* rebase to latest linus tree



Aneesh Kumar K.V (7):
   mm/hotplug: Simplify ARCH_MHP_MEMMAP_ON_MEMORY_ENABLE kconfig
   mm/hotplug: Allow memmap on memory hotplug request to fallback
   mm/hotplug: Allow architecture to override memmap on memory support
 check
   mm/hotplug: Support memmap_on_memory when memmap is not aligned to
 pageblocks
   powerpc/book3s64/memhotplug: Enable memmap on memory for radix
   mm/hotplug: Embed vmem_altmap details in memory block
   mm/hotplug: Enable runtime update of memmap_on_memory parameter


Nit for all patches: we use "mm/memory_hotplug" as prefix. (I somehow 
missed that earlier :D )


--
Cheers,

David / dhildenb



[PATCH v5 3/7] mm/hotplug: Allow architecture to override memmap on memory support check

2023-07-25 Thread Aneesh Kumar K.V
Some architectures would want different restrictions. Hence add an
architecture-specific override.

The PMD_SIZE check is moved there.

Acked-by: David Hildenbrand 
Signed-off-by: Aneesh Kumar K.V 
---
 mm/memory_hotplug.c | 21 ++---
 1 file changed, 18 insertions(+), 3 deletions(-)

diff --git a/mm/memory_hotplug.c b/mm/memory_hotplug.c
index eca32ccd45cc..457824a6ecb8 100644
--- a/mm/memory_hotplug.c
+++ b/mm/memory_hotplug.c
@@ -1247,9 +1247,24 @@ static int online_memory_block(struct memory_block *mem, 
void *arg)
return device_online(>dev);
 }
 
+#ifndef arch_supports_memmap_on_memory
+static inline bool arch_supports_memmap_on_memory(unsigned long size)
+{
+   unsigned long nr_vmemmap_pages = size >> PAGE_SHIFT;
+   unsigned long vmemmap_size = nr_vmemmap_pages * sizeof(struct page);
+
+   /*
+* As default, we want the vmemmap to span a complete PMD such that we
+* can map the vmemmap using a single PMD if supported by the
+* architecture.
+*/
+   return IS_ALIGNED(vmemmap_size, PMD_SIZE);
+}
+#endif
+
 static bool mhp_supports_memmap_on_memory(unsigned long size)
 {
-   unsigned long nr_vmemmap_pages = size / PAGE_SIZE;
+   unsigned long nr_vmemmap_pages = size >> PAGE_SHIFT;
unsigned long vmemmap_size = nr_vmemmap_pages * sizeof(struct page);
unsigned long remaining_size = size - vmemmap_size;
 
@@ -1281,8 +1296,8 @@ static bool mhp_supports_memmap_on_memory(unsigned long 
size)
 */
return mhp_memmap_on_memory() &&
   size == memory_block_size_bytes() &&
-  IS_ALIGNED(vmemmap_size, PMD_SIZE) &&
-  IS_ALIGNED(remaining_size, (pageblock_nr_pages << PAGE_SHIFT));
+  IS_ALIGNED(remaining_size, (pageblock_nr_pages << PAGE_SHIFT)) &&
+  arch_supports_memmap_on_memory(size);
 }
 
 /*
-- 
2.41.0



[PATCH v5 7/7] mm/hotplug: Enable runtime update of memmap_on_memory parameter

2023-07-25 Thread Aneesh Kumar K.V
Signed-off-by: Aneesh Kumar K.V 
---
 mm/memory_hotplug.c | 27 +++
 1 file changed, 15 insertions(+), 12 deletions(-)

diff --git a/mm/memory_hotplug.c b/mm/memory_hotplug.c
index 96e794f39313..6cb6eac1aee5 100644
--- a/mm/memory_hotplug.c
+++ b/mm/memory_hotplug.c
@@ -95,7 +95,12 @@ static int set_memmap_mode(const char *val, const struct 
kernel_param *kp)
mode =  MEMMAP_ON_MEMORY_DISABLE;
 
 matched:
+   /*
+* Avoid changing memmap mode during hotplug.
+*/
+   get_online_mems();
*((int *)kp->arg) =  mode;
+   put_online_mems();
if (mode == MEMMAP_ON_MEMORY_FORCE) {
unsigned long memmap_pages = 
memory_block_memmap_on_memory_pages();
 
@@ -116,7 +121,7 @@ static const struct kernel_param_ops memmap_mode_ops = {
.set = set_memmap_mode,
.get = get_memmap_mode,
 };
-module_param_cb(memmap_on_memory, _mode_ops, _mode, 0444);
+module_param_cb(memmap_on_memory, _mode_ops, _mode, 0644);
 MODULE_PARM_DESC(memmap_on_memory, "Enable memmap on memory for memory 
hotplug\n"
 "With value \"force\" it could result in memory wastage due "
 "to memmap size limitations (Y/N/force)");
@@ -2175,18 +2180,16 @@ static int __ref try_remove_memory(u64 start, u64 size)
 * We only support removing memory added with MHP_MEMMAP_ON_MEMORY in
 * the same granularity it was added - a single memory block.
 */
-   if (mhp_memmap_on_memory()) {
-   ret = walk_memory_blocks(start, size, _altmap,
-get_vmemmap_altmap_cb);
-   if (ret) {
-   if (size != memory_block_size_bytes()) {
-   pr_warn("Refuse to remove %#llx - %#llx,"
-   "wrong granularity\n",
-   start, start + size);
-   return -EINVAL;
-   }
-   altmap = _altmap;
+   ret = walk_memory_blocks(start, size, _altmap,
+get_vmemmap_altmap_cb);
+   if (ret) {
+   if (size != memory_block_size_bytes()) {
+   pr_warn("Refuse to remove %#llx - %#llx,"
+   "wrong granularity\n",
+   start, start + size);
+   return -EINVAL;
}
+   altmap = _altmap;
}
 
/* remove memmap entry */
-- 
2.41.0



[PATCH v5 5/7] powerpc/book3s64/memhotplug: Enable memmap on memory for radix

2023-07-25 Thread Aneesh Kumar K.V
Radix vmemmap mapping can map things correctly at the PMD level or PTE
level based on different device boundary checks. Hence we skip the
restrictions w.r.t vmemmap size to be multiple of PMD_SIZE. This also
makes the feature widely useful because to use PMD_SIZE vmemmap area we
require a memory block size of 2GiB

We can also use MHP_RESERVE_PAGES_MEMMAP_ON_MEMORY to that the feature
can work with a memory block size of 256MB. Using altmap.reserve feature
to align things correctly at pageblock granularity. We can end up
losing some pages in memory with this. For ex: with a 256MiB memory block
size, we require 4 pages to map vmemmap pages, In order to align things
correctly we end up adding a reserve of 28 pages. ie, for every 4096
pages 28 pages get reserved.

Signed-off-by: Aneesh Kumar K.V 
---
 arch/powerpc/Kconfig  |  1 +
 arch/powerpc/include/asm/pgtable.h| 24 +++
 .../platforms/pseries/hotplug-memory.c|  3 ++-
 3 files changed, 27 insertions(+), 1 deletion(-)

diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig
index d0497d13f5b4..938294c996dc 100644
--- a/arch/powerpc/Kconfig
+++ b/arch/powerpc/Kconfig
@@ -157,6 +157,7 @@ config PPC
select ARCH_HAS_UBSAN_SANITIZE_ALL
select ARCH_HAVE_NMI_SAFE_CMPXCHG
select ARCH_KEEP_MEMBLOCK
+   select ARCH_MHP_MEMMAP_ON_MEMORY_ENABLE if PPC_RADIX_MMU
select ARCH_MIGHT_HAVE_PC_PARPORT
select ARCH_MIGHT_HAVE_PC_SERIO
select ARCH_OPTIONAL_KERNEL_RWX if ARCH_HAS_STRICT_KERNEL_RWX
diff --git a/arch/powerpc/include/asm/pgtable.h 
b/arch/powerpc/include/asm/pgtable.h
index a4893b17705a..9b4a1fd24025 100644
--- a/arch/powerpc/include/asm/pgtable.h
+++ b/arch/powerpc/include/asm/pgtable.h
@@ -161,6 +161,30 @@ static inline pgtable_t pmd_pgtable(pmd_t pmd)
 int __meminit vmemmap_populated(unsigned long vmemmap_addr, int 
vmemmap_map_size);
 bool altmap_cross_boundary(struct vmem_altmap *altmap, unsigned long start,
   unsigned long page_size);
+/*
+ * mm/memory_hotplug.c:mhp_supports_memmap_on_memory goes into details
+ * some of the restrictions. We don't check for PMD_SIZE because our
+ * vmemmap allocation code can fallback correctly. The pageblock
+ * alignment requirement is met using altmap->reserve blocks.
+ */
+#define arch_supports_memmap_on_memory arch_supports_memmap_on_memory
+static inline bool arch_supports_memmap_on_memory(unsigned long size)
+{
+   unsigned long nr_pages = size >> PAGE_SHIFT;
+   unsigned long vmemmap_size = nr_pages * sizeof(struct page);
+
+   if (!radix_enabled())
+   return false;
+   /*
+* With 4K page size and 2M PMD_SIZE, we can align
+* things better with memory block size value
+* starting from 128MB. Hence align things with PMD_SIZE.
+*/
+   if (IS_ENABLED(CONFIG_PPC_4K_PAGES))
+   return IS_ALIGNED(vmemmap_size, PMD_SIZE);
+   return true;
+}
+
 #endif /* CONFIG_PPC64 */
 
 #endif /* __ASSEMBLY__ */
diff --git a/arch/powerpc/platforms/pseries/hotplug-memory.c 
b/arch/powerpc/platforms/pseries/hotplug-memory.c
index 9c62c2c3b3d0..1447509357a7 100644
--- a/arch/powerpc/platforms/pseries/hotplug-memory.c
+++ b/arch/powerpc/platforms/pseries/hotplug-memory.c
@@ -617,6 +617,7 @@ static int dlpar_memory_remove_by_ic(u32 lmbs_to_remove, 
u32 drc_index)
 
 static int dlpar_add_lmb(struct drmem_lmb *lmb)
 {
+   mhp_t mhp_flags = MHP_NONE | MHP_MEMMAP_ON_MEMORY;
unsigned long block_sz;
int nid, rc;
 
@@ -637,7 +638,7 @@ static int dlpar_add_lmb(struct drmem_lmb *lmb)
nid = first_online_node;
 
/* Add the memory */
-   rc = __add_memory(nid, lmb->base_addr, block_sz, MHP_NONE);
+   rc = __add_memory(nid, lmb->base_addr, block_sz, mhp_flags);
if (rc) {
invalidate_lmb_associativity_index(lmb);
return rc;
-- 
2.41.0



[PATCH v5 6/7] mm/hotplug: Embed vmem_altmap details in memory block

2023-07-25 Thread Aneesh Kumar K.V
With memmap on memory, some architecture needs more details w.r.t altmap
such as base_pfn, end_pfn, etc to unmap vmemmap memory. Instead of
computing them again when we remove a memory block, embed vmem_altmap
details in struct memory_block if we are using memmap on memory block
feature.

No functional change in this patch

Signed-off-by: Aneesh Kumar K.V 
---
 drivers/base/memory.c  | 32 +++-
 include/linux/memory.h |  8 ++--
 mm/memory_hotplug.c| 41 ++---
 3 files changed, 47 insertions(+), 34 deletions(-)

diff --git a/drivers/base/memory.c b/drivers/base/memory.c
index b456ac213610..0210ed7b7696 100644
--- a/drivers/base/memory.c
+++ b/drivers/base/memory.c
@@ -106,6 +106,7 @@ static void memory_block_release(struct device *dev)
 {
struct memory_block *mem = to_memory_block(dev);
 
+   kfree(mem->altmap);
kfree(mem);
 }
 
@@ -183,7 +184,7 @@ static int memory_block_online(struct memory_block *mem)
 {
unsigned long start_pfn = section_nr_to_pfn(mem->start_section_nr);
unsigned long nr_pages = PAGES_PER_SECTION * sections_per_block;
-   unsigned long nr_vmemmap_pages = mem->nr_vmemmap_pages;
+   unsigned long nr_vmemmap_pages = 0;
struct zone *zone;
int ret;
 
@@ -200,6 +201,9 @@ static int memory_block_online(struct memory_block *mem)
 * stage helps to keep accounting easier to follow - e.g vmemmaps
 * belong to the same zone as the memory they backed.
 */
+   if (mem->altmap)
+   nr_vmemmap_pages = mem->altmap->free;
+
if (nr_vmemmap_pages) {
ret = mhp_init_memmap_on_memory(start_pfn, nr_vmemmap_pages, 
zone);
if (ret)
@@ -230,7 +234,7 @@ static int memory_block_offline(struct memory_block *mem)
 {
unsigned long start_pfn = section_nr_to_pfn(mem->start_section_nr);
unsigned long nr_pages = PAGES_PER_SECTION * sections_per_block;
-   unsigned long nr_vmemmap_pages = mem->nr_vmemmap_pages;
+   unsigned long nr_vmemmap_pages = 0;
int ret;
 
if (!mem->zone)
@@ -240,6 +244,9 @@ static int memory_block_offline(struct memory_block *mem)
 * Unaccount before offlining, such that unpopulated zone and kthreads
 * can properly be torn down in offline_pages().
 */
+   if (mem->altmap)
+   nr_vmemmap_pages = mem->altmap->free;
+
if (nr_vmemmap_pages)
adjust_present_page_count(pfn_to_page(start_pfn), mem->group,
  -nr_vmemmap_pages);
@@ -726,7 +733,7 @@ void memory_block_add_nid(struct memory_block *mem, int nid,
 #endif
 
 static int add_memory_block(unsigned long block_id, unsigned long state,
-   unsigned long nr_vmemmap_pages,
+   struct vmem_altmap *altmap,
struct memory_group *group)
 {
struct memory_block *mem;
@@ -744,7 +751,14 @@ static int add_memory_block(unsigned long block_id, 
unsigned long state,
mem->start_section_nr = block_id * sections_per_block;
mem->state = state;
mem->nid = NUMA_NO_NODE;
-   mem->nr_vmemmap_pages = nr_vmemmap_pages;
+   if (altmap) {
+   mem->altmap = kmalloc(sizeof(struct vmem_altmap), GFP_KERNEL);
+   if (!mem->altmap) {
+   kfree(mem);
+   return -ENOMEM;
+   }
+   memcpy(mem->altmap, altmap, sizeof(*altmap));
+   }
INIT_LIST_HEAD(>group_next);
 
 #ifndef CONFIG_NUMA
@@ -783,14 +797,14 @@ static int __init add_boot_memory_block(unsigned long 
base_section_nr)
if (section_count == 0)
return 0;
return add_memory_block(memory_block_id(base_section_nr),
-   MEM_ONLINE, 0,  NULL);
+   MEM_ONLINE, NULL,  NULL);
 }
 
 static int add_hotplug_memory_block(unsigned long block_id,
-   unsigned long nr_vmemmap_pages,
+   struct vmem_altmap *altmap,
struct memory_group *group)
 {
-   return add_memory_block(block_id, MEM_OFFLINE, nr_vmemmap_pages, group);
+   return add_memory_block(block_id, MEM_OFFLINE, altmap, group);
 }
 
 static void remove_memory_block(struct memory_block *memory)
@@ -818,7 +832,7 @@ static void remove_memory_block(struct memory_block *memory)
  * Called under device_hotplug_lock.
  */
 int create_memory_block_devices(unsigned long start, unsigned long size,
-   unsigned long vmemmap_pages,
+   struct vmem_altmap *altmap,
struct memory_group *group)
 {
const unsigned long start_block_id = pfn_to_block_id(PFN_DOWN(start));
@@ -832,7 +846,7 @@ int create_memory_block_devices(unsigned long start, 
unsigned long size,

[PATCH v5 4/7] mm/hotplug: Support memmap_on_memory when memmap is not aligned to pageblocks

2023-07-25 Thread Aneesh Kumar K.V
Currently, memmap_on_memory feature is only supported with memory block
sizes that result in vmemmap pages covering full page blocks. This is
because memory onlining/offlining code requires applicable ranges to be
pageblock-aligned, for example, to set the migratetypes properly.

This patch helps to lift that restriction by reserving more pages than
required for vmemmap space. This helps the start address to be page
block aligned with different memory block sizes. Using this facility
implies the kernel will be reserving some pages for every memoryblock.
This allows the memmap on memory feature to be widely useful with
different memory block size values.

For ex: with 64K page size and 256MiB memory block size, we require 4
pages to map vmemmap pages, To align things correctly we end up adding a
reserve of 28 pages. ie, for every 4096 pages 28 pages get reserved.

Signed-off-by: Aneesh Kumar K.V 
---
 .../admin-guide/mm/memory-hotplug.rst |  12 ++
 mm/memory_hotplug.c   | 121 --
 2 files changed, 119 insertions(+), 14 deletions(-)

diff --git a/Documentation/admin-guide/mm/memory-hotplug.rst 
b/Documentation/admin-guide/mm/memory-hotplug.rst
index bd77841041af..2994958c7ce8 100644
--- a/Documentation/admin-guide/mm/memory-hotplug.rst
+++ b/Documentation/admin-guide/mm/memory-hotplug.rst
@@ -433,6 +433,18 @@ The following module parameters are currently defined:
 memory in a way that huge pages in bigger
 granularity cannot be formed on hotplugged
 memory.
+
+With value "force" it could result in memory
+wastage due to memmap size limitations. For
+example, if the memmap for a memory block
+requires 1 MiB, but the pageblock size is 2
+MiB, 1 MiB of hotplugged memory will be wasted.
+Note that there are still cases where the
+feature cannot be enforced: for example, if the
+memmap is smaller than a single page, or if the
+architecture does not support the forced mode
+in all configurations.
+
 ``online_policy``   read-write: Set the basic policy used for
 automatic zone selection when onlining memory
 blocks without specifying a target zone.
diff --git a/mm/memory_hotplug.c b/mm/memory_hotplug.c
index 457824a6ecb8..5b472e137898 100644
--- a/mm/memory_hotplug.c
+++ b/mm/memory_hotplug.c
@@ -41,17 +41,89 @@
 #include "internal.h"
 #include "shuffle.h"
 
+enum {
+   MEMMAP_ON_MEMORY_DISABLE = 0,
+   MEMMAP_ON_MEMORY_ENABLE,
+   MEMMAP_ON_MEMORY_FORCE,
+};
+
+static int memmap_mode __read_mostly = MEMMAP_ON_MEMORY_DISABLE;
+
+static inline unsigned long memory_block_memmap_pages(void)
+{
+   unsigned long memmap_size;
+
+   memmap_size = PHYS_PFN(memory_block_size_bytes()) * sizeof(struct page);
+   return memmap_size >> PAGE_SHIFT;
+}
+
+static inline unsigned long memory_block_memmap_on_memory_pages(void)
+{
+   unsigned long nr_pages = memory_block_memmap_pages();
+
+   /*
+* In "forced" memmap_on_memory mode, we add extra pages to align the
+* vmemmap size to cover full pageblocks. That way, we can add memory
+* even if the vmemmap size is not properly aligned, however, we might 
waste
+* memory.
+*/
+   if (memmap_mode == MEMMAP_ON_MEMORY_FORCE)
+   return pageblock_align(nr_pages);
+   return nr_pages;
+}
+
 #ifdef CONFIG_MHP_MEMMAP_ON_MEMORY
 /*
  * memory_hotplug.memmap_on_memory parameter
  */
-static bool memmap_on_memory __ro_after_init;
-module_param(memmap_on_memory, bool, 0444);
-MODULE_PARM_DESC(memmap_on_memory, "Enable memmap on memory for memory 
hotplug");
+static int set_memmap_mode(const char *val, const struct kernel_param *kp)
+{
+   int ret, mode;
+   bool enabled;
+
+   if (sysfs_streq(val, "force") ||  sysfs_streq(val, "FORCE")) {
+   mode =  MEMMAP_ON_MEMORY_FORCE;
+   goto matched;
+   }
+
+   ret = kstrtobool(val, );
+   if (ret < 0)
+   return ret;
+   if (enabled)
+   mode =  MEMMAP_ON_MEMORY_ENABLE;
+   else
+   mode =  MEMMAP_ON_MEMORY_DISABLE;
+
+matched:
+   *((int *)kp->arg) =  mode;
+   if (mode == MEMMAP_ON_MEMORY_FORCE) {
+   unsigned long memmap_pages = 
memory_block_memmap_on_memory_pages();
+
+   pr_info("Memory hotplug will reserve %ld pages in each memory 
block\n",
+   memmap_pages - memory_block_memmap_pages());
+   }
+   return 0;
+}
+
+static int get_memmap_mode(char *buffer, const struct 

[PATCH v5 2/7] mm/hotplug: Allow memmap on memory hotplug request to fallback

2023-07-25 Thread Aneesh Kumar K.V
If not supported, fallback to not using memap on memmory. This avoids
the need for callers to do the fallback.

Acked-by: David Hildenbrand 
Signed-off-by: Aneesh Kumar K.V 
---
 drivers/acpi/acpi_memhotplug.c |  3 +--
 include/linux/memory_hotplug.h |  3 ++-
 mm/memory_hotplug.c| 13 ++---
 3 files changed, 9 insertions(+), 10 deletions(-)

diff --git a/drivers/acpi/acpi_memhotplug.c b/drivers/acpi/acpi_memhotplug.c
index 24f662d8bd39..d0c1a71007d0 100644
--- a/drivers/acpi/acpi_memhotplug.c
+++ b/drivers/acpi/acpi_memhotplug.c
@@ -211,8 +211,7 @@ static int acpi_memory_enable_device(struct 
acpi_memory_device *mem_device)
if (!info->length)
continue;
 
-   if (mhp_supports_memmap_on_memory(info->length))
-   mhp_flags |= MHP_MEMMAP_ON_MEMORY;
+   mhp_flags |= MHP_MEMMAP_ON_MEMORY;
result = __add_memory(mgid, info->start_addr, info->length,
  mhp_flags);
 
diff --git a/include/linux/memory_hotplug.h b/include/linux/memory_hotplug.h
index 013c69753c91..7d2076583494 100644
--- a/include/linux/memory_hotplug.h
+++ b/include/linux/memory_hotplug.h
@@ -97,6 +97,8 @@ typedef int __bitwise mhp_t;
  * To do so, we will use the beginning of the hot-added range to build
  * the page tables for the memmap array that describes the entire range.
  * Only selected architectures support it with SPARSE_VMEMMAP.
+ * This is only a hint, the core kernel can decide to not do this based on
+ * different alignment checks.
  */
 #define MHP_MEMMAP_ON_MEMORY   ((__force mhp_t)BIT(1))
 /*
@@ -354,7 +356,6 @@ extern struct zone *zone_for_pfn_range(int online_type, int 
nid,
 extern int arch_create_linear_mapping(int nid, u64 start, u64 size,
  struct mhp_params *params);
 void arch_remove_linear_mapping(u64 start, u64 size);
-extern bool mhp_supports_memmap_on_memory(unsigned long size);
 #endif /* CONFIG_MEMORY_HOTPLUG */
 
 #endif /* __LINUX_MEMORY_HOTPLUG_H */
diff --git a/mm/memory_hotplug.c b/mm/memory_hotplug.c
index 7cfd13c91568..eca32ccd45cc 100644
--- a/mm/memory_hotplug.c
+++ b/mm/memory_hotplug.c
@@ -1247,7 +1247,7 @@ static int online_memory_block(struct memory_block *mem, 
void *arg)
return device_online(>dev);
 }
 
-bool mhp_supports_memmap_on_memory(unsigned long size)
+static bool mhp_supports_memmap_on_memory(unsigned long size)
 {
unsigned long nr_vmemmap_pages = size / PAGE_SIZE;
unsigned long vmemmap_size = nr_vmemmap_pages * sizeof(struct page);
@@ -1339,13 +1339,12 @@ int __ref add_memory_resource(int nid, struct resource 
*res, mhp_t mhp_flags)
 * Self hosted memmap array
 */
if (mhp_flags & MHP_MEMMAP_ON_MEMORY) {
-   if (!mhp_supports_memmap_on_memory(size)) {
-   ret = -EINVAL;
-   goto error;
+   if (mhp_supports_memmap_on_memory(size)) {
+   mhp_altmap.free = PHYS_PFN(size);
+   mhp_altmap.base_pfn = PHYS_PFN(start);
+   params.altmap = _altmap;
}
-   mhp_altmap.free = PHYS_PFN(size);
-   mhp_altmap.base_pfn = PHYS_PFN(start);
-   params.altmap = _altmap;
+   /* fallback to not using altmap  */
}
 
/* call arch's memory hotadd */
-- 
2.41.0



[PATCH v5 1/7] mm/hotplug: Simplify ARCH_MHP_MEMMAP_ON_MEMORY_ENABLE kconfig

2023-07-25 Thread Aneesh Kumar K.V
Instead of adding menu entry with all supported architectures, add
mm/Kconfig variable and select the same from supported architectures.

No functional change in this patch.

Acked-by: David Hildenbrand 
Signed-off-by: Aneesh Kumar K.V 
---
 arch/arm64/Kconfig | 4 +---
 arch/x86/Kconfig   | 4 +---
 mm/Kconfig | 3 +++
 3 files changed, 5 insertions(+), 6 deletions(-)

diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
index b1573257a4d6..0f749cfab8e6 100644
--- a/arch/arm64/Kconfig
+++ b/arch/arm64/Kconfig
@@ -78,6 +78,7 @@ config ARM64
select ARCH_INLINE_SPIN_UNLOCK_IRQ if !PREEMPTION
select ARCH_INLINE_SPIN_UNLOCK_IRQRESTORE if !PREEMPTION
select ARCH_KEEP_MEMBLOCK
+   select ARCH_MHP_MEMMAP_ON_MEMORY_ENABLE
select ARCH_USE_CMPXCHG_LOCKREF
select ARCH_USE_GNU_PROPERTY
select ARCH_USE_MEMTEST
@@ -347,9 +348,6 @@ config GENERIC_CSUM
 config GENERIC_CALIBRATE_DELAY
def_bool y
 
-config ARCH_MHP_MEMMAP_ON_MEMORY_ENABLE
-   def_bool y
-
 config SMP
def_bool y
 
diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
index 78224aa76409..d0258e92a8af 100644
--- a/arch/x86/Kconfig
+++ b/arch/x86/Kconfig
@@ -102,6 +102,7 @@ config X86
select ARCH_HAS_DEBUG_WX
select ARCH_HAS_ZONE_DMA_SET if EXPERT
select ARCH_HAVE_NMI_SAFE_CMPXCHG
+   select ARCH_MHP_MEMMAP_ON_MEMORY_ENABLE
select ARCH_MIGHT_HAVE_ACPI_PDC if ACPI
select ARCH_MIGHT_HAVE_PC_PARPORT
select ARCH_MIGHT_HAVE_PC_SERIO
@@ -2610,9 +2611,6 @@ config ARCH_HAS_ADD_PAGES
def_bool y
depends on ARCH_ENABLE_MEMORY_HOTPLUG
 
-config ARCH_MHP_MEMMAP_ON_MEMORY_ENABLE
-   def_bool y
-
 menu "Power management and ACPI options"
 
 config ARCH_HIBERNATION_HEADER
diff --git a/mm/Kconfig b/mm/Kconfig
index 5fe49c030961..721dc88423c7 100644
--- a/mm/Kconfig
+++ b/mm/Kconfig
@@ -571,6 +571,9 @@ config MHP_MEMMAP_ON_MEMORY
 
 endif # MEMORY_HOTPLUG
 
+config ARCH_MHP_MEMMAP_ON_MEMORY_ENABLE
+   bool
+
 # Heavily threaded applications may benefit from splitting the mm-wide
 # page_table_lock, so that faults on different parts of the user address
 # space can be handled with less contention: split it at this NR_CPUS.
-- 
2.41.0



[PATCH v5 0/7] Add support for memmap on memory feature on ppc64

2023-07-25 Thread Aneesh Kumar K.V
This patch series update memmap on memory feature to fall back to
memmap allocation outside the memory block if the alignment rules are
not met. This makes the feature more useful on architectures like
ppc64 where alignment rules are different with 64K page size.

This patch series is dependent on dax vmemmap optimization series
posted here
https://lore.kernel.org/linux-mm/20230718022934.90447-1-aneesh.ku...@linux.ibm.com/

Changes from v4:
* Use altmap.free instead of altmap.reserve
* Address review feedback

Changes from v3:
* Extend the module parameter memmap_on_memory to force allocation even
  though we can waste hotplug memory.

Changes from v2:
* Rebase to latest linus tree
* Redo the series based on review feedback. Multiple changes to the patchset.

Changes from v1:
* update the memblock to store vmemmap_altmap details. This is required
so that when we remove the memory we can find the altmap details which
is needed on some architectures.
* rebase to latest linus tree



Aneesh Kumar K.V (7):
  mm/hotplug: Simplify ARCH_MHP_MEMMAP_ON_MEMORY_ENABLE kconfig
  mm/hotplug: Allow memmap on memory hotplug request to fallback
  mm/hotplug: Allow architecture to override memmap on memory support
check
  mm/hotplug: Support memmap_on_memory when memmap is not aligned to
pageblocks
  powerpc/book3s64/memhotplug: Enable memmap on memory for radix
  mm/hotplug: Embed vmem_altmap details in memory block
  mm/hotplug: Enable runtime update of memmap_on_memory parameter

 .../admin-guide/mm/memory-hotplug.rst |  12 ++
 arch/arm64/Kconfig|   4 +-
 arch/powerpc/Kconfig  |   1 +
 arch/powerpc/include/asm/pgtable.h|  24 +++
 .../platforms/pseries/hotplug-memory.c|   3 +-
 arch/x86/Kconfig  |   4 +-
 drivers/acpi/acpi_memhotplug.c|   3 +-
 drivers/base/memory.c |  32 ++-
 include/linux/memory.h|   8 +-
 include/linux/memory_hotplug.h|   3 +-
 mm/Kconfig|   3 +
 mm/memory_hotplug.c   | 201 ++
 12 files changed, 229 insertions(+), 69 deletions(-)

-- 
2.41.0



[PATCH 23/26] MAINTAINERS: Add the Lantiq PEF2256 driver entry

2023-07-25 Thread Herve Codina
After contributing the driver, add myself as the maintainer for the
Lantiq PEF2256 driver.

Signed-off-by: Herve Codina 
---
 MAINTAINERS | 9 +
 1 file changed, 9 insertions(+)

diff --git a/MAINTAINERS b/MAINTAINERS
index 14041d90f9c8..07a7d9fca3c4 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -11776,6 +11776,15 @@ 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-regs.h
+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 22/26] pinctrl: Add support for the Lantic PEF2256 pinmux

2023-07-25 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 pinmux support handles the pin muxing part (pins RP(A..D) and pins
XP(A..D)) of the PEF2256.

Signed-off-by: Herve Codina 
---
 drivers/pinctrl/Kconfig|  14 ++
 drivers/pinctrl/Makefile   |   1 +
 drivers/pinctrl/pinctrl-pef2256-regs.h |  65 ++
 drivers/pinctrl/pinctrl-pef2256.c  | 310 +
 4 files changed, 390 insertions(+)
 create mode 100644 drivers/pinctrl/pinctrl-pef2256-regs.h
 create mode 100644 drivers/pinctrl/pinctrl-pef2256.c

diff --git a/drivers/pinctrl/Kconfig b/drivers/pinctrl/Kconfig
index 57d57af1f624..a3aa96b59c97 100644
--- a/drivers/pinctrl/Kconfig
+++ b/drivers/pinctrl/Kconfig
@@ -377,6 +377,20 @@ 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 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 482b391b5deb..8f211f7671a8 100644
--- a/drivers/pinctrl/Makefile
+++ b/drivers/pinctrl/Makefile
@@ -40,6 +40,7 @@ obj-$(CONFIG_PINCTRL_MLXBF3)  += pinctrl-mlxbf3.o
 obj-$(CONFIG_PINCTRL_OCELOT)   += pinctrl-ocelot.o
 obj-$(CONFIG_PINCTRL_OXNAS)+= pinctrl-oxnas.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-regs.h 
b/drivers/pinctrl/pinctrl-pef2256-regs.h
new file mode 100644
index ..586d94007e24
--- /dev/null
+++ b/drivers/pinctrl/pinctrl-pef2256-regs.h
@@ -0,0 +1,65 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * PEF2256 pinctrl registers definition
+ *
+ * Copyright 2023 CS GROUP France
+ *
+ * Author: Herve Codina 
+ */
+#ifndef __PEF2256_PINCTRL_REGS_H__
+#define __PEF2256_PINCTRL_REGS_H__
+
+#include "linux/bitfield.h"
+
+/* 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)
+#define PEF2256_2X_PC_RPC_DLRFIELD_PREP_CONST(PEF2256_2X_PC_RPC_MASK, 0x5)
+#define PEF2256_2X_PC_RPC_FREEZE  FIELD_PREP_CONST(PEF2256_2X_PC_RPC_MASK, 0x6)
+#define PEF2256_2X_PC_RPC_RFSP   

[PATCH 21/26] net: wan: framer: Add support for the Lantiq PEF2256 framer

2023-07-25 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 
---
 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 96ef1e7ba8eb..ba43d7f162a2 100644
--- a/drivers/net/wan/framer/Kconfig
+++ b/drivers/net/wan/framer/Kconfig
@@ -16,4 +16,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 
FIELD_PREP_CONST(PEF2256_FMR2_RFS_MASK, 0x0)
+#define 

[PATCH 20/26] mfd: core: Ensure disabled devices are skiped without aborting

2023-07-25 Thread Herve Codina
The loop searching for a matching device based on its compatible
string is aborted when a matching disabled device is found.
This abort avoid to add devices as soon as one disabled device
is found.

Continue searching for an other device instead of aborting on the
first disabled one fixes the issue.

Fixes: 22380b65dc70 ("mfd: mfd-core: Ensure disabled devices are ignored 
without error")
Signed-off-by: Herve Codina 
---
 drivers/mfd/mfd-core.c | 18 +-
 1 file changed, 13 insertions(+), 5 deletions(-)

diff --git a/drivers/mfd/mfd-core.c b/drivers/mfd/mfd-core.c
index 0ed7c0d7784e..bcc26e64639a 100644
--- a/drivers/mfd/mfd-core.c
+++ b/drivers/mfd/mfd-core.c
@@ -146,6 +146,7 @@ static int mfd_add_device(struct device *parent, int id,
struct platform_device *pdev;
struct device_node *np = NULL;
struct mfd_of_node_entry *of_entry, *tmp;
+   bool disabled;
int ret = -ENOMEM;
int platform_id;
int r;
@@ -181,13 +182,13 @@ static int mfd_add_device(struct device *parent, int id,
goto fail_res;
 
if (IS_ENABLED(CONFIG_OF) && parent->of_node && cell->of_compatible) {
+   disabled = false;
for_each_child_of_node(parent->of_node, np) {
if (of_device_is_compatible(np, cell->of_compatible)) {
-   /* Ignore 'disabled' devices error free */
+   /* Skip 'disabled' devices */
if (!of_device_is_available(np)) {
-   of_node_put(np);
-   ret = 0;
-   goto fail_alias;
+   disabled = true;
+   continue;
}
 
ret = mfd_match_of_node_to_dev(pdev, np, cell);
@@ -197,10 +198,17 @@ static int mfd_add_device(struct device *parent, int id,
if (ret)
goto fail_alias;
 
-   break;
+   goto match;
}
}
 
+   if (disabled) {
+   /* Ignore 'disabled' devices error free */
+   ret = 0;
+   goto fail_alias;
+   }
+
+match:
if (!pdev->dev.of_node)
pr_warn("%s: Failed to locate of_node [id: %d]\n",
cell->name, platform_id);
-- 
2.41.0



[PATCH 19/26] dt-bindings: net: Add the Lantiq PEF2256 E1/T1/J1 framer

2023-07-25 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 
---
 .../bindings/net/lantiq,pef2256.yaml  | 226 ++
 1 file changed, 226 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 ..b369a20d61b1
--- /dev/null
+++ b/Documentation/devicetree/bindings/net/lantiq,pef2256.yaml
@@ -0,0 +1,226 @@
+# 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: Receive System Clock
+  - description: Transmit System Clock
+
+  clock-names:
+items:
+  - const: mclk
+  - const: sclkr
+  - const: sclkx
+
+  interrupts:
+maxItems: 1
+
+  reset-gpios:
+description:
+  GPIO used to reset the device.
+maxItems: 1
+
+  '#framer-cells':
+const: 0
+
+  pinctrl:
+$ref: /schemas/pinctrl/pinctrl.yaml#
+additionalProperties: false
+
+patternProperties:
+  '-pins$':
+type: object
+$ref: /schemas/pinctrl/pincfg-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:
+$ref: /schemas/types.yaml#/definitions/uint32
+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 8bit time-slots in E1 and 24 8bit
+  time-slots 8 8bit 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 8bit) 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 8bit 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
+
+

[PATCH 18/26] net: wan: Add framer framework support

2023-07-25 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 
---
 drivers/net/wan/Kconfig|   2 +
 drivers/net/wan/Makefile   |   2 +
 drivers/net/wan/framer/Kconfig |  19 +
 drivers/net/wan/framer/Makefile|   6 +
 drivers/net/wan/framer/framer-core.c   | 935 +
 include/linux/framer/framer-provider.h | 194 +
 include/linux/framer/framer.h  | 215 ++
 7 files changed, 1373 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 ..96ef1e7ba8eb
--- /dev/null
+++ b/drivers/net/wan/framer/Kconfig
@@ -0,0 +1,19 @@
+# SPDX-License-Identifier: GPL-2.0-only
+#
+# FRAMER
+#
+
+menu "Framer Subsystem"
+
+config GENERIC_FRAMER
+   bool "Framer Core"
+   help
+ Generic Framer support.
+
+ 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 ..ef93b7d74fd1
--- /dev/null
+++ b/drivers/net/wan/framer/framer-core.c
@@ -0,0 +1,935 @@
+// 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 (!framer)
+   return 0;
+
+   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 (!framer)
+   return 0;
+
+   if (!pm_runtime_enabled(>dev))
+   return -EOPNOTSUPP;
+
+   ret = pm_runtime_get_sync(>dev);
+   if (ret < 0)
+   pm_runtime_put_sync(>dev);
+
+   return ret;
+}
+EXPORT_SYMBOL_GPL(framer_pm_runtime_get_sync);
+
+int framer_pm_runtime_put(struct framer *framer)
+{
+   if (!framer)
+   return 0;
+
+   if (!pm_runtime_enabled(>dev))
+   return 

[PATCH 17/26] wan: qmc_hdlc: Add runtime timeslots changes support

2023-07-25 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 
---
 drivers/net/wan/fsl_qmc_hdlc.c | 170 -
 1 file changed, 169 insertions(+), 1 deletion(-)

diff --git a/drivers/net/wan/fsl_qmc_hdlc.c b/drivers/net/wan/fsl_qmc_hdlc.c
index b4ebae963d39..7eb0ebaa30e7 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,163 @@ 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 = 0;
+
+   /* 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 = 0;
+
+   /* 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;
+   int ret;
+
+   switch (ifs->type) 

[PATCH 16/26] soc: fsl: cpm1: qmc: Introduce functions to change timeslots at runtime

2023-07-25 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 
---
 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 15872d3e4992..a90b3097722f 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 6f1d6cebc9fe..802c161636bd 100644
--- a/include/soc/fsl/qe/qmc.h
+++ b/include/soc/fsl/qe/qmc.h
@@ -38,6 +38,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 15/26] soc: fsl: cpm1: qmc: Remove timeslots handling from setup_chan()

2023-07-25 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 
---
 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 6d1cd203abd2..15872d3e4992 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 14/26] soc: fsl: cpm1: qmc: Handle timeslot entries at channel start() and stop()

2023-07-25 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 
---
 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 64c3bfc16010..6d1cd203abd2 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 inline 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;
+   int ret = 0;
+
+   

[PATCH 13/26] soc: fsl: cpm1: qmc: Introduce is_tsa_64rxtx flag

2023-07-25 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 
---
 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 d02acbc1d7e1..64c3bfc16010 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 12/26] soc: fsl: cpm1: qmc: Split Tx and Rx TSA entries setup

2023-07-25 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 
---
 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 e19782808f5b..d02acbc1d7e1 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 11/26] soc: fsl: cpm1: qmc: Add support for disabling channel TSA entries

2023-07-25 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 
---
 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 2753db0b914a..e19782808f5b 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 10/26] soc: fsl: cpm1: qmc: Check available timeslots in qmc_check_chans()

2023-07-25 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 
---
 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 658aef63505e..2753db0b914a 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



[PATCH 09/26] soc: fsl: cpm1: qmc: Remove no more needed checks from qmc_check_chans()

2023-07-25 Thread Herve Codina
The newly introduced qmc_chan_setup_tsa* functions check that the
channel entries are not already used.
These checks are also performed by qmc_check_chans() and are no more
needed.

Remove them from qmc_check_chans().

Signed-off-by: Herve Codina 
---
 drivers/soc/fsl/qe/qmc.c | 20 
 1 file changed, 20 deletions(-)

diff --git a/drivers/soc/fsl/qe/qmc.c b/drivers/soc/fsl/qe/qmc.c
index a9aba9943ab7..658aef63505e 100644
--- a/drivers/soc/fsl/qe/qmc.c
+++ b/drivers/soc/fsl/qe/qmc.c
@@ -884,10 +884,7 @@ EXPORT_SYMBOL(qmc_chan_reset);
 static int qmc_check_chans(struct qmc *qmc)
 {
struct tsa_serial_info info;
-   bool is_one_table = false;
struct qmc_chan *chan;
-   u64 tx_ts_mask = 0;
-   u64 rx_ts_mask = 0;
u64 tx_ts_assigned_mask;
u64 rx_ts_assigned_mask;
int ret;
@@ -911,7 +908,6 @@ static int qmc_check_chans(struct qmc *qmc)
dev_err(qmc->dev, "Number of TSA Tx/Rx TS assigned are 
not equal\n");
return -EINVAL;
}
-   is_one_table = true;
}
 
tx_ts_assigned_mask = info.nb_tx_ts == 64 ? U64_MAX : (((u64)1) << 
info.nb_tx_ts) - 1;
@@ -922,27 +918,11 @@ static int qmc_check_chans(struct qmc *qmc)
dev_err(qmc->dev, "chan %u uses TSA unassigned Tx 
TS\n", chan->id);
return -EINVAL;
}
-   if (tx_ts_mask & chan->tx_ts_mask) {
-   dev_err(qmc->dev, "chan %u uses an already used 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);
return -EINVAL;
}
-   if (rx_ts_mask & chan->rx_ts_mask) {
-   dev_err(qmc->dev, "chan %u uses an already used Rx 
TS\n", chan->id);
-   return -EINVAL;
-   }
-
-   if (is_one_table && (chan->tx_ts_mask != chan->rx_ts_mask)) {
-   dev_err(qmc->dev, "chan %u uses different Rx and Tx 
TS\n", chan->id);
-   return -EINVAL;
-   }
-
-   tx_ts_mask |= chan->tx_ts_mask;
-   rx_ts_mask |= chan->rx_ts_mask;
}
 
return 0;
-- 
2.41.0



[PATCH 08/26] soc: fsl: cpm1: qmc: Introduce qmc_chan_setup_tsa*

2023-07-25 Thread Herve Codina
Introduce the qmc_chan_setup_tsa* functions to setup entries related
to the given channel.
Use them during QMC channels setup.

Signed-off-by: Herve Codina 
---
 drivers/soc/fsl/qe/qmc.c | 161 ++-
 1 file changed, 125 insertions(+), 36 deletions(-)

diff --git a/drivers/soc/fsl/qe/qmc.c b/drivers/soc/fsl/qe/qmc.c
index 0dbf9e33715f..a9aba9943ab7 100644
--- a/drivers/soc/fsl/qe/qmc.c
+++ b/drivers/soc/fsl/qe/qmc.c
@@ -240,6 +240,11 @@ static inline void qmc_clrbits16(void *__iomem addr, u16 
clr)
qmc_write16(addr, qmc_read16(addr) & ~clr);
 }
 
+static inline void qmc_clrsetbits16(void *__iomem addr, u16 clr, u16 set)
+{
+   qmc_write16(addr, (qmc_read16(addr) & ~clr) | set);
+}
+
 static inline void qmc_write32(void *__iomem addr, u32 val)
 {
iowrite32be(val, addr);
@@ -562,6 +567,122 @@ 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)
+{
+   unsigned int i;
+   u16 curr;
+   u16 val;
+
+   /*
+* Use a common Tx/Rx 64 entries table.
+* Tx and Rx related stuffs must be identical
+*/
+   if (chan->tx_ts_mask != chan->rx_ts_mask) {
+   dev_err(chan->qmc->dev, "chan %u uses different Rx and Tx 
TS\n", chan->id);
+   return -EINVAL;
+   }
+
+   val = QMC_TSA_VALID | QMC_TSA_MASK | QMC_TSA_CHANNEL(chan->id);
+
+   /* Check entries based on Rx stuff*/
+   for (i = 0; i < info->nb_rx_ts; i++) {
+   if (!(chan->rx_ts_mask & (((u64)1) << i)))
+   continue;
+
+   curr = qmc_read16(chan->qmc->scc_pram + QMC_GBL_TSATRX + (i * 
2));
+   if (curr & QMC_TSA_VALID && (curr & ~QMC_TSA_WRAP) != val) {
+   dev_err(chan->qmc->dev, "chan %u TxRx entry %d already 
used\n",
+   chan->id, i);
+   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, val);
+   }
+
+   return 0;
+}
+
+static int qmc_chan_setup_tsa_32rx_32tx(struct qmc_chan *chan, const struct 
tsa_serial_info *info)
+{
+   unsigned int i;
+   u16 curr;
+   u16 val;
+
+   /* Use a Tx 32 entries table and a Rx 32 entries table */
+
+   val = QMC_TSA_VALID | QMC_TSA_MASK | QMC_TSA_CHANNEL(chan->id);
+
+   /* Check entries based on Rx stuff */
+   for (i = 0; i < info->nb_rx_ts; i++) {
+   if (!(chan->rx_ts_mask & (((u64)1) << i)))
+   continue;
+
+   curr = qmc_read16(chan->qmc->scc_pram + QMC_GBL_TSATRX + (i * 
2));
+   if (curr & QMC_TSA_VALID && (curr & ~QMC_TSA_WRAP) != val) {
+   dev_err(chan->qmc->dev, "chan %u Rx entry %d already 
used\n",
+   chan->id, i);
+   return -EBUSY;
+   }
+   }
+   /* Check entries based on Tx stuff */
+   for (i = 0; i < info->nb_tx_ts; i++) {
+   if (!(chan->tx_ts_mask & (((u64)1) << i)))
+   continue;
+
+   curr = qmc_read16(chan->qmc->scc_pram + QMC_GBL_TSATTX + (i * 
2));
+   if (curr & QMC_TSA_VALID && (curr & ~QMC_TSA_WRAP) != val) {
+   dev_err(chan->qmc->dev, "chan %u Tx entry %d already 
used\n",
+   chan->id, i);
+   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, val);
+   }
+   /* Set entries based on Tx stuff */
+   for (i = 0; i < info->nb_tx_ts; i++) {
+   if (!(chan->tx_ts_mask & (((u64)1) << i)))
+   continue;
+
+   qmc_clrsetbits16(chan->qmc->scc_pram + QMC_GBL_TSATTX + (i * 2),
+~QMC_TSA_WRAP, val);
+   }
+
+   return 0;
+}
+
+static int qmc_chan_setup_tsa(struct qmc_chan *chan)
+{
+   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.
+*/
+   return ((info.nb_tx_ts > 32) || 

[PATCH 07/26] soc: fsl: cpm1: qmc: Rename qmc_setup_tsa* to qmc_init_tsa*

2023-07-25 Thread Herve Codina
qmc_setup_tsa* are called once at initialisation.
They initialize the QMC TSA table.
In order to introduce setup function later on for dynamic timeslots
management, rename the function to avoid later confusion.

Signed-off-by: Herve Codina 
---
 drivers/soc/fsl/qe/qmc.c | 16 
 1 file changed, 8 insertions(+), 8 deletions(-)

diff --git a/drivers/soc/fsl/qe/qmc.c b/drivers/soc/fsl/qe/qmc.c
index a30cff7d325a..0dbf9e33715f 100644
--- a/drivers/soc/fsl/qe/qmc.c
+++ b/drivers/soc/fsl/qe/qmc.c
@@ -919,7 +919,7 @@ static int qmc_of_parse_chans(struct qmc *qmc, struct 
device_node *np)
return qmc_check_chans(qmc);
 }
 
-static int qmc_setup_tsa_64rxtx(struct qmc *qmc, const struct tsa_serial_info 
*info)
+static int qmc_init_tsa_64rxtx(struct qmc *qmc, const struct tsa_serial_info 
*info)
 {
struct qmc_chan *chan;
unsigned int i;
@@ -961,7 +961,7 @@ static int qmc_setup_tsa_64rxtx(struct qmc *qmc, const 
struct tsa_serial_info *i
return 0;
 }
 
-static int qmc_setup_tsa_32rx_32tx(struct qmc *qmc, const struct 
tsa_serial_info *info)
+static int qmc_init_tsa_32rx_32tx(struct qmc *qmc, const struct 
tsa_serial_info *info)
 {
struct qmc_chan *chan;
unsigned int i;
@@ -1019,7 +1019,7 @@ static int qmc_setup_tsa_32rx_32tx(struct qmc *qmc, const 
struct tsa_serial_info
return 0;
 }
 
-static int qmc_setup_tsa(struct qmc *qmc)
+static int qmc_init_tsa(struct qmc *qmc)
 {
struct tsa_serial_info info;
int ret;
@@ -1030,12 +1030,12 @@ static int qmc_setup_tsa(struct qmc *qmc)
return ret;
 
/*
-* Setup one common 64 entries table or two 32 entries (one for Tx and
-* one for Tx) according to assigned TS numbers.
+* Initialize 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_setup_tsa_64rxtx(qmc, ) :
-   qmc_setup_tsa_32rx_32tx(qmc, );
+   qmc_init_tsa_64rxtx(qmc, ) :
+   qmc_init_tsa_32rx_32tx(qmc, );
 }
 
 static int qmc_setup_chan_trnsync(struct qmc *qmc, struct qmc_chan *chan)
@@ -1391,7 +1391,7 @@ static int qmc_probe(struct platform_device *pdev)
qmc_write32(qmc->scc_pram + QMC_GBL_C_MASK32, 0xDEBB20E3);
qmc_write16(qmc->scc_pram + QMC_GBL_C_MASK16, 0xF0B8);
 
-   ret = qmc_setup_tsa(qmc);
+   ret = qmc_init_tsa(qmc);
if (ret)
goto err_tsa_serial_disconnect;
 
-- 
2.41.0



[PATCH 06/26] soc: fsl: cpm1: qmc: Introduce available timeslots masks

2023-07-25 Thread Herve Codina
Available timeslots masks define timeslots available for the related
channel. These timeslots are defined by the QMC binding.

Timeslots used are initialized to available timeslots but can be a
subset of available timeslots.
This prepares the dynamic timeslots management (ie. changing timeslots
at runtime).

Signed-off-by: Herve Codina 
---
 drivers/soc/fsl/qe/qmc.c | 8 ++--
 1 file changed, 6 insertions(+), 2 deletions(-)

diff --git a/drivers/soc/fsl/qe/qmc.c b/drivers/soc/fsl/qe/qmc.c
index 1c7853a20ef9..a30cff7d325a 100644
--- a/drivers/soc/fsl/qe/qmc.c
+++ b/drivers/soc/fsl/qe/qmc.c
@@ -177,7 +177,9 @@ struct qmc_chan {
struct qmc *qmc;
void *__iomem s_param;
enum qmc_mode mode;
+   u64 tx_ts_mask_avail;
u64 tx_ts_mask;
+   u64 rx_ts_mask_avail;
u64 rx_ts_mask;
bool is_reverse_data;
 
@@ -875,7 +877,8 @@ static int qmc_of_parse_chans(struct qmc *qmc, struct 
device_node *np)
of_node_put(chan_np);
return ret;
}
-   chan->tx_ts_mask = ts_mask;
+   chan->tx_ts_mask_avail = ts_mask;
+   chan->tx_ts_mask = chan->tx_ts_mask_avail;
 
ret = of_property_read_u64(chan_np, "fsl,rx-ts-mask", _mask);
if (ret) {
@@ -884,7 +887,8 @@ static int qmc_of_parse_chans(struct qmc *qmc, struct 
device_node *np)
of_node_put(chan_np);
return ret;
}
-   chan->rx_ts_mask = ts_mask;
+   chan->rx_ts_mask_avail = ts_mask;
+   chan->rx_ts_mask = chan->rx_ts_mask_avail;
 
mode = "transparent";
ret = of_property_read_string(chan_np, "fsl,operational-mode", 
);
-- 
2.41.0



[PATCH 05/26] MAINTAINERS: Add the Freescale QMC HDLC driver entry

2023-07-25 Thread Herve Codina
After contributing the driver, add myself as the maintainer for the
Freescale QMC HDLC driver.

Signed-off-by: Herve Codina 
---
 MAINTAINERS | 8 
 1 file changed, 8 insertions(+)

diff --git a/MAINTAINERS b/MAINTAINERS
index aee340630eca..14041d90f9c8 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -8304,6 +8304,14 @@ F:   
Documentation/devicetree/bindings/soc/fsl/cpm_qe/fsl,cpm1-scc-qmc.yaml
 F: drivers/soc/fsl/qe/qmc.c
 F: include/soc/fsl/qe/qmc.h
 
+FREESCALE QUICC ENGINE QMC HDLC DRIVER
+M: Herve Codina 
+L: net...@vger.kernel.org
+L: linuxppc-dev@lists.ozlabs.org
+S: Maintained
+F: Documentation/devicetree/bindings/net/fsl,qmc-hdlc.yaml
+F: drivers/net/wan/fsl_qmc_hdlc.c
+
 FREESCALE QUICC ENGINE TSA DRIVER
 M: Herve Codina 
 L: linuxppc-dev@lists.ozlabs.org
-- 
2.41.0



[PATCH 04/26] net: wan: Add support for QMC HDLC

2023-07-25 Thread Herve Codina
The QMC HDLC driver provides support for HDLC using the QMC (QUICC
Multichannel Controller) to transfer the HDLC data.

Signed-off-by: Herve Codina 
---
 drivers/net/wan/Kconfig|  12 +
 drivers/net/wan/Makefile   |   1 +
 drivers/net/wan/fsl_qmc_hdlc.c | 422 +
 3 files changed, 435 insertions(+)
 create mode 100644 drivers/net/wan/fsl_qmc_hdlc.c

diff --git a/drivers/net/wan/Kconfig b/drivers/net/wan/Kconfig
index dcb069dde66b..8de99f4b647b 100644
--- a/drivers/net/wan/Kconfig
+++ b/drivers/net/wan/Kconfig
@@ -195,6 +195,18 @@ config FARSYNC
  To compile this driver as a module, choose M here: the
  module will be called farsync.
 
+config FSL_QMC_HDLC
+   tristate "Freescale QMC HDLC support"
+   depends on HDLC
+   depends on CPM_QMC
+   help
+ HDLC support using the Freescale QUICC Multichannel Controller (QMC).
+
+ To compile this driver as a module, choose M here: the
+ module will be called fsl_qmc_hdlc.
+
+ If unsure, say N.
+
 config FSL_UCC_HDLC
tristate "Freescale QUICC Engine HDLC support"
depends on HDLC
diff --git a/drivers/net/wan/Makefile b/drivers/net/wan/Makefile
index 5bec8fae47f8..f338f4830626 100644
--- a/drivers/net/wan/Makefile
+++ b/drivers/net/wan/Makefile
@@ -23,6 +23,7 @@ obj-$(CONFIG_WANXL)   += wanxl.o
 obj-$(CONFIG_PCI200SYN)+= pci200syn.o
 obj-$(CONFIG_PC300TOO) += pc300too.o
 obj-$(CONFIG_IXP4XX_HSS)   += ixp4xx_hss.o
+obj-$(CONFIG_FSL_QMC_HDLC) += fsl_qmc_hdlc.o
 obj-$(CONFIG_FSL_UCC_HDLC) += fsl_ucc_hdlc.o
 obj-$(CONFIG_SLIC_DS26522) += slic_ds26522.o
 
diff --git a/drivers/net/wan/fsl_qmc_hdlc.c b/drivers/net/wan/fsl_qmc_hdlc.c
new file mode 100644
index ..b4ebae963d39
--- /dev/null
+++ b/drivers/net/wan/fsl_qmc_hdlc.c
@@ -0,0 +1,422 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Freescale QMC HDLC Device Driver
+ *
+ * Copyright 2023 CS GROUP France
+ *
+ * Author: Herve Codina 
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+struct qmc_hdlc_desc {
+   struct net_device *netdev;
+   struct sk_buff *skb; /* NULL if the descriptor is not in use */
+   dma_addr_t dma_addr;
+   size_t dma_size;
+};
+
+struct qmc_hdlc {
+   struct device *dev;
+   struct qmc_chan *qmc_chan;
+   struct net_device *netdev;
+   bool is_crc32;
+   spinlock_t tx_lock; /* Protect tx descriptors */
+   struct qmc_hdlc_desc tx_descs[8];
+   unsigned int tx_out;
+   struct qmc_hdlc_desc rx_descs[4];
+};
+
+static inline struct qmc_hdlc *netdev_to_qmc_hdlc(struct net_device *netdev)
+{
+   return (struct qmc_hdlc *)dev_to_hdlc(netdev)->priv;
+}
+
+static int qmc_hdlc_recv_queue(struct qmc_hdlc *qmc_hdlc, struct qmc_hdlc_desc 
*desc, size_t size);
+
+#define QMC_HDLC_RX_ERROR_FLAGS (QMC_RX_FLAG_HDLC_OVF | \
+QMC_RX_FLAG_HDLC_UNA | \
+QMC_RX_FLAG_HDLC_ABORT | \
+QMC_RX_FLAG_HDLC_CRC)
+
+static void qmc_hcld_recv_complete(void *context, size_t length, unsigned int 
flags)
+{
+   struct qmc_hdlc_desc *desc = context;
+   struct net_device *netdev = desc->netdev;
+   struct qmc_hdlc *qmc_hdlc = netdev_to_qmc_hdlc(desc->netdev);
+   int ret;
+
+   dma_unmap_single(qmc_hdlc->dev, desc->dma_addr, desc->dma_size, 
DMA_FROM_DEVICE);
+
+   if (flags & QMC_HDLC_RX_ERROR_FLAGS) {
+   netdev->stats.rx_errors++;
+   if (flags & QMC_RX_FLAG_HDLC_OVF) /* Data overflow */
+   netdev->stats.rx_over_errors++;
+   if (flags & QMC_RX_FLAG_HDLC_UNA) /* bits received not multiple 
of 8 */
+   netdev->stats.rx_frame_errors++;
+   if (flags & QMC_RX_FLAG_HDLC_ABORT) /* Received an abort 
sequence */
+   netdev->stats.rx_frame_errors++;
+   if (flags & QMC_RX_FLAG_HDLC_CRC) /* CRC error */
+   netdev->stats.rx_crc_errors++;
+   kfree_skb(desc->skb);
+   } else {
+   netdev->stats.rx_packets++;
+   netdev->stats.rx_bytes += length;
+
+   skb_put(desc->skb, length);
+   desc->skb->protocol = hdlc_type_trans(desc->skb, netdev);
+   netif_rx(desc->skb);
+   }
+
+   /* Re-queue a transfer using the same descriptor */
+   ret = qmc_hdlc_recv_queue(qmc_hdlc, desc, desc->dma_size);
+   if (ret) {
+   dev_err(qmc_hdlc->dev, "queue recv desc failed (%d)\n", ret);
+   netdev->stats.rx_errors++;
+   }
+}
+
+static int qmc_hdlc_recv_queue(struct qmc_hdlc *qmc_hdlc, struct qmc_hdlc_desc 
*desc, size_t size)
+{
+   int ret;
+
+   desc->skb = dev_alloc_skb(size);
+   if (!desc->skb)
+   return -ENOMEM;
+
+   desc->dma_size = size;
+   desc->dma_addr 

[PATCH 03/26] dt-bindings: net: Add support for QMC HDLC

2023-07-25 Thread Herve Codina
The QMC (QUICC mutichannel controller) is a controller present in some
PowerQUICC SoC such as MPC885.
The QMC HDLC uses the QMC controller to transfer HDLC data.

Signed-off-by: Herve Codina 
---
 .../devicetree/bindings/net/fsl,qmc-hdlc.yaml | 41 +++
 1 file changed, 41 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/net/fsl,qmc-hdlc.yaml

diff --git a/Documentation/devicetree/bindings/net/fsl,qmc-hdlc.yaml 
b/Documentation/devicetree/bindings/net/fsl,qmc-hdlc.yaml
new file mode 100644
index ..8bb6f34602d9
--- /dev/null
+++ b/Documentation/devicetree/bindings/net/fsl,qmc-hdlc.yaml
@@ -0,0 +1,41 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/net/fsl,qmc-hdlc.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: QMC HDLC
+
+maintainers:
+  - Herve Codina 
+
+description: |
+  The QMC HDLC uses a QMC (QUICC Multichannel Controller) channel to transfer
+  HDLC data.
+
+properties:
+  compatible:
+const: fsl,qmc-hdlc
+
+  fsl,qmc-chan:
+$ref: /schemas/types.yaml#/definitions/phandle-array
+items:
+  - items:
+  - description: phandle to QMC node
+  - description: Channel number
+description:
+  Should be a phandle/number pair. The phandle to QMC node and the QMC
+  channel to use.
+
+required:
+  - compatible
+  - fsl,qmc-chan
+
+additionalProperties: false
+
+examples:
+  - |
+hdlc {
+compatible = "fsl,qmc-hdlc";
+fsl,qmc-chan = < 16>;
+};
-- 
2.41.0



[PATCH 02/26] soc: fsl: cpm1: qmc: Extend the API to provide Rx status

2023-07-25 Thread Herve Codina
In HDLC mode, some status flags related to the data read transfer can be
set by the hardware and need to be known by a QMC consumer for further
analysis.

Extend the API in order to provide these transfer status flags at the
read complete() call.

In TRANSPARENT mode, these flags have no meaning. Keep only one read
complete() API and update the consumers working in transparent mode.
In this case, the newly introduced flags parameter is simply unused.

Signed-off-by: Herve Codina 
---
 drivers/soc/fsl/qe/qmc.c  | 29 +
 include/soc/fsl/qe/qmc.h  | 15 ++-
 sound/soc/fsl/fsl_qmc_audio.c |  2 +-
 3 files changed, 40 insertions(+), 6 deletions(-)

diff --git a/drivers/soc/fsl/qe/qmc.c b/drivers/soc/fsl/qe/qmc.c
index a45e40776b45..1c7853a20ef9 100644
--- a/drivers/soc/fsl/qe/qmc.c
+++ b/drivers/soc/fsl/qe/qmc.c
@@ -166,7 +166,7 @@
 struct qmc_xfer_desc {
union {
void (*tx_complete)(void *context);
-   void (*rx_complete)(void *context, size_t length);
+   void (*rx_complete)(void *context, size_t length, unsigned int 
flags);
};
void *context;
 };
@@ -421,7 +421,8 @@ static void qmc_chan_write_done(struct qmc_chan *chan)
 }
 
 int qmc_chan_read_submit(struct qmc_chan *chan, dma_addr_t addr, size_t length,
-void (*complete)(void *context, size_t length), void 
*context)
+void (*complete)(void *context, size_t length, 
unsigned int flags),
+void *context)
 {
struct qmc_xfer_desc *xfer_desc;
unsigned long flags;
@@ -454,6 +455,10 @@ int qmc_chan_read_submit(struct qmc_chan *chan, dma_addr_t 
addr, size_t length,
xfer_desc->rx_complete = complete;
xfer_desc->context = context;
 
+   /* Clear previous status flags */
+   ctrl &= ~(QMC_BD_RX_L | QMC_BD_RX_F | QMC_BD_RX_LG | QMC_BD_RX_NO |
+ QMC_BD_RX_AB | QMC_BD_RX_CR);
+
/* Activate the descriptor */
ctrl |= (QMC_BD_RX_E | QMC_BD_RX_UB);
wmb(); /* Be sure to flush data before descriptor activation */
@@ -485,7 +490,7 @@ EXPORT_SYMBOL(qmc_chan_read_submit);
 
 static void qmc_chan_read_done(struct qmc_chan *chan)
 {
-   void (*complete)(void *context, size_t size);
+   void (*complete)(void *context, size_t size, unsigned int flags);
struct qmc_xfer_desc *xfer_desc;
unsigned long flags;
cbd_t *__iomem bd;
@@ -527,7 +532,23 @@ static void qmc_chan_read_done(struct qmc_chan *chan)
 
if (complete) {
spin_unlock_irqrestore(>rx_lock, flags);
-   complete(context, datalen);
+
+   /*
+* Avoid conversion between internal hardware flags and
+* the software API flags.
+* -> Be sure that the software API flags are consistent
+*with the hardware flags
+*/
+   BUILD_BUG_ON(QMC_RX_FLAG_HDLC_LAST  != QMC_BD_RX_L);
+   BUILD_BUG_ON(QMC_RX_FLAG_HDLC_FIRST != QMC_BD_RX_F);
+   BUILD_BUG_ON(QMC_RX_FLAG_HDLC_OVF   != QMC_BD_RX_LG);
+   BUILD_BUG_ON(QMC_RX_FLAG_HDLC_UNA   != QMC_BD_RX_NO);
+   BUILD_BUG_ON(QMC_RX_FLAG_HDLC_ABORT != QMC_BD_RX_AB);
+   BUILD_BUG_ON(QMC_RX_FLAG_HDLC_CRC   != QMC_BD_RX_CR);
+
+   complete(context, datalen,
+ctrl & (QMC_BD_RX_L | QMC_BD_RX_F | 
QMC_BD_RX_LG |
+QMC_BD_RX_NO | QMC_BD_RX_AB | 
QMC_BD_RX_CR));
spin_lock_irqsave(>rx_lock, flags);
}
 
diff --git a/include/soc/fsl/qe/qmc.h b/include/soc/fsl/qe/qmc.h
index 3c61a50d2ae2..6f1d6cebc9fe 100644
--- a/include/soc/fsl/qe/qmc.h
+++ b/include/soc/fsl/qe/qmc.h
@@ -9,6 +9,7 @@
 #ifndef __SOC_FSL_QMC_H__
 #define __SOC_FSL_QMC_H__
 
+#include 
 #include 
 
 struct device_node;
@@ -56,8 +57,20 @@ int qmc_chan_set_param(struct qmc_chan *chan, const struct 
qmc_chan_param *param
 int qmc_chan_write_submit(struct qmc_chan *chan, dma_addr_t addr, size_t 
length,
  void (*complete)(void *context), void *context);
 
+/* Flags available (ORed) for read complete() flags parameter in HDLC mode.
+ * No flags are available in transparent mode and the read complete() flags
+ * parameter has no meaning in transparent mode.
+ */
+#define QMC_RX_FLAG_HDLC_LAST  BIT(11) /* Last in frame */
+#define QMC_RX_FLAG_HDLC_FIRST BIT(10) /* First in frame */
+#define QMC_RX_FLAG_HDLC_OVF   BIT(5)  /* Data overflow */
+#define QMC_RX_FLAG_HDLC_UNA   BIT(4)  /* Unaligned (ie. bits received not 
multiple of 8) */
+#define QMC_RX_FLAG_HDLC_ABORT BIT(3)  /* Received an abort sequence (seven 
consecutive ones) */
+#define QMC_RX_FLAG_HDLC_CRC   BIT(2)  /* CRC error */
+
 int 

[PATCH 00/26] Add support for QMC HDLC, framer infrastruture and PEF2256 framer

2023-07-25 Thread Herve Codina
Hi,

I have a system where I need to handle an HDLC interface and some audio
data.

The HDLC data are transferred using a TDM bus on which a PEF2256
(E1/T1 framer) is present. The PEF2256 transfers data from/to the TDM
bus to/from the E1 line. This PEF2256 is connected to a PowerQUICC SoC
for the control path and the TDM is connected to the SoC (QMC component)
for the data path.

>From the QMC HDLC driver, I need to handle HDLC data using the QMC,
carrier detection using the PEF2256 (E1 line carrier) and set/get some
PEF2256 configuration.

The QMC HDLC driver considers the PEF2256 as a generic framer.
It performs operations that involve the PEF2256 through the generic
framer API.

The audio data are exchanged with the PEF2256 using a CPU DAI connected
to the TDM bus through the QMC and the PEF2256 needs to be seen as a
codec in order to be linked to the CPU DAI.
The codec handles the carrier detection using the PEF2256 and reports
the carrier state to the ALSA subsystem using the ASoC jack detection.

The codec, even if instantiated by the PEF2256 driver, considers the
PEF2256 as a generic framer.

The generic framer has:
 - 2 consumers (QMC HDLC drv and codec)
 - 1 provider (PEF2256)

So, the design is the following:
+--+   +-+
| QMC  | <- TDM -> | PEF2256 | <-> E1
 +-+|  +-+ |   | |
 | CPU DAI | <-data--> | QMC channel | |   | |
 +-+|  +-+ |   | |
+--+|  +-+ |   | |
| QMC HDLC drv | <-data--> | QMC channel | |   | |
+--+|  +-+ |   | |
 ^  +--+   | |
 |   ++ +-+| |
 +-> | framer | <-> | PEF2256 drv | <- local bus ->| |
 || | |+-+
 +-> || | |
 |   ++ |  +---+  |
 +---> | codec |  |
|  +---+  |
+-+

Further more, the TDM timeslots used by the QMC HDLC driver need to be
configured at runtime (QMC dynamic timeslots).

Several weeks ago, I sent two series related to this topic:
 - Add the Lantiq PEF2256 audio support [1]
 - RFC Add support for QMC HDLC and PHY [2]
This current series is a rework of these two series taking into account
feedbacks previously received.

In order to implement all of this, I do the following:
 1) Perform some fixes (patches 1, 2)
 2) Introduce the QMC HDLC driver (patches 3, 4, 5)
 3) Add QMC dynamic timeslot support (patches 6 - 16)
 4) Add timeslots change support in QMC HDLC (patch 17)
 5) Introduce framer infrastructure (patch 18)
 6) Add PEF2256 framer provider (patches 19, 20, 21, 22, 23)
 7) Add framer codec as a framer consumer (patch 24)
 8) Add framer support as a framer consumer in QMC HDLC (patch 25, 26)

The series contains the full story and detailed modifications.
If needed, the series can be split and/or commmits can be squashed.
Let me know.

Best regards,
Hervé

[1]: 
https://lore.kernel.org/all/20230417171601.74656-1-herve.cod...@bootlin.com/
[2]: 
https://lore.kernel.org/all/20230323103154.264546-1-herve.cod...@bootlin.com/

Herve Codina (26):
  soc: fsl: cpm1: qmc: Fix rx channel reset
  soc: fsl: cpm1: qmc: Extend the API to provide Rx status
  dt-bindings: net: Add support for QMC HDLC
  net: wan: Add support for QMC HDLC
  MAINTAINERS: Add the Freescale QMC HDLC driver entry
  soc: fsl: cpm1: qmc: Introduce available timeslots masks
  soc: fsl: cpm1: qmc: Rename qmc_setup_tsa* to qmc_init_tsa*
  soc: fsl: cpm1: qmc: Introduce qmc_chan_setup_tsa*
  soc: fsl: cpm1: qmc: Remove no more needed checks from
qmc_check_chans()
  soc: fsl: cpm1: qmc: Check available timeslots in qmc_check_chans()
  soc: fsl: cpm1: qmc: Add support for disabling channel TSA entries
  soc: fsl: cpm1: qmc: Split Tx and Rx TSA entries setup
  soc: fsl: cpm1: qmc: Introduce is_tsa_64rxtx flag
  soc: fsl: cpm1: qmc: Handle timeslot entries at channel start() and
stop()
  soc: fsl: cpm1: qmc: Remove timeslots handling from setup_chan()
  soc: fsl: cpm1: qmc: Introduce functions to change timeslots at
runtime
  wan: qmc_hdlc: Add runtime timeslots changes support
  net: wan: Add framer framework support
  dt-bindings: net: Add the Lantiq PEF2256 E1/T1/J1 framer
  mfd: core: Ensure disabled devices are skiped without aborting
  net: wan: framer: Add support for the Lantiq PEF2256 framer
  pinctrl: Add support for the Lantic PEF2256 pinmux
  MAINTAINERS: Add the Lantiq PEF2256 driver entry
  ASoC: codecs: Add support for the framer codec
  dt-bindings: net: fsl,qmc-hdlc: Add framer support
  net: wan: fsl_qmc_hdlc: Add framer support

 

[PATCH 01/26] soc: fsl: cpm1: qmc: Fix rx channel reset

2023-07-25 Thread Herve Codina
The qmc_chan_reset_rx() set the is_rx_stopped flag. This leads to an
inconsistent state in the following sequence.
qmc_chan_stop()
qmc_chan_reset()
Indeed, after the qmc_chan_reset() call, the channel must still be
stopped. Only a qmc_chan_start() call can move the channel from stopped
state to started state.

Fix the issue removing the is_rx_stopped flag setting from
qmc_chan_reset()

Fixes: 3178d58e0b97 ("soc: fsl: cpm1: Add support for QMC")
Signed-off-by: Herve Codina 
---
 drivers/soc/fsl/qe/qmc.c | 1 -
 1 file changed, 1 deletion(-)

diff --git a/drivers/soc/fsl/qe/qmc.c b/drivers/soc/fsl/qe/qmc.c
index b3c292c9a14e..a45e40776b45 100644
--- a/drivers/soc/fsl/qe/qmc.c
+++ b/drivers/soc/fsl/qe/qmc.c
@@ -685,7 +685,6 @@ static void qmc_chan_reset_rx(struct qmc_chan *chan)
qmc_read16(chan->s_param + QMC_SPE_RBASE));
 
chan->rx_pending = 0;
-   chan->is_rx_stopped = false;
 
spin_unlock_irqrestore(>rx_lock, flags);
 }
-- 
2.41.0



[PATCH 26/26] net: wan: fsl_qmc_hdlc: Add framer support

2023-07-25 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 
---
 drivers/net/wan/fsl_qmc_hdlc.c | 238 -
 1 file changed, 234 insertions(+), 4 deletions(-)

diff --git a/drivers/net/wan/fsl_qmc_hdlc.c b/drivers/net/wan/fsl_qmc_hdlc.c
index 7eb0ebaa30e7..a873071fa5ca 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 (struct qmc_hdlc *)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 ret;
+
+

[PATCH 25/26] dt-bindings: net: fsl,qmc-hdlc: Add framer support

2023-07-25 Thread Herve Codina
A framer can be connected to the QMC HDLC.
If present, this framer is the interface between the TDM used by the QMC
HDLC and the E1/T1 line.
The QMC HDLC can use this framer to get information about the line and
configure the line.

Add an optional framer property to reference the framer itself.

Signed-off-by: Herve Codina 
---
 Documentation/devicetree/bindings/net/fsl,qmc-hdlc.yaml | 5 +
 1 file changed, 5 insertions(+)

diff --git a/Documentation/devicetree/bindings/net/fsl,qmc-hdlc.yaml 
b/Documentation/devicetree/bindings/net/fsl,qmc-hdlc.yaml
index 8bb6f34602d9..bf29863ab419 100644
--- a/Documentation/devicetree/bindings/net/fsl,qmc-hdlc.yaml
+++ b/Documentation/devicetree/bindings/net/fsl,qmc-hdlc.yaml
@@ -27,6 +27,11 @@ properties:
   Should be a phandle/number pair. The phandle to QMC node and the QMC
   channel to use.
 
+  framer:
+$ref: /schemas/types.yaml#/definitions/phandle
+description:
+  phandle to the framer node
+
 required:
   - compatible
   - fsl,qmc-chan
-- 
2.41.0



[PATCH 24/26] ASoC: codecs: Add support for the framer codec

2023-07-25 Thread Herve Codina
The framer codec interracts 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 
---
 sound/soc/codecs/Kconfig|  15 ++
 sound/soc/codecs/Makefile   |   2 +
 sound/soc/codecs/framer-codec.c | 423 
 3 files changed, 440 insertions(+)
 create mode 100644 sound/soc/codecs/framer-codec.c

diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig
index f99203ef9b03..8bd534c94893 100644
--- a/sound/soc/codecs/Kconfig
+++ b/sound/soc/codecs/Kconfig
@@ -110,6 +110,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
@@ -1043,6 +1044,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 with 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 32dcc6de58bd..54667274a0f6 100644
--- a/sound/soc/codecs/Makefile
+++ b/sound/soc/codecs/Makefile
@@ -116,6 +116,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
@@ -499,6 +500,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 ..0db82082620b
--- /dev/null
+++ b/sound/soc/codecs/framer-codec.c
@@ -0,0 +1,423 @@
+// 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 much tx slots defined (mask = 0x%x) 
support 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 much rx slots defined (mask = 0x%x) 
support 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 snd_interval *c = 

Re: [PATCH v4 3/5] arch: Register fchmodat2, usually as syscall 452

2023-07-25 Thread Geert Uytterhoeven
On Tue, Jul 11, 2023 at 6:25 PM Alexey Gladkov  wrote:
> From: Palmer Dabbelt 
>
> This registers the new fchmodat2 syscall in most places as nuber 452,
> with alpha being the exception where it's 562.  I found all these sites
> by grepping for fspick, which I assume has found me everything.
>
> Signed-off-by: Palmer Dabbelt 
> Signed-off-by: Alexey Gladkov 

>  arch/m68k/kernel/syscalls/syscall.tbl   | 1 +

Acked-by: Geert Uytterhoeven 

Gr{oetje,eeting}s,

Geert

-- 
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- ge...@linux-m68k.org

In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
-- Linus Torvalds


Re: [PATCH v2] tty: Explicitly include correct DT includes

2023-07-25 Thread Uwe Kleine-König
Hello Rob,

On Mon, Jul 24, 2023 at 02:54:38PM -0600, Rob Herring wrote:
> The DT of_device.h and of_platform.h date back to the separate
> of_platform_bus_type before it as merged into the regular platform bus.
> As part of that merge prepping Arm DT support 13 years ago, they
> "temporarily" include each other. They also include platform_device.h
> and of.h. As a result, there's a pretty much random mix of those include
> files used throughout the tree. In order to detangle these headers and
> replace the implicit includes with struct declarations, users need to
> explicitly include the correct includes.
> 
> Signed-off-by: Rob Herring 

Acked-by: Uwe Kleine-König  # for imx

Thanks for your efforts!

Best regards
Uwe

-- 
Pengutronix e.K.   | Uwe Kleine-König|
Industrial Linux Solutions | https://www.pengutronix.de/ |


signature.asc
Description: PGP signature


[RFC PATCH v2 7/7] ASoC: fsl_easrc: register m2m platform device

2023-07-25 Thread Shengjiu Wang
Register m2m platform device,that user can
use M2M feature.

Signed-off-by: Shengjiu Wang 
---
 sound/soc/fsl/fsl_easrc.c | 13 +
 1 file changed, 13 insertions(+)

diff --git a/sound/soc/fsl/fsl_easrc.c b/sound/soc/fsl/fsl_easrc.c
index b735b24badc2..b5befefa8fbe 100644
--- a/sound/soc/fsl/fsl_easrc.c
+++ b/sound/soc/fsl/fsl_easrc.c
@@ -2074,6 +2074,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;
@@ -2190,11 +2191,23 @@ static int fsl_easrc_probe(struct platform_device *pdev)
return ret;
}
 
+   m2m_pdata.asrc = easrc;
+   easrc->m2m_pdev = platform_device_register_data(>dev,
+   "fsl_asrc_m2m",
+   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 v2 6/7] ASoC: fsl_asrc: register m2m platform device

2023-07-25 Thread Shengjiu Wang
Register m2m platform device, that user can
use M2M feature.

Signed-off-by: Shengjiu Wang 
---
 include/sound/fsl_asrc_common.h |  2 ++
 sound/soc/fsl/fsl_asrc.c| 12 
 2 files changed, 14 insertions(+)

diff --git a/include/sound/fsl_asrc_common.h b/include/sound/fsl_asrc_common.h
index 191302711ea6..0f3effa42308 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
@@ -102,6 +103,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;
diff --git a/sound/soc/fsl/fsl_asrc.c b/sound/soc/fsl/fsl_asrc.c
index 30190ccb74e7..0d1dfa30271e 100644
--- a/sound/soc/fsl/fsl_asrc.c
+++ b/sound/soc/fsl/fsl_asrc.c
@@ -1198,6 +1198,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;
@@ -1380,6 +1381,12 @@ static int fsl_asrc_probe(struct platform_device *pdev)
goto err_pm_get_sync;
}
 
+   m2m_pdata.asrc = asrc;
+   asrc->m2m_pdev = platform_device_register_data(>dev,
+  "fsl_asrc_m2m",
+  PLATFORM_DEVID_AUTO,
+  _pdata,
+  sizeof(m2m_pdata));
return 0;
 
 err_pm_get_sync:
@@ -1392,6 +1399,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 v2 5/7] media: imx: fsl_asrc: Add memory to memory driver

2023-07-25 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/fsl_asrc_m2m.c | 962 ++
 include/sound/fsl_asrc_common.h   |   9 +
 4 files changed, 984 insertions(+)
 create mode 100644 drivers/media/platform/nxp/fsl_asrc_m2m.c

diff --git a/drivers/media/platform/nxp/Kconfig 
b/drivers/media/platform/nxp/Kconfig
index a0ca6b297fb8..359f11fe2a80 100644
--- a/drivers/media/platform/nxp/Kconfig
+++ b/drivers/media/platform/nxp/Kconfig
@@ -56,3 +56,15 @@ config VIDEO_MX2_EMMAPRP
 
 source "drivers/media/platform/nxp/dw100/Kconfig"
 source "drivers/media/platform/nxp/imx-jpeg/Kconfig"
+
+config VIDEO_FSL_ASRC_M2M
+   tristate "MXP 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 completement 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 b8e672b75fed..db565e39f7d5 100644
--- a/drivers/media/platform/nxp/Makefile
+++ b/drivers/media/platform/nxp/Makefile
@@ -8,3 +8,4 @@ obj-$(CONFIG_VIDEO_IMX7_CSI) += imx7-media-csi.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_FSL_ASRC_M2M) += fsl_asrc_m2m.o
diff --git a/drivers/media/platform/nxp/fsl_asrc_m2m.c 
b/drivers/media/platform/nxp/fsl_asrc_m2m.c
new file mode 100644
index ..67936915857b
--- /dev/null
+++ b/drivers/media/platform/nxp/fsl_asrc_m2m.c
@@ -0,0 +1,962 @@
+// 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) ? fsl_asrc_input_dma_callback \
+   : fsl_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 fsl_asrc_pair_m2m {
+   struct fsl_asrc_pair *pair;
+   struct fsl_asrc_m2m *m2m;
+   struct v4l2_fh fh;
+   struct v4l2_ctrl_handler ctrl_handler;
+};
+
+struct fsl_asrc_m2m {
+   struct fsl_asrc *asrc;
+   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 inline struct fsl_asrc_pair_m2m *fsl_asrc_m2m_fh_to_ctx(struct v4l2_fh 
*fh)
+{
+   return container_of(fh, struct fsl_asrc_pair_m2m, fh);
+}
+
+/**
+ * fsl_asrc_read_last_fifo: read all the remaining data from FIFO
+ * @pair: Structure pointer of fsl_asrc_pair
+ * @dma_vaddr: virtual address of capture buffer
+ * @length: payload length of capture buffer
+ */
+static void fsl_asrc_read_last_fifo(struct fsl_asrc_pair *pair, void 
*dma_vaddr, u32 *length)
+{
+   struct fsl_asrc *asrc = pair->asrc;
+   enum asrc_pair_index index = pair->index;
+   u32 i, reg, size, t_size = 0, width;
+   u32 *reg32 = NULL;
+   u16 *reg16 = NULL;
+   u8  *reg24 = NULL;
+
+   width = snd_pcm_format_physical_width(pair->sample_format[V4L_CAP]);
+   if (width == 32)
+   reg32 = dma_vaddr + *length;
+   else if (width == 16)
+   reg16 = dma_vaddr + *length;
+   else
+   reg24 = dma_vaddr + *length;
+retry:
+   size = asrc->get_output_fifo_size(pair);
+   if (size + *length > ASRC_M2M_BUFFER_SIZE)
+   goto end;
+
+   for (i = 0; i < size * pair->channels; i++) {
+   regmap_read(asrc->regmap, asrc->get_fifo_addr(OUT, index), 
);
+   if (reg32) {
+   *(reg32) = reg;
+   reg32++;
+   } else if (reg16) {
+   *(reg16) = (u16)reg;
+   reg16++;
+   } else {
+   *reg24++ = (u8)reg;
+   *reg24++ = (u8)(reg >> 8);
+   *reg24++ = (u8)(reg >> 16);
+   }
+   }
+  

[RFC PATCH v2 4/7] media: v4l2: Add audio capture and output support

2023-07-25 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/audioX".

Signed-off-by: Shengjiu Wang 
---
 .../media/common/videobuf2/videobuf2-v4l2.c   |  4 ++
 drivers/media/v4l2-core/v4l2-dev.c| 17 ++
 drivers/media/v4l2-core/v4l2-ioctl.c  | 52 +++
 include/media/v4l2-dev.h  |  2 +
 include/media/v4l2-ioctl.h| 34 
 include/uapi/linux/videodev2.h| 19 +++
 6 files changed, 128 insertions(+)

diff --git a/drivers/media/common/videobuf2/videobuf2-v4l2.c 
b/drivers/media/common/videobuf2/videobuf2-v4l2.c
index c7a54d82a55e..12f2be2773a2 100644
--- a/drivers/media/common/videobuf2/videobuf2-v4l2.c
+++ b/drivers/media/common/videobuf2/videobuf2-v4l2.c
@@ -785,6 +785,10 @@ int vb2_create_bufs(struct vb2_queue *q, struct 
v4l2_create_buffers *create)
case V4L2_BUF_TYPE_META_OUTPUT:
requested_sizes[0] = f->fmt.meta.buffersize;
break;
+   case V4L2_BUF_TYPE_AUDIO_CAPTURE:
+   case V4L2_BUF_TYPE_AUDIO_OUTPUT:
+   requested_sizes[0] = f->fmt.audio.buffersize;
+   break;
default:
return -EINVAL;
}
diff --git a/drivers/media/v4l2-core/v4l2-dev.c 
b/drivers/media/v4l2-core/v4l2-dev.c
index f81279492682..67484f4c6eaf 100644
--- a/drivers/media/v4l2-core/v4l2-dev.c
+++ b/drivers/media/v4l2-core/v4l2-dev.c
@@ -553,6 +553,7 @@ static void determine_valid_ioctls(struct video_device 
*vdev)
bool is_tch = vdev->vfl_type == VFL_TYPE_TOUCH;
bool is_meta = vdev->vfl_type == VFL_TYPE_VIDEO &&
   (vdev->device_caps & meta_caps);
+   bool is_audio = vdev->vfl_type == VFL_TYPE_AUDIO;
bool is_rx = vdev->vfl_dir != VFL_DIR_TX;
bool is_tx = vdev->vfl_dir != VFL_DIR_RX;
bool is_io_mc = vdev->device_caps & V4L2_CAP_IO_MC;
@@ -664,6 +665,19 @@ static void determine_valid_ioctls(struct video_device 
*vdev)
SET_VALID_IOCTL(ops, VIDIOC_S_FMT, vidioc_s_fmt_meta_out);
SET_VALID_IOCTL(ops, VIDIOC_TRY_FMT, vidioc_try_fmt_meta_out);
}
+   if (is_audio && is_rx) {
+   /* audio capture specific ioctls */
+   SET_VALID_IOCTL(ops, VIDIOC_ENUM_FMT, 
vidioc_enum_fmt_audio_cap);
+   SET_VALID_IOCTL(ops, VIDIOC_G_FMT, vidioc_g_fmt_audio_cap);
+   SET_VALID_IOCTL(ops, VIDIOC_S_FMT, vidioc_s_fmt_audio_cap);
+   SET_VALID_IOCTL(ops, VIDIOC_TRY_FMT, vidioc_try_fmt_audio_cap);
+   } else if (is_audio && is_tx) {
+   /* audio output specific ioctls */
+   SET_VALID_IOCTL(ops, VIDIOC_ENUM_FMT, 
vidioc_enum_fmt_audio_out);
+   SET_VALID_IOCTL(ops, VIDIOC_G_FMT, vidioc_g_fmt_audio_out);
+   SET_VALID_IOCTL(ops, VIDIOC_S_FMT, vidioc_s_fmt_audio_out);
+   SET_VALID_IOCTL(ops, VIDIOC_TRY_FMT, vidioc_try_fmt_audio_out);
+   }
if (is_vbi) {
/* vbi specific ioctls */
if ((is_rx && (ops->vidioc_g_fmt_vbi_cap ||
@@ -927,6 +941,9 @@ int __video_register_device(struct video_device *vdev,
case VFL_TYPE_TOUCH:
name_base = "v4l-touch";
break;
+   case VFL_TYPE_AUDIO:
+   name_base = "audio";
+   break;
default:
pr_err("%s called with unknown type: %d\n",
   __func__, type);
diff --git a/drivers/media/v4l2-core/v4l2-ioctl.c 
b/drivers/media/v4l2-core/v4l2-ioctl.c
index 01ba27f2ef87..aa9d872bba8d 100644
--- a/drivers/media/v4l2-core/v4l2-ioctl.c
+++ b/drivers/media/v4l2-core/v4l2-ioctl.c
@@ -188,6 +188,8 @@ const char *v4l2_type_names[] = {
[V4L2_BUF_TYPE_SDR_OUTPUT] = "sdr-out",
[V4L2_BUF_TYPE_META_CAPTURE]   = "meta-cap",
[V4L2_BUF_TYPE_META_OUTPUT]= "meta-out",
+   [V4L2_BUF_TYPE_AUDIO_CAPTURE]  = "audio-cap",
+   [V4L2_BUF_TYPE_AUDIO_OUTPUT]   = "audio-out",
 };
 EXPORT_SYMBOL(v4l2_type_names);
 
@@ -276,6 +278,7 @@ static void v4l_print_format(const void *arg, bool 
write_only)
const struct v4l2_sliced_vbi_format *sliced;
const struct v4l2_window *win;
const struct v4l2_meta_format *meta;
+   const struct v4l2_audio_format *audio;
u32 pixelformat;
u32 planes;
unsigned i;
@@ -346,6 +349,12 @@ static void v4l_print_format(const void *arg, bool 
write_only)
pr_cont(", dataformat=%p4cc, buffersize=%u\n",
, meta->buffersize);
break;
+   case V4L2_BUF_TYPE_AUDIO_CAPTURE:
+   case V4L2_BUF_TYPE_AUDIO_OUTPUT:
+   audio = >fmt.audio;
+   

[RFC PATCH v2 3/7] ASoC: fsl_asrc: move fsl_asrc_common.h to include/sound

2023-07-25 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 v2 2/7] ASoC: fsl_easrc: define functions for memory to memory usage

2023-07-25 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 | 214 ++
 sound/soc/fsl/fsl_easrc.h |   6 ++
 2 files changed, 220 insertions(+)

diff --git a/sound/soc/fsl/fsl_easrc.c b/sound/soc/fsl/fsl_easrc.c
index 670cbdb361b6..b735b24badc2 100644
--- a/sound/soc/fsl/fsl_easrc.c
+++ b/sound/soc/fsl/fsl_easrc.c
@@ -1861,6 +1861,210 @@ 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;
+}
+
+static int fsl_easrc_m2m_check_format(u8 dir, u32 rate, u32 channels, u32 
format)
+{
+   u64 support_format = FSL_EASRC_FORMATS;
+
+   if (channels < 1 || channels > 32)
+   return -EINVAL;
+
+   if (rate < 8000 || rate > 768000)
+   return -EINVAL;
+
+   if (dir == OUT)
+   support_format |= SNDRV_PCM_FMTBIT_IEC958_SUBFRAME_LE;
+
+   if (!(1 << format & support_format))
+   return -EINVAL;
+
+   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 

[RFC PATCH v2 1/7] ASoC: fsl_asrc: define functions for memory to memory usage

2023-07-25 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
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
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| 138 
 sound/soc/fsl/fsl_asrc.h|   2 +
 sound/soc/fsl/fsl_asrc_common.h |  37 +
 3 files changed, 177 insertions(+)

diff --git a/sound/soc/fsl/fsl_asrc.c b/sound/soc/fsl/fsl_asrc.c
index adb8a59de2bd..30190ccb74e7 100644
--- a/sound/soc/fsl/fsl_asrc.c
+++ b/sound/soc/fsl/fsl_asrc.c
@@ -1063,6 +1063,135 @@ 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;
+}
+
+static int fsl_asrc_m2m_check_format(u8 dir, u32 rate, u32 channels, u32 
format)
+{
+   u64 support_format = FSL_ASRC_FORMATS;
+
+   if (channels < 1 || channels > 10)
+   return -EINVAL;
+
+   if (rate < 5512 || rate > 192000)
+   return -EINVAL;
+
+   if (dir == IN)
+   support_format |= SNDRV_PCM_FMTBIT_S8;
+
+   if (!(1 << format & support_format))
+   return -EINVAL;
+
+   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 

[RFC PATCH v2 0/7] Add audio support in v4l2 framework

2023-07-25 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/audioX".

And add memory to memory support for two kinds of i.MX ASRC
module

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 (7):
  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
  media: v4l2: Add audio capture and output support
  media: imx: fsl_asrc: Add memory to memory driver
  ASoC: fsl_asrc: register m2m platform device
  ASoC: fsl_easrc: register m2m platform device

 .../media/common/videobuf2/videobuf2-v4l2.c   |   4 +
 drivers/media/platform/nxp/Kconfig|  12 +
 drivers/media/platform/nxp/Makefile   |   1 +
 drivers/media/platform/nxp/fsl_asrc_m2m.c | 962 ++
 drivers/media/v4l2-core/v4l2-dev.c|  17 +
 drivers/media/v4l2-core/v4l2-ioctl.c  |  52 +
 include/media/v4l2-dev.h  |   2 +
 include/media/v4l2-ioctl.h|  34 +
 .../fsl => include/sound}/fsl_asrc_common.h   |  48 +
 include/uapi/linux/videodev2.h|  19 +
 sound/soc/fsl/fsl_asrc.c  | 150 +++
 sound/soc/fsl/fsl_asrc.h  |   4 +-
 sound/soc/fsl/fsl_asrc_dma.c  |   2 +-
 sound/soc/fsl/fsl_easrc.c | 227 +
 sound/soc/fsl/fsl_easrc.h |   8 +-
 15 files changed, 1539 insertions(+), 3 deletions(-)
 create mode 100644 drivers/media/platform/nxp/fsl_asrc_m2m.c
 rename {sound/soc/fsl => include/sound}/fsl_asrc_common.h (63%)

-- 
2.34.1



[PATCH 1/1] perf tests task_analyzer: Check perf build options for libtraceevent support

2023-07-25 Thread Aditya Gupta
Currently we depend on output of 'perf record -e "sched:sched_switch"', to
check whether perf was built with libtraceevent support.

Instead, a more straightforward approach can be to check the build options,
using 'perf version --build-options', to check for libtraceevent support.

When perf is compiled WITHOUT libtraceevent ('make NO_LIBTRACEEVENT=1'),
'perf version --build-options' outputs (output trimmed):

 ...
 libtraceevent: [ OFF ]  # HAVE_LIBTRACEEVENT
 ...

While, when perf is compiled WITH libtraceevent,

'perf version --build-options' outputs:

...
 libtraceevent: [ on ]  # HAVE_LIBTRACEEVENT
 ...

Suggested-by: Ian Rogers 
Signed-off-by: Aditya Gupta 
---

 tools/perf/tests/shell/test_task_analyzer.sh | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/tools/perf/tests/shell/test_task_analyzer.sh 
b/tools/perf/tests/shell/test_task_analyzer.sh
index 0095abbe20ca..a28d784987b4 100755
--- a/tools/perf/tests/shell/test_task_analyzer.sh
+++ b/tools/perf/tests/shell/test_task_analyzer.sh
@@ -52,7 +52,7 @@ find_str_or_fail() {
 
 # check if perf is compiled with libtraceevent support
 skip_no_probe_record_support() {
-   perf record -e "sched:sched_switch" -a -- sleep 1 2>&1 | grep 
"libtraceevent is necessary for tracepoint support" && return 2
+   perf version --build-options | grep HAVE_LIBTRACEEVENT | grep -q OFF && 
return 2
return 0
 }
 
-- 
2.41.0