Re: [kvm-unit-tests PATCH v2 04/13] treewide: lib/stack: Make base_address arch specific
On Wed Mar 6, 2024 at 3:09 AM AEST, Andrew Jones wrote: > Calculating the offset of an address is image specific, which is > architecture specific. Until now, all architectures and architecture > configurations which select CONFIG_RELOC were able to subtract > _etext, but the EFI configuration of riscv cannot (it must subtract > ImageBase). Make this function weak, such that an architecture may > override it when necessary, to accommodate the image layout. Then, > immediately supply the riscv override. > Thanks for making these changes. Looks good. For the generic parts, Reviewed-by: Nicholas Piggin Thanks, Nick > Signed-off-by: Andrew Jones > --- > lib/riscv/stack.c | 18 ++ > lib/stack.c | 8 > lib/stack.h | 2 ++ > 3 files changed, 24 insertions(+), 4 deletions(-) > > diff --git a/lib/riscv/stack.c b/lib/riscv/stack.c > index d865594b9671..2cd7f012738b 100644 > --- a/lib/riscv/stack.c > +++ b/lib/riscv/stack.c > @@ -2,6 +2,24 @@ > #include > #include > > +#ifdef CONFIG_RELOC > +extern char ImageBase, _text, _etext; > + > +bool arch_base_address(const void *rebased_addr, unsigned long *addr) > +{ > + unsigned long ra = (unsigned long)rebased_addr; > + unsigned long base = (unsigned long) > + unsigned long start = (unsigned long)&_text; > + unsigned long end = (unsigned long)&_etext; > + > + if (ra < start || ra >= end) > + return false; > + > + *addr = ra - base; > + return true; > +} > +#endif > + > int arch_backtrace_frame(const void *frame, const void **return_addrs, >int max_depth, bool current_frame) > { > diff --git a/lib/stack.c b/lib/stack.c > index dd6bfa8dac6e..086fec544a81 100644 > --- a/lib/stack.c > +++ b/lib/stack.c > @@ -14,7 +14,7 @@ > #ifdef CONFIG_RELOC > extern char _text, _etext; > > -static bool base_address(const void *rebased_addr, unsigned long *addr) > +bool __attribute__((weak)) arch_base_address(const void *rebased_addr, > unsigned long *addr) > { > unsigned long ra = (unsigned long)rebased_addr; > unsigned long start = (unsigned long)&_text; > @@ -27,7 +27,7 @@ static bool base_address(const void *rebased_addr, unsigned > long *addr) > return true; > } > #else > -static bool base_address(const void *rebased_addr, unsigned long *addr) > +bool __attribute__((weak)) arch_base_address(const void *rebased_addr, > unsigned long *addr) > { > *addr = (unsigned long)rebased_addr; > return true; > @@ -45,13 +45,13 @@ static void print_stack(const void **return_addrs, int > depth, > /* @addr indicates a non-return address, as expected by the stack >* pretty printer script. */ > if (depth > 0 && !top_is_return_address) { > - if (base_address(return_addrs[0], )) > + if (arch_base_address(return_addrs[0], )) > printf(" @%lx", addr); > i++; > } > > for (; i < depth; i++) { > - if (base_address(return_addrs[i], )) > + if (arch_base_address(return_addrs[i], )) > printf(" %lx", addr); > } > printf("\n"); > diff --git a/lib/stack.h b/lib/stack.h > index 6edc84344b51..df076d94bf8f 100644 > --- a/lib/stack.h > +++ b/lib/stack.h > @@ -34,4 +34,6 @@ static inline int backtrace_frame(const void *frame, const > void **return_addrs, > } > #endif > > +bool __attribute__((weak)) arch_base_address(const void *rebased_addr, > unsigned long *addr); > + > #endif
Re: [PATCH v5 02/10] locking/mutex: introduce devm_mutex_init
Le 12/03/2024 à 02:10, Waiman Long a écrit : > On 3/11/24 19:47, George Stark wrote: >> Hello Waiman, Marek >> >> Thanks for the review. >> >> I've never used lockdep for debug but it seems preferable to >> keep that feature working. It could be look like this: >> >> diff --git a/include/linux/mutex.h b/include/linux/mutex.h >> index f7611c092db7..574f6de6084d 100644 >> --- a/include/linux/mutex.h >> +++ b/include/linux/mutex.h >> @@ -22,6 +22,8 @@ >> #include >> #include >> >> +struct device; >> + >> #ifdef CONFIG_DEBUG_LOCK_ALLOC >> # define __DEP_MAP_MUTEX_INITIALIZER(lockname) \ >> , .dep_map = { \ >> @@ -115,10 +117,31 @@ do { \ >> >> #ifdef CONFIG_DEBUG_MUTEXES >> >> +int debug_devm_mutex_init(struct device *dev, struct mutex *lock); >> + >> +#define devm_mutex_init(dev, mutex) \ >> +({ \ >> + int ret; \ >> + mutex_init(mutex); \ >> + ret = debug_devm_mutex_init(dev, mutex); \ >> + ret; \ >> +}) > > The int ret variable is not needed. The macro can just end with > debug_devm_mutex_init(). > > >> + >> void mutex_destroy(struct mutex *lock); >> >> #else >> >> +/* >> +* When CONFIG_DEBUG_MUTEXES is off mutex_destroy is just a nop so >> +* there's no really need to register it in devm subsystem. > "no really need"? >> +*/ >> +#define devm_mutex_init(dev, mutex) \ >> +({ \ >> + typecheck(struct device *, dev); \ >> + mutex_init(mutex); \ >> + 0; \ >> +}) > > Do we need a typecheck() here? Compilation will fail with > CONFIG_DEBUG_MUTEXES if dev is not a device pointer. I guess the idea is to have it fail _also_ when CONFIG_DEBUG_MUTEXES is not selected, in order to discover errors as soon as possible. > > >> + >> static inline void mutex_destroy(struct mutex *lock) {} >> >> #endif >> diff --git a/kernel/locking/mutex-debug.c b/kernel/locking/mutex-debug.c >> index bc8abb8549d2..967a5367c79a 100644 >> --- a/kernel/locking/mutex-debug.c >> +++ b/kernel/locking/mutex-debug.c >> @@ -19,6 +19,7 @@ >> #include >> #include >> #include >> +#include >> >> #include "mutex.h" >> >> @@ -89,6 +90,16 @@ void debug_mutex_init(struct mutex *lock, const >> char *name, >> lock->magic = lock; >> } >> >> +static void devm_mutex_release(void *res) >> +{ >> + mutex_destroy(res); >> +} >> + >> +int debug_devm_mutex_init(struct device *dev, struct mutex *lock) >> +{ >> + return devm_add_action_or_reset(dev, devm_mutex_release, lock); >> +} >> + >> /*** >> * mutex_destroy - mark a mutex unusable >> * @lock: the mutex to be destroyed >
Re: [PATCH v5 02/10] locking/mutex: introduce devm_mutex_init
Le 12/03/2024 à 01:01, George Stark a écrit : > [Vous ne recevez pas souvent de courriers de gnst...@salutedevices.com. > Découvrez pourquoi ceci est important à > https://aka.ms/LearnAboutSenderIdentification ] > > Hello Andy > > On 3/7/24 13:34, Andy Shevchenko wrote: >> On Thu, Mar 7, 2024 at 4:40 AM George Stark >> wrote: >>> >>> Using of devm API leads to a certain order of releasing resources. >>> So all dependent resources which are not devm-wrapped should be deleted >>> with respect to devm-release order. Mutex is one of such objects that >>> often is bound to other resources and has no own devm wrapping. >>> Since mutex_destroy() actually does nothing in non-debug builds >>> frequently calling mutex_destroy() is just ignored which is safe for now >>> but wrong formally and can lead to a problem if mutex_destroy() will be >>> extended so introduce devm_mutex_init() >>> >>> Signed-off-by: George Stark >>> Signed-off-by: Christophe Leroy >> >>> Hello Christophe. Hope you don't mind I put you SoB tag because you >>> helped alot >>> to make this patch happen. >> >> You also need to figure out who should be the author of the patch and >> probably add a (missing) Co-developed-by. After all you should also >> follow the correct order of SoBs. >> > > Thanks for the review. > I explained in the other letter as I see it. So I'd leave myself > as author and add appropriate tag with Christophe's name. > BTW what do you mean by correct SoB order? > Is it alphabetical order or order of importance? > The correct order is to first have the Author's SoB.
Re: [PATCH v8 1/3] powerpc: make fadump resilient with memory add/remove events
Hello Hari, On 11/03/24 14:08, Hari Bathini wrote: On 17/02/24 12:50 pm, Sourabh Jain wrote: Due to changes in memory resources caused by either memory hotplug or online/offline events, the elfcorehdr, which describes the CPUs and memory of the crashed kernel to the kernel that collects the dump (known as second/fadump kernel), becomes outdated. Consequently, attempting dump collection with an outdated elfcorehdr can lead to failed or inaccurate dump collection. Memory hotplug or online/offline events is referred as memory add/remove events in reset of the commit message. The current solution to address the aforementioned issue is as follows: Monitor memory add/remove events in userspace using udev rules, and re-register fadump whenever there are changes in memory resources. This leads to the creation of a new elfcorehdr with updated system memory information. There are several notable issues associated with re-registering fadump for every memory add/remove events. 1. Bulk memory add/remove events with udev-based fadump re-registration can lead to race conditions and, more importantly, it creates a wide window during which fadump is inactive until all memory add/remove events are settled. 2. Re-registering fadump for every memory add/remove event is inefficient. 3. The memory for elfcorehdr is allocated based on the memblock regions available during early boot and remains fixed thereafter. However, if elfcorehdr is later recreated with additional memblock regions, its size will increase, potentially leading to memory corruption. Address the aforementioned challenges by shifting the creation of elfcorehdr from the first kernel (also referred as the crashed kernel), where it was created and frequently recreated for every memory add/remove event, to the fadump kernel. As a result, the elfcorehdr only needs to be created once, thus eliminating the necessity to re-register fadump during memory add/remove events. At present, the first kernel is responsible for preparing the fadump header and storing it in the fadump reserved area. The fadump header includes the start address of the elfcorehdr, crashing CPU details, and other relevant information. In the event of a crash in the first kernel, the second/fadump boots and accesses the fadump header prepared by the first kernel. It then performs the following steps in a platform-specific function [rtas|opal]_fadump_process: 1. Sanity check for fadump header 2. Update CPU notes in elfcorehdr Along with the above, update the setup_fadump()/fadump.c to create elfcorehdr and set its address to the global variable elfcorehdr_addr for the vmcore module to process it in the second/fadump kernel. Section below outlines the information required to create the elfcorehdr and the changes made to make it available to the fadump kernel if it's not already. To create elfcorehdr, the following crashed kernel information is required: CPU notes, vmcoreinfo, and memory ranges. At present, the CPU notes are already prepared in the fadump kernel, so no changes are needed in that regard. The fadump kernel has access to all crashed kernel memory regions, including boot memory regions that are relocated by firmware to fadump reserved areas, so no changes for that either. However, it is necessary to add new members to the fadump header, i.e., the 'fadump_crash_info_header' structure, in order to pass the crashed kernel's vmcoreinfo address and its size to fadump kernel. In addition to the vmcoreinfo address and size, there are a few other attributes also added to the fadump_crash_info_header structure. 1. version: It stores the fadump header version, which is currently set to 1. This provides flexibility to update the fadump crash info header in the future without changing the magic number. For each change in the fadump header, the version will be increased. This will help the updated kernel determine how to handle kernel dumps from older kernels. The magic number remains relevant for checking fadump header corruption. 2. pt_regs_sz/cpu_mask_sz: Store size of pt_regs and cpu_mask structure of first kernel. These attributes are used to prevent dump processing if the sizes of pt_regs or cpu_mask structure differ between the first and fadump kernels. Note: if either first/crashed kernel or second/fadump kernel do not have the changes introduced here then kernel fail to collect the dump and prints relevant error message on the console. Signed-off-by: Sourabh Jain Cc: Aditya Gupta Cc: Aneesh Kumar K.V Cc: Hari Bathini Cc: Mahesh Salgaonkar Cc: Michael Ellerman Cc: Naveen N Rao --- arch/powerpc/include/asm/fadump-internal.h | 31 +- arch/powerpc/kernel/fadump.c | 339 +++ arch/powerpc/platforms/powernv/opal-fadump.c | 22 +- arch/powerpc/platforms/pseries/rtas-fadump.c | 30 +- 4 files changed, 232 insertions(+), 190 deletions(-) diff --git
Re: [PATCH v5 02/10] locking/mutex: introduce devm_mutex_init
On 3/11/24 19:47, George Stark wrote: Hello Waiman, Marek Thanks for the review. I've never used lockdep for debug but it seems preferable to keep that feature working. It could be look like this: diff --git a/include/linux/mutex.h b/include/linux/mutex.h index f7611c092db7..574f6de6084d 100644 --- a/include/linux/mutex.h +++ b/include/linux/mutex.h @@ -22,6 +22,8 @@ #include #include +struct device; + #ifdef CONFIG_DEBUG_LOCK_ALLOC # define __DEP_MAP_MUTEX_INITIALIZER(lockname) \ , .dep_map = { \ @@ -115,10 +117,31 @@ do { \ #ifdef CONFIG_DEBUG_MUTEXES +int debug_devm_mutex_init(struct device *dev, struct mutex *lock); + +#define devm_mutex_init(dev, mutex) \ +({ \ + int ret; \ + mutex_init(mutex); \ + ret = debug_devm_mutex_init(dev, mutex); \ + ret; \ +}) The int ret variable is not needed. The macro can just end with debug_devm_mutex_init(). + void mutex_destroy(struct mutex *lock); #else +/* +* When CONFIG_DEBUG_MUTEXES is off mutex_destroy is just a nop so +* there's no really need to register it in devm subsystem. "no really need"? +*/ +#define devm_mutex_init(dev, mutex) \ +({ \ + typecheck(struct device *, dev); \ + mutex_init(mutex); \ + 0; \ +}) Do we need a typecheck() here? Compilation will fail with CONFIG_DEBUG_MUTEXES if dev is not a device pointer. + static inline void mutex_destroy(struct mutex *lock) {} #endif diff --git a/kernel/locking/mutex-debug.c b/kernel/locking/mutex-debug.c index bc8abb8549d2..967a5367c79a 100644 --- a/kernel/locking/mutex-debug.c +++ b/kernel/locking/mutex-debug.c @@ -19,6 +19,7 @@ #include #include #include +#include #include "mutex.h" @@ -89,6 +90,16 @@ void debug_mutex_init(struct mutex *lock, const char *name, lock->magic = lock; } +static void devm_mutex_release(void *res) +{ + mutex_destroy(res); +} + +int debug_devm_mutex_init(struct device *dev, struct mutex *lock) +{ + return devm_add_action_or_reset(dev, devm_mutex_release, lock); +} + /*** * mutex_destroy - mark a mutex unusable * @lock: the mutex to be destroyed
Re: [PATCH v5 02/10] locking/mutex: introduce devm_mutex_init
Hello Andy On 3/7/24 13:34, Andy Shevchenko wrote: On Thu, Mar 7, 2024 at 4:40 AM George Stark wrote: Using of devm API leads to a certain order of releasing resources. So all dependent resources which are not devm-wrapped should be deleted with respect to devm-release order. Mutex is one of such objects that often is bound to other resources and has no own devm wrapping. Since mutex_destroy() actually does nothing in non-debug builds frequently calling mutex_destroy() is just ignored which is safe for now but wrong formally and can lead to a problem if mutex_destroy() will be extended so introduce devm_mutex_init() Signed-off-by: George Stark Signed-off-by: Christophe Leroy Hello Christophe. Hope you don't mind I put you SoB tag because you helped alot to make this patch happen. You also need to figure out who should be the author of the patch and probably add a (missing) Co-developed-by. After all you should also follow the correct order of SoBs. Thanks for the review. I explained in the other letter as I see it. So I'd leave myself as author and add appropriate tag with Christophe's name. BTW what do you mean by correct SoB order? Is it alphabetical order or order of importance? -- Best regards George
Re: [PATCH v5 02/10] locking/mutex: introduce devm_mutex_init
Hello Waiman, Marek Thanks for the review. I've never used lockdep for debug but it seems preferable to keep that feature working. It could be look like this: diff --git a/include/linux/mutex.h b/include/linux/mutex.h index f7611c092db7..574f6de6084d 100644 --- a/include/linux/mutex.h +++ b/include/linux/mutex.h @@ -22,6 +22,8 @@ #include #include +struct device; + #ifdef CONFIG_DEBUG_LOCK_ALLOC # define __DEP_MAP_MUTEX_INITIALIZER(lockname) \ , .dep_map = { \ @@ -115,10 +117,31 @@ do { \ #ifdef CONFIG_DEBUG_MUTEXES +int debug_devm_mutex_init(struct device *dev, struct mutex *lock); + +#define devm_mutex_init(dev, mutex)\ +({ \ + int ret;\ + mutex_init(mutex); \ + ret = debug_devm_mutex_init(dev, mutex);\ + ret;\ +}) + void mutex_destroy(struct mutex *lock); #else +/* +* When CONFIG_DEBUG_MUTEXES is off mutex_destroy is just a nop so +* there's no really need to register it in devm subsystem. +*/ +#define devm_mutex_init(dev, mutex)\ +({ \ + typecheck(struct device *, dev);\ + mutex_init(mutex); \ + 0; \ +}) + static inline void mutex_destroy(struct mutex *lock) {} #endif diff --git a/kernel/locking/mutex-debug.c b/kernel/locking/mutex-debug.c index bc8abb8549d2..967a5367c79a 100644 --- a/kernel/locking/mutex-debug.c +++ b/kernel/locking/mutex-debug.c @@ -19,6 +19,7 @@ #include #include #include +#include #include "mutex.h" @@ -89,6 +90,16 @@ void debug_mutex_init(struct mutex *lock, const char *name, lock->magic = lock; } +static void devm_mutex_release(void *res) +{ + mutex_destroy(res); +} + +int debug_devm_mutex_init(struct device *dev, struct mutex *lock) +{ + return devm_add_action_or_reset(dev, devm_mutex_release, lock); +} + /*** * mutex_destroy - mark a mutex unusable * @lock: the mutex to be destroyed -- 2.25.1 And now I would drop the the refactoring patch with moving down mutex_destroy. devm block is big enough to be declared standalone. On 3/7/24 19:44, Marek Behún wrote: On Thu, 7 Mar 2024 08:39:46 -0500 Waiman Long wrote: On 3/7/24 04:56, Marek Behún wrote: On Thu, Mar 07, 2024 at 05:40:26AM +0300, George Stark wrote: Using of devm API leads to a certain order of releasing resources. So all dependent resources which are not devm-wrapped should be deleted with respect to devm-release order. Mutex is one of such objects that often is bound to other resources and has no own devm wrapping. Since mutex_destroy() actually does nothing in non-debug builds frequently calling mutex_destroy() is just ignored which is safe for now but wrong formally and can lead to a problem if mutex_destroy() will be extended so introduce devm_mutex_init() Signed-off-by: George Stark Signed-off-by: Christophe Leroy --- Hello Christophe. Hope you don't mind I put you SoB tag because you helped alot to make this patch happen. include/linux/mutex.h| 13 + kernel/locking/mutex-debug.c | 22 ++ 2 files changed, 35 insertions(+) diff --git a/include/linux/mutex.h b/include/linux/mutex.h index f7611c092db7..9bcf72cb941a 100644 --- a/include/linux/mutex.h +++ b/include/linux/mutex.h @@ -22,6 +22,8 @@ #include #include +struct device; + #ifdef CONFIG_DEBUG_LOCK_ALLOC # define __DEP_MAP_MUTEX_INITIALIZER(lockname) \ , .dep_map = { \ @@ -115,10 +117,21 @@ do { \ #ifdef CONFIG_DEBUG_MUTEXES +int devm_mutex_init(struct device *dev, struct mutex *lock); void mutex_destroy(struct mutex *lock); #else +static inline int devm_mutex_init(struct device *dev, struct mutex *lock) +{ + /* +* since mutex_destroy is nop actually there's no need to register it +* in devm subsystem. +*/ + mutex_init(lock); + return 0; +} + static inline void mutex_destroy(struct mutex *lock) {} #endif diff --git a/kernel/locking/mutex-debug.c b/kernel/locking/mutex-debug.c index bc8abb8549d2..c9efab1a8026 100644 --- a/kernel/locking/mutex-debug.c +++ b/kernel/locking/mutex-debug.c @@ -19,6 +19,7 @@ #include #include #include +#include #include "mutex.h" @@ -104,3 +105,24 @@ void mutex_destroy(struct mutex *lock) } EXPORT_SYMBOL_GPL(mutex_destroy); + +static void devm_mutex_release(void *res) +{ + mutex_destroy(res); +} + +/** + * devm_mutex_init - Resource-managed mutex initialization + * @dev:
Re: [PATCH v5 02/10] locking/mutex: introduce devm_mutex_init
Hello Christophe On 3/7/24 16:50, Christophe Leroy wrote: Le 07/03/2024 à 03:40, George Stark a écrit : [Vous ne recevez pas souvent de courriers de gnst...@salutedevices.com. Découvrez pourquoi ceci est important à https://aka.ms/LearnAboutSenderIdentification ] Using of devm API leads to a certain order of releasing resources. So all dependent resources which are not devm-wrapped should be deleted with respect to devm-release order. Mutex is one of such objects that often is bound to other resources and has no own devm wrapping. Since mutex_destroy() actually does nothing in non-debug builds frequently calling mutex_destroy() is just ignored which is safe for now but wrong formally and can lead to a problem if mutex_destroy() will be extended so introduce devm_mutex_init() Signed-off-by: George Stark Signed-off-by: Christophe Leroy --- Hello Christophe. Hope you don't mind I put you SoB tag because you helped alot to make this patch happen. Up to you, I sent a RFC patch based on yours with my ideas included because an exemple is easier than a lot of words for understanding, and my scripts automatically sets the Signed-off-by: but feel free to change it to Suggested-by: Although we had close ideas for the final patch in v4 you encouraged me to do it in the right (=effective) way and go back from devm-helpers.h to mutex.h in the first place, reinforced the concept with appropriate examples from existing code, reviewed a lot. Thanks. Probably Suggested-by: is more suited here -- Best regards George
Re: [PATCH v9 07/10] PCI: dwc: ep: Remove "core_init_notifier" flag
On Mon, Mar 11, 2024 at 08:15:59PM +0530, Manivannan Sadhasivam wrote: > > > > I would say that it is the following change that breaks things: > > > > > - if (!core_init_notifier) { > > > - ret = pci_epf_test_core_init(epf); > > > - if (ret) > > > - return ret; > > > - } > > > - > > > > Since without this code, pci_epf_test_core_init() will no longer be called, > > as there is currently no one that calls epf->core_init() for a EPF driver > > after it has been bound. (For drivers that call dw_pcie_ep_init_notify() in > > .probe()) > > > > Thanks a lot for testing, Niklas! > > > I guess one way to solve this would be for the EPC core to keep track of > > the current EPC "core state" (up/down). If the core is "up" at EPF .bind() > > time, notify the EPF driver directly after .bind()? > > > > Yeah, that's a good solution. But I think it would be better if the EPC caches > all events if the EPF drivers are not available and dispatch them once the > bind > happens for each EPF driver. Even though INIT_COMPLETE is the only event that > is > getting generated before bind() now, IMO it is better to add provision to > catch > other events also. > > Wdyt? I'm not sure. What if the EPF goes up/down/up, it seems a bit silly to send all those events to the EPF driver that will alloc+free+alloc. Do we know for sure that we will want to store + replay events other than INIT_COMPLETE? And how many events should we store? Until we can think of a good reason which events other than UP/DOWN we can to store, I think that just storing the state as an integer in struct pci_epc seems simpler. Or I guess we could continue with a flag in struct pci_epc_features, like has_perst_notifier, which would then require the EPC driver to call both epc_notify_core_up() and epc_notify_core_down() when receiving the PERST deassert/assert. For a driver without the flag set, the EPC core would call .epc_notify_core_up() after bind. (And .epc_notify_core_down() would never be called, or it could call it before unbind().) That way an EPF driver itself would not need any different handling (all callbacks would always come, either triggered by an EPC driver that has PERST GPIO irq, or triggered by the EPC core for a driver that lacks a PERST GPIO). Kind regards, Niklas
Re: [PATCH v7 0/5] Add support for QMC HDLC
On Thu, 7 Mar 2024 12:39:03 +0100 Herve Codina wrote: > This series introduces the QMC HDLC support. > > Patches were previously sent as part of a full feature series and were > previously reviewed in that context: > "Add support for QMC HDLC, framer infrastructure and PEF2256 framer" [1] > > In order to ease the merge, the full feature series has been split and > needed parts were merged in v6.8-rc1: > - "Prepare the PowerQUICC QMC and TSA for the HDLC QMC driver" [2] > - "Add support for framer infrastructure and PEF2256 framer" [3] > > This series contains patches related to the QMC HDLC part (QMC HDLC > driver): > - Introduce the QMC HDLC driver (patches 1 and 2) > - Add timeslots change support in QMC HDLC (patch 3) > - Add framer support as a framer consumer in QMC HDLC (patch 4) > > Compare to the original full feature series, a modification was done on > patch 3 in order to use a coherent prefix in the commit title. > > I kept the patches unsquashed as they were previously sent and reviewed. > Of course, I can squash them if needed. Applied, thank you!
Re: [RFC PATCH v2 3/3] tpm: of: If available use linux,sml-log to get the log and its size
On 3/11/24 16:25, Jarkko Sakkinen wrote: On Mon Mar 11, 2024 at 3:20 PM EET, Stefan Berger wrote: If linux,sml-log is available use it to get the TPM log rather than the pointer found in linux,sml-base. This resolves an issue on PowerVM and KVM on Power where after a kexec the memory pointed to by linux,sml-base may have become inaccessible or corrupted. Also, linux,sml-log has replaced linux,sml-base and linux,sml-size on these two platforms. Keep the handling of linux,sml-base/sml-size for powernv platforms that provide the two properties via skiboot. Fixes: c5df39262dd5 ("drivers/char/tpm: Add securityfs support for event log") Signed-off-by: Stefan Berger I'm worried about not being up to date and instead using "cached" values when verifying anything from a security chip. Does this guarantee that TPM log is corrupted and will not get updated somehow? What do you mean 'guarantee that TPM log is corrupted'? The TPM was handed over from the firmware to Linux and the firmware then freed all memory associated with the log and will then not create a new log or touch the TPM or do anything that would require an update to the handed-over log. Linux also does not append to the firmware log. So whatever we now find in linux,sml-log would be the latest firmware log and the state of the 'firmware PCRs' computed from it should correspond to the current state of the 'firmware PCRs'. BR, Jarkko
Re: [RFC PATCH v2 3/3] tpm: of: If available use linux,sml-log to get the log and its size
On Mon Mar 11, 2024 at 3:20 PM EET, Stefan Berger wrote: > If linux,sml-log is available use it to get the TPM log rather than the > pointer found in linux,sml-base. This resolves an issue on PowerVM and KVM > on Power where after a kexec the memory pointed to by linux,sml-base may > have become inaccessible or corrupted. Also, linux,sml-log has replaced > linux,sml-base and linux,sml-size on these two platforms. > > Keep the handling of linux,sml-base/sml-size for powernv platforms that > provide the two properties via skiboot. > > Fixes: c5df39262dd5 ("drivers/char/tpm: Add securityfs support for event log") > Signed-off-by: Stefan Berger I'm worried about not being up to date and instead using "cached" values when verifying anything from a security chip. Does this guarantee that TPM log is corrupted and will not get updated somehow? BR, Jarkko
Re: [RFC PATCH v2 1/3] powerpc/prom_init: Replace linux,sml-base/sml-size with linux,sml-log
On Mon Mar 11, 2024 at 3:20 PM EET, Stefan Berger wrote: > linux,sml-base holds the address of a buffer with the TPM log. This > buffer may become invalid after a kexec. To avoid accessing an invalid > address or corrupted buffer, embed the whole TPM log in the device tree > property linux,sml-log. This helps to protect the log since it is > properly carried across a kexec soft reboot with both of the kexec > syscalls. - Describe the environment where TPM log gets corrupted. - Describe why TPM log gets corrupted on kexec. > > Avoid having the firmware ingest the whole TPM log when calling > prom_setprop but only create the linux,sml-log property as a place holder. > Insert the actual TPM log during the tree flattening phase. This commit message should shed some light about reasons of the corruption in order to conclude that it should be fixed up like this. I.e. why the "post-state" is a legit state where can be continued despite a log being corrupted. Especially in security features this is pretty essential information. BR, Jarkko
Re: [PATCH 2/2] tpm: of: If available Use linux,sml-log to get the log and its size
On Fri Mar 8, 2024 at 2:17 PM EET, Stefan Berger wrote: > > > On 3/7/24 15:00, Jarkko Sakkinen wrote: > > On Thu Mar 7, 2024 at 9:57 PM EET, Jarkko Sakkinen wrote: > >> in short summary: s/Use/use/ > >> > >> On Wed Mar 6, 2024 at 5:55 PM EET, Stefan Berger wrote: > >>> If linux,sml-log is available use it to get the TPM log rather than the > >>> pointer found in linux,sml-base. This resolves an issue on PowerVM and KVM > >>> on Power where after a kexec the memory pointed to by linux,sml-base may > >>> have been corrupted. Also, linux,sml-log has replaced linux,sml-base and > >>> linux,sml-size on these two platforms. > >>> > >>> Signed-off-by: Stefan Berger > >> > >> So shouldn't this have a fixed tag, or not? > > > > In English: do we want this to be backported to stable kernel releases or > > not? > > Ideally, yes. v3 will have 3 patches and all 3 of them will have to be > backported *together* and not applied otherwise if any one of them > fails. Can this be 'guaranteed'? All of them will end up to stable if the following conditions hold: - All have a fixes tag. - All have "Cc: sta...@vger.kernel.org". - We agree in the review process that they are all legit fixes. BR, Jarkko
Re: [PATCH v6 3/6] KEYS: trusted: Introduce NXP DCP-backed trusted keys
On Fri Mar 8, 2024 at 9:17 AM EET, David Gstir wrote: > Hi Jarkko, > > > On 07.03.2024, at 20:30, Jarkko Sakkinen wrote: > > [...] > > >> + > >> +static int trusted_dcp_init(void) > >> +{ > >> + int ret; > >> + > >> + if (use_otp_key) > >> + pr_info("Using DCP OTP key\n"); > >> + > >> + ret = test_for_zero_key(); > >> + if (ret) { > >> + pr_err("Test for zero'ed keys failed: %i\n", ret); > > > > I'm not sure whether this should err or warn. > > > > What sort of situations can cause the test the fail (e.g. > > adversary/interposer, bad configuration etc.). > > This occurs when the hardware is not in "secure mode". I.e. it’s a bad > configuration issue. > Once the board is properly configured, this will never trigger again. > Do you think a warning is better for this then? Bad configuration is not unexpected configuration so it cannot possibly be an error situation as far as Linux is considered. So warning is appropriate here I'd figure. BR, Jarkko
Re: [RFC PATCH v2 1/3] powerpc/prom_init: Replace linux,sml-base/sml-size with linux,sml-log
On 3/11/24 13:24, Christophe Leroy wrote: Le 11/03/2024 à 14:20, Stefan Berger a écrit : linux,sml-base holds the address of a buffer with the TPM log. This buffer may become invalid after a kexec. To avoid accessing an invalid address or corrupted buffer, embed the whole TPM log in the device tree property linux,sml-log. This helps to protect the log since it is properly carried across a kexec soft reboot with both of the kexec syscalls. Avoid having the firmware ingest the whole TPM log when calling prom_setprop but only create the linux,sml-log property as a place holder. Insert the actual TPM log during the tree flattening phase. Fixes: 4a727429abec ("PPC64: Add support for instantiating SML from Open Firmware") Suggested-by: Michael Ellerman Signed-off-by: Stefan Berger --- @@ -2645,6 +2645,17 @@ static void __init scan_dt_build_struct(phandle node, unsigned long *mem_start, } prev_name = sstart + soff; + if (!prom_strcmp("linux,sml-log", pname)) { + /* push property head */ + dt_push_token(OF_DT_PROP, mem_start, mem_end); + dt_push_token(sml_size, mem_start, mem_end); + dt_push_token(soff, mem_start, mem_end); + /* push property content */ + valp = make_room(mem_start, mem_end, sml_size, 1); + memcpy(valp, (void *)sml_base, sml_size); You can't cast a u64 into a pointer. If sml_base is an address, it must be declared as an unsigned long. Build with pmac32_defconfig : CC arch/powerpc/kernel/prom_init.o arch/powerpc/kernel/prom_init.c: In function 'scan_dt_build_struct': arch/powerpc/kernel/prom_init.c:2663:38: error: cast to pointer from integer of different size [-Werror=int-to-pointer-cast] 2663 | memcpy(valp, (void *)sml_base, sml_size); | ^ cc1: all warnings being treated as errors make[4]: *** [scripts/Makefile.build:243: arch/powerpc/kernel/prom_init.o] Error 1 Next round will have this block under #ifdef CONFIG_PPC64. Thanks.
Re: [RFC PATCH v2 1/3] powerpc/prom_init: Replace linux,sml-base/sml-size with linux,sml-log
On Mon, Mar 11, 2024 at 09:20:28AM -0400, Stefan Berger wrote: > linux,sml-base holds the address of a buffer with the TPM log. This > buffer may become invalid after a kexec. To avoid accessing an invalid > address or corrupted buffer, embed the whole TPM log in the device tree > property linux,sml-log. This helps to protect the log since it is > properly carried across a kexec soft reboot with both of the kexec > syscalls. > > Avoid having the firmware ingest the whole TPM log when calling > prom_setprop but only create the linux,sml-log property as a place holder. > Insert the actual TPM log during the tree flattening phase. > > Fixes: 4a727429abec ("PPC64: Add support for instantiating SML from Open > Firmware") > Suggested-by: Michael Ellerman > Signed-off-by: Stefan Berger > --- > arch/powerpc/kernel/prom_init.c | 27 +++ > 1 file changed, 19 insertions(+), 8 deletions(-) > > diff --git a/arch/powerpc/kernel/prom_init.c b/arch/powerpc/kernel/prom_init.c > index e67effdba85c..6f7ca72013c2 100644 > --- a/arch/powerpc/kernel/prom_init.c > +++ b/arch/powerpc/kernel/prom_init.c > @@ -211,6 +211,8 @@ static cell_t __prombss regbuf[1024]; > > static bool __prombss rtas_has_query_cpu_stopped; > > +static u64 __prombss sml_base; > +static u32 __prombss sml_size; Should inside an #ifdef CONFIG_PPC64 since prom_instantiate_sml() is? > > /* > * Error results ... some OF calls will return "-1" on error, some > @@ -1954,17 +1956,15 @@ static void __init prom_instantiate_sml(void) > } > prom_printf(" done\n"); > > - reserve_mem(base, size); > - > - prom_setprop(ibmvtpm_node, "/vdevice/vtpm", "linux,sml-base", > - , sizeof(base)); > - prom_setprop(ibmvtpm_node, "/vdevice/vtpm", "linux,sml-size", > - , sizeof(size)); > - > - prom_debug("sml base = 0x%llx\n", base); > + /* Add property now, defer adding log to tree flattening phase */ > + prom_setprop(ibmvtpm_node, "/vdevice/vtpm", "linux,sml-log", > + NULL, 0); > prom_debug("sml size = 0x%x\n", size); > > prom_debug("prom_instantiate_sml: end...\n"); > + > + sml_base = base; > + sml_size = size; > } > > /* > @@ -2645,6 +2645,17 @@ static void __init scan_dt_build_struct(phandle node, > unsigned long *mem_start, > } > prev_name = sstart + soff; > > + if (!prom_strcmp("linux,sml-log", pname)) { > + /* push property head */ > + dt_push_token(OF_DT_PROP, mem_start, mem_end); > + dt_push_token(sml_size, mem_start, mem_end); > + dt_push_token(soff, mem_start, mem_end); > + /* push property content */ > + valp = make_room(mem_start, mem_end, sml_size, 1); > + memcpy(valp, (void *)sml_base, sml_size); > + *mem_start = ALIGN(*mem_start, 4); > + continue; > + } Same question as above. Regards, Jerry > /* get length */ > l = call_prom("getproplen", 2, 1, node, pname); > > -- > 2.43.0 >
Re: [RFC PATCH v2 1/3] powerpc/prom_init: Replace linux,sml-base/sml-size with linux,sml-log
Le 11/03/2024 à 14:20, Stefan Berger a écrit : > linux,sml-base holds the address of a buffer with the TPM log. This > buffer may become invalid after a kexec. To avoid accessing an invalid > address or corrupted buffer, embed the whole TPM log in the device tree > property linux,sml-log. This helps to protect the log since it is > properly carried across a kexec soft reboot with both of the kexec > syscalls. > > Avoid having the firmware ingest the whole TPM log when calling > prom_setprop but only create the linux,sml-log property as a place holder. > Insert the actual TPM log during the tree flattening phase. > > Fixes: 4a727429abec ("PPC64: Add support for instantiating SML from Open > Firmware") > Suggested-by: Michael Ellerman > Signed-off-by: Stefan Berger > --- > arch/powerpc/kernel/prom_init.c | 27 +++ > 1 file changed, 19 insertions(+), 8 deletions(-) > > diff --git a/arch/powerpc/kernel/prom_init.c b/arch/powerpc/kernel/prom_init.c > index e67effdba85c..6f7ca72013c2 100644 > --- a/arch/powerpc/kernel/prom_init.c > +++ b/arch/powerpc/kernel/prom_init.c > @@ -211,6 +211,8 @@ static cell_t __prombss regbuf[1024]; > > static bool __prombss rtas_has_query_cpu_stopped; > > +static u64 __prombss sml_base; > +static u32 __prombss sml_size; > > /* >* Error results ... some OF calls will return "-1" on error, some > @@ -1954,17 +1956,15 @@ static void __init prom_instantiate_sml(void) > } > prom_printf(" done\n"); > > - reserve_mem(base, size); > - > - prom_setprop(ibmvtpm_node, "/vdevice/vtpm", "linux,sml-base", > - , sizeof(base)); > - prom_setprop(ibmvtpm_node, "/vdevice/vtpm", "linux,sml-size", > - , sizeof(size)); > - > - prom_debug("sml base = 0x%llx\n", base); > + /* Add property now, defer adding log to tree flattening phase */ > + prom_setprop(ibmvtpm_node, "/vdevice/vtpm", "linux,sml-log", > + NULL, 0); > prom_debug("sml size = 0x%x\n", size); > > prom_debug("prom_instantiate_sml: end...\n"); > + > + sml_base = base; > + sml_size = size; > } > > /* > @@ -2645,6 +2645,17 @@ static void __init scan_dt_build_struct(phandle node, > unsigned long *mem_start, > } > prev_name = sstart + soff; > > + if (!prom_strcmp("linux,sml-log", pname)) { > + /* push property head */ > + dt_push_token(OF_DT_PROP, mem_start, mem_end); > + dt_push_token(sml_size, mem_start, mem_end); > + dt_push_token(soff, mem_start, mem_end); > + /* push property content */ > + valp = make_room(mem_start, mem_end, sml_size, 1); > + memcpy(valp, (void *)sml_base, sml_size); You can't cast a u64 into a pointer. If sml_base is an address, it must be declared as an unsigned long. Build with pmac32_defconfig : CC arch/powerpc/kernel/prom_init.o arch/powerpc/kernel/prom_init.c: In function 'scan_dt_build_struct': arch/powerpc/kernel/prom_init.c:2663:38: error: cast to pointer from integer of different size [-Werror=int-to-pointer-cast] 2663 | memcpy(valp, (void *)sml_base, sml_size); | ^ cc1: all warnings being treated as errors make[4]: *** [scripts/Makefile.build:243: arch/powerpc/kernel/prom_init.o] Error 1 > + *mem_start = ALIGN(*mem_start, 4); > + continue; > + } > /* get length */ > l = call_prom("getproplen", 2, 1, node, pname); >
[PATCH net v5 1/2] soc: fsl: qbman: Always disable interrupts when taking cgr_lock
smp_call_function_single disables IRQs when executing the callback. To prevent deadlocks, we must disable IRQs when taking cgr_lock elsewhere. This is already done by qman_update_cgr and qman_delete_cgr; fix the other lockers. Fixes: 96f413f47677 ("soc/fsl/qbman: fix issue in qman_delete_cgr_safe()") CC: sta...@vger.kernel.org Signed-off-by: Sean Anderson Reviewed-by: Camelia Groza Tested-by: Vladimir Oltean --- Resent from a non-mangling email. (no changes since v3) Changes in v3: - Change blamed commit to something more appropriate Changes in v2: - Fix one additional call to spin_unlock drivers/soc/fsl/qbman/qman.c | 10 +- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/soc/fsl/qbman/qman.c b/drivers/soc/fsl/qbman/qman.c index 739e4eee6b75..1bf1f1ea67f0 100644 --- a/drivers/soc/fsl/qbman/qman.c +++ b/drivers/soc/fsl/qbman/qman.c @@ -1456,11 +1456,11 @@ static void qm_congestion_task(struct work_struct *work) union qm_mc_result *mcr; struct qman_cgr *cgr; - spin_lock(>cgr_lock); + spin_lock_irq(>cgr_lock); qm_mc_start(>p); qm_mc_commit(>p, QM_MCC_VERB_QUERYCONGESTION); if (!qm_mc_result_timeout(>p, )) { - spin_unlock(>cgr_lock); + spin_unlock_irq(>cgr_lock); dev_crit(p->config->dev, "QUERYCONGESTION timeout\n"); qman_p_irqsource_add(p, QM_PIRQ_CSCI); return; @@ -1476,7 +1476,7 @@ static void qm_congestion_task(struct work_struct *work) list_for_each_entry(cgr, >cgr_cbs, node) if (cgr->cb && qman_cgrs_get(, cgr->cgrid)) cgr->cb(p, cgr, qman_cgrs_get(, cgr->cgrid)); - spin_unlock(>cgr_lock); + spin_unlock_irq(>cgr_lock); qman_p_irqsource_add(p, QM_PIRQ_CSCI); } @@ -2440,7 +2440,7 @@ int qman_create_cgr(struct qman_cgr *cgr, u32 flags, preempt_enable(); cgr->chan = p->config->channel; - spin_lock(>cgr_lock); + spin_lock_irq(>cgr_lock); if (opts) { struct qm_mcc_initcgr local_opts = *opts; @@ -2477,7 +2477,7 @@ int qman_create_cgr(struct qman_cgr *cgr, u32 flags, qman_cgrs_get(>cgrs[1], cgr->cgrid)) cgr->cb(p, cgr, 1); out: - spin_unlock(>cgr_lock); + spin_unlock_irq(>cgr_lock); put_affine_portal(); return ret; } -- 2.35.1.1320.gc452695387.dirty
[PATCH net v5 2/2] soc: fsl: qbman: Use raw spinlock for cgr_lock
smp_call_function always runs its callback in hard IRQ context, even on PREEMPT_RT, where spinlocks can sleep. So we need to use a raw spinlock for cgr_lock to ensure we aren't waiting on a sleeping task. Although this bug has existed for a while, it was not apparent until commit ef2a8d5478b9 ("net: dpaa: Adjust queue depth on rate change") which invokes smp_call_function_single via qman_update_cgr_safe every time a link goes up or down. Fixes: 96f413f47677 ("soc/fsl/qbman: fix issue in qman_delete_cgr_safe()") CC: sta...@vger.kernel.org Reported-by: Vladimir Oltean Closes: https://lore.kernel.org/all/20230323153935.nofnjucqjqnz34ej@skbuf/ Reported-by: Steffen Trumtrar Closes: https://lore.kernel.org/linux-arm-kernel/87wmsyvclu@pengutronix.de/ Signed-off-by: Sean Anderson Reviewed-by: Camelia Groza Tested-by: Vladimir Oltean --- Changes in v5: - Clarify commit message Changes in v4: - Add a note about how raw spinlocks aren't quite right Changes in v3: - Change blamed commit to something more appropriate drivers/soc/fsl/qbman/qman.c | 25 ++--- 1 file changed, 14 insertions(+), 11 deletions(-) diff --git a/drivers/soc/fsl/qbman/qman.c b/drivers/soc/fsl/qbman/qman.c index 1bf1f1ea67f0..7e9074519ad2 100644 --- a/drivers/soc/fsl/qbman/qman.c +++ b/drivers/soc/fsl/qbman/qman.c @@ -991,7 +991,7 @@ struct qman_portal { /* linked-list of CSCN handlers. */ struct list_head cgr_cbs; /* list lock */ - spinlock_t cgr_lock; + raw_spinlock_t cgr_lock; struct work_struct congestion_work; struct work_struct mr_work; char irqname[MAX_IRQNAME]; @@ -1281,7 +1281,7 @@ static int qman_create_portal(struct qman_portal *portal, /* if the given mask is NULL, assume all CGRs can be seen */ qman_cgrs_fill(>cgrs[0]); INIT_LIST_HEAD(>cgr_cbs); - spin_lock_init(>cgr_lock); + raw_spin_lock_init(>cgr_lock); INIT_WORK(>congestion_work, qm_congestion_task); INIT_WORK(>mr_work, qm_mr_process_task); portal->bits = 0; @@ -1456,11 +1456,14 @@ static void qm_congestion_task(struct work_struct *work) union qm_mc_result *mcr; struct qman_cgr *cgr; - spin_lock_irq(>cgr_lock); + /* +* FIXME: QM_MCR_TIMEOUT is 10ms, which is too long for a raw spinlock! +*/ + raw_spin_lock_irq(>cgr_lock); qm_mc_start(>p); qm_mc_commit(>p, QM_MCC_VERB_QUERYCONGESTION); if (!qm_mc_result_timeout(>p, )) { - spin_unlock_irq(>cgr_lock); + raw_spin_unlock_irq(>cgr_lock); dev_crit(p->config->dev, "QUERYCONGESTION timeout\n"); qman_p_irqsource_add(p, QM_PIRQ_CSCI); return; @@ -1476,7 +1479,7 @@ static void qm_congestion_task(struct work_struct *work) list_for_each_entry(cgr, >cgr_cbs, node) if (cgr->cb && qman_cgrs_get(, cgr->cgrid)) cgr->cb(p, cgr, qman_cgrs_get(, cgr->cgrid)); - spin_unlock_irq(>cgr_lock); + raw_spin_unlock_irq(>cgr_lock); qman_p_irqsource_add(p, QM_PIRQ_CSCI); } @@ -2440,7 +2443,7 @@ int qman_create_cgr(struct qman_cgr *cgr, u32 flags, preempt_enable(); cgr->chan = p->config->channel; - spin_lock_irq(>cgr_lock); + raw_spin_lock_irq(>cgr_lock); if (opts) { struct qm_mcc_initcgr local_opts = *opts; @@ -2477,7 +2480,7 @@ int qman_create_cgr(struct qman_cgr *cgr, u32 flags, qman_cgrs_get(>cgrs[1], cgr->cgrid)) cgr->cb(p, cgr, 1); out: - spin_unlock_irq(>cgr_lock); + raw_spin_unlock_irq(>cgr_lock); put_affine_portal(); return ret; } @@ -2512,7 +2515,7 @@ int qman_delete_cgr(struct qman_cgr *cgr) return -EINVAL; memset(_opts, 0, sizeof(struct qm_mcc_initcgr)); - spin_lock_irqsave(>cgr_lock, irqflags); + raw_spin_lock_irqsave(>cgr_lock, irqflags); list_del(>node); /* * If there are no other CGR objects for this CGRID in the list, @@ -2537,7 +2540,7 @@ int qman_delete_cgr(struct qman_cgr *cgr) /* add back to the list */ list_add(>node, >cgr_cbs); release_lock: - spin_unlock_irqrestore(>cgr_lock, irqflags); + raw_spin_unlock_irqrestore(>cgr_lock, irqflags); put_affine_portal(); return ret; } @@ -2577,9 +2580,9 @@ static int qman_update_cgr(struct qman_cgr *cgr, struct qm_mcc_initcgr *opts) if (!p) return -EINVAL; - spin_lock_irqsave(>cgr_lock, irqflags); + raw_spin_lock_irqsave(>cgr_lock, irqflags); ret = qm_modify_cgr(cgr, 0, opts); - spin_unlock_irqrestore(>cgr_lock, irqflags); + raw_spin_unlock_irqrestore(>cgr_lock, irqflags); put_affine_portal(); return ret; } -- 2.35.1.1320.gc452695387.dirty
Re: [PATCH v9 07/10] PCI: dwc: ep: Remove "core_init_notifier" flag
On Fri, Mar 08, 2024 at 02:24:35PM +0100, Niklas Cassel wrote: > On Mon, Mar 04, 2024 at 02:52:19PM +0530, Manivannan Sadhasivam wrote: > > "core_init_notifier" flag is set by the glue drivers requiring refclk from > > the host to complete the DWC core initialization. Also, those drivers will > > send a notification to the EPF drivers once the initialization is fully > > completed using the pci_epc_init_notify() API. Only then, the EPF drivers > > will start functioning. > > > > For the rest of the drivers generating refclk locally, EPF drivers will > > start functioning post binding with them. EPF drivers rely on the > > 'core_init_notifier' flag to differentiate between the drivers. > > Unfortunately, this creates two different flows for the EPF drivers. > > > > So to avoid that, let's get rid of the "core_init_notifier" flag and follow > > a single initialization flow for the EPF drivers. This is done by calling > > the dw_pcie_ep_init_notify() from all glue drivers after the completion of > > dw_pcie_ep_init_registers() API. This will allow all the glue drivers to > > send the notification to the EPF drivers once the initialization is fully > > completed. > > > > Only difference here is that, the drivers requiring refclk from host will > > send the notification once refclk is received, while others will send it > > during probe time itself. > > > > Reviewed-by: Frank Li > > Signed-off-by: Manivannan Sadhasivam > > --- > > diff --git a/drivers/pci/endpoint/functions/pci-epf-test.c > > b/drivers/pci/endpoint/functions/pci-epf-test.c > > index 18c80002d3bd..fc0282b0d626 100644 > > --- a/drivers/pci/endpoint/functions/pci-epf-test.c > > +++ b/drivers/pci/endpoint/functions/pci-epf-test.c > > @@ -927,21 +928,12 @@ static int pci_epf_test_bind(struct pci_epf *epf) > > if (ret) > > return ret; > > > > Hello Mani, > > Since you asked for testing, I gave your series a spin > (with a driver without .core_init_notifier). > > > There seems to be a problem that pci_epc_write_header() is never called. > > Debugging this, it seems that .core_init in pci-epf-test is never called. > > If I add debug prints in pci_epc_init_notify(), I see that it does not > notify a single EPF driver. > > It appears that the patch in $subject will call pci_epc_init_notify() > at EPC driver .probe() time, and at that point in time, there are no > EPF drivers registered. > > They get registered later, when doing the configfs write. > > > I would say that it is the following change that breaks things: > > > - if (!core_init_notifier) { > > - ret = pci_epf_test_core_init(epf); > > - if (ret) > > - return ret; > > - } > > - > > Since without this code, pci_epf_test_core_init() will no longer be called, > as there is currently no one that calls epf->core_init() for a EPF driver > after it has been bound. (For drivers that call dw_pcie_ep_init_notify() in > .probe()) > Thanks a lot for testing, Niklas! > I guess one way to solve this would be for the EPC core to keep track of > the current EPC "core state" (up/down). If the core is "up" at EPF .bind() > time, notify the EPF driver directly after .bind()? > Yeah, that's a good solution. But I think it would be better if the EPC caches all events if the EPF drivers are not available and dispatch them once the bind happens for each EPF driver. Even though INIT_COMPLETE is the only event that is getting generated before bind() now, IMO it is better to add provision to catch other events also. Wdyt? - Mani -- மணிவண்ணன் சதாசிவம்
[RFC PATCH v2 2/3] dt-bindings: tpm: Add linux,sml-log to ibm,vtpm.yaml
Add linux,sml-log, which carries the firmware TPM log in a uint8-array, to the properties. Either this property is required or both linux,sml-base and linux,sml-size are required. Add a test case for verification. Fixes: 82003e0487fb ("Documentation: tpm: add the IBM Virtual TPM device tree binding documentation") Cc: Lukas Wunner Cc: Nayna Jain Signed-off-by: Michael Ellerman Signed-off-by: Stefan Berger --- .../devicetree/bindings/tpm/ibm,vtpm.yaml | 20 +-- .../devicetree/bindings/tpm/tpm-common.yaml | 14 - 2 files changed, 31 insertions(+), 3 deletions(-) diff --git a/Documentation/devicetree/bindings/tpm/ibm,vtpm.yaml b/Documentation/devicetree/bindings/tpm/ibm,vtpm.yaml index 50a3fd31241c..8885ef3b7638 100644 --- a/Documentation/devicetree/bindings/tpm/ibm,vtpm.yaml +++ b/Documentation/devicetree/bindings/tpm/ibm,vtpm.yaml @@ -74,8 +74,6 @@ required: - ibm,my-dma-window - ibm,my-drc-index - ibm,loc-code - - linux,sml-base - - linux,sml-size allOf: - $ref: tpm-common.yaml# @@ -102,3 +100,21 @@ examples: linux,sml-size = <0xbce10200>; }; }; + - | +soc { +#address-cells = <1>; +#size-cells = <0>; + +tpm@3003 { +compatible = "IBM,vtpm20"; +device_type = "IBM,vtpm"; +reg = <0x3003>; +interrupts = <0xa0003 0x0>; +ibm,#dma-address-cells = <0x2>; +ibm,#dma-size-cells = <0x2>; +ibm,my-dma-window = <0x1003 0x0 0x0 0x0 0x1000>; +ibm,my-drc-index = <0x3003>; +ibm,loc-code = "U9080.HEX.134CA08-V7-C3"; +linux,sml-log = <00 00 00 00 03 00 00>; +}; +}; diff --git a/Documentation/devicetree/bindings/tpm/tpm-common.yaml b/Documentation/devicetree/bindings/tpm/tpm-common.yaml index 3c1241b2a43f..f6f0b551268c 100644 --- a/Documentation/devicetree/bindings/tpm/tpm-common.yaml +++ b/Documentation/devicetree/bindings/tpm/tpm-common.yaml @@ -30,6 +30,11 @@ properties: size of reserved memory allocated for firmware event log $ref: /schemas/types.yaml#/definitions/uint32 + linux,sml-log: +description: + Content of firmware event log +$ref: /schemas/types.yaml#/definitions/uint8-array + memory-region: description: reserved memory allocated for firmware event log maxItems: 1 @@ -53,15 +58,22 @@ dependentRequired: linux,sml-base: ['linux,sml-size'] linux,sml-size: ['linux,sml-base'] -# must only have either memory-region or linux,sml-base +# must only have either memory-region or linux,sml-base/size or linux,sml-log # as well as either resets or reset-gpios dependentSchemas: memory-region: properties: linux,sml-base: false + linux,sml-log: false linux,sml-base: properties: memory-region: false + linux,sml-log: false + linux,sml-log: +properties: + memory-region: false + linux,sml-base: false + linux,sml-size: false resets: properties: reset-gpios: false -- 2.43.0
[RFC PATCH v2 3/3] tpm: of: If available use linux,sml-log to get the log and its size
If linux,sml-log is available use it to get the TPM log rather than the pointer found in linux,sml-base. This resolves an issue on PowerVM and KVM on Power where after a kexec the memory pointed to by linux,sml-base may have become inaccessible or corrupted. Also, linux,sml-log has replaced linux,sml-base and linux,sml-size on these two platforms. Keep the handling of linux,sml-base/sml-size for powernv platforms that provide the two properties via skiboot. Fixes: c5df39262dd5 ("drivers/char/tpm: Add securityfs support for event log") Signed-off-by: Stefan Berger --- drivers/char/tpm/eventlog/of.c | 36 +++--- 1 file changed, 11 insertions(+), 25 deletions(-) diff --git a/drivers/char/tpm/eventlog/of.c b/drivers/char/tpm/eventlog/of.c index 930fe43d5daf..dbd837d65264 100644 --- a/drivers/char/tpm/eventlog/of.c +++ b/drivers/char/tpm/eventlog/of.c @@ -54,8 +54,8 @@ int tpm_read_log_of(struct tpm_chip *chip) const u32 *sizep; const u64 *basep; struct tpm_bios_log *log; + const void *logp; u32 size; - u64 base; log = >log; if (chip->dev.parent && chip->dev.parent->of_node) @@ -66,37 +66,23 @@ int tpm_read_log_of(struct tpm_chip *chip) if (of_property_read_bool(np, "powered-while-suspended")) chip->flags |= TPM_CHIP_FLAG_ALWAYS_POWERED; - sizep = of_get_property(np, "linux,sml-size", NULL); - basep = of_get_property(np, "linux,sml-base", NULL); - if (sizep == NULL && basep == NULL) - return tpm_read_log_memory_region(chip); - if (sizep == NULL || basep == NULL) - return -EIO; - - /* -* For both vtpm/tpm, firmware has log addr and log size in big -* endian format. But in case of vtpm, there is a method called -* sml-handover which is run during kernel init even before -* device tree is setup. This sml-handover function takes care -* of endianness and writes to sml-base and sml-size in little -* endian format. For this reason, vtpm doesn't need conversion -* but physical tpm needs the conversion. -*/ - if (of_property_match_string(np, "compatible", "IBM,vtpm") < 0 && - of_property_match_string(np, "compatible", "IBM,vtpm20") < 0) { + logp = of_get_property(np, "linux,sml-log", ); + if (logp == NULL) { + sizep = of_get_property(np, "linux,sml-size", NULL); + basep = of_get_property(np, "linux,sml-base", NULL); + if (sizep == NULL && basep == NULL) + return tpm_read_log_memory_region(chip); + if (sizep == NULL || basep == NULL) + return -EIO; size = be32_to_cpup((__force __be32 *)sizep); - base = be64_to_cpup((__force __be64 *)basep); - } else { - size = *sizep; - base = *basep; + logp = __va(be64_to_cpup((__force __be64 *)basep)); } - if (size == 0) { dev_warn(>dev, "%s: Event log area empty\n", __func__); return -EIO; } - log->bios_event_log = devm_kmemdup(>dev, __va(base), size, GFP_KERNEL); + log->bios_event_log = devm_kmemdup(>dev, logp, size, GFP_KERNEL); if (!log->bios_event_log) return -ENOMEM; -- 2.43.0
[RFC PATCH v2 1/3] powerpc/prom_init: Replace linux,sml-base/sml-size with linux,sml-log
linux,sml-base holds the address of a buffer with the TPM log. This buffer may become invalid after a kexec. To avoid accessing an invalid address or corrupted buffer, embed the whole TPM log in the device tree property linux,sml-log. This helps to protect the log since it is properly carried across a kexec soft reboot with both of the kexec syscalls. Avoid having the firmware ingest the whole TPM log when calling prom_setprop but only create the linux,sml-log property as a place holder. Insert the actual TPM log during the tree flattening phase. Fixes: 4a727429abec ("PPC64: Add support for instantiating SML from Open Firmware") Suggested-by: Michael Ellerman Signed-off-by: Stefan Berger --- arch/powerpc/kernel/prom_init.c | 27 +++ 1 file changed, 19 insertions(+), 8 deletions(-) diff --git a/arch/powerpc/kernel/prom_init.c b/arch/powerpc/kernel/prom_init.c index e67effdba85c..6f7ca72013c2 100644 --- a/arch/powerpc/kernel/prom_init.c +++ b/arch/powerpc/kernel/prom_init.c @@ -211,6 +211,8 @@ static cell_t __prombss regbuf[1024]; static bool __prombss rtas_has_query_cpu_stopped; +static u64 __prombss sml_base; +static u32 __prombss sml_size; /* * Error results ... some OF calls will return "-1" on error, some @@ -1954,17 +1956,15 @@ static void __init prom_instantiate_sml(void) } prom_printf(" done\n"); - reserve_mem(base, size); - - prom_setprop(ibmvtpm_node, "/vdevice/vtpm", "linux,sml-base", -, sizeof(base)); - prom_setprop(ibmvtpm_node, "/vdevice/vtpm", "linux,sml-size", -, sizeof(size)); - - prom_debug("sml base = 0x%llx\n", base); + /* Add property now, defer adding log to tree flattening phase */ + prom_setprop(ibmvtpm_node, "/vdevice/vtpm", "linux,sml-log", +NULL, 0); prom_debug("sml size = 0x%x\n", size); prom_debug("prom_instantiate_sml: end...\n"); + + sml_base = base; + sml_size = size; } /* @@ -2645,6 +2645,17 @@ static void __init scan_dt_build_struct(phandle node, unsigned long *mem_start, } prev_name = sstart + soff; + if (!prom_strcmp("linux,sml-log", pname)) { + /* push property head */ + dt_push_token(OF_DT_PROP, mem_start, mem_end); + dt_push_token(sml_size, mem_start, mem_end); + dt_push_token(soff, mem_start, mem_end); + /* push property content */ + valp = make_room(mem_start, mem_end, sml_size, 1); + memcpy(valp, (void *)sml_base, sml_size); + *mem_start = ALIGN(*mem_start, 4); + continue; + } /* get length */ l = call_prom("getproplen", 2, 1, node, pname); -- 2.43.0
[RFC PATCH v2 0/3] Preserve TPM log across kexec
This series resolves an issue on PowerVM and KVM on Power where the memory the TPM log was held in may become inaccessible or corrupted after a kexec soft reboot. The solution on these two platforms is to store the whole log in the device tree because the device tree is preserved across a kexec with either of the two kexec syscalls. Regards, Stefan v2: - Added DT bindings patch (2/3) - Reformulated commit messages and addded Fixes tags - Follow Michael's suggestion on prom_init patch (1/3) Stefan Berger (3): powerpc/prom_init: Replace linux,sml-base/sml-size with linux,sml-log dt-bindings: tpm: Add linux,sml-log to ibm,vtpm.yaml tpm: of: If available use linux,sml-log to get the log and its size .../devicetree/bindings/tpm/ibm,vtpm.yaml | 20 +-- .../devicetree/bindings/tpm/tpm-common.yaml | 14 +++- arch/powerpc/kernel/prom_init.c | 27 +- drivers/char/tpm/eventlog/of.c| 36 ++- 4 files changed, 61 insertions(+), 36 deletions(-) -- 2.43.0
Re: [PATCH 0/4] PCI: Consolidate TLP Log reading and printing
On Fri, 8 Mar 2024, Bjorn Helgaas wrote: > On Tue, Feb 06, 2024 at 03:57:13PM +0200, Ilpo Järvinen wrote: > > This series consolidates AER & DPC TLP Log handling code. Helpers are > > added for reading and printing the TLP Log and the format is made to > > include E-E Prefixes in both cases (previously only one DPC RP PIO > > displayed the E-E Prefixes). > > > > I'd appreciate if people familiar with ixgbe could check the error > > handling conversion within the driver is correct. > > > > Ilpo Järvinen (4): > > PCI/AER: Cleanup register variable > > PCI: Generalize TLP Header Log reading > > I applied these first two to pci/aer for v6.9, thanks, these are all > nice improvements! > > I postponed the ixgbe part for now because I think we should get an > ack from those maintainers or just send it to them since it subtly > changes the error and device removal checking there. Okay, I'll make sure they're separated properly for the remaining patches (I was already planning on doing that separation and posting v2 to avoid their input blocking the changed but you beat me to it). > > PCI: Add TLP Prefix reading into pcie_read_tlp_log() > > PCI: Create helper to print TLP Header and Prefix Log > > I'll respond to these with some minor comments. Did you forget to send those comments? -- i.
[PATCH v3 5/5] ASoC: fsl: imx-rpmsg: Update to correct DT node
In order to support register and unregister rpmsg sound card through remoteproc platform device for card to probe is registered in imx-audio-rpmsg. ASoC machine driver no longer can get DT node of ASoC CPU DAI device through parent device. ASoC machine driver can get DT node of ASoC CPU DAI device with rpmsg channel name acquired from platform specific data. Signed-off-by: Chancel Liu --- sound/soc/fsl/imx-rpmsg.c | 28 +++- 1 file changed, 19 insertions(+), 9 deletions(-) diff --git a/sound/soc/fsl/imx-rpmsg.c b/sound/soc/fsl/imx-rpmsg.c index e5bd63dab10c..0f1ad7ad7d27 100644 --- a/sound/soc/fsl/imx-rpmsg.c +++ b/sound/soc/fsl/imx-rpmsg.c @@ -108,10 +108,8 @@ static int imx_rpmsg_late_probe(struct snd_soc_card *card) static int imx_rpmsg_probe(struct platform_device *pdev) { struct snd_soc_dai_link_component *dlc; - struct device *dev = pdev->dev.parent; - /* rpmsg_pdev is the platform device for the rpmsg node that probed us */ - struct platform_device *rpmsg_pdev = to_platform_device(dev); - struct device_node *np = rpmsg_pdev->dev.of_node; + struct snd_soc_dai *cpu_dai; + struct device_node *np = NULL; struct of_phandle_args args; const char *platform_name; struct imx_rpmsg *data; @@ -127,10 +125,6 @@ static int imx_rpmsg_probe(struct platform_device *pdev) goto fail; } - ret = of_reserved_mem_device_init_by_idx(>dev, np, 0); - if (ret) - dev_warn(>dev, "no reserved DMA memory\n"); - data->dai.cpus = [0]; data->dai.num_cpus = 1; data->dai.platforms = [1]; @@ -152,6 +146,23 @@ static int imx_rpmsg_probe(struct platform_device *pdev) */ data->dai.ignore_pmdown_time = 1; + data->dai.cpus->dai_name = pdev->dev.platform_data; + cpu_dai = snd_soc_find_dai(data->dai.cpus); + if (!cpu_dai) { + ret = -EPROBE_DEFER; + goto fail; + } + np = cpu_dai->dev->of_node; + if (!np) { + dev_err(>dev, "failed to parse CPU DAI device node\n"); + ret = -ENODEV; + goto fail; + } + + ret = of_reserved_mem_device_init_by_idx(>dev, np, 0); + if (ret) + dev_warn(>dev, "no reserved DMA memory\n"); + /* Optional codec node */ ret = of_parse_phandle_with_fixed_args(np, "audio-codec", 0, 0, ); if (ret) { @@ -170,7 +181,6 @@ static int imx_rpmsg_probe(struct platform_device *pdev) data->sysclk = clk_get_rate(clk); } - data->dai.cpus->dai_name = dev_name(_pdev->dev); if (!of_property_read_string(np, "fsl,rpmsg-channel-name", _name)) data->dai.platforms->name = platform_name; else -- 2.43.0
[PATCH v3 4/5] ASoC: fsl: fsl_rpmsg: Register CPU DAI with name of rpmsg channel
Each rpmsg sound card sits on one rpmsg channel. Register CPU DAI with name of rpmsg channel so that ASoC machine driver can easily link CPU DAI with rpmsg channel name. Signed-off-by: Chancel Liu --- sound/soc/fsl/fsl_rpmsg.c | 32 ++-- 1 file changed, 26 insertions(+), 6 deletions(-) diff --git a/sound/soc/fsl/fsl_rpmsg.c b/sound/soc/fsl/fsl_rpmsg.c index 53bd517e59d6..bc41a0666856 100644 --- a/sound/soc/fsl/fsl_rpmsg.c +++ b/sound/soc/fsl/fsl_rpmsg.c @@ -135,7 +135,6 @@ static struct snd_soc_dai_driver fsl_rpmsg_dai = { static const struct snd_soc_component_driver fsl_component = { .name = "fsl-rpmsg", - .legacy_dai_naming = 1, }; static const struct fsl_rpmsg_soc_data imx7ulp_data = { @@ -190,19 +189,40 @@ MODULE_DEVICE_TABLE(of, fsl_rpmsg_ids); static int fsl_rpmsg_probe(struct platform_device *pdev) { struct device_node *np = pdev->dev.of_node; + struct snd_soc_dai_driver *dai_drv; + const char *dai_name; struct fsl_rpmsg *rpmsg; int ret; + dai_drv = devm_kzalloc(>dev, sizeof(struct snd_soc_dai_driver), GFP_KERNEL); + if (!dai_drv) + return -ENOMEM; + memcpy(dai_drv, _rpmsg_dai, sizeof(fsl_rpmsg_dai)); + rpmsg = devm_kzalloc(>dev, sizeof(struct fsl_rpmsg), GFP_KERNEL); if (!rpmsg) return -ENOMEM; rpmsg->soc_data = of_device_get_match_data(>dev); - fsl_rpmsg_dai.playback.rates = rpmsg->soc_data->rates; - fsl_rpmsg_dai.capture.rates = rpmsg->soc_data->rates; - fsl_rpmsg_dai.playback.formats = rpmsg->soc_data->formats; - fsl_rpmsg_dai.capture.formats = rpmsg->soc_data->formats; + if (rpmsg->soc_data) { + dai_drv->playback.rates = rpmsg->soc_data->rates; + dai_drv->capture.rates = rpmsg->soc_data->rates; + dai_drv->playback.formats = rpmsg->soc_data->formats; + dai_drv->capture.formats = rpmsg->soc_data->formats; + } + + /* Use rpmsg channel name as cpu dai name */ + ret = of_property_read_string(np, "fsl,rpmsg-channel-name", _name); + if (ret) { + if (ret == -EINVAL) { + dai_name = "rpmsg-audio-channel"; + } else { + dev_err(>dev, "Failed to get rpmsg channel name: %d!\n", ret); + return ret; + } + } + dai_drv->name = dai_name; if (of_property_read_bool(np, "fsl,enable-lpa")) { rpmsg->enable_lpa = 1; @@ -236,7 +256,7 @@ static int fsl_rpmsg_probe(struct platform_device *pdev) pm_runtime_enable(>dev); ret = devm_snd_soc_register_component(>dev, _component, - _rpmsg_dai, 1); + dai_drv, 1); if (ret) goto err_pm_disable; -- 2.43.0
[PATCH v3 3/5] ASoC: fsl: Let imx-audio-rpmsg register platform device for card
Let imx-audio-rpmsg register platform device for card. So that card register and unregister can be controlled by rpmsg driver's register and unregister. Signed-off-by: Chancel Liu --- sound/soc/fsl/fsl_rpmsg.c | 11 --- sound/soc/fsl/imx-audio-rpmsg.c | 17 - 2 files changed, 16 insertions(+), 12 deletions(-) diff --git a/sound/soc/fsl/fsl_rpmsg.c b/sound/soc/fsl/fsl_rpmsg.c index 00852f174a69..53bd517e59d6 100644 --- a/sound/soc/fsl/fsl_rpmsg.c +++ b/sound/soc/fsl/fsl_rpmsg.c @@ -240,17 +240,6 @@ static int fsl_rpmsg_probe(struct platform_device *pdev) if (ret) goto err_pm_disable; - rpmsg->card_pdev = platform_device_register_data(>dev, -"imx-audio-rpmsg", -PLATFORM_DEVID_AUTO, -NULL, -0); - if (IS_ERR(rpmsg->card_pdev)) { - dev_err(>dev, "failed to register rpmsg card\n"); - ret = PTR_ERR(rpmsg->card_pdev); - goto err_pm_disable; - } - return 0; err_pm_disable: diff --git a/sound/soc/fsl/imx-audio-rpmsg.c b/sound/soc/fsl/imx-audio-rpmsg.c index 40820d5ad92d..38aafb8954c7 100644 --- a/sound/soc/fsl/imx-audio-rpmsg.c +++ b/sound/soc/fsl/imx-audio-rpmsg.c @@ -12,6 +12,7 @@ */ struct imx_audio_rpmsg { struct platform_device *rpmsg_pdev; + struct platform_device *card_pdev; }; static int imx_audio_rpmsg_cb(struct rpmsg_device *rpdev, void *data, int len, @@ -95,6 +96,16 @@ static int imx_audio_rpmsg_probe(struct rpmsg_device *rpdev) ret = PTR_ERR(data->rpmsg_pdev); } + data->card_pdev = platform_device_register_data(>dev, + "imx-audio-rpmsg", + PLATFORM_DEVID_AUTO, + rpdev->id.name, + strlen(rpdev->id.name) + 1); + if (IS_ERR(data->card_pdev)) { + dev_err(>dev, "failed to register rpmsg card.\n"); + ret = PTR_ERR(data->card_pdev); + } + return ret; } @@ -105,6 +116,9 @@ static void imx_audio_rpmsg_remove(struct rpmsg_device *rpdev) if (data->rpmsg_pdev) platform_device_unregister(data->rpmsg_pdev); + if (data->card_pdev) + platform_device_unregister(data->card_pdev); + dev_info(>dev, "audio rpmsg driver is removed\n"); } @@ -113,6 +127,7 @@ static struct rpmsg_device_id imx_audio_rpmsg_id_table[] = { { .name = "rpmsg-micfil-channel" }, { }, }; +MODULE_DEVICE_TABLE(rpmsg, imx_audio_rpmsg_id_table); static struct rpmsg_driver imx_audio_rpmsg_driver = { .drv.name = "imx_audio_rpmsg", @@ -126,5 +141,5 @@ module_rpmsg_driver(imx_audio_rpmsg_driver); MODULE_DESCRIPTION("Freescale SoC Audio RPMSG interface"); MODULE_AUTHOR("Shengjiu Wang "); -MODULE_ALIAS("platform:imx_audio_rpmsg"); +MODULE_ALIAS("rpmsg:imx_audio_rpmsg"); MODULE_LICENSE("GPL v2"); -- 2.43.0
[PATCH v3 2/5] ASoC: fsl: imx-audio-rpmsg: Register device with rpmsg channel name
This rpmsg driver registers device for ASoC platform driver. To align with platform driver use rpmsg channel name to create device. Signed-off-by: Chancel Liu --- sound/soc/fsl/imx-audio-rpmsg.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/soc/fsl/imx-audio-rpmsg.c b/sound/soc/fsl/imx-audio-rpmsg.c index 289e47c03d40..40820d5ad92d 100644 --- a/sound/soc/fsl/imx-audio-rpmsg.c +++ b/sound/soc/fsl/imx-audio-rpmsg.c @@ -87,8 +87,8 @@ static int imx_audio_rpmsg_probe(struct rpmsg_device *rpdev) /* Register platform driver for rpmsg routine */ data->rpmsg_pdev = platform_device_register_data(>dev, -IMX_PCM_DRV_NAME, -PLATFORM_DEVID_AUTO, +rpdev->id.name, +PLATFORM_DEVID_NONE, NULL, 0); if (IS_ERR(data->rpmsg_pdev)) { dev_err(>dev, "failed to register rpmsg platform.\n"); -- 2.43.0
[PATCH v3 1/5] ASoC: fsl: imx-pcm-rpmsg: Register component with rpmsg channel name
Machine driver uses rpmsg channel name to link this platform component. However if the component is re-registerd card will not find this new created component in snd_soc_try_rebind_card(). Explicitly register this component with rpmsg channel name so that card can always find this component. Signed-off-by: Chancel Liu --- sound/soc/fsl/imx-pcm-rpmsg.c | 11 --- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/sound/soc/fsl/imx-pcm-rpmsg.c b/sound/soc/fsl/imx-pcm-rpmsg.c index fb9244c1e9c5..b84d1dfddba2 100644 --- a/sound/soc/fsl/imx-pcm-rpmsg.c +++ b/sound/soc/fsl/imx-pcm-rpmsg.c @@ -732,9 +732,6 @@ static int imx_rpmsg_pcm_probe(struct platform_device *pdev) goto fail; } - /* platform component name is used by machine driver to link with */ - component->name = info->rpdev->id.name; - #ifdef CONFIG_DEBUG_FS component->debugfs_prefix = "rpmsg"; #endif @@ -822,9 +819,17 @@ static const struct dev_pm_ops imx_rpmsg_pcm_pm_ops = { imx_rpmsg_pcm_resume) }; +static const struct platform_device_id imx_rpmsg_pcm_id_table[] = { + { .name = "rpmsg-audio-channel" }, + { .name = "rpmsg-micfil-channel" }, + { }, +}; +MODULE_DEVICE_TABLE(platform, imx_rpmsg_pcm_id_table); + static struct platform_driver imx_pcm_rpmsg_driver = { .probe = imx_rpmsg_pcm_probe, .remove_new = imx_rpmsg_pcm_remove, + .id_table = imx_rpmsg_pcm_id_table, .driver = { .name = IMX_PCM_DRV_NAME, .pm = _rpmsg_pcm_pm_ops, -- 2.43.0
[PATCH v3 0/5] ASoC: fsl: Support register and unregister rpmsg sound card through remoteproc
echo /lib/firmware/fw.elf > /sys/class/remoteproc/remoteproc0/firmware (A) echo start > /sys/class/remoteproc/remoteproc0/state (B) echo stop > /sys/class/remoteproc/remoteproc0/state The rpmsg sound card is registered in (A) and unregistered in (B). After "start", imx-audio-rpmsg registers devices for ASoC platform driver and machine driver. Then sound card is registered. After "stop", imx-audio-rpmsg unregisters devices for ASoC platform driver and machine driver. Then sound card is unregistered. changes in v2 - Fix build errors reported by kernel test robot changes in v3 - Add a new patch for fsl_rpmsg to register CPU DAI with rpmsg channel name - Update imx-rpmsg.c to get DT node of ASoC CPU DAI device with rpmsg channel name instead of using undocumented bindings Chancel Liu (5): ASoC: fsl: imx-pcm-rpmsg: Register component with rpmsg channel name ASoC: fsl: imx-audio-rpmsg: Register device with rpmsg channel name ASoC: fsl: Let imx-audio-rpmsg register platform device for card ASoC: fsl: fsl_rpmsg: Register CPU DAI with name of rpmsg channel ASoC: fsl: imx-rpmsg: Update to correct DT node sound/soc/fsl/fsl_rpmsg.c | 43 - sound/soc/fsl/imx-audio-rpmsg.c | 21 +--- sound/soc/fsl/imx-pcm-rpmsg.c | 11 ++--- sound/soc/fsl/imx-rpmsg.c | 28 ++--- 4 files changed, 71 insertions(+), 32 deletions(-) -- 2.43.0
[PATCH v14 16/16] media: vim2m-audio: add virtual driver for audio memory to memory
Audio memory to memory virtual driver use video memory to memory virtual driver vim2m.c as example. The main difference is device type is VFL_TYPE_AUDIO and device cap type is V4L2_CAP_AUDIO_M2M. The device_run function is a dummy function, which is simply copy the data from input buffer to output buffer. Signed-off-by: Shengjiu Wang --- drivers/media/test-drivers/Kconfig | 10 + drivers/media/test-drivers/Makefile | 1 + drivers/media/test-drivers/vim2m-audio.c | 793 +++ 3 files changed, 804 insertions(+) create mode 100644 drivers/media/test-drivers/vim2m-audio.c diff --git a/drivers/media/test-drivers/Kconfig b/drivers/media/test-drivers/Kconfig index 5a5379524bde..b6b52a7ca042 100644 --- a/drivers/media/test-drivers/Kconfig +++ b/drivers/media/test-drivers/Kconfig @@ -16,6 +16,16 @@ config VIDEO_VIM2M This is a virtual test device for the memory-to-memory driver framework. +config VIDEO_VIM2M_AUDIO + tristate "Virtual Memory-to-Memory Driver For Audio" + depends on VIDEO_DEV + select VIDEOBUF2_VMALLOC + select V4L2_MEM2MEM_DEV + select MEDIA_CONTROLLER + help + This is a virtual audio test device for the memory-to-memory driver + framework. + source "drivers/media/test-drivers/vicodec/Kconfig" source "drivers/media/test-drivers/vimc/Kconfig" source "drivers/media/test-drivers/vivid/Kconfig" diff --git a/drivers/media/test-drivers/Makefile b/drivers/media/test-drivers/Makefile index 740714a4584d..0c61c9ada3e1 100644 --- a/drivers/media/test-drivers/Makefile +++ b/drivers/media/test-drivers/Makefile @@ -10,6 +10,7 @@ obj-$(CONFIG_DVB_VIDTV) += vidtv/ obj-$(CONFIG_VIDEO_VICODEC) += vicodec/ obj-$(CONFIG_VIDEO_VIM2M) += vim2m.o +obj-$(CONFIG_VIDEO_VIM2M_AUDIO) += vim2m-audio.o obj-$(CONFIG_VIDEO_VIMC) += vimc/ obj-$(CONFIG_VIDEO_VIVID) += vivid/ obj-$(CONFIG_VIDEO_VISL) += visl/ diff --git a/drivers/media/test-drivers/vim2m-audio.c b/drivers/media/test-drivers/vim2m-audio.c new file mode 100644 index ..6361df6320b3 --- /dev/null +++ b/drivers/media/test-drivers/vim2m-audio.c @@ -0,0 +1,793 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * A virtual v4l2-mem2mem example for audio device. + */ + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +MODULE_DESCRIPTION("Virtual device for audio mem2mem testing"); +MODULE_LICENSE("GPL"); + +static unsigned int debug; +module_param(debug, uint, 0644); +MODULE_PARM_DESC(debug, "debug level"); + +#define MEM2MEM_NAME "vim2m-audio" + +#define dprintk(dev, lvl, fmt, arg...) \ + v4l2_dbg(lvl, debug, &(dev)->v4l2_dev, "%s: " fmt, __func__, ## arg) + +#define SAMPLE_NUM 4096 + +static void audm2m_dev_release(struct device *dev) +{} + +static struct platform_device audm2m_pdev = { + .name = MEM2MEM_NAME, + .dev.release= audm2m_dev_release, +}; + +static u32 formats[] = { + V4L2_AUDIO_FMT_S16_LE, +}; + +#define NUM_FORMATS ARRAY_SIZE(formats) + +/* Per-queue, driver-specific private data */ +struct audm2m_q_data { + unsigned intrate; + unsigned intchannels; + unsigned intbuffersize; + unsigned intsequence; + u32 fourcc; +}; + +enum { + V4L2_M2M_SRC = 0, + V4L2_M2M_DST = 1, +}; + +static snd_pcm_format_t find_format(u32 fourcc) +{ + snd_pcm_format_t fmt; + unsigned int k; + + for (k = 0; k < NUM_FORMATS; k++) { + if (formats[k] == fourcc) + break; + } + + if (k == NUM_FORMATS) + return 0; + + fmt = v4l2_fourcc_to_audfmt(formats[k]); + + return fmt; +} + +struct audm2m_dev { + struct v4l2_device v4l2_dev; + struct video_device vfd; + + struct mutexdev_mutex; + + struct v4l2_m2m_dev *m2m_dev; +#ifdef CONFIG_MEDIA_CONTROLLER + struct media_device mdev; +#endif +}; + +struct audm2m_ctx { + struct v4l2_fh fh; + struct v4l2_ctrl_handlerctrl_handler; + struct audm2m_dev *dev; + + struct mutexvb_mutex; + + /* Source and destination queue data */ + struct audm2m_q_data q_data[2]; +}; + +static inline struct audm2m_ctx *file2ctx(struct file *file) +{ + return container_of(file->private_data, struct audm2m_ctx, fh); +} + +static struct audm2m_q_data *get_q_data(struct audm2m_ctx *ctx, + enum v4l2_buf_type type) +{ + if (type == V4L2_BUF_TYPE_AUDIO_OUTPUT) + return >q_data[V4L2_M2M_SRC]; + return >q_data[V4L2_M2M_DST]; +} + +static const char *type_name(enum v4l2_buf_type type) +{ + if (type == V4L2_BUF_TYPE_AUDIO_OUTPUT) + return "Output"; + return "Capture"; +} + +/* + * mem2mem callbacks + */
[PATCH v14 15/16] media: imx-asrc: Add memory to memory driver
Implement the ASRC memory to memory function using the v4l2 framework, user can use this function with v4l2 ioctl interface. User send the output and capture buffer to driver and driver store the converted data to the capture buffer. This feature can be shared by ASRC and EASRC drivers Signed-off-by: Shengjiu Wang --- drivers/media/platform/nxp/Kconfig| 13 + drivers/media/platform/nxp/Makefile |1 + drivers/media/platform/nxp/imx-asrc.c | 1256 + 3 files changed, 1270 insertions(+) create mode 100644 drivers/media/platform/nxp/imx-asrc.c diff --git a/drivers/media/platform/nxp/Kconfig b/drivers/media/platform/nxp/Kconfig index 40e3436669e2..8d0ca335601f 100644 --- a/drivers/media/platform/nxp/Kconfig +++ b/drivers/media/platform/nxp/Kconfig @@ -67,3 +67,16 @@ config VIDEO_MX2_EMMAPRP source "drivers/media/platform/nxp/dw100/Kconfig" source "drivers/media/platform/nxp/imx-jpeg/Kconfig" + +config VIDEO_IMX_ASRC + tristate "NXP i.MX ASRC M2M support" + depends on V4L_MEM2MEM_DRIVERS + depends on MEDIA_SUPPORT + select VIDEOBUF2_DMA_CONTIG + select V4L2_MEM2MEM_DEV + select MEDIA_CONTROLLER + help + Say Y if you want to add ASRC M2M support for NXP CPUs. + It is a complement for ASRC M2P and ASRC P2M features. + This option is only useful for out-of-tree drivers since + in-tree drivers select it automatically. diff --git a/drivers/media/platform/nxp/Makefile b/drivers/media/platform/nxp/Makefile index 4d90eb713652..1325675e34f5 100644 --- a/drivers/media/platform/nxp/Makefile +++ b/drivers/media/platform/nxp/Makefile @@ -9,3 +9,4 @@ obj-$(CONFIG_VIDEO_IMX8MQ_MIPI_CSI2) += imx8mq-mipi-csi2.o obj-$(CONFIG_VIDEO_IMX_MIPI_CSIS) += imx-mipi-csis.o obj-$(CONFIG_VIDEO_IMX_PXP) += imx-pxp.o obj-$(CONFIG_VIDEO_MX2_EMMAPRP) += mx2_emmaprp.o +obj-$(CONFIG_VIDEO_IMX_ASRC) += imx-asrc.o diff --git a/drivers/media/platform/nxp/imx-asrc.c b/drivers/media/platform/nxp/imx-asrc.c new file mode 100644 index ..0c25a36199b1 --- /dev/null +++ b/drivers/media/platform/nxp/imx-asrc.c @@ -0,0 +1,1256 @@ +// SPDX-License-Identifier: GPL-2.0 +// +// Copyright (C) 2014-2016 Freescale Semiconductor, Inc. +// Copyright (C) 2019-2023 NXP +// +// Freescale ASRC Memory to Memory (M2M) driver + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define V4L_CAP OUT +#define V4L_OUT IN + +#define ASRC_xPUT_DMA_CALLBACK(dir) \ + (((dir) == V4L_OUT) ? asrc_input_dma_callback \ + : asrc_output_dma_callback) + +#define DIR_STR(dir) (dir) == V4L_OUT ? "out" : "cap" + +/* Maximum output and capture buffer size */ +#define ASRC_M2M_BUFFER_SIZE (512 * 1024) + +/* Maximum output and capture period size */ +#define ASRC_M2M_PERIOD_SIZE (48 * 1024) + +struct asrc_pair_m2m { + struct fsl_asrc_pair *pair; + struct asrc_m2m *m2m; + struct v4l2_fh fh; + struct v4l2_ctrl_handler ctrl_handler; + int channels[2]; + unsigned int sequence[2]; + s64 src_rate_off_prev; /* Q31.32 */ + s64 dst_rate_off_prev; /* Q31.32 */ + s64 src_rate_off_cur; /* Q31.32 */ + s64 dst_rate_off_cur; /* Q31.32 */ +}; + +struct asrc_m2m { + struct fsl_asrc_m2m_pdata pdata; + struct v4l2_device v4l2_dev; + struct v4l2_m2m_dev *m2m_dev; + struct video_device *dec_vdev; + struct mutex mlock; /* v4l2 ioctls serialization */ + struct platform_device *pdev; +#ifdef CONFIG_MEDIA_CONTROLLER + struct media_device mdev; +#endif +}; + +static u32 formats[] = { + V4L2_AUDIO_FMT_S8, + V4L2_AUDIO_FMT_S16_LE, + V4L2_AUDIO_FMT_U16_LE, + V4L2_AUDIO_FMT_S24_LE, + V4L2_AUDIO_FMT_S24_3LE, + V4L2_AUDIO_FMT_U24_LE, + V4L2_AUDIO_FMT_U24_3LE, + V4L2_AUDIO_FMT_S32_LE, + V4L2_AUDIO_FMT_U32_LE, + V4L2_AUDIO_FMT_S20_3LE, + V4L2_AUDIO_FMT_U20_3LE, + V4L2_AUDIO_FMT_FLOAT_LE, + V4L2_AUDIO_FMT_IEC958_SUBFRAME_LE, +}; + +#define NUM_FORMATS ARRAY_SIZE(formats) + +static const s64 asrc_v1_m2m_rates[] = { + 5512, 8000, 11025, 12000, 16000, + 22050, 24000, 32000, 44100, + 48000, 64000, 88200, 96000, + 128000, 176400, 192000, +}; + +static const s64 asrc_v2_m2m_rates[] = { + 8000, 11025, 12000, 16000, + 22050, 24000, 32000, 44100, + 48000, 64000, 88200, 96000, + 128000, 176400, 192000, 256000, + 352800, 384000, 705600, 768000, +}; + +static u32 find_fourcc(snd_pcm_format_t format) +{ + snd_pcm_format_t fmt; + unsigned int k; + + for (k = 0; k < NUM_FORMATS; k++) { + fmt = v4l2_fourcc_to_audfmt(formats[k]); + if (fmt == format) + return formats[k]; + } + + return 0; +} + +static snd_pcm_format_t find_format(u32 fourcc) +{ + unsigned int k; +
[PATCH v14 14/16] media: vivid: add fixed point test controls
Add fixed point test controls, one is for Q4.16 format another one is for Q63 format. Signed-off-by: Shengjiu Wang --- drivers/media/test-drivers/vivid/vivid-core.h | 2 ++ .../media/test-drivers/vivid/vivid-ctrls.c| 26 +++ include/media/v4l2-ctrls.h| 6 + 3 files changed, 34 insertions(+) diff --git a/drivers/media/test-drivers/vivid/vivid-core.h b/drivers/media/test-drivers/vivid/vivid-core.h index cfb8e66083f6..f65465191bc9 100644 --- a/drivers/media/test-drivers/vivid/vivid-core.h +++ b/drivers/media/test-drivers/vivid/vivid-core.h @@ -222,6 +222,8 @@ struct vivid_dev { struct v4l2_ctrl*boolean; struct v4l2_ctrl*int32; struct v4l2_ctrl*int64; + struct v4l2_ctrl*int32_q16; + struct v4l2_ctrl*int64_q63; struct v4l2_ctrl*menu; struct v4l2_ctrl*string; struct v4l2_ctrl*bitmask; diff --git a/drivers/media/test-drivers/vivid/vivid-ctrls.c b/drivers/media/test-drivers/vivid/vivid-ctrls.c index f2b20e25a7a4..2444ea95b285 100644 --- a/drivers/media/test-drivers/vivid/vivid-ctrls.c +++ b/drivers/media/test-drivers/vivid/vivid-ctrls.c @@ -38,6 +38,8 @@ #define VIVID_CID_U8_PIXEL_ARRAY (VIVID_CID_CUSTOM_BASE + 14) #define VIVID_CID_S32_ARRAY(VIVID_CID_CUSTOM_BASE + 15) #define VIVID_CID_S64_ARRAY(VIVID_CID_CUSTOM_BASE + 16) +#define VIVID_CID_INT_Q4_16(VIVID_CID_CUSTOM_BASE + 17) +#define VIVID_CID_INT64_Q63(VIVID_CID_CUSTOM_BASE + 18) #define VIVID_CID_VIVID_BASE (0x00f0 | 0xf000) #define VIVID_CID_VIVID_CLASS (0x00f0 | 1) @@ -182,6 +184,28 @@ static const struct v4l2_ctrl_config vivid_ctrl_int64 = { .step = 1, }; +static const struct v4l2_ctrl_config vivid_ctrl_int32_q16 = { + .ops = _user_gen_ctrl_ops, + .id = VIVID_CID_INT_Q4_16, + .name = "Integer 32 Bits Q4.16", + .type = V4L2_CTRL_TYPE_INTEGER, + .min = v4l2_ctrl_fp_compose(-16, 0, 16), + .max = v4l2_ctrl_fp_compose(15, 0x, 16), + .step = 1, + .fraction_bits = 16, +}; + +static const struct v4l2_ctrl_config vivid_ctrl_int64_q63 = { + .ops = _user_gen_ctrl_ops, + .id = VIVID_CID_INT64_Q63, + .name = "Integer 64 Bits Q63", + .type = V4L2_CTRL_TYPE_INTEGER64, + .min = v4l2_ctrl_fp_compose(-1, 0, 63), + .max = v4l2_ctrl_fp_compose(0, LLONG_MAX, 63), + .step = 1, + .fraction_bits = 63, +}; + static const struct v4l2_ctrl_config vivid_ctrl_u32_array = { .ops = _user_gen_ctrl_ops, .id = VIVID_CID_U32_ARRAY, @@ -1670,6 +1694,8 @@ int vivid_create_controls(struct vivid_dev *dev, bool show_ccs_cap, dev->button = v4l2_ctrl_new_custom(hdl_user_gen, _ctrl_button, NULL); dev->int32 = v4l2_ctrl_new_custom(hdl_user_gen, _ctrl_int32, NULL); dev->int64 = v4l2_ctrl_new_custom(hdl_user_gen, _ctrl_int64, NULL); + dev->int32_q16 = v4l2_ctrl_new_custom(hdl_user_gen, _ctrl_int32_q16, NULL); + dev->int64_q63 = v4l2_ctrl_new_custom(hdl_user_gen, _ctrl_int64_q63, NULL); dev->boolean = v4l2_ctrl_new_custom(hdl_user_gen, _ctrl_boolean, NULL); dev->menu = v4l2_ctrl_new_custom(hdl_user_gen, _ctrl_menu, NULL); dev->string = v4l2_ctrl_new_custom(hdl_user_gen, _ctrl_string, NULL); diff --git a/include/media/v4l2-ctrls.h b/include/media/v4l2-ctrls.h index c35514c5bf88..197d8b67ac13 100644 --- a/include/media/v4l2-ctrls.h +++ b/include/media/v4l2-ctrls.h @@ -1593,4 +1593,10 @@ void v4l2_ctrl_type_op_log(const struct v4l2_ctrl *ctrl); */ int v4l2_ctrl_type_op_validate(const struct v4l2_ctrl *ctrl, union v4l2_ctrl_ptr ptr); +/* + * Fixed point compose helper define. This helper maps to the value + * i + f / (1 << fraction_bits). + */ +#define v4l2_ctrl_fp_compose(i, f, fraction_bits) (((s64)(i) << fraction_bits) + (f)) + #endif -- 2.34.1
[PATCH v14 13/16] media: uapi: Add an entity type for audio resampler
Add and document a media entity type for an audio resampler. It is MEDIA_ENT_F_PROC_AUDIO_RESAMPLER. Signed-off-by: Shengjiu Wang --- Documentation/userspace-api/media/mediactl/media-types.rst | 6 ++ include/uapi/linux/media.h | 1 + 2 files changed, 7 insertions(+) diff --git a/Documentation/userspace-api/media/mediactl/media-types.rst b/Documentation/userspace-api/media/mediactl/media-types.rst index adfb37430f8e..d353f17c3344 100644 --- a/Documentation/userspace-api/media/mediactl/media-types.rst +++ b/Documentation/userspace-api/media/mediactl/media-types.rst @@ -40,6 +40,7 @@ Types and flags used to represent the media graph elements .. _MEDIA-ENT-F-PROC-VIDEO-ENCODER: .. _MEDIA-ENT-F-PROC-VIDEO-DECODER: .. _MEDIA-ENT-F-PROC-VIDEO-ISP: +.. _MEDIA-ENT-F-PROC-AUDIO-RESAMPLER: .. _MEDIA-ENT-F-VID-MUX: .. _MEDIA-ENT-F-VID-IF-BRIDGE: .. _MEDIA-ENT-F-DV-DECODER: @@ -208,6 +209,11 @@ Types and flags used to represent the media graph elements combination of custom V4L2 controls and IOCTLs, and parameters supplied in a metadata buffer. +* - ``MEDIA_ENT_F_PROC_AUDIO_RESAMPLER`` + - An Audio Resampler device. An entity capable of + resampling an audio stream from one sample rate to another sample + rate. Must have one sink pad and at least one source pad. + * - ``MEDIA_ENT_F_VID_MUX`` - Video multiplexer. An entity capable of multiplexing must have at least two sink pads and one source pad, and must pass the video diff --git a/include/uapi/linux/media.h b/include/uapi/linux/media.h index 9ff6dec7393a..a8266eaa8042 100644 --- a/include/uapi/linux/media.h +++ b/include/uapi/linux/media.h @@ -125,6 +125,7 @@ struct media_device_info { #define MEDIA_ENT_F_PROC_VIDEO_ENCODER (MEDIA_ENT_F_BASE + 0x4007) #define MEDIA_ENT_F_PROC_VIDEO_DECODER (MEDIA_ENT_F_BASE + 0x4008) #define MEDIA_ENT_F_PROC_VIDEO_ISP (MEDIA_ENT_F_BASE + 0x4009) +#define MEDIA_ENT_F_PROC_AUDIO_RESAMPLER (MEDIA_ENT_F_BASE + 0x400a) /* * Switch and bridge entity functions -- 2.34.1
[PATCH v14 12/16] media: uapi: Declare interface types for Audio
Declare the interface types that will be used by Audio. The type is MEDIA_INTF_T_V4L_AUDIO. Signed-off-by: Shengjiu Wang --- .../userspace-api/media/mediactl/media-types.rst| 5 + drivers/media/v4l2-core/v4l2-dev.c | 4 drivers/media/v4l2-core/v4l2-mem2mem.c | 13 + include/uapi/linux/media.h | 1 + 4 files changed, 19 insertions(+), 4 deletions(-) diff --git a/Documentation/userspace-api/media/mediactl/media-types.rst b/Documentation/userspace-api/media/mediactl/media-types.rst index 6332e8395263..adfb37430f8e 100644 --- a/Documentation/userspace-api/media/mediactl/media-types.rst +++ b/Documentation/userspace-api/media/mediactl/media-types.rst @@ -265,6 +265,7 @@ Types and flags used to represent the media graph elements .. _MEDIA-INTF-T-V4L-SUBDEV: .. _MEDIA-INTF-T-V4L-SWRADIO: .. _MEDIA-INTF-T-V4L-TOUCH: +.. _MEDIA-INTF-T-V4L-AUDIO: .. _MEDIA-INTF-T-ALSA-PCM-CAPTURE: .. _MEDIA-INTF-T-ALSA-PCM-PLAYBACK: .. _MEDIA-INTF-T-ALSA-CONTROL: @@ -322,6 +323,10 @@ Types and flags used to represent the media graph elements - Device node interface for Touch device (V4L) - typically, /dev/v4l-touch? +* - ``MEDIA_INTF_T_V4L_AUDIO`` + - Device node interface for Audio device (V4L) + - typically, /dev/v4l-audio? + * - ``MEDIA_INTF_T_ALSA_PCM_CAPTURE`` - Device node interface for ALSA PCM Capture - typically, /dev/snd/pcmC?D?c diff --git a/drivers/media/v4l2-core/v4l2-dev.c b/drivers/media/v4l2-core/v4l2-dev.c index bac008fcedc6..ca8462a61e1f 100644 --- a/drivers/media/v4l2-core/v4l2-dev.c +++ b/drivers/media/v4l2-core/v4l2-dev.c @@ -844,6 +844,10 @@ static int video_register_media_controller(struct video_device *vdev) intf_type = MEDIA_INTF_T_V4L_SUBDEV; /* Entity will be created via v4l2_device_register_subdev() */ break; + case VFL_TYPE_AUDIO: + intf_type = MEDIA_INTF_T_V4L_AUDIO; + /* Entity will be created via v4l2_device_register_subdev() */ + break; default: return 0; } diff --git a/drivers/media/v4l2-core/v4l2-mem2mem.c b/drivers/media/v4l2-core/v4l2-mem2mem.c index 75517134a5e9..cda5e255305f 100644 --- a/drivers/media/v4l2-core/v4l2-mem2mem.c +++ b/drivers/media/v4l2-core/v4l2-mem2mem.c @@ -1143,10 +1143,15 @@ int v4l2_m2m_register_media_controller(struct v4l2_m2m_dev *m2m_dev, if (ret) goto err_rm_links0; - /* Create video interface */ - m2m_dev->intf_devnode = media_devnode_create(mdev, - MEDIA_INTF_T_V4L_VIDEO, 0, - VIDEO_MAJOR, vdev->minor); + if (vdev->vfl_type == VFL_TYPE_AUDIO) + m2m_dev->intf_devnode = media_devnode_create(mdev, + MEDIA_INTF_T_V4L_AUDIO, 0, + VIDEO_MAJOR, vdev->minor); + else + /* Create video interface */ + m2m_dev->intf_devnode = media_devnode_create(mdev, + MEDIA_INTF_T_V4L_VIDEO, 0, + VIDEO_MAJOR, vdev->minor); if (!m2m_dev->intf_devnode) { ret = -ENOMEM; goto err_rm_links1; diff --git a/include/uapi/linux/media.h b/include/uapi/linux/media.h index 1c80b1d6bbaf..9ff6dec7393a 100644 --- a/include/uapi/linux/media.h +++ b/include/uapi/linux/media.h @@ -260,6 +260,7 @@ struct media_links_enum { #define MEDIA_INTF_T_V4L_SUBDEV(MEDIA_INTF_T_V4L_BASE + 3) #define MEDIA_INTF_T_V4L_SWRADIO (MEDIA_INTF_T_V4L_BASE + 4) #define MEDIA_INTF_T_V4L_TOUCH (MEDIA_INTF_T_V4L_BASE + 5) +#define MEDIA_INTF_T_V4L_AUDIO (MEDIA_INTF_T_V4L_BASE + 6) #define MEDIA_INTF_T_ALSA_BASE 0x0300 #define MEDIA_INTF_T_ALSA_PCM_CAPTURE (MEDIA_INTF_T_ALSA_BASE) -- 2.34.1
[PATCH v14 11/16] media: uapi: Add audio rate controls support
Add V4L2_CID_M2M_AUDIO_SOURCE_RATE and V4L2_CID_M2M_AUDIO_DEST_RATE new IDs for rate control. Add V4L2_CID_M2M_AUDIO_SOURCE_RATE_OFFSET and V4L2_CID_M2M_AUDIO_DEST_RATE_OFFSET for clock drift. Signed-off-by: Shengjiu Wang --- .../media/v4l/ext-ctrls-audio-m2m.rst | 38 +++ drivers/media/v4l2-core/v4l2-ctrls-defs.c | 6 +++ include/uapi/linux/v4l2-controls.h| 5 +++ 3 files changed, 49 insertions(+) diff --git a/Documentation/userspace-api/media/v4l/ext-ctrls-audio-m2m.rst b/Documentation/userspace-api/media/v4l/ext-ctrls-audio-m2m.rst index 82d2ecedbfee..b137b7c442e6 100644 --- a/Documentation/userspace-api/media/v4l/ext-ctrls-audio-m2m.rst +++ b/Documentation/userspace-api/media/v4l/ext-ctrls-audio-m2m.rst @@ -19,3 +19,41 @@ Audio M2M Control IDs The Audio M2M class descriptor. Calling :ref:`VIDIOC_QUERYCTRL` for this control will return a description of this control class. + +.. _v4l2-audio-asrc: + +``V4L2_CID_M2M_AUDIO_SOURCE_RATE (integer menu)`` +This control specifies the audio source sample rate, unit is Hz + +``V4L2_CID_M2M_AUDIO_DEST_RATE (integer menu)`` +This control specifies the audio destination sample rate, unit is Hz + +``V4L2_CID_M2M_AUDIO_SOURCE_RATE_OFFSET (fixed point)`` +This control specifies the offset from the audio source sample rate, +unit is Hz. + +The offset compensates for any clock drift. The actual source audio +sample rate is the ideal source audio sample rate from +``V4L2_CID_M2M_AUDIO_SOURCE_RATE`` plus this fixed point offset. + +The audio source clock may have some drift. Reducing or increasing the +audio sample rate dynamically to ensure that Sample Rate Converter is +working on the real sample rate, this feature is for the Asynchronous +Sample Rate Converter module. +So, userspace would be expected to be monitoring such drift +and increasing/decreasing the sample frequency as needed by this control. + +``V4L2_CID_M2M_AUDIO_DEST_RATE_OFFSET (fixed point)`` +This control specifies the offset from the audio destination sample rate, +unit is Hz. + +The offset compensates for any clock drift. The actual destination audio +sample rate is the ideal source audio sample rate from +``V4L2_CID_M2M_AUDIO_DEST_RATE`` plus this fixed point offset. + +The audio destination clock may have some drift. Reducing or increasing +the audio sample rate dynamically to ensure that sample rate converter +is working on the real sample rate, this feature is for the Asynchronous +Sample Rate Converter module. +So, userspace would be expected to be monitoring such drift +and increasing/decreasing the sample frequency as needed by this control. diff --git a/drivers/media/v4l2-core/v4l2-ctrls-defs.c b/drivers/media/v4l2-core/v4l2-ctrls-defs.c index 2a85ea3dc92f..91e1f5348c23 100644 --- a/drivers/media/v4l2-core/v4l2-ctrls-defs.c +++ b/drivers/media/v4l2-core/v4l2-ctrls-defs.c @@ -1245,6 +1245,8 @@ const char *v4l2_ctrl_get_name(u32 id) /* Audio M2M controls */ case V4L2_CID_M2M_AUDIO_CLASS: return "Audio M2M Controls"; + case V4L2_CID_M2M_AUDIO_SOURCE_RATE:return "Audio Source Sample Rate"; + case V4L2_CID_M2M_AUDIO_DEST_RATE: return "Audio Destination Sample Rate"; default: return NULL; } @@ -1606,6 +1608,10 @@ void v4l2_ctrl_fill(u32 id, const char **name, enum v4l2_ctrl_type *type, case V4L2_CID_COLORIMETRY_HDR10_MASTERING_DISPLAY: *type = V4L2_CTRL_TYPE_HDR10_MASTERING_DISPLAY; break; + case V4L2_CID_M2M_AUDIO_SOURCE_RATE: + case V4L2_CID_M2M_AUDIO_DEST_RATE: + *type = V4L2_CTRL_TYPE_INTEGER_MENU; + break; default: *type = V4L2_CTRL_TYPE_INTEGER; break; diff --git a/include/uapi/linux/v4l2-controls.h b/include/uapi/linux/v4l2-controls.h index a8b4b830c757..30129ccdc282 100644 --- a/include/uapi/linux/v4l2-controls.h +++ b/include/uapi/linux/v4l2-controls.h @@ -3495,6 +3495,11 @@ struct v4l2_ctrl_av1_film_grain { #define V4L2_CID_M2M_AUDIO_CLASS_BASE (V4L2_CTRL_CLASS_M2M_AUDIO | 0x900) #define V4L2_CID_M2M_AUDIO_CLASS (V4L2_CTRL_CLASS_M2M_AUDIO | 1) +#define V4L2_CID_M2M_AUDIO_SOURCE_RATE (V4L2_CID_M2M_AUDIO_CLASS_BASE + 0) +#define V4L2_CID_M2M_AUDIO_DEST_RATE (V4L2_CID_M2M_AUDIO_CLASS_BASE + 1) +#define V4L2_CID_M2M_AUDIO_SOURCE_RATE_OFFSET (V4L2_CID_M2M_AUDIO_CLASS_BASE + 2) +#define V4L2_CID_M2M_AUDIO_DEST_RATE_OFFSET(V4L2_CID_M2M_AUDIO_CLASS_BASE + 3) + /* MPEG-compression definitions kept for backwards compatibility */ #ifndef __KERNEL__ #define V4L2_CTRL_CLASS_MPEGV4L2_CTRL_CLASS_CODEC -- 2.34.1
[PATCH v14 10/16] media: uapi: Add V4L2_CTRL_CLASS_M2M_AUDIO
The Audio M2M class includes controls for audio memory-to-memory use cases. The controls can be used for audio codecs, audio preprocessing, audio postprocessing. Signed-off-by: Shengjiu Wang --- .../userspace-api/media/v4l/common.rst| 1 + .../media/v4l/ext-ctrls-audio-m2m.rst | 21 +++ .../media/v4l/vidioc-g-ext-ctrls.rst | 4 drivers/media/v4l2-core/v4l2-ctrls-defs.c | 4 include/uapi/linux/v4l2-controls.h| 4 5 files changed, 34 insertions(+) create mode 100644 Documentation/userspace-api/media/v4l/ext-ctrls-audio-m2m.rst diff --git a/Documentation/userspace-api/media/v4l/common.rst b/Documentation/userspace-api/media/v4l/common.rst index ea0435182e44..d5366e96a596 100644 --- a/Documentation/userspace-api/media/v4l/common.rst +++ b/Documentation/userspace-api/media/v4l/common.rst @@ -52,6 +52,7 @@ applicable to all devices. ext-ctrls-fm-rx ext-ctrls-detect ext-ctrls-colorimetry +ext-ctrls-audio-m2m fourcc format planar-apis diff --git a/Documentation/userspace-api/media/v4l/ext-ctrls-audio-m2m.rst b/Documentation/userspace-api/media/v4l/ext-ctrls-audio-m2m.rst new file mode 100644 index ..82d2ecedbfee --- /dev/null +++ b/Documentation/userspace-api/media/v4l/ext-ctrls-audio-m2m.rst @@ -0,0 +1,21 @@ +.. SPDX-License-Identifier: GFDL-1.1-no-invariants-or-later + +.. _audiom2m-controls: + +*** +Audio M2M Control Reference +*** + +The Audio M2M class includes controls for audio memory-to-memory +use cases. The controls can be used for audio codecs, audio +preprocessing, audio postprocessing. + +Audio M2M Control IDs +--- + +.. _audiom2m-control-id: + +``V4L2_CID_M2M_AUDIO_CLASS (class)`` +The Audio M2M class descriptor. Calling +:ref:`VIDIOC_QUERYCTRL` for this control will +return a description of this control class. diff --git a/Documentation/userspace-api/media/v4l/vidioc-g-ext-ctrls.rst b/Documentation/userspace-api/media/v4l/vidioc-g-ext-ctrls.rst index 4d56c0528ad7..aeb1ad8e7d29 100644 --- a/Documentation/userspace-api/media/v4l/vidioc-g-ext-ctrls.rst +++ b/Documentation/userspace-api/media/v4l/vidioc-g-ext-ctrls.rst @@ -488,6 +488,10 @@ still cause this situation. - 0xa5 - The class containing colorimetry controls. These controls are described in :ref:`colorimetry-controls`. +* - ``V4L2_CTRL_CLASS_M2M_AUDIO`` + - 0xa6 + - The class containing audio m2m controls. These controls are + described in :ref:`audiom2m-controls`. Return Value diff --git a/drivers/media/v4l2-core/v4l2-ctrls-defs.c b/drivers/media/v4l2-core/v4l2-ctrls-defs.c index 8696eb1cdd61..2a85ea3dc92f 100644 --- a/drivers/media/v4l2-core/v4l2-ctrls-defs.c +++ b/drivers/media/v4l2-core/v4l2-ctrls-defs.c @@ -1242,6 +1242,9 @@ const char *v4l2_ctrl_get_name(u32 id) case V4L2_CID_COLORIMETRY_CLASS:return "Colorimetry Controls"; case V4L2_CID_COLORIMETRY_HDR10_CLL_INFO: return "HDR10 Content Light Info"; case V4L2_CID_COLORIMETRY_HDR10_MASTERING_DISPLAY: return "HDR10 Mastering Display"; + + /* Audio M2M controls */ + case V4L2_CID_M2M_AUDIO_CLASS: return "Audio M2M Controls"; default: return NULL; } @@ -1451,6 +1454,7 @@ void v4l2_ctrl_fill(u32 id, const char **name, enum v4l2_ctrl_type *type, case V4L2_CID_DETECT_CLASS: case V4L2_CID_CODEC_STATELESS_CLASS: case V4L2_CID_COLORIMETRY_CLASS: + case V4L2_CID_M2M_AUDIO_CLASS: *type = V4L2_CTRL_TYPE_CTRL_CLASS; /* You can neither read nor write these */ *flags |= V4L2_CTRL_FLAG_READ_ONLY | V4L2_CTRL_FLAG_WRITE_ONLY; diff --git a/include/uapi/linux/v4l2-controls.h b/include/uapi/linux/v4l2-controls.h index 99c3f5e99da7..a8b4b830c757 100644 --- a/include/uapi/linux/v4l2-controls.h +++ b/include/uapi/linux/v4l2-controls.h @@ -30,6 +30,7 @@ #define V4L2_CTRL_CLASS_DETECT 0x00a3 /* Detection controls */ #define V4L2_CTRL_CLASS_CODEC_STATELESS 0x00a4 /* Stateless codecs controls */ #define V4L2_CTRL_CLASS_COLORIMETRY0x00a5 /* Colorimetry controls */ +#define V4L2_CTRL_CLASS_M2M_AUDIO 0x00a6 /* Audio M2M controls */ /* User-class control IDs */ @@ -3491,6 +3492,9 @@ struct v4l2_ctrl_av1_film_grain { __u8 reserved[4]; }; +#define V4L2_CID_M2M_AUDIO_CLASS_BASE (V4L2_CTRL_CLASS_M2M_AUDIO | 0x900) +#define V4L2_CID_M2M_AUDIO_CLASS (V4L2_CTRL_CLASS_M2M_AUDIO | 1) + /* MPEG-compression definitions kept for backwards compatibility */ #ifndef __KERNEL__ #define V4L2_CTRL_CLASS_MPEGV4L2_CTRL_CLASS_CODEC -- 2.34.1
[PATCH v14 09/16] media: uapi: Define audio sample format fourcc type
The audio sample format definition is from alsa, the header file is include/uapi/sound/asound.h, but don't include this header file directly, because in user space, there is another copy in alsa-lib. There will be conflict in userspace for include videodev2.h & asound.h and asoundlib.h Here still use the fourcc format. Signed-off-by: Shengjiu Wang --- .../userspace-api/media/v4l/pixfmt-audio.rst | 100 ++ .../userspace-api/media/v4l/pixfmt.rst| 1 + drivers/media/v4l2-core/v4l2-ioctl.c | 13 +++ include/uapi/linux/videodev2.h| 29 + 4 files changed, 143 insertions(+) create mode 100644 Documentation/userspace-api/media/v4l/pixfmt-audio.rst diff --git a/Documentation/userspace-api/media/v4l/pixfmt-audio.rst b/Documentation/userspace-api/media/v4l/pixfmt-audio.rst new file mode 100644 index ..a66db9a19936 --- /dev/null +++ b/Documentation/userspace-api/media/v4l/pixfmt-audio.rst @@ -0,0 +1,100 @@ +.. SPDX-License-Identifier: GFDL-1.1-no-invariants-or-later + +.. _pixfmt-audio: + +* +Audio Formats +* + +These formats are used for :ref:`audiomem2mem` interface only. + +All FourCCs starting with 'AU' are reserved for mappings +of the snd_pcm_format_t type. + +The v4l2_audfmt_to_fourcc() is defined to convert the snd_pcm_format_t +type to a FourCC. The first character is 'A', the second character +is 'U', and the remaining two characters is the snd_pcm_format_t +value in ASCII. Example: SNDRV_PCM_FORMAT_S16_LE (with value 2) +maps to 'AU02' and SNDRV_PCM_FORMAT_S24_3LE (with value 32) maps +to 'AU32'." + +The v4l2_fourcc_to_audfmt() is defined to convert these FourCCs to +snd_pcm_format_t type. + +.. tabularcolumns:: |p{5.8cm}|p{1.2cm}|p{10.3cm}| + +.. cssclass:: longtable + +.. flat-table:: Audio Format +:header-rows: 1 +:stub-columns: 0 +:widths: 3 1 4 + +* - Identifier + - Code + - Details +* .. _V4L2-AUDIO-FMT-S8: + + - ``V4L2_AUDIO_FMT_S8`` + - 'S8' + - Corresponds to SNDRV_PCM_FORMAT_S8 in ALSA +* .. _V4L2-AUDIO-FMT-S16-LE: + + - ``V4L2_AUDIO_FMT_S16_LE`` + - 'S16_LE' + - Corresponds to SNDRV_PCM_FORMAT_S16_LE in ALSA +* .. _V4L2-AUDIO-FMT-U16-LE: + + - ``V4L2_AUDIO_FMT_U16_LE`` + - 'U16_LE' + - Corresponds to SNDRV_PCM_FORMAT_U16_LE in ALSA +* .. _V4L2-AUDIO-FMT-S24-LE: + + - ``V4L2_AUDIO_FMT_S24_LE`` + - 'S24_LE' + - Corresponds to SNDRV_PCM_FORMAT_S24_LE in ALSA +* .. _V4L2-AUDIO-FMT-U24-LE: + + - ``V4L2_AUDIO_FMT_U24_LE`` + - 'U24_LE' + - Corresponds to SNDRV_PCM_FORMAT_U24_LE in ALSA +* .. _V4L2-AUDIO-FMT-S32-LE: + + - ``V4L2_AUDIO_FMT_S32_LE`` + - 'S32_LE' + - Corresponds to SNDRV_PCM_FORMAT_S32_LE in ALSA +* .. _V4L2-AUDIO-FMT-U32-LE: + + - ``V4L2_AUDIO_FMT_U32_LE`` + - 'U32_LE' + - Corresponds to SNDRV_PCM_FORMAT_U32_LE in ALSA +* .. _V4L2-AUDIO-FMT-FLOAT-LE: + + - ``V4L2_AUDIO_FMT_FLOAT_LE`` + - 'FLOAT_LE' + - Corresponds to SNDRV_PCM_FORMAT_FLOAT_LE in ALSA +* .. _V4L2-AUDIO-FMT-IEC958-SUBFRAME-LE: + + - ``V4L2_AUDIO_FMT_IEC958_SUBFRAME_LE`` + - 'IEC958_SUBFRAME_LE' + - Corresponds to SNDRV_PCM_FORMAT_IEC958_SUBFRAME_LE in ALSA +* .. _V4L2-AUDIO-FMT-S24-3LE: + + - ``V4L2_AUDIO_FMT_S24_3LE`` + - 'S24_3LE' + - Corresponds to SNDRV_PCM_FORMAT_S24_3LE in ALSA +* .. _V4L2-AUDIO-FMT-U24-3LE: + + - ``V4L2_AUDIO_FMT_U24_3LE`` + - 'U24_3LE' + - Corresponds to SNDRV_PCM_FORMAT_U24_3LE in ALSA +* .. _V4L2-AUDIO-FMT-S20-3LE: + + - ``V4L2_AUDIO_FMT_S20_3LE`` + - 'S20_3LE' + - Corresponds to SNDRV_PCM_FORMAT_S24_3LE in ALSA +* .. _V4L2-AUDIO-FMT-U20-3LE: + + - ``V4L2_AUDIO_FMT_U20_3LE`` + - 'U20_3LE' + - Corresponds to SNDRV_PCM_FORMAT_U20_3LE in ALSA diff --git a/Documentation/userspace-api/media/v4l/pixfmt.rst b/Documentation/userspace-api/media/v4l/pixfmt.rst index 11dab4a90630..2eb6fdd3b43d 100644 --- a/Documentation/userspace-api/media/v4l/pixfmt.rst +++ b/Documentation/userspace-api/media/v4l/pixfmt.rst @@ -36,3 +36,4 @@ see also :ref:`VIDIOC_G_FBUF `.) colorspaces colorspaces-defs colorspaces-details +pixfmt-audio diff --git a/drivers/media/v4l2-core/v4l2-ioctl.c b/drivers/media/v4l2-core/v4l2-ioctl.c index 961abcdf7290..be229c69e991 100644 --- a/drivers/media/v4l2-core/v4l2-ioctl.c +++ b/drivers/media/v4l2-core/v4l2-ioctl.c @@ -1471,6 +1471,19 @@ static void v4l_fill_fmtdesc(struct v4l2_fmtdesc *fmt) case V4L2_PIX_FMT_Y210: descr = "10-bit YUYV Packed"; break; case V4L2_PIX_FMT_Y212: descr = "12-bit YUYV Packed"; break; case V4L2_PIX_FMT_Y216: descr = "16-bit YUYV Packed"; break; + case V4L2_AUDIO_FMT_S8: descr = "8-bit Signed"; break; + case V4L2_AUDIO_FMT_S16_LE: descr = "16-bit Signed LE"; break; + case V4L2_AUDIO_FMT_U16_LE:
[PATCH v14 08/16] media: v4l2: Add audio capture and output support
Audio signal processing has the requirement for memory to memory similar as Video. This patch is to add this support in v4l2 framework, defined new buffer type V4L2_BUF_TYPE_AUDIO_CAPTURE and V4L2_BUF_TYPE_AUDIO_OUTPUT, defined new format v4l2_audio_format for audio case usage. The created audio device is named "/dev/v4l-audioX". Signed-off-by: Shengjiu Wang --- .../userspace-api/media/v4l/buffer.rst| 6 ++ .../media/v4l/dev-audio-mem2mem.rst | 71 +++ .../userspace-api/media/v4l/devices.rst | 1 + .../media/v4l/vidioc-enum-fmt.rst | 2 + .../userspace-api/media/v4l/vidioc-g-fmt.rst | 4 ++ .../media/videodev2.h.rst.exceptions | 2 + .../media/common/videobuf2/videobuf2-v4l2.c | 4 ++ drivers/media/v4l2-core/v4l2-compat-ioctl32.c | 9 +++ drivers/media/v4l2-core/v4l2-dev.c| 17 + drivers/media/v4l2-core/v4l2-ioctl.c | 53 ++ include/media/v4l2-dev.h | 2 + include/media/v4l2-ioctl.h| 34 + include/uapi/linux/videodev2.h| 17 + 13 files changed, 222 insertions(+) create mode 100644 Documentation/userspace-api/media/v4l/dev-audio-mem2mem.rst diff --git a/Documentation/userspace-api/media/v4l/buffer.rst b/Documentation/userspace-api/media/v4l/buffer.rst index 52bbee81c080..a3754ca6f0d6 100644 --- a/Documentation/userspace-api/media/v4l/buffer.rst +++ b/Documentation/userspace-api/media/v4l/buffer.rst @@ -438,6 +438,12 @@ enum v4l2_buf_type * - ``V4L2_BUF_TYPE_META_OUTPUT`` - 14 - Buffer for metadata output, see :ref:`metadata`. +* - ``V4L2_BUF_TYPE_AUDIO_CAPTURE`` + - 15 + - Buffer for audio capture, see :ref:`audio`. +* - ``V4L2_BUF_TYPE_AUDIO_OUTPUT`` + - 16 + - Buffer for audio output, see :ref:`audio`. .. _buffer-flags: diff --git a/Documentation/userspace-api/media/v4l/dev-audio-mem2mem.rst b/Documentation/userspace-api/media/v4l/dev-audio-mem2mem.rst new file mode 100644 index ..54cc2abb6c04 --- /dev/null +++ b/Documentation/userspace-api/media/v4l/dev-audio-mem2mem.rst @@ -0,0 +1,71 @@ +.. SPDX-License-Identifier: GFDL-1.1-no-invariants-or-later + +.. _audiomem2mem: + + +Audio Memory-To-Memory Interface + + +An audio memory-to-memory device can compress, decompress, transform, or +otherwise convert audio data from one format into another format, in memory. +Such memory-to-memory devices set the ``V4L2_CAP_AUDIO_M2M`` capability. +Examples of memory-to-memory devices are audio codecs, audio preprocessing, +audio postprocessing. + +A memory-to-memory audio node supports both output (sending audio frames from +memory to the hardware) and capture (receiving the processed audio frames +from the hardware into memory) stream I/O. An application will have to +setup the stream I/O for both sides and finally call +:ref:`VIDIOC_STREAMON ` for both capture and output to +start the hardware. + +Memory-to-memory devices function as a shared resource: you can +open the audio node multiple times, each application setting up their +own properties that are local to the file handle, and each can use +it independently from the others. The driver will arbitrate access to +the hardware and reprogram it whenever another file handler gets access. + +Audio memory-to-memory devices are accessed through character device +special files named ``/dev/v4l-audio`` + +Querying Capabilities += + +Device nodes supporting the audio memory-to-memory interface set the +``V4L2_CAP_AUDIO_M2M`` flag in the ``device_caps`` field of the +:c:type:`v4l2_capability` structure returned by the :c:func:`VIDIOC_QUERYCAP` +ioctl. + +Data Format Negotiation +=== + +The audio device uses the :ref:`format` ioctls to select the capture format. +The audio buffer content format is bound to that selected format. In addition +to the basic :ref:`format` ioctls, the :c:func:`VIDIOC_ENUM_FMT` ioctl must be +supported as well. + +To use the :ref:`format` ioctls applications set the ``type`` field of the +:c:type:`v4l2_format` structure to ``V4L2_BUF_TYPE_AUDIO_CAPTURE`` or to +``V4L2_BUF_TYPE_AUDIO_OUTPUT``. Both drivers and applications must set the +remainder of the :c:type:`v4l2_format` structure to 0. + +.. c:type:: v4l2_audio_format + +.. tabularcolumns:: |p{1.4cm}|p{2.4cm}|p{13.5cm}| + +.. flat-table:: struct v4l2_audio_format +:header-rows: 0 +:stub-columns: 0 +:widths: 1 1 2 + +* - __u32 + - ``audioformat`` + - The sample format, set by the application. see :ref:`pixfmt-audio` +* - __u32 + - ``channels`` + - The channel number, set by the application. channel number range is +[1, 32]. +* - __u32 + - ``buffersize`` + - Maximum buffer size in bytes required for data. The value is set by the +driver. diff --git
[PATCH v14 07/16] media: uapi: Add V4L2_CAP_AUDIO_M2M capability flag
V4L2_CAP_AUDIO_M2M is similar to V4L2_CAP_VIDEO_M2M flag. It is used for audio memory to memory case. Signed-off-by: Shengjiu Wang --- Documentation/userspace-api/media/v4l/vidioc-querycap.rst| 3 +++ Documentation/userspace-api/media/videodev2.h.rst.exceptions | 1 + include/uapi/linux/videodev2.h | 1 + 3 files changed, 5 insertions(+) diff --git a/Documentation/userspace-api/media/v4l/vidioc-querycap.rst b/Documentation/userspace-api/media/v4l/vidioc-querycap.rst index 6c57b8428356..1c0d97bf192a 100644 --- a/Documentation/userspace-api/media/v4l/vidioc-querycap.rst +++ b/Documentation/userspace-api/media/v4l/vidioc-querycap.rst @@ -173,6 +173,9 @@ specification the ioctl returns an ``EINVAL`` error code. interface. A video overlay device typically stores captured images directly in the video memory of a graphics card, with hardware clipping and scaling. +* - ``V4L2_CAP_AUDIO_M2M`` + - 0x0008 + - The device supports the audio Memory-To-Memory interface. * - ``V4L2_CAP_VBI_CAPTURE`` - 0x0010 - The device supports the :ref:`Raw VBI Capture ` diff --git a/Documentation/userspace-api/media/videodev2.h.rst.exceptions b/Documentation/userspace-api/media/videodev2.h.rst.exceptions index 3e58aac4ef0b..da6d0b8e4c2c 100644 --- a/Documentation/userspace-api/media/videodev2.h.rst.exceptions +++ b/Documentation/userspace-api/media/videodev2.h.rst.exceptions @@ -197,6 +197,7 @@ replace define V4L2_CAP_META_OUTPUT device-capabilities replace define V4L2_CAP_DEVICE_CAPS device-capabilities replace define V4L2_CAP_TOUCH device-capabilities replace define V4L2_CAP_IO_MC device-capabilities +replace define V4L2_CAP_AUDIO_M2M device-capabilities # V4L2 pix flags replace define V4L2_PIX_FMT_PRIV_MAGIC :c:type:`v4l2_pix_format` diff --git a/include/uapi/linux/videodev2.h b/include/uapi/linux/videodev2.h index b8573e9ccde6..5cc2a978fd9c 100644 --- a/include/uapi/linux/videodev2.h +++ b/include/uapi/linux/videodev2.h @@ -473,6 +473,7 @@ struct v4l2_capability { #define V4L2_CAP_VIDEO_CAPTURE 0x0001 /* Is a video capture device */ #define V4L2_CAP_VIDEO_OUTPUT 0x0002 /* Is a video output device */ #define V4L2_CAP_VIDEO_OVERLAY 0x0004 /* Can do video overlay */ +#define V4L2_CAP_AUDIO_M2M 0x0008 /* audio memory to memory */ #define V4L2_CAP_VBI_CAPTURE 0x0010 /* Is a raw VBI capture device */ #define V4L2_CAP_VBI_OUTPUT0x0020 /* Is a raw VBI output device */ #define V4L2_CAP_SLICED_VBI_CAPTURE0x0040 /* Is a sliced VBI capture device */ -- 2.34.1
[PATCH v14 06/16] ASoC: fsl_easrc: register m2m platform device
Register m2m platform device,that user can use M2M feature. Signed-off-by: Shengjiu Wang Acked-by: Mark Brown --- sound/soc/fsl/fsl_easrc.c | 19 +++ 1 file changed, 19 insertions(+) diff --git a/sound/soc/fsl/fsl_easrc.c b/sound/soc/fsl/fsl_easrc.c index cf7ad30a323b..ccbf45c7abf4 100644 --- a/sound/soc/fsl/fsl_easrc.c +++ b/sound/soc/fsl/fsl_easrc.c @@ -2075,6 +2075,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,6 +2191,19 @@ static int fsl_easrc_probe(struct platform_device *pdev) goto err_pm_disable; } + m2m_pdata.asrc = easrc; + m2m_pdata.fmt_in = FSL_EASRC_FORMATS; + m2m_pdata.fmt_out = FSL_EASRC_FORMATS | SNDRV_PCM_FMTBIT_IEC958_SUBFRAME_LE; + m2m_pdata.rate_min = 8000; + m2m_pdata.rate_max = 768000; + m2m_pdata.chan_min = 1; + m2m_pdata.chan_max = 32; + easrc->m2m_pdev = platform_device_register_data(>dev, + M2M_DRV_NAME, + PLATFORM_DEVID_AUTO, + _pdata, + sizeof(m2m_pdata)); + return 0; err_pm_disable: @@ -2199,6 +2213,11 @@ static int fsl_easrc_probe(struct platform_device *pdev) 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
[PATCH v14 05/16] ASoC: fsl_asrc: register m2m platform device
Register m2m platform device, that user can use M2M feature. Defined platform data structure and platform driver name. Signed-off-by: Shengjiu Wang Acked-by: Mark Brown --- include/sound/fsl_asrc_common.h | 23 +++ sound/soc/fsl/fsl_asrc.c| 18 ++ 2 files changed, 41 insertions(+) diff --git a/include/sound/fsl_asrc_common.h b/include/sound/fsl_asrc_common.h index 3b53d366182f..c709b8906929 100644 --- a/include/sound/fsl_asrc_common.h +++ b/include/sound/fsl_asrc_common.h @@ -71,6 +71,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 @@ -103,6 +104,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; @@ -139,6 +141,27 @@ struct fsl_asrc { void *private; }; +/** + * struct fsl_asrc_m2m_pdata - platform data + * @asrc: pointer to struct fsl_asrc + * @fmt_in: input sample format + * @fmt_out: output sample format + * @chan_min: minimum channel number + * @chan_max: maximum channel number + * @rate_min: minimum rate + * @rate_max: maximum rete + */ +struct fsl_asrc_m2m_pdata { + struct fsl_asrc *asrc; + u64 fmt_in; + u64 fmt_out; + int chan_min; + int chan_max; + int rate_min; + int rate_max; +}; + +#define M2M_DRV_NAME "fsl_asrc_m2m" #define DRV_NAME "fsl-asrc-dai" extern struct snd_soc_component_driver fsl_asrc_component; diff --git a/sound/soc/fsl/fsl_asrc.c b/sound/soc/fsl/fsl_asrc.c index 7d8643ee0ba0..5ecb5d869607 100644 --- a/sound/soc/fsl/fsl_asrc.c +++ b/sound/soc/fsl/fsl_asrc.c @@ -1187,6 +1187,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; @@ -1368,6 +1369,18 @@ static int fsl_asrc_probe(struct platform_device *pdev) goto err_pm_get_sync; } + m2m_pdata.asrc = asrc; + m2m_pdata.fmt_in = FSL_ASRC_FORMATS; + m2m_pdata.fmt_out = FSL_ASRC_FORMATS | SNDRV_PCM_FMTBIT_S8; + m2m_pdata.rate_min = 5512; + m2m_pdata.rate_max = 192000; + m2m_pdata.chan_min = 1; + m2m_pdata.chan_max = 10; + asrc->m2m_pdev = platform_device_register_data(>dev, + M2M_DRV_NAME, + PLATFORM_DEVID_AUTO, + _pdata, + sizeof(m2m_pdata)); return 0; err_pm_get_sync: @@ -1380,6 +1393,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
[PATCH v14 04/16] ASoC: fsl_asrc: move fsl_asrc_common.h to include/sound
Move fsl_asrc_common.h to include/sound that it can be included from other drivers. Signed-off-by: Shengjiu Wang Acked-by: Mark Brown --- {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 f501f47242fb..f067bf1ecea7 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 c9f770862662..a24e540876a4 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
[PATCH v14 03/16] ASoC: fsl_easrc: define functions for memory to memory usage
ASRC can be used on memory to memory case, define several functions for m2m usage and export them as function pointer. Signed-off-by: Shengjiu Wang Acked-by: Mark Brown --- sound/soc/fsl/fsl_easrc.c | 214 ++ sound/soc/fsl/fsl_easrc.h | 4 + 2 files changed, 218 insertions(+) diff --git a/sound/soc/fsl/fsl_easrc.c b/sound/soc/fsl/fsl_easrc.c index ec53bda46a46..cf7ad30a323b 100644 --- a/sound/soc/fsl/fsl_easrc.c +++ b/sound/soc/fsl/fsl_easrc.c @@ -1861,6 +1861,211 @@ 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_prepare(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 */ + pair->first_convert = 1; + return 0; +} + +static int fsl_easrc_m2m_start(struct fsl_asrc_pair *pair) +{ + /* start context once */ + if (pair->first_convert) { + fsl_easrc_start_context(pair); + pair->first_convert = 0; + } + + return 0; +} + +static int fsl_easrc_m2m_stop(struct fsl_asrc_pair *pair) +{ + /* Stop pair/context */ + if (!pair->first_convert) { + fsl_easrc_stop_context(pair); + pair->first_convert = 1; + } + + return 0; +} + +/* calculate capture data length according to output data length and sample rate */ +static int fsl_easrc_m2m_calc_out_len(struct fsl_asrc_pair *pair, int input_buffer_length) +{ + struct fsl_asrc *easrc = pair->asrc; + struct fsl_easrc_priv *easrc_priv = easrc->private; + struct fsl_easrc_ctx_priv *ctx_priv = pair->private; + unsigned int in_rate = ctx_priv->in_params.norm_rate; + unsigned int out_rate = ctx_priv->out_params.norm_rate; + unsigned int channels = pair->channels; + unsigned int in_samples, out_samples; + unsigned int in_width, out_width; + unsigned int out_length; + unsigned int frac_bits; + u64 val1, val2; + + switch (easrc_priv->rs_num_taps) { + case EASRC_RS_32_TAPS: + /* integer bits = 5; */ + frac_bits = 39; + break; + case EASRC_RS_64_TAPS: + /* integer bits = 6; */ + frac_bits = 38; + break; + case EASRC_RS_128_TAPS: + /* integer bits = 7; */ + frac_bits = 37; + break; + default: + return -EINVAL; + } + + val1 = (u64)in_rate << frac_bits; + do_div(val1, out_rate); + val1 += (s64)ctx_priv->ratio_mod << (frac_bits - 31); + + in_width = snd_pcm_format_physical_width(ctx_priv->in_params.sample_format) / 8; + out_width = snd_pcm_format_physical_width(ctx_priv->out_params.sample_format) / 8; + + ctx_priv->in_filled_len += input_buffer_length; +
[PATCH v14 02/16] ASoC: fsl_asrc: define functions for memory to memory usage
ASRC can be used on memory to memory case, define several functions for m2m usage. m2m_prepare: prepare for the start step m2m_start: the start step m2m_unprepare: unprepare for stop step, optional m2m_stop: stop step m2m_check_format: check format is supported or not m2m_calc_out_len: calculate output length according to input length m2m_get_maxburst: burst size for dma m2m_pair_suspend: suspend function of pair, optional. m2m_pair_resume: resume function of pair get_output_fifo_size: get remaining data size in FIFO Signed-off-by: Shengjiu Wang Acked-by: Mark Brown --- sound/soc/fsl/fsl_asrc.c| 126 sound/soc/fsl/fsl_asrc.h| 2 + sound/soc/fsl/fsl_asrc_common.h | 37 ++ 3 files changed, 165 insertions(+) diff --git a/sound/soc/fsl/fsl_asrc.c b/sound/soc/fsl/fsl_asrc.c index b793263291dc..7d8643ee0ba0 100644 --- a/sound/soc/fsl/fsl_asrc.c +++ b/sound/soc/fsl/fsl_asrc.c @@ -1063,6 +1063,124 @@ 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_prepare(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; + } + + pair->first_convert = 1; + + return 0; +} + +static int fsl_asrc_m2m_start(struct fsl_asrc_pair *pair) +{ + if (pair->first_convert) { + fsl_asrc_start_pair(pair); + pair->first_convert = 0; + } + /* +* 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(struct fsl_asrc_pair *pair) +{ + if (!pair->first_convert) { + fsl_asrc_stop_pair(pair); + pair->first_convert = 1; + } + + return 0; +} + +/* calculate capture data length according to output data length and sample rate */ +static int fsl_asrc_m2m_calc_out_len(struct fsl_asrc_pair *pair, int input_buffer_length) +{ + unsigned int in_width, out_width; + unsigned int channels = pair->channels; + unsigned int in_samples, out_samples; + unsigned int out_length; + + in_width = snd_pcm_format_physical_width(pair->sample_format[IN]) / 8; + out_width = snd_pcm_format_physical_width(pair->sample_format[OUT]) / 8; + + in_samples = input_buffer_length / in_width / channels; + out_samples = pair->rate[OUT] * in_samples / pair->rate[IN]; + out_length = (out_samples - ASRC_OUTPUT_LAST_SAMPLE) * out_width * channels; + + return out_length; +} + +static int fsl_asrc_m2m_get_maxburst(u8 dir, struct fsl_asrc_pair *pair) +{ + struct fsl_asrc *asrc = pair->asrc; + struct fsl_asrc_priv *asrc_priv = asrc->private; + int wml = (dir == IN) ? ASRC_M2M_INPUTFIFO_WML : ASRC_M2M_OUTPUTFIFO_WML; + + if (!asrc_priv->soc->use_edma) + return wml * pair->channels; + else + return 1; +} + +static int fsl_asrc_m2m_pair_resume(struct fsl_asrc_pair *pair) +{ + struct fsl_asrc *asrc = pair->asrc; + int i; + + for (i = 0; i < pair->channels * 4; i++) + regmap_write(asrc->regmap, REG_ASRDI(pair->index), 0); + + pair->first_convert = 1; + return 0; +} + static int fsl_asrc_runtime_resume(struct device *dev); static int
[PATCH v14 00/16] Add audio support in v4l2 framework
Audio signal processing also has the requirement for memory to memory similar as Video. This asrc memory to memory (memory ->asrc->memory) case is a non real time use case. User fills the input buffer to the asrc module, after conversion, then asrc sends back the output buffer to user. So it is not a traditional ALSA playback and capture case. It is a specific use case, there is no reference in current kernel. v4l2 memory to memory is the closed implementation, v4l2 current support video, image, radio, tuner, touch devices, so it is not complicated to add support for this specific audio case. Because we had implemented the "memory -> asrc ->i2s device-> codec" use case in ALSA. Now the "memory->asrc->memory" needs to reuse the code in asrc driver, so the first 3 patches is for refining the code to make it can be shared by the "memory->asrc->memory" driver. The main change is in the v4l2 side, A /dev/vl4-audioX will be created, user applications only use the ioctl of v4l2 framework. Other change is to add memory to memory support for two kinds of i.MX ASRC module. changes in v14: - document the reservation of 'AUXX' fourcc format. - add v4l2_audfmt_to_fourcc() definition. changes in v13 - change 'pixelformat' to 'audioformat' in dev-audio-mem2mem.rst - add more description for clock drift in ext-ctrls-audio-m2m.rst - Add "media: v4l2-ctrls: add support for fraction_bits" from Hans to avoid build issue for kernel test robot changes in v12 - minor changes according to comments - drop min_buffers_needed = 1 and V4L2_CTRL_FLAG_UPDATE flag - drop bus_info changes in v11 - add add-fixed-point-test-controls in vivid. - add v4l2_ctrl_fp_compose() helper function for min and max changes in v10 - remove FIXED_POINT type - change code base on media: v4l2-ctrls: add support for fraction_bits - fix issue reported by kernel test robot - remove module_alias changes in v9: - add MEDIA_ENT_F_PROC_AUDIO_RESAMPLER. - add MEDIA_INTF_T_V4L_AUDIO - add media controller support - refine the vim2m-audio to support 8k<->16k conversion. changes in v8: - refine V4L2_CAP_AUDIO_M2M to be 0x0008 - update doc for FIXED_POINT - address comments for imx-asrc changes in v7: - add acked-by from Mark - separate commit for fixed point, m2m audio class, audio rate controls - use INTEGER_MENU for rate, FIXED_POINT for rate offset - remove used fmts - address other comments for Hans changes in v6: - use m2m_prepare/m2m_unprepare/m2m_start/m2m_stop to replace m2m_start_part_one/m2m_stop_part_one, m2m_start_part_two/m2m_stop_part_two. - change V4L2_CTRL_TYPE_ASRC_RATE to V4L2_CTRL_TYPE_FIXED_POINT - fix warning by kernel test rebot - remove some unused format V4L2_AUDIO_FMT_XX - Get SNDRV_PCM_FORMAT from V4L2_AUDIO_FMT in driver. - rename audm2m to viaudm2m. changes in v5: - remove V4L2_AUDIO_FMT_LPCM - define audio pixel format like V4L2_AUDIO_FMT_S8... - remove rate and format in struct v4l2_audio_format. - Add V4L2_CID_ASRC_SOURCE_RATE and V4L2_CID_ASRC_DEST_RATE controls - updata document accordingly. changes in v4: - update document style - separate V4L2_AUDIO_FMT_LPCM and V4L2_CAP_AUDIO_M2M in separate commit changes in v3: - Modify documents for adding audio m2m support - Add audio virtual m2m driver - Defined V4L2_AUDIO_FMT_LPCM format type for audio. - Defined V4L2_CAP_AUDIO_M2M capability type for audio m2m case. - with modification in v4l-utils, pass v4l2-compliance test. changes in v2: - decouple the implementation in v4l2 and ALSA - implement the memory to memory driver as a platfrom driver and move it to driver/media - move fsl_asrc_common.h to include/sound folder Hans Verkuil (1): media: v4l2-ctrls: add support for fraction_bits Shengjiu Wang (15): ASoC: fsl_asrc: define functions for memory to memory usage ASoC: fsl_easrc: define functions for memory to memory usage ASoC: fsl_asrc: move fsl_asrc_common.h to include/sound ASoC: fsl_asrc: register m2m platform device ASoC: fsl_easrc: register m2m platform device media: uapi: Add V4L2_CAP_AUDIO_M2M capability flag media: v4l2: Add audio capture and output support media: uapi: Define audio sample format fourcc type media: uapi: Add V4L2_CTRL_CLASS_M2M_AUDIO media: uapi: Add audio rate controls support media: uapi: Declare interface types for Audio media: uapi: Add an entity type for audio resampler media: vivid: add fixed point test controls media: imx-asrc: Add memory to memory driver media: vim2m-audio: add virtual driver for audio memory to memory .../media/mediactl/media-types.rst| 11 + .../userspace-api/media/v4l/buffer.rst|6 + .../userspace-api/media/v4l/common.rst|1 + .../media/v4l/dev-audio-mem2mem.rst | 71 + .../userspace-api/media/v4l/devices.rst |1 + .../media/v4l/ext-ctrls-audio-m2m.rst | 59 + .../userspace-api/media/v4l/pixfmt-audio.rst | 100 ++ .../userspace-api/media/v4l/pixfmt.rst|1 +
[PATCH v14 01/16] media: v4l2-ctrls: add support for fraction_bits
From: Hans Verkuil This adds support for the fraction_bits field, used with integer controls. This allows fixed point formats to be described. The fraction_bits field is only exposed through VIDIOC_QUERY_EXT_CTRL. For a given signed two's complement Qf fixed point value 'f' equals fraction_bits. Signed-off-by: Hans Verkuil --- .../media/v4l/vidioc-queryctrl.rst| 11 ++- drivers/media/v4l2-core/v4l2-ctrls-api.c | 1 + drivers/media/v4l2-core/v4l2-ctrls-core.c | 93 +++ include/media/v4l2-ctrls.h| 7 +- include/uapi/linux/videodev2.h| 3 +- 5 files changed, 95 insertions(+), 20 deletions(-) diff --git a/Documentation/userspace-api/media/v4l/vidioc-queryctrl.rst b/Documentation/userspace-api/media/v4l/vidioc-queryctrl.rst index 4d38acafe8e1..e65c7e5d78ec 100644 --- a/Documentation/userspace-api/media/v4l/vidioc-queryctrl.rst +++ b/Documentation/userspace-api/media/v4l/vidioc-queryctrl.rst @@ -267,7 +267,16 @@ See also the examples in :ref:`control`. - The size of each dimension. The first ``nr_of_dims`` elements of this array must be non-zero, all remaining elements must be zero. * - __u32 - - ``reserved``\ [32] + - ``fraction_bits`` + - The number of least significant bits of the control value that +form the fraction of the fixed point value. This is 0 if the value + is a regular integer. This can be used with all integer control types + (``INTEGER``, ``INTEGER64``, ``U8``, ``U16`` and ``U32``). + For the signed types the signed two's complement representation is used. + This field applies to the control value as well as the ``minimum``, + ``maximum``, ``step`` and ``default_value`` fields. +* - __u32 + - ``reserved``\ [31] - Reserved for future extensions. Applications and drivers must set the array to zero. diff --git a/drivers/media/v4l2-core/v4l2-ctrls-api.c b/drivers/media/v4l2-core/v4l2-ctrls-api.c index d9a422017bd9..ef16b00421ec 100644 --- a/drivers/media/v4l2-core/v4l2-ctrls-api.c +++ b/drivers/media/v4l2-core/v4l2-ctrls-api.c @@ -1101,6 +1101,7 @@ int v4l2_query_ext_ctrl(struct v4l2_ctrl_handler *hdl, struct v4l2_query_ext_ctr qc->elems = ctrl->elems; qc->nr_of_dims = ctrl->nr_of_dims; memcpy(qc->dims, ctrl->dims, qc->nr_of_dims * sizeof(qc->dims[0])); + qc->fraction_bits = ctrl->fraction_bits; qc->minimum = ctrl->minimum; qc->maximum = ctrl->maximum; qc->default_value = ctrl->default_value; diff --git a/drivers/media/v4l2-core/v4l2-ctrls-core.c b/drivers/media/v4l2-core/v4l2-ctrls-core.c index c4d995f32191..d83a37198bb5 100644 --- a/drivers/media/v4l2-core/v4l2-ctrls-core.c +++ b/drivers/media/v4l2-core/v4l2-ctrls-core.c @@ -252,12 +252,61 @@ void v4l2_ctrl_type_op_init(const struct v4l2_ctrl *ctrl, u32 from_idx, } EXPORT_SYMBOL(v4l2_ctrl_type_op_init); +static void v4l2_ctrl_log_fp(s64 v, unsigned int fraction_bits) +{ + s64 i, f, mask; + + if (!fraction_bits) { + pr_cont("%lld", v); + return; + } + + mask = (1ULL << fraction_bits) - 1; + + /* +* Note: this function does not support fixed point u64 with +* fraction_bits set to 64. At the moment there is no U64 +* control type, but if that is added, then this code will have +* to add support for it. +*/ + if (fraction_bits >= 63) + i = v < 0 ? -1 : 0; + else + i = div64_s64(v, 1LL << fraction_bits); + + f = v < 0 ? -((-v) & mask) : (v & mask); + + if (!f) { + pr_cont("%lld", i); + } else if (fraction_bits < 20) { + u64 div = 1ULL << fraction_bits; + + if (!i && f < 0) + pr_cont("-%lld/%llu", -f, div); + else if (!i) + pr_cont("%lld/%llu", f, div); + else if (i < 0 || f < 0) + pr_cont("-%lld-%llu/%llu", -i, -f, div); + else + pr_cont("%lld+%llu/%llu", i, f, div); + } else { + if (!i && f < 0) + pr_cont("-%lld/(2^%u)", -f, fraction_bits); + else if (!i) + pr_cont("%lld/(2^%u)", f, fraction_bits); + else if (i < 0 || f < 0) + pr_cont("-%lld-%llu/(2^%u)", -i, -f, fraction_bits); + else + pr_cont("%lld+%llu/(2^%u)", i, f, fraction_bits); + } +} + void v4l2_ctrl_type_op_log(const struct v4l2_ctrl *ctrl) { union v4l2_ctrl_ptr ptr = ctrl->p_cur; if (ctrl->is_array) { - unsigned i; + unsigned int i; for (i = 0; i < ctrl->nr_of_dims; i++) pr_cont("[%u]", ctrl->dims[i]); @@ -266,7 +315,7 @@ void v4l2_ctrl_type_op_log(const struct v4l2_ctrl *ctrl)
Re: [PATCH RFC 00/13] mm/treewide: Remove pXd_huge() API
Le 06/03/2024 à 11:41, pet...@redhat.com a écrit : > From: Peter Xu > > [based on akpm/mm-unstable latest commit a7f399ae964e] > > In previous work [1], we removed the pXd_large() API, which is arch > specific. This patchset further removes the hugetlb pXd_huge() API. > > Hugetlb was never special on creating huge mappings when compared with > other huge mappings. Having a standalone API just to detect such pgtable > entries is more or less redundant, especially after the pXd_leaf() API set > is introduced with/without CONFIG_HUGETLB_PAGE. > > When looking at this problem, a few issues are also exposed that we don't > have a clear definition of the *_huge() variance API. This patchset > started by cleaning these issues first, then replace all *_huge() users to > use *_leaf(), then drop all *_huge() code. > > On x86/sparc, swap entries will be reported "true" in pXd_huge(), while for > all the rest archs they're reported "false" instead. This part is done in > patch 1-5, in which I suspect patch 1 can be seen as a bug fix, but I'll > leave that to hmm experts to decide. > > Besides, there are three archs (arm, arm64, powerpc) that have slightly > different definitions between the *_huge() v.s. *_leaf() variances. I > tackled them separately so that it'll be easier for arch experts to chim in > when necessary. This part is done in patch 6-9. > > The final patches 10-13 do the rest on the final removal, since *_leaf() > will be the ultimate API in the future, and we seem to have quite some > confusions on how *_huge() APIs can be defined, provide a rich comment for > *_leaf() API set to define them properly to avoid future misuse, and > hopefully that'll also help new archs to start support huge mappings and > avoid traps (like either swap entries, or PROT_NONE entry checks). > > The whole series is only lightly tested on x86, while as usual I don't have > the capability to test all archs that it touches. > > Marking this series RFC as of now. > > [1] https://lore.kernel.org/r/20240305043750.93762-1-pet...@redhat.com > Hi Peter, and nice job you are doing in cleaning up things around _huge stuff. One thing that might be worth looking at also at some point is the mess around pmd_clear_huge() and pud_clear_huge(). I tried to clean things up with commit c742199a014d ("mm/pgtable: add stubs for {pmd/pub}_{set/clear}_huge") but it was reverted because of arm64 by commit d8a719059b9d ("Revert "mm/pgtable: add stubs for {pmd/pub}_{set/clear}_huge"") So now powerpc/8xx has to implement pmd_clear_huge() and pud_clear_huge() allthough 8xx page hierarchy only has 2 levels. Christophe
Re: [PATCH v8 1/3] powerpc: make fadump resilient with memory add/remove events
On 17/02/24 12:50 pm, Sourabh Jain wrote: Due to changes in memory resources caused by either memory hotplug or online/offline events, the elfcorehdr, which describes the CPUs and memory of the crashed kernel to the kernel that collects the dump (known as second/fadump kernel), becomes outdated. Consequently, attempting dump collection with an outdated elfcorehdr can lead to failed or inaccurate dump collection. Memory hotplug or online/offline events is referred as memory add/remove events in reset of the commit message. The current solution to address the aforementioned issue is as follows: Monitor memory add/remove events in userspace using udev rules, and re-register fadump whenever there are changes in memory resources. This leads to the creation of a new elfcorehdr with updated system memory information. There are several notable issues associated with re-registering fadump for every memory add/remove events. 1. Bulk memory add/remove events with udev-based fadump re-registration can lead to race conditions and, more importantly, it creates a wide window during which fadump is inactive until all memory add/remove events are settled. 2. Re-registering fadump for every memory add/remove event is inefficient. 3. The memory for elfcorehdr is allocated based on the memblock regions available during early boot and remains fixed thereafter. However, if elfcorehdr is later recreated with additional memblock regions, its size will increase, potentially leading to memory corruption. Address the aforementioned challenges by shifting the creation of elfcorehdr from the first kernel (also referred as the crashed kernel), where it was created and frequently recreated for every memory add/remove event, to the fadump kernel. As a result, the elfcorehdr only needs to be created once, thus eliminating the necessity to re-register fadump during memory add/remove events. At present, the first kernel is responsible for preparing the fadump header and storing it in the fadump reserved area. The fadump header includes the start address of the elfcorehdr, crashing CPU details, and other relevant information. In the event of a crash in the first kernel, the second/fadump boots and accesses the fadump header prepared by the first kernel. It then performs the following steps in a platform-specific function [rtas|opal]_fadump_process: 1. Sanity check for fadump header 2. Update CPU notes in elfcorehdr Along with the above, update the setup_fadump()/fadump.c to create elfcorehdr and set its address to the global variable elfcorehdr_addr for the vmcore module to process it in the second/fadump kernel. Section below outlines the information required to create the elfcorehdr and the changes made to make it available to the fadump kernel if it's not already. To create elfcorehdr, the following crashed kernel information is required: CPU notes, vmcoreinfo, and memory ranges. At present, the CPU notes are already prepared in the fadump kernel, so no changes are needed in that regard. The fadump kernel has access to all crashed kernel memory regions, including boot memory regions that are relocated by firmware to fadump reserved areas, so no changes for that either. However, it is necessary to add new members to the fadump header, i.e., the 'fadump_crash_info_header' structure, in order to pass the crashed kernel's vmcoreinfo address and its size to fadump kernel. In addition to the vmcoreinfo address and size, there are a few other attributes also added to the fadump_crash_info_header structure. 1. version: It stores the fadump header version, which is currently set to 1. This provides flexibility to update the fadump crash info header in the future without changing the magic number. For each change in the fadump header, the version will be increased. This will help the updated kernel determine how to handle kernel dumps from older kernels. The magic number remains relevant for checking fadump header corruption. 2. pt_regs_sz/cpu_mask_sz: Store size of pt_regs and cpu_mask structure of first kernel. These attributes are used to prevent dump processing if the sizes of pt_regs or cpu_mask structure differ between the first and fadump kernels. Note: if either first/crashed kernel or second/fadump kernel do not have the changes introduced here then kernel fail to collect the dump and prints relevant error message on the console. Signed-off-by: Sourabh Jain Cc: Aditya Gupta Cc: Aneesh Kumar K.V Cc: Hari Bathini Cc: Mahesh Salgaonkar Cc: Michael Ellerman Cc: Naveen N Rao --- arch/powerpc/include/asm/fadump-internal.h | 31 +- arch/powerpc/kernel/fadump.c | 339 +++ arch/powerpc/platforms/powernv/opal-fadump.c | 22 +- arch/powerpc/platforms/pseries/rtas-fadump.c | 30 +- 4 files changed, 232 insertions(+), 190 deletions(-) diff --git a/arch/powerpc/include/asm/fadump-internal.h
RE: Re: [PATCH v2 4/4] ASoC: fsl: imx-rpmsg: Update to correct DT node
> On 11/03/2024 08:33, Chancel Liu wrote: > >>> @@ -127,6 +126,22 @@ static int imx_rpmsg_probe(struct > platform_device > >> *pdev) > >>> goto fail; > >>> } > >>> > >>> + if (!strcmp(pdev->dev.platform_data, "rpmsg-micfil-channel")) > >>> + np = of_find_node_by_name(NULL, "rpmsg_micfil"); > >>> + else > >>> + np = of_find_node_by_name(NULL, "rpmsg_audio"); > >> > >> Why do you create ABI on node names? Where is it documented? Why > can't > >> you use phandles? > >> > >> Best regards, > >> Krzysztof > > > > Thanks for your reminder. Truly I shouldn't use undocumented bindings. I > will > > use “fsl,rpmsg-channel-name” to refine patch set. Please help review next > > version. > > Instead of hard-coding node names in the driver you want to put it in > "fsl,rpmsg-channel-name" property? I don't follow. I recommended instead > using phandles, care to address that? imx-rpmsg is ASoC machine driver and fsl_rpmsg is ASoC CPU DAI driver. In imx-rpmsg, driver needs to get CPU DAI DT node for hardware configuration. So imx-rpmsg needs some "information" to find the correct DT node. As you recommended, it's not wise to use hard-coding node name. Also the device of imx-rpmsg is created by imx-audio-rpmsg so it can't directly get phandle of CPU DAI node. Sorry for unclear statement. "fsl,rpmsg-channel-name" is the property of rpmsg channel name. Each rpmsg sound card sits on one rpmsg channel. So I decide to use rpmsg channel name to connect all parts of this sound card. If the CPU DAI is registerd with rpmsg channel name then imx-rpmsg can easily get the DT node by this name. Regards, Chancel Liu
Re: [PATCH v2 4/4] ASoC: fsl: imx-rpmsg: Update to correct DT node
On 11/03/2024 08:33, Chancel Liu wrote: >>> @@ -127,6 +126,22 @@ static int imx_rpmsg_probe(struct platform_device >> *pdev) >>> goto fail; >>> } >>> >>> + if (!strcmp(pdev->dev.platform_data, "rpmsg-micfil-channel")) >>> + np = of_find_node_by_name(NULL, "rpmsg_micfil"); >>> + else >>> + np = of_find_node_by_name(NULL, "rpmsg_audio"); >> >> Why do you create ABI on node names? Where is it documented? Why can't >> you use phandles? >> >> Best regards, >> Krzysztof > > Thanks for your reminder. Truly I shouldn't use undocumented bindings. I will > use “fsl,rpmsg-channel-name” to refine patch set. Please help review next > version. Instead of hard-coding node names in the driver you want to put it in "fsl,rpmsg-channel-name" property? I don't follow. I recommended instead using phandles, care to address that? Best regards, Krzysztof
RE: Re: [PATCH v2 4/4] ASoC: fsl: imx-rpmsg: Update to correct DT node
> On 07/03/2024 08:44, Chancel Liu wrote: > > Platform device for card to probe is registered in imx-audio-rpmsg. > > According to this change DT node of ASoC CPU DAI device is updated. > > > > Signed-off-by: Chancel Liu > > --- > > sound/soc/fsl/imx-rpmsg.c | 21 ++--- > > 1 file changed, 18 insertions(+), 3 deletions(-) > > > > diff --git a/sound/soc/fsl/imx-rpmsg.c b/sound/soc/fsl/imx-rpmsg.c > > index e5bd63dab10c..2686125b3043 100644 > > --- a/sound/soc/fsl/imx-rpmsg.c > > +++ b/sound/soc/fsl/imx-rpmsg.c > > @@ -108,10 +108,9 @@ static int imx_rpmsg_late_probe(struct > snd_soc_card *card) > > static int imx_rpmsg_probe(struct platform_device *pdev) > > { > > struct snd_soc_dai_link_component *dlc; > > - struct device *dev = pdev->dev.parent; > > /* rpmsg_pdev is the platform device for the rpmsg node that probed > us */ > > - struct platform_device *rpmsg_pdev = to_platform_device(dev); > > - struct device_node *np = rpmsg_pdev->dev.of_node; > > + struct platform_device *rpmsg_pdev = NULL; > > + struct device_node *np = NULL; > > struct of_phandle_args args; > > const char *platform_name; > > struct imx_rpmsg *data; > > @@ -127,6 +126,22 @@ static int imx_rpmsg_probe(struct platform_device > *pdev) > > goto fail; > > } > > > > + if (!strcmp(pdev->dev.platform_data, "rpmsg-micfil-channel")) > > + np = of_find_node_by_name(NULL, "rpmsg_micfil"); > > + else > > + np = of_find_node_by_name(NULL, "rpmsg_audio"); > > Why do you create ABI on node names? Where is it documented? Why can't > you use phandles? > > Best regards, > Krzysztof Thanks for your reminder. Truly I shouldn't use undocumented bindings. I will use “fsl,rpmsg-channel-name” to refine patch set. Please help review next version. Regards, Chancel Liu