Re: [PATCH V3 01/14] blk-mq: add blk_mq_max_nr_hw_queues()

2023-08-09 Thread Baoquan He
On 08/10/23 at 10:06am, Ming Lei wrote:
> On Thu, Aug 10, 2023 at 09:18:27AM +0800, Baoquan He wrote:
> > On 08/10/23 at 08:09am, Ming Lei wrote:
> > > On Wed, Aug 09, 2023 at 03:44:01PM +0200, Christoph Hellwig wrote:
> > > > I'm starting to sound like a broken record, but we can't just do random
> > > > is_kdump checks, and it's not going to get better by resending it again 
> > > > and
> > > > again.  If kdump kernels limit the number of possible CPUs, it needs to
> > > > reflected in cpu_possible_map and we need to use that information.
> > > > 
> > > 
> > > Can you look at previous kdump/arch guys' comment about kdump usage &
> > > num_possible_cpus?
> > > 
> > > 
> > > https://lore.kernel.org/linux-block/caf+s44ruqswbosy9kmdx35crviqnxoeuvgnsue75bb0y2jg...@mail.gmail.com/
> > > https://lore.kernel.org/linux-block/ZKz912KyFQ7q9qwL@MiWiFi-R3L-srv/
> > > 
> > > The point is that kdump kernels does not limit the number of possible 
> > > CPUs.
> > > 
> > > 1) some archs support 'nr_cpus=1' for kdump kernel, which is fine, since
> > > num_possible_cpus becomes 1.
> > 
> > Yes, "nr_cpus=" is strongly suggested in kdump kernel because "nr_cpus="
> > limits the possible cpu numbers, while "maxcpuss=" only limits the cpu
> > number which can be brought up during bootup. We noticed this diference
> > because a large number of possible cpus will cost more memory in kdump
> > kernel. e.g percpu initialization, even though kdump kernel have set
> > "maxcpus=1". 
> > 
> > Currently x86 and arm64 all support "nr_cpus=". Pingfan ever spent much
> > effort to make patches to add "nr_cpus=" support to ppc64, seems ppc64
> > dev and maintainers do not care about it. Finally the patches are not
> > accepted, and the work is not continued.
> > 
> > Now, I am wondering what is the barrier to add "nr_cpus=" to power ach.
> > Can we reconsider adding 'nr_cpus=' to power arch since real issue
> > occurred in kdump kernel?
> 
> If 'nr_cpus=' can be supported on ppc64, this patchset isn't needed.
> 
> > 
> > As for this patchset, it can be accpeted so that no failure in kdump
> > kernel is seen on ARCHes w/o "nr_cpus=" support? My personal opinion.
> 
> IMO 'nr_cpus=' support should be preferred, given it is annoying to
> maintain two kinds of implementation for kdump kernel from driver
> viewpoint. I guess kdump things can be simplified too with supporting
> 'nr_cpus=' only.

Yes, 'nr_cpus=' is ideal. Not sure if there's some underlying concerns so
that power people decided to not support it.



Re: [PATCH V3 01/14] blk-mq: add blk_mq_max_nr_hw_queues()

2023-08-09 Thread Ming Lei
On Thu, Aug 10, 2023 at 09:18:27AM +0800, Baoquan He wrote:
> On 08/10/23 at 08:09am, Ming Lei wrote:
> > On Wed, Aug 09, 2023 at 03:44:01PM +0200, Christoph Hellwig wrote:
> > > I'm starting to sound like a broken record, but we can't just do random
> > > is_kdump checks, and it's not going to get better by resending it again 
> > > and
> > > again.  If kdump kernels limit the number of possible CPUs, it needs to
> > > reflected in cpu_possible_map and we need to use that information.
> > > 
> > 
> > Can you look at previous kdump/arch guys' comment about kdump usage &
> > num_possible_cpus?
> > 
> > 
> > https://lore.kernel.org/linux-block/caf+s44ruqswbosy9kmdx35crviqnxoeuvgnsue75bb0y2jg...@mail.gmail.com/
> > https://lore.kernel.org/linux-block/ZKz912KyFQ7q9qwL@MiWiFi-R3L-srv/
> > 
> > The point is that kdump kernels does not limit the number of possible CPUs.
> > 
> > 1) some archs support 'nr_cpus=1' for kdump kernel, which is fine, since
> > num_possible_cpus becomes 1.
> 
> Yes, "nr_cpus=" is strongly suggested in kdump kernel because "nr_cpus="
> limits the possible cpu numbers, while "maxcpuss=" only limits the cpu
> number which can be brought up during bootup. We noticed this diference
> because a large number of possible cpus will cost more memory in kdump
> kernel. e.g percpu initialization, even though kdump kernel have set
> "maxcpus=1". 
> 
> Currently x86 and arm64 all support "nr_cpus=". Pingfan ever spent much
> effort to make patches to add "nr_cpus=" support to ppc64, seems ppc64
> dev and maintainers do not care about it. Finally the patches are not
> accepted, and the work is not continued.
> 
> Now, I am wondering what is the barrier to add "nr_cpus=" to power ach.
> Can we reconsider adding 'nr_cpus=' to power arch since real issue
> occurred in kdump kernel?

If 'nr_cpus=' can be supported on ppc64, this patchset isn't needed.

> 
> As for this patchset, it can be accpeted so that no failure in kdump
> kernel is seen on ARCHes w/o "nr_cpus=" support? My personal opinion.

IMO 'nr_cpus=' support should be preferred, given it is annoying to
maintain two kinds of implementation for kdump kernel from driver
viewpoint. I guess kdump things can be simplified too with supporting
'nr_cpus=' only.

thanks,
Ming



Re: [PATCH V3 01/14] blk-mq: add blk_mq_max_nr_hw_queues()

2023-08-09 Thread Baoquan He
On 08/10/23 at 08:09am, Ming Lei wrote:
> On Wed, Aug 09, 2023 at 03:44:01PM +0200, Christoph Hellwig wrote:
> > I'm starting to sound like a broken record, but we can't just do random
> > is_kdump checks, and it's not going to get better by resending it again and
> > again.  If kdump kernels limit the number of possible CPUs, it needs to
> > reflected in cpu_possible_map and we need to use that information.
> > 
> 
> Can you look at previous kdump/arch guys' comment about kdump usage &
> num_possible_cpus?
> 
> 
> https://lore.kernel.org/linux-block/caf+s44ruqswbosy9kmdx35crviqnxoeuvgnsue75bb0y2jg...@mail.gmail.com/
> https://lore.kernel.org/linux-block/ZKz912KyFQ7q9qwL@MiWiFi-R3L-srv/
> 
> The point is that kdump kernels does not limit the number of possible CPUs.
> 
> 1) some archs support 'nr_cpus=1' for kdump kernel, which is fine, since
> num_possible_cpus becomes 1.

Yes, "nr_cpus=" is strongly suggested in kdump kernel because "nr_cpus="
limits the possible cpu numbers, while "maxcpuss=" only limits the cpu
number which can be brought up during bootup. We noticed this diference
because a large number of possible cpus will cost more memory in kdump
kernel. e.g percpu initialization, even though kdump kernel have set
"maxcpus=1". 

Currently x86 and arm64 all support "nr_cpus=". Pingfan ever spent much
effort to make patches to add "nr_cpus=" support to ppc64, seems ppc64
dev and maintainers do not care about it. Finally the patches are not
accepted, and the work is not continued.

Now, I am wondering what is the barrier to add "nr_cpus=" to power ach.
Can we reconsider adding 'nr_cpus=' to power arch since real issue
occurred in kdump kernel?

As for this patchset, it can be accpeted so that no failure in kdump
kernel is seen on ARCHes w/o "nr_cpus=" support? My personal opinion.

> 
> 2) some archs do not support 'nr_cpus=1', and have to rely on
> 'max_cpus=1', so num_possible_cpus isn't changed, and kernel just boots
> with single online cpu. That causes trouble because blk-mq limits single
> queue.
> 
> Documentation/admin-guide/kdump/kdump.rst
> 
> Thanks, 
> Ming
> 



Re: [PATCH V3 01/14] blk-mq: add blk_mq_max_nr_hw_queues()

2023-08-09 Thread Ming Lei
On Wed, Aug 09, 2023 at 03:44:01PM +0200, Christoph Hellwig wrote:
> I'm starting to sound like a broken record, but we can't just do random
> is_kdump checks, and it's not going to get better by resending it again and
> again.  If kdump kernels limit the number of possible CPUs, it needs to
> reflected in cpu_possible_map and we need to use that information.
> 

Can you look at previous kdump/arch guys' comment about kdump usage &
num_possible_cpus?


https://lore.kernel.org/linux-block/caf+s44ruqswbosy9kmdx35crviqnxoeuvgnsue75bb0y2jg...@mail.gmail.com/
https://lore.kernel.org/linux-block/ZKz912KyFQ7q9qwL@MiWiFi-R3L-srv/

The point is that kdump kernels does not limit the number of possible CPUs.

1) some archs support 'nr_cpus=1' for kdump kernel, which is fine, since
num_possible_cpus becomes 1.

2) some archs do not support 'nr_cpus=1', and have to rely on
'max_cpus=1', so num_possible_cpus isn't changed, and kernel just boots
with single online cpu. That causes trouble because blk-mq limits single
queue.

Documentation/admin-guide/kdump/kdump.rst

Thanks, 
Ming



[PATCH] powerpc/pseries: PLPKS: undo kernel-doc comment notation

2023-08-09 Thread Randy Dunlap
Don't use kernel-doc "/**" comment format for non-kernel-doc comments.
This prevents a kernel-doc warning:

  arch/powerpc/platforms/pseries/plpks.c:186: warning: This comment starts with 
'/**', but isn't a kernel-doc comment. Refer 
Documentation/doc-guide/kernel-doc.rst
  * Label is combination of label attributes + name.

Fixes: 2454a7af0f2a ("powerpc/pseries: define driver for Platform KeyStore")
Signed-off-by: Randy Dunlap 
Reported-by: kernel test robot 
Link: lore.kernel.org/r/202308040430.gxmpanwz-...@intel.com
Cc: Nayna Jain 
Cc: Michael Ellerman 
Cc: linuxppc-dev@lists.ozlabs.org
---
 arch/powerpc/platforms/pseries/plpks.c |2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff -- a/arch/powerpc/platforms/pseries/plpks.c 
b/arch/powerpc/platforms/pseries/plpks.c
--- a/arch/powerpc/platforms/pseries/plpks.c
+++ b/arch/powerpc/platforms/pseries/plpks.c
@@ -194,7 +194,7 @@ static struct plpks_auth *construct_auth
return auth;
 }
 
-/**
+/*
  * Label is combination of label attributes + name.
  * Label attributes are used internally by kernel and not exposed to the user.
  */


Re: [PATCH V5 3/3] skiboot: Update IMC PMU node names for power10

2023-08-09 Thread Reza Arbab

On Mon, Jul 17, 2023 at 08:54:31AM +0530, Athira Rajeev wrote:

@@ -408,14 +469,129 @@ static void disable_unavailable_units(struct dt_node 
*dev)
avl_vec = (0xffULL) << 56;
}

-   for (i = 0; i < ARRAY_SIZE(nest_pmus); i++) {
-   if (!(PPC_BITMASK(i, i) & avl_vec)) {
-   /* Check if the device node exists */
-   target = dt_find_by_name_before_addr(dev, nest_pmus[i]);
-   if (!target)
-   continue;
-   /* Remove the device node */
-   dt_free(target);
+   if (proc_gen == proc_gen_p9) {
+   for (i = 0; i < ARRAY_SIZE(nest_pmus_p9); i++) {
+   if (!(PPC_BITMASK(i, i) & avl_vec)) {


I think all these PPC_BITMASK(i, i) can be changed to PPC_BIT(i).


+   /* Check if the device node exists */
+   target = dt_find_by_name_before_addr(dev, 
nest_pmus_p9[i]);
+   if (!target)
+   continue;
+   /* Remove the device node */
+   dt_free(target);
+   }
+   }
+   } else if (proc_gen == proc_gen_p10) {
+   int val;
+   char name[8];
+
+   for (i = 0; i < 11; i++) {
+   if (!(PPC_BITMASK(i, i) & avl_vec)) {
+   /* Check if the device node exists */
+   target = dt_find_by_name_before_addr(dev, 
nest_pmus_p10[i]);
+   if (!target)
+   continue;
+   /* Remove the device node */
+   dt_free(target);
+   }
+   }
+
+   for (i = 35; i < 41; i++) {
+   if (!(PPC_BITMASK(i, i) & avl_vec)) {
+   /* Check if the device node exists for phb */
+   for (j = 0; j < 3; j++) {
+   snprintf(name, sizeof(name), 
"phb%d_%d", (i-35), j);
+   target = 
dt_find_by_name_before_addr(dev, name);
+   if (!target)
+   continue;
+   /* Remove the device node */
+   dt_free(target);
+   }
+   }
+   }
+
+   for (i = 41; i < 58; i++) {
+   if (!(PPC_BITMASK(i, i) & avl_vec)) {
+   /* Check if the device node exists */
+   target = dt_find_by_name_before_addr(dev, 
nest_pmus_p10[i]);
+   if (!target)
+   continue;
+   /* Remove the device node */
+   dt_free(target);
+   }
+   }


--
Reza Arbab


Re: [PATCH V5 1/3] core/device: Add function to return child node using name at substring "@"

2023-08-09 Thread Reza Arbab

Hi Athira,

I still have a couple of the same questions I asked in v4.

On Mon, Jul 17, 2023 at 08:54:29AM +0530, Athira Rajeev wrote:

Add a function dt_find_by_name_before_addr() that returns the child node if
it matches till first occurrence at "@" of a given name, otherwise NULL.


Given this summary, I don't userstand the following:


+   assert(dt_find_by_name(root, "node@1") == addr1);
+   assert(dt_find_by_name(root, "node0_1@2") == addr2);


Is this behavior required? I don't think it makes sense to call this 
function with a second argument containing '@', so I wouldn't expect it 
to match anything in these cases. The function seems to specifically 
enable it:



+struct dt_node *dt_find_by_name_before_addr(struct dt_node *root, const char 
*name)
+{

[snip]

+   node = strdup(name);
+   if (!node)
+   return NULL;
+   node = strtok(node, "@");


Seems like you could get rid of this and just use name as-is.

I was curious about something else; say we have 'node@1' and 'node@2'.  
Is there an expectation of which it should match?


addr1 = dt_new_addr(root, "node", 0x1);
addr2 = dt_new_addr(root, "node", 0x2);
assert(dt_find_by_name_substr(root, "node") == ???);
   ^^^

--
Reza Arbab


Re: [PATCH v2 3/3] fork: lock VMAs of the parent process when forking

2023-08-09 Thread Mateusz Guzik
On 8/5/23, Suren Baghdasaryan  wrote:
> On Fri, Aug 4, 2023 at 6:06 PM Mateusz Guzik  wrote:
>>
>> On 8/5/23, Linus Torvalds  wrote:
>> > On Fri, 4 Aug 2023 at 16:25, Mateusz Guzik  wrote:
>> >>
>> >> I know of these guys, I think they are excluded as is -- they go
>> >> through access_remote_vm, starting with:
>> >> if (mmap_read_lock_killable(mm))
>> >> return 0;
>> >>
>> >> while dup_mmap already write locks the parent's mm.
>> >
>> > Oh, you're only worried about vma_start_write()?
>> >
>> > That's a non-issue. It doesn't take the lock normally, since it starts
>> > off
>> > with
>> >
>> > if (__is_vma_write_locked(vma, _lock_seq))
>> > return;
>> >
>> > which catches on the lock sequence number already being set.
>> >
>> > So no extra locking there.
>> >
>> > Well, technically there's extra locking because the code stupidly
>> > doesn't initialize new vma allocations to the right sequence number,
>> > but that was talked about here:
>> >
>> >
>> > https://lore.kernel.org/all/CAHk-=wicrwaoeesbuogoqqufvesicbgp3cx0lykgevsfazn...@mail.gmail.com/
>> >
>> > and it's a separate issue.
>> >
>>
>> I'm going to bet one beer this is the issue.
>>
>> The patch I'm responding to only consists of adding the call to
>> vma_start_write and claims the 5% slowdown from it, while fixing
>> crashes if the forking process is multithreaded.
>>
>> For the fix to work it has to lock something against the parent.
>>
>> VMA_ITERATOR(old_vmi, oldmm, 0);
>> [..]
>> for_each_vma(old_vmi, mpnt) {
>> [..]
>> vma_start_write(mpnt);
>>
>> the added line locks an obj in the parent's vm space.
>>
>> The problem you linked looks like pessimization for freshly allocated
>> vmas, but that's what is being operated on here.
>
> Sorry, now I'm having trouble understanding the problem you are
> describing. We are locking the parent's vma before copying it and the
> newly created vma is locked before it's added into the vma tree. What
> is the problem then?
>

Sorry for the late reply!

Looks there has been a bunch of weird talking past one another in this
thread and I don't think trying to straighten it all out is worth any
time.

I think at least the two of us agree that if a single-threaded process
enters dup_mmap an
down_writes the mmap semaphore, then no new thread can pop up in said
process, thus no surprise page faults from that angle. 3rd parties are
supposed to interfaces like access_remote_vm, which down_read said
semaphore and are consequently also not a problem. The only worry here
is that someone is messing with another process memory without the
semaphore, but is very unlikely and patchable in the worst case -- but
someone(tm) has to audit. With all these conditions satisfied one can
elide vma_start_write for a perf win.

Finally, I think we agreed you are going to do the audit ;)

Cheers,
-- 
Mateusz Guzik 


[PATCH v2 1/6] integrity: PowerVM support for loading CA keys on machine keyring

2023-08-09 Thread Nayna Jain
Keys that derive their trust from an entity such as a security officer,
administrator, system owner, or machine owner are said to have "imputed
trust". CA keys with imputed trust can be loaded onto the machine keyring.
The mechanism for loading these keys onto the machine keyring is platform
dependent.

Load keys stored in the variable trustedcadb onto the .machine keyring
on PowerVM platform.

Signed-off-by: Nayna Jain 
Reviewed-and-tested-by: Mimi Zohar 
---
 .../integrity/platform_certs/keyring_handler.c  |  8 
 .../integrity/platform_certs/keyring_handler.h  |  5 +
 .../integrity/platform_certs/load_powerpc.c | 17 +
 3 files changed, 30 insertions(+)

diff --git a/security/integrity/platform_certs/keyring_handler.c 
b/security/integrity/platform_certs/keyring_handler.c
index 8a1124e4d769..1649d047e3b8 100644
--- a/security/integrity/platform_certs/keyring_handler.c
+++ b/security/integrity/platform_certs/keyring_handler.c
@@ -69,6 +69,14 @@ __init efi_element_handler_t get_handler_for_mok(const 
efi_guid_t *sig_type)
return NULL;
 }
 
+__init efi_element_handler_t get_handler_for_ca_keys(const efi_guid_t 
*sig_type)
+{
+   if (efi_guidcmp(*sig_type, efi_cert_x509_guid) == 0)
+   return add_to_machine_keyring;
+
+   return NULL;
+}
+
 /*
  * Return the appropriate handler for particular signature list types found in
  * the UEFI dbx and MokListXRT tables.
diff --git a/security/integrity/platform_certs/keyring_handler.h 
b/security/integrity/platform_certs/keyring_handler.h
index 212d894a8c0c..6f15bb4cc8dc 100644
--- a/security/integrity/platform_certs/keyring_handler.h
+++ b/security/integrity/platform_certs/keyring_handler.h
@@ -29,6 +29,11 @@ efi_element_handler_t get_handler_for_db(const efi_guid_t 
*sig_type);
  */
 efi_element_handler_t get_handler_for_mok(const efi_guid_t *sig_type);
 
+/*
+ * Return the handler for particular signature list types for CA keys.
+ */
+efi_element_handler_t get_handler_for_ca_keys(const efi_guid_t *sig_type);
+
 /*
  * Return the handler for particular signature list types found in the dbx.
  */
diff --git a/security/integrity/platform_certs/load_powerpc.c 
b/security/integrity/platform_certs/load_powerpc.c
index 170789dc63d2..6263ce3b3f1e 100644
--- a/security/integrity/platform_certs/load_powerpc.c
+++ b/security/integrity/platform_certs/load_powerpc.c
@@ -59,6 +59,7 @@ static __init void *get_cert_list(u8 *key, unsigned long 
keylen, u64 *size)
 static int __init load_powerpc_certs(void)
 {
void *db = NULL, *dbx = NULL, *data = NULL;
+   void *trustedca = NULL;
u64 dsize = 0;
u64 offset = 0;
int rc = 0;
@@ -120,6 +121,22 @@ static int __init load_powerpc_certs(void)
kfree(data);
}
 
+   data = get_cert_list("trustedcadb", 12,  );
+   if (!data) {
+   pr_info("Couldn't get trustedcadb list from firmware\n");
+   } else if (IS_ERR(data)) {
+   rc = PTR_ERR(data);
+   pr_err("Error reading trustedcadb from firmware: %d\n", rc);
+   } else {
+   extract_esl(trustedca, data, dsize, offset);
+
+   rc = parse_efi_signature_list("powerpc:trustedca", trustedca, 
dsize,
+ get_handler_for_ca_keys);
+   if (rc)
+   pr_err("Couldn't parse trustedcadb signatures: %d\n", 
rc);
+   kfree(data);
+   }
+
return rc;
 }
 late_initcall(load_powerpc_certs);
-- 
2.31.1



[PATCH v2 6/6] integrity: PowerVM support for loading third party code signing keys

2023-08-09 Thread Nayna Jain
On secure boot enabled PowerVM LPAR, third party code signing keys are
needed during early boot to verify signed third party modules. These
third party keys are stored in moduledb object in the Platform
KeyStore(PKS).

Load third party code signing keys onto .secondary_trusted_keys keyring.

Signed-off-by: Nayna Jain 
---
 certs/system_keyring.c| 23 +++
 include/keys/system_keyring.h |  7 ++
 security/integrity/integrity.h|  1 +
 .../platform_certs/keyring_handler.c  |  8 +++
 .../platform_certs/keyring_handler.h  |  5 
 .../integrity/platform_certs/load_powerpc.c   | 18 ++-
 6 files changed, 61 insertions(+), 1 deletion(-)

diff --git a/certs/system_keyring.c b/certs/system_keyring.c
index b348e0898d34..3435d4936fb2 100644
--- a/certs/system_keyring.c
+++ b/certs/system_keyring.c
@@ -396,3 +396,26 @@ void __init set_platform_trusted_keys(struct key *keyring)
platform_trusted_keys = keyring;
 }
 #endif
+
+void __init add_to_secondary_keyring(const char *source, const void *data,
+size_t len)
+{
+   key_ref_t key;
+   key_perm_t perm;
+   int rc = 0;
+
+   perm = (KEY_POS_ALL & ~KEY_POS_SETATTR) | KEY_USR_VIEW;
+
+   key = key_create_or_update(make_key_ref(secondary_trusted_keys, 1),
+  "asymmetric",
+  NULL, data, len, perm,
+  KEY_ALLOC_NOT_IN_QUOTA);
+   if (IS_ERR(key)) {
+   rc = PTR_ERR(key);
+   pr_err("Problem loading X.509 certificate %d\n", rc);
+   } else {
+   pr_notice("Loaded X.509 cert '%s'\n",
+ key_ref_to_ptr(key)->description);
+   key_ref_put(key);
+   }
+}
diff --git a/include/keys/system_keyring.h b/include/keys/system_keyring.h
index 7e2583208820..4188f75d1bac 100644
--- a/include/keys/system_keyring.h
+++ b/include/keys/system_keyring.h
@@ -50,9 +50,16 @@ int restrict_link_by_digsig_builtin_and_secondary(struct key 
*keyring,
  const struct key_type *type,
  const union key_payload 
*payload,
  struct key *restriction_key);
+void __init add_to_secondary_keyring(const char *source, const void *data,
+size_t len);
+
 #else
 #define restrict_link_by_builtin_and_secondary_trusted 
restrict_link_by_builtin_trusted
 #define restrict_link_by_digsig_builtin_and_secondary 
restrict_link_by_digsig_builtin
+void __init add_to_secondary_keyring(const char *source, const void *data,
+size_t len)
+{
+}
 #endif
 
 #ifdef CONFIG_INTEGRITY_MACHINE_KEYRING
diff --git a/security/integrity/integrity.h b/security/integrity/integrity.h
index d7553c93f5c0..efaa2eb789ad 100644
--- a/security/integrity/integrity.h
+++ b/security/integrity/integrity.h
@@ -228,6 +228,7 @@ static inline int __init integrity_load_cert(const unsigned 
int id,
 {
return 0;
 }
+
 #endif /* CONFIG_INTEGRITY_SIGNATURE */
 
 #ifdef CONFIG_INTEGRITY_ASYMMETRIC_KEYS
diff --git a/security/integrity/platform_certs/keyring_handler.c 
b/security/integrity/platform_certs/keyring_handler.c
index 586027b9a3f5..13ea17207902 100644
--- a/security/integrity/platform_certs/keyring_handler.c
+++ b/security/integrity/platform_certs/keyring_handler.c
@@ -78,6 +78,14 @@ __init efi_element_handler_t get_handler_for_ca_keys(const 
efi_guid_t *sig_type)
return NULL;
 }
 
+__init efi_element_handler_t get_handler_for_code_signing_keys(const 
efi_guid_t *sig_type)
+{
+   if (efi_guidcmp(*sig_type, efi_cert_x509_guid) == 0)
+   return add_to_secondary_keyring;
+
+   return NULL;
+}
+
 /*
  * Return the appropriate handler for particular signature list types found in
  * the UEFI dbx and MokListXRT tables.
diff --git a/security/integrity/platform_certs/keyring_handler.h 
b/security/integrity/platform_certs/keyring_handler.h
index 6f15bb4cc8dc..f92895cc50f6 100644
--- a/security/integrity/platform_certs/keyring_handler.h
+++ b/security/integrity/platform_certs/keyring_handler.h
@@ -34,6 +34,11 @@ efi_element_handler_t get_handler_for_mok(const efi_guid_t 
*sig_type);
  */
 efi_element_handler_t get_handler_for_ca_keys(const efi_guid_t *sig_type);
 
+/*
+ * Return the handler for particular signature list types for code signing 
keys.
+ */
+efi_element_handler_t get_handler_for_code_signing_keys(const efi_guid_t 
*sig_type);
+
 /*
  * Return the handler for particular signature list types found in the dbx.
  */
diff --git a/security/integrity/platform_certs/load_powerpc.c 
b/security/integrity/platform_certs/load_powerpc.c
index 6263ce3b3f1e..32c4e5fbf0fb 100644
--- a/security/integrity/platform_certs/load_powerpc.c
+++ 

[PATCH v2 5/6] integrity: PowerVM machine keyring enablement

2023-08-09 Thread Nayna Jain
Update Kconfig to enable machine keyring and limit to CA certificates
on PowerVM. Only key signing CA keys are allowed.

Signed-off-by: Nayna Jain 
Reviewed-and-tested-by: Mimi Zohar 

---
 security/integrity/Kconfig | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/security/integrity/Kconfig b/security/integrity/Kconfig
index ec6e0d789da1..232191ee09e3 100644
--- a/security/integrity/Kconfig
+++ b/security/integrity/Kconfig
@@ -67,7 +67,9 @@ config INTEGRITY_MACHINE_KEYRING
depends on SECONDARY_TRUSTED_KEYRING
depends on INTEGRITY_ASYMMETRIC_KEYS
depends on SYSTEM_BLACKLIST_KEYRING
-   depends on LOAD_UEFI_KEYS
+   depends on LOAD_UEFI_KEYS || LOAD_PPC_KEYS
+   select INTEGRITY_CA_MACHINE_KEYRING if LOAD_PPC_KEYS
+   select INTEGRITY_CA_MACHINE_KEYRING_MAX if LOAD_PPC_KEYS
help
 If set, provide a keyring to which Machine Owner Keys (MOK) may
 be added. This keyring shall contain just MOK keys.  Unlike keys
-- 
2.31.1



[PATCH v2 4/6] integrity: check whether imputed trust is enabled

2023-08-09 Thread Nayna Jain
trust_moklist() is specific to UEFI enabled systems. Other platforms
rely only on the Kconfig.

Define a generic wrapper named imputed_trust_enabled().

Signed-off-by: Nayna Jain 
Reviewed-off-by: Mimi Zohar 
---
 security/integrity/digsig.c|  2 +-
 security/integrity/integrity.h |  5 +++--
 .../integrity/platform_certs/keyring_handler.c |  3 ++-
 .../integrity/platform_certs/machine_keyring.c | 18 --
 4 files changed, 22 insertions(+), 6 deletions(-)

diff --git a/security/integrity/digsig.c b/security/integrity/digsig.c
index d0704b1597d4..df387de29bfa 100644
--- a/security/integrity/digsig.c
+++ b/security/integrity/digsig.c
@@ -113,7 +113,7 @@ static int __init __integrity_init_keyring(const unsigned 
int id,
} else {
if (id == INTEGRITY_KEYRING_PLATFORM)
set_platform_trusted_keys(keyring[id]);
-   if (id == INTEGRITY_KEYRING_MACHINE && trust_moklist())
+   if (id == INTEGRITY_KEYRING_MACHINE && imputed_trust_enabled())
set_machine_trusted_keys(keyring[id]);
if (id == INTEGRITY_KEYRING_IMA)
load_module_cert(keyring[id]);
diff --git a/security/integrity/integrity.h b/security/integrity/integrity.h
index 7167a6e99bdc..d7553c93f5c0 100644
--- a/security/integrity/integrity.h
+++ b/security/integrity/integrity.h
@@ -320,13 +320,14 @@ static inline void __init add_to_platform_keyring(const 
char *source,
 
 #ifdef CONFIG_INTEGRITY_MACHINE_KEYRING
 void __init add_to_machine_keyring(const char *source, const void *data, 
size_t len);
-bool __init trust_moklist(void);
+bool __init imputed_trust_enabled(void);
 #else
 static inline void __init add_to_machine_keyring(const char *source,
  const void *data, size_t len)
 {
 }
-static inline bool __init trust_moklist(void)
+
+static inline bool __init imputed_trust_enabled(void)
 {
return false;
 }
diff --git a/security/integrity/platform_certs/keyring_handler.c 
b/security/integrity/platform_certs/keyring_handler.c
index 1649d047e3b8..586027b9a3f5 100644
--- a/security/integrity/platform_certs/keyring_handler.c
+++ b/security/integrity/platform_certs/keyring_handler.c
@@ -61,7 +61,8 @@ __init efi_element_handler_t get_handler_for_db(const 
efi_guid_t *sig_type)
 __init efi_element_handler_t get_handler_for_mok(const efi_guid_t *sig_type)
 {
if (efi_guidcmp(*sig_type, efi_cert_x509_guid) == 0) {
-   if (IS_ENABLED(CONFIG_INTEGRITY_MACHINE_KEYRING) && 
trust_moklist())
+   if (IS_ENABLED(CONFIG_INTEGRITY_MACHINE_KEYRING) &&
+   imputed_trust_enabled())
return add_to_machine_keyring;
else
return add_to_platform_keyring;
diff --git a/security/integrity/platform_certs/machine_keyring.c 
b/security/integrity/platform_certs/machine_keyring.c
index 9482e16cb2ca..a401640a63cd 100644
--- a/security/integrity/platform_certs/machine_keyring.c
+++ b/security/integrity/platform_certs/machine_keyring.c
@@ -34,7 +34,8 @@ void __init add_to_machine_keyring(const char *source, const 
void *data, size_t
 * If the restriction check does not pass and the platform keyring
 * is configured, try to add it into that keyring instead.
 */
-   if (rc && efi_enabled(EFI_BOOT) && 
IS_ENABLED(CONFIG_INTEGRITY_PLATFORM_KEYRING))
+   if (rc && efi_enabled(EFI_BOOT) &&
+   IS_ENABLED(CONFIG_INTEGRITY_PLATFORM_KEYRING))
rc = integrity_load_cert(INTEGRITY_KEYRING_PLATFORM, source,
 data, len, perm);
 
@@ -60,7 +61,7 @@ static __init bool uefi_check_trust_mok_keys(void)
return false;
 }
 
-bool __init trust_moklist(void)
+static bool __init trust_moklist(void)
 {
static bool initialized;
static bool trust_mok;
@@ -75,3 +76,16 @@ bool __init trust_moklist(void)
 
return trust_mok;
 }
+
+/*
+ * Provides platform specific check for trusting imputed keys before loading
+ * on .machine keyring. UEFI systems enable this trust based on a variable,
+ * and for other platforms, it is always enabled.
+ */
+bool __init imputed_trust_enabled(void)
+{
+   if (efi_enabled(EFI_BOOT))
+   return trust_moklist();
+
+   return true;
+}
-- 
2.31.1



[PATCH v2 3/6] integrity: remove global variable from machine_keyring.c

2023-08-09 Thread Nayna Jain
trust_mok variable is accessed within a single function locally.

Change trust_mok from global to local static variable.

Signed-off-by: Nayna Jain 
Reviewed-and-tested-by: Mimi Zohar 
---
 security/integrity/platform_certs/machine_keyring.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/security/integrity/platform_certs/machine_keyring.c 
b/security/integrity/platform_certs/machine_keyring.c
index 389a6e7c9245..9482e16cb2ca 100644
--- a/security/integrity/platform_certs/machine_keyring.c
+++ b/security/integrity/platform_certs/machine_keyring.c
@@ -8,8 +8,6 @@
 #include 
 #include "../integrity.h"
 
-static bool trust_mok;
-
 static __init int machine_keyring_init(void)
 {
int rc;
@@ -65,9 +63,11 @@ static __init bool uefi_check_trust_mok_keys(void)
 bool __init trust_moklist(void)
 {
static bool initialized;
+   static bool trust_mok;
 
if (!initialized) {
initialized = true;
+   trust_mok = false;
 
if (uefi_check_trust_mok_keys())
trust_mok = true;
-- 
2.31.1



[PATCH v2 2/6] integrity: ignore keys failing CA restrictions on non-UEFI platform

2023-08-09 Thread Nayna Jain
On non-UEFI platforms, handle restrict_link_by_ca failures differently.

Certificates which do not satisfy CA restrictions on non-UEFI platforms
are ignored.

Signed-off-by: Nayna Jain 
Reviewed-and-tested-by: Mimi Zohar 
---
 security/integrity/platform_certs/machine_keyring.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/security/integrity/platform_certs/machine_keyring.c 
b/security/integrity/platform_certs/machine_keyring.c
index 7aaed7950b6e..389a6e7c9245 100644
--- a/security/integrity/platform_certs/machine_keyring.c
+++ b/security/integrity/platform_certs/machine_keyring.c
@@ -36,7 +36,7 @@ void __init add_to_machine_keyring(const char *source, const 
void *data, size_t
 * If the restriction check does not pass and the platform keyring
 * is configured, try to add it into that keyring instead.
 */
-   if (rc && IS_ENABLED(CONFIG_INTEGRITY_PLATFORM_KEYRING))
+   if (rc && efi_enabled(EFI_BOOT) && 
IS_ENABLED(CONFIG_INTEGRITY_PLATFORM_KEYRING))
rc = integrity_load_cert(INTEGRITY_KEYRING_PLATFORM, source,
 data, len, perm);
 
-- 
2.31.1



[PATCH v2 0/6] Enable loading local and third party keys on PowerVM guest

2023-08-09 Thread Nayna Jain
On a secure boot enabled PowerVM guest, local and third party code signing
keys are needed to verify signed applications, configuration files, and
kernel modules.

Loading these keys onto either the .secondary_trusted_keys or .ima
keyrings requires the certificates be signed by keys on the
.builtin_trusted_keys, .machine or .secondary_trusted_keys keyrings.

Keys on the .builtin_trusted_keys keyring are trusted because of the chain
of trust from secure boot up to and including the linux kernel.  Keys on
the .machine keyring that derive their trust from an entity such as a
security officer, administrator, system owner, or machine owner are said
to have "imputed trust." The type of certificates and the mechanism for
loading them onto the .machine keyring is platform dependent.

Userspace may load certificates onto the .secondary_trusted_keys or .ima
keyrings. However, keys may also need to be loaded by the kernel if they
are needed for verification in early boot time. On PowerVM guest, third
party code signing keys are loaded from the moduledb variable in the
Platform KeyStore(PKS) onto the .secondary_trusted_keys.

The purpose of this patch set is to allow loading of local and third party
code signing keys on PowerVM.

Changelog:

v2:

* Patch 5/6: Update CA restriction to allow only key signing CA's.
* Rebase on Jarkko's master tree - 
https://kernel.googlesource.com/pub/scm/linux/kernel/git/jarkko/linux-tpmdd
* Tested after reverting cfa7522f280aa95 because of build failure due to
this commit.

Nayna Jain (6):
  integrity: PowerVM support for loading CA keys on machine keyring
  integrity: ignore keys failing CA restrictions on non-UEFI platform
  integrity: remove global variable from machine_keyring.c
  integrity: check whether imputed trust is enabled
  integrity: PowerVM machine keyring enablement
  integrity: PowerVM support for loading third party code signing keys

 certs/system_keyring.c| 23 +
 include/keys/system_keyring.h |  7 
 security/integrity/Kconfig|  4 ++-
 security/integrity/digsig.c   |  2 +-
 security/integrity/integrity.h|  6 ++--
 .../platform_certs/keyring_handler.c  | 19 ++-
 .../platform_certs/keyring_handler.h  | 10 ++
 .../integrity/platform_certs/load_powerpc.c   | 33 +++
 .../platform_certs/machine_keyring.c  | 22 ++---
 9 files changed, 117 insertions(+), 9 deletions(-)

-- 
2.31.1


Re: [PATCH v6 2/3] PCI/AER: Disable AER interrupt on suspend

2023-08-09 Thread Bjorn Helgaas
On Fri, Jul 21, 2023 at 11:58:24AM +0800, Kai-Heng Feng wrote:
> On Tue, Jul 18, 2023 at 7:17 PM Bjorn Helgaas  wrote:
> > On Fri, May 12, 2023 at 08:00:13AM +0800, Kai-Heng Feng wrote:
> > > PCIe services that share an IRQ with PME, such as AER or DPC,
> > > may cause a spurious wakeup on system suspend. To prevent this,
> > > disable the AER interrupt notification during the system suspend
> > > process.
> >
> > I see that in this particular BZ dmesg log, PME, AER, and DPC do share
> > the same IRQ, but I don't think this is true in general.
> >
> > Root Ports usually use MSI or MSI-X.  PME and hotplug events use the
> > Interrupt Message Number in the PCIe Capability, but AER uses the one
> > in the AER Root Error Status register, and DPC uses the one in the DPC
> > Capability register.  Those potentially correspond to three distinct
> > MSI/MSI-X vectors.
> >
> > I think this probably has nothing to do with the IRQ being *shared*,
> > but just that putting the downstream component into D3cold, where the
> > link state is L3, may cause the upstream component to log and signal a
> > link-related error as the link goes completely down.
> 
> That's quite likely a better explanation than my wording.
> Assuming AER IRQ and PME IRQ are not shared, does system get woken up
> by AER IRQ?

Rafael could answer this better than I can, but
Documentation/power/suspend-and-interrupts.rst says device interrupts
are generally disabled during suspend after the "late" phase of
suspending devices, i.e.,

  dpm_suspend_noirq
suspend_device_irqs   <-- disable non-wakeup IRQs
dpm_noirq_suspend_devices
  ...
pci_pm_suspend_noirq  # (I assume)
  pci_prepare_to_sleep

I think the downstream component would be put in D3cold by
pci_prepare_to_sleep(), so non-wakeup interrupts should be disabled by
then.

I assume PME would generally *not* be disabled since it's needed for
wakeup, so I think any interrupt that shares the PME IRQ and occurs
during suspend may cause a spurious wakeup.

If so, it's exactly as you said at the beginning: AER/DPC/etc sharing
the PME IRQ may cause spurious wakeups, and we would have to disable
those other interrupts at the source, e.g., by clearing
PCI_ERR_ROOT_CMD_FATAL_EN etc (exactly as your series does).

> > I don't think D0-D3hot should be relevant here because in all those
> > states, the link should be active because the downstream config space
> > remains accessible.  So I'm not sure if it's possible, but I wonder if
> > there's a more targeted place we could do this, e.g., in the path that
> > puts downstream devices in D3cold.
> 
> Let me try to work on this.
> 
> Kai-Heng
> 
> >
> > > As Per PCIe Base Spec 5.0, section 5.2, titled "Link State Power 
> > > Management",
> > > TLP and DLLP transmission are disabled for a Link in L2/L3 Ready (D3hot), 
> > > L2
> > > (D3cold with aux power) and L3 (D3cold) states. So disabling the AER
> > > notification during suspend and re-enabling them during the resume process
> > > should not affect the basic functionality.
> > >
> > > Link: https://bugzilla.kernel.org/show_bug.cgi?id=216295
> > > Reviewed-by: Mika Westerberg 
> > > Signed-off-by: Kai-Heng Feng 
> > > ---
> > > v6:
> > > v5:
> > >  - Wording.
> > >
> > > v4:
> > > v3:
> > >  - No change.
> > >
> > > v2:
> > >  - Only disable AER IRQ.
> > >  - No more check on PME IRQ#.
> > >  - Use helper.
> > >
> > >  drivers/pci/pcie/aer.c | 22 ++
> > >  1 file changed, 22 insertions(+)
> > >
> > > diff --git a/drivers/pci/pcie/aer.c b/drivers/pci/pcie/aer.c
> > > index 1420e1f27105..9c07fdbeb52d 100644
> > > --- a/drivers/pci/pcie/aer.c
> > > +++ b/drivers/pci/pcie/aer.c
> > > @@ -1356,6 +1356,26 @@ static int aer_probe(struct pcie_device *dev)
> > >   return 0;
> > >  }
> > >
> > > +static int aer_suspend(struct pcie_device *dev)
> > > +{
> > > + struct aer_rpc *rpc = get_service_data(dev);
> > > + struct pci_dev *pdev = rpc->rpd;
> > > +
> > > + aer_disable_irq(pdev);
> > > +
> > > + return 0;
> > > +}
> > > +
> > > +static int aer_resume(struct pcie_device *dev)
> > > +{
> > > + struct aer_rpc *rpc = get_service_data(dev);
> > > + struct pci_dev *pdev = rpc->rpd;
> > > +
> > > + aer_enable_irq(pdev);
> > > +
> > > + return 0;
> > > +}
> > > +
> > >  /**
> > >   * aer_root_reset - reset Root Port hierarchy, RCEC, or RCiEP
> > >   * @dev: pointer to Root Port, RCEC, or RCiEP
> > > @@ -1420,6 +1440,8 @@ static struct pcie_port_service_driver aerdriver = {
> > >   .service= PCIE_PORT_SERVICE_AER,
> > >
> > >   .probe  = aer_probe,
> > > + .suspend= aer_suspend,
> > > + .resume = aer_resume,
> > >   .remove = aer_remove,
> > >  };
> > >
> > > --
> > > 2.34.1
> > >


Re: [PATCH] spi: fsl-cpm: Properly define and use IO pointers

2023-08-09 Thread Mark Brown
On Wed, 09 Aug 2023 10:54:27 +0200, Christophe Leroy wrote:
> Sparse reports several issues with IO pointers.
> 
> Fix it by adding missing __iomem flags and using iowriteXXbe()
> generic helpers instead of the powerpc specific out_beXX() ones.
> 
> 

Applied to

   https://git.kernel.org/pub/scm/linux/kernel/git/broonie/spi.git for-next

Thanks!

[1/1] spi: fsl-cpm: Properly define and use IO pointers
  commit: ddaec4e44d4e2a556b51159d48788a85ff67179d

All being well this means that it will be integrated into the linux-next
tree (usually sometime in the next 24 hours) and sent to Linus during
the next merge window (or sooner if it is a bug fix), however if
problems are discovered then the patch may be dropped or reverted.

You may get further e-mails resulting from automated or manual testing
and review of the tree, please engage with people reporting problems and
send followup patches addressing any issues that are reported if needed.

If any updates are required or you are submitting further changes they
should be sent as incremental updates against current git, existing
patches will not be replaced.

Please add any relevant lists and maintainers to the CCs when replying
to this mail.

Thanks,
Mark



Re: [PATCH v3 21/28] net: wan: Add framer framework support

2023-08-09 Thread Herve Codina
Hi Randy,

On Wed, 9 Aug 2023 07:24:32 -0700
Randy Dunlap  wrote:

> Hi,
> 
> On 8/9/23 06:27, Herve Codina wrote:
> > diff --git a/drivers/net/wan/framer/Kconfig b/drivers/net/wan/framer/Kconfig
> > new file mode 100644
> > index ..96ef1e7ba8eb
> > --- /dev/null
> > +++ b/drivers/net/wan/framer/Kconfig
> > @@ -0,0 +1,19 @@
> > +# SPDX-License-Identifier: GPL-2.0-only
> > +#
> > +# FRAMER
> > +#
> > +
> > +menu "Framer Subsystem"
> > +
> > +config GENERIC_FRAMER
> > +   bool "Framer Core"  
> 
> Just curious: any reason that this cannot be tristate (i.e., a loadable 
> module)?
> Thanks.

For the same reasons as generic phy cannot be built as module
  b51fbf9fb0c3 phy-core: Don't allow building phy-core as a module

In the framer case, this allows to have the QMC HDLC driver built on systems
without any framers (no providers and no framer core framework).
Also the framer phandle is optional in the device tree QMC HDLC node.

Regards,
Hervé

> 
> > +   help
> > + Generic Framer support.
> > +
> > + This framework is designed to provide a generic interface for framer
> > + devices present in the kernel. This layer will have the generic
> > + API by which framer drivers can create framer using the framer
> > + framework and framer users can obtain reference to the framer.
> > + All the users of this framework should select this config.
> > +
> > +endmenu  
> 



-- 
Hervé Codina, Bootlin
Embedded Linux and Kernel engineering
https://bootlin.com


Re: [PATCH v3 05/28] soc: fsl: cpm1: qmc: Remove inline function specifiers

2023-08-09 Thread Christophe Leroy


Le 09/08/2023 à 15:27, Herve Codina a écrit :
> The inline function specifier is present on some functions but it is
> better to let the compiler decide inlining or not these functions.

And anyway the compiler can decide to not inline a function marked 
inline since commit ac7c3e4ff401 ("compiler: enable 
CONFIG_OPTIMIZE_INLINING forcibly") followed by commit 889b3c1245de 
("compiler: remove CONFIG_OPTIMIZE_INLINING entirely").

So unless you mark it __always_inline you have no guarranty that the 
compiler does what you tell it to do.

> 
> Remove inline specifiers.
> 
> Fixes: 3178d58e0b97 ("soc: fsl: cpm1: Add support for QMC")
> Signed-off-by: Herve Codina 
> Suggested-by: Andrew Lunn 

Reviewed-by: Christophe Leroy 

> ---
>   drivers/soc/fsl/qe/qmc.c | 14 +++---
>   1 file changed, 7 insertions(+), 7 deletions(-)
> 
> diff --git a/drivers/soc/fsl/qe/qmc.c b/drivers/soc/fsl/qe/qmc.c
> index 2d2a9d88ba6c..459e0bbd723d 100644
> --- a/drivers/soc/fsl/qe/qmc.c
> +++ b/drivers/soc/fsl/qe/qmc.c
> @@ -218,37 +218,37 @@ struct qmc {
>   struct qmc_chan *chans[64];
>   };
>   
> -static inline void qmc_write16(void __iomem *addr, u16 val)
> +static void qmc_write16(void __iomem *addr, u16 val)
>   {
>   iowrite16be(val, addr);
>   }
>   
> -static inline u16 qmc_read16(void __iomem *addr)
> +static u16 qmc_read16(void __iomem *addr)
>   {
>   return ioread16be(addr);
>   }
>   
> -static inline void qmc_setbits16(void __iomem *addr, u16 set)
> +static void qmc_setbits16(void __iomem *addr, u16 set)
>   {
>   qmc_write16(addr, qmc_read16(addr) | set);
>   }
>   
> -static inline void qmc_clrbits16(void __iomem *addr, u16 clr)
> +static void qmc_clrbits16(void __iomem *addr, u16 clr)
>   {
>   qmc_write16(addr, qmc_read16(addr) & ~clr);
>   }
>   
> -static inline void qmc_write32(void __iomem *addr, u32 val)
> +static void qmc_write32(void __iomem *addr, u32 val)
>   {
>   iowrite32be(val, addr);
>   }
>   
> -static inline u32 qmc_read32(void __iomem *addr)
> +static u32 qmc_read32(void __iomem *addr)
>   {
>   return ioread32be(addr);
>   }
>   
> -static inline void qmc_setbits32(void __iomem *addr, u32 set)
> +static void qmc_setbits32(void __iomem *addr, u32 set)
>   {
>   qmc_write32(addr, qmc_read32(addr) | set);
>   }


Re: [PATCH -next] net/ps3_gelic_net: Use ether_addr_to_u64() to convert ethernet address

2023-08-09 Thread Simon Horman
On Tue, Aug 08, 2023 at 07:40:50PM +0800, Li Zetao wrote:
> Use ether_addr_to_u64() to convert an Ethernet address into a u64 value,
> instead of directly calculating, as this is exactly what
> this function does.
> 
> Signed-off-by: Li Zetao 
> ---
>  drivers/net/ethernet/toshiba/ps3_gelic_net.c | 8 +---
>  1 file changed, 1 insertion(+), 7 deletions(-)
> 
> diff --git a/drivers/net/ethernet/toshiba/ps3_gelic_net.c 
> b/drivers/net/ethernet/toshiba/ps3_gelic_net.c
> index 9d535ae59626..77a02819e412 100644
> --- a/drivers/net/ethernet/toshiba/ps3_gelic_net.c
> +++ b/drivers/net/ethernet/toshiba/ps3_gelic_net.c
> @@ -596,7 +596,6 @@ void gelic_net_set_multi(struct net_device *netdev)
>   struct gelic_card *card = netdev_card(netdev);
>   struct netdev_hw_addr *ha;
>   unsigned int i;

Hi Li Zetao,

It looks like i is now unused in this function and should be removed.

> - uint8_t *p;
>   u64 addr;
>   int status;
>  
> @@ -629,12 +628,7 @@ void gelic_net_set_multi(struct net_device *netdev)
>  
>   /* set multicast addresses */
>   netdev_for_each_mc_addr(ha, netdev) {
> - addr = 0;
> - p = ha->addr;
> - for (i = 0; i < ETH_ALEN; i++) {
> - addr <<= 8;
> - addr |= *p++;
> - }
> + addr = ether_addr_to_u64(ha->addr);
>   status = lv1_net_add_multicast_address(bus_id(card),
>  dev_id(card),
>  addr, 0);
> -- 
> 2.34.1

-- 
pw-bot: changes-requested


Re: [PATCH v3 21/28] net: wan: Add framer framework support

2023-08-09 Thread Randy Dunlap
Hi,

On 8/9/23 06:27, Herve Codina wrote:
> diff --git a/drivers/net/wan/framer/Kconfig b/drivers/net/wan/framer/Kconfig
> new file mode 100644
> index ..96ef1e7ba8eb
> --- /dev/null
> +++ b/drivers/net/wan/framer/Kconfig
> @@ -0,0 +1,19 @@
> +# SPDX-License-Identifier: GPL-2.0-only
> +#
> +# FRAMER
> +#
> +
> +menu "Framer Subsystem"
> +
> +config GENERIC_FRAMER
> + bool "Framer Core"

Just curious: any reason that this cannot be tristate (i.e., a loadable module)?
Thanks.

> + help
> +   Generic Framer support.
> +
> +   This framework is designed to provide a generic interface for framer
> +   devices present in the kernel. This layer will have the generic
> +   API by which framer drivers can create framer using the framer
> +   framework and framer users can obtain reference to the framer.
> +   All the users of this framework should select this config.
> +
> +endmenu

-- 
~Randy


Re: [PATCH 1/2] powerpc: mark more local variables as volatile

2023-08-09 Thread Arnd Bergmann
On Wed, Aug 9, 2023, at 15:17, Christophe Leroy wrote:
> Le 09/08/2023 à 15:10, Arnd Bergmann a écrit :
>> From: Arnd Bergmann 
>> 
>> A while ago I created a2305e3de8193 ("powerpc: mark local variables
>> around longjmp as volatile") in order to allow building powerpc with
>> -Wextra enabled on gcc-11.
>
> Should this be explained in 
> https://docs.kernel.org/process/volatile-considered-harmful.html ?
>

My feeling is that these two files are special enough that we
don't have to worry about it in general, there is only one other
caller of setjmp in the kernel, and the setjmp() man page
explicitly mentions this problem and the workaround.

 Arnd


[PATCH v3 28/28] net: wan: fsl_qmc_hdlc: Add framer support

2023-08-09 Thread Herve Codina
Add framer support in the fsl_qmc_hdlc driver in order to be able to
signal carrier changes to the network stack based on the framer status
Also use this framer to provide information related to the E1/T1 line
interface on IF_GET_IFACE and configure the line interface according to
IF_IFACE_{E1,T1} information.

Signed-off-by: Herve Codina 
Reviewed-by: Christophe Leroy 
---
 drivers/net/wan/fsl_qmc_hdlc.c | 239 -
 1 file changed, 235 insertions(+), 4 deletions(-)

diff --git a/drivers/net/wan/fsl_qmc_hdlc.c b/drivers/net/wan/fsl_qmc_hdlc.c
index 4b8cb5761fd1..3efed8fedb40 100644
--- a/drivers/net/wan/fsl_qmc_hdlc.c
+++ b/drivers/net/wan/fsl_qmc_hdlc.c
@@ -8,6 +8,7 @@
  */
 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -27,6 +28,9 @@ struct qmc_hdlc {
struct device *dev;
struct qmc_chan *qmc_chan;
struct net_device *netdev;
+   struct framer *framer;
+   spinlock_t carrier_lock; /* Protect carrier detection */
+   struct notifier_block nb;
bool is_crc32;
spinlock_t tx_lock; /* Protect tx descriptors */
struct qmc_hdlc_desc tx_descs[8];
@@ -40,6 +44,195 @@ static inline struct qmc_hdlc *netdev_to_qmc_hdlc(struct 
net_device *netdev)
return dev_to_hdlc(netdev)->priv;
 }
 
+static int qmc_hdlc_framer_set_carrier(struct qmc_hdlc *qmc_hdlc)
+{
+   struct framer_status framer_status;
+   unsigned long flags;
+   int ret;
+
+   if (!qmc_hdlc->framer)
+   return 0;
+
+   spin_lock_irqsave(_hdlc->carrier_lock, flags);
+
+   ret = framer_get_status(qmc_hdlc->framer, _status);
+   if (ret) {
+   dev_err(qmc_hdlc->dev, "get framer status failed (%d)\n", ret);
+   goto end;
+   }
+   if (framer_status.link_is_on)
+   netif_carrier_on(qmc_hdlc->netdev);
+   else
+   netif_carrier_off(qmc_hdlc->netdev);
+
+end:
+   spin_unlock_irqrestore(_hdlc->carrier_lock, flags);
+   return ret;
+}
+
+static int qmc_hdlc_framer_notifier(struct notifier_block *nb, unsigned long 
action,
+   void *data)
+{
+   struct qmc_hdlc *qmc_hdlc = container_of(nb, struct qmc_hdlc, nb);
+   int ret;
+
+   if (action != FRAMER_EVENT_STATUS)
+   return NOTIFY_DONE;
+
+   ret = qmc_hdlc_framer_set_carrier(qmc_hdlc);
+   return ret ? NOTIFY_DONE : NOTIFY_OK;
+}
+
+static int qmc_hdlc_framer_start(struct qmc_hdlc *qmc_hdlc)
+{
+   struct framer_status framer_status;
+   int ret;
+
+   if (!qmc_hdlc->framer)
+   return 0;
+
+   ret = framer_power_on(qmc_hdlc->framer);
+   if (ret) {
+   dev_err(qmc_hdlc->dev, "framer power-on failed (%d)\n", ret);
+   return ret;
+   }
+
+   /* Be sure that get_status is supported */
+   ret = framer_get_status(qmc_hdlc->framer, _status);
+   if (ret) {
+   dev_err(qmc_hdlc->dev, "get framer status failed (%d)\n", ret);
+   goto framer_power_off;
+   }
+
+   qmc_hdlc->nb.notifier_call = qmc_hdlc_framer_notifier;
+   ret = framer_notifier_register(qmc_hdlc->framer, _hdlc->nb);
+   if (ret) {
+   dev_err(qmc_hdlc->dev, "framer notifier register failed 
(%d)\n", ret);
+   goto framer_power_off;
+   }
+
+   return 0;
+
+framer_power_off:
+   framer_power_off(qmc_hdlc->framer);
+   return ret;
+}
+
+static void qmc_hdlc_framer_stop(struct qmc_hdlc *qmc_hdlc)
+{
+   if (!qmc_hdlc->framer)
+   return;
+
+   framer_notifier_unregister(qmc_hdlc->framer, _hdlc->nb);
+   framer_power_off(qmc_hdlc->framer);
+}
+
+static int qmc_hdlc_framer_set_iface(struct qmc_hdlc *qmc_hdlc, int if_iface,
+const te1_settings *te1)
+{
+   struct framer_config config;
+   int ret;
+
+   if (!qmc_hdlc->framer)
+   return 0;
+
+   ret = framer_get_config(qmc_hdlc->framer, );
+   if (ret)
+   return ret;
+
+   switch (if_iface) {
+   case IF_IFACE_E1:
+   config.iface = FRAMER_IFACE_E1;
+   break;
+   case IF_IFACE_T1:
+   config.iface = FRAMER_IFACE_T1;
+   break;
+   default:
+   return -EINVAL;
+   }
+
+   switch (te1->clock_type) {
+   case CLOCK_DEFAULT:
+   /* Keep current value */
+   break;
+   case CLOCK_EXT:
+   config.clock_type = FRAMER_CLOCK_EXT;
+   break;
+   case CLOCK_INT:
+   config.clock_type = FRAMER_CLOCK_INT;
+   break;
+   default:
+   return -EINVAL;
+   }
+   config.line_clock_rate = te1->clock_rate;
+
+   return framer_set_config(qmc_hdlc->framer, );
+}
+
+static int qmc_hdlc_framer_get_iface(struct qmc_hdlc *qmc_hdlc, int *if_iface, 
te1_settings *te1)
+{
+   struct framer_config config;
+   int 

[PATCH v3 27/28] ASoC: codecs: Add support for the framer codec

2023-08-09 Thread Herve Codina
The framer codec interracts with a framer.
It allows to use some of the framer timeslots as audio channels to
transport audio data over the framer E1/T1/J1 lines.
It also reports line carrier detection events through the ALSA jack
detection feature.

Signed-off-by: Herve Codina 
Reviewed-by: Christophe Leroy 
---
 sound/soc/codecs/Kconfig|  15 ++
 sound/soc/codecs/Makefile   |   2 +
 sound/soc/codecs/framer-codec.c | 413 
 3 files changed, 430 insertions(+)
 create mode 100644 sound/soc/codecs/framer-codec.c

diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig
index f99203ef9b03..a86cdac39b72 100644
--- a/sound/soc/codecs/Kconfig
+++ b/sound/soc/codecs/Kconfig
@@ -110,6 +110,7 @@ config SND_SOC_ALL_CODECS
imply SND_SOC_ES8328_I2C
imply SND_SOC_ES7134
imply SND_SOC_ES7241
+   imply SND_SOC_FRAMER
imply SND_SOC_GTM601
imply SND_SOC_HDAC_HDMI
imply SND_SOC_HDAC_HDA
@@ -1043,6 +1044,20 @@ config SND_SOC_ES8328_SPI
depends on SPI_MASTER
select SND_SOC_ES8328
 
+config SND_SOC_FRAMER
+   tristate "Framer codec"
+   depends on GENERIC_FRAMER
+   help
+ Enable support for the framer codec.
+ The framer codec uses the generic framer infrastructure to transport
+ some audio data over an analog E1/T1/J1 line.
+ This codec allows to use some of the time slots available on the TDM
+ bus on which the framer is connected to transport the audio data.
+
+ To compile this driver as a module, choose M here: the module
+ will be called snd-soc-framer.
+
+
 config SND_SOC_GTM601
tristate 'GTM601 UMTS modem audio codec'
 
diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile
index 32dcc6de58bd..54667274a0f6 100644
--- a/sound/soc/codecs/Makefile
+++ b/sound/soc/codecs/Makefile
@@ -116,6 +116,7 @@ snd-soc-es8326-objs := es8326.o
 snd-soc-es8328-objs := es8328.o
 snd-soc-es8328-i2c-objs := es8328-i2c.o
 snd-soc-es8328-spi-objs := es8328-spi.o
+snd-soc-framer-objs := framer-codec.o
 snd-soc-gtm601-objs := gtm601.o
 snd-soc-hdac-hdmi-objs := hdac_hdmi.o
 snd-soc-hdac-hda-objs := hdac_hda.o
@@ -499,6 +500,7 @@ obj-$(CONFIG_SND_SOC_ES8326)+= snd-soc-es8326.o
 obj-$(CONFIG_SND_SOC_ES8328)   += snd-soc-es8328.o
 obj-$(CONFIG_SND_SOC_ES8328_I2C)+= snd-soc-es8328-i2c.o
 obj-$(CONFIG_SND_SOC_ES8328_SPI)+= snd-soc-es8328-spi.o
+obj-$(CONFIG_SND_SOC_FRAMER)   += snd-soc-framer.o
 obj-$(CONFIG_SND_SOC_GTM601)+= snd-soc-gtm601.o
 obj-$(CONFIG_SND_SOC_HDAC_HDMI) += snd-soc-hdac-hdmi.o
 obj-$(CONFIG_SND_SOC_HDAC_HDA) += snd-soc-hdac-hda.o
diff --git a/sound/soc/codecs/framer-codec.c b/sound/soc/codecs/framer-codec.c
new file mode 100644
index ..e5fcde9ee308
--- /dev/null
+++ b/sound/soc/codecs/framer-codec.c
@@ -0,0 +1,413 @@
+// SPDX-License-Identifier: GPL-2.0
+//
+// Framer ALSA SoC driver
+//
+// Copyright 2023 CS GROUP France
+//
+// Author: Herve Codina 
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#define FRAMER_NB_CHANNEL  32
+#define FRAMER_JACK_MASK (SND_JACK_LINEIN | SND_JACK_LINEOUT)
+
+struct framer_codec {
+   struct framer *framer;
+   struct device *dev;
+   struct snd_soc_jack jack;
+   struct notifier_block nb;
+   struct work_struct carrier_work;
+   int max_chan_playback;
+   int max_chan_capture;
+};
+
+static int framer_dai_set_tdm_slot(struct snd_soc_dai *dai, unsigned int 
tx_mask,
+  unsigned int rx_mask, int slots, int width)
+{
+   struct framer_codec *framer = 
snd_soc_component_get_drvdata(dai->component);
+
+   switch (width) {
+   case 0:
+   /* Not set -> default 8 */
+   case 8:
+   break;
+   default:
+   dev_err(dai->dev, "tdm slot width %d not supported\n", width);
+   return -EINVAL;
+   }
+
+   framer->max_chan_playback = hweight32(tx_mask);
+   if (framer->max_chan_playback > FRAMER_NB_CHANNEL) {
+   dev_err(dai->dev, "too many tx slots defined (mask = 0x%x) 
supported max %d\n",
+   tx_mask, FRAMER_NB_CHANNEL);
+   return -EINVAL;
+   }
+
+   framer->max_chan_capture = hweight32(rx_mask);
+   if (framer->max_chan_capture > FRAMER_NB_CHANNEL) {
+   dev_err(dai->dev, "too many rx slots defined (mask = 0x%x) 
supported max %d\n",
+   rx_mask, FRAMER_NB_CHANNEL);
+   return -EINVAL;
+   }
+
+   return 0;
+}
+
+/*
+ * The constraints for format/channel is to match with the number of 8bit
+ * time-slots available.
+ */
+static int framer_dai_hw_rule_channels_by_format(struct snd_soc_dai *dai,
+struct snd_pcm_hw_params 
*params,
+unsigned int nb_ts)
+{
+   struct 

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

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

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

diff --git a/MAINTAINERS b/MAINTAINERS
index 14041d90f9c8..07a7d9fca3c4 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -11776,6 +11776,15 @@ S: Maintained
 F: arch/mips/lantiq
 F: drivers/soc/lantiq
 
+LANTIQ PEF2256 DRIVER
+M: Herve Codina 
+S: Maintained
+F: Documentation/devicetree/bindings/net/lantiq,pef2256.yaml
+F: drivers/net/wan/framer/pef2256/
+F: drivers/pinctrl/pinctrl-pef2256-regs.h
+F: drivers/pinctrl/pinctrl-pef2256.c
+F: include/linux/framer/pef2256.h
+
 LASI 53c700 driver for PARISC
 M: "James E.J. Bottomley" 
 L: linux-s...@vger.kernel.org
-- 
2.41.0



[PATCH v3 25/28] pinctrl: Add support for the Lantic PEF2256 pinmux

2023-08-09 Thread Herve Codina
The Lantiq PEF2256 is a framer and line interface component designed to
fulfill all required interfacing between an analog E1/T1/J1 line and the
digital PCM system highway/H.100 bus.

This kind of component can be found in old telecommunication system.
It was used to digital transmission of many simultaneous telephone calls
by time-division multiplexing. Also using HDLC protocol, WAN networks
can be reached through the framer.

This pinmux support handles the pin muxing part (pins RP(A..D) and pins
XP(A..D)) of the PEF2256.

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

diff --git a/drivers/pinctrl/Kconfig b/drivers/pinctrl/Kconfig
index 57d57af1f624..a3aa96b59c97 100644
--- a/drivers/pinctrl/Kconfig
+++ b/drivers/pinctrl/Kconfig
@@ -377,6 +377,20 @@ config PINCTRL_PALMAS
  open drain configuration for the Palmas series devices like
  TPS65913, TPS80036 etc.
 
+config PINCTRL_PEF2256
+   tristate "Lantiq PEF2256 (FALC56) pin controller driver"
+   depends on OF && FRAMER_PEF2256
+   select PINMUX
+   select GENERIC_PINCONF
+   help
+ This option enables the pin controller support for the Lantiq PEF2256
+ framer, also known as FALC56.
+
+ If unsure, say N.
+
+ To compile this driver as a module, choose M here: the
+ module will be called pinctrl-pef2256.
+
 config PINCTRL_PIC32
bool "Microchip PIC32 pin controller driver"
depends on OF
diff --git a/drivers/pinctrl/Makefile b/drivers/pinctrl/Makefile
index 482b391b5deb..8f211f7671a8 100644
--- a/drivers/pinctrl/Makefile
+++ b/drivers/pinctrl/Makefile
@@ -40,6 +40,7 @@ obj-$(CONFIG_PINCTRL_MLXBF3)  += pinctrl-mlxbf3.o
 obj-$(CONFIG_PINCTRL_OCELOT)   += pinctrl-ocelot.o
 obj-$(CONFIG_PINCTRL_OXNAS)+= pinctrl-oxnas.o
 obj-$(CONFIG_PINCTRL_PALMAS)   += pinctrl-palmas.o
+obj-$(CONFIG_PINCTRL_PEF2256)  += pinctrl-pef2256.o
 obj-$(CONFIG_PINCTRL_PIC32)+= pinctrl-pic32.o
 obj-$(CONFIG_PINCTRL_PISTACHIO)+= pinctrl-pistachio.o
 obj-$(CONFIG_PINCTRL_RK805)+= pinctrl-rk805.o
diff --git a/drivers/pinctrl/pinctrl-pef2256-regs.h 
b/drivers/pinctrl/pinctrl-pef2256-regs.h
new file mode 100644
index ..cacc492a1623
--- /dev/null
+++ b/drivers/pinctrl/pinctrl-pef2256-regs.h
@@ -0,0 +1,65 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * PEF2256 pinctrl registers definition
+ *
+ * Copyright 2023 CS GROUP France
+ *
+ * Author: Herve Codina 
+ */
+#ifndef __PEF2256_PINCTRL_REGS_H__
+#define __PEF2256_PINCTRL_REGS_H__
+
+#include 
+
+/* Port Configuration 1..4 */
+#define PEF2256_PC1  0x80
+#define PEF2256_PC2  0x81
+#define PEF2256_PC3  0x82
+#define PEF2256_PC4  0x83
+#define PEF2256_12_PC_RPC_MASK   GENMASK(6, 4)
+#define PEF2256_12_PC_RPC_SYPR   FIELD_PREP_CONST(PEF2256_12_PC_RPC_MASK, 0x0)
+#define PEF2256_12_PC_RPC_RFMFIELD_PREP_CONST(PEF2256_12_PC_RPC_MASK, 0x1)
+#define PEF2256_12_PC_RPC_RFMB   FIELD_PREP_CONST(PEF2256_12_PC_RPC_MASK, 0x2)
+#define PEF2256_12_PC_RPC_RSIGM  
FIELD_PREP_CONST(PEF2256_12_PC_RPC_MASK, 0x3)
+#define PEF2256_12_PC_RPC_RSIG   FIELD_PREP_CONST(PEF2256_12_PC_RPC_MASK, 0x4)
+#define PEF2256_12_PC_RPC_DLRFIELD_PREP_CONST(PEF2256_12_PC_RPC_MASK, 0x5)
+#define PEF2256_12_PC_RPC_FREEZE  FIELD_PREP_CONST(PEF2256_12_PC_RPC_MASK, 0x6)
+#define PEF2256_12_PC_RPC_RFSP   FIELD_PREP_CONST(PEF2256_12_PC_RPC_MASK, 0x7)
+#define PEF2256_12_PC_XPC_MASKGENMASK(4, 0)
+#define PEF2256_12_PC_XPC_SYPX   FIELD_PREP_CONST(PEF2256_12_PC_XPC_MASK, 0x0)
+#define PEF2256_12_PC_XPC_XFMS   FIELD_PREP_CONST(PEF2256_12_PC_XPC_MASK, 0x1)
+#define PEF2256_12_PC_XPC_XSIG   FIELD_PREP_CONST(PEF2256_12_PC_XPC_MASK, 0x2)
+#define PEF2256_12_PC_XPC_TCLK   FIELD_PREP_CONST(PEF2256_12_PC_XPC_MASK, 0x3)
+#define PEF2256_12_PC_XPC_XMFB   FIELD_PREP_CONST(PEF2256_12_PC_XPC_MASK, 0x4)
+#define PEF2256_12_PC_XPC_XSIGM  
FIELD_PREP_CONST(PEF2256_12_PC_XPC_MASK, 0x5)
+#define PEF2256_12_PC_XPC_DLXFIELD_PREP_CONST(PEF2256_12_PC_XPC_MASK, 0x6)
+#define PEF2256_12_PC_XPC_XCLK   FIELD_PREP_CONST(PEF2256_12_PC_XPC_MASK, 0x7)
+#define PEF2256_12_PC_XPC_XLTFIELD_PREP_CONST(PEF2256_12_PC_XPC_MASK, 0x8)
+#define PEF2256_2X_PC_RPC_MASK   GENMASK(7, 4)
+#define PEF2256_2X_PC_RPC_SYPR   FIELD_PREP_CONST(PEF2256_2X_PC_RPC_MASK, 0x0)
+#define PEF2256_2X_PC_RPC_RFMFIELD_PREP_CONST(PEF2256_2X_PC_RPC_MASK, 0x1)
+#define PEF2256_2X_PC_RPC_RFMB   FIELD_PREP_CONST(PEF2256_2X_PC_RPC_MASK, 0x2)
+#define PEF2256_2X_PC_RPC_RSIGM  
FIELD_PREP_CONST(PEF2256_2X_PC_RPC_MASK, 0x3)
+#define PEF2256_2X_PC_RPC_RSIG   

[PATCH v3 24/28] net: wan: framer: Add support for the Lantiq PEF2256 framer

2023-08-09 Thread Herve Codina
The Lantiq PEF2256 is a framer and line interface component designed to
fulfill all required interfacing between an analog E1/T1/J1 line and the
digital PCM system highway/H.100 bus.

Signed-off-by: Herve Codina 
Reviewed-by: Christophe Leroy 
---
 drivers/net/wan/framer/Kconfig|  16 +
 drivers/net/wan/framer/Makefile   |   1 +
 drivers/net/wan/framer/pef2256/Makefile   |   8 +
 drivers/net/wan/framer/pef2256/pef2256-regs.h | 250 +
 drivers/net/wan/framer/pef2256/pef2256.c  | 880 ++
 include/linux/framer/pef2256.h|  31 +
 6 files changed, 1186 insertions(+)
 create mode 100644 drivers/net/wan/framer/pef2256/Makefile
 create mode 100644 drivers/net/wan/framer/pef2256/pef2256-regs.h
 create mode 100644 drivers/net/wan/framer/pef2256/pef2256.c
 create mode 100644 include/linux/framer/pef2256.h

diff --git a/drivers/net/wan/framer/Kconfig b/drivers/net/wan/framer/Kconfig
index 96ef1e7ba8eb..ba43d7f162a2 100644
--- a/drivers/net/wan/framer/Kconfig
+++ b/drivers/net/wan/framer/Kconfig
@@ -16,4 +16,20 @@ config GENERIC_FRAMER
  framework and framer users can obtain reference to the framer.
  All the users of this framework should select this config.
 
+config FRAMER_PEF2256
+   tristate "Lantiq PEF2256"
+   depends on OF
+   select GENERIC_FRAMER
+   select MFD_CORE
+   select REGMAP_MMIO
+   help
+ Enable support for the Lantiq PEF2256 (FALC56) framer.
+ The PEF2256 is a framer and line interface between analog E1/T1/J1
+ line and a digital PCM bus.
+
+ If unsure, say N.
+
+ To compile this driver as a module, choose M here: the
+ module will be called framer-pef2256.
+
 endmenu
diff --git a/drivers/net/wan/framer/Makefile b/drivers/net/wan/framer/Makefile
index 78dbd8e563d0..3403f2b14534 100644
--- a/drivers/net/wan/framer/Makefile
+++ b/drivers/net/wan/framer/Makefile
@@ -4,3 +4,4 @@
 #
 
 obj-$(CONFIG_GENERIC_FRAMER)   += framer-core.o
+obj-$(CONFIG_FRAMER_PEF2256)   += pef2256/
diff --git a/drivers/net/wan/framer/pef2256/Makefile 
b/drivers/net/wan/framer/pef2256/Makefile
new file mode 100644
index ..f4d1208dd8a4
--- /dev/null
+++ b/drivers/net/wan/framer/pef2256/Makefile
@@ -0,0 +1,8 @@
+# SPDX-License-Identifier: GPL-2.0
+#
+# Makefile for the pef2256 driver.
+#
+
+obj-$(CONFIG_FRAMER_PEF2256)   += framer-pef2256.o
+
+framer-pef2256-objs:= pef2256.o
diff --git a/drivers/net/wan/framer/pef2256/pef2256-regs.h 
b/drivers/net/wan/framer/pef2256/pef2256-regs.h
new file mode 100644
index ..5d3183c91714
--- /dev/null
+++ b/drivers/net/wan/framer/pef2256/pef2256-regs.h
@@ -0,0 +1,250 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * PEF2256 registers definition
+ *
+ * Copyright 2023 CS GROUP France
+ *
+ * Author: Herve Codina 
+ */
+#ifndef __PEF2256_REGS_H__
+#define __PEF2256_REGS_H__
+
+#include "linux/bitfield.h"
+
+/* Command Register */
+#define PEF2256_CMDR   0x02
+#define PEF2256_CMDR_RRES  BIT(6)
+#define PEF2256_CMDR_XRES  BIT(4)
+#define PEF2256_CMDR_SRES  BIT(0)
+
+/* Interrupt Mask Register 0..5 */
+#define PEF2256_IMR0   0x14
+#define PEF2256_IMR1   0x15
+#define PEF2256_IMR2   0x16
+#define PEF2256_IMR3   0x17
+#define PEF2256_IMR4   0x18
+#define PEF2256_IMR5   0x19
+
+/* Framer Mode Register 0 */
+#define PEF2256_FMR0   0x1C
+#define PEF2256_FMR0_XC_MASK   GENMASK(7, 6)
+#define PEF2256_FMR0_XC_NRZFIELD_PREP_CONST(PEF2256_FMR0_XC_MASK, 0x0)
+#define PEF2256_FMR0_XC_CMIFIELD_PREP_CONST(PEF2256_FMR0_XC_MASK, 0x1)
+#define PEF2256_FMR0_XC_AMIFIELD_PREP_CONST(PEF2256_FMR0_XC_MASK, 0x2)
+#define PEF2256_FMR0_XC_HDB3   FIELD_PREP_CONST(PEF2256_FMR0_XC_MASK, 0x3)
+#define PEF2256_FMR0_RC_MASK   GENMASK(5, 4)
+#define PEF2256_FMR0_RC_NRZFIELD_PREP_CONST(PEF2256_FMR0_RC_MASK, 0x0)
+#define PEF2256_FMR0_RC_CMIFIELD_PREP_CONST(PEF2256_FMR0_RC_MASK, 0x1)
+#define PEF2256_FMR0_RC_AMIFIELD_PREP_CONST(PEF2256_FMR0_RC_MASK, 0x2)
+#define PEF2256_FMR0_RC_HDB3   FIELD_PREP_CONST(PEF2256_FMR0_RC_MASK, 0x3)
+
+/* Framer Mode Register 1 */
+#define PEF2256_FMR1   0x1D
+#define PEF2256_FMR1_XFS   BIT(3)
+#define PEF2256_FMR1_ECM   BIT(2)
+/* SSD is defined on 2 bits. The other bit is on SIC1 register */
+#define PEF2256_FMR1_SSD_MASK  GENMASK(1, 1)
+#define PEF2256_FMR1_SSD_2048  FIELD_PREP_CONST(PEF2256_FMR1_SSD_MASK, 0x0)
+#define PEF2256_FMR1_SSD_4096  FIELD_PREP_CONST(PEF2256_FMR1_SSD_MASK, 0x1)
+#define PEF2256_FMR1_SSD_8192  FIELD_PREP_CONST(PEF2256_FMR1_SSD_MASK, 0x0)
+#define PEF2256_FMR1_SSD_16384 FIELD_PREP_CONST(PEF2256_FMR1_SSD_MASK, 0x1)
+
+/* Framer Mode Register 2 */
+#define PEF2256_FMR2 0x1E
+#define PEF2256_FMR2_RFS_MASKGENMASK(7, 6)
+#define PEF2256_FMR2_RFS_DOUBLEFRAME 
FIELD_PREP_CONST(PEF2256_FMR2_RFS_MASK, 0x0)
+#define 

[PATCH v3 23/28] mfd: core: Ensure disabled devices are skiped without aborting

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

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

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

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



[PATCH v3 22/28] dt-bindings: net: Add the Lantiq PEF2256 E1/T1/J1 framer

2023-08-09 Thread Herve Codina
The Lantiq PEF2256 is a framer and line interface component designed to
fulfill all required interfacing between an analog E1/T1/J1 line and the
digital PCM system highway/H.100 bus.

Signed-off-by: Herve Codina 
---
 .../bindings/net/lantiq,pef2256.yaml  | 219 ++
 1 file changed, 219 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/net/lantiq,pef2256.yaml

diff --git a/Documentation/devicetree/bindings/net/lantiq,pef2256.yaml 
b/Documentation/devicetree/bindings/net/lantiq,pef2256.yaml
new file mode 100644
index ..72f6777afa3a
--- /dev/null
+++ b/Documentation/devicetree/bindings/net/lantiq,pef2256.yaml
@@ -0,0 +1,219 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/net/lantiq,pef2256.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Lantiq PEF2256
+
+maintainers:
+  - Herve Codina 
+
+description:
+  The Lantiq PEF2256, also known as Infineon PEF2256 or FALC56, is a framer and
+  line interface component designed to fulfill all required interfacing between
+  an analog E1/T1/J1 line and the digital PCM system highway/H.100 bus.
+
+properties:
+  compatible:
+items:
+  - const: lantiq,pef2256
+
+  reg:
+maxItems: 1
+
+  clocks:
+items:
+  - description: Master clock
+  - description: System Clock Receive
+  - description: System Clock Transmit
+
+  clock-names:
+items:
+  - const: mclk
+  - const: sclkr
+  - const: sclkx
+
+  interrupts:
+maxItems: 1
+
+  reset-gpios:
+description:
+  GPIO used to reset the device.
+maxItems: 1
+
+  '#framer-cells':
+const: 0
+
+  pinctrl:
+$ref: /schemas/pinctrl/pinctrl.yaml#
+additionalProperties: false
+
+patternProperties:
+  '-pins$':
+type: object
+$ref: /schemas/pinctrl/pincfg-node.yaml#
+additionalProperties: false
+
+properties:
+  pins:
+enum: [ RPA, RPB, RPC, RPD, XPA, XPB, XPC, XPD ]
+
+  function:
+enum: [ SYPR, RFM, RFMB, RSIGM, RSIG, DLR, FREEZE, RFSP, LOS,
+SYPX, XFMS, XSIG, TCLK, XMFB, XSIGM, DLX, XCLK, XLT,
+GPI, GPOH, GPOL ]
+
+required:
+  - pins
+  - function
+
+  lantiq,data-rate-bps:
+$ref: /schemas/types.yaml#/definitions/uint32
+enum: [2048000, 4096000, 8192000, 16384000]
+default: 2048000
+description:
+  Data rate (bit per seconds) on the system highway.
+
+  lantiq,clock-falling-edge:
+$ref: /schemas/types.yaml#/definitions/flag
+description:
+  Data is sent on falling edge of the clock (and received on the rising
+  edge). If 'clock-falling-edge' is not present, data is sent on the
+  rising edge (and received on the falling edge).
+
+  lantiq,channel-phase:
+$ref: /schemas/types.yaml#/definitions/uint32
+enum: [0, 1, 2, 3, 4, 5, 6, 7]
+default: 0
+description:
+  The pef2256 delivers a full frame (32 8bit time-slots in E1 and 24 8bit
+  time-slots 8 8bit signaling in E1/J1) every 125us. This lead to a data
+  rate of 2048000 bit/s. When lantiq,data-rate-bps is more than 2048000
+  bit/s, the data (all 32 8bit) present in the frame are interleave with
+  unused time-slots. The lantiq,channel-phase property allows to set the
+  correct alignment of the interleave mechanism.
+  For instance, suppose lantiq,data-rate-bps = 8192000 (ie 4*2048000), and
+  lantiq,channel-phase = 2, the interleave schema with unused time-slots
+  (nu) and used time-slots (XX) for TSi is
+nu nu XX nu nu nu XX nu nu nu XX nu
+<-- TSi --> <- TSi+1 -> <- TSi+2 ->
+  With lantiq,data-rate-bps = 8192000, and lantiq,channel-phase = 1, the
+  interleave schema is
+nu XX nu nu nu XX nu nu nu XX nu nu
+<-- TSi --> <- TSi+1 -> <- TSi+2 ->
+  With lantiq,data-rate-bps = 4096000 (ie 2*2048000), and
+  lantiq,channel-phase = 1, the interleave schema is
+nuXXnuXXnuXX
+<-- TSi --> <- TSi+1 -> <- TSi+2 ->
+
+patternProperties:
+  '^codec(-([0-9]|[1-2][0-9]|3[0-1]))?$':
+type: object
+$ref: /schemas/sound/dai-common.yaml
+unevaluatedProperties: false
+description:
+  Codec provided by the pef2256. This codec allows to use some of the PCM
+  system highway time-slots as audio channels to transport audio data over
+  the E1/T1/J1 lines.
+  The time-slots used by the codec must be set and so, the properties
+  'dai-tdm-slot-num', 'dai-tdm-slot-width', 'dai-tdm-slot-tx-mask' and
+  'dai-tdm-slot-rx-mask' must be present in the sound card node for
+  sub-nodes that involve the codec. The codec uses 8bit time-slots.
+  'dai-tdm-tdm-slot-with' must be set to 8.
+  The tx and rx masks define the pef2256 time-slots assigned to the codec.
+
+properties:
+  compatible:
+const: lantiq,pef2256-codec
+
+

[PATCH v3 21/28] net: wan: Add framer framework support

2023-08-09 Thread Herve Codina
A framer is a component in charge of an E1/T1 line interface.
Connected usually to a TDM bus, it converts TDM frames to/from E1/T1
frames. It also provides information related to the E1/T1 line.

The framer framework provides a set of APIs for the framer drivers
(framer provider) to create/destroy a framer and APIs for the framer
users (framer consumer) to obtain a reference to the framer, and
use the framer.

This basic implementation provides a framer abstraction for:
 - power on/off the framer
 - get the framer status (line state)
 - be notified on framer status changes
 - get/set the framer configuration

Signed-off-by: Herve Codina 
Reviewed-by: Christophe Leroy 
---
 drivers/net/wan/Kconfig|   2 +
 drivers/net/wan/Makefile   |   2 +
 drivers/net/wan/framer/Kconfig |  19 +
 drivers/net/wan/framer/Makefile|   6 +
 drivers/net/wan/framer/framer-core.c   | 886 +
 include/linux/framer/framer-provider.h | 194 ++
 include/linux/framer/framer.h  | 199 ++
 7 files changed, 1308 insertions(+)
 create mode 100644 drivers/net/wan/framer/Kconfig
 create mode 100644 drivers/net/wan/framer/Makefile
 create mode 100644 drivers/net/wan/framer/framer-core.c
 create mode 100644 include/linux/framer/framer-provider.h
 create mode 100644 include/linux/framer/framer.h

diff --git a/drivers/net/wan/Kconfig b/drivers/net/wan/Kconfig
index 8de99f4b647b..31ab2136cdf1 100644
--- a/drivers/net/wan/Kconfig
+++ b/drivers/net/wan/Kconfig
@@ -95,6 +95,8 @@ config HDLC_X25
 comment "X.25/LAPB support is disabled"
depends on HDLC && (LAPB!=m || HDLC!=m) && LAPB!=y
 
+source "drivers/net/wan/framer/Kconfig"
+
 config PCI200SYN
tristate "Goramo PCI200SYN support"
depends on HDLC && PCI
diff --git a/drivers/net/wan/Makefile b/drivers/net/wan/Makefile
index f338f4830626..00e9b7ee1e01 100644
--- a/drivers/net/wan/Makefile
+++ b/drivers/net/wan/Makefile
@@ -14,6 +14,8 @@ obj-$(CONFIG_HDLC_FR) += hdlc_fr.o
 obj-$(CONFIG_HDLC_PPP) += hdlc_ppp.o
 obj-$(CONFIG_HDLC_X25) += hdlc_x25.o
 
+obj-y  += framer/
+
 obj-$(CONFIG_FARSYNC)  += farsync.o
 
 obj-$(CONFIG_LAPBETHER)+= lapbether.o
diff --git a/drivers/net/wan/framer/Kconfig b/drivers/net/wan/framer/Kconfig
new file mode 100644
index ..96ef1e7ba8eb
--- /dev/null
+++ b/drivers/net/wan/framer/Kconfig
@@ -0,0 +1,19 @@
+# SPDX-License-Identifier: GPL-2.0-only
+#
+# FRAMER
+#
+
+menu "Framer Subsystem"
+
+config GENERIC_FRAMER
+   bool "Framer Core"
+   help
+ Generic Framer support.
+
+ This framework is designed to provide a generic interface for framer
+ devices present in the kernel. This layer will have the generic
+ API by which framer drivers can create framer using the framer
+ framework and framer users can obtain reference to the framer.
+ All the users of this framework should select this config.
+
+endmenu
diff --git a/drivers/net/wan/framer/Makefile b/drivers/net/wan/framer/Makefile
new file mode 100644
index ..78dbd8e563d0
--- /dev/null
+++ b/drivers/net/wan/framer/Makefile
@@ -0,0 +1,6 @@
+# SPDX-License-Identifier: GPL-2.0
+#
+# Makefile for the framer drivers.
+#
+
+obj-$(CONFIG_GENERIC_FRAMER)   += framer-core.o
diff --git a/drivers/net/wan/framer/framer-core.c 
b/drivers/net/wan/framer/framer-core.c
new file mode 100644
index ..6dba19c4a1a1
--- /dev/null
+++ b/drivers/net/wan/framer/framer-core.c
@@ -0,0 +1,886 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Generic Framer framework.
+ *
+ * Copyright 2023 CS GROUP France
+ *
+ * Author: Herve Codina 
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+static struct class *framer_class;
+static DEFINE_MUTEX(framer_provider_mutex);
+static LIST_HEAD(framer_provider_list);
+static DEFINE_IDA(framer_ida);
+
+#define dev_to_framer(a)   (container_of((a), struct framer, dev))
+
+int framer_pm_runtime_get(struct framer *framer)
+{
+   int ret;
+
+   if (!pm_runtime_enabled(>dev))
+   return -EOPNOTSUPP;
+
+   ret = pm_runtime_get(>dev);
+   if (ret < 0 && ret != -EINPROGRESS)
+   pm_runtime_put_noidle(>dev);
+
+   return ret;
+}
+EXPORT_SYMBOL_GPL(framer_pm_runtime_get);
+
+int framer_pm_runtime_get_sync(struct framer *framer)
+{
+   int ret;
+
+   if (!pm_runtime_enabled(>dev))
+   return -EOPNOTSUPP;
+
+   ret = pm_runtime_get_sync(>dev);
+   if (ret < 0)
+   pm_runtime_put_sync(>dev);
+
+   return ret;
+}
+EXPORT_SYMBOL_GPL(framer_pm_runtime_get_sync);
+
+int framer_pm_runtime_put(struct framer *framer)
+{
+   if (!pm_runtime_enabled(>dev))
+   return -EOPNOTSUPP;
+
+   return pm_runtime_put(>dev);
+}
+EXPORT_SYMBOL_GPL(framer_pm_runtime_put);
+
+int 

[PATCH v3 20/28] wan: qmc_hdlc: Add runtime timeslots changes support

2023-08-09 Thread Herve Codina
QMC channels support runtime timeslots changes but nothing is done at
the QMC HDLC driver to handle these changes.

Use existing IFACE ioctl in order to configure the timeslots to use.

Signed-off-by: Herve Codina 
Reviewed-by: Christophe Leroy 
---
 drivers/net/wan/fsl_qmc_hdlc.c | 169 -
 1 file changed, 168 insertions(+), 1 deletion(-)

diff --git a/drivers/net/wan/fsl_qmc_hdlc.c b/drivers/net/wan/fsl_qmc_hdlc.c
index 4f84ac5fc63e..4b8cb5761fd1 100644
--- a/drivers/net/wan/fsl_qmc_hdlc.c
+++ b/drivers/net/wan/fsl_qmc_hdlc.c
@@ -32,6 +32,7 @@ struct qmc_hdlc {
struct qmc_hdlc_desc tx_descs[8];
unsigned int tx_out;
struct qmc_hdlc_desc rx_descs[4];
+   u32 slot_map;
 };
 
 static inline struct qmc_hdlc *netdev_to_qmc_hdlc(struct net_device *netdev)
@@ -202,6 +203,162 @@ static netdev_tx_t qmc_hdlc_xmit(struct sk_buff *skb, 
struct net_device *netdev)
return NETDEV_TX_OK;
 }
 
+static int qmc_hdlc_xlate_slot_map(struct qmc_hdlc *qmc_hdlc,
+  u32 slot_map, struct qmc_chan_ts_info 
*ts_info)
+{
+   u64 ts_mask_avail;
+   unsigned int bit;
+   unsigned int i;
+   u64 ts_mask;
+   u64 map = 0;
+
+   /* Tx and Rx masks must be identical */
+   if (ts_info->rx_ts_mask_avail != ts_info->tx_ts_mask_avail) {
+   dev_err(qmc_hdlc->dev, "tx and rx available timeslots mismatch 
(0x%llx, 0x%llx)\n",
+   ts_info->rx_ts_mask_avail, ts_info->tx_ts_mask_avail);
+   return -EINVAL;
+   }
+
+   ts_mask_avail = ts_info->rx_ts_mask_avail;
+   ts_mask = 0;
+   map = slot_map;
+   bit = 0;
+   for (i = 0; i < 64; i++) {
+   if (ts_mask_avail & BIT_ULL(i)) {
+   if (map & BIT_ULL(bit))
+   ts_mask |= BIT_ULL(i);
+   bit++;
+   }
+   }
+
+   if (hweight64(ts_mask) != hweight64(map)) {
+   dev_err(qmc_hdlc->dev, "Cannot translate timeslots 0x%llx -> 
(0x%llx,0x%llx)\n",
+   map, ts_mask_avail, ts_mask);
+   return -EINVAL;
+   }
+
+   ts_info->tx_ts_mask = ts_mask;
+   ts_info->rx_ts_mask = ts_mask;
+   return 0;
+}
+
+static int qmc_hdlc_xlate_ts_info(struct qmc_hdlc *qmc_hdlc,
+ const struct qmc_chan_ts_info *ts_info, u32 
*slot_map)
+{
+   u64 ts_mask_avail;
+   unsigned int bit;
+   unsigned int i;
+   u64 ts_mask;
+   u64 map = 0;
+
+   /* Tx and Rx masks must be identical */
+   if (ts_info->rx_ts_mask_avail != ts_info->tx_ts_mask_avail) {
+   dev_err(qmc_hdlc->dev, "tx and rx available timeslots mismatch 
(0x%llx, 0x%llx)\n",
+   ts_info->rx_ts_mask_avail, ts_info->tx_ts_mask_avail);
+   return -EINVAL;
+   }
+   if (ts_info->rx_ts_mask != ts_info->tx_ts_mask) {
+   dev_err(qmc_hdlc->dev, "tx and rx timeslots mismatch (0x%llx, 
0x%llx)\n",
+   ts_info->rx_ts_mask, ts_info->tx_ts_mask);
+   return -EINVAL;
+   }
+
+   ts_mask_avail = ts_info->rx_ts_mask_avail;
+   ts_mask = ts_info->rx_ts_mask;
+   map = 0;
+   bit = 0;
+   for (i = 0; i < 64; i++) {
+   if (ts_mask_avail & BIT_ULL(i)) {
+   if (ts_mask & BIT_ULL(i))
+   map |= BIT_ULL(bit);
+   bit++;
+   }
+   }
+
+   if (hweight64(ts_mask) != hweight64(map)) {
+   dev_err(qmc_hdlc->dev, "Cannot translate timeslots 
(0x%llx,0x%llx) -> 0x%llx\n",
+   ts_mask_avail, ts_mask, map);
+   return -EINVAL;
+   }
+
+   if (map >= BIT_ULL(32)) {
+   dev_err(qmc_hdlc->dev, "Slot map out of 32bit (0x%llx,0x%llx) 
-> 0x%llx\n",
+   ts_mask_avail, ts_mask, map);
+   return -EINVAL;
+   }
+
+   *slot_map = map;
+   return 0;
+}
+
+static int qmc_hdlc_set_iface(struct qmc_hdlc *qmc_hdlc, int if_iface, const 
te1_settings *te1)
+{
+   struct qmc_chan_ts_info ts_info;
+   int ret;
+
+   ret = qmc_chan_get_ts_info(qmc_hdlc->qmc_chan, _info);
+   if (ret) {
+   dev_err(qmc_hdlc->dev, "get QMC channel ts info failed %d\n", 
ret);
+   return ret;
+   }
+   ret = qmc_hdlc_xlate_slot_map(qmc_hdlc, te1->slot_map, _info);
+   if (ret)
+   return ret;
+
+   ret = qmc_chan_set_ts_info(qmc_hdlc->qmc_chan, _info);
+   if (ret) {
+   dev_err(qmc_hdlc->dev, "set QMC channel ts info failed %d\n", 
ret);
+   return ret;
+   }
+
+   qmc_hdlc->slot_map = te1->slot_map;
+
+   return 0;
+}
+
+static int qmc_hdlc_ioctl(struct net_device *netdev, struct if_settings *ifs)
+{
+   struct qmc_hdlc *qmc_hdlc = netdev_to_qmc_hdlc(netdev);
+   te1_settings te1;
+
+   

[PATCH v3 19/28] soc: fsl: cpm1: qmc: Introduce functions to change timeslots at runtime

2023-08-09 Thread Herve Codina
Introduce qmc_chan_{get,set}_ts_info() function to allow timeslots
modification at runtime.

The modification is provided using qmc_chan_set_ts_info() and will be
applied on next qmc_chan_start().
qmc_chan_set_ts_info() must be called with the channel rx and/or tx
stopped.

Signed-off-by: Herve Codina 
Reviewed-by: Christophe Leroy 
---
 drivers/soc/fsl/qe/qmc.c | 51 
 include/soc/fsl/qe/qmc.h | 10 
 2 files changed, 61 insertions(+)

diff --git a/drivers/soc/fsl/qe/qmc.c b/drivers/soc/fsl/qe/qmc.c
index b67e73ad7c1a..2ab21a0023a7 100644
--- a/drivers/soc/fsl/qe/qmc.c
+++ b/drivers/soc/fsl/qe/qmc.c
@@ -290,6 +290,57 @@ int qmc_chan_get_info(struct qmc_chan *chan, struct 
qmc_chan_info *info)
 }
 EXPORT_SYMBOL(qmc_chan_get_info);
 
+int qmc_chan_get_ts_info(struct qmc_chan *chan, struct qmc_chan_ts_info 
*ts_info)
+{
+   unsigned long flags;
+
+   spin_lock_irqsave(>ts_lock, flags);
+
+   ts_info->rx_ts_mask_avail = chan->rx_ts_mask_avail;
+   ts_info->tx_ts_mask_avail = chan->tx_ts_mask_avail;
+   ts_info->rx_ts_mask = chan->rx_ts_mask;
+   ts_info->tx_ts_mask = chan->tx_ts_mask;
+
+   spin_unlock_irqrestore(>ts_lock, flags);
+
+   return 0;
+}
+EXPORT_SYMBOL(qmc_chan_get_ts_info);
+
+int qmc_chan_set_ts_info(struct qmc_chan *chan, const struct qmc_chan_ts_info 
*ts_info)
+{
+   unsigned long flags;
+   int ret;
+
+   /* Only a subset of available timeslots is allowed */
+   if ((ts_info->rx_ts_mask & chan->rx_ts_mask_avail) != 
ts_info->rx_ts_mask)
+   return -EINVAL;
+   if ((ts_info->tx_ts_mask & chan->tx_ts_mask_avail) != 
ts_info->tx_ts_mask)
+   return -EINVAL;
+
+   /* In case of common rx/tx table, rx/tx masks must be identical */
+   if (chan->qmc->is_tsa_64rxtx) {
+   if (ts_info->rx_ts_mask != ts_info->tx_ts_mask)
+   return -EINVAL;
+   }
+
+   spin_lock_irqsave(>ts_lock, flags);
+
+   if ((chan->tx_ts_mask != ts_info->tx_ts_mask && !chan->is_tx_stopped) ||
+   (chan->rx_ts_mask != ts_info->rx_ts_mask && !chan->is_rx_stopped)) {
+   dev_err(chan->qmc->dev, "Channel rx and/or tx not stopped\n");
+   ret = -EBUSY;
+   } else {
+   chan->tx_ts_mask = ts_info->tx_ts_mask;
+   chan->rx_ts_mask = ts_info->rx_ts_mask;
+   ret = 0;
+   }
+   spin_unlock_irqrestore(>ts_lock, flags);
+
+   return ret;
+}
+EXPORT_SYMBOL(qmc_chan_set_ts_info);
+
 int qmc_chan_set_param(struct qmc_chan *chan, const struct qmc_chan_param 
*param)
 {
if (param->mode != chan->mode)
diff --git a/include/soc/fsl/qe/qmc.h b/include/soc/fsl/qe/qmc.h
index 6f1d6cebc9fe..802c161636bd 100644
--- a/include/soc/fsl/qe/qmc.h
+++ b/include/soc/fsl/qe/qmc.h
@@ -38,6 +38,16 @@ struct qmc_chan_info {
 
 int qmc_chan_get_info(struct qmc_chan *chan, struct qmc_chan_info *info);
 
+struct qmc_chan_ts_info {
+   u64 rx_ts_mask_avail;
+   u64 tx_ts_mask_avail;
+   u64 rx_ts_mask;
+   u64 tx_ts_mask;
+};
+
+int qmc_chan_get_ts_info(struct qmc_chan *chan, struct qmc_chan_ts_info 
*ts_info);
+int qmc_chan_set_ts_info(struct qmc_chan *chan, const struct qmc_chan_ts_info 
*ts_info);
+
 struct qmc_chan_param {
enum qmc_mode mode;
union {
-- 
2.41.0



[PATCH v3 18/28] soc: fsl: cpm1: qmc: Remove timeslots handling from setup_chan()

2023-08-09 Thread Herve Codina
Timeslots setting is done at channel start() and stop().
There is no more need to do that during setup_chan().

Simply remove timeslot setting from setup_chan().

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

diff --git a/drivers/soc/fsl/qe/qmc.c b/drivers/soc/fsl/qe/qmc.c
index 00408da14cb4..b67e73ad7c1a 100644
--- a/drivers/soc/fsl/qe/qmc.c
+++ b/drivers/soc/fsl/qe/qmc.c
@@ -723,30 +723,6 @@ static int qmc_chan_setup_tsa_rx(struct qmc_chan *chan, 
bool enable)
return qmc_chan_setup_tsa_32rx(chan, , enable);
 }
 
-static int qmc_chan_setup_tsa(struct qmc_chan *chan, bool enable)
-{
-   struct tsa_serial_info info;
-   int ret;
-
-   /* Retrieve info from the TSA related serial */
-   ret = tsa_serial_get_info(chan->qmc->tsa_serial, );
-   if (ret)
-   return ret;
-
-   /*
-* Setup one common 64 entries table or two 32 entries (one for Tx
-* and one for Tx) according to assigned TS numbers.
-*/
-   if (chan->qmc->is_tsa_64rxtx)
-   return qmc_chan_setup_tsa_64rxtx(chan, , enable);
-
-   ret = qmc_chan_setup_tsa_32rx(chan, , enable);
-   if (ret)
-   return ret;
-
-   return qmc_chan_setup_tsa_32tx(chan, , enable);
-}
-
 static int qmc_chan_command(struct qmc_chan *chan, u8 qmc_opcode)
 {
return cpm_command(chan->id << 2, (qmc_opcode << 4) | 0x0E);
@@ -1323,10 +1299,6 @@ static int qmc_setup_chan(struct qmc *qmc, struct 
qmc_chan *chan)
 
chan->qmc = qmc;
 
-   ret = qmc_chan_setup_tsa(chan, true);
-   if (ret)
-   return ret;
-
/* Set channel specific parameter base address */
chan->s_param = qmc->dpram + (chan->id * 64);
/* 16 bd per channel (8 rx and 8 tx) */
-- 
2.41.0



[PATCH v3 17/28] soc: fsl: cpm1: qmc: Handle timeslot entries at channel start() and stop()

2023-08-09 Thread Herve Codina
In order to support runtime timeslot route changes, enable the
channel timeslot entries at channel start() and disable them at
channel stop().

Signed-off-by: Herve Codina 
Reviewed-by: Christophe Leroy 
---
 drivers/soc/fsl/qe/qmc.c | 175 ---
 1 file changed, 163 insertions(+), 12 deletions(-)

diff --git a/drivers/soc/fsl/qe/qmc.c b/drivers/soc/fsl/qe/qmc.c
index 610be2b8855c..00408da14cb4 100644
--- a/drivers/soc/fsl/qe/qmc.c
+++ b/drivers/soc/fsl/qe/qmc.c
@@ -177,6 +177,7 @@ struct qmc_chan {
struct qmc *qmc;
void __iomem *s_param;
enum qmc_mode mode;
+   spinlock_t  ts_lock; /* Protect timeslots */
u64 tx_ts_mask_avail;
u64 tx_ts_mask;
u64 rx_ts_mask_avail;
@@ -265,6 +266,7 @@ static void qmc_setbits32(void __iomem *addr, u32 set)
 int qmc_chan_get_info(struct qmc_chan *chan, struct qmc_chan_info *info)
 {
struct tsa_serial_info tsa_info;
+   unsigned long flags;
int ret;
 
/* Retrieve info from the TSA related serial */
@@ -272,6 +274,8 @@ int qmc_chan_get_info(struct qmc_chan *chan, struct 
qmc_chan_info *info)
if (ret)
return ret;
 
+   spin_lock_irqsave(>ts_lock, flags);
+
info->mode = chan->mode;
info->rx_fs_rate = tsa_info.rx_fs_rate;
info->rx_bit_rate = tsa_info.rx_bit_rate;
@@ -280,6 +284,8 @@ int qmc_chan_get_info(struct qmc_chan *chan, struct 
qmc_chan_info *info)
info->tx_bit_rate = tsa_info.tx_bit_rate;
info->nb_rx_ts = hweight64(chan->rx_ts_mask);
 
+   spin_unlock_irqrestore(>ts_lock, flags);
+
return 0;
 }
 EXPORT_SYMBOL(qmc_chan_get_info);
@@ -683,6 +689,40 @@ static int qmc_chan_setup_tsa_32tx(struct qmc_chan *chan, 
const struct tsa_seria
return 0;
 }
 
+static int qmc_chan_setup_tsa_tx(struct qmc_chan *chan, bool enable)
+{
+   struct tsa_serial_info info;
+   int ret;
+
+   /* Retrieve info from the TSA related serial */
+   ret = tsa_serial_get_info(chan->qmc->tsa_serial, );
+   if (ret)
+   return ret;
+
+   /* Setup entries */
+   if (chan->qmc->is_tsa_64rxtx)
+   return qmc_chan_setup_tsa_64rxtx(chan, , enable);
+
+   return qmc_chan_setup_tsa_32tx(chan, , enable);
+}
+
+static int qmc_chan_setup_tsa_rx(struct qmc_chan *chan, bool enable)
+{
+   struct tsa_serial_info info;
+   int ret;
+
+   /* Retrieve info from the TSA related serial */
+   ret = tsa_serial_get_info(chan->qmc->tsa_serial, );
+   if (ret)
+   return ret;
+
+   /* Setup entries */
+   if (chan->qmc->is_tsa_64rxtx)
+   return qmc_chan_setup_tsa_64rxtx(chan, , enable);
+
+   return qmc_chan_setup_tsa_32rx(chan, , enable);
+}
+
 static int qmc_chan_setup_tsa(struct qmc_chan *chan, bool enable)
 {
struct tsa_serial_info info;
@@ -719,6 +759,12 @@ static int qmc_chan_stop_rx(struct qmc_chan *chan)
 
spin_lock_irqsave(>rx_lock, flags);
 
+   if (chan->is_rx_stopped) {
+   /* The channel is already stopped -> simply return ok */
+   ret = 0;
+   goto end;
+   }
+
/* Send STOP RECEIVE command */
ret = qmc_chan_command(chan, 0x0);
if (ret) {
@@ -729,6 +775,15 @@ static int qmc_chan_stop_rx(struct qmc_chan *chan)
 
chan->is_rx_stopped = true;
 
+   if (!chan->qmc->is_tsa_64rxtx || chan->is_tx_stopped) {
+   ret = qmc_chan_setup_tsa_rx(chan, false);
+   if (ret) {
+   dev_err(chan->qmc->dev, "chan %u: Disable tsa entries 
failed (%d)\n",
+   chan->id, ret);
+   goto end;
+   }
+   }
+
 end:
spin_unlock_irqrestore(>rx_lock, flags);
return ret;
@@ -741,6 +796,12 @@ static int qmc_chan_stop_tx(struct qmc_chan *chan)
 
spin_lock_irqsave(>tx_lock, flags);
 
+   if (chan->is_tx_stopped) {
+   /* The channel is already stopped -> simply return ok */
+   ret = 0;
+   goto end;
+   }
+
/* Send STOP TRANSMIT command */
ret = qmc_chan_command(chan, 0x1);
if (ret) {
@@ -751,37 +812,82 @@ static int qmc_chan_stop_tx(struct qmc_chan *chan)
 
chan->is_tx_stopped = true;
 
+   if (!chan->qmc->is_tsa_64rxtx || chan->is_rx_stopped) {
+   ret = qmc_chan_setup_tsa_tx(chan, false);
+   if (ret) {
+   dev_err(chan->qmc->dev, "chan %u: Disable tsa entries 
failed (%d)\n",
+   chan->id, ret);
+   goto end;
+   }
+   }
+
 end:
spin_unlock_irqrestore(>tx_lock, flags);
return ret;
 }
 
+static int qmc_chan_start_rx(struct qmc_chan *chan);
+
 int qmc_chan_stop(struct qmc_chan *chan, int direction)
 {
-   int ret;
+   bool is_rx_rollback_needed = false;
+   unsigned long flags;
+   

[PATCH v3 16/28] soc: fsl: cpm1: qmc: Introduce is_tsa_64rxtx flag

2023-08-09 Thread Herve Codina
In order to support runtime timeslot route changes, some operations will
be different according the routing table used (common Rx and Tx table or
one table for Rx and one for Tx).

The is_tsa_64rxtx flag is introduced to avoid extra computation to
determine the table format each time we need it.
It is set once at initialization.

Signed-off-by: Herve Codina 
Reviewed-by: Christophe Leroy 
---
 drivers/soc/fsl/qe/qmc.c | 5 -
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/drivers/soc/fsl/qe/qmc.c b/drivers/soc/fsl/qe/qmc.c
index 1eff1e138460..610be2b8855c 100644
--- a/drivers/soc/fsl/qe/qmc.c
+++ b/drivers/soc/fsl/qe/qmc.c
@@ -216,6 +216,7 @@ struct qmc {
u16 __iomem *int_curr;
dma_addr_t int_dma_addr;
size_t int_size;
+   bool is_tsa_64rxtx;
struct list_head chan_head;
struct qmc_chan *chans[64];
 };
@@ -696,7 +697,7 @@ static int qmc_chan_setup_tsa(struct qmc_chan *chan, bool 
enable)
 * Setup one common 64 entries table or two 32 entries (one for Tx
 * and one for Tx) according to assigned TS numbers.
 */
-   if (info.nb_tx_ts > 32 || info.nb_rx_ts > 32)
+   if (chan->qmc->is_tsa_64rxtx)
return qmc_chan_setup_tsa_64rxtx(chan, , enable);
 
ret = qmc_chan_setup_tsa_32rx(chan, , enable);
@@ -1053,6 +1054,7 @@ static int qmc_init_tsa_64rxtx(struct qmc *qmc, const 
struct tsa_serial_info *in
 * Everything was previously checked, Tx and Rx related stuffs are
 * identical -> Used Rx related stuff to build the table
 */
+   qmc->is_tsa_64rxtx = true;
 
/* Invalidate all entries */
for (i = 0; i < 64; i++)
@@ -1081,6 +1083,7 @@ static int qmc_init_tsa_32rx_32tx(struct qmc *qmc, const 
struct tsa_serial_info
 * Use a Tx 32 entries table and a Rx 32 entries table.
 * Everything was previously checked.
 */
+   qmc->is_tsa_64rxtx = false;
 
/* Invalidate all entries */
for (i = 0; i < 32; i++) {
-- 
2.41.0



[PATCH v3 15/28] soc: fsl: cpm1: qmc: Split Tx and Rx TSA entries setup

2023-08-09 Thread Herve Codina
The Tx and Rx entries for a given channel are set in one function.

In order to modify Rx entries and Tx entries independently of one other,
split this function in one for the Rx part and one for the Tx part.

Signed-off-by: Herve Codina 
Reviewed-by: Christophe Leroy 
---
 drivers/soc/fsl/qe/qmc.c | 49 
 1 file changed, 35 insertions(+), 14 deletions(-)

diff --git a/drivers/soc/fsl/qe/qmc.c b/drivers/soc/fsl/qe/qmc.c
index 90e6fffddab3..1eff1e138460 100644
--- a/drivers/soc/fsl/qe/qmc.c
+++ b/drivers/soc/fsl/qe/qmc.c
@@ -610,14 +610,14 @@ static int qmc_chan_setup_tsa_64rxtx(struct qmc_chan 
*chan, const struct tsa_ser
return 0;
 }
 
-static int qmc_chan_setup_tsa_32rx_32tx(struct qmc_chan *chan, const struct 
tsa_serial_info *info,
-   bool enable)
+static int qmc_chan_setup_tsa_32rx(struct qmc_chan *chan, const struct 
tsa_serial_info *info,
+  bool enable)
 {
unsigned int i;
u16 curr;
u16 val;
 
-   /* Use a Tx 32 entries table and a Rx 32 entries table */
+   /* Use a Rx 32 entries table */
 
val = QMC_TSA_VALID | QMC_TSA_MASK | QMC_TSA_CHANNEL(chan->id);
 
@@ -633,6 +633,30 @@ static int qmc_chan_setup_tsa_32rx_32tx(struct qmc_chan 
*chan, const struct tsa_
return -EBUSY;
}
}
+
+   /* Set entries based on Rx stuff */
+   for (i = 0; i < info->nb_rx_ts; i++) {
+   if (!(chan->rx_ts_mask & (((u64)1) << i)))
+   continue;
+
+   qmc_clrsetbits16(chan->qmc->scc_pram + QMC_GBL_TSATRX + (i * 2),
+~QMC_TSA_WRAP, enable ? val : 0x);
+   }
+
+   return 0;
+}
+
+static int qmc_chan_setup_tsa_32tx(struct qmc_chan *chan, const struct 
tsa_serial_info *info,
+  bool enable)
+{
+   unsigned int i;
+   u16 curr;
+   u16 val;
+
+   /* Use a Tx 32 entries table */
+
+   val = QMC_TSA_VALID | QMC_TSA_MASK | QMC_TSA_CHANNEL(chan->id);
+
/* Check entries based on Tx stuff */
for (i = 0; i < info->nb_tx_ts; i++) {
if (!(chan->tx_ts_mask & (((u64)1) << i)))
@@ -646,14 +670,6 @@ static int qmc_chan_setup_tsa_32rx_32tx(struct qmc_chan 
*chan, const struct tsa_
}
}
 
-   /* Set entries based on Rx stuff */
-   for (i = 0; i < info->nb_rx_ts; i++) {
-   if (!(chan->rx_ts_mask & (((u64)1) << i)))
-   continue;
-
-   qmc_clrsetbits16(chan->qmc->scc_pram + QMC_GBL_TSATRX + (i * 2),
-~QMC_TSA_WRAP, enable ? val : 0x);
-   }
/* Set entries based on Tx stuff */
for (i = 0; i < info->nb_tx_ts; i++) {
if (!(chan->tx_ts_mask & (((u64)1) << i)))
@@ -680,9 +696,14 @@ static int qmc_chan_setup_tsa(struct qmc_chan *chan, bool 
enable)
 * Setup one common 64 entries table or two 32 entries (one for Tx
 * and one for Tx) according to assigned TS numbers.
 */
-   return ((info.nb_tx_ts > 32) || (info.nb_rx_ts > 32)) ?
-   qmc_chan_setup_tsa_64rxtx(chan, , enable) :
-   qmc_chan_setup_tsa_32rx_32tx(chan, , enable);
+   if (info.nb_tx_ts > 32 || info.nb_rx_ts > 32)
+   return qmc_chan_setup_tsa_64rxtx(chan, , enable);
+
+   ret = qmc_chan_setup_tsa_32rx(chan, , enable);
+   if (ret)
+   return ret;
+
+   return qmc_chan_setup_tsa_32tx(chan, , enable);
 }
 
 static int qmc_chan_command(struct qmc_chan *chan, u8 qmc_opcode)
-- 
2.41.0



[PATCH v3 14/28] soc: fsl: cpm1: qmc: Add support for disabling channel TSA entries

2023-08-09 Thread Herve Codina
In order to allow runtime timeslot route changes, disabling channel TSA
entries needs to be supported.

Add support for this new feature.

Signed-off-by: Herve Codina 
Reviewed-by: Christophe Leroy 
---
 drivers/soc/fsl/qe/qmc.c | 20 +++-
 1 file changed, 11 insertions(+), 9 deletions(-)

diff --git a/drivers/soc/fsl/qe/qmc.c b/drivers/soc/fsl/qe/qmc.c
index 07fa3c265858..90e6fffddab3 100644
--- a/drivers/soc/fsl/qe/qmc.c
+++ b/drivers/soc/fsl/qe/qmc.c
@@ -567,7 +567,8 @@ static void qmc_chan_read_done(struct qmc_chan *chan)
spin_unlock_irqrestore(>rx_lock, flags);
 }
 
-static int qmc_chan_setup_tsa_64rxtx(struct qmc_chan *chan, const struct 
tsa_serial_info *info)
+static int qmc_chan_setup_tsa_64rxtx(struct qmc_chan *chan, const struct 
tsa_serial_info *info,
+bool enable)
 {
unsigned int i;
u16 curr;
@@ -603,13 +604,14 @@ static int qmc_chan_setup_tsa_64rxtx(struct qmc_chan 
*chan, const struct tsa_ser
continue;
 
qmc_clrsetbits16(chan->qmc->scc_pram + QMC_GBL_TSATRX + (i * 2),
-~QMC_TSA_WRAP, val);
+~QMC_TSA_WRAP, enable ? val : 0x);
}
 
return 0;
 }
 
-static int qmc_chan_setup_tsa_32rx_32tx(struct qmc_chan *chan, const struct 
tsa_serial_info *info)
+static int qmc_chan_setup_tsa_32rx_32tx(struct qmc_chan *chan, const struct 
tsa_serial_info *info,
+   bool enable)
 {
unsigned int i;
u16 curr;
@@ -650,7 +652,7 @@ static int qmc_chan_setup_tsa_32rx_32tx(struct qmc_chan 
*chan, const struct tsa_
continue;
 
qmc_clrsetbits16(chan->qmc->scc_pram + QMC_GBL_TSATRX + (i * 2),
-~QMC_TSA_WRAP, val);
+~QMC_TSA_WRAP, enable ? val : 0x);
}
/* Set entries based on Tx stuff */
for (i = 0; i < info->nb_tx_ts; i++) {
@@ -658,13 +660,13 @@ static int qmc_chan_setup_tsa_32rx_32tx(struct qmc_chan 
*chan, const struct tsa_
continue;
 
qmc_clrsetbits16(chan->qmc->scc_pram + QMC_GBL_TSATTX + (i * 2),
-~QMC_TSA_WRAP, val);
+~QMC_TSA_WRAP, enable ? val : 0x);
}
 
return 0;
 }
 
-static int qmc_chan_setup_tsa(struct qmc_chan *chan)
+static int qmc_chan_setup_tsa(struct qmc_chan *chan, bool enable)
 {
struct tsa_serial_info info;
int ret;
@@ -679,8 +681,8 @@ static int qmc_chan_setup_tsa(struct qmc_chan *chan)
 * and one for Tx) according to assigned TS numbers.
 */
return ((info.nb_tx_ts > 32) || (info.nb_rx_ts > 32)) ?
-   qmc_chan_setup_tsa_64rxtx(chan, ) :
-   qmc_chan_setup_tsa_32rx_32tx(chan, );
+   qmc_chan_setup_tsa_64rxtx(chan, , enable) :
+   qmc_chan_setup_tsa_32rx_32tx(chan, , enable);
 }
 
 static int qmc_chan_command(struct qmc_chan *chan, u8 qmc_opcode)
@@ -1146,7 +1148,7 @@ static int qmc_setup_chan(struct qmc *qmc, struct 
qmc_chan *chan)
 
chan->qmc = qmc;
 
-   ret = qmc_chan_setup_tsa(chan);
+   ret = qmc_chan_setup_tsa(chan, true);
if (ret)
return ret;
 
-- 
2.41.0



[PATCH v3 13/28] soc: fsl: cpm1: qmc: Check available timeslots in qmc_check_chans()

2023-08-09 Thread Herve Codina
The timeslots checked in qmc_check_chans() are the timeslots used.
With the introduction of the available timeslots, the used timeslots
are a subset of the available timeslots. The timeslots checked during
the qmc_check_chans() call should be the available ones.

Simply update and check the available timeslots instead of the used
timeslots in qmc_check_chans().

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

diff --git a/drivers/soc/fsl/qe/qmc.c b/drivers/soc/fsl/qe/qmc.c
index 2416408bb7e7..07fa3c265858 100644
--- a/drivers/soc/fsl/qe/qmc.c
+++ b/drivers/soc/fsl/qe/qmc.c
@@ -914,13 +914,13 @@ static int qmc_check_chans(struct qmc *qmc)
rx_ts_assigned_mask = info.nb_rx_ts == 64 ? U64_MAX : (((u64)1) << 
info.nb_rx_ts) - 1;
 
list_for_each_entry(chan, >chan_head, list) {
-   if (chan->tx_ts_mask > tx_ts_assigned_mask) {
-   dev_err(qmc->dev, "chan %u uses TSA unassigned Tx 
TS\n", chan->id);
+   if (chan->tx_ts_mask_avail > tx_ts_assigned_mask) {
+   dev_err(qmc->dev, "chan %u can use TSA unassigned Tx 
TS\n", chan->id);
return -EINVAL;
}
 
-   if (chan->rx_ts_mask > rx_ts_assigned_mask) {
-   dev_err(qmc->dev, "chan %u uses TSA unassigned Rx 
TS\n", chan->id);
+   if (chan->rx_ts_mask_avail > rx_ts_assigned_mask) {
+   dev_err(qmc->dev, "chan %u can use TSA unassigned Rx 
TS\n", chan->id);
return -EINVAL;
}
}
-- 
2.41.0



[PATCH v3 12/28] soc: fsl: cpm1: qmc: Remove no more needed checks from qmc_check_chans()

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

Remove them from qmc_check_chans().

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

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



[PATCH v3 11/28] soc: fsl: cpm1: qmc: Introduce qmc_chan_setup_tsa*

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

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

diff --git a/drivers/soc/fsl/qe/qmc.c b/drivers/soc/fsl/qe/qmc.c
index 261958e3199f..bddff0b74252 100644
--- a/drivers/soc/fsl/qe/qmc.c
+++ b/drivers/soc/fsl/qe/qmc.c
@@ -240,6 +240,11 @@ static void qmc_clrbits16(void __iomem *addr, u16 clr)
qmc_write16(addr, qmc_read16(addr) & ~clr);
 }
 
+static void qmc_clrsetbits16(void __iomem *addr, u16 clr, u16 set)
+{
+   qmc_write16(addr, (qmc_read16(addr) & ~clr) | set);
+}
+
 static void qmc_write32(void __iomem *addr, u32 val)
 {
iowrite32be(val, addr);
@@ -562,6 +567,122 @@ static void qmc_chan_read_done(struct qmc_chan *chan)
spin_unlock_irqrestore(>rx_lock, flags);
 }
 
+static int qmc_chan_setup_tsa_64rxtx(struct qmc_chan *chan, const struct 
tsa_serial_info *info)
+{
+   unsigned int i;
+   u16 curr;
+   u16 val;
+
+   /*
+* Use a common Tx/Rx 64 entries table.
+* Tx and Rx related stuffs must be identical
+*/
+   if (chan->tx_ts_mask != chan->rx_ts_mask) {
+   dev_err(chan->qmc->dev, "chan %u uses different Rx and Tx 
TS\n", chan->id);
+   return -EINVAL;
+   }
+
+   val = QMC_TSA_VALID | QMC_TSA_MASK | QMC_TSA_CHANNEL(chan->id);
+
+   /* Check entries based on Rx stuff*/
+   for (i = 0; i < info->nb_rx_ts; i++) {
+   if (!(chan->rx_ts_mask & (((u64)1) << i)))
+   continue;
+
+   curr = qmc_read16(chan->qmc->scc_pram + QMC_GBL_TSATRX + (i * 
2));
+   if (curr & QMC_TSA_VALID && (curr & ~QMC_TSA_WRAP) != val) {
+   dev_err(chan->qmc->dev, "chan %u TxRx entry %d already 
used\n",
+   chan->id, i);
+   return -EBUSY;
+   }
+   }
+
+   /* Set entries based on Rx stuff*/
+   for (i = 0; i < info->nb_rx_ts; i++) {
+   if (!(chan->rx_ts_mask & (((u64)1) << i)))
+   continue;
+
+   qmc_clrsetbits16(chan->qmc->scc_pram + QMC_GBL_TSATRX + (i * 2),
+~QMC_TSA_WRAP, val);
+   }
+
+   return 0;
+}
+
+static int qmc_chan_setup_tsa_32rx_32tx(struct qmc_chan *chan, const struct 
tsa_serial_info *info)
+{
+   unsigned int i;
+   u16 curr;
+   u16 val;
+
+   /* Use a Tx 32 entries table and a Rx 32 entries table */
+
+   val = QMC_TSA_VALID | QMC_TSA_MASK | QMC_TSA_CHANNEL(chan->id);
+
+   /* Check entries based on Rx stuff */
+   for (i = 0; i < info->nb_rx_ts; i++) {
+   if (!(chan->rx_ts_mask & (((u64)1) << i)))
+   continue;
+
+   curr = qmc_read16(chan->qmc->scc_pram + QMC_GBL_TSATRX + (i * 
2));
+   if (curr & QMC_TSA_VALID && (curr & ~QMC_TSA_WRAP) != val) {
+   dev_err(chan->qmc->dev, "chan %u Rx entry %d already 
used\n",
+   chan->id, i);
+   return -EBUSY;
+   }
+   }
+   /* Check entries based on Tx stuff */
+   for (i = 0; i < info->nb_tx_ts; i++) {
+   if (!(chan->tx_ts_mask & (((u64)1) << i)))
+   continue;
+
+   curr = qmc_read16(chan->qmc->scc_pram + QMC_GBL_TSATTX + (i * 
2));
+   if (curr & QMC_TSA_VALID && (curr & ~QMC_TSA_WRAP) != val) {
+   dev_err(chan->qmc->dev, "chan %u Tx entry %d already 
used\n",
+   chan->id, i);
+   return -EBUSY;
+   }
+   }
+
+   /* Set entries based on Rx stuff */
+   for (i = 0; i < info->nb_rx_ts; i++) {
+   if (!(chan->rx_ts_mask & (((u64)1) << i)))
+   continue;
+
+   qmc_clrsetbits16(chan->qmc->scc_pram + QMC_GBL_TSATRX + (i * 2),
+~QMC_TSA_WRAP, val);
+   }
+   /* Set entries based on Tx stuff */
+   for (i = 0; i < info->nb_tx_ts; i++) {
+   if (!(chan->tx_ts_mask & (((u64)1) << i)))
+   continue;
+
+   qmc_clrsetbits16(chan->qmc->scc_pram + QMC_GBL_TSATTX + (i * 2),
+~QMC_TSA_WRAP, val);
+   }
+
+   return 0;
+}
+
+static int qmc_chan_setup_tsa(struct qmc_chan *chan)
+{
+   struct tsa_serial_info info;
+   int ret;
+
+   /* Retrieve info from the TSA related serial */
+   ret = tsa_serial_get_info(chan->qmc->tsa_serial, );
+   if (ret)
+   return ret;
+
+   /*
+* Setup one common 64 entries table or two 32 entries (one for Tx
+* and one for Tx) according to assigned TS numbers.
+*/
+   return ((info.nb_tx_ts > 32) || 

[PATCH v3 10/28] soc: fsl: cpm1: qmc: Rename qmc_setup_tsa* to qmc_init_tsa*

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

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

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



[PATCH v3 09/28] soc: fsl: cpm1: qmc: Introduce available timeslots masks

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

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

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

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



[PATCH v3 08/28] MAINTAINERS: Add the Freescale QMC HDLC driver entry

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

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

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



[PATCH v3 07/28] net: wan: Add support for QMC HDLC

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

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

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

[PATCH v3 06/28] dt-bindings: net: Add support for QMC HDLC

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

Additionally, a framer can be connected to the QMC HDLC.
If present, this framer is the interface between the TDM bus used by the
QMC HDLC and the E1/T1 line.
The QMC HDLC can use this framer to get information about the E1/T1 line
and configure the E1/T1 line.

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

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



[PATCH v3 05/28] soc: fsl: cpm1: qmc: Remove inline function specifiers

2023-08-09 Thread Herve Codina
The inline function specifier is present on some functions but it is
better to let the compiler decide inlining or not these functions.

Remove inline specifiers.

Fixes: 3178d58e0b97 ("soc: fsl: cpm1: Add support for QMC")
Signed-off-by: Herve Codina 
Suggested-by: Andrew Lunn 
---
 drivers/soc/fsl/qe/qmc.c | 14 +++---
 1 file changed, 7 insertions(+), 7 deletions(-)

diff --git a/drivers/soc/fsl/qe/qmc.c b/drivers/soc/fsl/qe/qmc.c
index 2d2a9d88ba6c..459e0bbd723d 100644
--- a/drivers/soc/fsl/qe/qmc.c
+++ b/drivers/soc/fsl/qe/qmc.c
@@ -218,37 +218,37 @@ struct qmc {
struct qmc_chan *chans[64];
 };
 
-static inline void qmc_write16(void __iomem *addr, u16 val)
+static void qmc_write16(void __iomem *addr, u16 val)
 {
iowrite16be(val, addr);
 }
 
-static inline u16 qmc_read16(void __iomem *addr)
+static u16 qmc_read16(void __iomem *addr)
 {
return ioread16be(addr);
 }
 
-static inline void qmc_setbits16(void __iomem *addr, u16 set)
+static void qmc_setbits16(void __iomem *addr, u16 set)
 {
qmc_write16(addr, qmc_read16(addr) | set);
 }
 
-static inline void qmc_clrbits16(void __iomem *addr, u16 clr)
+static void qmc_clrbits16(void __iomem *addr, u16 clr)
 {
qmc_write16(addr, qmc_read16(addr) & ~clr);
 }
 
-static inline void qmc_write32(void __iomem *addr, u32 val)
+static void qmc_write32(void __iomem *addr, u32 val)
 {
iowrite32be(val, addr);
 }
 
-static inline u32 qmc_read32(void __iomem *addr)
+static u32 qmc_read32(void __iomem *addr)
 {
return ioread32be(addr);
 }
 
-static inline void qmc_setbits32(void __iomem *addr, u32 set)
+static void qmc_setbits32(void __iomem *addr, u32 set)
 {
qmc_write32(addr, qmc_read32(addr) | set);
 }
-- 
2.41.0



[PATCH v3 04/28] soc: fsl: cpm1: qmc: Extend the API to provide Rx status

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

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

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

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

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

[PATCH v3 02/28] soc: fsl: cpm1: qmc: Fix __iomem addresses declaration

2023-08-09 Thread Herve Codina
Running sparse (make C=1) on qmc.c raises a lot of warning such as:
  ...
  warning: incorrect type in assignment (different address spaces)
 expected struct cpm_buf_desc [usertype] *[noderef] __iomem bd
 got struct cpm_buf_desc [noderef] [usertype] __iomem *txbd_free
  ...

Indeed, some variable were declared 'type *__iomem var' instead of
'type __iomem *var'.

Use the correct declaration to remove these warnings.

Fixes: 3178d58e0b97 ("soc: fsl: cpm1: Add support for QMC")
Signed-off-by: Herve Codina 
Reviewed-by: Christophe Leroy 
---
 drivers/soc/fsl/qe/qmc.c | 34 +-
 1 file changed, 17 insertions(+), 17 deletions(-)

diff --git a/drivers/soc/fsl/qe/qmc.c b/drivers/soc/fsl/qe/qmc.c
index b3c292c9a14e..7ad0d77f1740 100644
--- a/drivers/soc/fsl/qe/qmc.c
+++ b/drivers/soc/fsl/qe/qmc.c
@@ -175,7 +175,7 @@ struct qmc_chan {
struct list_head list;
unsigned int id;
struct qmc *qmc;
-   void *__iomem s_param;
+   void __iomem *s_param;
enum qmc_mode mode;
u64 tx_ts_mask;
u64 rx_ts_mask;
@@ -203,9 +203,9 @@ struct qmc_chan {
 struct qmc {
struct device *dev;
struct tsa_serial *tsa_serial;
-   void *__iomem scc_regs;
-   void *__iomem scc_pram;
-   void *__iomem dpram;
+   void __iomem *scc_regs;
+   void __iomem *scc_pram;
+   void __iomem *dpram;
u16 scc_pram_offset;
cbd_t __iomem *bd_table;
dma_addr_t bd_dma_addr;
@@ -218,37 +218,37 @@ struct qmc {
struct qmc_chan *chans[64];
 };
 
-static inline void qmc_write16(void *__iomem addr, u16 val)
+static inline void qmc_write16(void __iomem *addr, u16 val)
 {
iowrite16be(val, addr);
 }
 
-static inline u16 qmc_read16(void *__iomem addr)
+static inline u16 qmc_read16(void __iomem *addr)
 {
return ioread16be(addr);
 }
 
-static inline void qmc_setbits16(void *__iomem addr, u16 set)
+static inline void qmc_setbits16(void __iomem *addr, u16 set)
 {
qmc_write16(addr, qmc_read16(addr) | set);
 }
 
-static inline void qmc_clrbits16(void *__iomem addr, u16 clr)
+static inline void qmc_clrbits16(void __iomem *addr, u16 clr)
 {
qmc_write16(addr, qmc_read16(addr) & ~clr);
 }
 
-static inline void qmc_write32(void *__iomem addr, u32 val)
+static inline void qmc_write32(void __iomem *addr, u32 val)
 {
iowrite32be(val, addr);
 }
 
-static inline u32 qmc_read32(void *__iomem addr)
+static inline u32 qmc_read32(void __iomem *addr)
 {
return ioread32be(addr);
 }
 
-static inline void qmc_setbits32(void *__iomem addr, u32 set)
+static inline void qmc_setbits32(void __iomem *addr, u32 set)
 {
qmc_write32(addr, qmc_read32(addr) | set);
 }
@@ -318,7 +318,7 @@ int qmc_chan_write_submit(struct qmc_chan *chan, dma_addr_t 
addr, size_t length,
 {
struct qmc_xfer_desc *xfer_desc;
unsigned long flags;
-   cbd_t *__iomem bd;
+   cbd_t __iomem *bd;
u16 ctrl;
int ret;
 
@@ -374,7 +374,7 @@ static void qmc_chan_write_done(struct qmc_chan *chan)
void (*complete)(void *context);
unsigned long flags;
void *context;
-   cbd_t *__iomem bd;
+   cbd_t __iomem *bd;
u16 ctrl;
 
/*
@@ -425,7 +425,7 @@ int qmc_chan_read_submit(struct qmc_chan *chan, dma_addr_t 
addr, size_t length,
 {
struct qmc_xfer_desc *xfer_desc;
unsigned long flags;
-   cbd_t *__iomem bd;
+   cbd_t __iomem *bd;
u16 ctrl;
int ret;
 
@@ -488,7 +488,7 @@ static void qmc_chan_read_done(struct qmc_chan *chan)
void (*complete)(void *context, size_t size);
struct qmc_xfer_desc *xfer_desc;
unsigned long flags;
-   cbd_t *__iomem bd;
+   cbd_t __iomem *bd;
void *context;
u16 datalen;
u16 ctrl;
@@ -663,7 +663,7 @@ static void qmc_chan_reset_rx(struct qmc_chan *chan)
 {
struct qmc_xfer_desc *xfer_desc;
unsigned long flags;
-   cbd_t *__iomem bd;
+   cbd_t __iomem *bd;
u16 ctrl;
 
spin_lock_irqsave(>rx_lock, flags);
@@ -694,7 +694,7 @@ static void qmc_chan_reset_tx(struct qmc_chan *chan)
 {
struct qmc_xfer_desc *xfer_desc;
unsigned long flags;
-   cbd_t *__iomem bd;
+   cbd_t __iomem *bd;
u16 ctrl;
 
spin_lock_irqsave(>tx_lock, flags);
-- 
2.41.0



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

2023-08-09 Thread Herve Codina
Hi,

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

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

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

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

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

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

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

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

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

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

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

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

Compare to the previous iteration
  
https://lore.kernel.org/linux-kernel/20230726150225.483464-1-herve.cod...@bootlin.com/
This v3 series mainly:
 - Fixes some implementation details.
 - Adds a new patch (patch 5) to remove existing inline keyword in the
   QMC driver.
 - Squashes patches related to the QMC HDLC binding together.

Best regards,
Hervé

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

Changes v2 -> v3

  - Patches 1, 2, 3, 4
Add 'Reviewed-by: Christophe Leroy '

  - New patch
Remove inline keyword from the existing registers accessors helpers

  - Patch 6 (patches 5, 27 in v2)
Update the binding title
Squash patch 27

  - Patch 7 (patch 6 in v2)
Remove the cast in netdev_to_qmc_hdlc()
Add 'Reviewed-by: Christophe Leroy '

  - Patch 8 (patch 7 in v2): No change

  - Patches 9, 10 (patches 8, 9 in v2)
Add 'Reviewed-by: Christophe Leroy '

  - Patch 11 (patch 10 in v2)
Remove inline keyword from the introduced qmc_clrsetbits16() helper
Add 'Reviewed-by: Christophe Leroy '

  - Patches 12, 13, 14, 15, 16, 17, 18, 19, 20
Add 'Reviewed-by: Christophe Leroy '

  - Patch 21 (patch 20 in v2)
Remove unneeded framer NULL pointer check
Add 'Reviewed-by: Christophe Leroy '

  - Patch 22 (patch 21 in v2)
Change sclkr and sclkx clocks description
Remove the framer phandle property from the framer subnodes
(ie. from framer-codec nodes)

  - Patch 23 (patch 22 in v2)
Initialize 'disabled' variable at declaration
Fix commit log
Add 'Reviewed-by: Christophe Leroy '

  - Patch 24 (patch 23 in v2)
Remove inline keyword 

[PATCH v3 03/28] soc: fsl: cpm1: qmc: Fix rx channel reset

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

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

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

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



[PATCH v3 01/28] soc: fsl: cpm1: tsa: Fix __iomem addresses declaration

2023-08-09 Thread Herve Codina
Running sparse (make C=1) on tsa.c raises a lot of warning such as:
  --- 8< ---
  warning: incorrect type in assignment (different address spaces)
 expected void *[noderef] si_regs
 got void [noderef] __iomem *
  --- 8< ---

Indeed, some variable were declared 'type *__iomem var' instead of
'type __iomem *var'.

Use the correct declaration to remove these warnings.

Fixes: 1d4ba0b81c1c ("soc: fsl: cpm1: Add support for TSA")
Signed-off-by: Herve Codina 
Reviewed-by: Christophe Leroy 
---
 drivers/soc/fsl/qe/tsa.c | 22 +++---
 1 file changed, 11 insertions(+), 11 deletions(-)

diff --git a/drivers/soc/fsl/qe/tsa.c b/drivers/soc/fsl/qe/tsa.c
index 3646153117b3..e0527b9efd05 100644
--- a/drivers/soc/fsl/qe/tsa.c
+++ b/drivers/soc/fsl/qe/tsa.c
@@ -98,9 +98,9 @@
 #define TSA_SIRP   0x10
 
 struct tsa_entries_area {
-   void *__iomem entries_start;
-   void *__iomem entries_next;
-   void *__iomem last_entry;
+   void __iomem *entries_start;
+   void __iomem *entries_next;
+   void __iomem *last_entry;
 };
 
 struct tsa_tdm {
@@ -117,8 +117,8 @@ struct tsa_tdm {
 
 struct tsa {
struct device *dev;
-   void *__iomem si_regs;
-   void *__iomem si_ram;
+   void __iomem *si_regs;
+   void __iomem *si_ram;
resource_size_t si_ram_sz;
spinlock_t  lock;
int tdms; /* TSA_TDMx ORed */
@@ -135,27 +135,27 @@ static inline struct tsa *tsa_serial_get_tsa(struct 
tsa_serial *tsa_serial)
return container_of(tsa_serial, struct tsa, serials[tsa_serial->id]);
 }
 
-static inline void tsa_write32(void *__iomem addr, u32 val)
+static inline void tsa_write32(void __iomem *addr, u32 val)
 {
iowrite32be(val, addr);
 }
 
-static inline void tsa_write8(void *__iomem addr, u32 val)
+static inline void tsa_write8(void __iomem *addr, u32 val)
 {
iowrite8(val, addr);
 }
 
-static inline u32 tsa_read32(void *__iomem addr)
+static inline u32 tsa_read32(void __iomem *addr)
 {
return ioread32be(addr);
 }
 
-static inline void tsa_clrbits32(void *__iomem addr, u32 clr)
+static inline void tsa_clrbits32(void __iomem *addr, u32 clr)
 {
tsa_write32(addr, tsa_read32(addr) & ~clr);
 }
 
-static inline void tsa_clrsetbits32(void *__iomem addr, u32 clr, u32 set)
+static inline void tsa_clrsetbits32(void __iomem *addr, u32 clr, u32 set)
 {
tsa_write32(addr, (tsa_read32(addr) & ~clr) | set);
 }
@@ -313,7 +313,7 @@ static u32 tsa_serial_id2csel(struct tsa *tsa, u32 
serial_id)
 static int tsa_add_entry(struct tsa *tsa, struct tsa_entries_area *area,
 u32 count, u32 serial_id)
 {
-   void *__iomem addr;
+   void __iomem *addr;
u32 left;
u32 val;
u32 cnt;
-- 
2.41.0



Re: [PATCH 1/2] powerpc: mark more local variables as volatile

2023-08-09 Thread Christophe Leroy


Le 09/08/2023 à 15:10, Arnd Bergmann a écrit :
> From: Arnd Bergmann 
> 
> A while ago I created a2305e3de8193 ("powerpc: mark local variables
> around longjmp as volatile") in order to allow building powerpc with
> -Wextra enabled on gcc-11.

Should this be explained in 
https://docs.kernel.org/process/volatile-considered-harmful.html ?

Christophe


> 
> I tried this again with gcc-13 and found two more of the same issues,
> presumably based on slightly different optimization paths being taken
> here:
> 
> arch/powerpc/xmon/xmon.c:3306:27: error: variable 'mm' might be clobbered by 
> 'longjmp' or 'vfork' [-Werror=clobbered]
> arch/powerpc/kexec/crash.c:353:22: error: variable 'i' might be clobbered by 
> 'longjmp' or 'vfork' [-Werror=clobbered]
> 
> I checked a bunch of randconfigs and found only these two, so just
> address them the same way as the others.
> 
> Signed-off-by: Arnd Bergmann 
> ---
>   arch/powerpc/kexec/crash.c | 2 +-
>   arch/powerpc/xmon/xmon.c   | 2 +-
>   2 files changed, 2 insertions(+), 2 deletions(-)
> 
> diff --git a/arch/powerpc/kexec/crash.c b/arch/powerpc/kexec/crash.c
> index 252724ed666a3..ef5c2d25ec397 100644
> --- a/arch/powerpc/kexec/crash.c
> +++ b/arch/powerpc/kexec/crash.c
> @@ -350,7 +350,7 @@ EXPORT_SYMBOL(crash_shutdown_unregister);
>   
>   void default_machine_crash_shutdown(struct pt_regs *regs)
>   {
> - unsigned int i;
> + volatile unsigned int i;
>   int (*old_handler)(struct pt_regs *regs);
>   
>   if (TRAP(regs) == INTERRUPT_SYSTEM_RESET)
> diff --git a/arch/powerpc/xmon/xmon.c b/arch/powerpc/xmon/xmon.c
> index 3b6f524c790e3..9e12b75850d75 100644
> --- a/arch/powerpc/xmon/xmon.c
> +++ b/arch/powerpc/xmon/xmon.c
> @@ -3303,7 +3303,7 @@ static void show_pte(unsigned long addr)
>   {
>   unsigned long tskv = 0;
>   struct task_struct *volatile tsk = NULL;
> - struct mm_struct *mm;
> + struct mm_struct *volatile mm;
>   pgd_t *pgdp;
>   p4d_t *p4dp;
>   pud_t *pudp;


[PATCH 2/2] powerpc: xmon: remove unused variables

2023-08-09 Thread Arnd Bergmann
From: Arnd Bergmann 

Randconfig testing with W=1 showed up these warnings that I'd like to enable
by default:

arch/powerpc/xmon/xmon.c: In function 'dump_tlb_book3e':
arch/powerpc/xmon/xmon.c:3833:42: error: variable 'lrat' set but not used 
[-Werror=unused-but-set-variable]
 3833 |  int i, tlb, ntlbs, pidsz, lpidsz, rasz, lrat = 0;
  |  ^~~~
arch/powerpc/xmon/xmon.c:3831:23: error: variable 'lpidmask' set but not used 
[-Werror=unused-but-set-variable]
 3831 |  u32 mmucfg, pidmask, lpidmask;
  |   ^~~~
arch/powerpc/xmon/xmon.c:3831:14: error: variable 'pidmask' set but not used 
[-Werror=unused-but-set-variable]
 3831 |  u32 mmucfg, pidmask, lpidmask;
  |  ^~~

Just remove these as they have been unused since the code was added in 2010.

Fixes: 03247157f7391 ("powerpc/book3e: Add TLB dump in xmon for Book3E")
Signed-off-by: Arnd Bergmann 
---
 arch/powerpc/xmon/xmon.c | 8 ++--
 1 file changed, 2 insertions(+), 6 deletions(-)

diff --git a/arch/powerpc/xmon/xmon.c b/arch/powerpc/xmon/xmon.c
index 9e12b75850d75..e35f13842ce15 100644
--- a/arch/powerpc/xmon/xmon.c
+++ b/arch/powerpc/xmon/xmon.c
@@ -3828,9 +3828,9 @@ static void dump_tlb_44x(void)
 #ifdef CONFIG_PPC_BOOK3E_64
 static void dump_tlb_book3e(void)
 {
-   u32 mmucfg, pidmask, lpidmask;
+   u32 mmucfg;
u64 ramask;
-   int i, tlb, ntlbs, pidsz, lpidsz, rasz, lrat = 0;
+   int i, tlb, ntlbs, pidsz, lpidsz, rasz;
int mmu_version;
static const char *pgsz_names[] = {
"  1K",
@@ -3874,12 +3874,8 @@ static void dump_tlb_book3e(void)
pidsz = ((mmucfg >> 6) & 0x1f) + 1;
lpidsz = (mmucfg >> 24) & 0xf;
rasz = (mmucfg >> 16) & 0x7f;
-   if ((mmu_version > 1) && (mmucfg & 0x1))
-   lrat = 1;
printf("Book3E MMU MAV=%d.0,%d TLBs,%d-bit PID,%d-bit LPID,%d-bit RA\n",
   mmu_version, ntlbs, pidsz, lpidsz, rasz);
-   pidmask = (1ul << pidsz) - 1;
-   lpidmask = (1ul << lpidsz) - 1;
ramask = (1ull << rasz) - 1;
 
for (tlb = 0; tlb < ntlbs; tlb++) {
-- 
2.39.2



[PATCH 1/2] powerpc: mark more local variables as volatile

2023-08-09 Thread Arnd Bergmann
From: Arnd Bergmann 

A while ago I created a2305e3de8193 ("powerpc: mark local variables
around longjmp as volatile") in order to allow building powerpc with
-Wextra enabled on gcc-11.

I tried this again with gcc-13 and found two more of the same issues,
presumably based on slightly different optimization paths being taken
here:

arch/powerpc/xmon/xmon.c:3306:27: error: variable 'mm' might be clobbered by 
'longjmp' or 'vfork' [-Werror=clobbered]
arch/powerpc/kexec/crash.c:353:22: error: variable 'i' might be clobbered by 
'longjmp' or 'vfork' [-Werror=clobbered]

I checked a bunch of randconfigs and found only these two, so just
address them the same way as the others.

Signed-off-by: Arnd Bergmann 
---
 arch/powerpc/kexec/crash.c | 2 +-
 arch/powerpc/xmon/xmon.c   | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/arch/powerpc/kexec/crash.c b/arch/powerpc/kexec/crash.c
index 252724ed666a3..ef5c2d25ec397 100644
--- a/arch/powerpc/kexec/crash.c
+++ b/arch/powerpc/kexec/crash.c
@@ -350,7 +350,7 @@ EXPORT_SYMBOL(crash_shutdown_unregister);
 
 void default_machine_crash_shutdown(struct pt_regs *regs)
 {
-   unsigned int i;
+   volatile unsigned int i;
int (*old_handler)(struct pt_regs *regs);
 
if (TRAP(regs) == INTERRUPT_SYSTEM_RESET)
diff --git a/arch/powerpc/xmon/xmon.c b/arch/powerpc/xmon/xmon.c
index 3b6f524c790e3..9e12b75850d75 100644
--- a/arch/powerpc/xmon/xmon.c
+++ b/arch/powerpc/xmon/xmon.c
@@ -3303,7 +3303,7 @@ static void show_pte(unsigned long addr)
 {
unsigned long tskv = 0;
struct task_struct *volatile tsk = NULL;
-   struct mm_struct *mm;
+   struct mm_struct *volatile mm;
pgd_t *pgdp;
p4d_t *p4dp;
pud_t *pudp;
-- 
2.39.2



[PATCH 4.19 077/323] crypto: nx - fix build warnings when DEBUG_FS is not enabled

2023-08-09 Thread Greg Kroah-Hartman
From: Randy Dunlap 

[ Upstream commit b04b076fb56560b39d695ac3744db457e12278fd ]

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

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

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

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

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





[PATCH 4.19 061/323] soc/fsl/qe: fix usb.c build errors

2023-08-09 Thread Greg Kroah-Hartman
From: Randy Dunlap 

[ Upstream commit 7b1a78babd0d2cd27aa07255dee0c2d7ac0f31e3 ]

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

Fixes these build errors:

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

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

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





[PATCH 4.14 050/204] crypto: nx - fix build warnings when DEBUG_FS is not enabled

2023-08-09 Thread Greg Kroah-Hartman
From: Randy Dunlap 

[ Upstream commit b04b076fb56560b39d695ac3744db457e12278fd ]

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

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

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

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

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





[PATCH 4.14 041/204] soc/fsl/qe: fix usb.c build errors

2023-08-09 Thread Greg Kroah-Hartman
From: Randy Dunlap 

[ Upstream commit 7b1a78babd0d2cd27aa07255dee0c2d7ac0f31e3 ]

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

Fixes these build errors:

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

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

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





[PATCH] spi: fsl-cpm: Properly define and use IO pointers

2023-08-09 Thread Christophe Leroy
Sparse reports several issues with IO pointers.

Fix it by adding missing __iomem flags and using iowriteXXbe()
generic helpers instead of the powerpc specific out_beXX() ones.

Reported-by: kernel test robot 
Closes: 
https://lore.kernel.org/oe-kbuild-all/202307252052.7rqhxfzj-...@intel.com/
Signed-off-by: Christophe Leroy 
---
 drivers/spi/spi-fsl-cpm.c | 74 +++
 1 file changed, 37 insertions(+), 37 deletions(-)

diff --git a/drivers/spi/spi-fsl-cpm.c b/drivers/spi/spi-fsl-cpm.c
index 38452089e8f3..47c7a5c6257f 100644
--- a/drivers/spi/spi-fsl-cpm.c
+++ b/drivers/spi/spi-fsl-cpm.c
@@ -56,12 +56,12 @@ void fsl_spi_cpm_reinit_txrx(struct mpc8xxx_spi *mspi)
 QE_CR_PROTOCOL_UNSPECIFIED, 0);
} else {
if (mspi->flags & SPI_CPM1) {
-   out_be32(>pram->rstate, 0);
-   out_be16(>pram->rbptr,
-in_be16(>pram->rbase));
-   out_be32(>pram->tstate, 0);
-   out_be16(>pram->tbptr,
-in_be16(>pram->tbase));
+   iowrite32be(0, >pram->rstate);
+   iowrite16be(ioread16be(>pram->rbase),
+   >pram->rbptr);
+   iowrite32be(0, >pram->tstate);
+   iowrite16be(ioread16be(>pram->tbase),
+   >pram->tbptr);
} else {
cpm_command(CPM_SPI_CMD, CPM_CR_INIT_TRX);
}
@@ -75,24 +75,24 @@ static void fsl_spi_cpm_bufs_start(struct mpc8xxx_spi *mspi)
struct cpm_buf_desc __iomem *rx_bd = mspi->rx_bd;
unsigned int xfer_len = min(mspi->count, SPI_MRBLR);
unsigned int xfer_ofs;
-   struct fsl_spi_reg *reg_base = mspi->reg_base;
+   struct fsl_spi_reg __iomem *reg_base = mspi->reg_base;
 
xfer_ofs = mspi->xfer_in_progress->len - mspi->count;
 
if (mspi->rx_dma == mspi->dma_dummy_rx)
-   out_be32(_bd->cbd_bufaddr, mspi->rx_dma);
+   iowrite32be(mspi->rx_dma, _bd->cbd_bufaddr);
else
-   out_be32(_bd->cbd_bufaddr, mspi->rx_dma + xfer_ofs);
-   out_be16(_bd->cbd_datlen, 0);
-   out_be16(_bd->cbd_sc, BD_SC_EMPTY | BD_SC_INTRPT | BD_SC_WRAP);
+   iowrite32be(mspi->rx_dma + xfer_ofs, _bd->cbd_bufaddr);
+   iowrite16be(0, _bd->cbd_datlen);
+   iowrite16be(BD_SC_EMPTY | BD_SC_INTRPT | BD_SC_WRAP, _bd->cbd_sc);
 
if (mspi->tx_dma == mspi->dma_dummy_tx)
-   out_be32(_bd->cbd_bufaddr, mspi->tx_dma);
+   iowrite32be(mspi->tx_dma, _bd->cbd_bufaddr);
else
-   out_be32(_bd->cbd_bufaddr, mspi->tx_dma + xfer_ofs);
-   out_be16(_bd->cbd_datlen, xfer_len);
-   out_be16(_bd->cbd_sc, BD_SC_READY | BD_SC_INTRPT | BD_SC_WRAP |
-BD_SC_LAST);
+   iowrite32be(mspi->tx_dma + xfer_ofs, _bd->cbd_bufaddr);
+   iowrite16be(xfer_len, _bd->cbd_datlen);
+   iowrite16be(BD_SC_READY | BD_SC_INTRPT | BD_SC_WRAP | BD_SC_LAST,
+   _bd->cbd_sc);
 
/* start transfer */
mpc8xxx_spi_write_reg(_base->command, SPCOM_STR);
@@ -102,7 +102,7 @@ int fsl_spi_cpm_bufs(struct mpc8xxx_spi *mspi,
 struct spi_transfer *t, bool is_dma_mapped)
 {
struct device *dev = mspi->dev;
-   struct fsl_spi_reg *reg_base = mspi->reg_base;
+   struct fsl_spi_reg __iomem *reg_base = mspi->reg_base;
 
if (is_dma_mapped) {
mspi->map_tx_dma = 0;
@@ -123,7 +123,7 @@ int fsl_spi_cpm_bufs(struct mpc8xxx_spi *mspi,
}
if (t->bits_per_word == 16 && t->tx_buf) {
const u16 *src = t->tx_buf;
-   u16 *dst;
+   __le16 *dst;
int i;
 
dst = kmalloc(t->len, GFP_KERNEL);
@@ -202,12 +202,12 @@ EXPORT_SYMBOL_GPL(fsl_spi_cpm_bufs_complete);
 void fsl_spi_cpm_irq(struct mpc8xxx_spi *mspi, u32 events)
 {
u16 len;
-   struct fsl_spi_reg *reg_base = mspi->reg_base;
+   struct fsl_spi_reg __iomem *reg_base = mspi->reg_base;
 
dev_dbg(mspi->dev, "%s: bd datlen %d, count %d\n", __func__,
-   in_be16(>rx_bd->cbd_datlen), mspi->count);
+   ioread16be(>rx_bd->cbd_datlen), mspi->count);
 
-   len = in_be16(>rx_bd->cbd_datlen);
+   len = ioread16be(>rx_bd->cbd_datlen);
if (len > mspi->count) {
WARN_ON(1);
len = mspi->count;
@@ -328,7 +328,7 @@ int fsl_spi_cpm_init(struct mpc8xxx_spi *mspi)
}
 
if (mspi->flags & SPI_CPM1) {
-   void *pram;
+   void __iomem *pram;
 
pram = devm_platform_ioremap_resource(to_platform_device(dev),
  1);
@@ -374,21 +374,21 @@ int fsl_spi_cpm_init(struct mpc8xxx_spi *mspi)
mspi->rx_bd = 

[PATCH] powerpc: Make virt_to_pfn() a static inline

2023-08-09 Thread Linus Walleij
Making virt_to_pfn() a static inline taking a strongly typed
(const void *) makes the contract of a passing a pointer of that
type to the function explicit and exposes any misuse of the
macro virt_to_pfn() acting polymorphic and accepting many types
such as (void *), (unitptr_t) or (unsigned long) as arguments
without warnings.

Move the virt_to_pfn() and related functions below the
declaration of __pa() so it compiles.

For symmetry do the same with pfn_to_kaddr().

As the file is included right into the linker file, we need
to surround the functions with ifndef __ASSEMBLY__ so we
don't cause compilation errors.

The conversion moreover exposes the fact that pmd_page_vaddr()
was returning an unsigned long rather than a const void * as
could be expected, so all the sites defining pmd_page_vaddr()
had to be augmented as well.

Finally the KVM code in book3s_64_mmu_hv.c was passing an
unsigned int to virt_to_phys() so fix that up with a cast so the
result compiles.

Signed-off-by: Linus Walleij 
---
 arch/powerpc/include/asm/nohash/32/pgtable.h |  2 +-
 arch/powerpc/include/asm/nohash/64/pgtable.h |  2 +-
 arch/powerpc/include/asm/page.h  | 30 ++--
 arch/powerpc/include/asm/pgtable.h   |  4 ++--
 arch/powerpc/kvm/book3s_64_mmu_hv.c  |  2 +-
 5 files changed, 25 insertions(+), 15 deletions(-)

diff --git a/arch/powerpc/include/asm/nohash/32/pgtable.h 
b/arch/powerpc/include/asm/nohash/32/pgtable.h
index fec56d965f00..d6201b5096b8 100644
--- a/arch/powerpc/include/asm/nohash/32/pgtable.h
+++ b/arch/powerpc/include/asm/nohash/32/pgtable.h
@@ -355,7 +355,7 @@ static inline int pte_young(pte_t pte)
 #define pmd_pfn(pmd)   (pmd_val(pmd) >> PAGE_SHIFT)
 #else
 #define pmd_page_vaddr(pmd)\
-   ((unsigned long)(pmd_val(pmd) & ~(PTE_TABLE_SIZE - 1)))
+   ((const void *)(pmd_val(pmd) & ~(PTE_TABLE_SIZE - 1)))
 #define pmd_pfn(pmd)   (__pa(pmd_val(pmd)) >> PAGE_SHIFT)
 #endif
 
diff --git a/arch/powerpc/include/asm/nohash/64/pgtable.h 
b/arch/powerpc/include/asm/nohash/64/pgtable.h
index 287e25864ffa..81c801880933 100644
--- a/arch/powerpc/include/asm/nohash/64/pgtable.h
+++ b/arch/powerpc/include/asm/nohash/64/pgtable.h
@@ -127,7 +127,7 @@ static inline pte_t pmd_pte(pmd_t pmd)
 #definepmd_bad(pmd)(!is_kernel_addr(pmd_val(pmd)) \
 || (pmd_val(pmd) & PMD_BAD_BITS))
 #definepmd_present(pmd)(!pmd_none(pmd))
-#define pmd_page_vaddr(pmd)(pmd_val(pmd) & ~PMD_MASKED_BITS)
+#define pmd_page_vaddr(pmd)((const void *)(pmd_val(pmd) & 
~PMD_MASKED_BITS))
 extern struct page *pmd_page(pmd_t pmd);
 #define pmd_pfn(pmd)   (page_to_pfn(pmd_page(pmd)))
 
diff --git a/arch/powerpc/include/asm/page.h b/arch/powerpc/include/asm/page.h
index f2b6bf5687d0..9ee4b6d4a82a 100644
--- a/arch/powerpc/include/asm/page.h
+++ b/arch/powerpc/include/asm/page.h
@@ -9,6 +9,7 @@
 #ifndef __ASSEMBLY__
 #include 
 #include 
+#include 
 #else
 #include 
 #endif
@@ -119,16 +120,6 @@ extern long long virt_phys_offset;
 #define ARCH_PFN_OFFSET((unsigned long)(MEMORY_START >> 
PAGE_SHIFT))
 #endif
 
-#define virt_to_pfn(kaddr) (__pa(kaddr) >> PAGE_SHIFT)
-#define virt_to_page(kaddr)pfn_to_page(virt_to_pfn(kaddr))
-#define pfn_to_kaddr(pfn)  __va((pfn) << PAGE_SHIFT)
-
-#define virt_addr_valid(vaddr) ({  \
-   unsigned long _addr = (unsigned long)vaddr; \
-   _addr >= PAGE_OFFSET && _addr < (unsigned long)high_memory &&   \
-   pfn_valid(virt_to_pfn(_addr));  \
-})
-
 /*
  * On Book-E parts we need __va to parse the device tree and we can't
  * determine MEMORY_START until then.  However we can determine PHYSICAL_START
@@ -233,6 +224,25 @@ extern long long virt_phys_offset;
 #endif
 #endif
 
+#ifndef __ASSEMBLY__
+static inline unsigned long virt_to_pfn(const void *kaddr)
+{
+   return __pa(kaddr) >> PAGE_SHIFT;
+}
+
+static inline const void *pfn_to_kaddr(unsigned long pfn)
+{
+   return (const void *)(((unsigned long)__va(pfn)) << PAGE_SHIFT);
+}
+#endif
+
+#define virt_to_page(kaddr)pfn_to_page(virt_to_pfn(kaddr))
+#define virt_addr_valid(vaddr) ({  \
+   unsigned long _addr = (unsigned long)vaddr; \
+   _addr >= PAGE_OFFSET && _addr < (unsigned long)high_memory &&   \
+   pfn_valid(virt_to_pfn((void *)_addr));  \
+})
+
 /*
  * Unfortunately the PLT is in the BSS in the PPC32 ELF ABI,
  * and needs to be executable.  This means the whole heap ends
diff --git a/arch/powerpc/include/asm/pgtable.h 
b/arch/powerpc/include/asm/pgtable.h
index 6a88bfdaa69b..a9515d3d7831 100644
--- a/arch/powerpc/include/asm/pgtable.h
+++ b/arch/powerpc/include/asm/pgtable.h
@@ -60,9 +60,9 @@ static inline pgprot_t pte_pgprot(pte_t pte)
 }
 
 #ifndef pmd_page_vaddr
-static inline unsigned 

[PATCH] powerpc/radix: Move some functions into #ifdef CONFIG_KVM_BOOK3S_HV_POSSIBLE

2023-08-09 Thread Christophe Leroy
With skiboot_defconfig, Clang reports:

  CC  arch/powerpc/mm/book3s64/radix_tlb.o
arch/powerpc/mm/book3s64/radix_tlb.c:419:20: error: unused function 
'_tlbie_pid_lpid' [-Werror,-Wunused-function]
static inline void _tlbie_pid_lpid(unsigned long pid, unsigned long lpid,
   ^
arch/powerpc/mm/book3s64/radix_tlb.c:663:20: error: unused function 
'_tlbie_va_range_lpid' [-Werror,-Wunused-function]
static inline void _tlbie_va_range_lpid(unsigned long start, unsigned long end,
   ^

This is because those functions are only called from functions
enclosed in a #ifdef CONFIG_KVM_BOOK3S_HV_POSSIBLE

Move below functions inside that #ifdef
* __tlbie_pid_lpid(unsigned long pid,
* __tlbie_va_lpid(unsigned long va, unsigned long pid,
* fixup_tlbie_pid_lpid(unsigned long pid, unsigned long lpid)
* _tlbie_pid_lpid(unsigned long pid, unsigned long lpid,
* fixup_tlbie_va_range_lpid(unsigned long va,
* __tlbie_va_range_lpid(unsigned long start, unsigned long end,
* _tlbie_va_range_lpid(unsigned long start, unsigned long end,

Fixes: f0c6fbbb9050 ("KVM: PPC: Book3S HV: Add support for H_RPT_INVALIDATE")
Reported-by: kernel test robot 
Closes: 
https://lore.kernel.org/oe-kbuild-all/202307260802.mjr99p5o-...@intel.com/
Signed-off-by: Christophe Leroy 
---
 arch/powerpc/mm/book3s64/radix_tlb.c | 240 ++-
 1 file changed, 121 insertions(+), 119 deletions(-)

diff --git a/arch/powerpc/mm/book3s64/radix_tlb.c 
b/arch/powerpc/mm/book3s64/radix_tlb.c
index ce804b7bf84e..867ce8c463ee 100644
--- a/arch/powerpc/mm/book3s64/radix_tlb.c
+++ b/arch/powerpc/mm/book3s64/radix_tlb.c
@@ -127,21 +127,6 @@ static __always_inline void __tlbie_pid(unsigned long pid, 
unsigned long ric)
trace_tlbie(0, 0, rb, rs, ric, prs, r);
 }
 
-static __always_inline void __tlbie_pid_lpid(unsigned long pid,
-unsigned long lpid,
-unsigned long ric)
-{
-   unsigned long rb, rs, prs, r;
-
-   rb = PPC_BIT(53); /* IS = 1 */
-   rs = (pid << PPC_BITLSHIFT(31)) | (lpid & ~(PPC_BITMASK(0, 31)));
-   prs = 1; /* process scoped */
-   r = 1;   /* radix format */
-
-   asm volatile(PPC_TLBIE_5(%0, %4, %3, %2, %1)
-: : "r"(rb), "i"(r), "i"(prs), "i"(ric), "r"(rs) : 
"memory");
-   trace_tlbie(0, 0, rb, rs, ric, prs, r);
-}
 static __always_inline void __tlbie_lpid(unsigned long lpid, unsigned long ric)
 {
unsigned long rb,rs,prs,r;
@@ -202,23 +187,6 @@ static __always_inline void __tlbie_va(unsigned long va, 
unsigned long pid,
trace_tlbie(0, 0, rb, rs, ric, prs, r);
 }
 
-static __always_inline void __tlbie_va_lpid(unsigned long va, unsigned long 
pid,
-   unsigned long lpid,
-   unsigned long ap, unsigned long ric)
-{
-   unsigned long rb, rs, prs, r;
-
-   rb = va & ~(PPC_BITMASK(52, 63));
-   rb |= ap << PPC_BITLSHIFT(58);
-   rs = (pid << PPC_BITLSHIFT(31)) | (lpid & ~(PPC_BITMASK(0, 31)));
-   prs = 1; /* process scoped */
-   r = 1;   /* radix format */
-
-   asm volatile(PPC_TLBIE_5(%0, %4, %3, %2, %1)
-: : "r"(rb), "i"(r), "i"(prs), "i"(ric), "r"(rs) : 
"memory");
-   trace_tlbie(0, 0, rb, rs, ric, prs, r);
-}
-
 static __always_inline void __tlbie_lpid_va(unsigned long va, unsigned long 
lpid,
unsigned long ap, unsigned long ric)
 {
@@ -264,22 +232,6 @@ static inline void fixup_tlbie_va_range(unsigned long va, 
unsigned long pid,
}
 }
 
-static inline void fixup_tlbie_va_range_lpid(unsigned long va,
-unsigned long pid,
-unsigned long lpid,
-unsigned long ap)
-{
-   if (cpu_has_feature(CPU_FTR_P9_TLBIE_ERAT_BUG)) {
-   asm volatile("ptesync" : : : "memory");
-   __tlbie_pid_lpid(0, lpid, RIC_FLUSH_TLB);
-   }
-
-   if (cpu_has_feature(CPU_FTR_P9_TLBIE_STQ_BUG)) {
-   asm volatile("ptesync" : : : "memory");
-   __tlbie_va_lpid(va, pid, lpid, ap, RIC_FLUSH_TLB);
-   }
-}
-
 static inline void fixup_tlbie_pid(unsigned long pid)
 {
/*
@@ -299,26 +251,6 @@ static inline void fixup_tlbie_pid(unsigned long pid)
}
 }
 
-static inline void fixup_tlbie_pid_lpid(unsigned long pid, unsigned long lpid)
-{
-   /*
-* We can use any address for the invalidation, pick one which is
-* probably unused as an optimisation.
-*/
-   unsigned long va = ((1UL << 52) - 1);
-
-   if (cpu_has_feature(CPU_FTR_P9_TLBIE_ERAT_BUG)) {
-   asm volatile("ptesync" : : : "memory");
-   __tlbie_pid_lpid(0, lpid, RIC_FLUSH_TLB);
-   }
-
-   if (cpu_has_feature(CPU_FTR_P9_TLBIE_STQ_BUG)) {
-   asm volatile("ptesync" :