Skip to contentSkip to conversation

Add cnxk_gpio PMD

PATCH Superseded Tomasz Duszynski 5 participants 75 messages Nov 17, 2021 – Feb 22, 2022 Arm/Amlogic Meson SoC support

lore
Share & tools
lore
#0 lore raw

cover Add cnxk_gpio PMD

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.

Tomasz Duszynski (10):
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

 doc/guides/rawdevs/cnxk_gpio.rst           | 195 +++++++
 doc/guides/rawdevs/index.rst               |   1 +
 drivers/raw/cnxk_gpio/cnxk_gpio.c          | 633 +++++++++++++++++++++
 drivers/raw/cnxk_gpio/cnxk_gpio.h          |  31 +
 drivers/raw/cnxk_gpio/cnxk_gpio_irq.c      | 216 +++++++
 drivers/raw/cnxk_gpio/cnxk_gpio_selftest.c | 442 ++++++++++++++
 drivers/raw/cnxk_gpio/meson.build          |  11 +
 drivers/raw/cnxk_gpio/rte_pmd_cnxk_gpio.h  | 429 ++++++++++++++
 drivers/raw/cnxk_gpio/version.map          |   3 +
 drivers/raw/meson.build                    |   1 +
 10 files changed, 1962 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

#1 lore raw

PATCH 1/10 raw/cnxk_gpio: add GPIO driver skeleton

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.

---
 doc/guides/rawdevs/cnxk_gpio.rst  |  65 +++++++++
 doc/guides/rawdevs/index.rst      |   1 +
 drivers/raw/cnxk_gpio/cnxk_gpio.c | 235 ++++++++++++++++++++++++++++++
 drivers/raw/cnxk_gpio/cnxk_gpio.h |  20 +++
 drivers/raw/cnxk_gpio/meson.build |   8 +
 drivers/raw/cnxk_gpio/version.map |   3 +
 drivers/raw/meson.build           |   1 +
 7 files changed, 333 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
doc/guides/rawdevs/cnxk_gpio.rst new file +65 -0
new file mode 100644
index 0000000000..868302d07f
@@ -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.
doc/guides/rawdevs/index.rst +1 -0
index b6cf917443..0c02da6e90 100644
@@ -12,6 +12,7 @@ application through rawdev API.
     :numbered:
 
     cnxk_bphy
+    cnxk_gpio
     dpaa2_cmdif
     dpaa2_qdma
     ifpga
drivers/raw/cnxk_gpio/cnxk_gpio.c new file +235 -0

235 lines not on this page · raw message

drivers/raw/cnxk_gpio/cnxk_gpio.h new file +20 -0
new file mode 100644
index 0000000000..0ee9789a01
@@ -0,0 +1,20 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(C) 2021 Marvell.
+ */
+
+#ifndef _CNXK_GPIO_H_
+#define _CNXK_GPIO_H_
+
+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_ */
drivers/raw/cnxk_gpio/meson.build new file +8 -0
new file mode 100644
index 0000000000..9a7e716c1e
@@ -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',
+)
drivers/raw/cnxk_gpio/version.map new file +3 -0
new file mode 100644
index 0000000000..4a76d1d52d
@@ -0,0 +1,3 @@
+DPDK_21 {
+	local: *;
+};
drivers/raw/meson.build +1 -0
index 87694a758e..4b52e93945 100644
@@ -7,6 +7,7 @@ endif
 
 drivers = [
         'cnxk_bphy',
+	'cnxk_gpio',
         'dpaa2_cmdif',
         'dpaa2_qdma',
         'ifpga',
Signature · 1 line
2.25.1
#2 lore raw

PATCH 2/10 raw/cnxk_gpio: support reading default queue conf

In reply to Tomasz Duszynski

Add support for reading default queue configuration.

---
 drivers/raw/cnxk_gpio/cnxk_gpio.c | 19 +++++++++++++++++++
 1 file changed, 19 insertions(+)
drivers/raw/cnxk_gpio/cnxk_gpio.c +19 -0
index bcce4b8fb7..deedf98af2 100644
@@ -134,7 +134,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
Signature · 1 line
2.25.1
#3 lore raw

PATCH 3/10 raw/cnxk_gpio: support reading queue count

In reply to Tomasz Duszynski

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

---
 drivers/raw/cnxk_gpio/cnxk_gpio.c | 9 +++++++++
 1 file changed, 9 insertions(+)
drivers/raw/cnxk_gpio/cnxk_gpio.c +9 -0
index deedf98af2..84be7f861e 100644
@@ -152,8 +152,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
Signature · 1 line
2.25.1
#4 lore raw

PATCH 4/10 raw/cnxk_gpio: support queue setup

In reply to Tomasz Duszynski

Add support for queue setup.

---
 drivers/raw/cnxk_gpio/cnxk_gpio.c | 80 +++++++++++++++++++++++++++++++
 1 file changed, 80 insertions(+)
drivers/raw/cnxk_gpio/cnxk_gpio.c +80 -0
index 84be7f861e..98b5dd9cd8 100644
@@ -134,6 +134,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)
@@ -163,6 +242,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
Signature · 1 line
2.25.1
#5 lore raw

PATCH 5/10 raw/cnxk_gpio: support queue release

In reply to Tomasz Duszynski

Add support for queue release.

---
 drivers/raw/cnxk_gpio/cnxk_gpio.c | 34 +++++++++++++++++++++++++++++++
 1 file changed, 34 insertions(+)
drivers/raw/cnxk_gpio/cnxk_gpio.c +34 -0
index 98b5dd9cd8..8ac3c5e1be 100644
@@ -213,6 +213,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)
@@ -243,6 +266,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
@@ -316,6 +340,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);
 
@@ -328,6 +354,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);
 
Signature · 1 line
2.25.1
#6 lore raw

PATCH 6/10 raw/cnxk_gpio: support enqueuing buffers

In reply to Tomasz Duszynski

Add dummy support for enqueuing buffers.

---
 drivers/raw/cnxk_gpio/cnxk_gpio.c         | 46 +++++++++++++++++++++++
 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, 86 insertions(+)
 create mode 100644 drivers/raw/cnxk_gpio/rte_pmd_cnxk_gpio.h
drivers/raw/cnxk_gpio/cnxk_gpio.c +46 -0
index 8ac3c5e1be..c08ccdfbb8 100644
@@ -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"
@@ -262,7 +263,52 @@ 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;
+
+	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 0;
+}
+
+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,
drivers/raw/cnxk_gpio/cnxk_gpio.h +1 -0
index 0ee9789a01..1eadde965e 100644
@@ -7,6 +7,7 @@
 
 struct cnxk_gpio {
 	struct cnxk_gpiochip *gpiochip;
+	void *rsp;
 	int num;
 };
 
drivers/raw/cnxk_gpio/meson.build +1 -0
index 9a7e716c1e..3fbfdd838c 100644
@@ -6,3 +6,4 @@ deps += ['bus_vdev', 'common_cnxk', 'rawdev', 'kvargs']
 sources = files(
         'cnxk_gpio.c',
 )
+headers = files('rte_pmd_cnxk_gpio.h')
drivers/raw/cnxk_gpio/rte_pmd_cnxk_gpio.h new file +38 -0
new file mode 100644
index 0000000000..c71065e10c
@@ -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_ */
Signature · 1 line
2.25.1
#7 lore raw

PATCH 7/10 raw/cnxk_gpio: support dequeuing buffers

In reply to Tomasz Duszynski

Add support for dequeuing buffers.

---
 drivers/raw/cnxk_gpio/cnxk_gpio.c | 26 ++++++++++++++++++++++++++
 1 file changed, 26 insertions(+)
drivers/raw/cnxk_gpio/cnxk_gpio.c +26 -0
index c08ccdfbb8..244a625822 100644
@@ -307,8 +307,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,
Signature · 1 line
2.25.1
#8 lore raw

PATCH 8/10 raw/cnxk_gpio: support standard GPIO operations

In reply to Tomasz Duszynski

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

---
 doc/guides/rawdevs/cnxk_gpio.rst          |  98 ++++++++
 drivers/raw/cnxk_gpio/cnxk_gpio.c         | 146 +++++++++++
 drivers/raw/cnxk_gpio/rte_pmd_cnxk_gpio.h | 279 +++++++++++++++++++++-
 3 files changed, 521 insertions(+), 2 deletions(-)
doc/guides/rawdevs/cnxk_gpio.rst +98 -0
index 868302d07f..f6c3c942c5 100644
@@ -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.
drivers/raw/cnxk_gpio/cnxk_gpio.c +146 -0

159 lines not on this page · raw message

drivers/raw/cnxk_gpio/rte_pmd_cnxk_gpio.h +277 -2

297 lines not on this page · raw message

Signature · 1 line
2.25.1
#9 lore raw

PATCH 9/10 raw/cnxk_gpio: support custom irq handlers

In reply to Tomasz Duszynski

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

---
 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
doc/guides/rawdevs/cnxk_gpio.rst +21 -0
index f6c3c942c5..ad93ec0d44 100644
@@ -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.
drivers/raw/cnxk_gpio/cnxk_gpio.c +37 -0
index c09bc5d56e..d39d203245 100644
@@ -335,6 +335,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)
 {
@@ -416,6 +438,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;
 	}
@@ -519,6 +548,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);
@@ -577,10 +610,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;
drivers/raw/cnxk_gpio/cnxk_gpio.h +8 -0
index 1eadde965e..a2e44fefbe 100644
@@ -9,6 +9,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 {
@@ -18,4 +21,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_ */
drivers/raw/cnxk_gpio/cnxk_gpio_irq.c new file +216 -0

216 lines not on this page · raw message

drivers/raw/cnxk_gpio/meson.build +1 -0
index 3fbfdd838c..9b55f029c7 100644
@@ -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')
drivers/raw/cnxk_gpio/rte_pmd_cnxk_gpio.h +116 -0

134 lines not on this page · raw message

Signature · 1 line
2.25.1
#10 lore raw

PATCH 10/10 raw/cnxk_gpio: support selftest

In reply to Tomasz Duszynski

Add support for performing selftest.

---
 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 | 442 +++++++++++++++++++++
 drivers/raw/cnxk_gpio/meson.build          |   1 +
 5 files changed, 457 insertions(+)
 create mode 100644 drivers/raw/cnxk_gpio/cnxk_gpio_selftest.c
doc/guides/rawdevs/cnxk_gpio.rst +11 -0
index ad93ec0d44..c03a5b937c 100644
@@ -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.
drivers/raw/cnxk_gpio/cnxk_gpio.c +1 -0
index d39d203245..fa81b45f89 100644
@@ -514,6 +514,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
drivers/raw/cnxk_gpio/cnxk_gpio.h +2 -0
index a2e44fefbe..dfbad47c51 100644
@@ -21,6 +21,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);
drivers/raw/cnxk_gpio/cnxk_gpio_selftest.c new file +442 -0

442 lines not on this page · raw message

drivers/raw/cnxk_gpio/meson.build +1 -0
index 9b55f029c7..a75a5b9084 100644
@@ -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')
Signature · 1 line
2.25.1
#11 lore raw

Re: [PATCH 10/10] raw/cnxk_gpio: support selftest

drivers/raw/cnxk_gpio/cnxk_gpio_selftest.c line 143

Quoted 11 lines · On Wed, 17 Nov 2021 01:21:55 +0100 Tomasz Duszynski <[email protected]>…
drivers/raw/cnxk_gpio/cnxk_gpio_selftest.c new file +11 -0
+static int
+cnxk_gpio_open_mem(void)
+{
+	int ret = 0, fd;
+
+	fd = open("/dev/mem", O_RDWR | O_SYNC);
+	if (fd < 0)
+		ret = -errno;
+
+	return ret;
+}

This is a dangerous security violation and most distributions will not allow it.

Also, why are you opening it? The code is forgetting the file descriptor so it is useless anyway.

#12 lore raw

v2 cover Add cnxk_gpio PMD

In reply to Tomasz Duszynski

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.

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

Tomasz Duszynski (10):
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

 doc/guides/rawdevs/cnxk_gpio.rst           | 195 +++++++
 doc/guides/rawdevs/index.rst               |   1 +
 drivers/raw/cnxk_gpio/cnxk_gpio.c          | 633 +++++++++++++++++++++
 drivers/raw/cnxk_gpio/cnxk_gpio.h          |  33 ++
 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  | 429 ++++++++++++++
 drivers/raw/cnxk_gpio/version.map          |   3 +
 drivers/raw/meson.build                    |   1 +
 10 files changed, 1908 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

#13 lore raw

PATCH v2 1/10 raw/cnxk_gpio: add GPIO driver skeleton

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.

---
 doc/guides/rawdevs/cnxk_gpio.rst  |  65 +++++++++
 doc/guides/rawdevs/index.rst      |   1 +
 drivers/raw/cnxk_gpio/cnxk_gpio.c | 235 ++++++++++++++++++++++++++++++
 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, 335 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
doc/guides/rawdevs/cnxk_gpio.rst new file +65 -0
new file mode 100644
index 0000000000..868302d07f
@@ -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.
doc/guides/rawdevs/index.rst +1 -0
index b6cf917443..0c02da6e90 100644
@@ -12,6 +12,7 @@ application through rawdev API.
     :numbered:
 
     cnxk_bphy
+    cnxk_gpio
     dpaa2_cmdif
     dpaa2_qdma
     ifpga
drivers/raw/cnxk_gpio/cnxk_gpio.c new file +235 -0

235 lines not on this page · raw message

drivers/raw/cnxk_gpio/cnxk_gpio.h new file +22 -0
new file mode 100644
index 0000000000..4dae8316ba
@@ -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_ */
drivers/raw/cnxk_gpio/meson.build new file +8 -0
new file mode 100644
index 0000000000..9a7e716c1e
@@ -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',
+)
drivers/raw/cnxk_gpio/version.map new file +3 -0
new file mode 100644
index 0000000000..4a76d1d52d
@@ -0,0 +1,3 @@
+DPDK_21 {
+	local: *;
+};
drivers/raw/meson.build +1 -0
index 87694a758e..4b52e93945 100644
@@ -7,6 +7,7 @@ endif
 
 drivers = [
         'cnxk_bphy',
+	'cnxk_gpio',
         'dpaa2_cmdif',
         'dpaa2_qdma',
         'ifpga',
Signature · 1 line
2.25.1
#14 lore raw

PATCH v2 2/10 raw/cnxk_gpio: support reading default queue conf

In reply to Tomasz Duszynski

Add support for reading default queue configuration.

---
 drivers/raw/cnxk_gpio/cnxk_gpio.c | 19 +++++++++++++++++++
 1 file changed, 19 insertions(+)
drivers/raw/cnxk_gpio/cnxk_gpio.c +19 -0
index bcce4b8fb7..deedf98af2 100644
@@ -134,7 +134,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
Signature · 1 line
2.25.1
#15 lore raw

PATCH v2 3/10 raw/cnxk_gpio: support reading queue count

In reply to Tomasz Duszynski

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

---
 drivers/raw/cnxk_gpio/cnxk_gpio.c | 9 +++++++++
 1 file changed, 9 insertions(+)
drivers/raw/cnxk_gpio/cnxk_gpio.c +9 -0
index deedf98af2..84be7f861e 100644
@@ -152,8 +152,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
Signature · 1 line
2.25.1
#16 lore raw

PATCH v2 4/10 raw/cnxk_gpio: support queue setup

In reply to Tomasz Duszynski

Add support for queue setup.

---
 drivers/raw/cnxk_gpio/cnxk_gpio.c | 80 +++++++++++++++++++++++++++++++
 1 file changed, 80 insertions(+)
drivers/raw/cnxk_gpio/cnxk_gpio.c +80 -0
index 84be7f861e..98b5dd9cd8 100644
@@ -134,6 +134,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)
@@ -163,6 +242,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
Signature · 1 line
2.25.1
#17 lore raw

PATCH v2 5/10 raw/cnxk_gpio: support queue release

In reply to Tomasz Duszynski

Add support for queue release.

---
 drivers/raw/cnxk_gpio/cnxk_gpio.c | 34 +++++++++++++++++++++++++++++++
 1 file changed, 34 insertions(+)
drivers/raw/cnxk_gpio/cnxk_gpio.c +34 -0
index 98b5dd9cd8..8ac3c5e1be 100644
@@ -213,6 +213,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)
@@ -243,6 +266,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
@@ -316,6 +340,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);
 
@@ -328,6 +354,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);
 
Signature · 1 line
2.25.1
#18 lore raw

PATCH v2 6/10 raw/cnxk_gpio: support enqueuing buffers

In reply to Tomasz Duszynski

Add dummy support for enqueuing buffers.

---
 drivers/raw/cnxk_gpio/cnxk_gpio.c         | 46 +++++++++++++++++++++++
 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, 86 insertions(+)
 create mode 100644 drivers/raw/cnxk_gpio/rte_pmd_cnxk_gpio.h
drivers/raw/cnxk_gpio/cnxk_gpio.c +46 -0
index 8ac3c5e1be..c08ccdfbb8 100644
@@ -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"
@@ -262,7 +263,52 @@ 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;
+
+	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 0;
+}
+
+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,
drivers/raw/cnxk_gpio/cnxk_gpio.h +1 -0
index 4dae8316ba..6b54ebe6e6 100644
@@ -9,6 +9,7 @@ struct cnxk_gpiochip;
 
 struct cnxk_gpio {
 	struct cnxk_gpiochip *gpiochip;
+	void *rsp;
 	int num;
 };
 
drivers/raw/cnxk_gpio/meson.build +1 -0
index 9a7e716c1e..3fbfdd838c 100644
@@ -6,3 +6,4 @@ deps += ['bus_vdev', 'common_cnxk', 'rawdev', 'kvargs']
 sources = files(
         'cnxk_gpio.c',
 )
+headers = files('rte_pmd_cnxk_gpio.h')
drivers/raw/cnxk_gpio/rte_pmd_cnxk_gpio.h new file +38 -0
new file mode 100644
index 0000000000..c71065e10c
@@ -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_ */
Signature · 1 line
2.25.1
#19 lore raw

PATCH v2 7/10 raw/cnxk_gpio: support dequeuing buffers

In reply to Tomasz Duszynski

Add support for dequeuing buffers.

---
 drivers/raw/cnxk_gpio/cnxk_gpio.c | 26 ++++++++++++++++++++++++++
 1 file changed, 26 insertions(+)
drivers/raw/cnxk_gpio/cnxk_gpio.c +26 -0
index c08ccdfbb8..244a625822 100644
@@ -307,8 +307,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,
Signature · 1 line
2.25.1
#20 lore raw

PATCH v2 8/10 raw/cnxk_gpio: support standard GPIO operations

In reply to Tomasz Duszynski

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

---
 doc/guides/rawdevs/cnxk_gpio.rst          |  98 ++++++++
 drivers/raw/cnxk_gpio/cnxk_gpio.c         | 146 +++++++++++
 drivers/raw/cnxk_gpio/rte_pmd_cnxk_gpio.h | 279 +++++++++++++++++++++-
 3 files changed, 521 insertions(+), 2 deletions(-)
doc/guides/rawdevs/cnxk_gpio.rst +98 -0
index 868302d07f..f6c3c942c5 100644
@@ -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.
drivers/raw/cnxk_gpio/cnxk_gpio.c +146 -0

159 lines not on this page · raw message

drivers/raw/cnxk_gpio/rte_pmd_cnxk_gpio.h +277 -2

297 lines not on this page · raw message

Signature · 1 line
2.25.1
#21 lore raw

PATCH v2 9/10 raw/cnxk_gpio: support custom irq handlers

In reply to Tomasz Duszynski

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

---
 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
doc/guides/rawdevs/cnxk_gpio.rst +21 -0
index f6c3c942c5..ad93ec0d44 100644
@@ -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.
drivers/raw/cnxk_gpio/cnxk_gpio.c +37 -0
index c09bc5d56e..d39d203245 100644
@@ -335,6 +335,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)
 {
@@ -416,6 +438,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;
 	}
@@ -519,6 +548,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);
@@ -577,10 +610,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;
drivers/raw/cnxk_gpio/cnxk_gpio.h +8 -0
index 6b54ebe6e6..c052ca5735 100644
@@ -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_ */
drivers/raw/cnxk_gpio/cnxk_gpio_irq.c new file +216 -0

216 lines not on this page · raw message

drivers/raw/cnxk_gpio/meson.build +1 -0
index 3fbfdd838c..9b55f029c7 100644
@@ -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')
drivers/raw/cnxk_gpio/rte_pmd_cnxk_gpio.h +116 -0

134 lines not on this page · raw message

Signature · 1 line
2.25.1
#22 lore raw

PATCH v2 10/10 raw/cnxk_gpio: support selftest

In reply to Tomasz Duszynski

Add support for performing selftest.

---
 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
doc/guides/rawdevs/cnxk_gpio.rst +11 -0
index ad93ec0d44..c03a5b937c 100644
@@ -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.
drivers/raw/cnxk_gpio/cnxk_gpio.c +1 -0
index d39d203245..fa81b45f89 100644
@@ -514,6 +514,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
drivers/raw/cnxk_gpio/cnxk_gpio.h +2 -0
index c052ca5735..1b31b5a486 100644
@@ -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);
drivers/raw/cnxk_gpio/cnxk_gpio_selftest.c new file +386 -0

386 lines not on this page · raw message

drivers/raw/cnxk_gpio/meson.build +1 -0
index 9b55f029c7..a75a5b9084 100644
@@ -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')
Signature · 1 line
2.25.1
#23 lore raw

v3 cover Add cnxk_gpio PMD

In reply to Tomasz Duszynski

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.

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 (10):
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

 doc/guides/rawdevs/cnxk_gpio.rst           | 195 +++++++
 doc/guides/rawdevs/index.rst               |   1 +
 drivers/raw/cnxk_gpio/cnxk_gpio.c          | 633 +++++++++++++++++++++
 drivers/raw/cnxk_gpio/cnxk_gpio.h          |  33 ++
 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  | 429 ++++++++++++++
 drivers/raw/cnxk_gpio/version.map          |   3 +
 drivers/raw/meson.build                    |   1 +
 10 files changed, 1908 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

#24 lore raw

PATCH v3 1/10 raw/cnxk_gpio: add GPIO driver skeleton

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.

---
 doc/guides/rawdevs/cnxk_gpio.rst  |  65 +++++++++
 doc/guides/rawdevs/index.rst      |   1 +
 drivers/raw/cnxk_gpio/cnxk_gpio.c | 235 ++++++++++++++++++++++++++++++
 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, 335 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
doc/guides/rawdevs/cnxk_gpio.rst new file +65 -0
new file mode 100644
index 0000000000..868302d07f
@@ -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.
doc/guides/rawdevs/index.rst +1 -0
index b6cf917443..0c02da6e90 100644
@@ -12,6 +12,7 @@ application through rawdev API.
     :numbered:
 
     cnxk_bphy
+    cnxk_gpio
     dpaa2_cmdif
     dpaa2_qdma
     ifpga
drivers/raw/cnxk_gpio/cnxk_gpio.c new file +235 -0

235 lines not on this page · raw message

drivers/raw/cnxk_gpio/cnxk_gpio.h new file +22 -0
new file mode 100644
index 0000000000..4dae8316ba
@@ -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_ */
drivers/raw/cnxk_gpio/meson.build new file +8 -0
new file mode 100644
index 0000000000..9a7e716c1e
@@ -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',
+)
drivers/raw/cnxk_gpio/version.map new file +3 -0
new file mode 100644
index 0000000000..4a76d1d52d
@@ -0,0 +1,3 @@
+DPDK_21 {
+	local: *;
+};
drivers/raw/meson.build +1 -0
index 87694a758e..05e7de1bfe 100644
@@ -7,6 +7,7 @@ endif
 
 drivers = [
         'cnxk_bphy',
+        'cnxk_gpio',
         'dpaa2_cmdif',
         'dpaa2_qdma',
         'ifpga',
Signature · 1 line
2.25.1
#25 lore raw

PATCH v3 2/10 raw/cnxk_gpio: support reading default queue conf

In reply to Tomasz Duszynski

Add support for reading default queue configuration.

---
 drivers/raw/cnxk_gpio/cnxk_gpio.c | 19 +++++++++++++++++++
 1 file changed, 19 insertions(+)
drivers/raw/cnxk_gpio/cnxk_gpio.c +19 -0
index bcce4b8fb7..deedf98af2 100644
@@ -134,7 +134,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
Signature · 1 line
2.25.1
#26 lore raw

PATCH v3 3/10 raw/cnxk_gpio: support reading queue count

In reply to Tomasz Duszynski

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

---
 drivers/raw/cnxk_gpio/cnxk_gpio.c | 9 +++++++++
 1 file changed, 9 insertions(+)
drivers/raw/cnxk_gpio/cnxk_gpio.c +9 -0
index deedf98af2..84be7f861e 100644
@@ -152,8 +152,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
Signature · 1 line
2.25.1
#27 lore raw

PATCH v3 4/10 raw/cnxk_gpio: support queue setup

In reply to Tomasz Duszynski

Add support for queue setup.

---
 drivers/raw/cnxk_gpio/cnxk_gpio.c | 80 +++++++++++++++++++++++++++++++
 1 file changed, 80 insertions(+)
drivers/raw/cnxk_gpio/cnxk_gpio.c +80 -0
index 84be7f861e..98b5dd9cd8 100644
@@ -134,6 +134,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)
@@ -163,6 +242,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
Signature · 1 line
2.25.1
#28 lore raw

PATCH v3 5/10 raw/cnxk_gpio: support queue release

In reply to Tomasz Duszynski

Add support for queue release.

---
 drivers/raw/cnxk_gpio/cnxk_gpio.c | 34 +++++++++++++++++++++++++++++++
 1 file changed, 34 insertions(+)
drivers/raw/cnxk_gpio/cnxk_gpio.c +34 -0
index 98b5dd9cd8..8ac3c5e1be 100644
@@ -213,6 +213,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)
@@ -243,6 +266,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
@@ -316,6 +340,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);
 
@@ -328,6 +354,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);
 
Signature · 1 line
2.25.1
#29 lore raw

PATCH v3 6/10 raw/cnxk_gpio: support enqueuing buffers

In reply to Tomasz Duszynski

Add dummy support for enqueuing buffers.

---
 drivers/raw/cnxk_gpio/cnxk_gpio.c         | 46 +++++++++++++++++++++++
 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, 86 insertions(+)
 create mode 100644 drivers/raw/cnxk_gpio/rte_pmd_cnxk_gpio.h
drivers/raw/cnxk_gpio/cnxk_gpio.c +46 -0
index 8ac3c5e1be..9477e7293a 100644
@@ -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"
@@ -262,7 +263,52 @@ 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;
+
+	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,
drivers/raw/cnxk_gpio/cnxk_gpio.h +1 -0
index 4dae8316ba..6b54ebe6e6 100644
@@ -9,6 +9,7 @@ struct cnxk_gpiochip;
 
 struct cnxk_gpio {
 	struct cnxk_gpiochip *gpiochip;
+	void *rsp;
 	int num;
 };
 
drivers/raw/cnxk_gpio/meson.build +1 -0
index 9a7e716c1e..3fbfdd838c 100644
@@ -6,3 +6,4 @@ deps += ['bus_vdev', 'common_cnxk', 'rawdev', 'kvargs']
 sources = files(
         'cnxk_gpio.c',
 )
+headers = files('rte_pmd_cnxk_gpio.h')
drivers/raw/cnxk_gpio/rte_pmd_cnxk_gpio.h new file +38 -0
new file mode 100644
index 0000000000..c71065e10c
@@ -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_ */
Signature · 1 line
2.25.1
#30 lore raw

PATCH v3 7/10 raw/cnxk_gpio: support dequeuing buffers

In reply to Tomasz Duszynski

Add support for dequeuing buffers.

---
 drivers/raw/cnxk_gpio/cnxk_gpio.c | 26 ++++++++++++++++++++++++++
 1 file changed, 26 insertions(+)
drivers/raw/cnxk_gpio/cnxk_gpio.c +26 -0
index 9477e7293a..570d9abb17 100644
@@ -307,8 +307,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,
Signature · 1 line
2.25.1
#31 lore raw

PATCH v3 8/10 raw/cnxk_gpio: support standard GPIO operations

In reply to Tomasz Duszynski

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

---
 doc/guides/rawdevs/cnxk_gpio.rst          |  98 ++++++++
 drivers/raw/cnxk_gpio/cnxk_gpio.c         | 146 +++++++++++
 drivers/raw/cnxk_gpio/rte_pmd_cnxk_gpio.h | 279 +++++++++++++++++++++-
 3 files changed, 521 insertions(+), 2 deletions(-)
doc/guides/rawdevs/cnxk_gpio.rst +98 -0
index 868302d07f..f6c3c942c5 100644
@@ -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.
drivers/raw/cnxk_gpio/cnxk_gpio.c +146 -0

159 lines not on this page · raw message

drivers/raw/cnxk_gpio/rte_pmd_cnxk_gpio.h +277 -2

297 lines not on this page · raw message

Signature · 1 line
2.25.1
#32 lore raw

PATCH v3 9/10 raw/cnxk_gpio: support custom irq handlers

In reply to Tomasz Duszynski

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

---
 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
doc/guides/rawdevs/cnxk_gpio.rst +21 -0
index f6c3c942c5..ad93ec0d44 100644
@@ -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.
drivers/raw/cnxk_gpio/cnxk_gpio.c +37 -0
index fa5b1359d0..f3fdd5a380 100644
@@ -335,6 +335,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)
 {
@@ -416,6 +438,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;
 	}
@@ -519,6 +548,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);
@@ -577,10 +610,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;
drivers/raw/cnxk_gpio/cnxk_gpio.h +8 -0
index 6b54ebe6e6..c052ca5735 100644
@@ -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_ */
drivers/raw/cnxk_gpio/cnxk_gpio_irq.c new file +216 -0

216 lines not on this page · raw message

drivers/raw/cnxk_gpio/meson.build +1 -0
index 3fbfdd838c..9b55f029c7 100644
@@ -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')
drivers/raw/cnxk_gpio/rte_pmd_cnxk_gpio.h +116 -0

134 lines not on this page · raw message

Signature · 1 line
2.25.1
#33 lore raw

PATCH v3 10/10 raw/cnxk_gpio: support selftest

In reply to Tomasz Duszynski

Add support for performing selftest.

---
 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
doc/guides/rawdevs/cnxk_gpio.rst +11 -0
index ad93ec0d44..c03a5b937c 100644
@@ -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.
drivers/raw/cnxk_gpio/cnxk_gpio.c +1 -0
index f3fdd5a380..c9f87a315a 100644
@@ -514,6 +514,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
drivers/raw/cnxk_gpio/cnxk_gpio.h +2 -0
index c052ca5735..1b31b5a486 100644
@@ -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);
drivers/raw/cnxk_gpio/cnxk_gpio_selftest.c new file +386 -0

386 lines not on this page · raw message

drivers/raw/cnxk_gpio/meson.build +1 -0
index 9b55f029c7..a75a5b9084 100644
@@ -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')
Signature · 1 line
2.25.1
#34 lore raw

v4 cover Add cnxk_gpio

In reply to Tomasz Duszynski

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

#35 lore raw

PATCH v4 1/11 raw/cnxk_gpio: add GPIO driver skeleton

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.

---
 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
doc/guides/rawdevs/cnxk_gpio.rst new file +65 -0
new file mode 100644
index 0000000000..868302d07f
@@ -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.
doc/guides/rawdevs/index.rst +1 -0
index b6cf917443..0c02da6e90 100644
@@ -12,6 +12,7 @@ application through rawdev API.
     :numbered:
 
     cnxk_bphy
+    cnxk_gpio
     dpaa2_cmdif
     dpaa2_qdma
     ifpga
drivers/raw/cnxk_gpio/cnxk_gpio.c new file +239 -0

239 lines not on this page · raw message

drivers/raw/cnxk_gpio/cnxk_gpio.h new file +22 -0
new file mode 100644
index 0000000000..4dae8316ba
@@ -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_ */
drivers/raw/cnxk_gpio/meson.build new file +8 -0
new file mode 100644
index 0000000000..9a7e716c1e
@@ -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',
+)
drivers/raw/cnxk_gpio/version.map new file +3 -0
new file mode 100644
index 0000000000..4a76d1d52d
@@ -0,0 +1,3 @@
+DPDK_21 {
+	local: *;
+};
drivers/raw/meson.build +1 -0
index 87694a758e..05e7de1bfe 100644
@@ -7,6 +7,7 @@ endif
 
 drivers = [
         'cnxk_bphy',
+        'cnxk_gpio',
         'dpaa2_cmdif',
         'dpaa2_qdma',
         'ifpga',
Signature · 1 line
2.25.1
#36 lore raw

PATCH v4 2/11 raw/cnxk_gpio: support reading default queue conf

In reply to Tomasz Duszynski

Add support for reading default queue configuration.

---
 drivers/raw/cnxk_gpio/cnxk_gpio.c | 19 +++++++++++++++++++
 1 file changed, 19 insertions(+)
drivers/raw/cnxk_gpio/cnxk_gpio.c +19 -0
index 881615d62e..f80788f7fb 100644
@@ -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
Signature · 1 line
2.25.1
#37 lore raw

PATCH v4 3/11 raw/cnxk_gpio: support reading queue count

In reply to Tomasz Duszynski

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

---
 drivers/raw/cnxk_gpio/cnxk_gpio.c | 9 +++++++++
 1 file changed, 9 insertions(+)
drivers/raw/cnxk_gpio/cnxk_gpio.c +9 -0
index f80788f7fb..3455d6258c 100644
@@ -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
Signature · 1 line
2.25.1
#38 lore raw

PATCH v4 4/11 raw/cnxk_gpio: support queue setup

In reply to Tomasz Duszynski

Add support for queue setup.

---
 drivers/raw/cnxk_gpio/cnxk_gpio.c | 80 +++++++++++++++++++++++++++++++
 1 file changed, 80 insertions(+)
drivers/raw/cnxk_gpio/cnxk_gpio.c +80 -0
index 3455d6258c..c1e74fad43 100644
@@ -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
Signature · 1 line
2.25.1
#39 lore raw

PATCH v4 5/11 raw/cnxk_gpio: support queue release

In reply to Tomasz Duszynski

Add support for queue release.

---
 drivers/raw/cnxk_gpio/cnxk_gpio.c | 34 +++++++++++++++++++++++++++++++
 1 file changed, 34 insertions(+)
drivers/raw/cnxk_gpio/cnxk_gpio.c +34 -0
index c1e74fad43..71f568f7a4 100644
@@ -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);
 
Signature · 1 line
2.25.1
#40 lore raw

PATCH v4 6/11 raw/cnxk_gpio: support enqueuing buffers

In reply to Tomasz Duszynski

Add dummy support for enqueuing buffers.

---
 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
drivers/raw/cnxk_gpio/cnxk_gpio.c +47 -0
index 71f568f7a4..235f0d6f7a 100644
@@ -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,
drivers/raw/cnxk_gpio/cnxk_gpio.h +1 -0
index 4dae8316ba..6b54ebe6e6 100644
@@ -9,6 +9,7 @@ struct cnxk_gpiochip;
 
 struct cnxk_gpio {
 	struct cnxk_gpiochip *gpiochip;
+	void *rsp;
 	int num;
 };
 
drivers/raw/cnxk_gpio/meson.build +1 -0
index 9a7e716c1e..3fbfdd838c 100644
@@ -6,3 +6,4 @@ deps += ['bus_vdev', 'common_cnxk', 'rawdev', 'kvargs']
 sources = files(
         'cnxk_gpio.c',
 )
+headers = files('rte_pmd_cnxk_gpio.h')
drivers/raw/cnxk_gpio/rte_pmd_cnxk_gpio.h new file +38 -0
new file mode 100644
index 0000000000..c71065e10c
@@ -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_ */
Signature · 1 line
2.25.1
#41 lore raw

PATCH v4 7/11 raw/cnxk_gpio: support dequeuing buffers

In reply to Tomasz Duszynski

Add support for dequeuing buffers.

---
 drivers/raw/cnxk_gpio/cnxk_gpio.c | 26 ++++++++++++++++++++++++++
 1 file changed, 26 insertions(+)
drivers/raw/cnxk_gpio/cnxk_gpio.c +26 -0
index 235f0d6f7a..909fa9d390 100644
@@ -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,
Signature · 1 line
2.25.1
#42 lore raw

PATCH v4 8/11 raw/cnxk_gpio: support standard GPIO operations

In reply to Tomasz Duszynski

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

---
 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(-)
doc/guides/rawdevs/cnxk_gpio.rst +98 -0
index 868302d07f..f6c3c942c5 100644
@@ -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.
drivers/raw/cnxk_gpio/cnxk_gpio.c +146 -1

160 lines not on this page · raw message

drivers/raw/cnxk_gpio/rte_pmd_cnxk_gpio.h +277 -2

297 lines not on this page · raw message

Signature · 1 line
2.25.1
#43 lore raw

PATCH v4 9/11 raw/cnxk_gpio: support custom irq handlers

In reply to Tomasz Duszynski

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

---
 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
doc/guides/rawdevs/cnxk_gpio.rst +21 -0
index f6c3c942c5..ad93ec0d44 100644
@@ -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.
drivers/raw/cnxk_gpio/cnxk_gpio.c +37 -0
index e24d8c1b6e..b30427c01c 100644
@@ -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;
drivers/raw/cnxk_gpio/cnxk_gpio.h +8 -0
index 6b54ebe6e6..c052ca5735 100644
@@ -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_ */
drivers/raw/cnxk_gpio/cnxk_gpio_irq.c new file +216 -0

216 lines not on this page · raw message

drivers/raw/cnxk_gpio/meson.build +1 -0
index 3fbfdd838c..9b55f029c7 100644
@@ -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')
drivers/raw/cnxk_gpio/rte_pmd_cnxk_gpio.h +116 -0

134 lines not on this page · raw message

Signature · 1 line
2.25.1
#44 lore raw

PATCH v4 10/11 raw/cnxk_gpio: support selftest

In reply to Tomasz Duszynski

Add support for performing selftest.

---
 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
doc/guides/rawdevs/cnxk_gpio.rst +11 -0
index ad93ec0d44..c03a5b937c 100644
@@ -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.
drivers/raw/cnxk_gpio/cnxk_gpio.c +1 -0
index b30427c01c..16a886b693 100644
@@ -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
drivers/raw/cnxk_gpio/cnxk_gpio.h +2 -0
index c052ca5735..1b31b5a486 100644
@@ -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);
drivers/raw/cnxk_gpio/cnxk_gpio_selftest.c new file +386 -0

386 lines not on this page · raw message

drivers/raw/cnxk_gpio/meson.build +1 -0
index 9b55f029c7..a75a5b9084 100644
@@ -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')
Signature · 1 line
2.25.1
#45 lore raw

PATCH v4 11/11 raw/cnxk_gpio: add option to allow using subset of GPIOs

In reply to Tomasz Duszynski

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.

---
 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(-)
doc/guides/rawdevs/cnxk_gpio.rst +5 -0
index c03a5b937c..adff535a77 100644
@@ -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.
 
drivers/raw/cnxk_gpio/cnxk_gpio.c +145 -28

323 lines not on this page · raw message

drivers/raw/cnxk_gpio/cnxk_gpio.h +2 -0
index 1b31b5a486..e62f78a760 100644
@@ -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);
drivers/raw/cnxk_gpio/cnxk_gpio_selftest.c +10 -10
index 6502902f86..303931fa0f 100644
@@ -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;
 
drivers/raw/cnxk_gpio/rte_pmd_cnxk_gpio.h +8 -0
index e3096dc14f..80a37be9c7 100644
@@ -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 */
Signature · 1 line
2.25.1
#46 lore raw

Re: [PATCH v4 00/11] Add cnxk_gpio

In reply to Tomasz Duszynski
Quoted 33 lines · Tomasz Duszynski

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

Quoted 1 line
 doc/guides/rawdevs/cnxk_gpio.rst           | 200 ++++++

1) Could you update doc/guides/platform/cnxk.rst file with _table_cnxk_rvu_dpdk_mapping table and "HW Offload Drivers" secion.

2) Please update doc/guides/rel_notes/release_21_11.rst release note.

#47 lore raw

v5 cover Add cnxk_gpio

In reply to Tomasz Duszynski

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.03 merge window.

v5:
- added close callback to make sure PMD resources are freed properly
- updated selftest to return early on error
- doc fixes

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/platform/cnxk.rst               |   2 +
 doc/guides/rawdevs/cnxk_gpio.rst           | 200 ++++++
 doc/guides/rawdevs/index.rst               |   1 +
 doc/guides/rel_notes/release_22_03.rst     |   9 +
 drivers/raw/cnxk_gpio/cnxk_gpio.c          | 763 +++++++++++++++++++++
 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 | 393 +++++++++++
 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 +
 12 files changed, 2071 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

#48 lore raw

PATCH v5 1/11 raw/cnxk_gpio: add GPIO driver skeleton

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.

---
 doc/guides/platform/cnxk.rst           |   2 +
 doc/guides/rawdevs/cnxk_gpio.rst       |  65 +++++++
 doc/guides/rawdevs/index.rst           |   1 +
 doc/guides/rel_notes/release_22_03.rst |   9 +
 drivers/raw/cnxk_gpio/cnxk_gpio.c      | 248 +++++++++++++++++++++++++
 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 +
 9 files changed, 359 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
doc/guides/platform/cnxk.rst +2 -0
index 97e38c868c..3dee725ac5 100644
@@ -73,6 +73,8 @@ DPDK subsystem.
    +---+-----+--------------------------------------------------------------+
    | 11| BPHY| rte_rawdev                                                   |
    +---+-----+--------------------------------------------------------------+
+   | 12| GPIO| rte_rawdev                                                   |
+   +---+-----+--------------------------------------------------------------+
 
 PF0 is called the administrative / admin function (AF) and has exclusive
 privileges to provision RVU functional block's LFs to each of the PF/VF.
doc/guides/rawdevs/cnxk_gpio.rst new file +65 -0

65 lines not on this page · raw message

doc/guides/rawdevs/index.rst +1 -0
index b6cf917443..0c02da6e90 100644
@@ -12,6 +12,7 @@ application through rawdev API.
     :numbered:
 
     cnxk_bphy
+    cnxk_gpio
     dpaa2_cmdif
     dpaa2_qdma
     ifpga
doc/guides/rel_notes/release_22_03.rst +9 -0
index 16c66c0641..09039899e8 100644
@@ -55,6 +55,15 @@ New Features
      Also, make sure to start the actual text at the margin.
      =======================================================
 
+* **Added CNXK GPIO PMD.**
+
+  Added 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.
+
+  See the :doc:`../rawdevs/cnxk_gpio` rawdev guide for more details on this
+  driver.
 
 Removed Items
 -------------
drivers/raw/cnxk_gpio/cnxk_gpio.c new file +248 -0

248 lines not on this page · raw message

drivers/raw/cnxk_gpio/cnxk_gpio.h new file +22 -0
new file mode 100644
index 0000000000..4dae8316ba
@@ -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_ */
drivers/raw/cnxk_gpio/meson.build new file +8 -0
new file mode 100644
index 0000000000..9a7e716c1e
@@ -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',
+)
drivers/raw/cnxk_gpio/version.map new file +3 -0
new file mode 100644
index 0000000000..4a76d1d52d
@@ -0,0 +1,3 @@
+DPDK_21 {
+	local: *;
+};
drivers/raw/meson.build +1 -0
index 87694a758e..05e7de1bfe 100644
@@ -7,6 +7,7 @@ endif
 
 drivers = [
         'cnxk_bphy',
+        'cnxk_gpio',
         'dpaa2_cmdif',
         'dpaa2_qdma',
         'ifpga',
Signature · 1 line
2.25.1
#49 lore raw

PATCH v5 2/11 raw/cnxk_gpio: support reading default queue conf

In reply to Tomasz Duszynski

Add support for reading default queue configuration.

---
 drivers/raw/cnxk_gpio/cnxk_gpio.c | 19 +++++++++++++++++++
 1 file changed, 19 insertions(+)
drivers/raw/cnxk_gpio/cnxk_gpio.c +19 -0
index 61069b2185..1f36f6e22c 100644
@@ -146,8 +146,27 @@ cnxk_gpio_dev_close(struct rte_rawdev *dev)
 	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 = {
 	.dev_close = cnxk_gpio_dev_close,
+	.queue_def_conf = cnxk_gpio_queue_def_conf,
 };
 
 static int
Signature · 1 line
2.25.1
#50 lore raw

PATCH v5 3/11 raw/cnxk_gpio: support reading queue count

In reply to Tomasz Duszynski

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

---
 drivers/raw/cnxk_gpio/cnxk_gpio.c | 9 +++++++++
 1 file changed, 9 insertions(+)
drivers/raw/cnxk_gpio/cnxk_gpio.c +9 -0
index 1f36f6e22c..cee75e389a 100644
@@ -164,9 +164,18 @@ 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 = {
 	.dev_close = cnxk_gpio_dev_close,
 	.queue_def_conf = cnxk_gpio_queue_def_conf,
+	.queue_count = cnxk_gpio_queue_count,
 };
 
 static int
Signature · 1 line
2.25.1
#51 lore raw

PATCH v5 4/11 raw/cnxk_gpio: support queue setup

In reply to Tomasz Duszynski

Add support for queue setup.

---
 drivers/raw/cnxk_gpio/cnxk_gpio.c | 84 ++++++++++++++++++++++++++++++-
 1 file changed, 82 insertions(+), 2 deletions(-)
drivers/raw/cnxk_gpio/cnxk_gpio.c +82 -2
index cee75e389a..9baa43187e 100644
@@ -139,9 +139,80 @@ cnxk_gpio_read_attr_int(char *attr, int *val)
 }
 
 static int
-cnxk_gpio_dev_close(struct rte_rawdev *dev)
+cnxk_gpio_write_attr(const char *attr, const char *val)
 {
-	RTE_SET_USED(dev);
+	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;
 }
@@ -172,10 +243,19 @@ cnxk_gpio_queue_count(struct rte_rawdev *dev)
 	return gpiochip->num_gpios;
 }
 
+static int
+cnxk_gpio_dev_close(struct rte_rawdev *dev)
+{
+	RTE_SET_USED(dev);
+
+	return 0;
+}
+
 static const struct rte_rawdev_ops cnxk_gpio_rawdev_ops = {
 	.dev_close = cnxk_gpio_dev_close,
 	.queue_def_conf = cnxk_gpio_queue_def_conf,
 	.queue_count = cnxk_gpio_queue_count,
+	.queue_setup = cnxk_gpio_queue_setup,
 };
 
 static int
Signature · 1 line
2.25.1
#52 lore raw

PATCH v5 5/11 raw/cnxk_gpio: support queue release

In reply to Tomasz Duszynski

Add support for queue release.

---
 drivers/raw/cnxk_gpio/cnxk_gpio.c | 34 +++++++++++++++++++++++++++++++
 1 file changed, 34 insertions(+)
drivers/raw/cnxk_gpio/cnxk_gpio.c +34 -0
index 9baa43187e..ec82a55918 100644
@@ -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)
@@ -256,6 +279,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
@@ -329,6 +353,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);
 
@@ -341,6 +367,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);
 
Signature · 1 line
2.25.1
#53 lore raw

PATCH v5 6/11 raw/cnxk_gpio: support enqueuing buffers

In reply to Tomasz Duszynski

Add dummy support for enqueuing buffers.

---
 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
drivers/raw/cnxk_gpio/cnxk_gpio.c +47 -0
index ec82a55918..6f3795df41 100644
@@ -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"
@@ -274,8 +275,54 @@ cnxk_gpio_dev_close(struct rte_rawdev *dev)
 	return 0;
 }
 
+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 = {
 	.dev_close = cnxk_gpio_dev_close,
+	.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,
drivers/raw/cnxk_gpio/cnxk_gpio.h +1 -0
index 4dae8316ba..6b54ebe6e6 100644
@@ -9,6 +9,7 @@ struct cnxk_gpiochip;
 
 struct cnxk_gpio {
 	struct cnxk_gpiochip *gpiochip;
+	void *rsp;
 	int num;
 };
 
drivers/raw/cnxk_gpio/meson.build +1 -0
index 9a7e716c1e..3fbfdd838c 100644
@@ -6,3 +6,4 @@ deps += ['bus_vdev', 'common_cnxk', 'rawdev', 'kvargs']
 sources = files(
         'cnxk_gpio.c',
 )
+headers = files('rte_pmd_cnxk_gpio.h')
drivers/raw/cnxk_gpio/rte_pmd_cnxk_gpio.h new file +38 -0
new file mode 100644
index 0000000000..c71065e10c
@@ -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_ */
Signature · 1 line
2.25.1
#54 lore raw

PATCH v5 7/11 raw/cnxk_gpio: support dequeuing buffers

In reply to Tomasz Duszynski

Add support for dequeuing buffers.

---
 drivers/raw/cnxk_gpio/cnxk_gpio.c | 26 ++++++++++++++++++++++++++
 1 file changed, 26 insertions(+)
drivers/raw/cnxk_gpio/cnxk_gpio.c +26 -0
index 6f3795df41..46f9e63dd7 100644
@@ -320,9 +320,35 @@ 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 = {
 	.dev_close = cnxk_gpio_dev_close,
 	.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,
Signature · 1 line
2.25.1
#55 lore raw

PATCH v5 8/11 raw/cnxk_gpio: support standard GPIO operations

In reply to Tomasz Duszynski

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

---
 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(-)
doc/guides/rawdevs/cnxk_gpio.rst +98 -0
index 868302d07f..f6c3c942c5 100644
@@ -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.
drivers/raw/cnxk_gpio/cnxk_gpio.c +146 -1

162 lines not on this page · raw message

drivers/raw/cnxk_gpio/rte_pmd_cnxk_gpio.h +277 -2

297 lines not on this page · raw message

Signature · 1 line
2.25.1
#56 lore raw

PATCH v5 9/11 raw/cnxk_gpio: support custom irq handlers

In reply to Tomasz Duszynski

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

---
 doc/guides/rawdevs/cnxk_gpio.rst          |  21 +++
 drivers/raw/cnxk_gpio/cnxk_gpio.c         |  41 +++-
 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, 401 insertions(+), 2 deletions(-)
 create mode 100644 drivers/raw/cnxk_gpio/cnxk_gpio_irq.c
doc/guides/rawdevs/cnxk_gpio.rst +21 -0
index f6c3c942c5..ad93ec0d44 100644
@@ -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.
drivers/raw/cnxk_gpio/cnxk_gpio.c +39 -2

80 lines not on this page · raw message

drivers/raw/cnxk_gpio/cnxk_gpio.h +8 -0
index 6b54ebe6e6..c052ca5735 100644
@@ -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_ */
drivers/raw/cnxk_gpio/cnxk_gpio_irq.c new file +216 -0

216 lines not on this page · raw message

drivers/raw/cnxk_gpio/meson.build +1 -0
index 3fbfdd838c..9b55f029c7 100644
@@ -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')
drivers/raw/cnxk_gpio/rte_pmd_cnxk_gpio.h +116 -0

134 lines not on this page · raw message

Signature · 1 line
2.25.1
#57 lore raw

PATCH v5 10/11 raw/cnxk_gpio: support selftest

In reply to Tomasz Duszynski

Add support for performing selftest.

---
 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
doc/guides/rawdevs/cnxk_gpio.rst +11 -0
index ad93ec0d44..c03a5b937c 100644
@@ -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.
drivers/raw/cnxk_gpio/cnxk_gpio.c +1 -0
index 58553ad3d9..230016b078 100644
@@ -527,6 +527,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
drivers/raw/cnxk_gpio/cnxk_gpio.h +2 -0
index c052ca5735..1b31b5a486 100644
@@ -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);
drivers/raw/cnxk_gpio/cnxk_gpio_selftest.c new file +386 -0

386 lines not on this page · raw message

drivers/raw/cnxk_gpio/meson.build +1 -0
index 9b55f029c7..a75a5b9084 100644
@@ -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')
Signature · 1 line
2.25.1
#58 lore raw

PATCH v5 11/11 raw/cnxk_gpio: add option to allow using subset of GPIOs

In reply to Tomasz Duszynski

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.

---
 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 |  49 +++---
 drivers/raw/cnxk_gpio/rte_pmd_cnxk_gpio.h  |   8 +
 5 files changed, 188 insertions(+), 49 deletions(-)
doc/guides/rawdevs/cnxk_gpio.rst +5 -0
index c03a5b937c..adff535a77 100644
@@ -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.
 
drivers/raw/cnxk_gpio/cnxk_gpio.c +145 -28

323 lines not on this page · raw message

drivers/raw/cnxk_gpio/cnxk_gpio.h +2 -0
index 1b31b5a486..e62f78a760 100644
@@ -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);
drivers/raw/cnxk_gpio/cnxk_gpio_selftest.c +28 -21

102 lines not on this page · raw message

drivers/raw/cnxk_gpio/rte_pmd_cnxk_gpio.h +8 -0
index e3096dc14f..80a37be9c7 100644
@@ -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 */
Signature · 1 line
2.25.1
#59 lore raw

Re: [PATCH v5 00/11] Add cnxk_gpio

In reply to Tomasz Duszynski

18/01/2022 14:24, Tomasz Duszynski:

Quoted 5 lines
 doc/guides/platform/cnxk.rst               |   2 +
 doc/guides/rawdevs/cnxk_gpio.rst           | 200 ++++++
 doc/guides/rawdevs/index.rst               |   1 +
 doc/guides/rel_notes/release_22_03.rst     |   9 +
 drivers/raw/cnxk_gpio/cnxk_gpio.c          | 763 +++++++++++++++++++++
Quoted 8 lines
 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 | 393 +++++++++++
 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 +
 12 files changed, 2071 insertions(+)

An update of the file MAINTAINERS is missing.

#60 lore raw

v6 cover Add cnxk_gpio

In reply to Tomasz Duszynski

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.03 merge window.

v6:
- update MAINTAINERS

v5:
- added close callback to make sure PMD resources are freed properly
- updated selftest to return early on error
- doc fixes

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

 MAINTAINERS                                |   6 +
 doc/guides/platform/cnxk.rst               |   2 +
 doc/guides/rawdevs/cnxk_gpio.rst           | 200 ++++++
 doc/guides/rawdevs/index.rst               |   1 +
 doc/guides/rel_notes/release_22_03.rst     |  10 +
 drivers/raw/cnxk_gpio/cnxk_gpio.c          | 763 +++++++++++++++++++++
 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 | 393 +++++++++++
 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 +
 13 files changed, 2078 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

#61 lore raw

PATCH v6 1/11 raw/cnxk_gpio: add GPIO driver skeleton

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.

---
 MAINTAINERS                            |   6 +
 doc/guides/platform/cnxk.rst           |   2 +
 doc/guides/rawdevs/cnxk_gpio.rst       |  65 +++++++
 doc/guides/rawdevs/index.rst           |   1 +
 doc/guides/rel_notes/release_22_03.rst |  10 +
 drivers/raw/cnxk_gpio/cnxk_gpio.c      | 248 +++++++++++++++++++++++++
 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 +
 10 files changed, 366 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
MAINTAINERS +6 -0
index 153c3ff4de..3ce78e6896 100644
@@ -1338,6 +1338,12 @@ M: Tomasz Duszynski <[email protected]>
 F: doc/guides/rawdevs/cnxk_bphy.rst
 F: drivers/raw/cnxk_bphy/
 
+Marvell CNXK GPIO
+M: Jakub Palider <[email protected]>
+M: Tomasz Duszynski <[email protected]>
+F: doc/guides/rawdevs/cnxk_gpio.rst
+F: drivers/raw/cnxk_gpio/
+
 NTB
 M: Jingjing Wu <[email protected]>
 M: Junfeng Guo <[email protected]>
doc/guides/platform/cnxk.rst +2 -0
index 97e38c868c..3dee725ac5 100644
@@ -73,6 +73,8 @@ DPDK subsystem.
    +---+-----+--------------------------------------------------------------+
    | 11| BPHY| rte_rawdev                                                   |
    +---+-----+--------------------------------------------------------------+
+   | 12| GPIO| rte_rawdev                                                   |
+   +---+-----+--------------------------------------------------------------+
 
 PF0 is called the administrative / admin function (AF) and has exclusive
 privileges to provision RVU functional block's LFs to each of the PF/VF.
doc/guides/rawdevs/cnxk_gpio.rst new file +65 -0

65 lines not on this page · raw message

doc/guides/rawdevs/index.rst +1 -0
index b6cf917443..0c02da6e90 100644
@@ -12,6 +12,7 @@ application through rawdev API.
     :numbered:
 
     cnxk_bphy
+    cnxk_gpio
     dpaa2_cmdif
     dpaa2_qdma
     ifpga
doc/guides/rel_notes/release_22_03.rst +10 -0
index 41923f50e6..714b7c8e5f 100644
@@ -55,6 +55,7 @@ New Features
      Also, make sure to start the actual text at the margin.
      =======================================================
 
+<<<<<<< HEAD
 * **Added ability to reuse hugepages in Linux.**
 
   It is possible to reuse files in hugetlbfs to speed up hugepage mapping,
@@ -158,6 +159,15 @@ New Features
   * Called ``rte_ipv4/6_udptcp_cksum_mbuf()`` functions in testpmd csum mode
     to support software UDP/TCP checksum over multiple segments.
 
+* **Added CNXK GPIO PMD.**
+
+  Added 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.
+
+  See the :doc:`../rawdevs/cnxk_gpio` rawdev guide for more details on this
+  driver.
 
 Removed Items
 -------------
drivers/raw/cnxk_gpio/cnxk_gpio.c new file +248 -0

248 lines not on this page · raw message

drivers/raw/cnxk_gpio/cnxk_gpio.h new file +22 -0
new file mode 100644
index 0000000000..4dae8316ba
@@ -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_ */
drivers/raw/cnxk_gpio/meson.build new file +8 -0
new file mode 100644
index 0000000000..9a7e716c1e
@@ -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',
+)
drivers/raw/cnxk_gpio/version.map new file +3 -0
new file mode 100644
index 0000000000..4a76d1d52d
@@ -0,0 +1,3 @@
+DPDK_21 {
+	local: *;
+};
drivers/raw/meson.build +1 -0
index 87694a758e..05e7de1bfe 100644
@@ -7,6 +7,7 @@ endif
 
 drivers = [
         'cnxk_bphy',
+        'cnxk_gpio',
         'dpaa2_cmdif',
         'dpaa2_qdma',
         'ifpga',
Signature · 1 line
2.25.1
#62 lore raw

Re: [PATCH v6 01/11] raw/cnxk_gpio: add GPIO driver skeleton

17/02/2022 12:09, Tomasz Duszynski:

doc/guides/rel_notes/release_22_03.rst New Features · line 59

Quoted 8 lines
doc/guides/rel_notes/release_22_03.rst +1 -0
@@ -55,6 +55,7 @@ New Features
      Also, make sure to start the actual text at the margin.
      =======================================================
 
+<<<<<<< HEAD
 * **Added ability to reuse hugepages in Linux.**

Will remove this rebase trace while merging.

#63 lore raw

Re: [PATCH v6 01/11] raw/cnxk_gpio: add GPIO driver skeleton

In reply to Tomasz Duszynski

drivers/raw/cnxk_gpio/version.map line 3

Quoted 9 lines · Tomasz Duszynski
drivers/raw/cnxk_gpio/version.map new file +3 -0
new file mode 100644
index 0000000000..4a76d1d52d
@@ -0,0 +1,3 @@
+DPDK_21 {
+	local: *;
+};

This should be 'DPDK_22' now, since patch is merged can you please send an incremental fix?

#64 lore raw

PATCH v6 2/11 raw/cnxk_gpio: support reading default queue conf

In reply to Tomasz Duszynski

Add support for reading default queue configuration.

---
 drivers/raw/cnxk_gpio/cnxk_gpio.c | 19 +++++++++++++++++++
 1 file changed, 19 insertions(+)
drivers/raw/cnxk_gpio/cnxk_gpio.c +19 -0
index 61069b2185..1f36f6e22c 100644
@@ -146,8 +146,27 @@ cnxk_gpio_dev_close(struct rte_rawdev *dev)
 	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 = {
 	.dev_close = cnxk_gpio_dev_close,
+	.queue_def_conf = cnxk_gpio_queue_def_conf,
 };
 
 static int
Signature · 1 line
2.25.1
#65 lore raw

PATCH v6 3/11 raw/cnxk_gpio: support reading queue count

In reply to Tomasz Duszynski

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

---
 drivers/raw/cnxk_gpio/cnxk_gpio.c | 9 +++++++++
 1 file changed, 9 insertions(+)
drivers/raw/cnxk_gpio/cnxk_gpio.c +9 -0
index 1f36f6e22c..cee75e389a 100644
@@ -164,9 +164,18 @@ 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 = {
 	.dev_close = cnxk_gpio_dev_close,
 	.queue_def_conf = cnxk_gpio_queue_def_conf,
+	.queue_count = cnxk_gpio_queue_count,
 };
 
 static int
Signature · 1 line
2.25.1
#66 lore raw

PATCH v6 4/11 raw/cnxk_gpio: support queue setup

In reply to Tomasz Duszynski

Add support for queue setup.

---
 drivers/raw/cnxk_gpio/cnxk_gpio.c | 84 ++++++++++++++++++++++++++++++-
 1 file changed, 82 insertions(+), 2 deletions(-)
drivers/raw/cnxk_gpio/cnxk_gpio.c +82 -2
index cee75e389a..9baa43187e 100644
@@ -139,9 +139,80 @@ cnxk_gpio_read_attr_int(char *attr, int *val)
 }
 
 static int
-cnxk_gpio_dev_close(struct rte_rawdev *dev)
+cnxk_gpio_write_attr(const char *attr, const char *val)
 {
-	RTE_SET_USED(dev);
+	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;
 }
@@ -172,10 +243,19 @@ cnxk_gpio_queue_count(struct rte_rawdev *dev)
 	return gpiochip->num_gpios;
 }
 
+static int
+cnxk_gpio_dev_close(struct rte_rawdev *dev)
+{
+	RTE_SET_USED(dev);
+
+	return 0;
+}
+
 static const struct rte_rawdev_ops cnxk_gpio_rawdev_ops = {
 	.dev_close = cnxk_gpio_dev_close,
 	.queue_def_conf = cnxk_gpio_queue_def_conf,
 	.queue_count = cnxk_gpio_queue_count,
+	.queue_setup = cnxk_gpio_queue_setup,
 };
 
 static int
Signature · 1 line
2.25.1
#67 lore raw

PATCH v6 5/11 raw/cnxk_gpio: support queue release

In reply to Tomasz Duszynski

Add support for queue release.

---
 drivers/raw/cnxk_gpio/cnxk_gpio.c | 34 +++++++++++++++++++++++++++++++
 1 file changed, 34 insertions(+)
drivers/raw/cnxk_gpio/cnxk_gpio.c +34 -0
index 9baa43187e..ec82a55918 100644
@@ -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)
@@ -256,6 +279,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
@@ -329,6 +353,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);
 
@@ -341,6 +367,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);
 
Signature · 1 line
2.25.1
#68 lore raw

PATCH v6 6/11 raw/cnxk_gpio: support enqueuing buffers

In reply to Tomasz Duszynski

Add dummy support for enqueuing buffers.

---
 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
drivers/raw/cnxk_gpio/cnxk_gpio.c +47 -0
index ec82a55918..6f3795df41 100644
@@ -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"
@@ -274,8 +275,54 @@ cnxk_gpio_dev_close(struct rte_rawdev *dev)
 	return 0;
 }
 
+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 = {
 	.dev_close = cnxk_gpio_dev_close,
+	.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,
drivers/raw/cnxk_gpio/cnxk_gpio.h +1 -0
index 4dae8316ba..6b54ebe6e6 100644
@@ -9,6 +9,7 @@ struct cnxk_gpiochip;
 
 struct cnxk_gpio {
 	struct cnxk_gpiochip *gpiochip;
+	void *rsp;
 	int num;
 };
 
drivers/raw/cnxk_gpio/meson.build +1 -0
index 9a7e716c1e..3fbfdd838c 100644
@@ -6,3 +6,4 @@ deps += ['bus_vdev', 'common_cnxk', 'rawdev', 'kvargs']
 sources = files(
         'cnxk_gpio.c',
 )
+headers = files('rte_pmd_cnxk_gpio.h')
drivers/raw/cnxk_gpio/rte_pmd_cnxk_gpio.h new file +38 -0
new file mode 100644
index 0000000000..c71065e10c
@@ -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_ */
Signature · 1 line
2.25.1
#69 lore raw

PATCH v6 7/11 raw/cnxk_gpio: support dequeuing buffers

In reply to Tomasz Duszynski

Add support for dequeuing buffers.

---
 drivers/raw/cnxk_gpio/cnxk_gpio.c | 26 ++++++++++++++++++++++++++
 1 file changed, 26 insertions(+)
drivers/raw/cnxk_gpio/cnxk_gpio.c +26 -0
index 6f3795df41..46f9e63dd7 100644
@@ -320,9 +320,35 @@ 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 = {
 	.dev_close = cnxk_gpio_dev_close,
 	.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,
Signature · 1 line
2.25.1
#70 lore raw

PATCH v6 8/11 raw/cnxk_gpio: support standard GPIO operations

In reply to Tomasz Duszynski

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

---
 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(-)
doc/guides/rawdevs/cnxk_gpio.rst +98 -0
index 868302d07f..f6c3c942c5 100644
@@ -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.
drivers/raw/cnxk_gpio/cnxk_gpio.c +146 -1

162 lines not on this page · raw message

drivers/raw/cnxk_gpio/rte_pmd_cnxk_gpio.h +277 -2

297 lines not on this page · raw message

Signature · 1 line
2.25.1
#71 lore raw

PATCH v6 9/11 raw/cnxk_gpio: support custom irq handlers

In reply to Tomasz Duszynski

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

---
 doc/guides/rawdevs/cnxk_gpio.rst          |  21 +++
 drivers/raw/cnxk_gpio/cnxk_gpio.c         |  41 +++-
 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, 401 insertions(+), 2 deletions(-)
 create mode 100644 drivers/raw/cnxk_gpio/cnxk_gpio_irq.c
doc/guides/rawdevs/cnxk_gpio.rst +21 -0
index f6c3c942c5..ad93ec0d44 100644
@@ -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.
drivers/raw/cnxk_gpio/cnxk_gpio.c +39 -2

80 lines not on this page · raw message

drivers/raw/cnxk_gpio/cnxk_gpio.h +8 -0
index 6b54ebe6e6..c052ca5735 100644
@@ -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_ */
drivers/raw/cnxk_gpio/cnxk_gpio_irq.c new file +216 -0

216 lines not on this page · raw message

drivers/raw/cnxk_gpio/meson.build +1 -0
index 3fbfdd838c..9b55f029c7 100644
@@ -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')
drivers/raw/cnxk_gpio/rte_pmd_cnxk_gpio.h +116 -0

134 lines not on this page · raw message

Signature · 1 line
2.25.1
#72 lore raw

PATCH v6 10/11 raw/cnxk_gpio: support selftest

In reply to Tomasz Duszynski

Add support for performing selftest.

---
 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
doc/guides/rawdevs/cnxk_gpio.rst +11 -0
index ad93ec0d44..c03a5b937c 100644
@@ -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.
drivers/raw/cnxk_gpio/cnxk_gpio.c +1 -0
index 58553ad3d9..230016b078 100644
@@ -527,6 +527,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
drivers/raw/cnxk_gpio/cnxk_gpio.h +2 -0
index c052ca5735..1b31b5a486 100644
@@ -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);
drivers/raw/cnxk_gpio/cnxk_gpio_selftest.c new file +386 -0

386 lines not on this page · raw message

drivers/raw/cnxk_gpio/meson.build +1 -0
index 9b55f029c7..a75a5b9084 100644
@@ -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')
Signature · 1 line
2.25.1
#73 lore raw

PATCH v6 11/11 raw/cnxk_gpio: add option to allow using subset of GPIOs

In reply to Tomasz Duszynski

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.

---
 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 |  49 +++---
 drivers/raw/cnxk_gpio/rte_pmd_cnxk_gpio.h  |   8 +
 5 files changed, 188 insertions(+), 49 deletions(-)
doc/guides/rawdevs/cnxk_gpio.rst +5 -0
index c03a5b937c..adff535a77 100644
@@ -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.
 
drivers/raw/cnxk_gpio/cnxk_gpio.c +145 -28

323 lines not on this page · raw message

drivers/raw/cnxk_gpio/cnxk_gpio.h +2 -0
index 1b31b5a486..e62f78a760 100644
@@ -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);
drivers/raw/cnxk_gpio/cnxk_gpio_selftest.c +28 -21

102 lines not on this page · raw message

drivers/raw/cnxk_gpio/rte_pmd_cnxk_gpio.h +8 -0
index e3096dc14f..80a37be9c7 100644
@@ -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 */
Signature · 1 line
2.25.1
#74 lore raw

Re: [PATCH v6 00/11] Add cnxk_gpio

In reply to Tomasz Duszynski
Quoted 4 lines

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

Quoted 8 lines

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

Applied, thanks.