From: Nicolas Chautru <nicolas.chautru@intel.com>
To: dev@dpdk.org, gakhil@marvell.com, maxime.coquelin@redhat.com,
thomas@monjalon.net
Cc: hemant.agrawal@nxp.com, hernan.vargas@intel.com, g.singh@nxp.com,
david.marchand@redhat.com,
Nicolas Chautru <nicolas.chautru@intel.com>
Subject: [RFC 1/1] bbdev: device PF initialization helper through bbdev API
Date: Thu, 13 Oct 2022 18:42:05 -0700 [thread overview]
Message-ID: <20221014014205.38074-2-nicolas.chautru@intel.com> (raw)
In-Reply-To: <20221014014205.38074-1-nicolas.chautru@intel.com>
Moved from PMD API to bbdev API.
This API is only meant for bbdev-test usage (notably for OEMs).
The actual configuration structure still need to
be exposed as it is device specific.
RFI only
Signed-off-by: Nicolas Chautru <nicolas.chautru@intel.com>
---
app/test-bbdev/test_bbdev_perf.c | 10 +-
drivers/baseband/acc/acc100_pmd.h | 1 -
drivers/baseband/acc/acc200_cfg.h | 32 --
drivers/baseband/acc/acc200_pmd.h | 1 -
drivers/baseband/acc/meson.build | 2 +-
drivers/baseband/acc/rte_acc100_pmd.c | 308 +++++++++---------
drivers/baseband/acc/rte_acc200_pmd.c | 256 +++++++--------
drivers/baseband/acc/rte_acc_cfg.h | 49 ---
drivers/baseband/acc/rte_acc_common_cfg.h | 15 +-
drivers/baseband/acc/version.map | 6 -
.../fpga_5gnr_fec/rte_fpga_5gnr_fec.c | 206 ++++++------
.../fpga_5gnr_fec/rte_pmd_fpga_5gnr_fec.h | 35 +-
drivers/baseband/fpga_5gnr_fec/version.map | 7 -
drivers/baseband/fpga_lte_fec/fpga_lte_fec.c | 202 ++++++------
drivers/baseband/fpga_lte_fec/fpga_lte_fec.h | 35 +-
drivers/baseband/fpga_lte_fec/version.map | 7 -
lib/bbdev/rte_bbdev.c | 20 ++
lib/bbdev/rte_bbdev.h | 17 +
lib/bbdev/rte_bbdev_pmd.h | 10 +
lib/bbdev/version.map | 1 +
20 files changed, 535 insertions(+), 685 deletions(-)
delete mode 100644 drivers/baseband/acc/acc200_cfg.h
delete mode 100644 drivers/baseband/acc/rte_acc_cfg.h
diff --git a/app/test-bbdev/test_bbdev_perf.c b/app/test-bbdev/test_bbdev_perf.c
index 52396f1473..89a4f20b0b 100644
--- a/app/test-bbdev/test_bbdev_perf.c
+++ b/app/test-bbdev/test_bbdev_perf.c
@@ -54,7 +54,7 @@
#endif
#ifdef RTE_BASEBAND_ACC
-#include <rte_acc_cfg.h>
+#include <rte_acc_common_cfg.h>
#define ACC100PF_DRIVER_NAME ("intel_acc100_pf")
#define ACC100VF_DRIVER_NAME ("intel_acc100_vf")
#define ACC100_QMGR_NUM_AQS 16
@@ -667,7 +667,7 @@ add_bbdev_dev(uint8_t dev_id, struct rte_bbdev_info *info,
conf.flr_time_out = FLR_4G_TIMEOUT;
/* setup FPGA PF with configuration information */
- ret = rte_fpga_lte_fec_configure(info->dev_name, &conf);
+ ret = rte_bbdev_pf_init_helper(dev_id, (void *)&conf);
TEST_ASSERT_SUCCESS(ret,
"Failed to configure 4G FPGA PF for bbdev %s",
info->dev_name);
@@ -708,7 +708,7 @@ add_bbdev_dev(uint8_t dev_id, struct rte_bbdev_info *info,
conf.dl_load_balance = DL_5G_LOAD_BALANCE;
/* setup FPGA PF with configuration information */
- ret = rte_fpga_5gnr_fec_configure(info->dev_name, &conf);
+ ret = rte_bbdev_pf_init_helper(dev_id, (void *)&conf);
TEST_ASSERT_SUCCESS(ret,
"Failed to configure 5G FPGA PF for bbdev %s",
info->dev_name);
@@ -765,7 +765,7 @@ add_bbdev_dev(uint8_t dev_id, struct rte_bbdev_info *info,
conf.q_dl_5g.aq_depth_log2 = ACC100_QMGR_AQ_DEPTH;
/* setup PF with configuration information */
- ret = rte_acc_configure(info->dev_name, &conf);
+ ret = rte_bbdev_pf_init_helper(dev_id, (void *)&conf);
TEST_ASSERT_SUCCESS(ret,
"Failed to configure ACC100 PF for bbdev %s",
info->dev_name);
@@ -827,7 +827,7 @@ add_bbdev_dev(uint8_t dev_id, struct rte_bbdev_info *info,
conf.q_fft.aq_depth_log2 = ACC200_QMGR_AQ_DEPTH;
/* setup PF with configuration information */
- ret = rte_acc_configure(info->dev_name, &conf);
+ ret = rte_bbdev_pf_init_helper(dev_id, (void *)&conf);
TEST_ASSERT_SUCCESS(ret,
"Failed to configure ACC200 PF for bbdev %s",
info->dev_name);
diff --git a/drivers/baseband/acc/acc100_pmd.h b/drivers/baseband/acc/acc100_pmd.h
index 9486e98521..56ae427092 100644
--- a/drivers/baseband/acc/acc100_pmd.h
+++ b/drivers/baseband/acc/acc100_pmd.h
@@ -7,7 +7,6 @@
#include "acc100_pf_enum.h"
#include "acc100_vf_enum.h"
-#include "rte_acc_cfg.h"
#include "acc_common.h"
/* Helper macro for logging */
diff --git a/drivers/baseband/acc/acc200_cfg.h b/drivers/baseband/acc/acc200_cfg.h
deleted file mode 100644
index d77506b560..0000000000
--- a/drivers/baseband/acc/acc200_cfg.h
+++ /dev/null
@@ -1,32 +0,0 @@
-/* SPDX-License-Identifier: BSD-3-Clause
- * Copyright(c) 2022 Intel Corporation
- */
-
-#ifndef _ACC200_CFG_H_
-#define _ACC200_CFG_H_
-
-/**
- * @file acc200_cfg.h
- *
- * Functions for configuring ACC200 HW.
- * Configuration related to encoding/decoding is done through the
- * librte_bbdev library.
- */
-
-/**
- * Configure a ACC200 device.
- *
- * @param dev_name
- * The name of the device. This is the short form of PCI BDF, e.g. 00:01.0.
- * It can also be retrieved for a bbdev device from the dev_name field in the
- * rte_bbdev_info structure returned by rte_bbdev_info_get().
- * @param conf
- * Configuration to apply to ACC200 HW.
- *
- * @return
- * Zero on success, negative value on failure.
- */
-int
-acc200_configure(const char *dev_name, struct rte_acc_conf *conf);
-
-#endif /* _ACC200_CFG_H_ */
diff --git a/drivers/baseband/acc/acc200_pmd.h b/drivers/baseband/acc/acc200_pmd.h
index f3f2627ae9..acead1d17c 100644
--- a/drivers/baseband/acc/acc200_pmd.h
+++ b/drivers/baseband/acc/acc200_pmd.h
@@ -8,7 +8,6 @@
#include "acc_common.h"
#include "acc200_pf_enum.h"
#include "acc200_vf_enum.h"
-#include "acc200_cfg.h"
/* Helper macro for logging */
#define rte_bbdev_log(level, fmt, ...) \
diff --git a/drivers/baseband/acc/meson.build b/drivers/baseband/acc/meson.build
index 77c393b533..c7f7004174 100644
--- a/drivers/baseband/acc/meson.build
+++ b/drivers/baseband/acc/meson.build
@@ -5,4 +5,4 @@ deps += ['bbdev', 'bus_pci']
sources = files('rte_acc100_pmd.c', 'rte_acc200_pmd.c')
-headers = files('rte_acc_cfg.h')
+headers = files('rte_acc_common_cfg.h')
diff --git a/drivers/baseband/acc/rte_acc100_pmd.c b/drivers/baseband/acc/rte_acc100_pmd.c
index e5384223d1..a932754d5d 100644
--- a/drivers/baseband/acc/rte_acc100_pmd.c
+++ b/drivers/baseband/acc/rte_acc100_pmd.c
@@ -23,7 +23,6 @@
#include <rte_bbdev_pmd.h>
#include "acc100_pmd.h"
#include "acc101_pmd.h"
-#include "acc200_cfg.h"
#ifdef RTE_LIBRTE_BBDEV_DEBUG
RTE_LOG_REGISTER_DEFAULT(acc100_logtype, DEBUG);
@@ -964,40 +963,6 @@ acc100_queue_intr_disable(struct rte_bbdev *dev, uint16_t queue_id)
return 0;
}
-static const struct rte_bbdev_ops acc100_bbdev_ops = {
- .setup_queues = acc100_setup_queues,
- .intr_enable = acc100_intr_enable,
- .close = acc100_dev_close,
- .info_get = acc100_dev_info_get,
- .queue_setup = acc100_queue_setup,
- .queue_release = acc100_queue_release,
- .queue_intr_enable = acc100_queue_intr_enable,
- .queue_intr_disable = acc100_queue_intr_disable
-};
-
-/* ACC100 PCI PF address map */
-static struct rte_pci_id pci_id_acc100_pf_map[] = {
- {
- RTE_PCI_DEVICE(ACC100_VENDOR_ID, ACC100_PF_DEVICE_ID),
- },
- {
- RTE_PCI_DEVICE(ACC101_VENDOR_ID, ACC101_PF_DEVICE_ID),
- },
- {.device_id = 0},
-};
-
-/* ACC100 PCI VF address map */
-static struct rte_pci_id pci_id_acc100_vf_map[] = {
- {
- RTE_PCI_DEVICE(ACC100_VENDOR_ID, ACC100_VF_DEVICE_ID),
- },
- {
- RTE_PCI_DEVICE(ACC101_VENDOR_ID, ACC101_VF_DEVICE_ID),
- },
- {.device_id = 0},
-};
-
-
/* Fill in a frame control word for turbo decoding. */
static inline void
acc100_fcw_td_fill(const struct rte_bbdev_dec_op *op, struct acc_fcw_td *fcw)
@@ -3662,107 +3627,6 @@ acc100_dequeue_ldpc_dec(struct rte_bbdev_queue_data *q_data,
return i;
}
-/* Initialization Function */
-static void
-acc100_bbdev_init(struct rte_bbdev *dev, struct rte_pci_driver *drv)
-{
- struct rte_pci_device *pci_dev = RTE_DEV_TO_PCI(dev->device);
-
- dev->dev_ops = &acc100_bbdev_ops;
- dev->enqueue_enc_ops = acc100_enqueue_enc;
- dev->enqueue_dec_ops = acc100_enqueue_dec;
- dev->dequeue_enc_ops = acc100_dequeue_enc;
- dev->dequeue_dec_ops = acc100_dequeue_dec;
- dev->enqueue_ldpc_enc_ops = acc100_enqueue_ldpc_enc;
- dev->enqueue_ldpc_dec_ops = acc100_enqueue_ldpc_dec;
- dev->dequeue_ldpc_enc_ops = acc100_dequeue_ldpc_enc;
- dev->dequeue_ldpc_dec_ops = acc100_dequeue_ldpc_dec;
-
- /* Device variant specific handling */
- if ((pci_dev->id.device_id == ACC100_PF_DEVICE_ID) ||
- (pci_dev->id.device_id == ACC100_VF_DEVICE_ID)) {
- ((struct acc_device *) dev->data->dev_private)->device_variant = ACC100_VARIANT;
- ((struct acc_device *) dev->data->dev_private)->fcw_ld_fill = acc100_fcw_ld_fill;
- } else {
- ((struct acc_device *) dev->data->dev_private)->device_variant = ACC101_VARIANT;
- ((struct acc_device *) dev->data->dev_private)->fcw_ld_fill = acc101_fcw_ld_fill;
- }
-
- ((struct acc_device *) dev->data->dev_private)->pf_device =
- !strcmp(drv->driver.name, RTE_STR(ACC100PF_DRIVER_NAME));
-
- ((struct acc_device *) dev->data->dev_private)->mmio_base =
- pci_dev->mem_resource[0].addr;
-
- rte_bbdev_log_debug("Init device %s [%s] @ vaddr %p paddr %#"PRIx64"",
- drv->driver.name, dev->data->name,
- (void *)pci_dev->mem_resource[0].addr,
- pci_dev->mem_resource[0].phys_addr);
-}
-
-static int acc100_pci_probe(struct rte_pci_driver *pci_drv,
- struct rte_pci_device *pci_dev)
-{
- struct rte_bbdev *bbdev = NULL;
- char dev_name[RTE_BBDEV_NAME_MAX_LEN];
-
- if (pci_dev == NULL) {
- rte_bbdev_log(ERR, "NULL PCI device");
- return -EINVAL;
- }
-
- rte_pci_device_name(&pci_dev->addr, dev_name, sizeof(dev_name));
-
- /* Allocate memory to be used privately by drivers */
- bbdev = rte_bbdev_allocate(pci_dev->device.name);
- if (bbdev == NULL)
- return -ENODEV;
-
- /* allocate device private memory */
- bbdev->data->dev_private = rte_zmalloc_socket(dev_name,
- sizeof(struct acc_device), RTE_CACHE_LINE_SIZE,
- pci_dev->device.numa_node);
-
- if (bbdev->data->dev_private == NULL) {
- rte_bbdev_log(CRIT,
- "Allocate of %zu bytes for device \"%s\" failed",
- sizeof(struct acc_device), dev_name);
- rte_bbdev_release(bbdev);
- return -ENOMEM;
- }
-
- /* Fill HW specific part of device structure */
- bbdev->device = &pci_dev->device;
- bbdev->intr_handle = pci_dev->intr_handle;
- bbdev->data->socket_id = pci_dev->device.numa_node;
-
- /* Invoke ACC100 device initialization function */
- acc100_bbdev_init(bbdev, pci_drv);
-
- rte_bbdev_log_debug("Initialised bbdev %s (id = %u)",
- dev_name, bbdev->data->dev_id);
- return 0;
-}
-
-static struct rte_pci_driver acc100_pci_pf_driver = {
- .probe = acc100_pci_probe,
- .remove = acc_pci_remove,
- .id_table = pci_id_acc100_pf_map,
- .drv_flags = RTE_PCI_DRV_NEED_MAPPING
-};
-
-static struct rte_pci_driver acc100_pci_vf_driver = {
- .probe = acc100_pci_probe,
- .remove = acc_pci_remove,
- .id_table = pci_id_acc100_vf_map,
- .drv_flags = RTE_PCI_DRV_NEED_MAPPING
-};
-
-RTE_PMD_REGISTER_PCI(ACC100PF_DRIVER_NAME, acc100_pci_pf_driver);
-RTE_PMD_REGISTER_PCI_TABLE(ACC100PF_DRIVER_NAME, pci_id_acc100_pf_map);
-RTE_PMD_REGISTER_PCI(ACC100VF_DRIVER_NAME, acc100_pci_vf_driver);
-RTE_PMD_REGISTER_PCI_TABLE(ACC100VF_DRIVER_NAME, pci_id_acc100_vf_map);
-
/*
* Workaround implementation to fix the power on status of some 5GUL engines
* This requires DMA permission if ported outside DPDK
@@ -3919,12 +3783,11 @@ poweron_cleanup(struct rte_bbdev *bbdev, struct acc_device *d,
/* Initial configuration of a ACC100 device prior to running configure() */
static int
-acc100_configure(const char *dev_name, struct rte_acc_conf *conf)
+acc100_configure(struct rte_bbdev *bbdev, struct rte_acc_conf *conf)
{
rte_bbdev_log(INFO, "rte_acc100_configure");
uint32_t value, address, status;
int qg_idx, template_idx, vf_idx, acc, i, j;
- struct rte_bbdev *bbdev = rte_bbdev_get_named_dev(dev_name);
/* Compile time checks */
RTE_BUILD_BUG_ON(sizeof(struct acc_dma_req_desc) != 256);
@@ -3932,12 +3795,6 @@ acc100_configure(const char *dev_name, struct rte_acc_conf *conf)
RTE_BUILD_BUG_ON(sizeof(struct acc_fcw_td) != 24);
RTE_BUILD_BUG_ON(sizeof(struct acc_fcw_te) != 32);
- if (bbdev == NULL) {
- rte_bbdev_log(ERR,
- "Invalid dev_name (%s), or device is not yet initialised",
- dev_name);
- return -ENODEV;
- }
struct acc_device *d = bbdev->data->dev_private;
/* Store configuration */
@@ -4314,12 +4171,11 @@ acc100_configure(const char *dev_name, struct rte_acc_conf *conf)
/* Initial configuration of a ACC101 device prior to running configure() */
static int
-acc101_configure(const char *dev_name, struct rte_acc_conf *conf)
+acc101_configure(struct rte_bbdev *bbdev, struct rte_acc_conf *conf)
{
rte_bbdev_log(INFO, "rte_acc101_configure");
uint32_t value, address, status;
int qg_idx, template_idx, vf_idx, acc, i;
- struct rte_bbdev *bbdev = rte_bbdev_get_named_dev(dev_name);
/* Compile time checks */
RTE_BUILD_BUG_ON(sizeof(struct acc_dma_req_desc) != 256);
@@ -4327,12 +4183,6 @@ acc101_configure(const char *dev_name, struct rte_acc_conf *conf)
RTE_BUILD_BUG_ON(sizeof(struct acc_fcw_td) != 24);
RTE_BUILD_BUG_ON(sizeof(struct acc_fcw_te) != 32);
- if (bbdev == NULL) {
- rte_bbdev_log(ERR,
- "Invalid dev_name (%s), or device is not yet initialised",
- dev_name);
- return -ENODEV;
- }
struct acc_device *d = bbdev->data->dev_private;
/* Store configuration */
@@ -4604,21 +4454,157 @@ acc101_configure(const char *dev_name, struct rte_acc_conf *conf)
return 0;
}
-int
-rte_acc_configure(const char *dev_name, struct rte_acc_conf *conf)
+static int
+acc1xx_configure(struct rte_bbdev *bbdev, void *conf)
{
- struct rte_bbdev *bbdev = rte_bbdev_get_named_dev(dev_name);
+ struct rte_pci_device *pci_dev;
+
if (bbdev == NULL) {
- rte_bbdev_log(ERR, "Invalid dev_name (%s), or device is not yet initialised",
- dev_name);
+ rte_bbdev_log(ERR, "Invalid device or not yet initialised");
return -ENODEV;
}
- struct rte_pci_device *pci_dev = RTE_DEV_TO_PCI(bbdev->device);
+ pci_dev = RTE_DEV_TO_PCI(bbdev->device);
+
printf("Configure dev id %x\n", pci_dev->id.device_id);
if (pci_dev->id.device_id == ACC100_PF_DEVICE_ID)
- return acc100_configure(dev_name, conf);
+ return acc100_configure(bbdev, (struct rte_acc_conf *)conf);
else if (pci_dev->id.device_id == ACC101_PF_DEVICE_ID)
- return acc101_configure(dev_name, conf);
+ return acc101_configure(bbdev, (struct rte_acc_conf *)conf);
else
- return acc200_configure(dev_name, conf);
+ return -1;
}
+
+static const struct rte_bbdev_ops acc100_bbdev_ops = {
+ .setup_queues = acc100_setup_queues,
+ .intr_enable = acc100_intr_enable,
+ .close = acc100_dev_close,
+ .info_get = acc100_dev_info_get,
+ .queue_setup = acc100_queue_setup,
+ .queue_release = acc100_queue_release,
+ .queue_intr_enable = acc100_queue_intr_enable,
+ .queue_intr_disable = acc100_queue_intr_disable,
+ .pf_init_helper = acc1xx_configure
+};
+
+/* ACC100 PCI PF address map */
+static struct rte_pci_id pci_id_acc100_pf_map[] = {
+ {
+ RTE_PCI_DEVICE(ACC100_VENDOR_ID, ACC100_PF_DEVICE_ID),
+ },
+ {
+ RTE_PCI_DEVICE(ACC101_VENDOR_ID, ACC101_PF_DEVICE_ID),
+ },
+ {.device_id = 0},
+};
+
+/* ACC100 PCI VF address map */
+static struct rte_pci_id pci_id_acc100_vf_map[] = {
+ {
+ RTE_PCI_DEVICE(ACC100_VENDOR_ID, ACC100_VF_DEVICE_ID),
+ },
+ {
+ RTE_PCI_DEVICE(ACC101_VENDOR_ID, ACC101_VF_DEVICE_ID),
+ },
+ {.device_id = 0},
+};
+
+/* Initialization Function */
+static void
+acc100_bbdev_init(struct rte_bbdev *dev, struct rte_pci_driver *drv)
+{
+ struct rte_pci_device *pci_dev = RTE_DEV_TO_PCI(dev->device);
+
+ dev->dev_ops = &acc100_bbdev_ops;
+ dev->enqueue_enc_ops = acc100_enqueue_enc;
+ dev->enqueue_dec_ops = acc100_enqueue_dec;
+ dev->dequeue_enc_ops = acc100_dequeue_enc;
+ dev->dequeue_dec_ops = acc100_dequeue_dec;
+ dev->enqueue_ldpc_enc_ops = acc100_enqueue_ldpc_enc;
+ dev->enqueue_ldpc_dec_ops = acc100_enqueue_ldpc_dec;
+ dev->dequeue_ldpc_enc_ops = acc100_dequeue_ldpc_enc;
+ dev->dequeue_ldpc_dec_ops = acc100_dequeue_ldpc_dec;
+
+ /* Device variant specific handling */
+ if ((pci_dev->id.device_id == ACC100_PF_DEVICE_ID) ||
+ (pci_dev->id.device_id == ACC100_VF_DEVICE_ID)) {
+ ((struct acc_device *) dev->data->dev_private)->device_variant = ACC100_VARIANT;
+ ((struct acc_device *) dev->data->dev_private)->fcw_ld_fill = acc100_fcw_ld_fill;
+ } else {
+ ((struct acc_device *) dev->data->dev_private)->device_variant = ACC101_VARIANT;
+ ((struct acc_device *) dev->data->dev_private)->fcw_ld_fill = acc101_fcw_ld_fill;
+ }
+
+ ((struct acc_device *) dev->data->dev_private)->pf_device =
+ !strcmp(drv->driver.name, RTE_STR(ACC100PF_DRIVER_NAME));
+
+ ((struct acc_device *) dev->data->dev_private)->mmio_base =
+ pci_dev->mem_resource[0].addr;
+
+ rte_bbdev_log_debug("Init device %s [%s] @ vaddr %p paddr %#"PRIx64"",
+ drv->driver.name, dev->data->name,
+ (void *)pci_dev->mem_resource[0].addr,
+ pci_dev->mem_resource[0].phys_addr);
+}
+
+static int acc100_pci_probe(struct rte_pci_driver *pci_drv,
+ struct rte_pci_device *pci_dev)
+{
+ struct rte_bbdev *bbdev = NULL;
+ char dev_name[RTE_BBDEV_NAME_MAX_LEN];
+
+ if (pci_dev == NULL) {
+ rte_bbdev_log(ERR, "NULL PCI device");
+ return -EINVAL;
+ }
+
+ rte_pci_device_name(&pci_dev->addr, dev_name, sizeof(dev_name));
+
+ /* Allocate memory to be used privately by drivers */
+ bbdev = rte_bbdev_allocate(pci_dev->device.name);
+ if (bbdev == NULL)
+ return -ENODEV;
+
+ /* allocate device private memory */
+ bbdev->data->dev_private = rte_zmalloc_socket(dev_name,
+ sizeof(struct acc_device), RTE_CACHE_LINE_SIZE,
+ pci_dev->device.numa_node);
+
+ if (bbdev->data->dev_private == NULL) {
+ rte_bbdev_log(CRIT,
+ "Allocate of %zu bytes for device \"%s\" failed",
+ sizeof(struct acc_device), dev_name);
+ rte_bbdev_release(bbdev);
+ return -ENOMEM;
+ }
+
+ /* Fill HW specific part of device structure */
+ bbdev->device = &pci_dev->device;
+ bbdev->intr_handle = pci_dev->intr_handle;
+ bbdev->data->socket_id = pci_dev->device.numa_node;
+
+ /* Invoke ACC100 device initialization function */
+ acc100_bbdev_init(bbdev, pci_drv);
+
+ rte_bbdev_log_debug("Initialised bbdev %s (id = %u)",
+ dev_name, bbdev->data->dev_id);
+ return 0;
+}
+
+static struct rte_pci_driver acc100_pci_pf_driver = {
+ .probe = acc100_pci_probe,
+ .remove = acc_pci_remove,
+ .id_table = pci_id_acc100_pf_map,
+ .drv_flags = RTE_PCI_DRV_NEED_MAPPING
+};
+
+static struct rte_pci_driver acc100_pci_vf_driver = {
+ .probe = acc100_pci_probe,
+ .remove = acc_pci_remove,
+ .id_table = pci_id_acc100_vf_map,
+ .drv_flags = RTE_PCI_DRV_NEED_MAPPING
+};
+
+RTE_PMD_REGISTER_PCI(ACC100PF_DRIVER_NAME, acc100_pci_pf_driver);
+RTE_PMD_REGISTER_PCI_TABLE(ACC100PF_DRIVER_NAME, pci_id_acc100_pf_map);
+RTE_PMD_REGISTER_PCI(ACC100VF_DRIVER_NAME, acc100_pci_vf_driver);
+RTE_PMD_REGISTER_PCI_TABLE(ACC100VF_DRIVER_NAME, pci_id_acc100_vf_map);
diff --git a/drivers/baseband/acc/rte_acc200_pmd.c b/drivers/baseband/acc/rte_acc200_pmd.c
index 8ee9023451..d219c5d4db 100644
--- a/drivers/baseband/acc/rte_acc200_pmd.c
+++ b/drivers/baseband/acc/rte_acc200_pmd.c
@@ -1154,34 +1154,6 @@ acc200_queue_intr_disable(struct rte_bbdev *dev, uint16_t queue_id)
return 0;
}
-static const struct rte_bbdev_ops acc200_bbdev_ops = {
- .setup_queues = acc200_setup_queues,
- .intr_enable = acc200_intr_enable,
- .close = acc200_dev_close,
- .info_get = acc200_dev_info_get,
- .queue_setup = acc200_queue_setup,
- .queue_release = acc200_queue_release,
- .queue_stop = acc200_queue_stop,
- .queue_intr_enable = acc200_queue_intr_enable,
- .queue_intr_disable = acc200_queue_intr_disable
-};
-
-/* ACC200 PCI PF address map. */
-static struct rte_pci_id pci_id_acc200_pf_map[] = {
- {
- RTE_PCI_DEVICE(RTE_ACC200_VENDOR_ID, RTE_ACC200_PF_DEVICE_ID)
- },
- {.device_id = 0},
-};
-
-/* ACC200 PCI VF address map. */
-static struct rte_pci_id pci_id_acc200_vf_map[] = {
- {
- RTE_PCI_DEVICE(RTE_ACC200_VENDOR_ID, RTE_ACC200_VF_DEVICE_ID)
- },
- {.device_id = 0},
-};
-
/* Fill in a frame control word for turbo decoding. */
static inline void
acc200_fcw_td_fill(const struct rte_bbdev_dec_op *op, struct acc_fcw_td *fcw)
@@ -3320,108 +3292,15 @@ acc200_dequeue_fft(struct rte_bbdev_queue_data *q_data,
return i;
}
-/* Initialization Function */
-static void
-acc200_bbdev_init(struct rte_bbdev *dev, struct rte_pci_driver *drv)
-{
- struct rte_pci_device *pci_dev = RTE_DEV_TO_PCI(dev->device);
-
- dev->dev_ops = &acc200_bbdev_ops;
- dev->enqueue_enc_ops = acc200_enqueue_enc;
- dev->enqueue_dec_ops = acc200_enqueue_dec;
- dev->dequeue_enc_ops = acc200_dequeue_enc;
- dev->dequeue_dec_ops = acc200_dequeue_dec;
- dev->enqueue_ldpc_enc_ops = acc200_enqueue_ldpc_enc;
- dev->enqueue_ldpc_dec_ops = acc200_enqueue_ldpc_dec;
- dev->dequeue_ldpc_enc_ops = acc200_dequeue_ldpc_enc;
- dev->dequeue_ldpc_dec_ops = acc200_dequeue_ldpc_dec;
- dev->enqueue_fft_ops = acc200_enqueue_fft;
- dev->dequeue_fft_ops = acc200_dequeue_fft;
-
- ((struct acc_device *) dev->data->dev_private)->pf_device =
- !strcmp(drv->driver.name,
- RTE_STR(ACC200PF_DRIVER_NAME));
- ((struct acc_device *) dev->data->dev_private)->mmio_base =
- pci_dev->mem_resource[0].addr;
-
- rte_bbdev_log_debug("Init device %s [%s] @ vaddr %p paddr %#"PRIx64"",
- drv->driver.name, dev->data->name,
- (void *)pci_dev->mem_resource[0].addr,
- pci_dev->mem_resource[0].phys_addr);
-}
-
-static int acc200_pci_probe(struct rte_pci_driver *pci_drv,
- struct rte_pci_device *pci_dev)
-{
- struct rte_bbdev *bbdev = NULL;
- char dev_name[RTE_BBDEV_NAME_MAX_LEN];
-
- if (pci_dev == NULL) {
- rte_bbdev_log(ERR, "NULL PCI device");
- return -EINVAL;
- }
-
- rte_pci_device_name(&pci_dev->addr, dev_name, sizeof(dev_name));
-
- /* Allocate memory to be used privately by drivers. */
- bbdev = rte_bbdev_allocate(pci_dev->device.name);
- if (bbdev == NULL)
- return -ENODEV;
-
- /* allocate device private memory. */
- bbdev->data->dev_private = rte_zmalloc_socket(dev_name,
- sizeof(struct acc_device), RTE_CACHE_LINE_SIZE,
- pci_dev->device.numa_node);
-
- if (bbdev->data->dev_private == NULL) {
- rte_bbdev_log(CRIT,
- "Allocate of %zu bytes for device \"%s\" failed",
- sizeof(struct acc_device), dev_name);
- rte_bbdev_release(bbdev);
- return -ENOMEM;
- }
-
- /* Fill HW specific part of device structure. */
- bbdev->device = &pci_dev->device;
- bbdev->intr_handle = pci_dev->intr_handle;
- bbdev->data->socket_id = pci_dev->device.numa_node;
-
- /* Invoke ACC200 device initialization function. */
- acc200_bbdev_init(bbdev, pci_drv);
-
- rte_bbdev_log_debug("Initialised bbdev %s (id = %u)",
- dev_name, bbdev->data->dev_id);
- return 0;
-}
-
-static struct rte_pci_driver acc200_pci_pf_driver = {
- .probe = acc200_pci_probe,
- .remove = acc_pci_remove,
- .id_table = pci_id_acc200_pf_map,
- .drv_flags = RTE_PCI_DRV_NEED_MAPPING
-};
-
-static struct rte_pci_driver acc200_pci_vf_driver = {
- .probe = acc200_pci_probe,
- .remove = acc_pci_remove,
- .id_table = pci_id_acc200_vf_map,
- .drv_flags = RTE_PCI_DRV_NEED_MAPPING
-};
-
-RTE_PMD_REGISTER_PCI(ACC200PF_DRIVER_NAME, acc200_pci_pf_driver);
-RTE_PMD_REGISTER_PCI_TABLE(ACC200PF_DRIVER_NAME, pci_id_acc200_pf_map);
-RTE_PMD_REGISTER_PCI(ACC200VF_DRIVER_NAME, acc200_pci_vf_driver);
-RTE_PMD_REGISTER_PCI_TABLE(ACC200VF_DRIVER_NAME, pci_id_acc200_vf_map);
-
/* Initial configuration of a ACC200 device prior to running configure(). */
-int
-acc200_configure(const char *dev_name, struct rte_acc_conf *conf)
+static int
+acc200_configure(struct rte_bbdev *bbdev, void *config)
{
rte_bbdev_log(INFO, "acc200_configure");
uint32_t value, address, status;
int qg_idx, template_idx, vf_idx, acc, i, rlim, alen, timestamp, totalQgs, numEngines;
int numQgs, numQqsAcc;
- struct rte_bbdev *bbdev = rte_bbdev_get_named_dev(dev_name);
+ struct rte_acc_conf *conf = (struct rte_acc_conf *)config;
/* Compile time checks. */
RTE_BUILD_BUG_ON(sizeof(struct acc_dma_req_desc) != 256);
@@ -3429,12 +3308,6 @@ acc200_configure(const char *dev_name, struct rte_acc_conf *conf)
RTE_BUILD_BUG_ON(sizeof(struct acc_fcw_td) != 24);
RTE_BUILD_BUG_ON(sizeof(struct acc_fcw_te) != 32);
- if (bbdev == NULL) {
- rte_bbdev_log(ERR,
- "Invalid dev_name (%s), or device is not yet initialised",
- dev_name);
- return -ENODEV;
- }
struct acc_device *d = bbdev->data->dev_private;
/* Store configuration. */
@@ -3819,3 +3692,126 @@ acc200_configure(const char *dev_name, struct rte_acc_conf *conf)
rte_bbdev_log_debug("PF Tip configuration complete for %s", dev_name);
return 0;
}
+
+static const struct rte_bbdev_ops acc200_bbdev_ops = {
+ .setup_queues = acc200_setup_queues,
+ .intr_enable = acc200_intr_enable,
+ .close = acc200_dev_close,
+ .info_get = acc200_dev_info_get,
+ .queue_setup = acc200_queue_setup,
+ .queue_release = acc200_queue_release,
+ .queue_stop = acc200_queue_stop,
+ .queue_intr_enable = acc200_queue_intr_enable,
+ .queue_intr_disable = acc200_queue_intr_disable,
+ .pf_init_helper = acc200_configure
+};
+
+/* ACC200 PCI PF address map. */
+static struct rte_pci_id pci_id_acc200_pf_map[] = {
+ {
+ RTE_PCI_DEVICE(RTE_ACC200_VENDOR_ID, RTE_ACC200_PF_DEVICE_ID)
+ },
+ {.device_id = 0},
+};
+
+/* ACC200 PCI VF address map. */
+static struct rte_pci_id pci_id_acc200_vf_map[] = {
+ {
+ RTE_PCI_DEVICE(RTE_ACC200_VENDOR_ID, RTE_ACC200_VF_DEVICE_ID)
+ },
+ {.device_id = 0},
+};
+
+
+/* Initialization Function */
+static void
+acc200_bbdev_init(struct rte_bbdev *dev, struct rte_pci_driver *drv)
+{
+ struct rte_pci_device *pci_dev = RTE_DEV_TO_PCI(dev->device);
+
+ dev->dev_ops = &acc200_bbdev_ops;
+ dev->enqueue_enc_ops = acc200_enqueue_enc;
+ dev->enqueue_dec_ops = acc200_enqueue_dec;
+ dev->dequeue_enc_ops = acc200_dequeue_enc;
+ dev->dequeue_dec_ops = acc200_dequeue_dec;
+ dev->enqueue_ldpc_enc_ops = acc200_enqueue_ldpc_enc;
+ dev->enqueue_ldpc_dec_ops = acc200_enqueue_ldpc_dec;
+ dev->dequeue_ldpc_enc_ops = acc200_dequeue_ldpc_enc;
+ dev->dequeue_ldpc_dec_ops = acc200_dequeue_ldpc_dec;
+ dev->enqueue_fft_ops = acc200_enqueue_fft;
+ dev->dequeue_fft_ops = acc200_dequeue_fft;
+
+ ((struct acc_device *) dev->data->dev_private)->pf_device =
+ !strcmp(drv->driver.name,
+ RTE_STR(ACC200PF_DRIVER_NAME));
+ ((struct acc_device *) dev->data->dev_private)->mmio_base =
+ pci_dev->mem_resource[0].addr;
+
+ rte_bbdev_log_debug("Init device %s [%s] @ vaddr %p paddr %#"PRIx64"",
+ drv->driver.name, dev->data->name,
+ (void *)pci_dev->mem_resource[0].addr,
+ pci_dev->mem_resource[0].phys_addr);
+}
+
+static int acc200_pci_probe(struct rte_pci_driver *pci_drv,
+ struct rte_pci_device *pci_dev)
+{
+ struct rte_bbdev *bbdev = NULL;
+ char dev_name[RTE_BBDEV_NAME_MAX_LEN];
+
+ if (pci_dev == NULL) {
+ rte_bbdev_log(ERR, "NULL PCI device");
+ return -EINVAL;
+ }
+
+ rte_pci_device_name(&pci_dev->addr, dev_name, sizeof(dev_name));
+
+ /* Allocate memory to be used privately by drivers. */
+ bbdev = rte_bbdev_allocate(pci_dev->device.name);
+ if (bbdev == NULL)
+ return -ENODEV;
+
+ /* allocate device private memory. */
+ bbdev->data->dev_private = rte_zmalloc_socket(dev_name,
+ sizeof(struct acc_device), RTE_CACHE_LINE_SIZE,
+ pci_dev->device.numa_node);
+
+ if (bbdev->data->dev_private == NULL) {
+ rte_bbdev_log(CRIT,
+ "Allocate of %zu bytes for device \"%s\" failed",
+ sizeof(struct acc_device), dev_name);
+ rte_bbdev_release(bbdev);
+ return -ENOMEM;
+ }
+
+ /* Fill HW specific part of device structure. */
+ bbdev->device = &pci_dev->device;
+ bbdev->intr_handle = pci_dev->intr_handle;
+ bbdev->data->socket_id = pci_dev->device.numa_node;
+
+ /* Invoke ACC200 device initialization function. */
+ acc200_bbdev_init(bbdev, pci_drv);
+
+ rte_bbdev_log_debug("Initialised bbdev %s (id = %u)",
+ dev_name, bbdev->data->dev_id);
+ return 0;
+}
+
+static struct rte_pci_driver acc200_pci_pf_driver = {
+ .probe = acc200_pci_probe,
+ .remove = acc_pci_remove,
+ .id_table = pci_id_acc200_pf_map,
+ .drv_flags = RTE_PCI_DRV_NEED_MAPPING
+};
+
+static struct rte_pci_driver acc200_pci_vf_driver = {
+ .probe = acc200_pci_probe,
+ .remove = acc_pci_remove,
+ .id_table = pci_id_acc200_vf_map,
+ .drv_flags = RTE_PCI_DRV_NEED_MAPPING
+};
+
+RTE_PMD_REGISTER_PCI(ACC200PF_DRIVER_NAME, acc200_pci_pf_driver);
+RTE_PMD_REGISTER_PCI_TABLE(ACC200PF_DRIVER_NAME, pci_id_acc200_pf_map);
+RTE_PMD_REGISTER_PCI(ACC200VF_DRIVER_NAME, acc200_pci_vf_driver);
+RTE_PMD_REGISTER_PCI_TABLE(ACC200VF_DRIVER_NAME, pci_id_acc200_vf_map);
diff --git a/drivers/baseband/acc/rte_acc_cfg.h b/drivers/baseband/acc/rte_acc_cfg.h
deleted file mode 100644
index 21bcf88dad..0000000000
--- a/drivers/baseband/acc/rte_acc_cfg.h
+++ /dev/null
@@ -1,49 +0,0 @@
-/* SPDX-License-Identifier: BSD-3-Clause
- * Copyright(c) 2022 Intel Corporation
- */
-
-#ifndef _RTE_ACC_CFG_H_
-#define _RTE_ACC_CFG_H_
-
-/**
- * @file rte_acc_cfg.h
- *
- * Functions for configuring ACC HW, exposed directly to applications.
- * Configuration related to encoding/decoding is done through the
- * librte_bbdev library.
- *
- * @warning
- * @b EXPERIMENTAL: this API may change without prior notice
- */
-
-#include <stdint.h>
-#include <stdbool.h>
-#include "rte_acc_common_cfg.h"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-
-/**
- * Configure a ACC device in PF mode notably for bbdev-test
- *
- * @param dev_name
- * The name of the device. This is the short form of PCI BDF, e.g. 00:01.0.
- * It can also be retrieved for a bbdev device from the dev_name field in the
- * rte_bbdev_info structure returned by rte_bbdev_info_get().
- * @param conf
- * Configuration to apply to ACC HW.
- *
- * @return
- * Zero on success, negative value on failure.
- */
-__rte_experimental
-int
-rte_acc_configure(const char *dev_name, struct rte_acc_conf *conf);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* _RTE_ACC_CFG_H_ */
diff --git a/drivers/baseband/acc/rte_acc_common_cfg.h b/drivers/baseband/acc/rte_acc_common_cfg.h
index cce75d5878..28175c5dde 100644
--- a/drivers/baseband/acc/rte_acc_common_cfg.h
+++ b/drivers/baseband/acc/rte_acc_common_cfg.h
@@ -8,20 +8,13 @@
/**
* @file rte_acc_common_cfg.h
*
- * Functions for configuring ACC HW, exposed directly to applications.
- * Configuration related to encoding/decoding is done through the
- * librte_bbdev library.
- *
- * @warning
- * @b EXPERIMENTAL: this API may change without prior notice
+ * Structure used for the PF configuration from bbdev-test
+ * using *rte_pf_init_helper*.
*/
#include <stdint.h>
#include <stdbool.h>
-#ifdef __cplusplus
-extern "C" {
-#endif
/**< Maximum number of Virtual Functions ACC may support */
#define RTE_ACC_NUM_VFS 64
@@ -94,8 +87,4 @@ struct rte_acc_conf {
struct rte_acc_arbitration arb_mld[RTE_ACC_NUM_VFS];
};
-#ifdef __cplusplus
-}
-#endif
-
#endif /* _RTE_ACC_COMMON_CFG_H_ */
diff --git a/drivers/baseband/acc/version.map b/drivers/baseband/acc/version.map
index 95ae74dd35..78c3585d7c 100644
--- a/drivers/baseband/acc/version.map
+++ b/drivers/baseband/acc/version.map
@@ -1,9 +1,3 @@
DPDK_23 {
local: *;
};
-
-EXPERIMENTAL {
- global:
-
- rte_acc_configure;
-};
diff --git a/drivers/baseband/fpga_5gnr_fec/rte_fpga_5gnr_fec.c b/drivers/baseband/fpga_5gnr_fec/rte_fpga_5gnr_fec.c
index d520d5238f..b26d652e4e 100644
--- a/drivers/baseband/fpga_5gnr_fec/rte_fpga_5gnr_fec.c
+++ b/drivers/baseband/fpga_5gnr_fec/rte_fpga_5gnr_fec.c
@@ -781,19 +781,6 @@ fpga_intr_enable(struct rte_bbdev *dev)
return 0;
}
-static const struct rte_bbdev_ops fpga_ops = {
- .setup_queues = fpga_setup_queues,
- .intr_enable = fpga_intr_enable,
- .close = fpga_dev_close,
- .info_get = fpga_dev_info_get,
- .queue_setup = fpga_queue_setup,
- .queue_stop = fpga_queue_stop,
- .queue_start = fpga_queue_start,
- .queue_release = fpga_queue_release,
- .queue_intr_enable = fpga_queue_intr_enable,
- .queue_intr_disable = fpga_queue_intr_disable
-};
-
static inline void
fpga_dma_enqueue(struct fpga_queue *q, uint16_t num_desc,
struct rte_bbdev_stats *queue_stats)
@@ -2142,90 +2129,6 @@ fpga_dequeue_ldpc_dec(struct rte_bbdev_queue_data *q_data,
return i;
}
-
-/* Initialization Function */
-static void
-fpga_5gnr_fec_init(struct rte_bbdev *dev, struct rte_pci_driver *drv)
-{
- struct rte_pci_device *pci_dev = RTE_DEV_TO_PCI(dev->device);
-
- dev->dev_ops = &fpga_ops;
- dev->enqueue_ldpc_enc_ops = fpga_enqueue_ldpc_enc;
- dev->enqueue_ldpc_dec_ops = fpga_enqueue_ldpc_dec;
- dev->dequeue_ldpc_enc_ops = fpga_dequeue_ldpc_enc;
- dev->dequeue_ldpc_dec_ops = fpga_dequeue_ldpc_dec;
-
- ((struct fpga_5gnr_fec_device *) dev->data->dev_private)->pf_device =
- !strcmp(drv->driver.name,
- RTE_STR(FPGA_5GNR_FEC_PF_DRIVER_NAME));
- ((struct fpga_5gnr_fec_device *) dev->data->dev_private)->mmio_base =
- pci_dev->mem_resource[0].addr;
-
- rte_bbdev_log_debug(
- "Init device %s [%s] @ virtaddr %p phyaddr %#"PRIx64,
- drv->driver.name, dev->data->name,
- (void *)pci_dev->mem_resource[0].addr,
- pci_dev->mem_resource[0].phys_addr);
-}
-
-static int
-fpga_5gnr_fec_probe(struct rte_pci_driver *pci_drv,
- struct rte_pci_device *pci_dev)
-{
- struct rte_bbdev *bbdev = NULL;
- char dev_name[RTE_BBDEV_NAME_MAX_LEN];
-
- if (pci_dev == NULL) {
- rte_bbdev_log(ERR, "NULL PCI device");
- return -EINVAL;
- }
-
- rte_pci_device_name(&pci_dev->addr, dev_name, sizeof(dev_name));
-
- /* Allocate memory to be used privately by drivers */
- bbdev = rte_bbdev_allocate(pci_dev->device.name);
- if (bbdev == NULL)
- return -ENODEV;
-
- /* allocate device private memory */
- bbdev->data->dev_private = rte_zmalloc_socket(dev_name,
- sizeof(struct fpga_5gnr_fec_device),
- RTE_CACHE_LINE_SIZE,
- pci_dev->device.numa_node);
-
- if (bbdev->data->dev_private == NULL) {
- rte_bbdev_log(CRIT,
- "Allocate of %zu bytes for device \"%s\" failed",
- sizeof(struct fpga_5gnr_fec_device), dev_name);
- rte_bbdev_release(bbdev);
- return -ENOMEM;
- }
-
- /* Fill HW specific part of device structure */
- bbdev->device = &pci_dev->device;
- bbdev->intr_handle = pci_dev->intr_handle;
- bbdev->data->socket_id = pci_dev->device.numa_node;
-
- /* Invoke FEC FPGA device initialization function */
- fpga_5gnr_fec_init(bbdev, pci_drv);
-
- rte_bbdev_log_debug("bbdev id = %u [%s]",
- bbdev->data->dev_id, dev_name);
-
- struct fpga_5gnr_fec_device *d = bbdev->data->dev_private;
- uint32_t version_id = fpga_reg_read_32(d->mmio_base,
- FPGA_5GNR_FEC_VERSION_ID);
- rte_bbdev_log(INFO, "FEC FPGA RTL v%u.%u",
- ((uint16_t)(version_id >> 16)), ((uint16_t)version_id));
-
-#ifdef RTE_LIBRTE_BBDEV_DEBUG
- if (!strcmp(pci_drv->driver.name,
- RTE_STR(FPGA_5GNR_FEC_PF_DRIVER_NAME)))
- print_static_reg_debug_info(d->mmio_base);
-#endif
- return 0;
-}
-
static int
fpga_5gnr_fec_remove(struct rte_pci_device *pci_dev)
{
@@ -2285,21 +2188,18 @@ set_default_fpga_conf(struct rte_fpga_5gnr_fec_conf *def_conf)
}
/* Initial configuration of FPGA 5GNR FEC device */
-int
-rte_fpga_5gnr_fec_configure(const char *dev_name,
- const struct rte_fpga_5gnr_fec_conf *conf)
+static int
+fpga_5gnr_fec_configure(struct rte_bbdev *bbdev, void *config)
{
uint32_t payload_32, address;
uint16_t payload_16;
uint8_t payload_8;
uint16_t q_id, vf_id, total_q_id, total_ul_q_id, total_dl_q_id;
- struct rte_bbdev *bbdev = rte_bbdev_get_named_dev(dev_name);
struct rte_fpga_5gnr_fec_conf def_conf;
+ const struct rte_fpga_5gnr_fec_conf *conf = config;
if (bbdev == NULL) {
- rte_bbdev_log(ERR,
- "Invalid dev_name (%s), or device is not yet initialised",
- dev_name);
+ rte_bbdev_log(ERR, "Invalid device, or device is not yet initialised");
return -ENODEV;
}
@@ -2457,6 +2357,104 @@ rte_fpga_5gnr_fec_configure(const char *dev_name,
return 0;
}
+static const struct rte_bbdev_ops fpga_ops = {
+ .setup_queues = fpga_setup_queues,
+ .intr_enable = fpga_intr_enable,
+ .close = fpga_dev_close,
+ .info_get = fpga_dev_info_get,
+ .queue_setup = fpga_queue_setup,
+ .queue_stop = fpga_queue_stop,
+ .queue_start = fpga_queue_start,
+ .queue_release = fpga_queue_release,
+ .queue_intr_enable = fpga_queue_intr_enable,
+ .queue_intr_disable = fpga_queue_intr_disable,
+ .pf_init_helper = fpga_5gnr_fec_configure
+};
+
+
+/* Initialization Function */
+static void
+fpga_5gnr_fec_init(struct rte_bbdev *dev, struct rte_pci_driver *drv)
+{
+ struct rte_pci_device *pci_dev = RTE_DEV_TO_PCI(dev->device);
+
+ dev->dev_ops = &fpga_ops;
+ dev->enqueue_ldpc_enc_ops = fpga_enqueue_ldpc_enc;
+ dev->enqueue_ldpc_dec_ops = fpga_enqueue_ldpc_dec;
+ dev->dequeue_ldpc_enc_ops = fpga_dequeue_ldpc_enc;
+ dev->dequeue_ldpc_dec_ops = fpga_dequeue_ldpc_dec;
+
+ ((struct fpga_5gnr_fec_device *) dev->data->dev_private)->pf_device =
+ !strcmp(drv->driver.name,
+ RTE_STR(FPGA_5GNR_FEC_PF_DRIVER_NAME));
+ ((struct fpga_5gnr_fec_device *) dev->data->dev_private)->mmio_base =
+ pci_dev->mem_resource[0].addr;
+
+ rte_bbdev_log_debug(
+ "Init device %s [%s] @ virtaddr %p phyaddr %#"PRIx64,
+ drv->driver.name, dev->data->name,
+ (void *)pci_dev->mem_resource[0].addr,
+ pci_dev->mem_resource[0].phys_addr);
+}
+
+static int
+fpga_5gnr_fec_probe(struct rte_pci_driver *pci_drv,
+ struct rte_pci_device *pci_dev)
+{
+ struct rte_bbdev *bbdev = NULL;
+ char dev_name[RTE_BBDEV_NAME_MAX_LEN];
+
+ if (pci_dev == NULL) {
+ rte_bbdev_log(ERR, "NULL PCI device");
+ return -EINVAL;
+ }
+
+ rte_pci_device_name(&pci_dev->addr, dev_name, sizeof(dev_name));
+
+ /* Allocate memory to be used privately by drivers */
+ bbdev = rte_bbdev_allocate(pci_dev->device.name);
+ if (bbdev == NULL)
+ return -ENODEV;
+
+ /* allocate device private memory */
+ bbdev->data->dev_private = rte_zmalloc_socket(dev_name,
+ sizeof(struct fpga_5gnr_fec_device),
+ RTE_CACHE_LINE_SIZE,
+ pci_dev->device.numa_node);
+
+ if (bbdev->data->dev_private == NULL) {
+ rte_bbdev_log(CRIT,
+ "Allocate of %zu bytes for device \"%s\" failed",
+ sizeof(struct fpga_5gnr_fec_device), dev_name);
+ rte_bbdev_release(bbdev);
+ return -ENOMEM;
+ }
+
+ /* Fill HW specific part of device structure */
+ bbdev->device = &pci_dev->device;
+ bbdev->intr_handle = pci_dev->intr_handle;
+ bbdev->data->socket_id = pci_dev->device.numa_node;
+
+ /* Invoke FEC FPGA device initialization function */
+ fpga_5gnr_fec_init(bbdev, pci_drv);
+
+ rte_bbdev_log_debug("bbdev id = %u [%s]",
+ bbdev->data->dev_id, dev_name);
+
+ struct fpga_5gnr_fec_device *d = bbdev->data->dev_private;
+ uint32_t version_id = fpga_reg_read_32(d->mmio_base,
+ FPGA_5GNR_FEC_VERSION_ID);
+ rte_bbdev_log(INFO, "FEC FPGA RTL v%u.%u",
+ ((uint16_t)(version_id >> 16)), ((uint16_t)version_id));
+
+#ifdef RTE_LIBRTE_BBDEV_DEBUG
+ if (!strcmp(pci_drv->driver.name,
+ RTE_STR(FPGA_5GNR_FEC_PF_DRIVER_NAME)))
+ print_static_reg_debug_info(d->mmio_base);
+#endif
+ return 0;
+}
+
/* FPGA 5GNR FEC PCI PF address map */
static struct rte_pci_id pci_id_fpga_5gnr_fec_pf_map[] = {
{
diff --git a/drivers/baseband/fpga_5gnr_fec/rte_pmd_fpga_5gnr_fec.h b/drivers/baseband/fpga_5gnr_fec/rte_pmd_fpga_5gnr_fec.h
index 93a87c8e82..1c0eb7d815 100644
--- a/drivers/baseband/fpga_5gnr_fec/rte_pmd_fpga_5gnr_fec.h
+++ b/drivers/baseband/fpga_5gnr_fec/rte_pmd_fpga_5gnr_fec.h
@@ -11,19 +11,10 @@
/**
* @file rte_pmd_fpga_5gnr_fec.h
*
- * Interface for Intel(R) FGPA 5GNR FEC device configuration at the host level,
- * directly accessible by the application.
- * Configuration related to 5GNR functionality is done through
- * librte_bbdev library.
- *
- * @warning
- * @b EXPERIMENTAL: this API may change without prior notice
+ * Structure used for the PF configuration from bbdev-test
+ * using *rte_pf_init_helper*.
*/
-#ifdef __cplusplus
-extern "C" {
-#endif
-
/** Number of Virtual Functions FGPA 4G FEC supports */
#define FPGA_5GNR_FEC_NUM_VFS 8
@@ -47,26 +38,4 @@ struct rte_fpga_5gnr_fec_conf {
uint8_t dl_load_balance;
};
-/**
- * Configure Intel(R) FPGA 5GNR FEC device
- *
- * @param dev_name
- * The name of the device. This is the short form of PCI BDF, e.g. 00:01.0.
- * It can also be retrieved for a bbdev device from the dev_name field in the
- * rte_bbdev_info structure returned by rte_bbdev_info_get().
- * @param conf
- * Configuration to apply to FPGA 4G FEC.
- *
- * @return
- * Zero on success, negative value on failure.
- */
-__rte_experimental
-int
-rte_fpga_5gnr_fec_configure(const char *dev_name,
- const struct rte_fpga_5gnr_fec_conf *conf);
-
-#ifdef __cplusplus
-}
-#endif
-
#endif /* _RTE_PMD_FPGA_5GNR_FEC_H_ */
diff --git a/drivers/baseband/fpga_5gnr_fec/version.map b/drivers/baseband/fpga_5gnr_fec/version.map
index 6b191cf330..78c3585d7c 100644
--- a/drivers/baseband/fpga_5gnr_fec/version.map
+++ b/drivers/baseband/fpga_5gnr_fec/version.map
@@ -1,10 +1,3 @@
DPDK_23 {
local: *;
};
-
-EXPERIMENTAL {
- global:
-
- rte_fpga_5gnr_fec_configure;
-
-};
diff --git a/drivers/baseband/fpga_lte_fec/fpga_lte_fec.c b/drivers/baseband/fpga_lte_fec/fpga_lte_fec.c
index fc86f13bee..8083905efe 100644
--- a/drivers/baseband/fpga_lte_fec/fpga_lte_fec.c
+++ b/drivers/baseband/fpga_lte_fec/fpga_lte_fec.c
@@ -1056,19 +1056,6 @@ fpga_intr_enable(struct rte_bbdev *dev)
return 0;
}
-static const struct rte_bbdev_ops fpga_ops = {
- .setup_queues = fpga_setup_queues,
- .intr_enable = fpga_intr_enable,
- .close = fpga_dev_close,
- .info_get = fpga_dev_info_get,
- .queue_setup = fpga_queue_setup,
- .queue_stop = fpga_queue_stop,
- .queue_start = fpga_queue_start,
- .queue_release = fpga_queue_release,
- .queue_intr_enable = fpga_queue_intr_enable,
- .queue_intr_disable = fpga_queue_intr_disable
-};
-
static inline void
fpga_dma_enqueue(struct fpga_queue *q, uint16_t num_desc,
struct rte_bbdev_stats *queue_stats)
@@ -2320,88 +2307,6 @@ fpga_dequeue_dec(struct rte_bbdev_queue_data *q_data,
return i;
}
-/* Initialization Function */
-static void
-fpga_lte_fec_init(struct rte_bbdev *dev, struct rte_pci_driver *drv)
-{
- struct rte_pci_device *pci_dev = RTE_DEV_TO_PCI(dev->device);
-
- dev->dev_ops = &fpga_ops;
- dev->enqueue_enc_ops = fpga_enqueue_enc;
- dev->enqueue_dec_ops = fpga_enqueue_dec;
- dev->dequeue_enc_ops = fpga_dequeue_enc;
- dev->dequeue_dec_ops = fpga_dequeue_dec;
-
- ((struct fpga_lte_fec_device *) dev->data->dev_private)->pf_device =
- !strcmp(drv->driver.name,
- RTE_STR(FPGA_LTE_FEC_PF_DRIVER_NAME));
- ((struct fpga_lte_fec_device *) dev->data->dev_private)->mmio_base =
- pci_dev->mem_resource[0].addr;
-
- rte_bbdev_log_debug(
- "Init device %s [%s] @ virtaddr %p phyaddr %#"PRIx64,
- drv->driver.name, dev->data->name,
- (void *)pci_dev->mem_resource[0].addr,
- pci_dev->mem_resource[0].phys_addr);
-}
-
-static int
-fpga_lte_fec_probe(struct rte_pci_driver *pci_drv,
- struct rte_pci_device *pci_dev)
-{
- struct rte_bbdev *bbdev = NULL;
- char dev_name[RTE_BBDEV_NAME_MAX_LEN];
-
- if (pci_dev == NULL) {
- rte_bbdev_log(ERR, "NULL PCI device");
- return -EINVAL;
- }
-
- rte_pci_device_name(&pci_dev->addr, dev_name, sizeof(dev_name));
-
- /* Allocate memory to be used privately by drivers */
- bbdev = rte_bbdev_allocate(pci_dev->device.name);
- if (bbdev == NULL)
- return -ENODEV;
-
- /* allocate device private memory */
- bbdev->data->dev_private = rte_zmalloc_socket(dev_name,
- sizeof(struct fpga_lte_fec_device), RTE_CACHE_LINE_SIZE,
- pci_dev->device.numa_node);
-
- if (bbdev->data->dev_private == NULL) {
- rte_bbdev_log(CRIT,
- "Allocate of %zu bytes for device \"%s\" failed",
- sizeof(struct fpga_lte_fec_device), dev_name);
- rte_bbdev_release(bbdev);
- return -ENOMEM;
- }
-
- /* Fill HW specific part of device structure */
- bbdev->device = &pci_dev->device;
- bbdev->intr_handle = pci_dev->intr_handle;
- bbdev->data->socket_id = pci_dev->device.numa_node;
-
- /* Invoke FEC FPGA device initialization function */
- fpga_lte_fec_init(bbdev, pci_drv);
-
- rte_bbdev_log_debug("bbdev id = %u [%s]",
- bbdev->data->dev_id, dev_name);
-
- struct fpga_lte_fec_device *d = bbdev->data->dev_private;
- uint32_t version_id = fpga_reg_read_32(d->mmio_base,
- FPGA_LTE_FEC_VERSION_ID);
- rte_bbdev_log(INFO, "FEC FPGA RTL v%u.%u",
- ((uint16_t)(version_id >> 16)), ((uint16_t)version_id));
-
-#ifdef RTE_LIBRTE_BBDEV_DEBUG
- if (!strcmp(pci_drv->driver.name,
- RTE_STR(FPGA_LTE_FEC_PF_DRIVER_NAME)))
- print_static_reg_debug_info(d->mmio_base);
-#endif
- return 0;
-}
-
static int
fpga_lte_fec_remove(struct rte_pci_device *pci_dev)
{
@@ -2461,21 +2366,18 @@ set_default_fpga_conf(struct rte_fpga_lte_fec_conf *def_conf)
}
/* Initial configuration of FPGA LTE FEC device */
-int
-rte_fpga_lte_fec_configure(const char *dev_name,
- const struct rte_fpga_lte_fec_conf *conf)
+static int
+fpga_lte_fec_configure(struct rte_bbdev *bbdev, void *config)
{
uint32_t payload_32, address;
uint16_t payload_16;
uint8_t payload_8;
uint16_t q_id, vf_id, total_q_id, total_ul_q_id, total_dl_q_id;
- struct rte_bbdev *bbdev = rte_bbdev_get_named_dev(dev_name);
struct rte_fpga_lte_fec_conf def_conf;
+ const struct rte_fpga_lte_fec_conf *conf = config;
if (bbdev == NULL) {
- rte_bbdev_log(ERR,
- "Invalid dev_name (%s), or device is not yet initialised",
- dev_name);
+ rte_bbdev_log(ERR, "Invalid device, or device is not yet initialised");
return -ENODEV;
}
@@ -2638,6 +2540,102 @@ rte_fpga_lte_fec_configure(const char *dev_name,
return 0;
}
+static const struct rte_bbdev_ops fpga_ops = {
+ .setup_queues = fpga_setup_queues,
+ .intr_enable = fpga_intr_enable,
+ .close = fpga_dev_close,
+ .info_get = fpga_dev_info_get,
+ .queue_setup = fpga_queue_setup,
+ .queue_stop = fpga_queue_stop,
+ .queue_start = fpga_queue_start,
+ .queue_release = fpga_queue_release,
+ .queue_intr_enable = fpga_queue_intr_enable,
+ .queue_intr_disable = fpga_queue_intr_disable,
+ .pf_init_helper = fpga_lte_fec_configure
+};
+
+/* Initialization Function */
+static void
+fpga_lte_fec_init(struct rte_bbdev *dev, struct rte_pci_driver *drv)
+{
+ struct rte_pci_device *pci_dev = RTE_DEV_TO_PCI(dev->device);
+
+ dev->dev_ops = &fpga_ops;
+ dev->enqueue_enc_ops = fpga_enqueue_enc;
+ dev->enqueue_dec_ops = fpga_enqueue_dec;
+ dev->dequeue_enc_ops = fpga_dequeue_enc;
+ dev->dequeue_dec_ops = fpga_dequeue_dec;
+
+ ((struct fpga_lte_fec_device *) dev->data->dev_private)->pf_device =
+ !strcmp(drv->driver.name,
+ RTE_STR(FPGA_LTE_FEC_PF_DRIVER_NAME));
+ ((struct fpga_lte_fec_device *) dev->data->dev_private)->mmio_base =
+ pci_dev->mem_resource[0].addr;
+
+ rte_bbdev_log_debug(
+ "Init device %s [%s] @ virtaddr %p phyaddr %#"PRIx64,
+ drv->driver.name, dev->data->name,
+ (void *)pci_dev->mem_resource[0].addr,
+ pci_dev->mem_resource[0].phys_addr);
+}
+
+static int
+fpga_lte_fec_probe(struct rte_pci_driver *pci_drv,
+ struct rte_pci_device *pci_dev)
+{
+ struct rte_bbdev *bbdev = NULL;
+ char dev_name[RTE_BBDEV_NAME_MAX_LEN];
+
+ if (pci_dev == NULL) {
+ rte_bbdev_log(ERR, "NULL PCI device");
+ return -EINVAL;
+ }
+
+ rte_pci_device_name(&pci_dev->addr, dev_name, sizeof(dev_name));
+
+ /* Allocate memory to be used privately by drivers */
+ bbdev = rte_bbdev_allocate(pci_dev->device.name);
+ if (bbdev == NULL)
+ return -ENODEV;
+
+ /* allocate device private memory */
+ bbdev->data->dev_private = rte_zmalloc_socket(dev_name,
+ sizeof(struct fpga_lte_fec_device), RTE_CACHE_LINE_SIZE,
+ pci_dev->device.numa_node);
+
+ if (bbdev->data->dev_private == NULL) {
+ rte_bbdev_log(CRIT,
+ "Allocate of %zu bytes for device \"%s\" failed",
+ sizeof(struct fpga_lte_fec_device), dev_name);
+ rte_bbdev_release(bbdev);
+ return -ENOMEM;
+ }
+
+ /* Fill HW specific part of device structure */
+ bbdev->device = &pci_dev->device;
+ bbdev->intr_handle = pci_dev->intr_handle;
+ bbdev->data->socket_id = pci_dev->device.numa_node;
+
+ /* Invoke FEC FPGA device initialization function */
+ fpga_lte_fec_init(bbdev, pci_drv);
+
+ rte_bbdev_log_debug("bbdev id = %u [%s]",
+ bbdev->data->dev_id, dev_name);
+
+ struct fpga_lte_fec_device *d = bbdev->data->dev_private;
+ uint32_t version_id = fpga_reg_read_32(d->mmio_base,
+ FPGA_LTE_FEC_VERSION_ID);
+ rte_bbdev_log(INFO, "FEC FPGA RTL v%u.%u",
+ ((uint16_t)(version_id >> 16)), ((uint16_t)version_id));
+
+#ifdef RTE_LIBRTE_BBDEV_DEBUG
+ if (!strcmp(pci_drv->driver.name,
+ RTE_STR(FPGA_LTE_FEC_PF_DRIVER_NAME)))
+ print_static_reg_debug_info(d->mmio_base);
+#endif
+ return 0;
+}
+
/* FPGA LTE FEC PCI PF address map */
static struct rte_pci_id pci_id_fpga_lte_fec_pf_map[] = {
{
diff --git a/drivers/baseband/fpga_lte_fec/fpga_lte_fec.h b/drivers/baseband/fpga_lte_fec/fpga_lte_fec.h
index b35c7a484e..b416e34018 100644
--- a/drivers/baseband/fpga_lte_fec/fpga_lte_fec.h
+++ b/drivers/baseband/fpga_lte_fec/fpga_lte_fec.h
@@ -11,19 +11,10 @@
/**
* @file fpga_lte_fec.h
*
- * Interface for Intel(R) FGPA LTE FEC device configuration at the host level,
- * directly accessible by the application.
- * Configuration related to LTE Turbo coding functionality is done through
- * librte_bbdev library.
- *
- * @warning
- * @b EXPERIMENTAL: this API may change without prior notice
+ * Structure used for the PF configuration from bbdev-test
+ * using *rte_pf_init_helper*.
*/
-#ifdef __cplusplus
-extern "C" {
-#endif
-
/**< Number of Virtual Functions FGPA 4G FEC supports */
#define FPGA_LTE_FEC_NUM_VFS 8
@@ -49,26 +40,4 @@ struct rte_fpga_lte_fec_conf {
uint16_t flr_time_out;
};
-/**
- * Configure Intel(R) FPGA LTE FEC device
- *
- * @param dev_name
- * The name of the device. This is the short form of PCI BDF, e.g. 00:01.0.
- * It can also be retrieved for a bbdev device from the dev_name field in the
- * rte_bbdev_info structure returned by rte_bbdev_info_get().
- * @param conf
- * Configuration to apply to FPGA 4G FEC.
- *
- * @return
- * Zero on success, negative value on failure.
- */
-__rte_experimental
-int
-rte_fpga_lte_fec_configure(const char *dev_name,
- const struct rte_fpga_lte_fec_conf *conf);
-
-#ifdef __cplusplus
-}
-#endif
-
#endif /* _FPGA_LTE_FEC_H_ */
diff --git a/drivers/baseband/fpga_lte_fec/version.map b/drivers/baseband/fpga_lte_fec/version.map
index aab28a9976..78c3585d7c 100644
--- a/drivers/baseband/fpga_lte_fec/version.map
+++ b/drivers/baseband/fpga_lte_fec/version.map
@@ -1,10 +1,3 @@
DPDK_23 {
local: *;
};
-
-EXPERIMENTAL {
- global:
-
- rte_fpga_lte_fec_configure;
-
-};
diff --git a/lib/bbdev/rte_bbdev.c b/lib/bbdev/rte_bbdev.c
index 1521cdbc53..a84bcac260 100644
--- a/lib/bbdev/rte_bbdev.c
+++ b/lib/bbdev/rte_bbdev.c
@@ -1184,3 +1184,23 @@ rte_bbdev_enqueue_status_str(enum rte_bbdev_enqueue_status status)
rte_bbdev_log(ERR, "Invalid enqueue status");
return NULL;
}
+
+int
+rte_bbdev_pf_init_helper(uint16_t dev_id, void *config)
+{
+ struct rte_bbdev *dev = get_dev(dev_id);
+ VALID_DEV_OR_RET_ERR(dev, dev_id);
+
+ VALID_DEV_OPS_OR_RET_ERR(dev, dev_id);
+
+ if (dev->dev_ops->pf_init_helper) {
+ int ret = dev->dev_ops->pf_init_helper(dev, config);
+ if (ret < 0) {
+ rte_bbdev_log(ERR, "Device %u PF inialization failed", dev_id);
+ return ret;
+ }
+ }
+
+ rte_bbdev_log_debug("PF initialization of device %u", dev_id);
+ return 0;
+}
diff --git a/lib/bbdev/rte_bbdev.h b/lib/bbdev/rte_bbdev.h
index 1eb5fa532b..b34c1ea7e6 100644
--- a/lib/bbdev/rte_bbdev.h
+++ b/lib/bbdev/rte_bbdev.h
@@ -230,6 +230,23 @@ rte_bbdev_queue_start(uint16_t dev_id, uint16_t queue_id);
int
rte_bbdev_queue_stop(uint16_t dev_id, uint16_t queue_id);
+/**
+ * Helper function to initialize the device from the PF.
+ * This is only meant to be used in the context of bbdev-test
+ * so that to be able to test the device from the PF without
+ * dependency on 3rd party configuration ingredients.
+ * Optional only.
+ *
+ * @param dev_id
+ * The identifier of the device.
+ *
+ * @return
+ * - negative value on failure - as returned from PMD
+ */
+__rte_experimental
+int
+rte_bbdev_pf_init_helper(uint16_t dev_id, void *config);
+
/**
* Flags to indicate the reason why a previous enqueue may not have
* consumed all requested operations.
diff --git a/lib/bbdev/rte_bbdev_pmd.h b/lib/bbdev/rte_bbdev_pmd.h
index 3da7a2bdf5..be71db91db 100644
--- a/lib/bbdev/rte_bbdev_pmd.h
+++ b/lib/bbdev/rte_bbdev_pmd.h
@@ -134,6 +134,13 @@ typedef int (*rte_bbdev_queue_intr_enable_t)(struct rte_bbdev *dev,
typedef int (*rte_bbdev_queue_intr_disable_t)(struct rte_bbdev *dev,
uint16_t queue_id);
+/*
+ * @internal
+ * Function to help to initialize the device from the PF.
+ * Only meant for test purpose notably using bbdev-test.
+ */
+typedef int (*rte_bbdev_pf_init_helper_t)(struct rte_bbdev *dev, void *conf);
+
/**
* Operations implemented by drivers. Fields marked as "Required" must be
* provided by a driver for a device to have basic functionality. "Optional"
@@ -171,6 +178,9 @@ struct rte_bbdev_ops {
rte_bbdev_queue_intr_enable_t queue_intr_enable;
/** Disable queue interrupt. Optional */
rte_bbdev_queue_intr_disable_t queue_intr_disable;
+
+ /** Companion helper to init device for testing purpose. Optional. */
+ rte_bbdev_pf_init_helper_t pf_init_helper;
};
/**
diff --git a/lib/bbdev/version.map b/lib/bbdev/version.map
index d0bb835255..d05d63483a 100644
--- a/lib/bbdev/version.map
+++ b/lib/bbdev/version.map
@@ -50,4 +50,5 @@ EXPERIMENTAL {
rte_bbdev_enqueue_status_str;
rte_bbdev_fft_op_alloc_bulk;
rte_bbdev_fft_op_free_bulk;
+ rte_bbdev_pf_init_helper;
};
--
2.37.1
prev parent reply other threads:[~2022-10-14 1:42 UTC|newest]
Thread overview: 2+ messages / expand[flat|nested] mbox.gz Atom feed top
2022-10-14 1:42 [RFC 0/1] baseband PMD API Nicolas Chautru
2022-10-14 1:42 ` Nicolas Chautru [this message]
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20221014014205.38074-2-nicolas.chautru@intel.com \
--to=nicolas.chautru@intel.com \
--cc=david.marchand@redhat.com \
--cc=dev@dpdk.org \
--cc=g.singh@nxp.com \
--cc=gakhil@marvell.com \
--cc=hemant.agrawal@nxp.com \
--cc=hernan.vargas@intel.com \
--cc=maxime.coquelin@redhat.com \
--cc=thomas@monjalon.net \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).