Add cnxk_gpio PMD
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
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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -0,0 +1,3 @@ +DPDK_21 { + local: *; +};
drivers/raw/meson.build +1 -0
@@ -7,6 +7,7 @@ endif drivers = [ 'cnxk_bphy', + 'cnxk_gpio', 'dpaa2_cmdif', 'dpaa2_qdma', 'ifpga',
Signature · 1 line
2.25.1
PATCH 2/10 raw/cnxk_gpio: support reading default queue conf
In reply to Tomasz DuszynskiAdd 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
@@ -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
PATCH 3/10 raw/cnxk_gpio: support reading queue count
In reply to Tomasz DuszynskiAdd 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
@@ -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
PATCH 4/10 raw/cnxk_gpio: support queue setup
In reply to Tomasz DuszynskiAdd 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
@@ -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
PATCH 5/10 raw/cnxk_gpio: support queue release
In reply to Tomasz DuszynskiAdd 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
@@ -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
PATCH 6/10 raw/cnxk_gpio: support enqueuing buffers
In reply to Tomasz DuszynskiAdd 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
@@ -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
@@ -7,6 +7,7 @@struct cnxk_gpio {struct cnxk_gpiochip *gpiochip; +void *rsp;int num; };
drivers/raw/cnxk_gpio/meson.build +1 -0
@@ -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
@@ -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
PATCH 7/10 raw/cnxk_gpio: support dequeuing buffers
In reply to Tomasz DuszynskiAdd 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
@@ -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
PATCH 8/10 raw/cnxk_gpio: support standard GPIO operations
In reply to Tomasz DuszynskiAdd 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
@@ -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
PATCH 9/10 raw/cnxk_gpio: support custom irq handlers
In reply to Tomasz DuszynskiAdd 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
@@ -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
@@ -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
@@ -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
@@ -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
PATCH 10/10 raw/cnxk_gpio: support selftest
In reply to Tomasz DuszynskiAdd 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
@@ -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
@@ -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
@@ -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
@@ -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
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.
v2 cover Add cnxk_gpio PMD
In reply to Tomasz DuszynskiThis 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
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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -0,0 +1,3 @@ +DPDK_21 { + local: *; +};
drivers/raw/meson.build +1 -0
@@ -7,6 +7,7 @@ endif drivers = [ 'cnxk_bphy', + 'cnxk_gpio', 'dpaa2_cmdif', 'dpaa2_qdma', 'ifpga',
Signature · 1 line
2.25.1
PATCH v2 2/10 raw/cnxk_gpio: support reading default queue conf
In reply to Tomasz DuszynskiAdd 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
@@ -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
PATCH v2 3/10 raw/cnxk_gpio: support reading queue count
In reply to Tomasz DuszynskiAdd 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
@@ -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
PATCH v2 4/10 raw/cnxk_gpio: support queue setup
In reply to Tomasz DuszynskiAdd 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
@@ -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
PATCH v2 5/10 raw/cnxk_gpio: support queue release
In reply to Tomasz DuszynskiAdd 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
@@ -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
PATCH v2 6/10 raw/cnxk_gpio: support enqueuing buffers
In reply to Tomasz DuszynskiAdd 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
@@ -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
@@ -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
@@ -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
@@ -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
PATCH v2 7/10 raw/cnxk_gpio: support dequeuing buffers
In reply to Tomasz DuszynskiAdd 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
@@ -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
PATCH v2 8/10 raw/cnxk_gpio: support standard GPIO operations
In reply to Tomasz DuszynskiAdd 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
@@ -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
PATCH v2 9/10 raw/cnxk_gpio: support custom irq handlers
In reply to Tomasz DuszynskiAdd 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
@@ -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
@@ -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
@@ -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
@@ -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
PATCH v2 10/10 raw/cnxk_gpio: support selftest
In reply to Tomasz DuszynskiAdd 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
@@ -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
@@ -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
@@ -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
@@ -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
v3 cover Add cnxk_gpio PMD
In reply to Tomasz DuszynskiThis 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
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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -0,0 +1,3 @@ +DPDK_21 { + local: *; +};
drivers/raw/meson.build +1 -0
@@ -7,6 +7,7 @@ endif drivers = [ 'cnxk_bphy', + 'cnxk_gpio', 'dpaa2_cmdif', 'dpaa2_qdma', 'ifpga',
Signature · 1 line
2.25.1
PATCH v3 2/10 raw/cnxk_gpio: support reading default queue conf
In reply to Tomasz DuszynskiAdd 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
@@ -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
PATCH v3 3/10 raw/cnxk_gpio: support reading queue count
In reply to Tomasz DuszynskiAdd 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
@@ -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
PATCH v3 4/10 raw/cnxk_gpio: support queue setup
In reply to Tomasz DuszynskiAdd 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
@@ -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
PATCH v3 5/10 raw/cnxk_gpio: support queue release
In reply to Tomasz DuszynskiAdd 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
@@ -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
PATCH v3 6/10 raw/cnxk_gpio: support enqueuing buffers
In reply to Tomasz DuszynskiAdd 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
@@ -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
@@ -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
@@ -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
@@ -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
PATCH v3 7/10 raw/cnxk_gpio: support dequeuing buffers
In reply to Tomasz DuszynskiAdd 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
@@ -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
PATCH v3 8/10 raw/cnxk_gpio: support standard GPIO operations
In reply to Tomasz DuszynskiAdd 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
@@ -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
PATCH v3 9/10 raw/cnxk_gpio: support custom irq handlers
In reply to Tomasz DuszynskiAdd 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
@@ -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
@@ -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
@@ -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
@@ -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
PATCH v3 10/10 raw/cnxk_gpio: support selftest
In reply to Tomasz DuszynskiAdd 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
@@ -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
@@ -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
@@ -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
@@ -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
v4 cover Add cnxk_gpio
In reply to Tomasz DuszynskiThis 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
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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -0,0 +1,3 @@ +DPDK_21 { + local: *; +};
drivers/raw/meson.build +1 -0
@@ -7,6 +7,7 @@ endif drivers = [ 'cnxk_bphy', + 'cnxk_gpio', 'dpaa2_cmdif', 'dpaa2_qdma', 'ifpga',
Signature · 1 line
2.25.1
PATCH v4 2/11 raw/cnxk_gpio: support reading default queue conf
In reply to Tomasz DuszynskiAdd 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
@@ -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
PATCH v4 3/11 raw/cnxk_gpio: support reading queue count
In reply to Tomasz DuszynskiAdd 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
@@ -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
PATCH v4 4/11 raw/cnxk_gpio: support queue setup
In reply to Tomasz DuszynskiAdd 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
@@ -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
PATCH v4 5/11 raw/cnxk_gpio: support queue release
In reply to Tomasz DuszynskiAdd 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
@@ -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
PATCH v4 6/11 raw/cnxk_gpio: support enqueuing buffers
In reply to Tomasz DuszynskiAdd 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
@@ -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
@@ -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
@@ -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
@@ -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
PATCH v4 7/11 raw/cnxk_gpio: support dequeuing buffers
In reply to Tomasz DuszynskiAdd 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
@@ -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
PATCH v4 8/11 raw/cnxk_gpio: support standard GPIO operations
In reply to Tomasz DuszynskiAdd 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
@@ -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
PATCH v4 9/11 raw/cnxk_gpio: support custom irq handlers
In reply to Tomasz DuszynskiAdd 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
@@ -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
@@ -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
@@ -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
@@ -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
PATCH v4 10/11 raw/cnxk_gpio: support selftest
In reply to Tomasz DuszynskiAdd 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
@@ -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
@@ -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
@@ -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
@@ -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
PATCH v4 11/11 raw/cnxk_gpio: add option to allow using subset of GPIOs
In reply to Tomasz DuszynskiAdd 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
@@ -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
@@ -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
@@ -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
@@ -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
Re: [PATCH v4 00/11] Add cnxk_gpio
In reply to Tomasz DuszynskiQuoted 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 GPIOsv3:
- fix meson formatting
- fixcnxk_gpio_process_buf()return valuev2:
- do not trigger irq by writing to/dev/mem, useioctl()insteadTomasz 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.
v5 cover Add cnxk_gpio
In reply to Tomasz DuszynskiThis 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
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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -0,0 +1,3 @@ +DPDK_21 { + local: *; +};
drivers/raw/meson.build +1 -0
@@ -7,6 +7,7 @@ endif drivers = [ 'cnxk_bphy', + 'cnxk_gpio', 'dpaa2_cmdif', 'dpaa2_qdma', 'ifpga',
Signature · 1 line
2.25.1
PATCH v5 2/11 raw/cnxk_gpio: support reading default queue conf
In reply to Tomasz DuszynskiAdd 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
@@ -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
PATCH v5 3/11 raw/cnxk_gpio: support reading queue count
In reply to Tomasz DuszynskiAdd 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
@@ -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
PATCH v5 4/11 raw/cnxk_gpio: support queue setup
In reply to Tomasz DuszynskiAdd 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
@@ -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
PATCH v5 5/11 raw/cnxk_gpio: support queue release
In reply to Tomasz DuszynskiAdd 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
@@ -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
PATCH v5 6/11 raw/cnxk_gpio: support enqueuing buffers
In reply to Tomasz DuszynskiAdd 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
@@ -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
@@ -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
@@ -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
@@ -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
PATCH v5 7/11 raw/cnxk_gpio: support dequeuing buffers
In reply to Tomasz DuszynskiAdd 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
@@ -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
PATCH v5 8/11 raw/cnxk_gpio: support standard GPIO operations
In reply to Tomasz DuszynskiAdd 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
@@ -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
PATCH v5 9/11 raw/cnxk_gpio: support custom irq handlers
In reply to Tomasz DuszynskiAdd 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
@@ -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
@@ -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
@@ -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
PATCH v5 10/11 raw/cnxk_gpio: support selftest
In reply to Tomasz DuszynskiAdd 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
@@ -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
@@ -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
@@ -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
@@ -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
PATCH v5 11/11 raw/cnxk_gpio: add option to allow using subset of GPIOs
In reply to Tomasz DuszynskiAdd 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
@@ -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
@@ -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
@@ -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
Re: [PATCH v5 00/11] Add cnxk_gpio
In reply to Tomasz Duszynski18/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.
v6 cover Add cnxk_gpio
In reply to Tomasz DuszynskiThis 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
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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -0,0 +1,3 @@ +DPDK_21 { + local: *; +};
drivers/raw/meson.build +1 -0
@@ -7,6 +7,7 @@ endif drivers = [ 'cnxk_bphy', + 'cnxk_gpio', 'dpaa2_cmdif', 'dpaa2_qdma', 'ifpga',
Signature · 1 line
2.25.1
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.
Re: [PATCH v6 01/11] raw/cnxk_gpio: add GPIO driver skeleton
In reply to Tomasz Duszynskidrivers/raw/cnxk_gpio/version.map line 3
Quoted 9 lines · Tomasz Duszynski
drivers/raw/cnxk_gpio/version.map new file +3
-0@@ -0,0 +1,3 @@ +DPDK_21 { + local: *; +};
This should be 'DPDK_22' now, since patch is merged can you please send an incremental fix?
PATCH v6 2/11 raw/cnxk_gpio: support reading default queue conf
In reply to Tomasz DuszynskiAdd 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
@@ -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
PATCH v6 3/11 raw/cnxk_gpio: support reading queue count
In reply to Tomasz DuszynskiAdd 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
@@ -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
PATCH v6 4/11 raw/cnxk_gpio: support queue setup
In reply to Tomasz DuszynskiAdd 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
@@ -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
PATCH v6 5/11 raw/cnxk_gpio: support queue release
In reply to Tomasz DuszynskiAdd 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
@@ -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
PATCH v6 6/11 raw/cnxk_gpio: support enqueuing buffers
In reply to Tomasz DuszynskiAdd 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
@@ -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
@@ -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
@@ -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
@@ -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
PATCH v6 7/11 raw/cnxk_gpio: support dequeuing buffers
In reply to Tomasz DuszynskiAdd 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
@@ -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
PATCH v6 8/11 raw/cnxk_gpio: support standard GPIO operations
In reply to Tomasz DuszynskiAdd 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
@@ -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
PATCH v6 9/11 raw/cnxk_gpio: support custom irq handlers
In reply to Tomasz DuszynskiAdd 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
@@ -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
@@ -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
@@ -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
PATCH v6 10/11 raw/cnxk_gpio: support selftest
In reply to Tomasz DuszynskiAdd 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
@@ -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
@@ -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
@@ -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
@@ -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
PATCH v6 11/11 raw/cnxk_gpio: add option to allow using subset of GPIOs
In reply to Tomasz DuszynskiAdd 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
@@ -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
@@ -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
@@ -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
Thomas Monjalon
AppliedRe: [PATCH v6 00/11] Add cnxk_gpio
In reply to Tomasz DuszynskiQuoted 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.