All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v2 3/3] x86/perfc: fold HVM's VM-exit counter arrays
From: Jan Beulich @ 2022-01-05 13:59 UTC (permalink / raw)
  To: xen-devel@lists.xenproject.org
  Cc: Andrew Cooper, Wei Liu, Roger Pau Monné
In-Reply-To: <ff461a77-93a0-5424-6565-2e947bec3912@suse.com>

Only one of them can be in use at a time, so make the whole set union-
like. While doing the rename in SVM code, combine the two perf_incra(),
generalizing the range upwards of VMEXIT_NPF.

Signed-off-by: Jan Beulich <jbeulich@suse.com>
---
v2: New.

--- a/xen/arch/x86/hvm/svm/svm.c
+++ b/xen/arch/x86/hvm/svm/svm.c
@@ -2644,7 +2644,10 @@ void svm_vmexit_handler(struct cpu_user_
         goto out;
     }
 
-    perfc_incra(svmexits, exit_reason);
+    perfc_incra(vmexits,
+                exit_reason < VMEXIT_NPF
+                ? exit_reason
+                : exit_reason - VMEXIT_NPF + VMEXIT_NPF_PERFC);
 
     hvm_maybe_deassert_evtchn_irq();
 
@@ -2973,7 +2976,6 @@ void svm_vmexit_handler(struct cpu_user_
         break;
 
     case VMEXIT_NPF:
-        perfc_incra(svmexits, VMEXIT_NPF_PERFC);
         if ( cpu_has_svm_decode )
             v->arch.hvm.svm.cached_insn_len = vmcb->guest_ins_len & 0xf;
         rc = vmcb->exitinfo1 & PFEC_page_present
--- a/xen/arch/x86/include/asm/perfc_defn.h
+++ b/xen/arch/x86/include/asm/perfc_defn.h
@@ -7,13 +7,13 @@ PERFCOUNTER_ARRAY(exceptions,
 #ifdef CONFIG_HVM
 
 #define VMX_PERF_EXIT_REASON_SIZE 65
-#define VMX_PERF_VECTOR_SIZE 0x20
-PERFCOUNTER_ARRAY(vmexits,              "vmexits", VMX_PERF_EXIT_REASON_SIZE)
-PERFCOUNTER_ARRAY(cause_vector,         "cause vector", VMX_PERF_VECTOR_SIZE)
-
 #define VMEXIT_NPF_PERFC 143
 #define SVM_PERF_EXIT_REASON_SIZE (VMEXIT_NPF_PERFC + 1)
-PERFCOUNTER_ARRAY(svmexits,             "SVMexits", SVM_PERF_EXIT_REASON_SIZE)
+PERFCOUNTER_ARRAY(vmexits,              "vmexits",
+                  MAX(VMX_PERF_EXIT_REASON_SIZE, SVM_PERF_EXIT_REASON_SIZE))
+
+#define VMX_PERF_VECTOR_SIZE 0x20
+PERFCOUNTER_ARRAY(cause_vector,         "cause vector", VMX_PERF_VECTOR_SIZE)
 
 #endif /* CONFIG_HVM */
 



^ permalink raw reply

* [Intel-wired-lan] [syzbot] kernel BUG in pskb_expand_head
From: Eric Dumazet @ 2022-01-05 13:59 UTC (permalink / raw)
  To: intel-wired-lan
In-Reply-To: <000000000000c7845605d4d3f0a0@google.com>

On Wed, Jan 5, 2022 at 3:20 AM syzbot
<syzbot+4c63f36709a642f801c5@syzkaller.appspotmail.com> wrote:
>
> syzbot has found a reproducer for the following issue on:
>
> HEAD commit:    c9e6606c7fe9 Linux 5.16-rc8
> git tree:       upstream
> console output: https://syzkaller.appspot.com/x/log.txt?x=148351c3b00000
> kernel config:  https://syzkaller.appspot.com/x/.config?x=32f9fa260d7413b4
> dashboard link: https://syzkaller.appspot.com/bug?extid=4c63f36709a642f801c5
> compiler:       gcc (Debian 10.2.1-6) 10.2.1 20210110, GNU ld (GNU Binutils for Debian) 2.35.2
> syz repro:      https://syzkaller.appspot.com/x/repro.syz?x=15435e2bb00000
> C reproducer:   https://syzkaller.appspot.com/x/repro.c?x=12f4508db00000
>

This C repro looks legit, bug should be in CAN layer.

> The issue was bisected to:
>
> commit e4b8954074f6d0db01c8c97d338a67f9389c042f
> Author: Eric Dumazet <edumazet@google.com>
> Date:   Tue Dec 7 01:30:37 2021 +0000
>
>     netlink: add net device refcount tracker to struct ethnl_req_info

Ignore this bisection, an unrelated commit whent in its way.

>
> bisection log:  https://syzkaller.appspot.com/x/bisect.txt?x=109e6fcbb00000
> final oops:     https://syzkaller.appspot.com/x/report.txt?x=129e6fcbb00000
> console output: https://syzkaller.appspot.com/x/log.txt?x=149e6fcbb00000
>
> IMPORTANT: if you fix the issue, please add the following tag to the commit:
> Reported-by: syzbot+4c63f36709a642f801c5 at syzkaller.appspotmail.com
> Fixes: e4b8954074f6 ("netlink: add net device refcount tracker to struct ethnl_req_info")
>
> skbuff: skb_over_panic: text:ffffffff88235fb8 len:4096 put:4096 head:ffff888021cb8400 data:ffff888021cb8400 tail:0x1000 end:0xc0 dev:<NULL>
> ------------[ cut here ]------------
> kernel BUG at net/core/skbuff.c:113!
> invalid opcode: 0000 [#1] PREEMPT SMP KASAN
> CPU: 1 PID: 19 Comm: ksoftirqd/1 Not tainted 5.16.0-rc8-syzkaller #0
> Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 01/01/2011
> RIP: 0010:skb_panic+0x16c/0x16e net/core/skbuff.c:113
> Code: f8 4c 8b 4c 24 10 8b 4b 70 41 56 45 89 e8 4c 89 e2 41 57 48 89 ee 48 c7 c7 e0 4b ad 8a ff 74 24 10 ff 74 24 20 e8 6e 24 c2 ff <0f> 0b e8 74 92 38 f8 4c 8b 64 24 18 e8 da 47 7f f8 48 c7 c1 80 58
> RSP: 0018:ffffc90000d979e0 EFLAGS: 00010286
> RAX: 000000000000008b RBX: ffff888021ccb500 RCX: 0000000000000000
> RDX: ffff88801196d700 RSI: ffffffff815f0948 RDI: fffff520001b2f2e
> RBP: ffffffff8aad58c0 R08: 000000000000008b R09: 0000000000000000
> R10: ffffffff815ea6ee R11: 0000000000000000 R12: ffffffff88235fb8
> R13: 0000000000001000 R14: ffffffff8aad4ba0 R15: 00000000000000c0
> FS:  0000000000000000(0000) GS:ffff8880b9d00000(0000) knlGS:0000000000000000
> CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
> CR2: 00007f886c8cc718 CR3: 000000007ad6d000 CR4: 00000000003506e0
> DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000
> DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400
> Call Trace:
>  <TASK>
>  skb_over_panic net/core/skbuff.c:118 [inline]
>  skb_put.cold+0x24/0x24 net/core/skbuff.c:1990
>  isotp_rcv_cf net/can/isotp.c:570 [inline]
>  isotp_rcv+0xa38/0x1e30 net/can/isotp.c:668
>  deliver net/can/af_can.c:574 [inline]
>  can_rcv_filter+0x445/0x8d0 net/can/af_can.c:635
>  can_receive+0x31d/0x580 net/can/af_can.c:665
>  can_rcv+0x120/0x1c0 net/can/af_can.c:696
>  __netif_receive_skb_one_core+0x114/0x180 net/core/dev.c:5465
>  __netif_receive_skb+0x24/0x1b0 net/core/dev.c:5579
>  process_backlog+0x2a5/0x6c0 net/core/dev.c:6455
>  __napi_poll+0xaf/0x440 net/core/dev.c:7023
>  napi_poll net/core/dev.c:7090 [inline]
>  net_rx_action+0x801/0xb40 net/core/dev.c:7177
>  __do_softirq+0x29b/0x9c2 kernel/softirq.c:558
>  run_ksoftirqd kernel/softirq.c:921 [inline]
>  run_ksoftirqd+0x2d/0x60 kernel/softirq.c:913
>  smpboot_thread_fn+0x645/0x9c0 kernel/smpboot.c:164
>  kthread+0x405/0x4f0 kernel/kthread.c:327
>  ret_from_fork+0x1f/0x30 arch/x86/entry/entry_64.S:295
>  </TASK>
> Modules linked in:
> ---[ end trace 9f06028ec4daf4be ]---
> RIP: 0010:skb_panic+0x16c/0x16e net/core/skbuff.c:113
> Code: f8 4c 8b 4c 24 10 8b 4b 70 41 56 45 89 e8 4c 89 e2 41 57 48 89 ee 48 c7 c7 e0 4b ad 8a ff 74 24 10 ff 74 24 20 e8 6e 24 c2 ff <0f> 0b e8 74 92 38 f8 4c 8b 64 24 18 e8 da 47 7f f8 48 c7 c1 80 58
> RSP: 0018:ffffc90000d979e0 EFLAGS: 00010286
> RAX: 000000000000008b RBX: ffff888021ccb500 RCX: 0000000000000000
> RDX: ffff88801196d700 RSI: ffffffff815f0948 RDI: fffff520001b2f2e
> RBP: ffffffff8aad58c0 R08: 000000000000008b R09: 0000000000000000
> R10: ffffffff815ea6ee R11: 0000000000000000 R12: ffffffff88235fb8
> R13: 0000000000001000 R14: ffffffff8aad4ba0 R15: 00000000000000c0
> FS:  0000000000000000(0000) GS:ffff8880b9d00000(0000) knlGS:0000000000000000
> CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
> CR2: 00007f886c8cc718 CR3: 000000007ad6d000 CR4: 00000000003506e0
> DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000
> DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400
>

^ permalink raw reply

* Re: [syzbot] kernel BUG in pskb_expand_head
From: Eric Dumazet @ 2022-01-05 13:59 UTC (permalink / raw)
  To: syzbot
  Cc: anthony.l.nguyen, changbin.du, Christian Brauner, David Miller,
	Eric Dumazet, Jesper Dangaard Brouer, Heiner Kallweit,
	intel-wired-lan-owner, intel-wired-lan, Jesse Brandeburg,
	Jakub Kicinski, linux-can, LKML, Marc Kleine-Budde, netdev,
	Oliver Hartkopp, syzkaller-bugs, Yajun Deng
In-Reply-To: <000000000000c7845605d4d3f0a0@google.com>

On Wed, Jan 5, 2022 at 3:20 AM syzbot
<syzbot+4c63f36709a642f801c5@syzkaller.appspotmail.com> wrote:
>
> syzbot has found a reproducer for the following issue on:
>
> HEAD commit:    c9e6606c7fe9 Linux 5.16-rc8
> git tree:       upstream
> console output: https://syzkaller.appspot.com/x/log.txt?x=148351c3b00000
> kernel config:  https://syzkaller.appspot.com/x/.config?x=32f9fa260d7413b4
> dashboard link: https://syzkaller.appspot.com/bug?extid=4c63f36709a642f801c5
> compiler:       gcc (Debian 10.2.1-6) 10.2.1 20210110, GNU ld (GNU Binutils for Debian) 2.35.2
> syz repro:      https://syzkaller.appspot.com/x/repro.syz?x=15435e2bb00000
> C reproducer:   https://syzkaller.appspot.com/x/repro.c?x=12f4508db00000
>

This C repro looks legit, bug should be in CAN layer.

> The issue was bisected to:
>
> commit e4b8954074f6d0db01c8c97d338a67f9389c042f
> Author: Eric Dumazet <edumazet@google.com>
> Date:   Tue Dec 7 01:30:37 2021 +0000
>
>     netlink: add net device refcount tracker to struct ethnl_req_info

Ignore this bisection, an unrelated commit whent in its way.

>
> bisection log:  https://syzkaller.appspot.com/x/bisect.txt?x=109e6fcbb00000
> final oops:     https://syzkaller.appspot.com/x/report.txt?x=129e6fcbb00000
> console output: https://syzkaller.appspot.com/x/log.txt?x=149e6fcbb00000
>
> IMPORTANT: if you fix the issue, please add the following tag to the commit:
> Reported-by: syzbot+4c63f36709a642f801c5@syzkaller.appspotmail.com
> Fixes: e4b8954074f6 ("netlink: add net device refcount tracker to struct ethnl_req_info")
>
> skbuff: skb_over_panic: text:ffffffff88235fb8 len:4096 put:4096 head:ffff888021cb8400 data:ffff888021cb8400 tail:0x1000 end:0xc0 dev:<NULL>
> ------------[ cut here ]------------
> kernel BUG at net/core/skbuff.c:113!
> invalid opcode: 0000 [#1] PREEMPT SMP KASAN
> CPU: 1 PID: 19 Comm: ksoftirqd/1 Not tainted 5.16.0-rc8-syzkaller #0
> Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 01/01/2011
> RIP: 0010:skb_panic+0x16c/0x16e net/core/skbuff.c:113
> Code: f8 4c 8b 4c 24 10 8b 4b 70 41 56 45 89 e8 4c 89 e2 41 57 48 89 ee 48 c7 c7 e0 4b ad 8a ff 74 24 10 ff 74 24 20 e8 6e 24 c2 ff <0f> 0b e8 74 92 38 f8 4c 8b 64 24 18 e8 da 47 7f f8 48 c7 c1 80 58
> RSP: 0018:ffffc90000d979e0 EFLAGS: 00010286
> RAX: 000000000000008b RBX: ffff888021ccb500 RCX: 0000000000000000
> RDX: ffff88801196d700 RSI: ffffffff815f0948 RDI: fffff520001b2f2e
> RBP: ffffffff8aad58c0 R08: 000000000000008b R09: 0000000000000000
> R10: ffffffff815ea6ee R11: 0000000000000000 R12: ffffffff88235fb8
> R13: 0000000000001000 R14: ffffffff8aad4ba0 R15: 00000000000000c0
> FS:  0000000000000000(0000) GS:ffff8880b9d00000(0000) knlGS:0000000000000000
> CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
> CR2: 00007f886c8cc718 CR3: 000000007ad6d000 CR4: 00000000003506e0
> DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000
> DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400
> Call Trace:
>  <TASK>
>  skb_over_panic net/core/skbuff.c:118 [inline]
>  skb_put.cold+0x24/0x24 net/core/skbuff.c:1990
>  isotp_rcv_cf net/can/isotp.c:570 [inline]
>  isotp_rcv+0xa38/0x1e30 net/can/isotp.c:668
>  deliver net/can/af_can.c:574 [inline]
>  can_rcv_filter+0x445/0x8d0 net/can/af_can.c:635
>  can_receive+0x31d/0x580 net/can/af_can.c:665
>  can_rcv+0x120/0x1c0 net/can/af_can.c:696
>  __netif_receive_skb_one_core+0x114/0x180 net/core/dev.c:5465
>  __netif_receive_skb+0x24/0x1b0 net/core/dev.c:5579
>  process_backlog+0x2a5/0x6c0 net/core/dev.c:6455
>  __napi_poll+0xaf/0x440 net/core/dev.c:7023
>  napi_poll net/core/dev.c:7090 [inline]
>  net_rx_action+0x801/0xb40 net/core/dev.c:7177
>  __do_softirq+0x29b/0x9c2 kernel/softirq.c:558
>  run_ksoftirqd kernel/softirq.c:921 [inline]
>  run_ksoftirqd+0x2d/0x60 kernel/softirq.c:913
>  smpboot_thread_fn+0x645/0x9c0 kernel/smpboot.c:164
>  kthread+0x405/0x4f0 kernel/kthread.c:327
>  ret_from_fork+0x1f/0x30 arch/x86/entry/entry_64.S:295
>  </TASK>
> Modules linked in:
> ---[ end trace 9f06028ec4daf4be ]---
> RIP: 0010:skb_panic+0x16c/0x16e net/core/skbuff.c:113
> Code: f8 4c 8b 4c 24 10 8b 4b 70 41 56 45 89 e8 4c 89 e2 41 57 48 89 ee 48 c7 c7 e0 4b ad 8a ff 74 24 10 ff 74 24 20 e8 6e 24 c2 ff <0f> 0b e8 74 92 38 f8 4c 8b 64 24 18 e8 da 47 7f f8 48 c7 c1 80 58
> RSP: 0018:ffffc90000d979e0 EFLAGS: 00010286
> RAX: 000000000000008b RBX: ffff888021ccb500 RCX: 0000000000000000
> RDX: ffff88801196d700 RSI: ffffffff815f0948 RDI: fffff520001b2f2e
> RBP: ffffffff8aad58c0 R08: 000000000000008b R09: 0000000000000000
> R10: ffffffff815ea6ee R11: 0000000000000000 R12: ffffffff88235fb8
> R13: 0000000000001000 R14: ffffffff8aad4ba0 R15: 00000000000000c0
> FS:  0000000000000000(0000) GS:ffff8880b9d00000(0000) knlGS:0000000000000000
> CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
> CR2: 00007f886c8cc718 CR3: 000000007ad6d000 CR4: 00000000003506e0
> DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000
> DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400
>

^ permalink raw reply

* [PATCH 0/3] mtd: rawnand: stm32_fmc2: Add NAND Write Protect support
From: Christophe Kerello @ 2022-01-05 13:57 UTC (permalink / raw)
  To: miquel.raynal, richard, vigneshr, robh+dt, srinivas.kandagatla
  Cc: linux-mtd, linux-kernel, linux-stm32, devicetree, chenshumin86,
	Christophe Kerello

This patchset adds the management of the WP# signal in FMC2 driver.
WP will be disabled in probe/resume callbacks and will be enabled
in remove/suspend callbacks.

This patchset also fixes a conflict on wp-gpios property between
MTD and NVMEN.

Christophe Kerello (3):
  dt-binding: mtd: nand: Document the wp-gpios property
  mtd: rawnand: stm32_fmc2: Add NAND Write Protect support
  nvmem: core: Fix a conflict between MTD and NVMEM on wp-gpios property

 .../bindings/mtd/nand-controller.yaml         |  7 ++++
 drivers/mtd/nand/raw/stm32_fmc2_nand.c        | 40 ++++++++++++++++++-
 drivers/nvmem/core.c                          |  2 +-
 3 files changed, 47 insertions(+), 2 deletions(-)

-- 
2.25.1


______________________________________________________
Linux MTD discussion mailing list
http://lists.infradead.org/mailman/listinfo/linux-mtd/

^ permalink raw reply

* [PATCH 1/3] dt-binding: mtd: nand: Document the wp-gpios property
From: Christophe Kerello @ 2022-01-05 13:57 UTC (permalink / raw)
  To: miquel.raynal, richard, vigneshr, robh+dt, srinivas.kandagatla
  Cc: linux-mtd, linux-kernel, linux-stm32, devicetree, chenshumin86,
	Christophe Kerello
In-Reply-To: <20220105135734.271313-1-christophe.kerello@foss.st.com>

A few drivers use this property to describe the GPIO pin used to protect
the NAND during program/erase operations.

Signed-off-by: Christophe Kerello <christophe.kerello@foss.st.com>
---
 Documentation/devicetree/bindings/mtd/nand-controller.yaml | 7 +++++++
 1 file changed, 7 insertions(+)

diff --git a/Documentation/devicetree/bindings/mtd/nand-controller.yaml b/Documentation/devicetree/bindings/mtd/nand-controller.yaml
index bd217e6f5018..53b21aed0ac5 100644
--- a/Documentation/devicetree/bindings/mtd/nand-controller.yaml
+++ b/Documentation/devicetree/bindings/mtd/nand-controller.yaml
@@ -154,6 +154,13 @@ patternProperties:
           Ready/Busy pins. Active state refers to the NAND ready state and
           should be set to GPIOD_ACTIVE_HIGH unless the signal is inverted.
 
+      wp-gpios:
+        description:
+          Contains one GPIO descriptor for the Write Protect pin.
+          Active state refers to the NAND Write Protect state and should be
+          set to GPIOD_ACTIVE_LOW unless the signal is inverted.
+        maxItems: 1
+
       secure-regions:
         $ref: /schemas/types.yaml#/definitions/uint64-matrix
         description:
-- 
2.25.1


______________________________________________________
Linux MTD discussion mailing list
http://lists.infradead.org/mailman/listinfo/linux-mtd/

^ permalink raw reply related

* [PATCH 2/3] mtd: rawnand: stm32_fmc2: Add NAND Write Protect support
From: Christophe Kerello @ 2022-01-05 13:57 UTC (permalink / raw)
  To: miquel.raynal, richard, vigneshr, robh+dt, srinivas.kandagatla
  Cc: linux-mtd, linux-kernel, linux-stm32, devicetree, chenshumin86,
	Christophe Kerello
In-Reply-To: <20220105135734.271313-1-christophe.kerello@foss.st.com>

This patch adds the support of the WP# signal. WP will be disabled in
probe/resume callbacks and will be enabled in remove/suspend callbacks.

Signed-off-by: Christophe Kerello <christophe.kerello@foss.st.com>
---
 drivers/mtd/nand/raw/stm32_fmc2_nand.c | 40 +++++++++++++++++++++++++-
 1 file changed, 39 insertions(+), 1 deletion(-)

diff --git a/drivers/mtd/nand/raw/stm32_fmc2_nand.c b/drivers/mtd/nand/raw/stm32_fmc2_nand.c
index 97b4e02e43e4..87c1c7dd97eb 100644
--- a/drivers/mtd/nand/raw/stm32_fmc2_nand.c
+++ b/drivers/mtd/nand/raw/stm32_fmc2_nand.c
@@ -9,6 +9,7 @@
 #include <linux/dmaengine.h>
 #include <linux/dma-mapping.h>
 #include <linux/errno.h>
+#include <linux/gpio/consumer.h>
 #include <linux/interrupt.h>
 #include <linux/iopoll.h>
 #include <linux/mfd/syscon.h>
@@ -231,6 +232,7 @@ struct stm32_fmc2_timings {
 
 struct stm32_fmc2_nand {
 	struct nand_chip chip;
+	struct gpio_desc *wp_gpio;
 	struct stm32_fmc2_timings timings;
 	int ncs;
 	int cs_used[FMC2_MAX_CE];
@@ -1747,6 +1749,18 @@ static const struct nand_controller_ops stm32_fmc2_nfc_controller_ops = {
 	.setup_interface = stm32_fmc2_nfc_setup_interface,
 };
 
+static void stm32_fmc2_nfc_wp_enable(struct stm32_fmc2_nand *nand)
+{
+	if (nand->wp_gpio)
+		gpiod_set_value(nand->wp_gpio, 1);
+}
+
+static void stm32_fmc2_nfc_wp_disable(struct stm32_fmc2_nand *nand)
+{
+	if (nand->wp_gpio)
+		gpiod_set_value(nand->wp_gpio, 0);
+}
+
 static int stm32_fmc2_nfc_parse_child(struct stm32_fmc2_nfc *nfc,
 				      struct device_node *dn)
 {
@@ -1785,6 +1799,18 @@ static int stm32_fmc2_nfc_parse_child(struct stm32_fmc2_nfc *nfc,
 		nand->cs_used[i] = cs;
 	}
 
+	nand->wp_gpio = devm_gpiod_get_from_of_node(nfc->dev, dn,
+						    "wp-gpios", 0,
+						    GPIOD_OUT_HIGH, "wp");
+	if (IS_ERR(nand->wp_gpio)) {
+		ret = PTR_ERR(nand->wp_gpio);
+		if (ret != -ENOENT)
+			return dev_err_probe(nfc->dev, ret,
+					     "failed to request WP GPIO\n");
+
+		nand->wp_gpio = NULL;
+	}
+
 	nand_set_flash_node(&nand->chip, dn);
 
 	return 0;
@@ -1956,10 +1982,12 @@ static int stm32_fmc2_nfc_probe(struct platform_device *pdev)
 	chip->options |= NAND_BUSWIDTH_AUTO | NAND_NO_SUBPAGE_WRITE |
 			 NAND_USES_DMA;
 
+	stm32_fmc2_nfc_wp_disable(nand);
+
 	/* Scan to find existence of the device */
 	ret = nand_scan(chip, nand->ncs);
 	if (ret)
-		goto err_release_dma;
+		goto err_wp_enable;
 
 	ret = mtd_device_register(mtd, NULL, 0);
 	if (ret)
@@ -1972,6 +2000,9 @@ static int stm32_fmc2_nfc_probe(struct platform_device *pdev)
 err_nand_cleanup:
 	nand_cleanup(chip);
 
+err_wp_enable:
+	stm32_fmc2_nfc_wp_enable(nand);
+
 err_release_dma:
 	if (nfc->dma_ecc_ch)
 		dma_release_channel(nfc->dma_ecc_ch);
@@ -2012,15 +2043,20 @@ static int stm32_fmc2_nfc_remove(struct platform_device *pdev)
 
 	clk_disable_unprepare(nfc->clk);
 
+	stm32_fmc2_nfc_wp_enable(nand);
+
 	return 0;
 }
 
 static int __maybe_unused stm32_fmc2_nfc_suspend(struct device *dev)
 {
 	struct stm32_fmc2_nfc *nfc = dev_get_drvdata(dev);
+	struct stm32_fmc2_nand *nand = &nfc->nand;
 
 	clk_disable_unprepare(nfc->clk);
 
+	stm32_fmc2_nfc_wp_enable(nand);
+
 	pinctrl_pm_select_sleep_state(dev);
 
 	return 0;
@@ -2042,6 +2078,8 @@ static int __maybe_unused stm32_fmc2_nfc_resume(struct device *dev)
 
 	stm32_fmc2_nfc_init(nfc);
 
+	stm32_fmc2_nfc_wp_disable(nand);
+
 	for (chip_cs = 0; chip_cs < FMC2_MAX_CE; chip_cs++) {
 		if (!(nfc->cs_assigned & BIT(chip_cs)))
 			continue;
-- 
2.25.1


______________________________________________________
Linux MTD discussion mailing list
http://lists.infradead.org/mailman/listinfo/linux-mtd/

^ permalink raw reply related

* [PATCH 3/3] nvmem: core: Fix a conflict between MTD and NVMEM on wp-gpios property
From: Christophe Kerello @ 2022-01-05 13:57 UTC (permalink / raw)
  To: miquel.raynal, richard, vigneshr, robh+dt, srinivas.kandagatla
  Cc: linux-mtd, linux-kernel, linux-stm32, devicetree, chenshumin86,
	Christophe Kerello
In-Reply-To: <20220105135734.271313-1-christophe.kerello@foss.st.com>

Wp-gpios property can be used on NVMEN nodes and the same property can
be also used on MTD NAND nodes. In case of the wp-gpios property is
defined at NAND level node, the GPIO management is done at NAND driver
level. Write protect is disabled when the driver is probed or resumed
and is enabled when the driver is released or suspended.

When no partitions are defined in the NAND DT node, then the NAND DT node
will be passed to NVMEM framework. If wp-gpios property is defined in
this node, the GPIO resource is taken twice and the NAND controller
driver fails to probe.

It would be possible to set config->wp_gpio at MTD level before calling
nvmem_register function but NVMEM framework will toggled this GPIO on
each write when this GPIO should only be controlled at NAND level driver
to ensure that the Write Protect has not been enabled.

As MTD framework is only using NVMEN framework in read only, a way to fix
this conflict is to get the GPIO resource at NVMEM level only if reg_write
API is defined. This GPIO is only toggled if reg_write ops is defined.

Signed-off-by: Christophe Kerello <christophe.kerello@foss.st.com>
---
 drivers/nvmem/core.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/nvmem/core.c b/drivers/nvmem/core.c
index e765d3d0542e..e11c74db64f9 100644
--- a/drivers/nvmem/core.c
+++ b/drivers/nvmem/core.c
@@ -769,7 +769,7 @@ struct nvmem_device *nvmem_register(const struct nvmem_config *config)
 
 	if (config->wp_gpio)
 		nvmem->wp_gpio = config->wp_gpio;
-	else
+	else if (config->reg_write)
 		nvmem->wp_gpio = gpiod_get_optional(config->dev, "wp",
 						    GPIOD_OUT_HIGH);
 	if (IS_ERR(nvmem->wp_gpio)) {
-- 
2.25.1


______________________________________________________
Linux MTD discussion mailing list
http://lists.infradead.org/mailman/listinfo/linux-mtd/

^ permalink raw reply related

* [PATCH  v1 21/34] hw/arm: add control knob to disable kaslr_seed via DTB
From: Alex Bennée @ 2022-01-05 13:49 UTC (permalink / raw)
  To: qemu-devel
  Cc: fam, berrange, f4bug, aurelien, pbonzini, stefanha, crosa,
	Alex Bennée, Heinrich Schuchardt, Ilias Apalodimas,
	Jerome Forissier, Peter Maydell, open list:Virt
In-Reply-To: <20220105135009.1584676-1-alex.bennee@linaro.org>

Generally a guest needs an external source of randomness to properly
enable things like address space randomisation. However in a trusted
boot environment where the firmware will cryptographically verify
components having random data in the DTB will cause verification to
fail. Add a control knob so we can prevent this being added to the
system DTB.

Signed-off-by: Alex Bennée <alex.bennee@linaro.org>
Tested-by: Heinrich Schuchardt <xypron.glpk@gmx.de>
Acked-by: Ilias Apalodimas <ilias.apalodimas@linaro.org>
Acked-by: Jerome Forissier <jerome@forissier.org>
Message-Id: <20211215120926.1696302-1-alex.bennee@linaro.org>
---
 docs/system/arm/virt.rst |  7 +++++++
 include/hw/arm/virt.h    |  1 +
 hw/arm/virt.c            | 32 ++++++++++++++++++++++++++++++--
 3 files changed, 38 insertions(+), 2 deletions(-)

diff --git a/docs/system/arm/virt.rst b/docs/system/arm/virt.rst
index 850787495b..c86a4808df 100644
--- a/docs/system/arm/virt.rst
+++ b/docs/system/arm/virt.rst
@@ -121,6 +121,13 @@ ras
   Set ``on``/``off`` to enable/disable reporting host memory errors to a guest
   using ACPI and guest external abort exceptions. The default is off.
 
+kaslr-dtb-seed
+  Set ``on``/``off`` to pass a random seed via the guest dtb to use for features
+  like address space randomisation. The default is ``on``. You will want
+  to disable it if your trusted boot chain will verify the DTB it is
+  passed. It would be the responsibility of the firmware to come up
+  with a seed and pass it on if it wants to.
+
 Linux guest kernel configuration
 """"""""""""""""""""""""""""""""
 
diff --git a/include/hw/arm/virt.h b/include/hw/arm/virt.h
index dc6b66ffc8..acd0665fe7 100644
--- a/include/hw/arm/virt.h
+++ b/include/hw/arm/virt.h
@@ -148,6 +148,7 @@ struct VirtMachineState {
     bool virt;
     bool ras;
     bool mte;
+    bool kaslr_dtb_seed;
     OnOffAuto acpi;
     VirtGICType gic_version;
     VirtIOMMUType iommu;
diff --git a/hw/arm/virt.c b/hw/arm/virt.c
index 6bce595aba..1781e47c76 100644
--- a/hw/arm/virt.c
+++ b/hw/arm/virt.c
@@ -247,11 +247,15 @@ static void create_fdt(VirtMachineState *vms)
 
     /* /chosen must exist for load_dtb to fill in necessary properties later */
     qemu_fdt_add_subnode(fdt, "/chosen");
-    create_kaslr_seed(ms, "/chosen");
+    if (vms->kaslr_dtb_seed) {
+        create_kaslr_seed(ms, "/chosen");
+    }
 
     if (vms->secure) {
         qemu_fdt_add_subnode(fdt, "/secure-chosen");
-        create_kaslr_seed(ms, "/secure-chosen");
+        if (vms->kaslr_dtb_seed) {
+            create_kaslr_seed(ms, "/secure-chosen");
+        }
     }
 
     /* Clock node, for the benefit of the UART. The kernel device tree
@@ -2235,6 +2239,20 @@ static void virt_set_its(Object *obj, bool value, Error **errp)
     vms->its = value;
 }
 
+static bool virt_get_kaslr_dtb_seed(Object *obj, Error **errp)
+{
+    VirtMachineState *vms = VIRT_MACHINE(obj);
+
+    return vms->kaslr_dtb_seed;
+}
+
+static void virt_set_kaslr_dtb_seed(Object *obj, bool value, Error **errp)
+{
+    VirtMachineState *vms = VIRT_MACHINE(obj);
+
+    vms->kaslr_dtb_seed = value;
+}
+
 static char *virt_get_oem_id(Object *obj, Error **errp)
 {
     VirtMachineState *vms = VIRT_MACHINE(obj);
@@ -2764,6 +2782,13 @@ static void virt_machine_class_init(ObjectClass *oc, void *data)
                                           "Set on/off to enable/disable "
                                           "ITS instantiation");
 
+    object_class_property_add_bool(oc, "kaslr-dtb-seed",
+                                   virt_get_kaslr_dtb_seed,
+                                   virt_set_kaslr_dtb_seed);
+    object_class_property_set_description(oc, "kaslr-dtb-seed",
+                                          "Set off to disable passing of kaslr "
+                                          "dtb node to guest");
+
     object_class_property_add_str(oc, "x-oem-id",
                                   virt_get_oem_id,
                                   virt_set_oem_id);
@@ -2828,6 +2853,9 @@ static void virt_instance_init(Object *obj)
     /* MTE is disabled by default.  */
     vms->mte = false;
 
+    /* Supply a kaslr-seed by default */
+    vms->kaslr_dtb_seed = true;
+
     vms->irqmap = a15irqmap;
 
     virt_flash_create(vms);
-- 
2.30.2

^ permalink raw reply related

* [PATCH v4 00/11] Add cnxk_gpio
From: Tomasz Duszynski @ 2022-01-05 14:00 UTC (permalink / raw)
  To: dev; +Cc: thomas, jerinj, Tomasz Duszynski
In-Reply-To: <20211213081732.2096334-1-tduszynski@marvell.com>

This series introduces a new rawdevice PMD which allows
to manage userspace GPIOs and install custom GPIO interrupt
handlers which bypass kernel. This is especially useful for
applications that, besides providing standard dataplane functionality,
want to have fast and low latency access to GPIO pin state.

It'd be great to have that merged during 22.02 merge window.

v4:
- free kvargs after parsing arguments
- add support for allowing only subset of available GPIOs

v3:
- fix meson formatting
- fix cnxk_gpio_process_buf() return value

v2:
- do not trigger irq by writing to /dev/mem, use ioctl() instead

Tomasz Duszynski (11):
  raw/cnxk_gpio: add GPIO driver skeleton
  raw/cnxk_gpio: support reading default queue conf
  raw/cnxk_gpio: support reading queue count
  raw/cnxk_gpio: support queue setup
  raw/cnxk_gpio: support queue release
  raw/cnxk_gpio: support enqueuing buffers
  raw/cnxk_gpio: support dequeuing buffers
  raw/cnxk_gpio: support standard GPIO operations
  raw/cnxk_gpio: support custom irq handlers
  raw/cnxk_gpio: support selftest
  raw/cnxk_gpio: add option to allow using subset of GPIOs

 doc/guides/rawdevs/cnxk_gpio.rst           | 200 ++++++
 doc/guides/rawdevs/index.rst               |   1 +
 drivers/raw/cnxk_gpio/cnxk_gpio.c          | 754 +++++++++++++++++++++
 drivers/raw/cnxk_gpio/cnxk_gpio.h          |  35 +
 drivers/raw/cnxk_gpio/cnxk_gpio_irq.c      | 216 ++++++
 drivers/raw/cnxk_gpio/cnxk_gpio_selftest.c | 386 +++++++++++
 drivers/raw/cnxk_gpio/meson.build          |  11 +
 drivers/raw/cnxk_gpio/rte_pmd_cnxk_gpio.h  | 437 ++++++++++++
 drivers/raw/cnxk_gpio/version.map          |   3 +
 drivers/raw/meson.build                    |   1 +
 10 files changed, 2044 insertions(+)
 create mode 100644 doc/guides/rawdevs/cnxk_gpio.rst
 create mode 100644 drivers/raw/cnxk_gpio/cnxk_gpio.c
 create mode 100644 drivers/raw/cnxk_gpio/cnxk_gpio.h
 create mode 100644 drivers/raw/cnxk_gpio/cnxk_gpio_irq.c
 create mode 100644 drivers/raw/cnxk_gpio/cnxk_gpio_selftest.c
 create mode 100644 drivers/raw/cnxk_gpio/meson.build
 create mode 100644 drivers/raw/cnxk_gpio/rte_pmd_cnxk_gpio.h
 create mode 100644 drivers/raw/cnxk_gpio/version.map

--
2.25.1


^ permalink raw reply

* [PATCH v4 02/11] raw/cnxk_gpio: support reading default queue conf
From: Tomasz Duszynski @ 2022-01-05 14:00 UTC (permalink / raw)
  To: dev; +Cc: thomas, jerinj, Tomasz Duszynski
In-Reply-To: <20220105140020.1615256-1-tduszynski@marvell.com>

Add support for reading default queue configuration.

Signed-off-by: Tomasz Duszynski <tduszynski@marvell.com>
---
 drivers/raw/cnxk_gpio/cnxk_gpio.c | 19 +++++++++++++++++++
 1 file changed, 19 insertions(+)

diff --git a/drivers/raw/cnxk_gpio/cnxk_gpio.c b/drivers/raw/cnxk_gpio/cnxk_gpio.c
index 881615d62e..f80788f7fb 100644
--- a/drivers/raw/cnxk_gpio/cnxk_gpio.c
+++ b/drivers/raw/cnxk_gpio/cnxk_gpio.c
@@ -138,7 +138,26 @@ cnxk_gpio_read_attr_int(char *attr, int *val)
 	return 0;
 }
 
+static int
+cnxk_gpio_queue_def_conf(struct rte_rawdev *dev, uint16_t queue_id,
+			 rte_rawdev_obj_t queue_conf, size_t queue_conf_size)
+{
+	unsigned int *conf;
+
+	RTE_SET_USED(dev);
+	RTE_SET_USED(queue_id);
+
+	if (queue_conf_size != sizeof(*conf))
+		return -EINVAL;
+
+	conf = (unsigned int *)queue_conf;
+	*conf = 1;
+
+	return 0;
+}
+
 static const struct rte_rawdev_ops cnxk_gpio_rawdev_ops = {
+	.queue_def_conf = cnxk_gpio_queue_def_conf,
 };
 
 static int
-- 
2.25.1


^ permalink raw reply related

* [PATCH v4 01/11] raw/cnxk_gpio: add GPIO driver skeleton
From: Tomasz Duszynski @ 2022-01-05 14:00 UTC (permalink / raw)
  To: dev, Ray Kinsella, Anatoly Burakov; +Cc: thomas, jerinj, Tomasz Duszynski
In-Reply-To: <20220105140020.1615256-1-tduszynski@marvell.com>

Add initial support for PMD that allows to control particular pins form
userspace. Moreover PMD allows to attach custom interrupt handlers to
controllable GPIOs.

Main users of this PMD are dataplain applications requiring fast and low
latency access to pin state.

Signed-off-by: Tomasz Duszynski <tduszynski@marvell.com>
---
 doc/guides/rawdevs/cnxk_gpio.rst  |  65 ++++++++
 doc/guides/rawdevs/index.rst      |   1 +
 drivers/raw/cnxk_gpio/cnxk_gpio.c | 239 ++++++++++++++++++++++++++++++
 drivers/raw/cnxk_gpio/cnxk_gpio.h |  22 +++
 drivers/raw/cnxk_gpio/meson.build |   8 +
 drivers/raw/cnxk_gpio/version.map |   3 +
 drivers/raw/meson.build           |   1 +
 7 files changed, 339 insertions(+)
 create mode 100644 doc/guides/rawdevs/cnxk_gpio.rst
 create mode 100644 drivers/raw/cnxk_gpio/cnxk_gpio.c
 create mode 100644 drivers/raw/cnxk_gpio/cnxk_gpio.h
 create mode 100644 drivers/raw/cnxk_gpio/meson.build
 create mode 100644 drivers/raw/cnxk_gpio/version.map

diff --git a/doc/guides/rawdevs/cnxk_gpio.rst b/doc/guides/rawdevs/cnxk_gpio.rst
new file mode 100644
index 0000000000..868302d07f
--- /dev/null
+++ b/doc/guides/rawdevs/cnxk_gpio.rst
@@ -0,0 +1,65 @@
+..  SPDX-License-Identifier: BSD-3-Clause
+    Copyright(c) 2021 Marvell.
+
+Marvell CNXK GPIO Driver
+========================
+
+CNXK GPIO PMD configures and manages GPIOs available on the system using
+standard enqueue/dequeue mechanism offered by raw device abstraction. PMD relies
+both on standard sysfs GPIO interface provided by the Linux kernel and GPIO
+kernel driver custom interface allowing one to install userspace interrupt
+handlers.
+
+Features
+--------
+
+Following features are available:
+
+- export/unexport a GPIO
+- read/write specific value from/to exported GPIO
+- set GPIO direction
+- set GPIO edge that triggers interrupt
+- set GPIO active low
+- register interrupt handler for specific GPIO
+
+Requirements
+------------
+
+PMD relies on modified kernel GPIO driver which exposes ``ioctl()`` interface
+for installing interrupt handlers for low latency signal processing.
+
+Driver is shipped with Marvell SDK.
+
+Device Setup
+------------
+
+CNXK GPIO PMD binds to virtual device which gets created by passing
+`--vdev=cnxk_gpio,gpiochip=<number>` command line to EAL. `gpiochip` parameter
+tells PMD which GPIO controller should be used. Available controllers are
+available under `/sys/class/gpio`. For further details on how Linux represents
+GPIOs in userspace please refer to
+`sysfs.txt <https://www.kernel.org/doc/Documentation/gpio/sysfs.txt>`_.
+
+If `gpiochip=<number>` was omitted then first gpiochip from the alphabetically
+sort list of available gpiochips is used.
+
+.. code-block:: console
+
+   $ ls /sys/class/gpio
+   export gpiochip448 unexport
+
+In above scenario only one GPIO controller is present hence
+`--vdev=cnxk_gpio,gpiochip=448` should be passed to EAL.
+
+Before performing actual data transfer one needs to call
+``rte_rawdev_queue_count()`` followed by ``rte_rawdev_queue_conf_get()``. The
+former returns number GPIOs available in the system irrespective of GPIOs
+being controllable or not. Thus it is user responsibility to pick the proper
+ones. The latter call simply returns queue capacity.
+
+Respective queue needs to be configured with ``rte_rawdev_queue_setup()``. This
+call barely exports GPIO to userspace.
+
+To perform actual data transfer use standard ``rte_rawdev_enqueue_buffers()``
+and ``rte_rawdev_dequeue_buffers()`` APIs. Not all messages produce sensible
+responses hence dequeueing is not always necessary.
diff --git a/doc/guides/rawdevs/index.rst b/doc/guides/rawdevs/index.rst
index b6cf917443..0c02da6e90 100644
--- a/doc/guides/rawdevs/index.rst
+++ b/doc/guides/rawdevs/index.rst
@@ -12,6 +12,7 @@ application through rawdev API.
     :numbered:
 
     cnxk_bphy
+    cnxk_gpio
     dpaa2_cmdif
     dpaa2_qdma
     ifpga
diff --git a/drivers/raw/cnxk_gpio/cnxk_gpio.c b/drivers/raw/cnxk_gpio/cnxk_gpio.c
new file mode 100644
index 0000000000..881615d62e
--- /dev/null
+++ b/drivers/raw/cnxk_gpio/cnxk_gpio.c
@@ -0,0 +1,239 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(C) 2021 Marvell.
+ */
+
+#include <dirent.h>
+#include <string.h>
+
+#include <rte_bus_vdev.h>
+#include <rte_eal.h>
+#include <rte_kvargs.h>
+#include <rte_lcore.h>
+#include <rte_rawdev_pmd.h>
+
+#include <roc_api.h>
+
+#include "cnxk_gpio.h"
+
+#define CNXK_GPIO_BUFSZ 128
+#define CNXK_GPIO_CLASS_PATH "/sys/class/gpio"
+
+static const char *const cnxk_gpio_args[] = {
+#define CNXK_GPIO_ARG_GPIOCHIP "gpiochip"
+	CNXK_GPIO_ARG_GPIOCHIP,
+	NULL
+};
+
+static void
+cnxk_gpio_format_name(char *name, size_t len)
+{
+	snprintf(name, len, "cnxk_gpio");
+}
+
+static int
+cnxk_gpio_filter_gpiochip(const struct dirent *dirent)
+{
+	const char *pattern = "gpiochip";
+
+	return !strncmp(dirent->d_name, pattern, strlen(pattern));
+}
+
+static void
+cnxk_gpio_set_defaults(struct cnxk_gpiochip *gpiochip)
+{
+	struct dirent **namelist;
+	int n;
+
+	n = scandir(CNXK_GPIO_CLASS_PATH, &namelist, cnxk_gpio_filter_gpiochip,
+		    alphasort);
+	if (n < 0 || n == 0)
+		return;
+
+	sscanf(namelist[0]->d_name, "gpiochip%d", &gpiochip->num);
+	while (n--)
+		free(namelist[n]);
+	free(namelist);
+}
+
+static int
+cnxk_gpio_parse_arg_gpiochip(const char *key __rte_unused, const char *value,
+			     void *extra_args)
+{
+	long val;
+
+	errno = 0;
+	val = strtol(value, NULL, 10);
+	if (errno)
+		return -errno;
+
+	*(int *)extra_args = (int)val;
+
+	return 0;
+}
+
+static int
+cnxk_gpio_parse_args(struct cnxk_gpiochip *gpiochip,
+		     struct rte_devargs *devargs)
+{
+	struct rte_kvargs *kvlist;
+	int ret;
+
+	kvlist = rte_kvargs_parse(devargs->args, cnxk_gpio_args);
+	if (!kvlist)
+		return 0;
+
+	ret = rte_kvargs_count(kvlist, CNXK_GPIO_ARG_GPIOCHIP);
+	if (ret == 1) {
+		ret = rte_kvargs_process(kvlist, CNXK_GPIO_ARG_GPIOCHIP,
+					 cnxk_gpio_parse_arg_gpiochip,
+					 &gpiochip->num);
+		if (ret)
+			goto out;
+	}
+
+	ret = 0;
+out:
+	rte_kvargs_free(kvlist);
+
+	return ret;
+}
+
+static int
+cnxk_gpio_read_attr(char *attr, char *val)
+{
+	FILE *fp;
+	int ret;
+
+	fp = fopen(attr, "r");
+	if (!fp)
+		return -errno;
+
+	ret = fscanf(fp, "%s", val);
+	if (ret < 0)
+		return -errno;
+	if (ret != 1)
+		return -EIO;
+
+	ret = fclose(fp);
+	if (ret)
+		return -errno;
+
+	return 0;
+}
+
+static int
+cnxk_gpio_read_attr_int(char *attr, int *val)
+{
+	char buf[CNXK_GPIO_BUFSZ];
+	int ret;
+
+	ret = cnxk_gpio_read_attr(attr, buf);
+	if (ret)
+		return ret;
+
+	ret = sscanf(buf, "%d", val);
+	if (ret < 0)
+		return -errno;
+
+	return 0;
+}
+
+static const struct rte_rawdev_ops cnxk_gpio_rawdev_ops = {
+};
+
+static int
+cnxk_gpio_probe(struct rte_vdev_device *dev)
+{
+	char name[RTE_RAWDEV_NAME_MAX_LEN];
+	struct cnxk_gpiochip *gpiochip;
+	struct rte_rawdev *rawdev;
+	char buf[CNXK_GPIO_BUFSZ];
+	int ret;
+
+	if (rte_eal_process_type() != RTE_PROC_PRIMARY)
+		return 0;
+
+	cnxk_gpio_format_name(name, sizeof(name));
+	rawdev = rte_rawdev_pmd_allocate(name, sizeof(*gpiochip),
+					 rte_socket_id());
+	if (!rawdev) {
+		RTE_LOG(ERR, PMD, "failed to allocate %s rawdev", name);
+		return -ENOMEM;
+	}
+
+	rawdev->dev_ops = &cnxk_gpio_rawdev_ops;
+	rawdev->device = &dev->device;
+	rawdev->driver_name = dev->device.name;
+
+	gpiochip = rawdev->dev_private;
+	cnxk_gpio_set_defaults(gpiochip);
+
+	/* defaults may be overwritten by this call */
+	ret = cnxk_gpio_parse_args(gpiochip, dev->device.devargs);
+	if (ret)
+		goto out;
+
+	/* read gpio base */
+	snprintf(buf, sizeof(buf), "%s/gpiochip%d/base", CNXK_GPIO_CLASS_PATH,
+		 gpiochip->num);
+	ret = cnxk_gpio_read_attr_int(buf, &gpiochip->base);
+	if (ret) {
+		RTE_LOG(ERR, PMD, "failed to read %s", buf);
+		goto out;
+	}
+
+	/* read number of available gpios */
+	snprintf(buf, sizeof(buf), "%s/gpiochip%d/ngpio", CNXK_GPIO_CLASS_PATH,
+		 gpiochip->num);
+	ret = cnxk_gpio_read_attr_int(buf, &gpiochip->num_gpios);
+	if (ret) {
+		RTE_LOG(ERR, PMD, "failed to read %s", buf);
+		goto out;
+	}
+
+	gpiochip->gpios = rte_calloc(NULL, gpiochip->num_gpios,
+				     sizeof(struct cnxk_gpio *), 0);
+	if (!gpiochip->gpios) {
+		RTE_LOG(ERR, PMD, "failed to allocate gpios memory");
+		ret = -ENOMEM;
+		goto out;
+	}
+
+	return 0;
+out:
+	rte_rawdev_pmd_release(rawdev);
+
+	return ret;
+}
+
+static int
+cnxk_gpio_remove(struct rte_vdev_device *dev)
+{
+	char name[RTE_RAWDEV_NAME_MAX_LEN];
+	struct cnxk_gpiochip *gpiochip;
+	struct rte_rawdev *rawdev;
+
+	RTE_SET_USED(dev);
+
+	if (rte_eal_process_type() != RTE_PROC_PRIMARY)
+		return 0;
+
+	cnxk_gpio_format_name(name, sizeof(name));
+	rawdev = rte_rawdev_pmd_get_named_dev(name);
+	if (!rawdev)
+		return -ENODEV;
+
+	gpiochip = rawdev->dev_private;
+	rte_free(gpiochip->gpios);
+	rte_rawdev_pmd_release(rawdev);
+
+	return 0;
+}
+
+static struct rte_vdev_driver cnxk_gpio_drv = {
+	.probe = cnxk_gpio_probe,
+	.remove = cnxk_gpio_remove,
+};
+
+RTE_PMD_REGISTER_VDEV(cnxk_gpio, cnxk_gpio_drv);
+RTE_PMD_REGISTER_PARAM_STRING(cnxk_gpio, "gpiochip=<int>");
diff --git a/drivers/raw/cnxk_gpio/cnxk_gpio.h b/drivers/raw/cnxk_gpio/cnxk_gpio.h
new file mode 100644
index 0000000000..4dae8316ba
--- /dev/null
+++ b/drivers/raw/cnxk_gpio/cnxk_gpio.h
@@ -0,0 +1,22 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(C) 2021 Marvell.
+ */
+
+#ifndef _CNXK_GPIO_H_
+#define _CNXK_GPIO_H_
+
+struct cnxk_gpiochip;
+
+struct cnxk_gpio {
+	struct cnxk_gpiochip *gpiochip;
+	int num;
+};
+
+struct cnxk_gpiochip {
+	int num;
+	int base;
+	int num_gpios;
+	struct cnxk_gpio **gpios;
+};
+
+#endif /* _CNXK_GPIO_H_ */
diff --git a/drivers/raw/cnxk_gpio/meson.build b/drivers/raw/cnxk_gpio/meson.build
new file mode 100644
index 0000000000..9a7e716c1e
--- /dev/null
+++ b/drivers/raw/cnxk_gpio/meson.build
@@ -0,0 +1,8 @@
+# SPDX-License-Identifier: BSD-3-Clause
+# Copyright(C) 2021 Marvell.
+#
+
+deps += ['bus_vdev', 'common_cnxk', 'rawdev', 'kvargs']
+sources = files(
+        'cnxk_gpio.c',
+)
diff --git a/drivers/raw/cnxk_gpio/version.map b/drivers/raw/cnxk_gpio/version.map
new file mode 100644
index 0000000000..4a76d1d52d
--- /dev/null
+++ b/drivers/raw/cnxk_gpio/version.map
@@ -0,0 +1,3 @@
+DPDK_21 {
+	local: *;
+};
diff --git a/drivers/raw/meson.build b/drivers/raw/meson.build
index 87694a758e..05e7de1bfe 100644
--- a/drivers/raw/meson.build
+++ b/drivers/raw/meson.build
@@ -7,6 +7,7 @@ endif
 
 drivers = [
         'cnxk_bphy',
+        'cnxk_gpio',
         'dpaa2_cmdif',
         'dpaa2_qdma',
         'ifpga',
-- 
2.25.1


^ permalink raw reply related

* [PATCH v4 03/11] raw/cnxk_gpio: support reading queue count
From: Tomasz Duszynski @ 2022-01-05 14:00 UTC (permalink / raw)
  To: dev; +Cc: thomas, jerinj, Tomasz Duszynski
In-Reply-To: <20220105140020.1615256-1-tduszynski@marvell.com>

Add support for reading number of available queues. Single queue
corresponds to GPIO.

Signed-off-by: Tomasz Duszynski <tduszynski@marvell.com>
---
 drivers/raw/cnxk_gpio/cnxk_gpio.c | 9 +++++++++
 1 file changed, 9 insertions(+)

diff --git a/drivers/raw/cnxk_gpio/cnxk_gpio.c b/drivers/raw/cnxk_gpio/cnxk_gpio.c
index f80788f7fb..3455d6258c 100644
--- a/drivers/raw/cnxk_gpio/cnxk_gpio.c
+++ b/drivers/raw/cnxk_gpio/cnxk_gpio.c
@@ -156,8 +156,17 @@ cnxk_gpio_queue_def_conf(struct rte_rawdev *dev, uint16_t queue_id,
 	return 0;
 }
 
+static uint16_t
+cnxk_gpio_queue_count(struct rte_rawdev *dev)
+{
+	struct cnxk_gpiochip *gpiochip = dev->dev_private;
+
+	return gpiochip->num_gpios;
+}
+
 static const struct rte_rawdev_ops cnxk_gpio_rawdev_ops = {
 	.queue_def_conf = cnxk_gpio_queue_def_conf,
+	.queue_count = cnxk_gpio_queue_count,
 };
 
 static int
-- 
2.25.1


^ permalink raw reply related

* [PATCH v4 04/11] raw/cnxk_gpio: support queue setup
From: Tomasz Duszynski @ 2022-01-05 14:00 UTC (permalink / raw)
  To: dev; +Cc: thomas, jerinj, Tomasz Duszynski
In-Reply-To: <20220105140020.1615256-1-tduszynski@marvell.com>

Add support for queue setup.

Signed-off-by: Tomasz Duszynski <tduszynski@marvell.com>
---
 drivers/raw/cnxk_gpio/cnxk_gpio.c | 80 +++++++++++++++++++++++++++++++
 1 file changed, 80 insertions(+)

diff --git a/drivers/raw/cnxk_gpio/cnxk_gpio.c b/drivers/raw/cnxk_gpio/cnxk_gpio.c
index 3455d6258c..c1e74fad43 100644
--- a/drivers/raw/cnxk_gpio/cnxk_gpio.c
+++ b/drivers/raw/cnxk_gpio/cnxk_gpio.c
@@ -138,6 +138,85 @@ cnxk_gpio_read_attr_int(char *attr, int *val)
 	return 0;
 }
 
+static int
+cnxk_gpio_write_attr(const char *attr, const char *val)
+{
+	FILE *fp;
+	int ret;
+
+	if (!val)
+		return -EINVAL;
+
+	fp = fopen(attr, "w");
+	if (!fp)
+		return -errno;
+
+	ret = fprintf(fp, "%s", val);
+	if (ret < 0) {
+		fclose(fp);
+		return ret;
+	}
+
+	ret = fclose(fp);
+	if (ret)
+		return -errno;
+
+	return 0;
+}
+
+static int
+cnxk_gpio_write_attr_int(const char *attr, int val)
+{
+	char buf[CNXK_GPIO_BUFSZ];
+
+	snprintf(buf, sizeof(buf), "%d", val);
+
+	return cnxk_gpio_write_attr(attr, buf);
+}
+
+static struct cnxk_gpio *
+cnxk_gpio_lookup(struct cnxk_gpiochip *gpiochip, uint16_t queue)
+{
+	if (queue >= gpiochip->num_gpios)
+		return NULL;
+
+	return gpiochip->gpios[queue];
+}
+
+static int
+cnxk_gpio_queue_setup(struct rte_rawdev *dev, uint16_t queue_id,
+		      rte_rawdev_obj_t queue_conf, size_t queue_conf_size)
+{
+	struct cnxk_gpiochip *gpiochip = dev->dev_private;
+	char buf[CNXK_GPIO_BUFSZ];
+	struct cnxk_gpio *gpio;
+	int ret;
+
+	RTE_SET_USED(queue_conf);
+	RTE_SET_USED(queue_conf_size);
+
+	gpio = cnxk_gpio_lookup(gpiochip, queue_id);
+	if (gpio)
+		return -EEXIST;
+
+	gpio = rte_zmalloc(NULL, sizeof(*gpio), 0);
+	if (!gpio)
+		return -ENOMEM;
+	gpio->num = queue_id + gpiochip->base;
+	gpio->gpiochip = gpiochip;
+
+	snprintf(buf, sizeof(buf), "%s/export", CNXK_GPIO_CLASS_PATH);
+	ret = cnxk_gpio_write_attr_int(buf, gpio->num);
+	if (ret) {
+		rte_free(gpio);
+		return ret;
+	}
+
+	gpiochip->gpios[queue_id] = gpio;
+
+	return 0;
+}
+
 static int
 cnxk_gpio_queue_def_conf(struct rte_rawdev *dev, uint16_t queue_id,
 			 rte_rawdev_obj_t queue_conf, size_t queue_conf_size)
@@ -167,6 +246,7 @@ cnxk_gpio_queue_count(struct rte_rawdev *dev)
 static const struct rte_rawdev_ops cnxk_gpio_rawdev_ops = {
 	.queue_def_conf = cnxk_gpio_queue_def_conf,
 	.queue_count = cnxk_gpio_queue_count,
+	.queue_setup = cnxk_gpio_queue_setup,
 };
 
 static int
-- 
2.25.1


^ permalink raw reply related

* [PATCH v4 05/11] raw/cnxk_gpio: support queue release
From: Tomasz Duszynski @ 2022-01-05 14:00 UTC (permalink / raw)
  To: dev; +Cc: thomas, jerinj, Tomasz Duszynski
In-Reply-To: <20220105140020.1615256-1-tduszynski@marvell.com>

Add support for queue release.

Signed-off-by: Tomasz Duszynski <tduszynski@marvell.com>
---
 drivers/raw/cnxk_gpio/cnxk_gpio.c | 34 +++++++++++++++++++++++++++++++
 1 file changed, 34 insertions(+)

diff --git a/drivers/raw/cnxk_gpio/cnxk_gpio.c b/drivers/raw/cnxk_gpio/cnxk_gpio.c
index c1e74fad43..71f568f7a4 100644
--- a/drivers/raw/cnxk_gpio/cnxk_gpio.c
+++ b/drivers/raw/cnxk_gpio/cnxk_gpio.c
@@ -217,6 +217,29 @@ cnxk_gpio_queue_setup(struct rte_rawdev *dev, uint16_t queue_id,
 	return 0;
 }
 
+static int
+cnxk_gpio_queue_release(struct rte_rawdev *dev, uint16_t queue_id)
+{
+	struct cnxk_gpiochip *gpiochip = dev->dev_private;
+	char buf[CNXK_GPIO_BUFSZ];
+	struct cnxk_gpio *gpio;
+	int ret;
+
+	gpio = cnxk_gpio_lookup(gpiochip, queue_id);
+	if (!gpio)
+		return -ENODEV;
+
+	snprintf(buf, sizeof(buf), "%s/unexport", CNXK_GPIO_CLASS_PATH);
+	ret = cnxk_gpio_write_attr_int(buf, gpiochip->base + queue_id);
+	if (ret)
+		return ret;
+
+	gpiochip->gpios[queue_id] = NULL;
+	rte_free(gpio);
+
+	return 0;
+}
+
 static int
 cnxk_gpio_queue_def_conf(struct rte_rawdev *dev, uint16_t queue_id,
 			 rte_rawdev_obj_t queue_conf, size_t queue_conf_size)
@@ -247,6 +270,7 @@ static const struct rte_rawdev_ops cnxk_gpio_rawdev_ops = {
 	.queue_def_conf = cnxk_gpio_queue_def_conf,
 	.queue_count = cnxk_gpio_queue_count,
 	.queue_setup = cnxk_gpio_queue_setup,
+	.queue_release = cnxk_gpio_queue_release,
 };
 
 static int
@@ -320,6 +344,8 @@ cnxk_gpio_remove(struct rte_vdev_device *dev)
 	char name[RTE_RAWDEV_NAME_MAX_LEN];
 	struct cnxk_gpiochip *gpiochip;
 	struct rte_rawdev *rawdev;
+	struct cnxk_gpio *gpio;
+	int i;
 
 	RTE_SET_USED(dev);
 
@@ -332,6 +358,14 @@ cnxk_gpio_remove(struct rte_vdev_device *dev)
 		return -ENODEV;
 
 	gpiochip = rawdev->dev_private;
+	for (i = 0; i < gpiochip->num_gpios; i++) {
+		gpio = gpiochip->gpios[i];
+		if (!gpio)
+			continue;
+
+		cnxk_gpio_queue_release(rawdev, gpio->num);
+	}
+
 	rte_free(gpiochip->gpios);
 	rte_rawdev_pmd_release(rawdev);
 
-- 
2.25.1


^ permalink raw reply related

* [PATCH v4 06/11] raw/cnxk_gpio: support enqueuing buffers
From: Tomasz Duszynski @ 2022-01-05 14:00 UTC (permalink / raw)
  To: dev; +Cc: thomas, jerinj, Tomasz Duszynski
In-Reply-To: <20220105140020.1615256-1-tduszynski@marvell.com>

Add dummy support for enqueuing buffers.

Signed-off-by: Tomasz Duszynski <tduszynski@marvell.com>
---
 drivers/raw/cnxk_gpio/cnxk_gpio.c         | 47 +++++++++++++++++++++++
 drivers/raw/cnxk_gpio/cnxk_gpio.h         |  1 +
 drivers/raw/cnxk_gpio/meson.build         |  1 +
 drivers/raw/cnxk_gpio/rte_pmd_cnxk_gpio.h | 38 ++++++++++++++++++
 4 files changed, 87 insertions(+)
 create mode 100644 drivers/raw/cnxk_gpio/rte_pmd_cnxk_gpio.h

diff --git a/drivers/raw/cnxk_gpio/cnxk_gpio.c b/drivers/raw/cnxk_gpio/cnxk_gpio.c
index 71f568f7a4..235f0d6f7a 100644
--- a/drivers/raw/cnxk_gpio/cnxk_gpio.c
+++ b/drivers/raw/cnxk_gpio/cnxk_gpio.c
@@ -14,6 +14,7 @@
 #include <roc_api.h>
 
 #include "cnxk_gpio.h"
+#include "rte_pmd_cnxk_gpio.h"
 
 #define CNXK_GPIO_BUFSZ 128
 #define CNXK_GPIO_CLASS_PATH "/sys/class/gpio"
@@ -266,7 +267,53 @@ cnxk_gpio_queue_count(struct rte_rawdev *dev)
 	return gpiochip->num_gpios;
 }
 
+static int
+cnxk_gpio_process_buf(struct cnxk_gpio *gpio, struct rte_rawdev_buf *rbuf)
+{
+	struct cnxk_gpio_msg *msg = rbuf->buf_addr;
+	void *rsp = NULL;
+	int ret;
+
+	switch (msg->type) {
+	default:
+		return -EINVAL;
+	}
+
+	/* get rid of last response if any */
+	if (gpio->rsp) {
+		RTE_LOG(WARNING, PMD, "previous response got overwritten\n");
+		rte_free(gpio->rsp);
+	}
+	gpio->rsp = rsp;
+
+	return ret;
+}
+
+static int
+cnxk_gpio_enqueue_bufs(struct rte_rawdev *dev, struct rte_rawdev_buf **buffers,
+		       unsigned int count, rte_rawdev_obj_t context)
+{
+	struct cnxk_gpiochip *gpiochip = dev->dev_private;
+	unsigned int queue = (size_t)context;
+	struct cnxk_gpio *gpio;
+	int ret;
+
+	if (count == 0)
+		return 0;
+
+	gpio = cnxk_gpio_lookup(gpiochip, queue);
+	if (!gpio)
+		return -ENODEV;
+
+	ret = cnxk_gpio_process_buf(gpio, buffers[0]);
+	if (ret)
+		return ret;
+
+	return 1;
+}
+
 static const struct rte_rawdev_ops cnxk_gpio_rawdev_ops = {
+	.enqueue_bufs = cnxk_gpio_enqueue_bufs,
 	.queue_def_conf = cnxk_gpio_queue_def_conf,
 	.queue_count = cnxk_gpio_queue_count,
 	.queue_setup = cnxk_gpio_queue_setup,
diff --git a/drivers/raw/cnxk_gpio/cnxk_gpio.h b/drivers/raw/cnxk_gpio/cnxk_gpio.h
index 4dae8316ba..6b54ebe6e6 100644
--- a/drivers/raw/cnxk_gpio/cnxk_gpio.h
+++ b/drivers/raw/cnxk_gpio/cnxk_gpio.h
@@ -9,6 +9,7 @@ struct cnxk_gpiochip;
 
 struct cnxk_gpio {
 	struct cnxk_gpiochip *gpiochip;
+	void *rsp;
 	int num;
 };
 
diff --git a/drivers/raw/cnxk_gpio/meson.build b/drivers/raw/cnxk_gpio/meson.build
index 9a7e716c1e..3fbfdd838c 100644
--- a/drivers/raw/cnxk_gpio/meson.build
+++ b/drivers/raw/cnxk_gpio/meson.build
@@ -6,3 +6,4 @@ deps += ['bus_vdev', 'common_cnxk', 'rawdev', 'kvargs']
 sources = files(
         'cnxk_gpio.c',
 )
+headers = files('rte_pmd_cnxk_gpio.h')
diff --git a/drivers/raw/cnxk_gpio/rte_pmd_cnxk_gpio.h b/drivers/raw/cnxk_gpio/rte_pmd_cnxk_gpio.h
new file mode 100644
index 0000000000..c71065e10c
--- /dev/null
+++ b/drivers/raw/cnxk_gpio/rte_pmd_cnxk_gpio.h
@@ -0,0 +1,38 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(C) 2021 Marvell.
+ */
+
+#ifndef _RTE_PMD_CNXK_GPIO_H_
+#define _RTE_PMD_CNXK_GPIO_H_
+
+/**
+ * @file rte_pmd_cnxk_gpio.h
+ *
+ * Marvell GPIO PMD specific structures and interface
+ *
+ * This API allows applications to manage GPIOs in user space along with
+ * installing interrupt handlers for low latency signal processing.
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/** Available message types */
+enum cnxk_gpio_msg_type {
+	/** Invalid message type */
+	CNXK_GPIO_MSG_TYPE_INVALID,
+};
+
+struct cnxk_gpio_msg {
+	/** Message type */
+	enum cnxk_gpio_msg_type type;
+	/** Message data passed to PMD or received from PMD */
+	void *data;
+};
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _RTE_PMD_CNXK_GPIO_H_ */
-- 
2.25.1


^ permalink raw reply related

* [PATCH v4 07/11] raw/cnxk_gpio: support dequeuing buffers
From: Tomasz Duszynski @ 2022-01-05 14:00 UTC (permalink / raw)
  To: dev; +Cc: thomas, jerinj, Tomasz Duszynski
In-Reply-To: <20220105140020.1615256-1-tduszynski@marvell.com>

Add support for dequeuing buffers.

Signed-off-by: Tomasz Duszynski <tduszynski@marvell.com>
---
 drivers/raw/cnxk_gpio/cnxk_gpio.c | 26 ++++++++++++++++++++++++++
 1 file changed, 26 insertions(+)

diff --git a/drivers/raw/cnxk_gpio/cnxk_gpio.c b/drivers/raw/cnxk_gpio/cnxk_gpio.c
index 235f0d6f7a..909fa9d390 100644
--- a/drivers/raw/cnxk_gpio/cnxk_gpio.c
+++ b/drivers/raw/cnxk_gpio/cnxk_gpio.c
@@ -312,8 +312,34 @@ cnxk_gpio_enqueue_bufs(struct rte_rawdev *dev, struct rte_rawdev_buf **buffers,
 	return 1;
 }
 
+static int
+cnxk_gpio_dequeue_bufs(struct rte_rawdev *dev, struct rte_rawdev_buf **buffers,
+		       unsigned int count, rte_rawdev_obj_t context)
+{
+	struct cnxk_gpiochip *gpiochip = dev->dev_private;
+	unsigned int queue = (size_t)context;
+	struct cnxk_gpio *gpio;
+
+	if (count == 0)
+		return 0;
+
+	gpio = cnxk_gpio_lookup(gpiochip, queue);
+	if (!gpio)
+		return -ENODEV;
+
+	if (gpio->rsp) {
+		buffers[0]->buf_addr = gpio->rsp;
+		gpio->rsp = NULL;
+
+		return 1;
+	}
+
+	return 0;
+}
+
 static const struct rte_rawdev_ops cnxk_gpio_rawdev_ops = {
 	.enqueue_bufs = cnxk_gpio_enqueue_bufs,
+	.dequeue_bufs = cnxk_gpio_dequeue_bufs,
 	.queue_def_conf = cnxk_gpio_queue_def_conf,
 	.queue_count = cnxk_gpio_queue_count,
 	.queue_setup = cnxk_gpio_queue_setup,
-- 
2.25.1


^ permalink raw reply related

* [PATCH v4 08/11] raw/cnxk_gpio: support standard GPIO operations
From: Tomasz Duszynski @ 2022-01-05 14:00 UTC (permalink / raw)
  To: dev; +Cc: thomas, jerinj, Tomasz Duszynski
In-Reply-To: <20220105140020.1615256-1-tduszynski@marvell.com>

Add support for standard GPIO operations i.e ones normally
provided by GPIO sysfs interface.

Signed-off-by: Tomasz Duszynski <tduszynski@marvell.com>
---
 doc/guides/rawdevs/cnxk_gpio.rst          |  98 ++++++++
 drivers/raw/cnxk_gpio/cnxk_gpio.c         | 147 +++++++++++-
 drivers/raw/cnxk_gpio/rte_pmd_cnxk_gpio.h | 279 +++++++++++++++++++++-
 3 files changed, 521 insertions(+), 3 deletions(-)

diff --git a/doc/guides/rawdevs/cnxk_gpio.rst b/doc/guides/rawdevs/cnxk_gpio.rst
index 868302d07f..f6c3c942c5 100644
--- a/doc/guides/rawdevs/cnxk_gpio.rst
+++ b/doc/guides/rawdevs/cnxk_gpio.rst
@@ -63,3 +63,101 @@ call barely exports GPIO to userspace.
 To perform actual data transfer use standard ``rte_rawdev_enqueue_buffers()``
 and ``rte_rawdev_dequeue_buffers()`` APIs. Not all messages produce sensible
 responses hence dequeueing is not always necessary.
+
+CNXK GPIO PMD
+-------------
+
+PMD accepts ``struct cnxk_gpio_msg`` messages which differ by type and payload.
+Message types along with description are listed below. As for the usage examples
+please refer to ``cnxk_gpio_selftest()``. There's a set of convenient wrappers
+available, one for each existing command.
+
+Set GPIO value
+~~~~~~~~~~~~~~
+
+Message is used to set output to low or high. This does not work for GPIOs
+configured as input.
+
+Message must have type set to ``CNXK_GPIO_MSG_TYPE_SET_PIN_VALUE``.
+
+Payload must be an integer set to 0 (low) or 1 (high).
+
+Consider using ``rte_pmd_gpio_set_pin_value()`` wrapper.
+
+Set GPIO edge
+~~~~~~~~~~~~~
+
+Message is used to set edge that triggers interrupt.
+
+Message must have type set to ``CNXK_GPIO_MSG_TYPE_SET_PIN_EDGE``.
+
+Payload must be `enum cnxk_gpio_pin_edge`.
+
+Consider using ``rte_pmd_gpio_set_pin_edge()`` wrapper.
+
+Set GPIO direction
+~~~~~~~~~~~~~~~~~~
+
+Message is used to change GPIO direction to either input or output.
+
+Message must have type set to ``CNXK_GPIO_MSG_TYPE_SET_PIN_DIR``.
+
+Payload must be `enum cnxk_gpio_pin_dir`.
+
+Consider using ``rte_pmd_gpio_set_pin_dir()`` wrapper.
+
+Set GPIO active low
+~~~~~~~~~~~~~~~~~~~
+
+Message is used to set whether pin is active low.
+
+Message must have type set to ``CNXK_GPIO_MSG_TYPE_SET_PIN_ACTIVE_LOW``.
+
+Payload must be an integer set to 0 or 1. The latter activates inversion.
+
+Consider using ``rte_pmd_gpio_set_pin_active_low()`` wrapper.
+
+Get GPIO value
+~~~~~~~~~~~~~~
+
+Message is used to read GPIO value. Value can be 0 (low) or 1 (high).
+
+Message must have type set to ``CNXK_GPIO_MSG_TYPE_GET_PIN_VALUE``.
+
+Payload contains integer set to either 0 or 1.
+
+Consider using ``rte_pmd_gpio_get_pin_value()`` wrapper.
+
+Get GPIO edge
+~~~~~~~~~~~~~
+
+Message is used to read GPIO edge.
+
+Message must have type set to ``CNXK_GPIO_MSG_TYPE_GET_PIN_EDGE``.
+
+Payload contains `enum cnxk_gpio_pin_edge`.
+
+Consider using ``rte_pmd_gpio_get_pin_edge()`` wrapper.
+
+Get GPIO direction
+~~~~~~~~~~~~~~~~~~
+
+Message is used to read GPIO direction.
+
+Message must have type set to ``CNXK_GPIO_MSG_TYPE_GET_PIN_DIR``.
+
+Payload contains `enum cnxk_gpio_pin_dir`.
+
+Consider using ``rte_pmd_gpio_get_pin_dir()`` wrapper.
+
+Get GPIO active low
+~~~~~~~~~~~~~~~~~~~
+
+Message is used check whether inverted logic is active.
+
+Message must have type set to ``CNXK_GPIO_MSG_TYPE_GET_PIN_ACTIVE_LOW``.
+
+Payload contains an integer set to 0 or 1. The latter means inverted logic
+is turned on.
+
+Consider using ``rte_pmd_gpio_get_pin_active_low()`` wrapper.
diff --git a/drivers/raw/cnxk_gpio/cnxk_gpio.c b/drivers/raw/cnxk_gpio/cnxk_gpio.c
index 909fa9d390..e24d8c1b6e 100644
--- a/drivers/raw/cnxk_gpio/cnxk_gpio.c
+++ b/drivers/raw/cnxk_gpio/cnxk_gpio.c
@@ -267,14 +267,159 @@ cnxk_gpio_queue_count(struct rte_rawdev *dev)
 	return gpiochip->num_gpios;
 }
 
+static const struct {
+	enum cnxk_gpio_pin_edge edge;
+	const char *name;
+} cnxk_gpio_edge_name[] = {
+	{ CNXK_GPIO_PIN_EDGE_NONE, "none" },
+	{ CNXK_GPIO_PIN_EDGE_FALLING, "falling" },
+	{ CNXK_GPIO_PIN_EDGE_RISING, "rising" },
+	{ CNXK_GPIO_PIN_EDGE_BOTH, "both" },
+};
+
+static const char *
+cnxk_gpio_edge_to_name(enum cnxk_gpio_pin_edge edge)
+{
+	unsigned int i;
+
+	for (i = 0; i < RTE_DIM(cnxk_gpio_edge_name); i++) {
+		if (cnxk_gpio_edge_name[i].edge == edge)
+			return cnxk_gpio_edge_name[i].name;
+	}
+
+	return NULL;
+}
+
+static enum cnxk_gpio_pin_edge
+cnxk_gpio_name_to_edge(const char *name)
+{
+	unsigned int i;
+
+	for (i = 0; i < RTE_DIM(cnxk_gpio_edge_name); i++) {
+		if (!strcmp(cnxk_gpio_edge_name[i].name, name))
+			break;
+	}
+
+	return cnxk_gpio_edge_name[i].edge;
+}
+
+static const struct {
+	enum cnxk_gpio_pin_dir dir;
+	const char *name;
+} cnxk_gpio_dir_name[] = {
+	{ CNXK_GPIO_PIN_DIR_IN, "in" },
+	{ CNXK_GPIO_PIN_DIR_OUT, "out" },
+	{ CNXK_GPIO_PIN_DIR_HIGH, "high" },
+	{ CNXK_GPIO_PIN_DIR_LOW, "low" },
+};
+
+static const char *
+cnxk_gpio_dir_to_name(enum cnxk_gpio_pin_dir dir)
+{
+	unsigned int i;
+
+	for (i = 0; i < RTE_DIM(cnxk_gpio_dir_name); i++) {
+		if (cnxk_gpio_dir_name[i].dir == dir)
+			return cnxk_gpio_dir_name[i].name;
+	}
+
+	return NULL;
+}
+
+static enum cnxk_gpio_pin_dir
+cnxk_gpio_name_to_dir(const char *name)
+{
+	unsigned int i;
+
+	for (i = 0; i < RTE_DIM(cnxk_gpio_dir_name); i++) {
+		if (!strcmp(cnxk_gpio_dir_name[i].name, name))
+			break;
+	}
+
+	return cnxk_gpio_dir_name[i].dir;
+}
+
 static int
 cnxk_gpio_process_buf(struct cnxk_gpio *gpio, struct rte_rawdev_buf *rbuf)
 {
 	struct cnxk_gpio_msg *msg = rbuf->buf_addr;
+	enum cnxk_gpio_pin_edge edge;
+	enum cnxk_gpio_pin_dir dir;
+	char buf[CNXK_GPIO_BUFSZ];
 	void *rsp = NULL;
-	int ret;
+	int ret, val, n;
+
+	n = snprintf(buf, sizeof(buf), "%s/gpio%d", CNXK_GPIO_CLASS_PATH,
+		     gpio->num);
 
 	switch (msg->type) {
+	case CNXK_GPIO_MSG_TYPE_SET_PIN_VALUE:
+		snprintf(buf + n, sizeof(buf) - n, "/value");
+		ret = cnxk_gpio_write_attr_int(buf, !!*(int *)msg->data);
+		break;
+	case CNXK_GPIO_MSG_TYPE_SET_PIN_EDGE:
+		snprintf(buf + n, sizeof(buf) - n, "/edge");
+		edge = *(enum cnxk_gpio_pin_edge *)msg->data;
+		ret = cnxk_gpio_write_attr(buf, cnxk_gpio_edge_to_name(edge));
+		break;
+	case CNXK_GPIO_MSG_TYPE_SET_PIN_DIR:
+		snprintf(buf + n, sizeof(buf) - n, "/direction");
+		dir = *(enum cnxk_gpio_pin_dir *)msg->data;
+		ret = cnxk_gpio_write_attr(buf, cnxk_gpio_dir_to_name(dir));
+		break;
+	case CNXK_GPIO_MSG_TYPE_SET_PIN_ACTIVE_LOW:
+		snprintf(buf + n, sizeof(buf) - n, "/active_low");
+		val = *(int *)msg->data;
+		ret = cnxk_gpio_write_attr_int(buf, val);
+		break;
+	case CNXK_GPIO_MSG_TYPE_GET_PIN_VALUE:
+		snprintf(buf + n, sizeof(buf) - n, "/value");
+		ret = cnxk_gpio_read_attr_int(buf, &val);
+		if (ret)
+			break;
+
+		rsp = rte_zmalloc(NULL, sizeof(int), 0);
+		if (!rsp)
+			return -ENOMEM;
+
+		*(int *)rsp = val;
+		break;
+	case CNXK_GPIO_MSG_TYPE_GET_PIN_EDGE:
+		snprintf(buf + n, sizeof(buf) - n, "/edge");
+		ret = cnxk_gpio_read_attr(buf, buf);
+		if (ret)
+			break;
+
+		rsp = rte_zmalloc(NULL, sizeof(enum cnxk_gpio_pin_edge), 0);
+		if (!rsp)
+			return -ENOMEM;
+
+		*(enum cnxk_gpio_pin_edge *)rsp = cnxk_gpio_name_to_edge(buf);
+		break;
+	case CNXK_GPIO_MSG_TYPE_GET_PIN_DIR:
+		snprintf(buf + n, sizeof(buf) - n, "/direction");
+		ret = cnxk_gpio_read_attr(buf, buf);
+		if (ret)
+			break;
+
+		rsp = rte_zmalloc(NULL, sizeof(enum cnxk_gpio_pin_dir), 0);
+		if (!rsp)
+			return -ENOMEM;
+
+		*(enum cnxk_gpio_pin_dir *)rsp = cnxk_gpio_name_to_dir(buf);
+		break;
+	case CNXK_GPIO_MSG_TYPE_GET_PIN_ACTIVE_LOW:
+		snprintf(buf + n, sizeof(buf) - n, "/active_low");
+		ret = cnxk_gpio_read_attr_int(buf, &val);
+		if (ret)
+			break;
+
+		rsp = rte_zmalloc(NULL, sizeof(int), 0);
+		if (!rsp)
+			return -ENOMEM;
+
+		*(int *)rsp = val;
+		break;
 	default:
 		return -EINVAL;
 	}
diff --git a/drivers/raw/cnxk_gpio/rte_pmd_cnxk_gpio.h b/drivers/raw/cnxk_gpio/rte_pmd_cnxk_gpio.h
index c71065e10c..7c3dc225ca 100644
--- a/drivers/raw/cnxk_gpio/rte_pmd_cnxk_gpio.h
+++ b/drivers/raw/cnxk_gpio/rte_pmd_cnxk_gpio.h
@@ -5,6 +5,10 @@
 #ifndef _RTE_PMD_CNXK_GPIO_H_
 #define _RTE_PMD_CNXK_GPIO_H_
 
+#include <rte_malloc.h>
+#include <rte_memcpy.h>
+#include <rte_rawdev.h>
+
 /**
  * @file rte_pmd_cnxk_gpio.h
  *
@@ -20,8 +24,46 @@ extern "C" {
 
 /** Available message types */
 enum cnxk_gpio_msg_type {
-	/** Invalid message type */
-	CNXK_GPIO_MSG_TYPE_INVALID,
+	/** Type used to set output value */
+	CNXK_GPIO_MSG_TYPE_SET_PIN_VALUE,
+	/** Type used to set edge */
+	CNXK_GPIO_MSG_TYPE_SET_PIN_EDGE,
+	/** Type used to set direction */
+	CNXK_GPIO_MSG_TYPE_SET_PIN_DIR,
+	/** Type used to set inverted logic */
+	CNXK_GPIO_MSG_TYPE_SET_PIN_ACTIVE_LOW,
+	/** Type used to read value */
+	CNXK_GPIO_MSG_TYPE_GET_PIN_VALUE,
+	/** Type used to read edge */
+	CNXK_GPIO_MSG_TYPE_GET_PIN_EDGE,
+	/** Type used to read direction */
+	CNXK_GPIO_MSG_TYPE_GET_PIN_DIR,
+	/** Type used to read inverted logic state */
+	CNXK_GPIO_MSG_TYPE_GET_PIN_ACTIVE_LOW,
+};
+
+/** Available edges */
+enum cnxk_gpio_pin_edge {
+	/** Set edge to none */
+	CNXK_GPIO_PIN_EDGE_NONE,
+	/** Set edge to falling */
+	CNXK_GPIO_PIN_EDGE_FALLING,
+	/** Set edge to rising */
+	CNXK_GPIO_PIN_EDGE_RISING,
+	/** Set edge to both rising and falling */
+	CNXK_GPIO_PIN_EDGE_BOTH,
+};
+
+/** Available directions */
+enum cnxk_gpio_pin_dir {
+	/** Set direction to input */
+	CNXK_GPIO_PIN_DIR_IN,
+	/** Set direction to output */
+	CNXK_GPIO_PIN_DIR_OUT,
+	/** Set direction to output and value to 1 */
+	CNXK_GPIO_PIN_DIR_HIGH,
+	/* Set direction to output and value to 0 */
+	CNXK_GPIO_PIN_DIR_LOW,
 };
 
 struct cnxk_gpio_msg {
@@ -31,6 +73,239 @@ struct cnxk_gpio_msg {
 	void *data;
 };
 
+/** @internal helper routine for enqueuing/dequeuing messages */
+static __rte_always_inline int
+__rte_pmd_gpio_enq_deq(uint16_t dev_id, int gpio, void *req, void *rsp,
+		       size_t rsp_size)
+{
+	struct rte_rawdev_buf *bufs[1];
+	struct rte_rawdev_buf buf;
+	void *q;
+	int ret;
+
+	q = (void *)(size_t)gpio;
+	buf.buf_addr = req;
+	bufs[0] = &buf;
+
+	ret = rte_rawdev_enqueue_buffers(dev_id, bufs, RTE_DIM(bufs), q);
+	if (ret < 0)
+		return ret;
+	if (ret != RTE_DIM(bufs))
+		return -EIO;
+
+	if (!rsp)
+		return 0;
+
+	ret = rte_rawdev_dequeue_buffers(dev_id, bufs, RTE_DIM(bufs), q);
+	if (ret < 0)
+		return ret;
+	if (ret != RTE_DIM(bufs))
+		return -EIO;
+
+	rte_memcpy(rsp, buf.buf_addr, rsp_size);
+	rte_free(buf.buf_addr);
+
+	return 0;
+}
+
+/**
+ * Set output to specific value
+ *
+ * @param dev_id
+ *   The identifier of the device
+ * @param gpio
+ *   Zero-based GPIO number
+ * @param val
+ *   Value output will be set to. 0 represents low state while
+ *   1 high state
+ *
+ * @return
+ *   Returns 0 on success, negative error code otherwise
+ */
+static __rte_always_inline int
+rte_pmd_gpio_set_pin_value(uint16_t dev_id, int gpio, int val)
+{
+	struct cnxk_gpio_msg msg = {
+		.type = CNXK_GPIO_MSG_TYPE_SET_PIN_VALUE,
+		.data = &val,
+	};
+
+	return __rte_pmd_gpio_enq_deq(dev_id, gpio, &msg, NULL, 0);
+}
+
+/**
+ * Select signal edge that triggers interrupt
+ *
+ * @param dev_id
+ *   The identifier of the device
+ * @param gpio
+ *   Zero-based GPIO number
+ * @param edge
+ *   Signal edge that triggers interrupt
+ *
+ * @return
+ *   Returns 0 on success, negative error code otherwise
+ */
+static __rte_always_inline int
+rte_pmd_gpio_set_pin_edge(uint16_t dev_id, int gpio,
+			  enum cnxk_gpio_pin_edge edge)
+{
+	struct cnxk_gpio_msg msg = {
+		.type = CNXK_GPIO_MSG_TYPE_SET_PIN_EDGE,
+		.data = &edge
+	};
+
+	return __rte_pmd_gpio_enq_deq(dev_id, gpio, &msg, NULL, 0);
+}
+
+/**
+ * Configure GPIO as input or output
+ *
+ * @param dev_id
+ *   The identifier of the device
+ * @param gpio
+ *   Zero-based GPIO number
+ * @param dir
+ *   Direction of the GPIO
+ *
+ * @return
+ *   Returns 0 on success, negative error code otherwise
+ */
+static __rte_always_inline int
+rte_pmd_gpio_set_pin_dir(uint16_t dev_id, int gpio, enum cnxk_gpio_pin_dir dir)
+{
+	struct cnxk_gpio_msg msg = {
+		.type = CNXK_GPIO_MSG_TYPE_SET_PIN_DIR,
+		.data = &dir,
+	};
+
+	return __rte_pmd_gpio_enq_deq(dev_id, gpio, &msg, NULL, 0);
+}
+
+/**
+ * Enable or disable inverted logic
+ *
+ * If GPIO is configured as output then writing 1 or 0 will result in setting
+ * output to respectively low or high
+ *
+ * If GPIO is configured as input then logic inversion applies to edges. Both
+ * current and future settings are affected
+ *
+ * @param dev_id
+ *   The identifier of the device
+ * @param gpio
+ *   Zero-based GPIO number
+ * @param val
+ *   0 to disable, 1 to enable inverted logic
+ *
+ * @return
+ *   Returns 0 on success, negative error code otherwise
+ */
+static __rte_always_inline int
+rte_pmd_gpio_set_pin_active_low(uint16_t dev_id, int gpio, int val)
+{
+	struct cnxk_gpio_msg msg = {
+		.type = CNXK_GPIO_MSG_TYPE_SET_PIN_ACTIVE_LOW,
+		.data = &val,
+	};
+
+	return __rte_pmd_gpio_enq_deq(dev_id, gpio, &msg, NULL, 0);
+}
+
+/**
+ * Read GPIO value
+ *
+ * @param dev_id
+ *   The identifier of the device
+ * @param gpio
+ *   Zero-based GPIO number
+ * @param val
+ *   Where to store read logical signal value i.e 0 or 1
+ *
+ * @return
+ *   Returns 0 on success, negative error code otherwise
+ */
+static __rte_always_inline int
+rte_pmd_gpio_get_pin_value(uint16_t dev_id, int gpio, int *val)
+{
+	struct cnxk_gpio_msg msg = {
+		.type = CNXK_GPIO_MSG_TYPE_GET_PIN_VALUE,
+	};
+
+	return __rte_pmd_gpio_enq_deq(dev_id, gpio, &msg, val, sizeof(*val));
+}
+
+/**
+ * Read GPIO edge
+ *
+ * @param dev_id
+ *   The identifier of the device
+ * @param gpio
+ *   Zero-based GPIO number
+ * @param edge
+ *   Where to store edge
+ *
+ * @return
+ *   Returns 0 on success, negative error code otherwise
+ */
+static __rte_always_inline int
+rte_pmd_gpio_get_pin_edge(uint16_t dev_id, int gpio,
+			  enum cnxk_gpio_pin_edge *edge)
+{
+	struct cnxk_gpio_msg msg = {
+		.type = CNXK_GPIO_MSG_TYPE_GET_PIN_EDGE,
+	};
+
+	return __rte_pmd_gpio_enq_deq(dev_id, gpio, &msg, edge, sizeof(*edge));
+}
+
+/**
+ * Read GPIO direction
+ *
+ * @param dev_id
+ *   The identifier of the device
+ * @param gpio
+ *   Zero-based GPIO number
+ * @param dir
+ *   Where to store direction
+ *
+ * @return
+ *   Returns 0 on success, negative error code otherwise
+ */
+static __rte_always_inline int
+rte_pmd_gpio_get_pin_dir(uint16_t dev_id, int gpio, enum cnxk_gpio_pin_dir *dir)
+{
+	struct cnxk_gpio_msg msg = {
+		.type = CNXK_GPIO_MSG_TYPE_GET_PIN_DIR,
+	};
+
+	return __rte_pmd_gpio_enq_deq(dev_id, gpio, &msg, dir, sizeof(*dir));
+}
+
+/**
+ * Read whether GPIO is active low
+ *
+ * @param dev_id
+ *   The identifier of the device
+ * @param gpio
+ *   Zero-based GPIO number
+ * @param val
+ *   Where to store active low state
+ *
+ * @return
+ *   Returns 0 on success, negative error code otherwise
+ */
+static __rte_always_inline int
+rte_pmd_gpio_get_pin_active_low(uint16_t dev_id, int gpio, int *val)
+{
+	struct cnxk_gpio_msg msg = {
+		.type = CNXK_GPIO_MSG_TYPE_GET_PIN_ACTIVE_LOW,
+		.data = &val,
+	};
+
+	return __rte_pmd_gpio_enq_deq(dev_id, gpio, &msg, val, sizeof(*val));
+}
+
 #ifdef __cplusplus
 }
 #endif
-- 
2.25.1


^ permalink raw reply related

* [PATCH v4 09/11] raw/cnxk_gpio: support custom irq handlers
From: Tomasz Duszynski @ 2022-01-05 14:00 UTC (permalink / raw)
  To: dev; +Cc: thomas, jerinj, Tomasz Duszynski
In-Reply-To: <20220105140020.1615256-1-tduszynski@marvell.com>

Add support for custom interrupt handlers. Custom interrupt
handlers bypass kernel completely and are meant for fast
and low latency access to GPIO state.

Signed-off-by: Tomasz Duszynski <tduszynski@marvell.com>
---
 doc/guides/rawdevs/cnxk_gpio.rst          |  21 +++
 drivers/raw/cnxk_gpio/cnxk_gpio.c         |  37 ++++
 drivers/raw/cnxk_gpio/cnxk_gpio.h         |   8 +
 drivers/raw/cnxk_gpio/cnxk_gpio_irq.c     | 216 ++++++++++++++++++++++
 drivers/raw/cnxk_gpio/meson.build         |   1 +
 drivers/raw/cnxk_gpio/rte_pmd_cnxk_gpio.h | 116 ++++++++++++
 6 files changed, 399 insertions(+)
 create mode 100644 drivers/raw/cnxk_gpio/cnxk_gpio_irq.c

diff --git a/doc/guides/rawdevs/cnxk_gpio.rst b/doc/guides/rawdevs/cnxk_gpio.rst
index f6c3c942c5..ad93ec0d44 100644
--- a/doc/guides/rawdevs/cnxk_gpio.rst
+++ b/doc/guides/rawdevs/cnxk_gpio.rst
@@ -161,3 +161,24 @@ Payload contains an integer set to 0 or 1. The latter means inverted logic
 is turned on.
 
 Consider using ``rte_pmd_gpio_get_pin_active_low()`` wrapper.
+
+Request interrupt
+~~~~~~~~~~~~~~~~~
+
+Message is used to install custom interrupt handler.
+
+Message must have type set to ``CNXK_GPIO_MSG_TYPE_REGISTER_IRQ``.
+
+Payload needs to be set to ``struct cnxk_gpio_irq`` which describes interrupt
+being requested.
+
+Consider using ``rte_pmd_gpio_register_gpio()`` wrapper.
+
+Free interrupt
+~~~~~~~~~~~~~~
+
+Message is used to remove installed interrupt handler.
+
+Message must have type set to ``CNXK_GPIO_MSG_TYPE_UNREGISTER_IRQ``.
+
+Consider using ``rte_pmd_gpio_unregister_gpio()`` wrapper.
diff --git a/drivers/raw/cnxk_gpio/cnxk_gpio.c b/drivers/raw/cnxk_gpio/cnxk_gpio.c
index e24d8c1b6e..b30427c01c 100644
--- a/drivers/raw/cnxk_gpio/cnxk_gpio.c
+++ b/drivers/raw/cnxk_gpio/cnxk_gpio.c
@@ -339,6 +339,28 @@ cnxk_gpio_name_to_dir(const char *name)
 	return cnxk_gpio_dir_name[i].dir;
 }
 
+static int
+cnxk_gpio_register_irq(struct cnxk_gpio *gpio, struct cnxk_gpio_irq *irq)
+{
+	int ret;
+
+	ret = cnxk_gpio_irq_request(gpio->num - gpio->gpiochip->base, irq->cpu);
+	if (ret)
+		return ret;
+
+	gpio->handler = irq->handler;
+	gpio->data = irq->data;
+	gpio->cpu = irq->cpu;
+
+	return 0;
+}
+
+static int
+cnxk_gpio_unregister_irq(struct cnxk_gpio *gpio)
+{
+	return cnxk_gpio_irq_free(gpio->num - gpio->gpiochip->base);
+}
+
 static int
 cnxk_gpio_process_buf(struct cnxk_gpio *gpio, struct rte_rawdev_buf *rbuf)
 {
@@ -420,6 +442,13 @@ cnxk_gpio_process_buf(struct cnxk_gpio *gpio, struct rte_rawdev_buf *rbuf)
 
 		*(int *)rsp = val;
 		break;
+	case CNXK_GPIO_MSG_TYPE_REGISTER_IRQ:
+		ret = cnxk_gpio_register_irq(gpio,
+					     (struct cnxk_gpio_irq *)msg->data);
+		break;
+	case CNXK_GPIO_MSG_TYPE_UNREGISTER_IRQ:
+		ret = cnxk_gpio_unregister_irq(gpio);
+		break;
 	default:
 		return -EINVAL;
 	}
@@ -523,6 +552,10 @@ cnxk_gpio_probe(struct rte_vdev_device *dev)
 	if (ret)
 		goto out;
 
+	ret = cnxk_gpio_irq_init(gpiochip);
+	if (ret)
+		goto out;
+
 	/* read gpio base */
 	snprintf(buf, sizeof(buf), "%s/gpiochip%d/base", CNXK_GPIO_CLASS_PATH,
 		 gpiochip->num);
@@ -581,10 +614,14 @@ cnxk_gpio_remove(struct rte_vdev_device *dev)
 		if (!gpio)
 			continue;
 
+		if (gpio->handler)
+			cnxk_gpio_unregister_irq(gpio);
+
 		cnxk_gpio_queue_release(rawdev, gpio->num);
 	}
 
 	rte_free(gpiochip->gpios);
+	cnxk_gpio_irq_fini();
 	rte_rawdev_pmd_release(rawdev);
 
 	return 0;
diff --git a/drivers/raw/cnxk_gpio/cnxk_gpio.h b/drivers/raw/cnxk_gpio/cnxk_gpio.h
index 6b54ebe6e6..c052ca5735 100644
--- a/drivers/raw/cnxk_gpio/cnxk_gpio.h
+++ b/drivers/raw/cnxk_gpio/cnxk_gpio.h
@@ -11,6 +11,9 @@ struct cnxk_gpio {
 	struct cnxk_gpiochip *gpiochip;
 	void *rsp;
 	int num;
+	void (*handler)(int gpio, void *data);
+	void *data;
+	int cpu;
 };
 
 struct cnxk_gpiochip {
@@ -20,4 +23,9 @@ struct cnxk_gpiochip {
 	struct cnxk_gpio **gpios;
 };
 
+int cnxk_gpio_irq_init(struct cnxk_gpiochip *gpiochip);
+void cnxk_gpio_irq_fini(void);
+int cnxk_gpio_irq_request(int gpio, int cpu);
+int cnxk_gpio_irq_free(int gpio);
+
 #endif /* _CNXK_GPIO_H_ */
diff --git a/drivers/raw/cnxk_gpio/cnxk_gpio_irq.c b/drivers/raw/cnxk_gpio/cnxk_gpio_irq.c
new file mode 100644
index 0000000000..2fa8e69899
--- /dev/null
+++ b/drivers/raw/cnxk_gpio/cnxk_gpio_irq.c
@@ -0,0 +1,216 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(C) 2021 Marvell.
+ */
+
+#include <fcntl.h>
+#include <pthread.h>
+#include <sys/ioctl.h>
+#include <sys/mman.h>
+#include <sys/queue.h>
+#include <unistd.h>
+
+#include <rte_rawdev_pmd.h>
+
+#include <roc_api.h>
+
+#include "cnxk_gpio.h"
+
+#define OTX_IOC_MAGIC 0xF2
+#define OTX_IOC_SET_GPIO_HANDLER                                               \
+	_IOW(OTX_IOC_MAGIC, 1, struct otx_gpio_usr_data)
+#define OTX_IOC_CLR_GPIO_HANDLER                                               \
+	_IO(OTX_IOC_MAGIC, 2)
+
+struct otx_gpio_usr_data {
+	uint64_t isr_base;
+	uint64_t sp;
+	uint64_t cpu;
+	uint64_t gpio_num;
+};
+
+struct cnxk_gpio_irq_stack {
+	LIST_ENTRY(cnxk_gpio_irq_stack) next;
+	void *sp_buffer;
+	int cpu;
+	int inuse;
+};
+
+struct cnxk_gpio_irqchip {
+	int fd;
+	/* serialize access to this struct */
+	pthread_mutex_t lock;
+	LIST_HEAD(, cnxk_gpio_irq_stack) stacks;
+
+	struct cnxk_gpiochip *gpiochip;
+};
+
+static struct cnxk_gpio_irqchip *irqchip;
+
+static void
+cnxk_gpio_irq_stack_free(int cpu)
+{
+	struct cnxk_gpio_irq_stack *stack;
+
+	LIST_FOREACH(stack, &irqchip->stacks, next) {
+		if (stack->cpu == cpu)
+			break;
+	}
+
+	if (!stack)
+		return;
+
+	if (stack->inuse)
+		stack->inuse--;
+
+	if (stack->inuse == 0) {
+		LIST_REMOVE(stack, next);
+		rte_free(stack->sp_buffer);
+		rte_free(stack);
+	}
+}
+
+static void *
+cnxk_gpio_irq_stack_alloc(int cpu)
+{
+#define ARM_STACK_ALIGNMENT (2 * sizeof(void *))
+#define IRQ_STACK_SIZE 0x200000
+
+	struct cnxk_gpio_irq_stack *stack;
+
+	LIST_FOREACH(stack, &irqchip->stacks, next) {
+		if (stack->cpu == cpu)
+			break;
+	}
+
+	if (stack) {
+		stack->inuse++;
+		return (char *)stack->sp_buffer + IRQ_STACK_SIZE;
+	}
+
+	stack = rte_malloc(NULL, sizeof(*stack), 0);
+	if (!stack)
+		return NULL;
+
+	stack->sp_buffer =
+		rte_zmalloc(NULL, IRQ_STACK_SIZE * 2, ARM_STACK_ALIGNMENT);
+	if (!stack->sp_buffer) {
+		rte_free(stack);
+		return NULL;
+	}
+
+	stack->cpu = cpu;
+	stack->inuse = 1;
+	LIST_INSERT_HEAD(&irqchip->stacks, stack, next);
+
+	return (char *)stack->sp_buffer + IRQ_STACK_SIZE;
+}
+
+static void
+cnxk_gpio_irq_handler(int gpio_num)
+{
+	struct cnxk_gpiochip *gpiochip = irqchip->gpiochip;
+	struct cnxk_gpio *gpio;
+
+	if (gpio_num >= gpiochip->num_gpios)
+		goto out;
+
+	gpio = gpiochip->gpios[gpio_num];
+	if (likely(gpio->handler))
+		gpio->handler(gpio_num, gpio->data);
+
+out:
+	roc_atf_ret();
+}
+
+int
+cnxk_gpio_irq_init(struct cnxk_gpiochip *gpiochip)
+{
+	if (irqchip)
+		return 0;
+
+	irqchip = rte_zmalloc(NULL, sizeof(*irqchip), 0);
+	if (!irqchip)
+		return -ENOMEM;
+
+	irqchip->fd = open("/dev/otx-gpio-ctr", O_RDWR | O_SYNC);
+	if (irqchip->fd < 0) {
+		rte_free(irqchip);
+		return -errno;
+	}
+
+	pthread_mutex_init(&irqchip->lock, NULL);
+	LIST_INIT(&irqchip->stacks);
+	irqchip->gpiochip = gpiochip;
+
+	return 0;
+}
+
+void
+cnxk_gpio_irq_fini(void)
+{
+	if (!irqchip)
+		return;
+
+	close(irqchip->fd);
+	rte_free(irqchip);
+	irqchip = NULL;
+}
+
+int
+cnxk_gpio_irq_request(int gpio, int cpu)
+{
+	struct otx_gpio_usr_data data;
+	void *sp;
+	int ret;
+
+	pthread_mutex_lock(&irqchip->lock);
+
+	sp = cnxk_gpio_irq_stack_alloc(cpu);
+	if (!sp) {
+		ret = -ENOMEM;
+		goto out_unlock;
+	}
+
+	data.isr_base = (uint64_t)cnxk_gpio_irq_handler;
+	data.sp = (uint64_t)sp;
+	data.cpu = (uint64_t)cpu;
+	data.gpio_num = (uint64_t)gpio;
+
+	mlockall(MCL_CURRENT | MCL_FUTURE);
+	ret = ioctl(irqchip->fd, OTX_IOC_SET_GPIO_HANDLER, &data);
+	if (ret) {
+		ret = -errno;
+		goto out_free_stack;
+	}
+
+	pthread_mutex_unlock(&irqchip->lock);
+
+	return 0;
+
+out_free_stack:
+	cnxk_gpio_irq_stack_free(cpu);
+out_unlock:
+	pthread_mutex_unlock(&irqchip->lock);
+
+	return ret;
+}
+
+int
+cnxk_gpio_irq_free(int gpio)
+{
+	int ret;
+
+	pthread_mutex_lock(&irqchip->lock);
+
+	ret = ioctl(irqchip->fd, OTX_IOC_CLR_GPIO_HANDLER, gpio);
+	if (ret) {
+		pthread_mutex_unlock(&irqchip->lock);
+		return -errno;
+	}
+
+	cnxk_gpio_irq_stack_free(irqchip->gpiochip->gpios[gpio]->cpu);
+
+	pthread_mutex_unlock(&irqchip->lock);
+
+	return 0;
+}
diff --git a/drivers/raw/cnxk_gpio/meson.build b/drivers/raw/cnxk_gpio/meson.build
index 3fbfdd838c..9b55f029c7 100644
--- a/drivers/raw/cnxk_gpio/meson.build
+++ b/drivers/raw/cnxk_gpio/meson.build
@@ -5,5 +5,6 @@
 deps += ['bus_vdev', 'common_cnxk', 'rawdev', 'kvargs']
 sources = files(
         'cnxk_gpio.c',
+        'cnxk_gpio_irq.c',
 )
 headers = files('rte_pmd_cnxk_gpio.h')
diff --git a/drivers/raw/cnxk_gpio/rte_pmd_cnxk_gpio.h b/drivers/raw/cnxk_gpio/rte_pmd_cnxk_gpio.h
index 7c3dc225ca..e3096dc14f 100644
--- a/drivers/raw/cnxk_gpio/rte_pmd_cnxk_gpio.h
+++ b/drivers/raw/cnxk_gpio/rte_pmd_cnxk_gpio.h
@@ -40,6 +40,10 @@ enum cnxk_gpio_msg_type {
 	CNXK_GPIO_MSG_TYPE_GET_PIN_DIR,
 	/** Type used to read inverted logic state */
 	CNXK_GPIO_MSG_TYPE_GET_PIN_ACTIVE_LOW,
+	/** Type used to register interrupt handler */
+	CNXK_GPIO_MSG_TYPE_REGISTER_IRQ,
+	/** Type used to remove interrupt handler */
+	CNXK_GPIO_MSG_TYPE_UNREGISTER_IRQ,
 };
 
 /** Available edges */
@@ -66,6 +70,25 @@ enum cnxk_gpio_pin_dir {
 	CNXK_GPIO_PIN_DIR_LOW,
 };
 
+/**
+ * GPIO interrupt handler
+ *
+ * @param gpio
+ *   Zero-based GPIO number
+ * @param data
+ *   Cookie passed to interrupt handler
+ */
+typedef void (*cnxk_gpio_irq_handler_t)(int gpio, void *data);
+
+struct cnxk_gpio_irq {
+	/** Interrupt handler */
+	cnxk_gpio_irq_handler_t handler;
+	/** User data passed to irq handler */
+	void *data;
+	/** CPU which will run irq handler */
+	int cpu;
+};
+
 struct cnxk_gpio_msg {
 	/** Message type */
 	enum cnxk_gpio_msg_type type;
@@ -306,6 +329,99 @@ rte_pmd_gpio_get_pin_active_low(uint16_t dev_id, int gpio, int *val)
 	return __rte_pmd_gpio_enq_deq(dev_id, gpio, &msg, val, sizeof(*val));
 }
 
+/**
+ * Attach interrupt handler to GPIO
+ *
+ * @param dev_id
+ *   The identifier of the device
+ * @param gpio
+ *   Zero-based GPIO number
+ * @param cpu
+ *   CPU which will be handling interrupt
+ * @param handler
+ *   Interrupt handler to be executed
+ * @param data
+ *   Data to be passed to interrupt handler
+ *
+ * @return
+ *   Returns 0 on success, negative error code otherwise
+ */
+static __rte_always_inline int
+rte_pmd_gpio_register_irq(uint16_t dev_id, int gpio, int cpu,
+			  cnxk_gpio_irq_handler_t handler, void *data)
+{
+	struct cnxk_gpio_irq irq = {
+		.handler = handler,
+		.data = data,
+		.cpu = cpu,
+	};
+	struct cnxk_gpio_msg msg = {
+		.type = CNXK_GPIO_MSG_TYPE_REGISTER_IRQ,
+		.data = &irq,
+	};
+
+	return __rte_pmd_gpio_enq_deq(dev_id, gpio, &msg, NULL, 0);
+}
+
+/**
+ * Detach interrupt handler from GPIO
+ *
+ * @param dev_id
+ *   The identifier of the device
+ * @param gpio
+ *   Zero-based GPIO number
+ *
+ * @return
+ *   Returns 0 on success, negative error code otherwise
+ */
+static __rte_always_inline int
+rte_pmd_gpio_unregister_irq(uint16_t dev_id, int gpio)
+{
+	struct cnxk_gpio_msg msg = {
+		.type = CNXK_GPIO_MSG_TYPE_UNREGISTER_IRQ,
+		.data = &gpio,
+	};
+
+	return __rte_pmd_gpio_enq_deq(dev_id, gpio, &msg, NULL, 0);
+}
+
+/**
+ * Enable interrupt
+ *
+ * @param dev_id
+ *   The identifier of the device
+ * @param gpio
+ *   Zero-based GPIO number
+ * @param edge
+ *   Edge that should trigger interrupt
+ *
+ * @return
+ *   Returns 0 on success, negative error code otherwise
+ */
+static __rte_always_inline int
+rte_pmd_gpio_enable_interrupt(uint16_t dev_id, int gpio,
+			      enum cnxk_gpio_pin_edge edge)
+{
+	return rte_pmd_gpio_set_pin_edge(dev_id, gpio, edge);
+}
+
+/**
+ * Disable interrupt
+ *
+ * @param dev_id
+ *   The identifier of the device
+ * @param gpio
+ *   Zero-based GPIO number
+ *
+ * @return
+ *   Returns 0 on success, negative error code otherwise
+ */
+static __rte_always_inline int
+rte_pmd_gpio_disable_interrupt(uint16_t dev_id, int gpio)
+{
+	return rte_pmd_gpio_set_pin_edge(dev_id, gpio, CNXK_GPIO_PIN_EDGE_NONE);
+}
+
 #ifdef __cplusplus
 }
 #endif
-- 
2.25.1


^ permalink raw reply related

* [PATCH v4 10/11] raw/cnxk_gpio: support selftest
From: Tomasz Duszynski @ 2022-01-05 14:00 UTC (permalink / raw)
  To: dev; +Cc: thomas, jerinj, Tomasz Duszynski
In-Reply-To: <20220105140020.1615256-1-tduszynski@marvell.com>

Add support for performing selftest.

Signed-off-by: Tomasz Duszynski <tduszynski@marvell.com>
---
 doc/guides/rawdevs/cnxk_gpio.rst           |  11 +
 drivers/raw/cnxk_gpio/cnxk_gpio.c          |   1 +
 drivers/raw/cnxk_gpio/cnxk_gpio.h          |   2 +
 drivers/raw/cnxk_gpio/cnxk_gpio_selftest.c | 386 +++++++++++++++++++++
 drivers/raw/cnxk_gpio/meson.build          |   1 +
 5 files changed, 401 insertions(+)
 create mode 100644 drivers/raw/cnxk_gpio/cnxk_gpio_selftest.c

diff --git a/doc/guides/rawdevs/cnxk_gpio.rst b/doc/guides/rawdevs/cnxk_gpio.rst
index ad93ec0d44..c03a5b937c 100644
--- a/doc/guides/rawdevs/cnxk_gpio.rst
+++ b/doc/guides/rawdevs/cnxk_gpio.rst
@@ -182,3 +182,14 @@ Message is used to remove installed interrupt handler.
 Message must have type set to ``CNXK_GPIO_MSG_TYPE_UNREGISTER_IRQ``.
 
 Consider using ``rte_pmd_gpio_unregister_gpio()`` wrapper.
+
+Self test
+---------
+
+On EAL initialization CNXK GPIO device will be probed and populated into
+the list of raw devices on condition ``--vdev=cnxk_gpio,gpiochip=<number>`` was
+passed. ``rte_rawdev_get_dev_id("CNXK_GPIO")`` returns unique device id. Use
+this identifier for further rawdev function calls.
+
+Selftest rawdev API can be used to verify the PMD functionality. Note it blindly
+assumes that all GPIOs are controllable so some errors during test are expected.
diff --git a/drivers/raw/cnxk_gpio/cnxk_gpio.c b/drivers/raw/cnxk_gpio/cnxk_gpio.c
index b30427c01c..16a886b693 100644
--- a/drivers/raw/cnxk_gpio/cnxk_gpio.c
+++ b/drivers/raw/cnxk_gpio/cnxk_gpio.c
@@ -518,6 +518,7 @@ static const struct rte_rawdev_ops cnxk_gpio_rawdev_ops = {
 	.queue_count = cnxk_gpio_queue_count,
 	.queue_setup = cnxk_gpio_queue_setup,
 	.queue_release = cnxk_gpio_queue_release,
+	.dev_selftest = cnxk_gpio_selftest,
 };
 
 static int
diff --git a/drivers/raw/cnxk_gpio/cnxk_gpio.h b/drivers/raw/cnxk_gpio/cnxk_gpio.h
index c052ca5735..1b31b5a486 100644
--- a/drivers/raw/cnxk_gpio/cnxk_gpio.h
+++ b/drivers/raw/cnxk_gpio/cnxk_gpio.h
@@ -23,6 +23,8 @@ struct cnxk_gpiochip {
 	struct cnxk_gpio **gpios;
 };
 
+int cnxk_gpio_selftest(uint16_t dev_id);
+
 int cnxk_gpio_irq_init(struct cnxk_gpiochip *gpiochip);
 void cnxk_gpio_irq_fini(void);
 int cnxk_gpio_irq_request(int gpio, int cpu);
diff --git a/drivers/raw/cnxk_gpio/cnxk_gpio_selftest.c b/drivers/raw/cnxk_gpio/cnxk_gpio_selftest.c
new file mode 100644
index 0000000000..6502902f86
--- /dev/null
+++ b/drivers/raw/cnxk_gpio/cnxk_gpio_selftest.c
@@ -0,0 +1,386 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(C) 2021 Marvell.
+ */
+
+#include <fcntl.h>
+#include <sys/ioctl.h>
+#include <sys/stat.h>
+#include <unistd.h>
+
+#include <rte_cycles.h>
+#include <rte_rawdev.h>
+#include <rte_rawdev_pmd.h>
+#include <rte_service.h>
+
+#include "cnxk_gpio.h"
+#include "rte_pmd_cnxk_gpio.h"
+
+#define CNXK_GPIO_BUFSZ 128
+
+#define OTX_IOC_MAGIC 0xF2
+#define OTX_IOC_TRIGGER_GPIO_HANDLER                                           \
+	_IO(OTX_IOC_MAGIC, 3)
+
+static int fd;
+
+static int
+cnxk_gpio_attr_exists(const char *attr)
+{
+	struct stat st;
+
+	return !stat(attr, &st);
+}
+
+static int
+cnxk_gpio_read_attr(char *attr, char *val)
+{
+	FILE *fp;
+	int ret;
+
+	fp = fopen(attr, "r");
+	if (!fp)
+		return -errno;
+
+	ret = fscanf(fp, "%s", val);
+	if (ret < 0)
+		return -errno;
+	if (ret != 1)
+		return -EIO;
+
+	ret = fclose(fp);
+	if (ret)
+		return -errno;
+
+	return 0;
+}
+
+#define CNXK_GPIO_ERR_STR(err, str, ...) do {                                  \
+	if (err) {                                                             \
+		RTE_LOG(ERR, PMD, "%s:%d: " str " (%d)\n", __func__, __LINE__, \
+			##__VA_ARGS__, err);                                   \
+		goto out;                                                      \
+	}                                                                      \
+} while (0)
+
+static int
+cnxk_gpio_validate_attr(char *attr, const char *expected)
+{
+	char buf[CNXK_GPIO_BUFSZ];
+	int ret;
+
+	ret = cnxk_gpio_read_attr(attr, buf);
+	if (ret)
+		return ret;
+
+	if (strncmp(buf, expected, sizeof(buf)))
+		return -EIO;
+
+	return 0;
+}
+
+#define CNXK_GPIO_PATH_FMT "/sys/class/gpio/gpio%d"
+
+static int
+cnxk_gpio_test_input(uint16_t dev_id, int base, int gpio)
+{
+	char buf[CNXK_GPIO_BUFSZ];
+	int ret, n;
+
+	n = snprintf(buf, sizeof(buf), CNXK_GPIO_PATH_FMT, base + gpio);
+	snprintf(buf + n, sizeof(buf) - n, "/direction");
+
+	ret = rte_pmd_gpio_set_pin_dir(dev_id, gpio, CNXK_GPIO_PIN_DIR_IN);
+	CNXK_GPIO_ERR_STR(ret, "failed to set dir to input");
+	ret = cnxk_gpio_validate_attr(buf, "in");
+	CNXK_GPIO_ERR_STR(ret, "failed to validate %s", buf);
+
+	ret = rte_pmd_gpio_set_pin_value(dev_id, gpio, 1) |
+	      rte_pmd_gpio_set_pin_value(dev_id, gpio, 0);
+	if (!ret) {
+		ret = -EIO;
+		CNXK_GPIO_ERR_STR(ret, "input pin overwritten");
+	}
+
+	snprintf(buf + n, sizeof(buf) - n, "/edge");
+
+	ret = rte_pmd_gpio_set_pin_edge(dev_id, gpio,
+					CNXK_GPIO_PIN_EDGE_FALLING);
+	CNXK_GPIO_ERR_STR(ret, "failed to set edge to falling");
+	ret = cnxk_gpio_validate_attr(buf, "falling");
+	CNXK_GPIO_ERR_STR(ret, "failed to validate %s", buf);
+
+	ret = rte_pmd_gpio_set_pin_edge(dev_id, gpio,
+					CNXK_GPIO_PIN_EDGE_RISING);
+	CNXK_GPIO_ERR_STR(ret, "failed to change edge to rising");
+	ret = cnxk_gpio_validate_attr(buf, "rising");
+	CNXK_GPIO_ERR_STR(ret, "failed to validate %s", buf);
+
+	ret = rte_pmd_gpio_set_pin_edge(dev_id, gpio, CNXK_GPIO_PIN_EDGE_BOTH);
+	CNXK_GPIO_ERR_STR(ret, "failed to change edge to both");
+	ret = cnxk_gpio_validate_attr(buf, "both");
+	CNXK_GPIO_ERR_STR(ret, "failed to validate %s", buf);
+
+	ret = rte_pmd_gpio_set_pin_edge(dev_id, gpio, CNXK_GPIO_PIN_EDGE_NONE);
+	CNXK_GPIO_ERR_STR(ret, "failed to set edge to none");
+	ret = cnxk_gpio_validate_attr(buf, "none");
+	CNXK_GPIO_ERR_STR(ret, "failed to validate %s", buf);
+
+	/*
+	 * calling this makes sure kernel driver switches off inverted
+	 * logic
+	 */
+	rte_pmd_gpio_set_pin_dir(dev_id, gpio, CNXK_GPIO_PIN_DIR_IN);
+
+out:
+	return ret;
+}
+
+static int
+cnxk_gpio_trigger_irq(int gpio)
+{
+	int ret;
+
+	ret = ioctl(fd, OTX_IOC_TRIGGER_GPIO_HANDLER, gpio);
+
+	return ret == -1 ? -errno : 0;
+}
+
+static void
+cnxk_gpio_irq_handler(int gpio, void *data)
+{
+	*(int *)data = gpio;
+}
+
+static int
+cnxk_gpio_test_irq(uint16_t dev_id, int gpio)
+{
+	int irq_data, ret;
+
+	ret = rte_pmd_gpio_set_pin_dir(dev_id, gpio, CNXK_GPIO_PIN_DIR_IN);
+	CNXK_GPIO_ERR_STR(ret, "failed to set dir to input");
+
+	irq_data = 0;
+	ret = rte_pmd_gpio_register_irq(dev_id, gpio, rte_lcore_id(),
+					cnxk_gpio_irq_handler, &irq_data);
+	CNXK_GPIO_ERR_STR(ret, "failed to register irq handler");
+
+	ret = rte_pmd_gpio_enable_interrupt(dev_id, gpio,
+					    CNXK_GPIO_PIN_EDGE_RISING);
+	CNXK_GPIO_ERR_STR(ret, "failed to enable interrupt");
+
+	ret = cnxk_gpio_trigger_irq(gpio);
+	CNXK_GPIO_ERR_STR(ret, "failed to trigger irq");
+	rte_delay_ms(1);
+	ret = *(volatile int *)&irq_data == gpio ? 0 : -EIO;
+	CNXK_GPIO_ERR_STR(ret, "failed to test irq");
+
+	ret = rte_pmd_gpio_disable_interrupt(dev_id, gpio);
+	CNXK_GPIO_ERR_STR(ret, "failed to disable interrupt");
+
+	ret = rte_pmd_gpio_unregister_irq(dev_id, gpio);
+	CNXK_GPIO_ERR_STR(ret, "failed to unregister irq handler");
+out:
+	rte_pmd_gpio_disable_interrupt(dev_id, gpio);
+	rte_pmd_gpio_unregister_irq(dev_id, gpio);
+
+	return ret;
+}
+
+static int
+cnxk_gpio_test_output(uint16_t dev_id, int base, int gpio)
+{
+	char buf[CNXK_GPIO_BUFSZ];
+	int ret, val, n;
+
+	n = snprintf(buf, sizeof(buf), CNXK_GPIO_PATH_FMT, base + gpio);
+
+	snprintf(buf + n, sizeof(buf) - n, "/direction");
+	ret = rte_pmd_gpio_set_pin_dir(dev_id, gpio, CNXK_GPIO_PIN_DIR_OUT);
+	CNXK_GPIO_ERR_STR(ret, "failed to set dir to out");
+	ret = cnxk_gpio_validate_attr(buf, "out");
+	CNXK_GPIO_ERR_STR(ret, "failed to validate %s", buf);
+
+	snprintf(buf + n, sizeof(buf) - n, "/value");
+	ret = rte_pmd_gpio_set_pin_value(dev_id, gpio, 0);
+	CNXK_GPIO_ERR_STR(ret, "failed to set value to 0");
+	ret = cnxk_gpio_validate_attr(buf, "0");
+	CNXK_GPIO_ERR_STR(ret, "failed to validate %s", buf);
+	ret = rte_pmd_gpio_get_pin_value(dev_id, gpio, &val);
+	CNXK_GPIO_ERR_STR(ret, "failed to read value");
+	if (val)
+		ret = -EIO;
+	CNXK_GPIO_ERR_STR(ret, "read %d instead of 0", val);
+
+	ret = rte_pmd_gpio_set_pin_value(dev_id, gpio, 1);
+	CNXK_GPIO_ERR_STR(ret, "failed to set value to 1");
+	ret = cnxk_gpio_validate_attr(buf, "1");
+	CNXK_GPIO_ERR_STR(ret, "failed to validate %s", buf);
+	ret = rte_pmd_gpio_get_pin_value(dev_id, gpio, &val);
+	CNXK_GPIO_ERR_STR(ret, "failed to read value");
+	if (val != 1)
+		ret = -EIO;
+	CNXK_GPIO_ERR_STR(ret, "read %d instead of 1", val);
+
+	snprintf(buf + n, sizeof(buf) - n, "/direction");
+	ret = rte_pmd_gpio_set_pin_dir(dev_id, gpio, CNXK_GPIO_PIN_DIR_LOW);
+	CNXK_GPIO_ERR_STR(ret, "failed to set dir to low");
+	ret = cnxk_gpio_validate_attr(buf, "out");
+	CNXK_GPIO_ERR_STR(ret, "failed to validate %s", buf);
+	snprintf(buf + n, sizeof(buf) - n, "/value");
+	ret = cnxk_gpio_validate_attr(buf, "0");
+	CNXK_GPIO_ERR_STR(ret, "failed to validate %s", buf);
+
+	snprintf(buf + n, sizeof(buf) - n, "/direction");
+	ret = rte_pmd_gpio_set_pin_dir(dev_id, gpio, CNXK_GPIO_PIN_DIR_HIGH);
+	CNXK_GPIO_ERR_STR(ret, "failed to set dir to high");
+	ret = cnxk_gpio_validate_attr(buf, "out");
+	CNXK_GPIO_ERR_STR(ret, "failed to validate %s", buf);
+	snprintf(buf + n, sizeof(buf) - n, "/value");
+	ret = cnxk_gpio_validate_attr(buf, "1");
+	CNXK_GPIO_ERR_STR(ret, "failed to validate %s", buf);
+
+	snprintf(buf + n, sizeof(buf) - n, "/edge");
+	ret = rte_pmd_gpio_set_pin_edge(dev_id, gpio,
+					CNXK_GPIO_PIN_EDGE_FALLING);
+	ret = ret == 0 ? -EIO : 0;
+	CNXK_GPIO_ERR_STR(ret, "changed edge to falling");
+	ret = cnxk_gpio_validate_attr(buf, "none");
+	CNXK_GPIO_ERR_STR(ret, "failed to validate %s", buf);
+
+	ret = rte_pmd_gpio_set_pin_edge(dev_id, gpio,
+					CNXK_GPIO_PIN_EDGE_RISING);
+	ret = ret == 0 ? -EIO : 0;
+	CNXK_GPIO_ERR_STR(ret, "changed edge to rising");
+	ret = cnxk_gpio_validate_attr(buf, "none");
+	CNXK_GPIO_ERR_STR(ret, "failed to validate %s", buf);
+
+	ret = rte_pmd_gpio_set_pin_edge(dev_id, gpio, CNXK_GPIO_PIN_EDGE_BOTH);
+	ret = ret == 0 ? -EIO : 0;
+	CNXK_GPIO_ERR_STR(ret, "changed edge to both");
+	ret = cnxk_gpio_validate_attr(buf, "none");
+	CNXK_GPIO_ERR_STR(ret, "failed to validate %s", buf);
+
+	/* this one should succeed */
+	ret = rte_pmd_gpio_set_pin_edge(dev_id, gpio, CNXK_GPIO_PIN_EDGE_NONE);
+	CNXK_GPIO_ERR_STR(ret, "failed to change edge to none");
+	ret = cnxk_gpio_validate_attr(buf, "none");
+	CNXK_GPIO_ERR_STR(ret, "failed to validate %s", buf);
+
+	snprintf(buf + n, sizeof(buf) - n, "/active_low");
+	ret = rte_pmd_gpio_set_pin_active_low(dev_id, gpio, 1);
+	CNXK_GPIO_ERR_STR(ret, "failed to set active_low to 1");
+	ret = cnxk_gpio_validate_attr(buf, "1");
+	CNXK_GPIO_ERR_STR(ret, "failed to validate %s", buf);
+
+	ret = rte_pmd_gpio_get_pin_active_low(dev_id, gpio, &val);
+	CNXK_GPIO_ERR_STR(ret, "failed to read active_low");
+	if (val != 1)
+		ret = -EIO;
+	CNXK_GPIO_ERR_STR(ret, "read %d instead of 1", val);
+
+	snprintf(buf + n, sizeof(buf) - n, "/value");
+	ret = rte_pmd_gpio_set_pin_value(dev_id, gpio, 1);
+	CNXK_GPIO_ERR_STR(ret, "failed to set value to 1");
+	ret = cnxk_gpio_validate_attr(buf, "1");
+	CNXK_GPIO_ERR_STR(ret, "failed to validate %s", buf);
+
+	ret = rte_pmd_gpio_set_pin_value(dev_id, gpio, 0);
+	CNXK_GPIO_ERR_STR(ret, "failed to set value to 0");
+	ret = cnxk_gpio_validate_attr(buf, "0");
+	CNXK_GPIO_ERR_STR(ret, "failed to validate %s", buf);
+
+	snprintf(buf + n, sizeof(buf) - n, "/active_low");
+	ret = rte_pmd_gpio_set_pin_active_low(dev_id, gpio, 0);
+	CNXK_GPIO_ERR_STR(ret, "failed to set active_low to 0");
+	ret = cnxk_gpio_validate_attr(buf, "0");
+	CNXK_GPIO_ERR_STR(ret, "failed to validate %s", buf);
+
+out:
+	return ret;
+}
+
+int
+cnxk_gpio_selftest(uint16_t dev_id)
+{
+	struct cnxk_gpiochip *gpiochip;
+	unsigned int queues, i, size;
+	char buf[CNXK_GPIO_BUFSZ];
+	struct rte_rawdev *rawdev;
+	struct cnxk_gpio *gpio;
+	int ret;
+
+	rawdev = rte_rawdev_pmd_get_named_dev("cnxk_gpio");
+	gpiochip = rawdev->dev_private;
+
+	queues = rte_rawdev_queue_count(dev_id);
+	if (queues == 0)
+		return -ENODEV;
+
+	ret = rte_rawdev_start(dev_id);
+	if (ret)
+		return ret;
+
+	fd = open("/dev/otx-gpio-ctr", O_RDWR | O_SYNC);
+	if (fd < 0)
+		return -errno;
+
+	for (i = 0; i < queues; i++) {
+		RTE_LOG(INFO, PMD, "testing queue %d (gpio%d)\n", i,
+			gpiochip->base + i);
+
+		ret = rte_rawdev_queue_conf_get(dev_id, i, &size, sizeof(size));
+		if (ret) {
+			RTE_LOG(ERR, PMD,
+				"failed to read queue configuration (%d)\n",
+				ret);
+			continue;
+		}
+
+		if (size != 1) {
+			RTE_LOG(ERR, PMD, "wrong queue size received\n");
+			continue;
+		}
+
+		ret = rte_rawdev_queue_setup(dev_id, i, NULL, 0);
+		if (ret) {
+			RTE_LOG(ERR, PMD, "failed to setup queue (%d)\n", ret);
+			continue;
+		}
+
+		gpio = gpiochip->gpios[i];
+		snprintf(buf, sizeof(buf), CNXK_GPIO_PATH_FMT, gpio->num);
+		if (!cnxk_gpio_attr_exists(buf)) {
+			RTE_LOG(ERR, PMD, "%s does not exist\n", buf);
+			continue;
+		}
+
+		ret = cnxk_gpio_test_input(dev_id, gpiochip->base, i);
+		if (ret)
+			goto release;
+
+		ret = cnxk_gpio_test_irq(dev_id, i);
+		if (ret)
+			goto release;
+
+		ret = cnxk_gpio_test_output(dev_id, gpiochip->base, i);
+		if (ret)
+			goto release;
+
+release:
+		ret = rte_rawdev_queue_release(dev_id, i);
+		if (ret) {
+			RTE_LOG(ERR, PMD, "failed to release queue (%d)\n",
+				ret);
+			continue;
+		}
+
+		if (cnxk_gpio_attr_exists(buf)) {
+			RTE_LOG(ERR, PMD, "%s still exists\n", buf);
+			continue;
+		}
+	}
+
+	close(fd);
+
+	return 0;
+}
diff --git a/drivers/raw/cnxk_gpio/meson.build b/drivers/raw/cnxk_gpio/meson.build
index 9b55f029c7..a75a5b9084 100644
--- a/drivers/raw/cnxk_gpio/meson.build
+++ b/drivers/raw/cnxk_gpio/meson.build
@@ -6,5 +6,6 @@ deps += ['bus_vdev', 'common_cnxk', 'rawdev', 'kvargs']
 sources = files(
         'cnxk_gpio.c',
         'cnxk_gpio_irq.c',
+        'cnxk_gpio_selftest.c',
 )
 headers = files('rte_pmd_cnxk_gpio.h')
-- 
2.25.1


^ permalink raw reply related

* Re: [PATCH v3] PCI: mt7621: Convert driver into 'bool'
From: Lorenzo Pieralisi @ 2022-01-05 14:01 UTC (permalink / raw)
  To: Sergio Paracuellos
  Cc: linux-pci, tsbogend, bhelgaas, arnd, linux, linux-kernel
In-Reply-To: <20211203192454.32624-1-sergio.paracuellos@gmail.com>

On Fri, Dec 03, 2021 at 08:24:54PM +0100, Sergio Paracuellos wrote:
> Driver is not ready yet to be compiled as a module since it depends on some
> MIPS not exported symbols. We have the following current problems:
> 
> Building mips:allmodconfig ... failed
> --------------
> Error log:
> ERROR: modpost: missing MODULE_LICENSE() in drivers/pci/controller/pcie-mt7621.o
> ERROR: modpost: "mips_cm_unlock_other" [drivers/pci/controller/pcie-mt7621.ko] undefined!
> ERROR: modpost: "mips_cpc_base" [drivers/pci/controller/pcie-mt7621.ko] undefined!
> ERROR: modpost: "mips_cm_lock_other" [drivers/pci/controller/pcie-mt7621.ko] undefined!
> ERROR: modpost: "mips_cm_is64" [drivers/pci/controller/pcie-mt7621.ko] undefined!
> ERROR: modpost: "mips_gcr_base" [drivers/pci/controller/pcie-mt7621.ko] undefined!
> 
> Temporarily move from 'tristate' to 'bool' until a better solution is ready.
> 
> Also RALINK is redundant because SOC_MT7621 already depends on it. Hence,
> simplify condition.
> 
> Fixes: 2bdd5238e756 ("PCI: mt7621: Add MediaTek MT7621 PCIe host controller driver").
> Reviewed-and-tested-by: Guenter Roeck <linux@roeck-us.net>
> Signed-off-by: Sergio Paracuellos <sergio.paracuellos@gmail.com>
> ---
> Changes in v3:
>  - Adjust subject to follow convention:
>     s/PCI: mt7621: Kconfig:/PCI: mt7621:/
> Changes in v2:
>  - Add Guenter's 'Reviewed-and-tested-by'.
>  - s/after/until
>  drivers/pci/controller/Kconfig | 4 ++--
>  1 file changed, 2 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/pci/controller/Kconfig b/drivers/pci/controller/Kconfig
> index 93b141110537..7fc5135ffbbf 100644
> --- a/drivers/pci/controller/Kconfig
> +++ b/drivers/pci/controller/Kconfig
> @@ -332,8 +332,8 @@ config PCIE_APPLE
>  	  If unsure, say Y if you have an Apple Silicon system.
>  
>  config PCIE_MT7621
> -	tristate "MediaTek MT7621 PCIe Controller"
> -	depends on (RALINK && SOC_MT7621) || (MIPS && COMPILE_TEST)
> +	bool "MediaTek MT7621 PCIe Controller"
> +	depends on SOC_MT7621 || (MIPS && COMPILE_TEST)
>  	select PHY_MT7621_PCI
>  	default SOC_MT7621
>  	help
> -- 
> 2.33.0
> 

Hi Sergio,

I believe this is still to be pulled in some tree, just asking for
confirmation, please let me know and I will queue it.

Thanks,
Lorenzo

^ permalink raw reply

* [PATCH v1 07/34] tests: integrate lcitool for generating build env manifests
From: Alex Bennée @ 2022-01-05 13:49 UTC (permalink / raw)
  To: qemu-devel
  Cc: fam, berrange, Alex Bennée, f4bug, stefanha, crosa, pbonzini,
	Philippe Mathieu-Daudé, aurelien
In-Reply-To: <20220105135009.1584676-1-alex.bennee@linaro.org>

From: Daniel P. Berrangé <berrange@redhat.com>

This introduces

  https://gitlab.com/libvirt/libvirt-ci

as a git submodule at tests/lcitool/libvirt-ci

The 'lcitool' program within this submodule will be used to
automatically generate build environment manifests from a definition
of requirements in tests/lcitool/projects/qemu.yml

It will ultimately be capable of generating

 - Dockerfiles
 - Package lists for installation in VMs
 - Variables for configuring Cirrus CI environments

When a new build pre-requisite is needed for QEMU, if this package
is not currently known to libvirt-ci, it must first be added to the
'mappings.yml' file in the above git repo.

Then the submodule can be updated and the build pre-requisite added
to the tests/lcitool/projects/qemu.yml file. Now all the build env
manifests can be re-generated using  'make lcitool-refresh'

This ensures that when a new build pre-requisite is introduced, it
is added to all the different OS containers, VMs and Cirrus CI
environments consistently.

It also facilitates the addition of containers targetting new distros
or updating existing containers to new versions of the same distro,
where packages might have been renamed.

Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>
Signed-off-by: Alex Bennée <alex.bennee@linaro.org>
Message-Id: <20211215141949.3512719-8-berrange@redhat.com>
---
 docs/devel/testing.rst          | 104 ++++++++++++++++++++++++++++-
 Makefile                        |   2 +
 .gitmodules                     |   3 +
 tests/lcitool/Makefile.include  |  17 +++++
 tests/lcitool/libvirt-ci        |   1 +
 tests/lcitool/projects/qemu.yml | 115 ++++++++++++++++++++++++++++++++
 tests/lcitool/refresh           |  67 +++++++++++++++++++
 7 files changed, 306 insertions(+), 3 deletions(-)
 create mode 100644 tests/lcitool/Makefile.include
 create mode 160000 tests/lcitool/libvirt-ci
 create mode 100644 tests/lcitool/projects/qemu.yml
 create mode 100755 tests/lcitool/refresh

diff --git a/docs/devel/testing.rst b/docs/devel/testing.rst
index 755343c7dd..d744b5909c 100644
--- a/docs/devel/testing.rst
+++ b/docs/devel/testing.rst
@@ -382,14 +382,112 @@ Along with many other images, the ``centos8`` image is defined in a Dockerfile
 in ``tests/docker/dockerfiles/``, called ``centos8.docker``. ``make docker-help``
 command will list all the available images.
 
-To add a new image, simply create a new ``.docker`` file under the
-``tests/docker/dockerfiles/`` directory.
-
 A ``.pre`` script can be added beside the ``.docker`` file, which will be
 executed before building the image under the build context directory. This is
 mainly used to do necessary host side setup. One such setup is ``binfmt_misc``,
 for example, to make qemu-user powered cross build containers work.
 
+Most of the existing Dockerfiles were written by hand, simply by creating a
+a new ``.docker`` file under the ``tests/docker/dockerfiles/`` directory.
+This has led to an inconsistent set of packages being present across the
+different containers.
+
+Thus going forward, QEMU is aiming to automatically generate the Dockerfiles
+using the ``lcitool`` program provided by the ``libvirt-ci`` project:
+
+  https://gitlab.com/libvirt/libvirt-ci
+
+In that project, there is a ``mappings.yml`` file defining the distro native
+package names for a wide variety of third party projects. This is processed
+in combination with a project defined list of build pre-requisites to determine
+the list of native packages to install on each distribution. This can be used
+to generate dockerfiles, VM package lists and Cirrus CI variables needed to
+setup build environments across OS distributions with a consistent set of
+packages present.
+
+When preparing a patch series that adds a new build pre-requisite to QEMU,
+updates to various lcitool data files may be required.
+
+
+Adding new build pre-requisites
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+In the simple case where the pre-requisite is already known to ``libvirt-ci``
+the following steps are needed
+
+ * Edit ``tests/lcitool/projects/qemu.yml`` and add the pre-requisite
+
+ * Run ``make lcitool-refresh`` to re-generate all relevant build environment
+   manifests
+
+In some cases ``libvirt-ci`` will not know about the build pre-requisite and
+thus some extra preparation steps will be required first
+
+ * Fork the ``libvirt-ci`` project on gitlab
+
+ * Edit the ``mappings.yml`` change to add an entry for the new build
+   prerequisite, listing its native package name on as many OS distros
+   as practical.
+
+ * Commit the ``mappings.yml`` change and submit a merge request to
+   the ``libvirt-ci`` project, noting in the description that this
+   is a new build pre-requisite desired for use with QEMU
+
+ * CI pipeline will run to validate that the changes to ``mappings.yml``
+   are correct, by attempting to install the newly listed package on
+   all OS distributions supported by ``libvirt-ci``.
+
+ * Once the merge request is accepted, go back to QEMU and update
+   the ``libvirt-ci`` submodule to point to a commit that contains
+   the ``mappings.yml`` update.
+
+
+Adding new OS distros
+^^^^^^^^^^^^^^^^^^^^^
+
+In some cases ``libvirt-ci`` will not know about the OS distro that is
+desired to be tested. Before adding a new OS distro, discuss the proposed
+addition:
+
+ * Send a mail to qemu-devel, copying people listed in the
+   MAINTAINERS file for ``Build and test automation``.
+
+   There are limited CI compute resources available to QEMU, so the
+   cost/benefit tradeoff of adding new OS distros needs to be considered.
+
+ * File an issue at https://gitlab.com/libvirt/libvirt-ci/-/issues
+   pointing to the qemu-devel mail thread in the archives.
+
+   This alerts other people who might be interested in the work
+   to avoid duplication, as well as to get feedback from libvirt-ci
+   maintainers on any tips to ease the addition
+
+Assuming there is agreement to add a new OS distro then
+
+ * Fork the ``libvirt-ci`` project on gitlab
+
+ * Add metadata under ``guests/lcitool/lcitool/ansible/group_vars/``
+   for the new OS distro. There might be code changes required if
+   the OS distro uses a package format not currently known. The
+   ``libvirt-ci`` maintainers can advise on this when the issue
+   is file.
+
+ * Edit the ``mappings.yml`` change to update all the existing package
+   entries, providing details of the new OS distro
+
+ * Commit the ``mappings.yml`` change and submit a merge request to
+   the ``libvirt-ci`` project, noting in the description that this
+   is a new build pre-requisite desired for use with QEMU
+
+ * CI pipeline will run to validate that the changes to ``mappings.yml``
+   are correct, by attempting to install the newly listed package on
+   all OS distributions supported by ``libvirt-ci``.
+
+ * Once the merge request is accepted, go back to QEMU and update
+   the ``libvirt-ci`` submodule to point to a commit that contains
+   the ``mappings.yml`` update.
+
+
 Tests
 ~~~~~
 
diff --git a/Makefile b/Makefile
index 5d66c35ea5..c9a049be6f 100644
--- a/Makefile
+++ b/Makefile
@@ -288,6 +288,7 @@ cscope:
 # Needed by "meson install"
 export DESTDIR
 
+include $(SRC_PATH)/tests/lcitool/Makefile.include
 include $(SRC_PATH)/tests/docker/Makefile.include
 include $(SRC_PATH)/tests/vm/Makefile.include
 
@@ -317,6 +318,7 @@ endif
 	@echo  'Test targets:'
 	$(call print-help,check,Run all tests (check-help for details))
 	$(call print-help,bench,Run all benchmarks)
+	$(call print-help,lcitool-help,Help about targets for managing build environment manifests)
 	$(call print-help,docker-help,Help about targets running tests inside containers)
 	$(call print-help,vm-help,Help about targets running tests inside VM)
 	@echo  ''
diff --git a/.gitmodules b/.gitmodules
index 08b1b48a09..84425d87e2 100644
--- a/.gitmodules
+++ b/.gitmodules
@@ -64,3 +64,6 @@
 [submodule "roms/vbootrom"]
 	path = roms/vbootrom
 	url = https://gitlab.com/qemu-project/vbootrom.git
+[submodule "tests/lcitool/libvirt-ci"]
+	path = tests/lcitool/libvirt-ci
+	url = http://gitlab.com/libvirt/libvirt-ci
diff --git a/tests/lcitool/Makefile.include b/tests/lcitool/Makefile.include
new file mode 100644
index 0000000000..cff7c0b814
--- /dev/null
+++ b/tests/lcitool/Makefile.include
@@ -0,0 +1,17 @@
+
+LCITOOL_REFRESH = $(SRC_PATH)/tests/lcitool/refresh
+
+lcitool:
+	@echo 'Manage build environment manifests'
+	@echo
+	@echo 'Available targets:'
+	@echo
+	@echo '    lcitool:             Print this help.'
+	@echo '    lcitool-refresh:     Re-generate all build environment manifests.'
+	@echo
+
+lcitool-help: lcitool
+
+lcitool-refresh:
+	$(call quiet-command, git submodule update --init $(SRC_PATH)/tests/lcitool/libvirt-ci)
+	$(call quiet-command, $(LCITOOL_REFRESH))
diff --git a/tests/lcitool/libvirt-ci b/tests/lcitool/libvirt-ci
new file mode 160000
index 0000000000..29cec2153b
--- /dev/null
+++ b/tests/lcitool/libvirt-ci
@@ -0,0 +1 @@
+Subproject commit 29cec2153b9a4dbb2e66f1cbc9866a4eff519cfd
diff --git a/tests/lcitool/projects/qemu.yml b/tests/lcitool/projects/qemu.yml
new file mode 100644
index 0000000000..2e2271510e
--- /dev/null
+++ b/tests/lcitool/projects/qemu.yml
@@ -0,0 +1,115 @@
+---
+packages:
+ - alsa
+ - bash
+ - bc
+ - brlapi
+ - bzip2
+ - bzip2-libs
+ - capstone
+ - ccache
+ - clang
+ - column
+ - ctags
+ - cyrus-sasl
+ - daxctl
+ - dbus-daemon
+ - device-mapper-multipath
+ - diffutils
+ - dtrace
+ - findutils
+ - g++
+ - gcc
+ - gcovr
+ - gettext
+ - genisoimage
+ - glib2
+ - glib2-static
+ - glibc-static
+ - glusterfs
+ - gnutls
+ - gtk3
+ - hostname
+ - libaio
+ - libattr
+ - libasan
+ - libbpf
+ - libcacard
+ - libcap-ng
+ - libcurl
+ - libdrm
+ - libepoxy
+ - libfdt
+ - libffi
+ - libgcrypt
+ - libibverbs
+ - libiscsi
+ - libjemalloc
+ - libjpeg
+ - libnfs
+ - libnuma
+ - libpmem
+ - libpng
+ - librbd
+ - librdmacm
+ - libseccomp
+ - libselinux
+ - libslirp
+ - libssh
+ - libtasn1
+ - libubsan
+ - libudev
+ - liburing
+ - libusbx
+ - libvdeplug
+ - libxml2
+ - libzstd
+ - llvm
+ - lttng-ust
+ - lzo
+ - netcat
+ - nettle
+ - ninja
+ - nsis
+ - make
+ - mesa-libgbm
+ - meson
+ - ncursesw
+ - pam
+ - pcre-static
+ - perl
+ - perl-Test-Harness
+ - pixman
+ - pkg-config
+ - pulseaudio
+ - python3
+ - python3-PyYAML
+ - python3-numpy
+ - python3-opencv
+ - python3-pillow
+ - python3-pip
+ - python3-sphinx
+ - python3-sphinx-rtd-theme
+ - python3-virtualenv
+ - rpm2cpio
+ - sdl2
+ - sdl2-image
+ - sed
+ - snappy
+ - sparse
+ - spice-protocol
+ - spice-server
+ - ssh-client
+ - systemd
+ - tar
+ - tesseract
+ - tesseract-eng
+ - texinfo
+ - usbredir
+ - virglrenderer
+ - vte
+ - which
+ - xen
+ - xfsprogs
+ - zlib
+ - zlib-static
diff --git a/tests/lcitool/refresh b/tests/lcitool/refresh
new file mode 100755
index 0000000000..b47e25f64b
--- /dev/null
+++ b/tests/lcitool/refresh
@@ -0,0 +1,67 @@
+#!/usr/bin/python3
+#
+# Re-generate container recipes
+#
+# This script uses the "lcitool" available from
+#
+#   https://gitlab.com/libvirt/libvirt-ci
+#
+# Copyright (c) 2020 Red Hat Inc.
+#
+# This work is licensed under the terms of the GNU GPL, version 2
+# or (at your option) any later version. See the COPYING file in
+# the top-level directory.
+
+import sys
+import os
+import subprocess
+
+from pathlib import Path
+
+if len(sys.argv) != 1:
+   print("syntax: %s" % sys.argv[0], file=sys.stderr)
+   sys.exit(1)
+
+self_dir = Path(__file__).parent
+src_dir = self_dir.parent.parent
+dockerfiles_dir = Path(src_dir, "tests", "docker", "dockerfiles")
+
+lcitool_path = Path(self_dir, "libvirt-ci", "lcitool")
+
+lcitool_cmd = [lcitool_path, "--data-dir", self_dir]
+
+def atomic_write(filename, content):
+   tmp = filename.with_suffix(filename.suffix + ".tmp")
+   try:
+      with tmp.open("w") as fp:
+         print(content, file=fp, end="")
+         tmp.rename(filename)
+   except Exception as ex:
+      tmp.unlink()
+      raise
+
+def generate(filename, cmd, trailer):
+   print("Generate %s" % filename)
+   lcitool=subprocess.run(cmd, capture_output=True)
+
+   if lcitool.returncode != 0:
+      raise Exception("Failed to generate %s: %s" % (filename, lcitool.stderr))
+
+   content = lcitool.stdout.decode("utf8")
+   if trailer is not None:
+      content += trailer
+   atomic_write(filename, content)
+
+def generate_dockerfile(host, target, cross=None, trailer=None):
+   filename = Path(src_dir, "tests", "docker", "dockerfiles", host + ".docker")
+   cmd = lcitool_cmd + ["dockerfile"]
+   if cross is not None:
+      cmd.extend(["--cross", cross])
+   cmd.extend([target, "qemu"])
+   generate(filename, cmd, trailer)
+
+try:
+   sys.exit(0)
+except Exception as ex:
+   print(str(ex), file=sys.stderr)
+   sys.exit(1)
-- 
2.30.2



^ permalink raw reply related

* [PATCH  v1 03/34] meson: require liburing >= 0.3
From: Alex Bennée @ 2022-01-05 13:49 UTC (permalink / raw)
  To: qemu-devel
  Cc: fam, berrange, Alex Bennée, f4bug, stefanha, crosa, pbonzini,
	Philippe Mathieu-Daudé, aurelien
In-Reply-To: <20220105135009.1584676-1-alex.bennee@linaro.org>

From: Daniel P. Berrangé <berrange@redhat.com>

openSUSE Leap 15.2 ships with liburing == 0.2 against which QEMU fails
to build.

../util/fdmon-io_uring.c: In function ‘fdmon_io_uring_need_wait’:
../util/fdmon-io_uring.c:305:9: error: implicit declaration of function ‘io_uring_sq_ready’; did you mean ‘io_uring_cq_ready’? [-Werror=implicit-function-declaration]
     if (io_uring_sq_ready(&ctx->fdmon_io_uring)) {
         ^~~~~~~~~~~~~~~~~
         io_uring_cq_ready

This method was introduced in liburing 0.3, so set that as a minimum
requirement.

Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>
Signed-off-by: Alex Bennée <alex.bennee@linaro.org>
Message-Id: <20211215141949.3512719-4-berrange@redhat.com>
---
 meson.build | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/meson.build b/meson.build
index 53065e96ec..0e52f54b10 100644
--- a/meson.build
+++ b/meson.build
@@ -440,7 +440,8 @@ if not get_option('linux_aio').auto() or have_block
 endif
 linux_io_uring = not_found
 if not get_option('linux_io_uring').auto() or have_block
-  linux_io_uring = dependency('liburing', required: get_option('linux_io_uring'),
+  linux_io_uring = dependency('liburing', version: '>=0.3',
+                              required: get_option('linux_io_uring'),
                               method: 'pkg-config', kwargs: static_kwargs)
 endif
 libxml2 = not_found
-- 
2.30.2



^ permalink raw reply related

* [PATCH v4 11/11] raw/cnxk_gpio: add option to allow using subset of GPIOs
From: Tomasz Duszynski @ 2022-01-05 14:00 UTC (permalink / raw)
  To: dev; +Cc: thomas, jerinj, Tomasz Duszynski
In-Reply-To: <20220105140020.1615256-1-tduszynski@marvell.com>

Add PMD parameter that allows one to select only subset of available
GPIOs.

This might be useful in cases where some GPIOs are already reserved yet
still available for userspace access but particular app should not touch
them.

Signed-off-by: Tomasz Duszynski <tduszynski@marvell.com>
Reviewed-by: Jerin Jacob Kollanukkaran <jerinj@marvell.com>
---
 doc/guides/rawdevs/cnxk_gpio.rst           |   5 +
 drivers/raw/cnxk_gpio/cnxk_gpio.c          | 173 +++++++++++++++++----
 drivers/raw/cnxk_gpio/cnxk_gpio.h          |   2 +
 drivers/raw/cnxk_gpio/cnxk_gpio_selftest.c |  20 +--
 drivers/raw/cnxk_gpio/rte_pmd_cnxk_gpio.h  |   8 +
 5 files changed, 170 insertions(+), 38 deletions(-)

diff --git a/doc/guides/rawdevs/cnxk_gpio.rst b/doc/guides/rawdevs/cnxk_gpio.rst
index c03a5b937c..adff535a77 100644
--- a/doc/guides/rawdevs/cnxk_gpio.rst
+++ b/doc/guides/rawdevs/cnxk_gpio.rst
@@ -57,6 +57,11 @@ former returns number GPIOs available in the system irrespective of GPIOs
 being controllable or not. Thus it is user responsibility to pick the proper
 ones. The latter call simply returns queue capacity.
 
+In order to allow using only subset of available GPIOs `allowlist` PMD param may
+be used. For example passing `--vdev=cnxk_gpio,gpiochip=448,allowlist=[0,1,2,3]`
+to EAL will deny using all GPIOs except those specified explicitly in the
+`allowlist`.
+
 Respective queue needs to be configured with ``rte_rawdev_queue_setup()``. This
 call barely exports GPIO to userspace.
 
diff --git a/drivers/raw/cnxk_gpio/cnxk_gpio.c b/drivers/raw/cnxk_gpio/cnxk_gpio.c
index 16a886b693..0951899a45 100644
--- a/drivers/raw/cnxk_gpio/cnxk_gpio.c
+++ b/drivers/raw/cnxk_gpio/cnxk_gpio.c
@@ -22,9 +22,13 @@
 static const char *const cnxk_gpio_args[] = {
 #define CNXK_GPIO_ARG_GPIOCHIP "gpiochip"
 	CNXK_GPIO_ARG_GPIOCHIP,
+#define CNXK_GPIO_ARG_ALLOWLIST "allowlist"
+	CNXK_GPIO_ARG_ALLOWLIST,
 	NULL
 };
 
+static char *allowlist;
+
 static void
 cnxk_gpio_format_name(char *name, size_t len)
 {
@@ -73,13 +77,23 @@ cnxk_gpio_parse_arg_gpiochip(const char *key __rte_unused, const char *value,
 }
 
 static int
-cnxk_gpio_parse_args(struct cnxk_gpiochip *gpiochip,
-		     struct rte_devargs *devargs)
+cnxk_gpio_parse_arg_allowlist(const char *key __rte_unused, const char *value,
+			      void *extra_args __rte_unused)
+{
+	allowlist = strdup(value);
+	if (!allowlist)
+		return -ENOMEM;
+
+	return 0;
+}
+
+static int
+cnxk_gpio_parse_args(struct cnxk_gpiochip *gpiochip, const char *args)
 {
 	struct rte_kvargs *kvlist;
 	int ret;
 
-	kvlist = rte_kvargs_parse(devargs->args, cnxk_gpio_args);
+	kvlist = rte_kvargs_parse(args, cnxk_gpio_args);
 	if (!kvlist)
 		return 0;
 
@@ -92,6 +106,14 @@ cnxk_gpio_parse_args(struct cnxk_gpiochip *gpiochip,
 			goto out;
 	}
 
+	ret = rte_kvargs_count(kvlist, CNXK_GPIO_ARG_ALLOWLIST);
+	if (ret == 1) {
+		ret = rte_kvargs_process(kvlist, CNXK_GPIO_ARG_ALLOWLIST,
+					 cnxk_gpio_parse_arg_allowlist, NULL);
+		if (ret)
+			goto out;
+	}
+
 	ret = 0;
 out:
 	rte_kvargs_free(kvlist);
@@ -99,6 +121,60 @@ cnxk_gpio_parse_args(struct cnxk_gpiochip *gpiochip,
 	return ret;
 }
 
+static int
+cnxk_gpio_parse_allowlist(struct cnxk_gpiochip *gpiochip)
+{
+	int i, ret, val, queue = 0;
+	char *token;
+	int *list;
+
+	list = rte_calloc(NULL, gpiochip->num_gpios, sizeof(*list), 0);
+	if (!list)
+		return -ENOMEM;
+
+	/* replace brackets with something meaningless for strtol() */
+	allowlist[0] = ' ';
+	allowlist[strlen(allowlist) - 1] = ' ';
+
+	/* quiesce -Wcast-qual */
+	token = strtok((char *)(uintptr_t)allowlist, ",");
+	do {
+		errno = 0;
+		val = strtol(token, NULL, 10);
+		if (errno) {
+			RTE_LOG(ERR, PMD, "failed to parse %s\n", token);
+			ret = -errno;
+			goto out;
+		}
+
+		if (val < 0 || val >= gpiochip->num_gpios) {
+			RTE_LOG(ERR, PMD, "gpio%d out of 0-%d range\n", val,
+				gpiochip->num_gpios - 1);
+			ret = -EINVAL;
+			goto out;
+		}
+
+		for (i = 0; i < queue; i++) {
+			if (list[i] != val)
+				continue;
+
+			RTE_LOG(WARNING, PMD, "gpio%d already allowed\n", val);
+			break;
+		}
+		if (i == queue)
+			list[queue++] = val;
+	} while ((token = strtok(NULL, ",")));
+
+	gpiochip->allowlist = list;
+	gpiochip->num_queues = queue;
+
+	return 0;
+out:
+	rte_free(list);
+
+	return ret;
+}
+
 static int
 cnxk_gpio_read_attr(char *attr, char *val)
 {
@@ -175,13 +251,24 @@ cnxk_gpio_write_attr_int(const char *attr, int val)
 	return cnxk_gpio_write_attr(attr, buf);
 }
 
+static bool
+cnxk_gpio_queue_valid(struct cnxk_gpiochip *gpiochip, uint16_t queue)
+{
+	return queue < gpiochip->num_queues;
+}
+
+static int
+cnxk_queue_to_gpio(struct cnxk_gpiochip *gpiochip, uint16_t queue)
+{
+	return gpiochip->allowlist ? gpiochip->allowlist[queue] : queue;
+}
+
 static struct cnxk_gpio *
 cnxk_gpio_lookup(struct cnxk_gpiochip *gpiochip, uint16_t queue)
 {
-	if (queue >= gpiochip->num_gpios)
-		return NULL;
+	int gpio = cnxk_queue_to_gpio(gpiochip, queue);
 
-	return gpiochip->gpios[queue];
+	return gpiochip->gpios[gpio];
 }
 
 static int
@@ -191,11 +278,14 @@ cnxk_gpio_queue_setup(struct rte_rawdev *dev, uint16_t queue_id,
 	struct cnxk_gpiochip *gpiochip = dev->dev_private;
 	char buf[CNXK_GPIO_BUFSZ];
 	struct cnxk_gpio *gpio;
-	int ret;
+	int num, ret;
 
 	RTE_SET_USED(queue_conf);
 	RTE_SET_USED(queue_conf_size);
 
+	if (!cnxk_gpio_queue_valid(gpiochip, queue_id))
+		return -EINVAL;
+
 	gpio = cnxk_gpio_lookup(gpiochip, queue_id);
 	if (gpio)
 		return -EEXIST;
@@ -203,7 +293,9 @@ cnxk_gpio_queue_setup(struct rte_rawdev *dev, uint16_t queue_id,
 	gpio = rte_zmalloc(NULL, sizeof(*gpio), 0);
 	if (!gpio)
 		return -ENOMEM;
-	gpio->num = queue_id + gpiochip->base;
+
+	num = cnxk_queue_to_gpio(gpiochip, queue_id);
+	gpio->num = num + gpiochip->base;
 	gpio->gpiochip = gpiochip;
 
 	snprintf(buf, sizeof(buf), "%s/export", CNXK_GPIO_CLASS_PATH);
@@ -213,7 +305,7 @@ cnxk_gpio_queue_setup(struct rte_rawdev *dev, uint16_t queue_id,
 		return ret;
 	}
 
-	gpiochip->gpios[queue_id] = gpio;
+	gpiochip->gpios[num] = gpio;
 
 	return 0;
 }
@@ -224,18 +316,22 @@ cnxk_gpio_queue_release(struct rte_rawdev *dev, uint16_t queue_id)
 	struct cnxk_gpiochip *gpiochip = dev->dev_private;
 	char buf[CNXK_GPIO_BUFSZ];
 	struct cnxk_gpio *gpio;
-	int ret;
+	int num, ret;
+
+	if (!cnxk_gpio_queue_valid(gpiochip, queue_id))
+		return -EINVAL;
 
 	gpio = cnxk_gpio_lookup(gpiochip, queue_id);
 	if (!gpio)
 		return -ENODEV;
 
 	snprintf(buf, sizeof(buf), "%s/unexport", CNXK_GPIO_CLASS_PATH);
-	ret = cnxk_gpio_write_attr_int(buf, gpiochip->base + queue_id);
+	ret = cnxk_gpio_write_attr_int(buf, gpio->num);
 	if (ret)
 		return ret;
 
-	gpiochip->gpios[queue_id] = NULL;
+	num = cnxk_queue_to_gpio(gpiochip, queue_id);
+	gpiochip->gpios[num] = NULL;
 	rte_free(gpio);
 
 	return 0;
@@ -245,16 +341,17 @@ static int
 cnxk_gpio_queue_def_conf(struct rte_rawdev *dev, uint16_t queue_id,
 			 rte_rawdev_obj_t queue_conf, size_t queue_conf_size)
 {
-	unsigned int *conf;
+	struct cnxk_gpiochip *gpiochip = dev->dev_private;
+	struct cnxk_gpio_queue_conf *conf = queue_conf;
 
-	RTE_SET_USED(dev);
-	RTE_SET_USED(queue_id);
+	if (!cnxk_gpio_queue_valid(gpiochip, queue_id))
+		return -EINVAL;
 
 	if (queue_conf_size != sizeof(*conf))
 		return -EINVAL;
 
-	conf = (unsigned int *)queue_conf;
-	*conf = 1;
+	conf->size = 1;
+	conf->gpio = cnxk_queue_to_gpio(gpiochip, queue_id);
 
 	return 0;
 }
@@ -264,7 +361,7 @@ cnxk_gpio_queue_count(struct rte_rawdev *dev)
 {
 	struct cnxk_gpiochip *gpiochip = dev->dev_private;
 
-	return gpiochip->num_gpios;
+	return gpiochip->num_queues;
 }
 
 static const struct {
@@ -463,21 +560,27 @@ cnxk_gpio_process_buf(struct cnxk_gpio *gpio, struct rte_rawdev_buf *rbuf)
 	return ret;
 }
 
+static bool
+cnxk_gpio_valid(struct cnxk_gpiochip *gpiochip, int gpio)
+{
+	return gpio < gpiochip->num_gpios && gpiochip->gpios[gpio];
+}
+
 static int
 cnxk_gpio_enqueue_bufs(struct rte_rawdev *dev, struct rte_rawdev_buf **buffers,
 		       unsigned int count, rte_rawdev_obj_t context)
 {
 	struct cnxk_gpiochip *gpiochip = dev->dev_private;
-	unsigned int queue = (size_t)context;
+	unsigned int gpio_num = (size_t)context;
 	struct cnxk_gpio *gpio;
 	int ret;
 
 	if (count == 0)
 		return 0;
 
-	gpio = cnxk_gpio_lookup(gpiochip, queue);
-	if (!gpio)
-		return -ENODEV;
+	if (!cnxk_gpio_valid(gpiochip, gpio_num))
+		return -EINVAL;
+	gpio = gpiochip->gpios[gpio_num];
 
 	ret = cnxk_gpio_process_buf(gpio, buffers[0]);
 	if (ret)
@@ -491,15 +594,15 @@ cnxk_gpio_dequeue_bufs(struct rte_rawdev *dev, struct rte_rawdev_buf **buffers,
 		       unsigned int count, rte_rawdev_obj_t context)
 {
 	struct cnxk_gpiochip *gpiochip = dev->dev_private;
-	unsigned int queue = (size_t)context;
+	unsigned int gpio_num = (size_t)context;
 	struct cnxk_gpio *gpio;
 
 	if (count == 0)
 		return 0;
 
-	gpio = cnxk_gpio_lookup(gpiochip, queue);
-	if (!gpio)
-		return -ENODEV;
+	if (!cnxk_gpio_valid(gpiochip, gpio_num))
+		return -EINVAL;
+	gpio = gpiochip->gpios[gpio_num];
 
 	if (gpio->rsp) {
 		buffers[0]->buf_addr = gpio->rsp;
@@ -549,7 +652,7 @@ cnxk_gpio_probe(struct rte_vdev_device *dev)
 	cnxk_gpio_set_defaults(gpiochip);
 
 	/* defaults may be overwritten by this call */
-	ret = cnxk_gpio_parse_args(gpiochip, dev->device.devargs);
+	ret = cnxk_gpio_parse_args(gpiochip, rte_vdev_device_args(dev));
 	if (ret)
 		goto out;
 
@@ -574,6 +677,15 @@ cnxk_gpio_probe(struct rte_vdev_device *dev)
 		RTE_LOG(ERR, PMD, "failed to read %s", buf);
 		goto out;
 	}
+	gpiochip->num_queues = gpiochip->num_gpios;
+
+	if (allowlist) {
+		ret = cnxk_gpio_parse_allowlist(gpiochip);
+		free(allowlist);
+		allowlist = NULL;
+		if (ret)
+			goto out;
+	}
 
 	gpiochip->gpios = rte_calloc(NULL, gpiochip->num_gpios,
 				     sizeof(struct cnxk_gpio *), 0);
@@ -585,6 +697,8 @@ cnxk_gpio_probe(struct rte_vdev_device *dev)
 
 	return 0;
 out:
+	free(allowlist);
+	rte_free(gpiochip->allowlist);
 	rte_rawdev_pmd_release(rawdev);
 
 	return ret;
@@ -621,6 +735,7 @@ cnxk_gpio_remove(struct rte_vdev_device *dev)
 		cnxk_gpio_queue_release(rawdev, gpio->num);
 	}
 
+	rte_free(gpiochip->allowlist);
 	rte_free(gpiochip->gpios);
 	cnxk_gpio_irq_fini();
 	rte_rawdev_pmd_release(rawdev);
@@ -634,4 +749,6 @@ static struct rte_vdev_driver cnxk_gpio_drv = {
 };
 
 RTE_PMD_REGISTER_VDEV(cnxk_gpio, cnxk_gpio_drv);
-RTE_PMD_REGISTER_PARAM_STRING(cnxk_gpio, "gpiochip=<int>");
+RTE_PMD_REGISTER_PARAM_STRING(cnxk_gpio,
+		"gpiochip=<int> "
+		"allowlist=<list>");
diff --git a/drivers/raw/cnxk_gpio/cnxk_gpio.h b/drivers/raw/cnxk_gpio/cnxk_gpio.h
index 1b31b5a486..e62f78a760 100644
--- a/drivers/raw/cnxk_gpio/cnxk_gpio.h
+++ b/drivers/raw/cnxk_gpio/cnxk_gpio.h
@@ -20,7 +20,9 @@ struct cnxk_gpiochip {
 	int num;
 	int base;
 	int num_gpios;
+	int num_queues;
 	struct cnxk_gpio **gpios;
+	int *allowlist;
 };
 
 int cnxk_gpio_selftest(uint16_t dev_id);
diff --git a/drivers/raw/cnxk_gpio/cnxk_gpio_selftest.c b/drivers/raw/cnxk_gpio/cnxk_gpio_selftest.c
index 6502902f86..303931fa0f 100644
--- a/drivers/raw/cnxk_gpio/cnxk_gpio_selftest.c
+++ b/drivers/raw/cnxk_gpio/cnxk_gpio_selftest.c
@@ -302,10 +302,11 @@ cnxk_gpio_test_output(uint16_t dev_id, int base, int gpio)
 int
 cnxk_gpio_selftest(uint16_t dev_id)
 {
+	struct cnxk_gpio_queue_conf conf;
 	struct cnxk_gpiochip *gpiochip;
-	unsigned int queues, i, size;
 	char buf[CNXK_GPIO_BUFSZ];
 	struct rte_rawdev *rawdev;
+	unsigned int queues, i;
 	struct cnxk_gpio *gpio;
 	int ret;
 
@@ -325,10 +326,7 @@ cnxk_gpio_selftest(uint16_t dev_id)
 		return -errno;
 
 	for (i = 0; i < queues; i++) {
-		RTE_LOG(INFO, PMD, "testing queue %d (gpio%d)\n", i,
-			gpiochip->base + i);
-
-		ret = rte_rawdev_queue_conf_get(dev_id, i, &size, sizeof(size));
+		ret = rte_rawdev_queue_conf_get(dev_id, i, &conf, sizeof(conf));
 		if (ret) {
 			RTE_LOG(ERR, PMD,
 				"failed to read queue configuration (%d)\n",
@@ -336,7 +334,9 @@ cnxk_gpio_selftest(uint16_t dev_id)
 			continue;
 		}
 
-		if (size != 1) {
+		RTE_LOG(INFO, PMD, "testing queue%d (gpio%d)\n", i, conf.gpio);
+
+		if (conf.size != 1) {
 			RTE_LOG(ERR, PMD, "wrong queue size received\n");
 			continue;
 		}
@@ -347,22 +347,22 @@ cnxk_gpio_selftest(uint16_t dev_id)
 			continue;
 		}
 
-		gpio = gpiochip->gpios[i];
+		gpio = gpiochip->gpios[conf.gpio];
 		snprintf(buf, sizeof(buf), CNXK_GPIO_PATH_FMT, gpio->num);
 		if (!cnxk_gpio_attr_exists(buf)) {
 			RTE_LOG(ERR, PMD, "%s does not exist\n", buf);
 			continue;
 		}
 
-		ret = cnxk_gpio_test_input(dev_id, gpiochip->base, i);
+		ret = cnxk_gpio_test_input(dev_id, gpiochip->base, conf.gpio);
 		if (ret)
 			goto release;
 
-		ret = cnxk_gpio_test_irq(dev_id, i);
+		ret = cnxk_gpio_test_irq(dev_id, conf.gpio);
 		if (ret)
 			goto release;
 
-		ret = cnxk_gpio_test_output(dev_id, gpiochip->base, i);
+		ret = cnxk_gpio_test_output(dev_id, gpiochip->base, conf.gpio);
 		if (ret)
 			goto release;
 
diff --git a/drivers/raw/cnxk_gpio/rte_pmd_cnxk_gpio.h b/drivers/raw/cnxk_gpio/rte_pmd_cnxk_gpio.h
index e3096dc14f..80a37be9c7 100644
--- a/drivers/raw/cnxk_gpio/rte_pmd_cnxk_gpio.h
+++ b/drivers/raw/cnxk_gpio/rte_pmd_cnxk_gpio.h
@@ -22,6 +22,14 @@
 extern "C" {
 #endif
 
+/* Queue default configuration */
+struct cnxk_gpio_queue_conf {
+	/** Queue size */
+	int size;
+	/** GPIO number as seen by hardware */
+	int gpio;
+};
+
 /** Available message types */
 enum cnxk_gpio_msg_type {
 	/** Type used to set output value */
-- 
2.25.1


^ permalink raw reply related

* [PATCH  v1 27/34] tests/avocado: add :avocado: tags for some tests
From: Alex Bennée @ 2022-01-05 13:50 UTC (permalink / raw)
  To: qemu-devel
  Cc: fam, berrange, Beraldo Leal, f4bug, Wainer dos Santos Moschetta,
	stefanha, crosa, pbonzini, Alex Bennée, aurelien
In-Reply-To: <20220105135009.1584676-1-alex.bennee@linaro.org>

This stops a bunch of tests failing because of a lack of
"./qemu-system-x86-64" in a build directory where you have configured
only one non-default target. I suspect what we really need is:

    :avocado: tags=arch:host

to be properly multi-arch safe.

Signed-off-by: Alex Bennée <alex.bennee@linaro.org>
---
 tests/avocado/empty_cpu_model.py | 3 +++
 tests/avocado/info_usernet.py    | 3 +++
 tests/avocado/migration.py       | 1 +
 tests/avocado/version.py         | 1 +
 tests/avocado/vnc.py             | 1 +
 5 files changed, 9 insertions(+)

diff --git a/tests/avocado/empty_cpu_model.py b/tests/avocado/empty_cpu_model.py
index 22f504418d..ffe27780a3 100644
--- a/tests/avocado/empty_cpu_model.py
+++ b/tests/avocado/empty_cpu_model.py
@@ -11,6 +11,9 @@
 
 class EmptyCPUModel(QemuSystemTest):
     def test(self):
+        """
+        :avocado: tags=arch:x86_64
+        """
         self.vm.add_args('-S', '-display', 'none', '-machine', 'none', '-cpu', '')
         self.vm.set_qmp_monitor(enabled=False)
         self.vm.launch()
diff --git a/tests/avocado/info_usernet.py b/tests/avocado/info_usernet.py
index dc01f74150..bafbc0e23e 100644
--- a/tests/avocado/info_usernet.py
+++ b/tests/avocado/info_usernet.py
@@ -16,6 +16,9 @@
 class InfoUsernet(QemuSystemTest):
 
     def test_hostfwd(self):
+        """
+        :avocado: tags=arch:x86_64
+        """
         self.vm.add_args('-netdev', 'user,id=vnet,hostfwd=:127.0.0.1:0-:22')
         self.vm.launch()
         res = self.vm.command('human-monitor-command',
diff --git a/tests/avocado/migration.py b/tests/avocado/migration.py
index 584d6ef53f..4e5516f425 100644
--- a/tests/avocado/migration.py
+++ b/tests/avocado/migration.py
@@ -22,6 +22,7 @@
 class Migration(QemuSystemTest):
     """
     :avocado: tags=migration
+    :avocado: tags=arch:x86_64
     """
 
     timeout = 10
diff --git a/tests/avocado/version.py b/tests/avocado/version.py
index ded7f039c1..be794b9354 100644
--- a/tests/avocado/version.py
+++ b/tests/avocado/version.py
@@ -15,6 +15,7 @@
 class Version(QemuSystemTest):
     """
     :avocado: tags=quick
+    :avocado: tags=arch:x86_64
     """
     def test_qmp_human_info_version(self):
         self.vm.add_args('-nodefaults')
diff --git a/tests/avocado/vnc.py b/tests/avocado/vnc.py
index 096432988f..1f80647414 100644
--- a/tests/avocado/vnc.py
+++ b/tests/avocado/vnc.py
@@ -14,6 +14,7 @@
 class Vnc(QemuSystemTest):
     """
     :avocado: tags=vnc,quick
+    :avocado: tags=arch:x86_64
     """
     def test_no_vnc(self):
         self.vm.add_args('-nodefaults', '-S')
-- 
2.30.2



^ permalink raw reply related

* [Intel-wired-lan] [syzbot] kernel BUG in pskb_expand_head
From: Marc Kleine-Budde @ 2022-01-05 14:04 UTC (permalink / raw)
  To: intel-wired-lan
In-Reply-To: <CANn89i+LbcWn3xoYU-eMjjmQPz0x1pSAat2OpF=i0+RByc-h4w@mail.gmail.com>

On 05.01.2022 05:59:35, Eric Dumazet wrote:
> On Wed, Jan 5, 2022 at 3:20 AM syzbot
> <syzbot+4c63f36709a642f801c5@syzkaller.appspotmail.com> wrote:
> >
> > syzbot has found a reproducer for the following issue on:
> >
> > HEAD commit:    c9e6606c7fe9 Linux 5.16-rc8
> > git tree:       upstream
> > console output: https://syzkaller.appspot.com/x/log.txt?x=148351c3b00000
> > kernel config:  https://syzkaller.appspot.com/x/.config?x=32f9fa260d7413b4
> > dashboard link: https://syzkaller.appspot.com/bug?extid=4c63f36709a642f801c5
> > compiler:       gcc (Debian 10.2.1-6) 10.2.1 20210110, GNU ld (GNU Binutils for Debian) 2.35.2
> > syz repro:      https://syzkaller.appspot.com/x/repro.syz?x=15435e2bb00000
> > C reproducer:   https://syzkaller.appspot.com/x/repro.c?x=12f4508db00000
> >
> 
> This C repro looks legit, bug should be in CAN layer.

ACK - it's bug in CAN's ISOTP

> > The issue was bisected to:
> >
> > commit e4b8954074f6d0db01c8c97d338a67f9389c042f
> > Author: Eric Dumazet <edumazet@google.com>
> > Date:   Tue Dec 7 01:30:37 2021 +0000
> >
> >     netlink: add net device refcount tracker to struct ethnl_req_info
> 
> Ignore this bisection, an unrelated commit whent in its way.

ACK - We have a RFC fix for this:

https://lore.kernel.org/all/20220105132429.1170627-1-mkl at pengutronix.de

regards,
Marc

-- 
Pengutronix e.K.                 | Marc Kleine-Budde           |
Embedded Linux                   | https://www.pengutronix.de  |
Vertretung West/Dortmund         | Phone: +49-231-2826-924     |
Amtsgericht Hildesheim, HRA 2686 | Fax:   +49-5121-206917-5555 |
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 488 bytes
Desc: not available
URL: <http://lists.osuosl.org/pipermail/intel-wired-lan/attachments/20220105/1a7af409/attachment.asc>

^ permalink raw reply


This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.