Skip to contentSkip to conversation

From: Nic Chautru <[email protected]>

PATCH In review Nic Chautru 2 participants 18 messages Sep 16, 2022 – Sep 21, 2022 Arm/Amlogic Meson SoC support

lore
Share & tools
lore
#0 lore raw

v3: New commit to combine in same folder the ACC100 and ACC200 PMDS. Also simplifying the meson dependency and fixing typos.
v2: Includes now code refactory to have common structures and code reused with the parallel ACC1XX serie PMD which can be shared moving forward.
v1: This is targeting 22.11 and includes the PMD for the
new serie integrated accelerator on Intel Xeon SPR-EEC.
There is a dependency on that parallel patch serie still in-flight which extends the bbdev api https://patches.dpdk.org/project/dpdk/list/?series=23894
and is required to apply that patch.

Nic Chautru (3):
baseband/acc100: refactor to segregate common code baseband/acc: rename and merge directories into acc baseband/acc: simplify meson dependency

Nicolas Chautru (10):
baseband/acc200: introduce PMD for ACC200 baseband/acc200: add HW register definitions baseband/acc200: add info get function baseband/acc200: add queue configuration baseband/acc200: add LDPC processing functions baseband/acc200: add LTE processing functions baseband/acc200: add support for FFT operations baseband/acc200: support interrupt baseband/acc200: add device status and vf2pf comms baseband/acc200: add PF configure companion function

 MAINTAINERS                               |    4 +-
 app/test-bbdev/meson.build                |    4 +-
 app/test-bbdev/test_bbdev_perf.c          |   81 +-
 doc/guides/bbdevs/acc200.rst              |  244 ++
 doc/guides/bbdevs/index.rst               |    1 +
 drivers/baseband/acc/acc100_pf_enum.h     |  147 +
 drivers/baseband/acc/acc100_pmd.h         |  177 +
 drivers/baseband/acc/acc100_vf_enum.h     |   73 +
 drivers/baseband/acc/acc101_pmd.h         |   40 +
 drivers/baseband/acc/acc200_pf_enum.h     |  108 +
 drivers/baseband/acc/acc200_pmd.h         |  196 ++
 drivers/baseband/acc/acc200_vf_enum.h     |   83 +
 drivers/baseband/acc/acc_common.h         | 1388 ++++++++
 drivers/baseband/acc/meson.build          |    8 +
 drivers/baseband/acc/rte_acc100_cfg.h     |   49 +
 drivers/baseband/acc/rte_acc100_pmd.c     | 4578 +++++++++++++++++++++++++
 drivers/baseband/acc/rte_acc200_cfg.h     |   48 +
 drivers/baseband/acc/rte_acc200_pmd.c     | 4195 +++++++++++++++++++++++
 drivers/baseband/acc/rte_acc_common_cfg.h |  101 +
 drivers/baseband/acc/version.map          |   10 +
 drivers/baseband/acc100/acc100_pf_enum.h  | 1086 ------
 drivers/baseband/acc100/acc100_pmd.h      |  624 ----
 drivers/baseband/acc100/acc100_vf_enum.h  |   73 -
 drivers/baseband/acc100/acc101_pmd.h      |   50 -
 drivers/baseband/acc100/meson.build       |    8 -
 drivers/baseband/acc100/rte_acc100_cfg.h  |  113 -
 drivers/baseband/acc100/rte_acc100_pmd.c  | 5288 -----------------------------
 drivers/baseband/acc100/version.map       |    9 -
 drivers/baseband/meson.build              |    2 +-
 29 files changed, 11528 insertions(+), 7260 deletions(-)
 create mode 100644 doc/guides/bbdevs/acc200.rst
 create mode 100644 drivers/baseband/acc/acc100_pf_enum.h
 create mode 100644 drivers/baseband/acc/acc100_pmd.h
 create mode 100644 drivers/baseband/acc/acc100_vf_enum.h
 create mode 100644 drivers/baseband/acc/acc101_pmd.h
 create mode 100644 drivers/baseband/acc/acc200_pf_enum.h
 create mode 100644 drivers/baseband/acc/acc200_pmd.h
 create mode 100644 drivers/baseband/acc/acc200_vf_enum.h
 create mode 100644 drivers/baseband/acc/acc_common.h
 create mode 100644 drivers/baseband/acc/meson.build
 create mode 100644 drivers/baseband/acc/rte_acc100_cfg.h
 create mode 100644 drivers/baseband/acc/rte_acc100_pmd.c
 create mode 100644 drivers/baseband/acc/rte_acc200_cfg.h
 create mode 100644 drivers/baseband/acc/rte_acc200_pmd.c
 create mode 100644 drivers/baseband/acc/rte_acc_common_cfg.h
 create mode 100644 drivers/baseband/acc/version.map
 delete mode 100644 drivers/baseband/acc100/acc100_pf_enum.h
 delete mode 100644 drivers/baseband/acc100/acc100_pmd.h
 delete mode 100644 drivers/baseband/acc100/acc100_vf_enum.h
 delete mode 100644 drivers/baseband/acc100/acc101_pmd.h
 delete mode 100644 drivers/baseband/acc100/meson.build
 delete mode 100644 drivers/baseband/acc100/rte_acc100_cfg.h
 delete mode 100644 drivers/baseband/acc100/rte_acc100_pmd.c
 delete mode 100644 drivers/baseband/acc100/version.map
Signature · 1 line
1.8.3.1
#1 lore raw

PATCH v3 1/13 baseband/acc100: refactor to segregate common code

Refactoring all shareable common code to be used by future PMD (including ACC200 in this patchset as well as taking into account following PMDs in roadmap) by gathering such structures or inline methods. Cleaning up the enum files to remove un-used registers definitions. No functionality change.

---
 app/test-bbdev/test_bbdev_perf.c             |    6 +-
 drivers/baseband/acc100/acc100_pf_enum.h     |  939 -------------
 drivers/baseband/acc100/acc100_pmd.h         |  449 +------
 drivers/baseband/acc100/acc101_pmd.h         |   10 -
 drivers/baseband/acc100/acc_common.h         | 1388 +++++++++++++++++++
 drivers/baseband/acc100/rte_acc100_cfg.h     |   70 +-
 drivers/baseband/acc100/rte_acc100_pmd.c     | 1856 ++++++++------------------
 drivers/baseband/acc100/rte_acc_common_cfg.h |  101 ++
 8 files changed, 2069 insertions(+), 2750 deletions(-)
 create mode 100644 drivers/baseband/acc100/acc_common.h
 create mode 100644 drivers/baseband/acc100/rte_acc_common_cfg.h
app/test-bbdev/test_bbdev_perf.c +3 -3
index 5d07670..af9ceca 100644
@@ -708,18 +708,18 @@ typedef int (test_case_function)(struct active_device *ad,
 #ifdef RTE_BASEBAND_ACC100
 	if ((get_init_device() == true) &&
 			(!strcmp(info->drv.driver_name, ACC100PF_DRIVER_NAME))) {
-		struct rte_acc100_conf conf;
+		struct rte_acc_conf conf;
 		unsigned int i;
 
 		printf("Configure ACC100/ACC101 FEC Driver %s with default values\n",
 				info->drv.driver_name);
 
 		/* clear default configuration before initialization */
-		memset(&conf, 0, sizeof(struct rte_acc100_conf));
+		memset(&conf, 0, sizeof(struct rte_acc_conf));
 
 		/* Always set in PF mode for built-in configuration */
 		conf.pf_mode_en = true;
-		for (i = 0; i < RTE_ACC100_NUM_VFS; ++i) {
+		for (i = 0; i < RTE_ACC_NUM_VFS; ++i) {
 			conf.arb_dl_4g[i].gbr_threshold1 = ACC100_QOS_GBR;
 			conf.arb_dl_4g[i].gbr_threshold1 = ACC100_QOS_GBR;
 			conf.arb_dl_4g[i].round_robin_weight = ACC100_QMGR_RR;
drivers/baseband/acc100/acc100_pf_enum.h +0 -939

1,033 lines not on this page · raw message

drivers/baseband/acc100/acc100_pmd.h +1 -448

505 lines not on this page · raw message

drivers/baseband/acc100/acc101_pmd.h +0 -10
index 9d8862c..37df008 100644
@@ -11,16 +11,9 @@
 #define ACC101_NUM_VFS                  16
 #define ACC101_NUM_QGRPS                8
 #define ACC101_NUM_AQS                  16
-/* All ACC101 Registers alignment are 32bits = 4B */
-#define ACC101_BYTES_IN_WORD                 4
 
-#define ACC101_TMPL_PRI_0      0x03020100
-#define ACC101_TMPL_PRI_1      0x07060504
-#define ACC101_TMPL_PRI_2      0x0b0a0908
-#define ACC101_TMPL_PRI_3      0x0f0e0d0c
 #define ACC101_WORDS_IN_ARAM_SIZE (128 * 1024 / 4)
 
-#define ACC101_NUM_TMPL       32
 /* Mapping of signals for the available engines */
 #define ACC101_SIG_UL_5G      0
 #define ACC101_SIG_UL_5G_LAST 8
@@ -31,7 +24,6 @@
 #define ACC101_SIG_DL_4G      27
 #define ACC101_SIG_DL_4G_LAST 31
 #define ACC101_NUM_ACCS       5
-#define ACC101_PF_VAL         2
 
 /* ACC101 Configuration */
 #define ACC101_CFG_DMA_ERROR    0x3D7
@@ -39,8 +31,6 @@
 #define ACC101_CFG_QMGR_HI_P    0x0F0F
 #define ACC101_CFG_PCI_AXI      0xC003
 #define ACC101_CFG_PCI_BRIDGE   0x40006033
-#define ACC101_ENGINE_OFFSET    0x1000
-#define ACC101_LONG_WAIT        1000
 #define ACC101_GPEX_AXIMAP_NUM  17
 #define ACC101_CLOCK_GATING_EN  0x30000
 #define ACC101_DMA_INBOUND      0x104
drivers/baseband/acc100/acc_common.h new file +1388 -0

1,388 lines not on this page · raw message

drivers/baseband/acc100/rte_acc100_cfg.h +3 -67

22 lines not on this page · raw message

drivers/baseband/acc100/rte_acc100_pmd.c +573 -1283

1,856 lines not on this page · raw message

drivers/baseband/acc100/rte_acc_common_cfg.h new file +101 -0

101 lines not on this page · raw message

The rest of this diff is not shown. View the raw message.

Signature · 1 line
1.8.3.1

Part of the diff is not shown here. View the raw message.

#2 lore raw

Re: [PATCH v3 01/13] baseband/acc100: refactor to segregate common code

Quoted 7 lines · Nic Chautru

Refactoring all shareable common code to be used by future PMD (including ACC200 in this patchset as well as taking into account following PMDs in roadmap) by gathering such structures or inline methods. Cleaning up the enum files to remove un-used registers definitions. No functionality change.

You usually sign-off with Nicolas, but some of the patches of this series are with Nic.

Quoted 11 lines
---
  app/test-bbdev/test_bbdev_perf.c             |    6 +-
  drivers/baseband/acc100/acc100_pf_enum.h     |  939 -------------
  drivers/baseband/acc100/acc100_pmd.h         |  449 +------
  drivers/baseband/acc100/acc101_pmd.h         |   10 -
  drivers/baseband/acc100/acc_common.h         | 1388 +++++++++++++++++++
  drivers/baseband/acc100/rte_acc100_cfg.h     |   70 +-
  drivers/baseband/acc100/rte_acc100_pmd.c     | 1856 ++++++++------------------
  drivers/baseband/acc100/rte_acc_common_cfg.h |  101 ++
  8 files changed, 2069 insertions(+), 2750 deletions(-)
Quoted 2 lines

create mode 100644 drivers/baseband/acc100/acc_common.h create mode 100644 drivers/baseband/acc100/rte_acc_common_cfg.h

Overall, I think the patch should be split.
For example:
- One patch for rings rework as it introduces new helpers (and this patch should make use of them in ACC100).
- One patch for the structs renaming and move to common file.
- One patch for registers
- ...

It will make easier for the reviewer to identify discrepancies, and also will help to identify regressions when using git bisect.

I have not done a full review of this patch, but something caught my eye wrt to available entries calculation in rings:

Quoted 5 lines
drivers/baseband/acc100/acc100_pf_enum.h +0 -0
index 2fba667..f4e5002 100644
@@ -14,32 +14,6 @@

...

Quoted 4 lines
drivers/baseband/acc100/acc100_pf_enum.h +4 -0
+
+/* Number of available descriptor in ring to enqueue */
+static inline uint32_t
+acc_ring_avail_enq(struct acc_queue *q)

drivers/baseband/acc100/acc100_pf_enum.h

Quoted 10 lines
drivers/baseband/acc100/acc100_pf_enum.h +10 -0
+{
+	return (q->sw_ring_depth - 1 + q->sw_ring_tail - q->sw_ring_head) % q->sw_ring_depth;
+}
+
+/* Number of available descriptor in ring to dequeue */
+static inline uint32_t
+acc_ring_avail_deq(struct acc_queue *q)
+{
+	return (q->sw_ring_depth + q->sw_ring_head - q->sw_ring_tail) % q->sw_ring_depth;
+}

It is surprising to me that the number of available descriptors calculation for enqueue and dequeue are différent. Could you please explain why there a off-by-one delta between enc and dec?

If we look at other avail calculations in ACC100 enqueue, we get this:
int32_t avail = q->sw_ring_depth + q->sw_ring_tail - q->sw_ring_head; It looks like there is indeed a off-by-one delta even for different avail enqueue calculation.

Also, these new helpers are introduced but are not used in the patch.

#3 lore raw

RE: [PATCH v3 01/13] baseband/acc100: refactor to segregate common code

Hi Maxime,

Quoted 18 lines

-----Original Message-----
From: Maxime Coquelin <[email protected]>
Sent: Wednesday, September 21, 2022 12:13 AM
To: Chautru, Nicolas <[email protected]>; [email protected]; [email protected]
Cc: [email protected]; [email protected]; Richardson, Bruce <[email protected]>; [email protected]; [email protected]; [email protected]; Vargas, Hernan <[email protected]>
Subject: Re: [PATCH v3 01/13] baseband/acc100: refactor to segregate common code

Quoted 3 lines · Nic Chautru

Refactoring all shareable common code to be used by future PMD (including ACC200 in this patchset as well as taking into account following PMDs in roadmap) by gathering such structures or inline

Quoted 9 lines

methods.

Quoted 4 lines

Cleaning up the enum files to remove un-used registers definitions. No functionality change.

You usually sign-off with Nicolas, but some of the patches of this series are with Nic.

OK

Quoted 16 lines
Quoted 7 lines
---
  app/test-bbdev/test_bbdev_perf.c             |    6 +-
  drivers/baseband/acc100/acc100_pf_enum.h     |  939 -------------
  drivers/baseband/acc100/acc100_pmd.h         |  449 +------
  drivers/baseband/acc100/acc101_pmd.h         |   10 -
  drivers/baseband/acc100/acc_common.h         | 1388

+++++++++++++++++++

Quoted 2 lines
  drivers/baseband/acc100/rte_acc100_cfg.h     |   70 +-
  drivers/baseband/acc100/rte_acc100_pmd.c     | 1856 ++++++++-----------

-------

Quoted 4 lines
  drivers/baseband/acc100/rte_acc_common_cfg.h |  101 ++
  8 files changed, 2069 insertions(+), 2750 deletions(-)

create mode 100644 drivers/baseband/acc100/acc_common.h create mode 100644 drivers/baseband/acc100/rte_acc_common_cfg.h

Quoted 4 lines

Overall, I think the patch should be split.
For example:
- One patch for rings rework as it introduces new helpers (and this patch should make use of them in ACC100).

Actually that ring rework is on the other serie specific to ACC100. Still I can remove the function from acc_common.h which are not used yet, and only add them for ACC200.

Quoted 1 line

- One patch for the structs renaming and move to common file.

This is 90% of the content of that commit

Quoted 1 line

- One patch for registers

Can do.

Quoted 1 line

- ...

What else you have in mind?

Quoted 31 lines

It will make easier for the reviewer to identify discrepancies, and also will help to identify regressions when using git bisect.

I have not done a full review of this patch, but something caught my eye wrt to available entries calculation in rings:

Quoted 6 lines
drivers/baseband/acc100/acc100_pf_enum.h +0 -0
index 2fba667..f4e5002 100644
@@ -14,32 +14,6 @@

...

drivers/baseband/acc100/acc100_pf_enum.h

Quoted 10 lines
drivers/baseband/acc100/acc100_pf_enum.h +10 -0
+
+/* Number of available descriptor in ring to enqueue */ static inline
+uint32_t acc_ring_avail_enq(struct acc_queue *q) {
+	return (q->sw_ring_depth - 1 + q->sw_ring_tail - q->sw_ring_head) %
+q->sw_ring_depth; }
+
+/* Number of available descriptor in ring to dequeue */ static inline
+uint32_t acc_ring_avail_deq(struct acc_queue *q) {
+	return (q->sw_ring_depth + q->sw_ring_head - q->sw_ring_tail) %
+q->sw_ring_depth; }

It is surprising to me that the number of available descriptors calculation for enqueue and dequeue are différent. Could you please explain why there a off-by-one delta between enc and dec?

Quoted 6 lines

If we look at other avail calculations in ACC100 enqueue, we get this:
int32_t avail = q->sw_ring_depth + q->sw_ring_tail - q->sw_ring_head; It looks like there is indeed a off-by-one delta even for different avail enqueue calculation.

Also, these new helpers are introduced but are not used in the patch.

I can remove and only add when ACC200 uses them.
With regards to the code itself they are different number on purpose and not just off by one, there are the quasi complement of each other (note head - tail vs tail -head). There was a bug indeed in the ACC100 implementation. But again this not addressed by this serie.

Thanks
Nic

#4 lore raw

PATCH v3 2/13 baseband/acc200: introduce PMD for ACC200

In reply to Nic Chautru

From: Nicolas Chautru <[email protected]>

This patch introduce stubs for device driver for the ACC200 integrated VRAN accelerator on SPR-EEC

---
 MAINTAINERS                              |   3 +
 doc/guides/bbdevs/acc200.rst             | 244 +++++++++++++++++++++++++++++++
 doc/guides/bbdevs/index.rst              |   1 +
 drivers/baseband/acc200/acc200_pmd.h     |  32 ++++
 drivers/baseband/acc200/meson.build      |   6 +
 drivers/baseband/acc200/rte_acc200_pmd.c | 142 ++++++++++++++++++
 drivers/baseband/acc200/version.map      |   3 +
 drivers/baseband/meson.build             |   1 +
 8 files changed, 432 insertions(+)
 create mode 100644 doc/guides/bbdevs/acc200.rst
 create mode 100644 drivers/baseband/acc200/acc200_pmd.h
 create mode 100644 drivers/baseband/acc200/meson.build
 create mode 100644 drivers/baseband/acc200/rte_acc200_pmd.c
 create mode 100644 drivers/baseband/acc200/version.map
MAINTAINERS +3 -0
index 32ffdd1..2abaf45 100644
@@ -1340,6 +1340,9 @@ F: drivers/baseband/acc100/
 F: doc/guides/bbdevs/acc100.rst
 F: doc/guides/bbdevs/features/acc100.ini
 F: doc/guides/bbdevs/features/acc101.ini
+F: drivers/baseband/acc200/
+F: doc/guides/bbdevs/acc200.rst
+F: doc/guides/bbdevs/features/acc200.ini
 
 Null baseband
 M: Nicolas Chautru <[email protected]>
doc/guides/bbdevs/acc200.rst new file +244 -0

244 lines not on this page · raw message

doc/guides/bbdevs/index.rst +1 -0
index cedd706..4e9dea8 100644
@@ -14,4 +14,5 @@ Baseband Device Drivers
     fpga_lte_fec
     fpga_5gnr_fec
     acc100
+    acc200
     la12xx
drivers/baseband/acc200/acc200_pmd.h new file +32 -0
new file mode 100644
index 0000000..626e9fb
@@ -0,0 +1,32 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2022 Intel Corporation
+ */
+
+#ifndef _RTE_ACC200_PMD_H_
+#define _RTE_ACC200_PMD_H_
+
+#include "../acc100/acc_common.h"
+
+/* Helper macro for logging */
+#define rte_bbdev_log(level, fmt, ...) \
+	rte_log(RTE_LOG_ ## level, acc200_logtype, fmt "\n", \
+		##__VA_ARGS__)
+
+#ifdef RTE_LIBRTE_BBDEV_DEBUG
+#define rte_bbdev_log_debug(fmt, ...) \
+		rte_bbdev_log(DEBUG, "acc200_pmd: " fmt, \
+		##__VA_ARGS__)
+#else
+#define rte_bbdev_log_debug(fmt, ...)
+#endif
+
+/* ACC200 PF and VF driver names */
+#define ACC200PF_DRIVER_NAME           intel_acc200_pf
+#define ACC200VF_DRIVER_NAME           intel_acc200_vf
+
+/* ACC200 PCI vendor & device IDs */
+#define RTE_ACC200_VENDOR_ID           (0x8086)
+#define RTE_ACC200_PF_DEVICE_ID        (0x57C0)
+#define RTE_ACC200_VF_DEVICE_ID        (0x57C1)
+
+#endif /* _RTE_ACC200_PMD_H_ */
drivers/baseband/acc200/meson.build new file +6 -0
new file mode 100644
index 0000000..7ec8679
@@ -0,0 +1,6 @@
+# SPDX-License-Identifier: BSD-3-Clause
+# Copyright(c) 2022 Intel Corporation
+
+deps += ['bbdev', 'bus_vdev', 'ring', 'pci', 'bus_pci']
+
+sources = files('rte_acc200_pmd.c')
drivers/baseband/acc200/rte_acc200_pmd.c new file +142 -0

142 lines not on this page · raw message

drivers/baseband/acc200/version.map new file +3 -0
new file mode 100644
index 0000000..c2e0723
@@ -0,0 +1,3 @@
+DPDK_22 {
+	local: *;
+};
drivers/baseband/meson.build +1 -0
index 686e98b..343f83a 100644
@@ -7,6 +7,7 @@ endif
 
 drivers = [
         'acc100',
+        'acc200',
         'fpga_5gnr_fec',
         'fpga_lte_fec',
         'la12xx',
Signature · 1 line
1.8.3.1
#5 lore raw

Re: [PATCH v3 02/13] baseband/acc200: introduce PMD for ACC200

Quoted 16 lines · Nic Chautru

From: Nicolas Chautru <[email protected]>

This patch introduce stubs for device driver for the ACC200 integrated VRAN accelerator on SPR-EEC

---
  MAINTAINERS                              |   3 +
  doc/guides/bbdevs/acc200.rst             | 244 +++++++++++++++++++++++++++++++
  doc/guides/bbdevs/index.rst              |   1 +
  drivers/baseband/acc200/acc200_pmd.h     |  32 ++++
  drivers/baseband/acc200/meson.build      |   6 +
  drivers/baseband/acc200/rte_acc200_pmd.c | 142 ++++++++++++++++++
  drivers/baseband/acc200/version.map      |   3 +
  drivers/baseband/meson.build             |   1 +
  8 files changed, 432 insertions(+)
Quoted 5 lines

create mode 100644 doc/guides/bbdevs/acc200.rst create mode 100644 drivers/baseband/acc200/acc200_pmd.h create mode 100644 drivers/baseband/acc200/meson.build create mode 100644 drivers/baseband/acc200/rte_acc200_pmd.c create mode 100644 drivers/baseband/acc200/version.map

This is not how the common code sharing rework should be done. It does not make sense to introduce acc200 directory in patch 2 to move it to acc in patch 12.

The series must follow a logical path, by first refactoring acc100 to share common code and then to add acc200 by making directly use of this common code.

Regards,
Maxime

#6 lore raw

RE: [PATCH v3 02/13] baseband/acc200: introduce PMD for ACC200

Hi Maxime,

Quoted 37 lines

-----Original Message-----
From: Maxime Coquelin <[email protected]>
Sent: Wednesday, September 21, 2022 12:18 AM
To: Chautru, Nicolas <[email protected]>; [email protected]; [email protected]
Cc: [email protected]; [email protected]; Richardson, Bruce <[email protected]>; [email protected]; [email protected]; [email protected]; Vargas, Hernan <[email protected]>
Subject: Re: [PATCH v3 02/13] baseband/acc200: introduce PMD for ACC200

Quoted 9 lines · Nic Chautru

From: Nicolas Chautru <[email protected]>

This patch introduce stubs for device driver for the ACC200 integrated VRAN accelerator on SPR-EEC

---
  MAINTAINERS                              |   3 +
  doc/guides/bbdevs/acc200.rst             | 244

+++++++++++++++++++++++++++++++

Quoted 7 lines
  doc/guides/bbdevs/index.rst              |   1 +
  drivers/baseband/acc200/acc200_pmd.h     |  32 ++++
  drivers/baseband/acc200/meson.build      |   6 +
  drivers/baseband/acc200/rte_acc200_pmd.c | 142 ++++++++++++++++++
  drivers/baseband/acc200/version.map      |   3 +
  drivers/baseband/meson.build             |   1 +
  8 files changed, 432 insertions(+)
Quoted 5 lines

create mode 100644 doc/guides/bbdevs/acc200.rst create mode 100644 drivers/baseband/acc200/acc200_pmd.h create mode 100644 drivers/baseband/acc200/meson.build create mode 100644 drivers/baseband/acc200/rte_acc200_pmd.c create mode 100644 drivers/baseband/acc200/version.map

Quoted 7 lines

This is not how the common code sharing rework should be done. It does not make sense to introduce acc200 directory in patch 2 to move it to acc in patch 12.

The series must follow a logical path, by first refactoring acc100 to share common code and then to add acc200 by making directly use of this common code.

OK sure. I was hoping I could avoid having to rebase all these commits but I will update now in the v4.

Quoted 3 lines

Regards,
Maxime

#7 lore raw

PATCH v3 3/13 baseband/acc200: add HW register definitions

In reply to Nic Chautru

From: Nicolas Chautru <[email protected]>

Add registers list and structure to access the device.

---
 drivers/baseband/acc200/acc200_pf_enum.h | 108 ++++++++++++++++++++
 drivers/baseband/acc200/acc200_pmd.h     | 163 +++++++++++++++++++++++++++++++
 drivers/baseband/acc200/acc200_vf_enum.h |  83 ++++++++++++++++
 drivers/baseband/acc200/rte_acc200_pmd.c |   2 +
 4 files changed, 356 insertions(+)
 create mode 100644 drivers/baseband/acc200/acc200_pf_enum.h
 create mode 100644 drivers/baseband/acc200/acc200_vf_enum.h
drivers/baseband/acc200/acc200_pf_enum.h new file +108 -0
new file mode 100644
index 0000000..e52d8f5
@@ -0,0 +1,108 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2021 Intel Corporation
+ */
+
+#ifndef ACC200_PF_ENUM_H
+#define ACC200_PF_ENUM_H
+
+/*
+ * ACC200 Register mapping on PF BAR0
+ * This is automatically generated from RDL, format may change with new RDL
+ * Release.
+ * Variable names are as is
+ */
+enum {
+	HWPfQmgrEgressQueuesTemplate          =  0x0007FC00,
+	HWPfQmgrIngressAq                     =  0x00080000,
+	HWPfQmgrDepthLog2Grp                  =  0x00A00200,
+	HWPfQmgrTholdGrp                      =  0x00A00300,
+	HWPfQmgrGrpTmplateReg0Indx            =  0x00A00600,
+	HWPfQmgrGrpTmplateReg1Indx            =  0x00A00700,
+	HWPfQmgrGrpTmplateReg2indx            =  0x00A00800,
+	HWPfQmgrGrpTmplateReg3Indx            =  0x00A00900,
+	HWPfQmgrGrpTmplateReg4Indx            =  0x00A00A00,
+	HWPfQmgrVfBaseAddr                    =  0x00A01000,
+	HWPfQmgrArbQDepthGrp                  =  0x00A02F00,
+	HWPfQmgrGrpFunction0                  =  0x00A02F40,
+	HWPfQmgrGrpFunction1                  =  0x00A02F44,
+	HWPfQmgrGrpPriority                   =  0x00A02F48,
+	HWPfQmgrAqEnableVf                    =  0x00A10000,
+	HWPfQmgrRingSizeVf                    =  0x00A20004,
+	HWPfQmgrGrpDepthLog20Vf               =  0x00A20008,
+	HWPfQmgrGrpDepthLog21Vf               =  0x00A2000C,
+	HWPfFabricM2iBufferReg                =  0x00B30000,
+	HWPfFabricI2Mdma_weight               =  0x00B31044,
+	HwPfFecUl5gIbDebugReg                 =  0x00B40200,
+	HWPfFftConfig0                        =  0x00B58004,
+	HWPfFftRamPageAccess                  =  0x00B5800C,
+	HWPfFftRamOff                         =  0x00B58800,
+	HWPfDmaConfig0Reg                     =  0x00B80000,
+	HWPfDmaConfig1Reg                     =  0x00B80004,
+	HWPfDmaQmgrAddrReg                    =  0x00B80008,
+	HWPfDmaAxcacheReg                     =  0x00B80010,
+	HWPfDmaAxiControl                     =  0x00B8002C,
+	HWPfDmaQmanen                         =  0x00B80040,
+	HWPfDma4gdlIbThld                     =  0x00B800CC,
+	HWPfDmaCfgRrespBresp                  =  0x00B80814,
+	HWPfDmaDescriptorSignatuture          =  0x00B80868,
+	HWPfDmaErrorDetectionEn               =  0x00B80870,
+	HWPfDmaFec5GulDescBaseLoRegVf         =  0x00B88020,
+	HWPfDmaFec5GulDescBaseHiRegVf         =  0x00B88024,
+	HWPfDmaFec5GulRespPtrLoRegVf          =  0x00B88028,
+	HWPfDmaFec5GulRespPtrHiRegVf          =  0x00B8802C,
+	HWPfDmaFec5GdlDescBaseLoRegVf         =  0x00B88040,
+	HWPfDmaFec5GdlDescBaseHiRegVf         =  0x00B88044,
+	HWPfDmaFec5GdlRespPtrLoRegVf          =  0x00B88048,
+	HWPfDmaFec5GdlRespPtrHiRegVf          =  0x00B8804C,
+	HWPfDmaFec4GulDescBaseLoRegVf         =  0x00B88060,
+	HWPfDmaFec4GulDescBaseHiRegVf         =  0x00B88064,
+	HWPfDmaFec4GulRespPtrLoRegVf          =  0x00B88068,
+	HWPfDmaFec4GulRespPtrHiRegVf          =  0x00B8806C,
+	HWPfDmaFec4GdlDescBaseLoRegVf         =  0x00B88080,
+	HWPfDmaFec4GdlDescBaseHiRegVf         =  0x00B88084,
+	HWPfDmaFec4GdlRespPtrLoRegVf          =  0x00B88088,
+	HWPfDmaFec4GdlRespPtrHiRegVf          =  0x00B8808C,
+	HWPDmaFftDescBaseLoRegVf              =  0x00B880A0,
+	HWPDmaFftDescBaseHiRegVf              =  0x00B880A4,
+	HWPDmaFftRespPtrLoRegVf               =  0x00B880A8,
+	HWPDmaFftRespPtrHiRegVf               =  0x00B880AC,
+	HWPfQosmonAEvalOverflow0              =  0x00B90008,
+	HWPfPermonACntrlRegVf                 =  0x00B98000,
+	HWPfQosmonBEvalOverflow0              =  0x00BA0008,
+	HWPfPermonBCntrlRegVf                 =  0x00BA8000,
+	HWPfPermonCCntrlRegVf                 =  0x00BB8000,
+	HWPfHiInfoRingBaseLoRegPf             =  0x00C84014,
+	HWPfHiInfoRingBaseHiRegPf             =  0x00C84018,
+	HWPfHiInfoRingPointerRegPf            =  0x00C8401C,
+	HWPfHiInfoRingIntWrEnRegPf            =  0x00C84020,
+	HWPfHiBlockTransmitOnErrorEn          =  0x00C84038,
+	HWPfHiCfgMsiIntWrEnRegPf              =  0x00C84040,
+	HWPfHiMsixVectorMapperPf              =  0x00C84060,
+	HWPfHiPfMode                          =  0x00C84108,
+	HWPfHiClkGateHystReg                  =  0x00C8410C,
+	HWPfHiMsiDropEnableReg                =  0x00C84114,
+	HWPfHiSectionPowerGatingReq           =  0x00C84128,
+	HWPfHiSectionPowerGatingAck           =  0x00C8412C,
+};
+
+/* TIP PF Interrupt numbers */
+enum {
+	ACC200_PF_INT_QMGR_AQ_OVERFLOW = 0,
+	ACC200_PF_INT_DOORBELL_VF_2_PF = 1,
+	ACC200_PF_INT_ILLEGAL_FORMAT = 2,
+	ACC200_PF_INT_QMGR_DISABLED_ACCESS = 3,
+	ACC200_PF_INT_QMGR_AQ_OVERTHRESHOLD = 4,
+	ACC200_PF_INT_DMA_DL_DESC_IRQ = 5,
+	ACC200_PF_INT_DMA_UL_DESC_IRQ = 6,
+	ACC200_PF_INT_DMA_FFT_DESC_IRQ = 7,
+	ACC200_PF_INT_DMA_UL5G_DESC_IRQ = 8,
+	ACC200_PF_INT_DMA_DL5G_DESC_IRQ = 9,
+	ACC200_PF_INT_DMA_MLD_DESC_IRQ = 10,
+	ACC200_PF_INT_ARAM_ECC_1BIT_ERR = 11,
+	ACC200_PF_INT_PARITY_ERR = 12,
+	ACC200_PF_INT_QMGR_ERR = 13,
+	ACC200_PF_INT_INT_REQ_OVERFLOW = 14,
+	ACC200_PF_INT_APB_TIMEOUT = 15,
+};
+
+#endif /* ACC200_PF_ENUM_H */
drivers/baseband/acc200/acc200_pmd.h +163 -0

173 lines not on this page · raw message

drivers/baseband/acc200/acc200_vf_enum.h new file +83 -0

83 lines not on this page · raw message

drivers/baseband/acc200/rte_acc200_pmd.c +2 -0
index db8b641..5554488 100644
@@ -34,6 +34,8 @@
 acc200_dev_close(struct rte_bbdev *dev)
 {
 	RTE_SET_USED(dev);
+	/* Ensure all in flight HW transactions are completed */
+	usleep(ACC_LONG_WAIT);
 	return 0;
 }
 
Signature · 1 line
1.8.3.1
#8 lore raw

PATCH v3 4/13 baseband/acc200: add info get function

In reply to Nic Chautru

From: Nicolas Chautru <[email protected]>

Add support for info_get to allow to query the device. Null capability exposed.

---
 drivers/baseband/acc200/acc200_pmd.h     |   1 +
 drivers/baseband/acc200/rte_acc200_cfg.h |  27 ++++
 drivers/baseband/acc200/rte_acc200_pmd.c | 239 +++++++++++++++++++++++++++++++
 3 files changed, 267 insertions(+)
 create mode 100644 drivers/baseband/acc200/rte_acc200_cfg.h
drivers/baseband/acc200/acc200_pmd.h +1 -0
index 57b7e63..ec30e76 100644
@@ -8,6 +8,7 @@
 #include "../acc100/acc_common.h"
 #include "acc200_pf_enum.h"
 #include "acc200_vf_enum.h"
+#include "rte_acc200_cfg.h"
 
 /* Helper macro for logging */
 #define rte_bbdev_log(level, fmt, ...) \
drivers/baseband/acc200/rte_acc200_cfg.h new file +27 -0
new file mode 100644
index 0000000..9ae96c6
@@ -0,0 +1,27 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2021 Intel Corporation
+ */
+
+#ifndef _RTE_ACC200_CFG_H_
+#define _RTE_ACC200_CFG_H_
+
+/**
+ * @file rte_acc200_cfg.h
+ *
+ * Functions for configuring ACC200 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 "../acc100/rte_acc_common_cfg.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#endif /* _RTE_ACC200_CFG_H_ */
drivers/baseband/acc200/rte_acc200_pmd.c +239 -0

254 lines not on this page · raw message

Signature · 1 line
1.8.3.1
#9 lore raw

PATCH v3 5/13 baseband/acc200: add queue configuration

In reply to Nic Chautru

From: Nicolas Chautru <[email protected]>

Adding fuinction to create and configure queues for the device.

---
 drivers/baseband/acc200/rte_acc200_pmd.c | 373 ++++++++++++++++++++++++++++++-
 1 file changed, 372 insertions(+), 1 deletion(-)
drivers/baseband/acc200/rte_acc200_pmd.c +372 -1
index 43415eb..225bab9 100644
@@ -220,16 +220,383 @@
 			acc_conf->q_fft.aq_depth_log2);
 }
 
+/* Allocate 64MB memory used for all software rings */
+static int
+acc200_setup_queues(struct rte_bbdev *dev, uint16_t num_queues, int socket_id)
+{
+	uint32_t phys_low, phys_high, value;
+	struct acc_device *d = dev->data->dev_private;
+	const struct acc200_registry_addr *reg_addr;
+
+	if (d->pf_device && !d->acc_conf.pf_mode_en) {
+		rte_bbdev_log(NOTICE,
+				"%s has PF mode disabled. This PF can't be used.",
+				dev->data->name);
+		return -ENODEV;
+	}
+	if (!d->pf_device && d->acc_conf.pf_mode_en) {
+		rte_bbdev_log(NOTICE,
+				"%s has PF mode enabled. This VF can't be used.",
+				dev->data->name);
+		return -ENODEV;
+	}
+
+	alloc_sw_rings_min_mem(dev, d, num_queues, socket_id);
+
+	/* If minimal memory space approach failed, then allocate
+	 * the 2 * 64MB block for the sw rings
+	 */
+	if (d->sw_rings == NULL)
+		alloc_2x64mb_sw_rings_mem(dev, d, socket_id);
+
+	if (d->sw_rings == NULL) {
+		rte_bbdev_log(NOTICE,
+				"Failure allocating sw_rings memory");
+		return -ENODEV;
+	}
+
+	/* Configure ACC200 with the base address for DMA descriptor rings
+	 * Same descriptor rings used for UL and DL DMA Engines
+	 * Note : Assuming only VF0 bundle is used for PF mode
+	 */
+	phys_high = (uint32_t)(d->sw_rings_iova >> 32);
+	phys_low  = (uint32_t)(d->sw_rings_iova & ~(ACC_SIZE_64MBYTE-1));
+
+	/* Choose correct registry addresses for the device type */
+	if (d->pf_device)
+		reg_addr = &pf_reg_addr;
+	else
+		reg_addr = &vf_reg_addr;
+
+	/* Read the populated cfg from ACC200 registers */
+	fetch_acc200_config(dev);
+
+	/* Start Pmon */
+	for (value = 0; value <= 2; value++) {
+		acc_reg_write(d, reg_addr->pmon_ctrl_a, value);
+		acc_reg_write(d, reg_addr->pmon_ctrl_b, value);
+		acc_reg_write(d, reg_addr->pmon_ctrl_c, value);
+	}
+
+	/* Release AXI from PF */
+	if (d->pf_device)
+		acc_reg_write(d, HWPfDmaAxiControl, 1);
+
+	acc_reg_write(d, reg_addr->dma_ring_ul5g_hi, phys_high);
+	acc_reg_write(d, reg_addr->dma_ring_ul5g_lo, phys_low);
+	acc_reg_write(d, reg_addr->dma_ring_dl5g_hi, phys_high);
+	acc_reg_write(d, reg_addr->dma_ring_dl5g_lo, phys_low);
+	acc_reg_write(d, reg_addr->dma_ring_ul4g_hi, phys_high);
+	acc_reg_write(d, reg_addr->dma_ring_ul4g_lo, phys_low);
+	acc_reg_write(d, reg_addr->dma_ring_dl4g_hi, phys_high);
+	acc_reg_write(d, reg_addr->dma_ring_dl4g_lo, phys_low);
+	acc_reg_write(d, reg_addr->dma_ring_fft_hi, phys_high);
+	acc_reg_write(d, reg_addr->dma_ring_fft_lo, phys_low);
+	/*
+	 * Configure Ring Size to the max queue ring size
+	 * (used for wrapping purpose)
+	 */
+	value = log2_basic(d->sw_ring_size / 64);
+	acc_reg_write(d, reg_addr->ring_size, value);
+
+	/* Configure tail pointer for use when SDONE enabled */
+	if (d->tail_ptrs == NULL)
+		d->tail_ptrs = rte_zmalloc_socket(
+				dev->device->driver->name,
+				ACC200_NUM_QGRPS * ACC200_NUM_AQS * sizeof(uint32_t),
+				RTE_CACHE_LINE_SIZE, socket_id);
+	if (d->tail_ptrs == NULL) {
+		rte_bbdev_log(ERR, "Failed to allocate tail ptr for %s:%u",
+				dev->device->driver->name,
+				dev->data->dev_id);
+		rte_free(d->sw_rings);
+		return -ENOMEM;
+	}
+	d->tail_ptr_iova = rte_malloc_virt2iova(d->tail_ptrs);
+
+	phys_high = (uint32_t)(d->tail_ptr_iova >> 32);
+	phys_low  = (uint32_t)(d->tail_ptr_iova);
+	acc_reg_write(d, reg_addr->tail_ptrs_ul5g_hi, phys_high);
+	acc_reg_write(d, reg_addr->tail_ptrs_ul5g_lo, phys_low);
+	acc_reg_write(d, reg_addr->tail_ptrs_dl5g_hi, phys_high);
+	acc_reg_write(d, reg_addr->tail_ptrs_dl5g_lo, phys_low);
+	acc_reg_write(d, reg_addr->tail_ptrs_ul4g_hi, phys_high);
+	acc_reg_write(d, reg_addr->tail_ptrs_ul4g_lo, phys_low);
+	acc_reg_write(d, reg_addr->tail_ptrs_dl4g_hi, phys_high);
+	acc_reg_write(d, reg_addr->tail_ptrs_dl4g_lo, phys_low);
+	acc_reg_write(d, reg_addr->tail_ptrs_fft_hi, phys_high);
+	acc_reg_write(d, reg_addr->tail_ptrs_fft_lo, phys_low);
+
+	if (d->harq_layout == NULL)
+		d->harq_layout = rte_zmalloc_socket("HARQ Layout",
+				ACC_HARQ_LAYOUT * sizeof(*d->harq_layout),
+				RTE_CACHE_LINE_SIZE, dev->data->socket_id);
+	if (d->harq_layout == NULL) {
+		rte_bbdev_log(ERR, "Failed to allocate harq_layout for %s:%u",
+				dev->device->driver->name,
+				dev->data->dev_id);
+		rte_free(d->sw_rings);
+		return -ENOMEM;
+	}
+
+	/* Mark as configured properly */
+	d->configured = true;
+
+	rte_bbdev_log_debug(
+			"ACC200 (%s) configured  sw_rings = %p, sw_rings_iova = %#"
+			PRIx64, dev->data->name, d->sw_rings, d->sw_rings_iova);
+
+	return 0;
+}
+
 /* Free memory used for software rings */
 static int
 acc200_dev_close(struct rte_bbdev *dev)
 {
-	RTE_SET_USED(dev);
+	struct acc_device *d = dev->data->dev_private;
+	if (d->sw_rings_base != NULL) {
+		rte_free(d->tail_ptrs);
+		rte_free(d->sw_rings_base);
+		rte_free(d->harq_layout);
+		d->sw_rings_base = NULL;
+		d->tail_ptrs = NULL;
+		d->harq_layout = NULL;
+	}
 	/* Ensure all in flight HW transactions are completed */
 	usleep(ACC_LONG_WAIT);
 	return 0;
 }
 
+/**
+ * Report a ACC200 queue index which is free
+ * Return 0 to 16k for a valid queue_idx or -1 when no queue is available
+ * Note : Only supporting VF0 Bundle for PF mode
+ */
+static int
+acc200_find_free_queue_idx(struct rte_bbdev *dev,
+		const struct rte_bbdev_queue_conf *conf)
+{
+	struct acc_device *d = dev->data->dev_private;
+	int op_2_acc[6] = {0, UL_4G, DL_4G, UL_5G, DL_5G, FFT};
+	int acc = op_2_acc[conf->op_type];
+	struct rte_acc_queue_topology *qtop = NULL;
+
+	qtopFromAcc(&qtop, acc, &(d->acc_conf));
+	if (qtop == NULL)
+		return -1;
+	/* Identify matching QGroup Index which are sorted in priority order */
+	uint16_t group_idx = qtop->first_qgroup_index;
+	group_idx += conf->priority;
+	if (group_idx >= ACC200_NUM_QGRPS ||
+			conf->priority >= qtop->num_qgroups) {
+		rte_bbdev_log(INFO, "Invalid Priority on %s, priority %u",
+				dev->data->name, conf->priority);
+		return -1;
+	}
+	/* Find a free AQ_idx  */
+	uint16_t aq_idx;
+	for (aq_idx = 0; aq_idx < qtop->num_aqs_per_groups; aq_idx++) {
+		if (((d->q_assigned_bit_map[group_idx] >> aq_idx) & 0x1) == 0) {
+			/* Mark the Queue as assigned */
+			d->q_assigned_bit_map[group_idx] |= (1 << aq_idx);
+			/* Report the AQ Index */
+			return (group_idx << ACC200_GRP_ID_SHIFT) + aq_idx;
+		}
+	}
+	rte_bbdev_log(INFO, "Failed to find free queue on %s, priority %u",
+			dev->data->name, conf->priority);
+	return -1;
+}
+
+/* Setup ACC200 queue */
+static int
+acc200_queue_setup(struct rte_bbdev *dev, uint16_t queue_id,
+		const struct rte_bbdev_queue_conf *conf)
+{
+	struct acc_device *d = dev->data->dev_private;
+	struct acc_queue *q;
+	int16_t q_idx;
+
+	if (d == NULL) {
+		rte_bbdev_log(ERR, "Undefined device");
+		return -ENODEV;
+	}
+	/* Allocate the queue data structure. */
+	q = rte_zmalloc_socket(dev->device->driver->name, sizeof(*q),
+			RTE_CACHE_LINE_SIZE, conf->socket);
+	if (q == NULL) {
+		rte_bbdev_log(ERR, "Failed to allocate queue memory");
+		return -ENOMEM;
+	}
+
+	q->d = d;
+	q->ring_addr = RTE_PTR_ADD(d->sw_rings, (d->sw_ring_size * queue_id));
+	q->ring_addr_iova = d->sw_rings_iova + (d->sw_ring_size * queue_id);
+
+	/* Prepare the Ring with default descriptor format */
+	union acc_dma_desc *desc = NULL;
+	unsigned int desc_idx, b_idx;
+	int fcw_len = (conf->op_type == RTE_BBDEV_OP_LDPC_ENC ?
+		ACC_FCW_LE_BLEN : (conf->op_type == RTE_BBDEV_OP_TURBO_DEC ?
+		ACC_FCW_TD_BLEN : (conf->op_type == RTE_BBDEV_OP_LDPC_DEC ?
+		ACC_FCW_LD_BLEN : ACC_FCW_FFT_BLEN)));
+
+	for (desc_idx = 0; desc_idx < d->sw_ring_max_depth; desc_idx++) {
+		desc = q->ring_addr + desc_idx;
+		desc->req.word0 = ACC_DMA_DESC_TYPE;
+		desc->req.word1 = 0; /**< Timestamp */
+		desc->req.word2 = 0;
+		desc->req.word3 = 0;
+		uint64_t fcw_offset = (desc_idx << 8) + ACC_DESC_FCW_OFFSET;
+		desc->req.data_ptrs[0].address = q->ring_addr_iova + fcw_offset;
+		desc->req.data_ptrs[0].blen = fcw_len;
+		desc->req.data_ptrs[0].blkid = ACC_DMA_BLKID_FCW;
+		desc->req.data_ptrs[0].last = 0;
+		desc->req.data_ptrs[0].dma_ext = 0;
+		for (b_idx = 1; b_idx < ACC_DMA_MAX_NUM_POINTERS - 1;
+				b_idx++) {
+			desc->req.data_ptrs[b_idx].blkid = ACC_DMA_BLKID_IN;
+			desc->req.data_ptrs[b_idx].last = 1;
+			desc->req.data_ptrs[b_idx].dma_ext = 0;
+			b_idx++;
+			desc->req.data_ptrs[b_idx].blkid =
+					ACC_DMA_BLKID_OUT_ENC;
+			desc->req.data_ptrs[b_idx].last = 1;
+			desc->req.data_ptrs[b_idx].dma_ext = 0;
+		}
+		/* Preset some fields of LDPC FCW */
+		desc->req.fcw_ld.FCWversion = ACC_FCW_VER;
+		desc->req.fcw_ld.gain_i = 1;
+		desc->req.fcw_ld.gain_h = 1;
+	}
+
+	q->lb_in = rte_zmalloc_socket(dev->device->driver->name,
+			RTE_CACHE_LINE_SIZE,
+			RTE_CACHE_LINE_SIZE, conf->socket);
+	if (q->lb_in == NULL) {
+		rte_bbdev_log(ERR, "Failed to allocate lb_in memory");
+		rte_free(q);
+		return -ENOMEM;
+	}
+	q->lb_in_addr_iova = rte_malloc_virt2iova(q->lb_in);
+	q->lb_out = rte_zmalloc_socket(dev->device->driver->name,
+			RTE_CACHE_LINE_SIZE,
+			RTE_CACHE_LINE_SIZE, conf->socket);
+	if (q->lb_out == NULL) {
+		rte_bbdev_log(ERR, "Failed to allocate lb_out memory");
+		rte_free(q->lb_in);
+		rte_free(q);
+		return -ENOMEM;
+	}
+	q->lb_out_addr_iova = rte_malloc_virt2iova(q->lb_out);
+	q->companion_ring_addr = rte_zmalloc_socket(dev->device->driver->name,
+			d->sw_ring_max_depth * sizeof(*q->companion_ring_addr),
+			RTE_CACHE_LINE_SIZE, conf->socket);
+	if (q->companion_ring_addr == NULL) {
+		rte_bbdev_log(ERR, "Failed to allocate companion_ring memory");
+		rte_free(q->lb_in);
+		rte_free(q->lb_out);
+		rte_free(q);
+		return -ENOMEM;
+	}
+
+	/*
+	 * Software queue ring wraps synchronously with the HW when it reaches
+	 * the boundary of the maximum allocated queue size, no matter what the
+	 * sw queue size is. This wrapping is guarded by setting the wrap_mask
+	 * to represent the maximum queue size as allocated at the time when
+	 * the device has been setup (in configure()).
+	 *
+	 * The queue depth is set to the queue size value (conf->queue_size).
+	 * This limits the occupancy of the queue at any point of time, so that
+	 * the queue does not get swamped with enqueue requests.
+	 */
+	q->sw_ring_depth = conf->queue_size;
+	q->sw_ring_wrap_mask = d->sw_ring_max_depth - 1;
+
+	q->op_type = conf->op_type;
+
+	q_idx = acc200_find_free_queue_idx(dev, conf);
+	if (q_idx == -1) {
+		rte_free(q->companion_ring_addr);
+		rte_free(q->lb_in);
+		rte_free(q->lb_out);
+		rte_free(q);
+		return -1;
+	}
+
+	q->qgrp_id = (q_idx >> ACC200_GRP_ID_SHIFT) & 0xF;
+	q->vf_id = (q_idx >> ACC200_VF_ID_SHIFT)  & 0x3F;
+	q->aq_id = q_idx & 0xF;
+	q->aq_depth = 0;
+	if (conf->op_type ==  RTE_BBDEV_OP_TURBO_DEC)
+		q->aq_depth = (1 << d->acc_conf.q_ul_4g.aq_depth_log2);
+	else if (conf->op_type ==  RTE_BBDEV_OP_TURBO_ENC)
+		q->aq_depth = (1 << d->acc_conf.q_dl_4g.aq_depth_log2);
+	else if (conf->op_type ==  RTE_BBDEV_OP_LDPC_DEC)
+		q->aq_depth = (1 << d->acc_conf.q_ul_5g.aq_depth_log2);
+	else if (conf->op_type ==  RTE_BBDEV_OP_LDPC_ENC)
+		q->aq_depth = (1 << d->acc_conf.q_dl_5g.aq_depth_log2);
+	else if (conf->op_type ==  RTE_BBDEV_OP_FFT)
+		q->aq_depth = (1 << d->acc_conf.q_fft.aq_depth_log2);
+
+	q->mmio_reg_enqueue = RTE_PTR_ADD(d->mmio_base,
+			queue_offset(d->pf_device,
+					q->vf_id, q->qgrp_id, q->aq_id));
+
+	rte_bbdev_log_debug(
+			"Setup dev%u q%u: qgrp_id=%u, vf_id=%u, aq_id=%u, aq_depth=%u, mmio_reg_enqueue=%p base %p\n",
+			dev->data->dev_id, queue_id, q->qgrp_id, q->vf_id,
+			q->aq_id, q->aq_depth, q->mmio_reg_enqueue,
+			d->mmio_base);
+
+	dev->data->queues[queue_id].queue_private = q;
+	return 0;
+}
+
+
+static int
+acc_queue_stop(struct rte_bbdev *dev, uint16_t queue_id)
+{
+	struct acc_queue *q;
+	q = dev->data->queues[queue_id].queue_private;
+	rte_bbdev_log(INFO, "Queue Stop %d H/T/D %d %d %x OpType %d",
+			queue_id, q->sw_ring_head, q->sw_ring_tail,
+			q->sw_ring_depth, q->op_type);
+	/* ignore all operations in flight and clear counters */
+	q->sw_ring_tail = q->sw_ring_head;
+	q->aq_enqueued = 0;
+	q->aq_dequeued = 0;
+	dev->data->queues[queue_id].queue_stats.enqueued_count = 0;
+	dev->data->queues[queue_id].queue_stats.dequeued_count = 0;
+	dev->data->queues[queue_id].queue_stats.enqueue_err_count = 0;
+	dev->data->queues[queue_id].queue_stats.dequeue_err_count = 0;
+	dev->data->queues[queue_id].queue_stats.enqueue_warn_count = 0;
+	dev->data->queues[queue_id].queue_stats.dequeue_warn_count = 0;
+	return 0;
+}
+
+/* Release ACC200 queue */
+static int
+acc200_queue_release(struct rte_bbdev *dev, uint16_t q_id)
+{
+	struct acc_device *d = dev->data->dev_private;
+	struct acc_queue *q = dev->data->queues[q_id].queue_private;
+
+	if (q != NULL) {
+		/* Mark the Queue as un-assigned */
+		d->q_assigned_bit_map[q->qgrp_id] &= (0xFFFFFFFF -
+				(1 << q->aq_id));
+		rte_free(q->companion_ring_addr);
+		rte_free(q->lb_in);
+		rte_free(q->lb_out);
+		rte_free(q);
+		dev->data->queues[q_id].queue_private = NULL;
+	}
+
+	return 0;
+}
+
 /* Get ACC200 device info */
 static void
 acc200_dev_info_get(struct rte_bbdev *dev,
@@ -279,8 +646,12 @@
 }
 
 static const struct rte_bbdev_ops acc200_bbdev_ops = {
+	.setup_queues = acc200_setup_queues,
 	.close = acc200_dev_close,
 	.info_get = acc200_dev_info_get,
+	.queue_setup = acc200_queue_setup,
+	.queue_release = acc200_queue_release,
+	.queue_stop = acc_queue_stop,
 };
 
 /* ACC200 PCI PF address map */
Signature · 1 line
1.8.3.1
#10 lore raw

PATCH v3 6/13 baseband/acc200: add LDPC processing functions

In reply to Nic Chautru

From: Nicolas Chautru <[email protected]>

Adding LDPC encode and decode processing functions.

---
 drivers/baseband/acc200/rte_acc200_pmd.c | 1526 +++++++++++++++++++++++++++++-
 1 file changed, 1522 insertions(+), 4 deletions(-)
drivers/baseband/acc200/rte_acc200_pmd.c +1522 -4
index 225bab9..def5ed7 100644
@@ -554,15 +554,50 @@
 	return 0;
 }
 
+static inline void
+acc200_print_op(struct rte_bbdev_dec_op *op, enum rte_bbdev_op_type op_type,
+		uint16_t index)
+{
+	if (op == NULL)
+		return;
+	if (op_type == RTE_BBDEV_OP_LDPC_DEC)
+		rte_bbdev_log(INFO,
+			"  Op 5GUL %d %d %d %d %d %d %d %d %d %d %d %d",
+			index,
+			op->ldpc_dec.basegraph, op->ldpc_dec.z_c,
+			op->ldpc_dec.n_cb, op->ldpc_dec.q_m,
+			op->ldpc_dec.n_filler, op->ldpc_dec.cb_params.e,
+			op->ldpc_dec.op_flags, op->ldpc_dec.rv_index,
+			op->ldpc_dec.iter_max, op->ldpc_dec.iter_count,
+			op->ldpc_dec.harq_combined_input.length
+			);
+	else if (op_type == RTE_BBDEV_OP_LDPC_ENC) {
+		struct rte_bbdev_enc_op *op_dl = (struct rte_bbdev_enc_op *) op;
+		rte_bbdev_log(INFO,
+			"  Op 5GDL %d %d %d %d %d %d %d %d %d",
+			index,
+			op_dl->ldpc_enc.basegraph, op_dl->ldpc_enc.z_c,
+			op_dl->ldpc_enc.n_cb, op_dl->ldpc_enc.q_m,
+			op_dl->ldpc_enc.n_filler, op_dl->ldpc_enc.cb_params.e,
+			op_dl->ldpc_enc.op_flags, op_dl->ldpc_enc.rv_index
+			);
+	}
+}
 
 static int
 acc_queue_stop(struct rte_bbdev *dev, uint16_t queue_id)
 {
 	struct acc_queue *q;
+	struct rte_bbdev_dec_op *op;
+	uint16_t i;
 	q = dev->data->queues[queue_id].queue_private;
 	rte_bbdev_log(INFO, "Queue Stop %d H/T/D %d %d %x OpType %d",
 			queue_id, q->sw_ring_head, q->sw_ring_tail,
 			q->sw_ring_depth, q->op_type);
+	for (i = 0; i < q->sw_ring_depth; ++i) {
+		op = (q->ring_addr + i)->req.op_addr;
+		acc200_print_op(op, q->op_type, i);
+	}
 	/* ignore all operations in flight and clear counters */
 	q->sw_ring_tail = q->sw_ring_head;
 	q->aq_enqueued = 0;
@@ -605,6 +640,43 @@
 	struct acc_device *d = dev->data->dev_private;
 	int i;
 	static const struct rte_bbdev_op_cap bbdev_capabilities[] = {
+		{
+			.type   = RTE_BBDEV_OP_LDPC_ENC,
+			.cap.ldpc_enc = {
+				.capability_flags =
+					RTE_BBDEV_LDPC_RATE_MATCH |
+					RTE_BBDEV_LDPC_CRC_24B_ATTACH |
+					RTE_BBDEV_LDPC_INTERLEAVER_BYPASS,
+				.num_buffers_src =
+						RTE_BBDEV_LDPC_MAX_CODE_BLOCKS,
+				.num_buffers_dst =
+						RTE_BBDEV_LDPC_MAX_CODE_BLOCKS,
+			}
+		},
+		{
+			.type   = RTE_BBDEV_OP_LDPC_DEC,
+			.cap.ldpc_dec = {
+			.capability_flags =
+				RTE_BBDEV_LDPC_CRC_TYPE_24B_CHECK |
+				RTE_BBDEV_LDPC_CRC_TYPE_24B_DROP |
+				RTE_BBDEV_LDPC_CRC_TYPE_24A_CHECK |
+				RTE_BBDEV_LDPC_CRC_TYPE_16_CHECK |
+				RTE_BBDEV_LDPC_HQ_COMBINE_IN_ENABLE |
+				RTE_BBDEV_LDPC_HQ_COMBINE_OUT_ENABLE |
+				RTE_BBDEV_LDPC_ITERATION_STOP_ENABLE |
+				RTE_BBDEV_LDPC_DEINTERLEAVER_BYPASS |
+				RTE_BBDEV_LDPC_DEC_SCATTER_GATHER |
+				RTE_BBDEV_LDPC_HARQ_6BIT_COMPRESSION |
+				RTE_BBDEV_LDPC_LLR_COMPRESSION,
+			.llr_size = 8,
+			.llr_decimals = 1,
+			.num_buffers_src =
+					RTE_BBDEV_LDPC_MAX_CODE_BLOCKS,
+			.num_buffers_hard_out =
+					RTE_BBDEV_LDPC_MAX_CODE_BLOCKS,
+			.num_buffers_soft_out = 0,
+			}
+		},
 		RTE_BBDEV_END_OF_CAPABILITIES_LIST()
 	};
 
@@ -621,13 +693,15 @@
 	dev_info->num_queues[RTE_BBDEV_OP_NONE] = 0;
 	dev_info->num_queues[RTE_BBDEV_OP_TURBO_DEC] = 0;
 	dev_info->num_queues[RTE_BBDEV_OP_TURBO_ENC] = 0;
-	dev_info->num_queues[RTE_BBDEV_OP_LDPC_DEC] = 0;
-	dev_info->num_queues[RTE_BBDEV_OP_LDPC_ENC] = 0;
+	dev_info->num_queues[RTE_BBDEV_OP_LDPC_DEC] = d->acc_conf.q_ul_5g.num_aqs_per_groups *
+			d->acc_conf.q_ul_5g.num_qgroups;
+	dev_info->num_queues[RTE_BBDEV_OP_LDPC_ENC] = d->acc_conf.q_dl_5g.num_aqs_per_groups *
+			d->acc_conf.q_dl_5g.num_qgroups;
 	dev_info->num_queues[RTE_BBDEV_OP_FFT] = 0;
 	dev_info->queue_priority[RTE_BBDEV_OP_TURBO_DEC] = 0;
 	dev_info->queue_priority[RTE_BBDEV_OP_TURBO_ENC] = 0;
-	dev_info->queue_priority[RTE_BBDEV_OP_LDPC_DEC] = 0;
-	dev_info->queue_priority[RTE_BBDEV_OP_LDPC_ENC] = 0;
+	dev_info->queue_priority[RTE_BBDEV_OP_LDPC_DEC] = d->acc_conf.q_ul_5g.num_qgroups;
+	dev_info->queue_priority[RTE_BBDEV_OP_LDPC_ENC] = d->acc_conf.q_dl_5g.num_qgroups;
 	dev_info->queue_priority[RTE_BBDEV_OP_FFT] = 0;
 	dev_info->max_num_queues = 0;
 	for (i = RTE_BBDEV_OP_NONE; i <= RTE_BBDEV_OP_FFT; i++)
@@ -670,6 +744,1446 @@
 	{.device_id = 0},
 };
 
+/* Fill in a frame control word for LDPC decoding. */
+static inline void
+acc200_fcw_ld_fill(struct rte_bbdev_dec_op *op, struct acc_fcw_ld *fcw,
+		union acc_harq_layout_data *harq_layout)
+{
+	uint16_t harq_out_length, harq_in_length, ncb_p, k0_p, parity_offset;
+	uint32_t harq_index;
+	uint32_t l;
+
+	fcw->qm = op->ldpc_dec.q_m;
+	fcw->nfiller = op->ldpc_dec.n_filler;
+	fcw->BG = (op->ldpc_dec.basegraph - 1);
+	fcw->Zc = op->ldpc_dec.z_c;
+	fcw->ncb = op->ldpc_dec.n_cb;
+	fcw->k0 = get_k0(fcw->ncb, fcw->Zc, op->ldpc_dec.basegraph,
+			op->ldpc_dec.rv_index);
+	if (op->ldpc_dec.code_block_mode == RTE_BBDEV_CODE_BLOCK)
+		fcw->rm_e = op->ldpc_dec.cb_params.e;
+	else
+		fcw->rm_e = (op->ldpc_dec.tb_params.r <
+				op->ldpc_dec.tb_params.cab) ?
+						op->ldpc_dec.tb_params.ea :
+						op->ldpc_dec.tb_params.eb;
+
+	if (unlikely(check_bit(op->ldpc_dec.op_flags,
+			RTE_BBDEV_LDPC_HQ_COMBINE_IN_ENABLE) &&
+			(op->ldpc_dec.harq_combined_input.length == 0))) {
+		rte_bbdev_log(WARNING, "Null HARQ input size provided");
+		/* Disable HARQ input in that case to carry forward */
+		op->ldpc_dec.op_flags ^= RTE_BBDEV_LDPC_HQ_COMBINE_IN_ENABLE;
+	}
+	if (unlikely(fcw->rm_e == 0)) {
+		rte_bbdev_log(WARNING, "Null E input provided");
+		fcw->rm_e = 2;
+	}
+
+	fcw->hcin_en = check_bit(op->ldpc_dec.op_flags,
+			RTE_BBDEV_LDPC_HQ_COMBINE_IN_ENABLE);
+	fcw->hcout_en = check_bit(op->ldpc_dec.op_flags,
+			RTE_BBDEV_LDPC_HQ_COMBINE_OUT_ENABLE);
+	fcw->crc_select = check_bit(op->ldpc_dec.op_flags,
+			RTE_BBDEV_LDPC_CRC_TYPE_24B_CHECK);
+	fcw->bypass_dec = 0;
+	fcw->bypass_intlv = check_bit(op->ldpc_dec.op_flags,
+			RTE_BBDEV_LDPC_DEINTERLEAVER_BYPASS);
+	if (op->ldpc_dec.q_m == 1) {
+		fcw->bypass_intlv = 1;
+		fcw->qm = 2;
+	}
+	fcw->hcin_decomp_mode = check_bit(op->ldpc_dec.op_flags,
+			RTE_BBDEV_LDPC_HARQ_6BIT_COMPRESSION);
+	fcw->hcout_comp_mode = check_bit(op->ldpc_dec.op_flags,
+			RTE_BBDEV_LDPC_HARQ_6BIT_COMPRESSION);
+	fcw->llr_pack_mode = check_bit(op->ldpc_dec.op_flags,
+			RTE_BBDEV_LDPC_LLR_COMPRESSION);
+	harq_index = hq_index(op->ldpc_dec.harq_combined_output.offset);
+
+	if (fcw->hcin_en > 0) {
+		harq_in_length = op->ldpc_dec.harq_combined_input.length;
+		if (fcw->hcin_decomp_mode > 0)
+			harq_in_length = harq_in_length * 8 / 6;
+		harq_in_length = RTE_MIN(harq_in_length, op->ldpc_dec.n_cb
+				- op->ldpc_dec.n_filler);
+		harq_in_length = RTE_ALIGN_CEIL(harq_in_length, 64);
+		fcw->hcin_size0 = harq_in_length;
+		fcw->hcin_offset = 0;
+		fcw->hcin_size1 = 0;
+	} else {
+		fcw->hcin_size0 = 0;
+		fcw->hcin_offset = 0;
+		fcw->hcin_size1 = 0;
+	}
+
+	fcw->itmax = op->ldpc_dec.iter_max;
+	fcw->itstop = check_bit(op->ldpc_dec.op_flags,
+			RTE_BBDEV_LDPC_ITERATION_STOP_ENABLE);
+	fcw->cnu_algo = ACC_ALGO_MSA;
+	fcw->synd_precoder = fcw->itstop;
+	/*
+	 * These are all implicitly set
+	 * fcw->synd_post = 0;
+	 * fcw->so_en = 0;
+	 * fcw->so_bypass_rm = 0;
+	 * fcw->so_bypass_intlv = 0;
+	 * fcw->dec_convllr = 0;
+	 * fcw->hcout_convllr = 0;
+	 * fcw->hcout_size1 = 0;
+	 * fcw->so_it = 0;
+	 * fcw->hcout_offset = 0;
+	 * fcw->negstop_th = 0;
+	 * fcw->negstop_it = 0;
+	 * fcw->negstop_en = 0;
+	 * fcw->gain_i = 1;
+	 * fcw->gain_h = 1;
+	 */
+	if (fcw->hcout_en > 0) {
+		parity_offset = (op->ldpc_dec.basegraph == 1 ? 20 : 8)
+			* op->ldpc_dec.z_c - op->ldpc_dec.n_filler;
+		k0_p = (fcw->k0 > parity_offset) ?
+				fcw->k0 - op->ldpc_dec.n_filler : fcw->k0;
+		ncb_p = fcw->ncb - op->ldpc_dec.n_filler;
+		l = k0_p + fcw->rm_e;
+		harq_out_length = (uint16_t) fcw->hcin_size0;
+		harq_out_length = RTE_MIN(RTE_MAX(harq_out_length, l), ncb_p);
+		harq_out_length = RTE_ALIGN_CEIL(harq_out_length, 64);
+		fcw->hcout_size0 = harq_out_length;
+		fcw->hcout_size1 = 0;
+		fcw->hcout_offset = 0;
+		harq_layout[harq_index].offset = fcw->hcout_offset;
+		harq_layout[harq_index].size0 = fcw->hcout_size0;
+	} else {
+		fcw->hcout_size0 = 0;
+		fcw->hcout_size1 = 0;
+		fcw->hcout_offset = 0;
+	}
+
+	fcw->tb_crc_select = 0;
+	if (check_bit(op->ldpc_dec.op_flags,
+			RTE_BBDEV_LDPC_CRC_TYPE_24A_CHECK))
+		fcw->tb_crc_select = 2;
+	if (check_bit(op->ldpc_dec.op_flags,
+			RTE_BBDEV_LDPC_CRC_TYPE_16_CHECK))
+		fcw->tb_crc_select = 1;
+}
+
+static inline int
+acc200_dma_desc_le_fill(struct rte_bbdev_enc_op *op,
+		struct acc_dma_req_desc *desc, struct rte_mbuf **input,
+		struct rte_mbuf *output, uint32_t *in_offset,
+		uint32_t *out_offset, uint32_t *out_length,
+		uint32_t *mbuf_total_left, uint32_t *seg_total_left)
+{
+	int next_triplet = 1; /* FCW already done */
+	uint16_t K, in_length_in_bits, in_length_in_bytes;
+	struct rte_bbdev_op_ldpc_enc *enc = &op->ldpc_enc;
+
+	acc_header_init(desc);
+	K = (enc->basegraph == 1 ? 22 : 10) * enc->z_c;
+	in_length_in_bits = K - enc->n_filler;
+	if ((enc->op_flags & RTE_BBDEV_LDPC_CRC_24A_ATTACH) ||
+			(enc->op_flags & RTE_BBDEV_LDPC_CRC_24B_ATTACH))
+		in_length_in_bits -= 24;
+	in_length_in_bytes = in_length_in_bits >> 3;
+
+	if (unlikely((*mbuf_total_left == 0) ||
+			(*mbuf_total_left < in_length_in_bytes))) {
+		rte_bbdev_log(ERR,
+				"Mismatch between mbuf length and included CB sizes: mbuf len %u, cb len %u",
+				*mbuf_total_left, in_length_in_bytes);
+		return -1;
+	}
+
+	next_triplet = acc_dma_fill_blk_type_in(desc, input, in_offset,
+			in_length_in_bytes,
+			seg_total_left, next_triplet,
+			check_bit(op->ldpc_enc.op_flags,
+			RTE_BBDEV_LDPC_ENC_SCATTER_GATHER));
+	if (unlikely(next_triplet < 0)) {
+		rte_bbdev_log(ERR,
+				"Mismatch between data to process and mbuf data length in bbdev_op: %p",
+				op);
+		return -1;
+	}
+	desc->data_ptrs[next_triplet - 1].last = 1;
+	desc->m2dlen = next_triplet;
+	*mbuf_total_left -= in_length_in_bytes;
+
+	/* Set output length */
+	/* Integer round up division by 8 */
+	*out_length = (enc->cb_params.e + 7) >> 3;
+
+	next_triplet = acc_dma_fill_blk_type(desc, output, *out_offset,
+			*out_length, next_triplet, ACC_DMA_BLKID_OUT_ENC);
+	op->ldpc_enc.output.length += *out_length;
+	*out_offset += *out_length;
+	desc->data_ptrs[next_triplet - 1].last = 1;
+	desc->data_ptrs[next_triplet - 1].dma_ext = 0;
+	desc->d2mlen = next_triplet - desc->m2dlen;
+
+	desc->op_addr = op;
+
+	return 0;
+}
+
+static inline int
+acc200_dma_desc_ld_fill(struct rte_bbdev_dec_op *op,
+		struct acc_dma_req_desc *desc,
+		struct rte_mbuf **input, struct rte_mbuf *h_output,
+		uint32_t *in_offset, uint32_t *h_out_offset,
+		uint32_t *h_out_length, uint32_t *mbuf_total_left,
+		uint32_t *seg_total_left,
+		struct acc_fcw_ld *fcw)
+{
+	struct rte_bbdev_op_ldpc_dec *dec = &op->ldpc_dec;
+	int next_triplet = 1; /* FCW already done */
+	uint32_t input_length;
+	uint16_t output_length, crc24_overlap = 0;
+	uint16_t sys_cols, K, h_p_size, h_np_size;
+	bool h_comp = check_bit(dec->op_flags,
+			RTE_BBDEV_LDPC_HARQ_6BIT_COMPRESSION);
+
+	acc_header_init(desc);
+
+	if (check_bit(op->ldpc_dec.op_flags,
+			RTE_BBDEV_LDPC_CRC_TYPE_24B_DROP))
+		crc24_overlap = 24;
+
+	/* Compute some LDPC BG lengths */
+	input_length = fcw->rm_e;
+	if (check_bit(op->ldpc_dec.op_flags,
+			RTE_BBDEV_LDPC_LLR_COMPRESSION))
+		input_length = (input_length * 3 + 3) / 4;
+	sys_cols = (dec->basegraph == 1) ? 22 : 10;
+	K = sys_cols * dec->z_c;
+	output_length = K - dec->n_filler - crc24_overlap;
+
+	if (unlikely((*mbuf_total_left == 0) ||
+			(*mbuf_total_left < input_length))) {
+		rte_bbdev_log(ERR,
+				"Mismatch between mbuf length and included CB sizes: mbuf len %u, cb len %u",
+				*mbuf_total_left, input_length);
+		return -1;
+	}
+
+	next_triplet = acc_dma_fill_blk_type_in(desc, input,
+			in_offset, input_length,
+			seg_total_left, next_triplet,
+			check_bit(op->ldpc_dec.op_flags,
+			RTE_BBDEV_LDPC_DEC_SCATTER_GATHER));
+
+	if (unlikely(next_triplet < 0)) {
+		rte_bbdev_log(ERR,
+				"Mismatch between data to process and mbuf data length in bbdev_op: %p",
+				op);
+		return -1;
+	}
+
+	if (check_bit(op->ldpc_dec.op_flags,
+				RTE_BBDEV_LDPC_HQ_COMBINE_IN_ENABLE)) {
+		if (op->ldpc_dec.harq_combined_input.data == 0) {
+			rte_bbdev_log(ERR, "HARQ input is not defined");
+			return -1;
+		}
+		h_p_size = fcw->hcin_size0 + fcw->hcin_size1;
+		if (h_comp)
+			h_p_size = (h_p_size * 3 + 3) / 4;
+		if (op->ldpc_dec.harq_combined_input.data == 0) {
+			rte_bbdev_log(ERR, "HARQ input is not defined");
+			return -1;
+		}
+		acc_dma_fill_blk_type(
+				desc,
+				op->ldpc_dec.harq_combined_input.data,
+				op->ldpc_dec.harq_combined_input.offset,
+				h_p_size,
+				next_triplet,
+				ACC_DMA_BLKID_IN_HARQ);
+		next_triplet++;
+	}
+
+	desc->data_ptrs[next_triplet - 1].last = 1;
+	desc->m2dlen = next_triplet;
+	*mbuf_total_left -= input_length;
+
+	next_triplet = acc_dma_fill_blk_type(desc, h_output,
+			*h_out_offset, output_length >> 3, next_triplet,
+			ACC_DMA_BLKID_OUT_HARD);
+
+	if (check_bit(op->ldpc_dec.op_flags,
+				RTE_BBDEV_LDPC_HQ_COMBINE_OUT_ENABLE)) {
+		if (op->ldpc_dec.harq_combined_output.data == 0) {
+			rte_bbdev_log(ERR, "HARQ output is not defined");
+			return -1;
+		}
+
+		/* Pruned size of the HARQ */
+		h_p_size = fcw->hcout_size0 + fcw->hcout_size1;
+		/* Non-Pruned size of the HARQ */
+		h_np_size = fcw->hcout_offset > 0 ?
+				fcw->hcout_offset + fcw->hcout_size1 :
+				h_p_size;
+		if (h_comp) {
+			h_np_size = (h_np_size * 3 + 3) / 4;
+			h_p_size = (h_p_size * 3 + 3) / 4;
+		}
+		dec->harq_combined_output.length = h_np_size;
+		acc_dma_fill_blk_type(
+				desc,
+				dec->harq_combined_output.data,
+				dec->harq_combined_output.offset,
+				h_p_size,
+				next_triplet,
+				ACC_DMA_BLKID_OUT_HARQ);
+
+		next_triplet++;
+	}
+
+	*h_out_length = output_length >> 3;
+	dec->hard_output.length += *h_out_length;
+	*h_out_offset += *h_out_length;
+	desc->data_ptrs[next_triplet - 1].last = 1;
+	desc->d2mlen = next_triplet - desc->m2dlen;
+
+	desc->op_addr = op;
+
+	return 0;
+}
+
+static inline void
+acc200_dma_desc_ld_update(struct rte_bbdev_dec_op *op,
+		struct acc_dma_req_desc *desc,
+		struct rte_mbuf *input, struct rte_mbuf *h_output,
+		uint32_t *in_offset, uint32_t *h_out_offset,
+		uint32_t *h_out_length,
+		union acc_harq_layout_data *harq_layout)
+{
+	int next_triplet = 1; /* FCW already done */
+	desc->data_ptrs[next_triplet].address =
+			rte_pktmbuf_iova_offset(input, *in_offset);
+	next_triplet++;
+
+	if (check_bit(op->ldpc_dec.op_flags,
+				RTE_BBDEV_LDPC_HQ_COMBINE_IN_ENABLE)) {
+		struct rte_bbdev_op_data hi = op->ldpc_dec.harq_combined_input;
+		desc->data_ptrs[next_triplet].address =
+				rte_pktmbuf_iova_offset(hi.data, hi.offset);
+		next_triplet++;
+	}
+
+	desc->data_ptrs[next_triplet].address =
+			rte_pktmbuf_iova_offset(h_output, *h_out_offset);
+	*h_out_length = desc->data_ptrs[next_triplet].blen;
+	next_triplet++;
+
+	if (check_bit(op->ldpc_dec.op_flags,
+				RTE_BBDEV_LDPC_HQ_COMBINE_OUT_ENABLE)) {
+		/* Adjust based on previous operation */
+		struct rte_bbdev_dec_op *prev_op = desc->op_addr;
+		op->ldpc_dec.harq_combined_output.length =
+				prev_op->ldpc_dec.harq_combined_output.length;
+		uint32_t harq_idx = hq_index(
+				op->ldpc_dec.harq_combined_output.offset);
+		uint32_t prev_harq_idx = hq_index(
+				prev_op->ldpc_dec.harq_combined_output.offset);
+		harq_layout[harq_idx].val = harq_layout[prev_harq_idx].val;
+		struct rte_bbdev_op_data ho =
+				op->ldpc_dec.harq_combined_output;
+		desc->data_ptrs[next_triplet].address =
+				rte_pktmbuf_iova_offset(ho.data, ho.offset);
+		next_triplet++;
+	}
+
+	op->ldpc_dec.hard_output.length += *h_out_length;
+	desc->op_addr = op;
+}
+
+/* Enqueue one encode operations for ACC200 device in CB mode
+ * multiplexed on the same descriptor
+ */
+static inline int
+enqueue_ldpc_enc_n_op_cb(struct acc_queue *q, struct rte_bbdev_enc_op **ops,
+		uint16_t total_enqueued_descs, int16_t num)
+{
+	union acc_dma_desc *desc = NULL;
+	uint32_t out_length;
+	struct rte_mbuf *output_head, *output;
+	int i, next_triplet;
+	uint16_t  in_length_in_bytes;
+	struct rte_bbdev_op_ldpc_enc *enc = &ops[0]->ldpc_enc;
+
+	uint16_t desc_idx = ((q->sw_ring_head + total_enqueued_descs)
+			& q->sw_ring_wrap_mask);
+	desc = q->ring_addr + desc_idx;
+	acc_fcw_le_fill(ops[0], &desc->req.fcw_le, num, 0);
+
+	/** This could be done at polling */
+	acc_header_init(&desc->req);
+	desc->req.numCBs = num;
+
+	in_length_in_bytes = ops[0]->ldpc_enc.input.data->data_len;
+	out_length = (enc->cb_params.e + 7) >> 3;
+	desc->req.m2dlen = 1 + num;
+	desc->req.d2mlen = num;
+	next_triplet = 1;
+
+	for (i = 0; i < num; i++) {
+		desc->req.data_ptrs[next_triplet].address =
+			rte_pktmbuf_iova_offset(ops[i]->ldpc_enc.input.data, 0);
+		desc->req.data_ptrs[next_triplet].blen = in_length_in_bytes;
+		next_triplet++;
+		desc->req.data_ptrs[next_triplet].address =
+				rte_pktmbuf_iova_offset(
+				ops[i]->ldpc_enc.output.data, 0);
+		desc->req.data_ptrs[next_triplet].blen = out_length;
+		next_triplet++;
+		ops[i]->ldpc_enc.output.length = out_length;
+		output_head = output = ops[i]->ldpc_enc.output.data;
+		mbuf_append(output_head, output, out_length);
+		output->data_len = out_length;
+	}
+
+	desc->req.op_addr = ops[0];
+	/* Keep track of pointers even when multiplexed in single descriptor */
+	struct acc_ptrs *context_ptrs = q->companion_ring_addr + desc_idx;
+	for (i = 0; i < num; i++)
+		context_ptrs->ptr[i].op_addr = ops[i];
+
+#ifdef RTE_LIBRTE_BBDEV_DEBUG
+	rte_memdump(stderr, "FCW", &desc->req.fcw_le,
+			sizeof(desc->req.fcw_le) - 8);
+	rte_memdump(stderr, "Req Desc.", desc, sizeof(*desc));
+#endif
+
+	/* One CB (one op) was successfully prepared to enqueue */
+	return num;
+}
+
+/* Enqueue one encode operations for ACC200 device for a partial TB
+ * all codes blocks have same configuration multiplexed on the same descriptor
+ */
+static inline void
+enqueue_ldpc_enc_part_tb(struct acc_queue *q, struct rte_bbdev_enc_op *op,
+		uint16_t total_enqueued_descs, int16_t num_cbs, uint32_t e,
+		uint16_t in_len_B, uint32_t out_len_B, uint32_t *in_offset,
+		uint32_t *out_offset)
+{
+
+	union acc_dma_desc *desc = NULL;
+	struct rte_mbuf *output_head, *output;
+	int i, next_triplet;
+	struct rte_bbdev_op_ldpc_enc *enc = &op->ldpc_enc;
+
+
+	uint16_t desc_idx = ((q->sw_ring_head + total_enqueued_descs)
+			& q->sw_ring_wrap_mask);
+	desc = q->ring_addr + desc_idx;
+	acc_fcw_le_fill(op, &desc->req.fcw_le, num_cbs, e);
+
+	/** This could be done at polling */
+	acc_header_init(&desc->req);
+	desc->req.numCBs = num_cbs;
+
+	desc->req.m2dlen = 1 + num_cbs;
+	desc->req.d2mlen = num_cbs;
+	next_triplet = 1;
+
+	for (i = 0; i < num_cbs; i++) {
+		desc->req.data_ptrs[next_triplet].address =
+			rte_pktmbuf_iova_offset(enc->input.data,
+					*in_offset);
+		*in_offset += in_len_B;
+		desc->req.data_ptrs[next_triplet].blen = in_len_B;
+		next_triplet++;
+		desc->req.data_ptrs[next_triplet].address =
+				rte_pktmbuf_iova_offset(
+						enc->output.data, *out_offset);
+		*out_offset += out_len_B;
+		desc->req.data_ptrs[next_triplet].blen = out_len_B;
+		next_triplet++;
+		enc->output.length += out_len_B;
+		output_head = output = enc->output.data;
+		mbuf_append(output_head, output, out_len_B);
+	}
+
+#ifdef RTE_LIBRTE_BBDEV_DEBUG
+	rte_memdump(stderr, "FCW", &desc->req.fcw_le,
+			sizeof(desc->req.fcw_le) - 8);
+	rte_memdump(stderr, "Req Desc.", desc, sizeof(*desc));
+#endif
+
+}
+
+/* Enqueue one encode operations for ACC200 device in CB mode */
+static inline int
+enqueue_ldpc_enc_one_op_cb(struct acc_queue *q, struct rte_bbdev_enc_op *op,
+		uint16_t total_enqueued_cbs)
+{
+	union acc_dma_desc *desc = NULL;
+	int ret;
+	uint32_t in_offset, out_offset, out_length, mbuf_total_left,
+		seg_total_left;
+	struct rte_mbuf *input, *output_head, *output;
+
+	uint16_t desc_idx = ((q->sw_ring_head + total_enqueued_cbs)
+			& q->sw_ring_wrap_mask);
+	desc = q->ring_addr + desc_idx;
+	acc_fcw_le_fill(op, &desc->req.fcw_le, 1, 0);
+
+	input = op->ldpc_enc.input.data;
+	output_head = output = op->ldpc_enc.output.data;
+	in_offset = op->ldpc_enc.input.offset;
+	out_offset = op->ldpc_enc.output.offset;
+	out_length = 0;
+	mbuf_total_left = op->ldpc_enc.input.length;
+	seg_total_left = rte_pktmbuf_data_len(op->ldpc_enc.input.data)
+			- in_offset;
+
+	ret = acc200_dma_desc_le_fill(op, &desc->req, &input, output,
+			&in_offset, &out_offset, &out_length, &mbuf_total_left,
+			&seg_total_left);
+
+	if (unlikely(ret < 0))
+		return ret;
+
+	mbuf_append(output_head, output, out_length);
+
+#ifdef RTE_LIBRTE_BBDEV_DEBUG
+	rte_memdump(stderr, "FCW", &desc->req.fcw_le,
+			sizeof(desc->req.fcw_le) - 8);
+	rte_memdump(stderr, "Req Desc.", desc, sizeof(*desc));
+
+	if (check_mbuf_total_left(mbuf_total_left) != 0)
+		return -EINVAL;
+#endif
+	/* One CB (one op) was successfully prepared to enqueue */
+	return 1;
+}
+
+/* Enqueue one encode operations for ACC200 device in TB mode.
+ * returns the number of descs used
+ */
+static inline int
+enqueue_ldpc_enc_one_op_tb(struct acc_queue *q, struct rte_bbdev_enc_op *op,
+		uint16_t enq_descs, uint8_t cbs_in_tb)
+{
+	uint8_t num_a, num_b;
+	uint16_t desc_idx;
+	uint8_t r = op->ldpc_enc.tb_params.r;
+	uint8_t cab =  op->ldpc_enc.tb_params.cab;
+	union acc_dma_desc *desc;
+	uint16_t init_enq_descs = enq_descs;
+	uint16_t input_len_B = ((op->ldpc_enc.basegraph == 1 ? 22 : 10) *
+			op->ldpc_enc.z_c) >> 3;
+	if (check_bit(op->ldpc_enc.op_flags, RTE_BBDEV_LDPC_CRC_24B_ATTACH))
+		input_len_B -= 3;
+
+	if (r < cab) {
+		num_a = cab - r;
+		num_b = cbs_in_tb - cab;
+	} else {
+		num_a = 0;
+		num_b = cbs_in_tb - r;
+	}
+	uint32_t in_offset = 0, out_offset = 0;
+
+	while (num_a > 0) {
+		uint32_t e = op->ldpc_enc.tb_params.ea;
+		uint32_t out_len_B = (e + 7) >> 3;
+		uint8_t enq = RTE_MIN(num_a, ACC_MUX_5GDL_DESC);
+		num_a -= enq;
+		enqueue_ldpc_enc_part_tb(q, op, enq_descs, enq, e, input_len_B,
+				out_len_B, &in_offset, &out_offset);
+		enq_descs++;
+	}
+	while (num_b > 0) {
+		uint32_t e = op->ldpc_enc.tb_params.eb;
+		uint32_t out_len_B = (e + 7) >> 3;
+		uint8_t enq = RTE_MIN(num_b, ACC_MUX_5GDL_DESC);
+		num_b -= enq;
+		enqueue_ldpc_enc_part_tb(q, op, enq_descs, enq, e, input_len_B,
+				out_len_B, &in_offset, &out_offset);
+		enq_descs++;
+	}
+
+	uint16_t return_descs = enq_descs - init_enq_descs;
+	/* Keep total number of CBs in first TB */
+	desc_idx = ((q->sw_ring_head + init_enq_descs)
+			& q->sw_ring_wrap_mask);
+	desc = q->ring_addr + desc_idx;
+	desc->req.cbs_in_tb = return_descs; /** Actual number of descriptors */
+	desc->req.op_addr = op;
+
+	/* Set SDone on last CB descriptor for TB mode. */
+	desc_idx = ((q->sw_ring_head + enq_descs - 1)
+			& q->sw_ring_wrap_mask);
+	desc = q->ring_addr + desc_idx;
+	desc->req.sdone_enable = 1;
+	desc->req.irq_enable = q->irq_enable;
+	desc->req.op_addr = op;
+	return return_descs;
+}
+
+/** Enqueue one decode operations for ACC200 device in CB mode */
+static inline int
+enqueue_ldpc_dec_one_op_cb(struct acc_queue *q, struct rte_bbdev_dec_op *op,
+		uint16_t total_enqueued_cbs, bool same_op)
+{
+	int ret, hq_len;
+	if (op->ldpc_dec.cb_params.e == 0)
+		return -EINVAL;
+
+	union acc_dma_desc *desc;
+	uint16_t desc_idx = ((q->sw_ring_head + total_enqueued_cbs)
+			& q->sw_ring_wrap_mask);
+	desc = q->ring_addr + desc_idx;
+	struct rte_mbuf *input, *h_output_head, *h_output;
+	uint32_t in_offset, h_out_offset, mbuf_total_left, h_out_length = 0;
+	input = op->ldpc_dec.input.data;
+	h_output_head = h_output = op->ldpc_dec.hard_output.data;
+	in_offset = op->ldpc_dec.input.offset;
+	h_out_offset = op->ldpc_dec.hard_output.offset;
+	mbuf_total_left = op->ldpc_dec.input.length;
+#ifdef RTE_LIBRTE_BBDEV_DEBUG
+	if (unlikely(input == NULL)) {
+		rte_bbdev_log(ERR, "Invalid mbuf pointer");
+		return -EFAULT;
+	}
+#endif
+	union acc_harq_layout_data *harq_layout = q->d->harq_layout;
+
+	if (same_op) {
+		union acc_dma_desc *prev_desc;
+		desc_idx = ((q->sw_ring_head + total_enqueued_cbs - 1)
+				& q->sw_ring_wrap_mask);
+		prev_desc = q->ring_addr + desc_idx;
+		uint8_t *prev_ptr = (uint8_t *) prev_desc;
+		uint8_t *new_ptr = (uint8_t *) desc;
+		/* Copy first 4 words and BDESCs */
+		rte_memcpy(new_ptr, prev_ptr, ACC_5GUL_SIZE_0);
+		rte_memcpy(new_ptr + ACC_5GUL_OFFSET_0,
+				prev_ptr + ACC_5GUL_OFFSET_0,
+				ACC_5GUL_SIZE_1);
+		desc->req.op_addr = prev_desc->req.op_addr;
+		/* Copy FCW */
+		rte_memcpy(new_ptr + ACC_DESC_FCW_OFFSET,
+				prev_ptr + ACC_DESC_FCW_OFFSET,
+				ACC_FCW_LD_BLEN);
+		acc200_dma_desc_ld_update(op, &desc->req, input, h_output,
+				&in_offset, &h_out_offset,
+				&h_out_length, harq_layout);
+	} else {
+		struct acc_fcw_ld *fcw;
+		uint32_t seg_total_left;
+		fcw = &desc->req.fcw_ld;
+		acc200_fcw_ld_fill(op, fcw, harq_layout);
+
+		/* Special handling when using mbuf or not */
+		if (check_bit(op->ldpc_dec.op_flags,
+			RTE_BBDEV_LDPC_DEC_SCATTER_GATHER))
+			seg_total_left = rte_pktmbuf_data_len(input)
+					- in_offset;
+		else
+			seg_total_left = fcw->rm_e;
+
+		ret = acc200_dma_desc_ld_fill(op, &desc->req, &input, h_output,
+				&in_offset, &h_out_offset,
+				&h_out_length, &mbuf_total_left,
+				&seg_total_left, fcw);
+		if (unlikely(ret < 0))
+			return ret;
+	}
+
+	/* Hard output */
+	mbuf_append(h_output_head, h_output, h_out_length);
+	if (op->ldpc_dec.harq_combined_output.length > 0) {
+		/* Push the HARQ output into host memory */
+		struct rte_mbuf *hq_output_head, *hq_output;
+		hq_output_head = op->ldpc_dec.harq_combined_output.data;
+		hq_output = op->ldpc_dec.harq_combined_output.data;
+		hq_len = op->ldpc_dec.harq_combined_output.length;
+		if (unlikely(!mbuf_append(hq_output_head, hq_output,
+				hq_len))) {
+			rte_bbdev_log(ERR, "HARQ output mbuf issue %d %d\n",
+					hq_output->buf_len,
+					hq_len);
+			return -1;
+		}
+	}
+
+#ifdef RTE_LIBRTE_BBDEV_DEBUG
+	rte_memdump(stderr, "FCW", &desc->req.fcw_ld,
+			sizeof(desc->req.fcw_ld) - 8);
+	rte_memdump(stderr, "Req Desc.", desc, sizeof(*desc));
+#endif
+
+	/* One CB (one op) was successfully prepared to enqueue */
+	return 1;
+}
+
+
+/* Enqueue one decode operations for ACC200 device in TB mode */
+static inline int
+enqueue_ldpc_dec_one_op_tb(struct acc_queue *q, struct rte_bbdev_dec_op *op,
+		uint16_t total_enqueued_cbs, uint8_t cbs_in_tb)
+{
+	union acc_dma_desc *desc = NULL;
+	union acc_dma_desc *desc_first = NULL;
+	int ret;
+	uint8_t r, c;
+	uint32_t in_offset, h_out_offset,
+		h_out_length, mbuf_total_left, seg_total_left;
+	struct rte_mbuf *input, *h_output_head, *h_output;
+	uint16_t current_enqueued_cbs = 0;
+	uint16_t sys_cols, trail_len = 0;
+
+	uint16_t desc_idx = ((q->sw_ring_head + total_enqueued_cbs)
+			& q->sw_ring_wrap_mask);
+	desc = q->ring_addr + desc_idx;
+	desc_first = desc;
+	uint64_t fcw_offset = (desc_idx << 8) + ACC_DESC_FCW_OFFSET;
+	union acc_harq_layout_data *harq_layout = q->d->harq_layout;
+	acc200_fcw_ld_fill(op, &desc->req.fcw_ld, harq_layout);
+
+	input = op->ldpc_dec.input.data;
+	h_output_head = h_output = op->ldpc_dec.hard_output.data;
+	in_offset = op->ldpc_dec.input.offset;
+	h_out_offset = op->ldpc_dec.hard_output.offset;
+	h_out_length = 0;
+	mbuf_total_left = op->ldpc_dec.input.length;
+	c = op->ldpc_dec.tb_params.c;
+	r = op->ldpc_dec.tb_params.r;
+	if (check_bit(op->ldpc_dec.op_flags,
+			RTE_BBDEV_LDPC_CRC_TYPE_24A_CHECK)) {
+		sys_cols = (op->ldpc_dec.basegraph == 1) ? 22 : 10;
+		trail_len = sys_cols * op->ldpc_dec.z_c -
+				op->ldpc_dec.n_filler - 24;
+	}
+
+	while (mbuf_total_left > 0 && r < c) {
+		if (check_bit(op->ldpc_dec.op_flags,
+				RTE_BBDEV_LDPC_DEC_SCATTER_GATHER))
+			seg_total_left = rte_pktmbuf_data_len(input)
+					- in_offset;
+		else
+			seg_total_left = op->ldpc_dec.input.length;
+		/* Set up DMA descriptor */
+		desc_idx = ((q->sw_ring_head + total_enqueued_cbs)
+				& q->sw_ring_wrap_mask);
+		desc = q->ring_addr + desc_idx;
+		fcw_offset = (desc_idx << 8) + ACC_DESC_FCW_OFFSET;
+		desc->req.data_ptrs[0].address = q->ring_addr_iova +
+				fcw_offset;
+		desc->req.data_ptrs[0].blen = ACC_FCW_LD_BLEN;
+		rte_memcpy(&desc->req.fcw_ld, &desc_first->req.fcw_ld,
+				ACC_FCW_LD_BLEN);
+		desc->req.fcw_ld.tb_trailer_size = (c - r - 1) * trail_len;
+
+		ret = acc200_dma_desc_ld_fill(op, &desc->req, &input,
+				h_output, &in_offset, &h_out_offset,
+				&h_out_length,
+				&mbuf_total_left, &seg_total_left,
+				&desc->req.fcw_ld);
+
+		if (unlikely(ret < 0))
+			return ret;
+
+		/* Hard output */
+		mbuf_append(h_output_head, h_output, h_out_length);
+
+		/* Set total number of CBs in TB */
+		desc->req.cbs_in_tb = cbs_in_tb;
+#ifdef RTE_LIBRTE_BBDEV_DEBUG
+		rte_memdump(stderr, "FCW", &desc->req.fcw_td,
+				sizeof(desc->req.fcw_td) - 8);
+		rte_memdump(stderr, "Req Desc.", desc, sizeof(*desc));
+#endif
+		if (check_bit(op->ldpc_dec.op_flags,
+				RTE_BBDEV_LDPC_DEC_SCATTER_GATHER)
+				&& (seg_total_left == 0)) {
+			/* Go to the next mbuf */
+			input = input->next;
+			in_offset = 0;
+			h_output = h_output->next;
+			h_out_offset = 0;
+		}
+		total_enqueued_cbs++;
+		current_enqueued_cbs++;
+		r++;
+	}
+
+#ifdef RTE_LIBRTE_BBDEV_DEBUG
+	if (check_mbuf_total_left(mbuf_total_left) != 0)
+		return -EINVAL;
+#endif
+	/* Set SDone on last CB descriptor for TB mode */
+	desc->req.sdone_enable = 1;
+	desc->req.irq_enable = q->irq_enable;
+
+	return current_enqueued_cbs;
+}
+
+/** Enqueue encode operations for ACC200 device in CB mode. */
+static inline uint16_t
+acc200_enqueue_ldpc_enc_cb(struct rte_bbdev_queue_data *q_data,
+		struct rte_bbdev_enc_op **ops, uint16_t num)
+{
+	struct acc_queue *q = q_data->queue_private;
+	int32_t avail = acc_ring_avail_enq(q);
+	uint16_t i = 0;
+	union acc_dma_desc *desc;
+	int ret, desc_idx = 0;
+	int16_t enq, left = num;
+
+	while (left > 0) {
+		if (unlikely(avail < 1)) {
+			acc_enqueue_ring_full(q_data);
+			break;
+		}
+		avail--;
+		enq = RTE_MIN(left, ACC_MUX_5GDL_DESC);
+		enq = check_mux(&ops[i], enq);
+		if (enq > 1) {
+			ret = enqueue_ldpc_enc_n_op_cb(q, &ops[i],
+					desc_idx, enq);
+			if (ret < 0) {
+				acc_enqueue_invalid(q_data);
+				break;
+			}
+			i += enq;
+		} else {
+			ret = enqueue_ldpc_enc_one_op_cb(q, ops[i], desc_idx);
+			if (ret < 0) {
+				acc_enqueue_invalid(q_data);
+				break;
+			}
+			i++;
+		}
+		desc_idx++;
+		left = num - i;
+	}
+
+	if (unlikely(i == 0))
+		return 0; /* Nothing to enqueue */
+
+	/* Set SDone in last CB in enqueued ops for CB mode*/
+	desc = q->ring_addr + ((q->sw_ring_head + desc_idx - 1)
+			& q->sw_ring_wrap_mask);
+	desc->req.sdone_enable = 1;
+	desc->req.irq_enable = q->irq_enable;
+
+	acc_dma_enqueue(q, desc_idx, &q_data->queue_stats);
+
+	/* Update stats */
+	q_data->queue_stats.enqueued_count += i;
+	q_data->queue_stats.enqueue_err_count += num - i;
+
+	return i;
+}
+
+/* Enqueue LDPC encode operations for ACC200 device in TB mode. */
+static uint16_t
+acc200_enqueue_ldpc_enc_tb(struct rte_bbdev_queue_data *q_data,
+		struct rte_bbdev_enc_op **ops, uint16_t num)
+{
+	struct acc_queue *q = q_data->queue_private;
+	int32_t avail = acc_ring_avail_enq(q);
+	uint16_t i, enqueued_descs = 0;
+	uint8_t cbs_in_tb;
+	int descs_used;
+
+	for (i = 0; i < num; ++i) {
+		cbs_in_tb = get_num_cbs_in_tb_ldpc_enc(&ops[i]->ldpc_enc);
+		/* Check if there are available space for further processing */
+		if (unlikely((avail - cbs_in_tb < 0) || (cbs_in_tb == 0))) {
+			acc_enqueue_ring_full(q_data);
+			break;
+		}
+
+		descs_used = enqueue_ldpc_enc_one_op_tb(q, ops[i],
+				enqueued_descs, cbs_in_tb);
+		if (descs_used < 0) {
+			acc_enqueue_invalid(q_data);
+			break;
+		}
+		enqueued_descs += descs_used;
+		avail -= descs_used;
+	}
+	if (unlikely(enqueued_descs == 0))
+		return 0; /* Nothing to enqueue */
+
+	acc_dma_enqueue(q, enqueued_descs, &q_data->queue_stats);
+
+	/* Update stats */
+	q_data->queue_stats.enqueued_count += i;
+	q_data->queue_stats.enqueue_err_count += num - i;
+
+	return i;
+}
+
+/* Check room in AQ for the enqueues batches into Qmgr */
+static int32_t
+acc200_aq_avail(struct rte_bbdev_queue_data *q_data, uint16_t num_ops)
+{
+	struct acc_queue *q = q_data->queue_private;
+	int32_t aq_avail = q->aq_depth -
+			((q->aq_enqueued - q->aq_dequeued +
+			ACC_MAX_QUEUE_DEPTH) % ACC_MAX_QUEUE_DEPTH)
+			- (num_ops >> 7);
+	if (aq_avail <= 0)
+		acc_enqueue_queue_full(q_data);
+	return aq_avail;
+}
+
+/* Enqueue encode operations for ACC200 device. */
+static uint16_t
+acc200_enqueue_ldpc_enc(struct rte_bbdev_queue_data *q_data,
+		struct rte_bbdev_enc_op **ops, uint16_t num)
+{
+	struct acc_queue *q = q_data->queue_private;
+	int32_t aq_avail = acc_ring_avail_enq(q);
+	if (unlikely((aq_avail <= 0) || (num == 0)))
+		return 0;
+	if (ops[0]->ldpc_enc.code_block_mode == RTE_BBDEV_TRANSPORT_BLOCK)
+		return acc200_enqueue_ldpc_enc_tb(q_data, ops, num);
+	else
+		return acc200_enqueue_ldpc_enc_cb(q_data, ops, num);
+}
+
+/* Enqueue decode operations for ACC200 device in TB mode */
+static uint16_t
+acc200_enqueue_ldpc_dec_tb(struct rte_bbdev_queue_data *q_data,
+		struct rte_bbdev_dec_op **ops, uint16_t num)
+{
+	struct acc_queue *q = q_data->queue_private;
+	int32_t avail = acc_ring_avail_enq(q);
+	uint16_t i, enqueued_cbs = 0;
+	uint8_t cbs_in_tb;
+	int ret;
+
+	for (i = 0; i < num; ++i) {
+		cbs_in_tb = get_num_cbs_in_tb_ldpc_dec(&ops[i]->ldpc_dec);
+		/* Check if there are available space for further processing */
+		if (unlikely((avail - cbs_in_tb < 0) ||
+				(cbs_in_tb == 0)))
+			break;
+		avail -= cbs_in_tb;
+
+		ret = enqueue_ldpc_dec_one_op_tb(q, ops[i],
+				enqueued_cbs, cbs_in_tb);
+		if (ret <= 0)
+			break;
+		enqueued_cbs += ret;
+	}
+
+	acc_dma_enqueue(q, enqueued_cbs, &q_data->queue_stats);
+
+	/* Update stats */
+	q_data->queue_stats.enqueued_count += i;
+	q_data->queue_stats.enqueue_err_count += num - i;
+	return i;
+}
+
+/* Enqueue decode operations for ACC200 device in CB mode */
+static uint16_t
+acc200_enqueue_ldpc_dec_cb(struct rte_bbdev_queue_data *q_data,
+		struct rte_bbdev_dec_op **ops, uint16_t num)
+{
+	struct acc_queue *q = q_data->queue_private;
+	int32_t avail = acc_ring_avail_enq(q);
+	uint16_t i;
+	union acc_dma_desc *desc;
+	int ret;
+	bool same_op = false;
+	for (i = 0; i < num; ++i) {
+		/* Check if there are available space for further processing */
+		if (unlikely(avail < 1)) {
+			acc_enqueue_ring_full(q_data);
+			break;
+		}
+		avail -= 1;
+#ifdef ACC200_DESC_OPTIMIZATION
+		if (i > 0)
+			same_op = cmp_ldpc_dec_op(&ops[i-1]);
+#endif
+		rte_bbdev_log(INFO, "Op %d %d %d %d %d %d %d %d %d %d %d %d\n",
+			i, ops[i]->ldpc_dec.op_flags, ops[i]->ldpc_dec.rv_index,
+			ops[i]->ldpc_dec.iter_max, ops[i]->ldpc_dec.iter_count,
+			ops[i]->ldpc_dec.basegraph, ops[i]->ldpc_dec.z_c,
+			ops[i]->ldpc_dec.n_cb, ops[i]->ldpc_dec.q_m,
+			ops[i]->ldpc_dec.n_filler, ops[i]->ldpc_dec.cb_params.e,
+			same_op);
+		ret = enqueue_ldpc_dec_one_op_cb(q, ops[i], i, same_op);
+		if (ret < 0) {
+			acc_enqueue_invalid(q_data);
+			break;
+		}
+	}
+
+	if (unlikely(i == 0))
+		return 0; /* Nothing to enqueue */
+
+	/* Set SDone in last CB in enqueued ops for CB mode*/
+	desc = q->ring_addr + ((q->sw_ring_head + i - 1)
+			& q->sw_ring_wrap_mask);
+
+	desc->req.sdone_enable = 1;
+	desc->req.irq_enable = q->irq_enable;
+
+	acc_dma_enqueue(q, i, &q_data->queue_stats);
+
+	/* Update stats */
+	q_data->queue_stats.enqueued_count += i;
+	q_data->queue_stats.enqueue_err_count += num - i;
+	return i;
+}
+
+/* Enqueue decode operations for ACC200 device. */
+static uint16_t
+acc200_enqueue_ldpc_dec(struct rte_bbdev_queue_data *q_data,
+		struct rte_bbdev_dec_op **ops, uint16_t num)
+{
+	int32_t aq_avail = acc200_aq_avail(q_data, num);
+	if (unlikely((aq_avail <= 0) || (num == 0)))
+		return 0;
+	if (ops[0]->ldpc_dec.code_block_mode == RTE_BBDEV_TRANSPORT_BLOCK)
+		return acc200_enqueue_ldpc_dec_tb(q_data, ops, num);
+	else
+		return acc200_enqueue_ldpc_dec_cb(q_data, ops, num);
+}
+
+
+/* Dequeue one encode operations from ACC200 device in CB mode
+ */
+static inline int
+dequeue_enc_one_op_cb(struct acc_queue *q, struct rte_bbdev_enc_op **ref_op,
+		uint16_t *dequeued_ops, uint32_t *aq_dequeued,
+		uint16_t *dequeued_descs)
+{
+	union acc_dma_desc *desc, atom_desc;
+	union acc_dma_rsp_desc rsp;
+	struct rte_bbdev_enc_op *op;
+	int i;
+	int desc_idx = ((q->sw_ring_tail + *dequeued_descs)
+			& q->sw_ring_wrap_mask);
+	desc = q->ring_addr + desc_idx;
+	atom_desc.atom_hdr = __atomic_load_n((uint64_t *)desc,
+			__ATOMIC_RELAXED);
+
+	/* Check fdone bit */
+	if (!(atom_desc.rsp.val & ACC_FDONE))
+		return -1;
+
+	rsp.val = atom_desc.rsp.val;
+	rte_bbdev_log_debug("Resp. desc %p: %x", desc, rsp.val);
+
+	/* Dequeue */
+	op = desc->req.op_addr;
+
+	/* Clearing status, it will be set based on response */
+	op->status = 0;
+
+	op->status |= ((rsp.input_err)
+			? (1 << RTE_BBDEV_DATA_ERROR) : 0);
+	op->status |= ((rsp.dma_err) ? (1 << RTE_BBDEV_DRV_ERROR) : 0);
+	op->status |= ((rsp.fcw_err) ? (1 << RTE_BBDEV_DRV_ERROR) : 0);
+
+	if (desc->req.last_desc_in_batch) {
+		(*aq_dequeued)++;
+		desc->req.last_desc_in_batch = 0;
+	}
+	desc->rsp.val = ACC_DMA_DESC_TYPE;
+	desc->rsp.add_info_0 = 0; /*Reserved bits */
+	desc->rsp.add_info_1 = 0; /*Reserved bits */
+
+	ref_op[0] = op;
+	struct acc_ptrs *context_ptrs = q->companion_ring_addr + desc_idx;
+	for (i = 1 ; i < desc->req.numCBs; i++)
+		ref_op[i] = context_ptrs->ptr[i].op_addr;
+
+	/* One op was successfully dequeued */
+	(*dequeued_descs)++;
+	*dequeued_ops += desc->req.numCBs;
+	return desc->req.numCBs;
+}
+
+/* Dequeue one LDPC encode operations from ACC200 device in TB mode
+ * That operation may cover multiple descriptors
+ */
+static inline int
+dequeue_enc_one_op_tb(struct acc_queue *q, struct rte_bbdev_enc_op **ref_op,
+		uint16_t *dequeued_ops, uint32_t *aq_dequeued,
+		uint16_t *dequeued_descs)
+{
+	union acc_dma_desc *desc, *last_desc, atom_desc;
+	union acc_dma_rsp_desc rsp;
+	struct rte_bbdev_enc_op *op;
+	uint8_t i = 0;
+	uint16_t current_dequeued_descs = 0, descs_in_tb;
+
+	desc = q->ring_addr + ((q->sw_ring_tail + *dequeued_descs)
+			& q->sw_ring_wrap_mask);
+	atom_desc.atom_hdr = __atomic_load_n((uint64_t *)desc,
+			__ATOMIC_RELAXED);
+
+	/* Check fdone bit */
+	if (!(atom_desc.rsp.val & ACC_FDONE))
+		return -1;
+
+	/* Get number of CBs in dequeued TB */
+	descs_in_tb = desc->req.cbs_in_tb;
+	/* Get last CB */
+	last_desc = q->ring_addr + ((q->sw_ring_tail
+			+ *dequeued_descs + descs_in_tb - 1)
+			& q->sw_ring_wrap_mask);
+	/* Check if last CB in TB is ready to dequeue (and thus
+	 * the whole TB) - checking sdone bit. If not return.
+	 */
+	atom_desc.atom_hdr = __atomic_load_n((uint64_t *)last_desc,
+			__ATOMIC_RELAXED);
+	if (!(atom_desc.rsp.val & ACC_SDONE))
+		return -1;
+
+	/* Dequeue */
+	op = desc->req.op_addr;
+
+	/* Clearing status, it will be set based on response */
+	op->status = 0;
+
+	while (i < descs_in_tb) {
+		desc = q->ring_addr + ((q->sw_ring_tail
+				+ *dequeued_descs)
+				& q->sw_ring_wrap_mask);
+		atom_desc.atom_hdr = __atomic_load_n((uint64_t *)desc,
+				__ATOMIC_RELAXED);
+		rsp.val = atom_desc.rsp.val;
+		rte_bbdev_log_debug("Resp. desc %p: %x", desc,
+				rsp.val);
+
+		op->status |= ((rsp.input_err)
+				? (1 << RTE_BBDEV_DATA_ERROR) : 0);
+		op->status |= ((rsp.dma_err) ? (1 << RTE_BBDEV_DRV_ERROR) : 0);
+		op->status |= ((rsp.fcw_err) ? (1 << RTE_BBDEV_DRV_ERROR) : 0);
+
+		if (desc->req.last_desc_in_batch) {
+			(*aq_dequeued)++;
+			desc->req.last_desc_in_batch = 0;
+		}
+		desc->rsp.val = ACC_DMA_DESC_TYPE;
+		desc->rsp.add_info_0 = 0;
+		desc->rsp.add_info_1 = 0;
+		(*dequeued_descs)++;
+		current_dequeued_descs++;
+		i++;
+	}
+
+	*ref_op = op;
+	(*dequeued_ops)++;
+	return current_dequeued_descs;
+}
+
+/* Dequeue one decode operation from ACC200 device in CB mode */
+static inline int
+dequeue_dec_one_op_cb(struct rte_bbdev_queue_data *q_data,
+		struct acc_queue *q, struct rte_bbdev_dec_op **ref_op,
+		uint16_t dequeued_cbs, uint32_t *aq_dequeued)
+{
+	union acc_dma_desc *desc, atom_desc;
+	union acc_dma_rsp_desc rsp;
+	struct rte_bbdev_dec_op *op;
+
+	desc = q->ring_addr + ((q->sw_ring_tail + dequeued_cbs)
+			& q->sw_ring_wrap_mask);
+	atom_desc.atom_hdr = __atomic_load_n((uint64_t *)desc,
+			__ATOMIC_RELAXED);
+
+	/* Check fdone bit */
+	if (!(atom_desc.rsp.val & ACC_FDONE))
+		return -1;
+
+	rsp.val = atom_desc.rsp.val;
+	rte_bbdev_log_debug("Resp. desc %p: %x\n", desc, rsp.val);
+
+	/* Dequeue */
+	op = desc->req.op_addr;
+
+	/* Clearing status, it will be set based on response */
+	op->status = 0;
+	op->status |= ((rsp.input_err)
+			? (1 << RTE_BBDEV_DATA_ERROR) : 0);
+	op->status |= ((rsp.dma_err) ? (1 << RTE_BBDEV_DRV_ERROR) : 0);
+	op->status |= ((rsp.fcw_err) ? (1 << RTE_BBDEV_DRV_ERROR) : 0);
+	if (op->status != 0) {
+		/* These errors are not expected */
+		q_data->queue_stats.dequeue_err_count++;
+	}
+
+	/* CRC invalid if error exists */
+	if (!op->status)
+		op->status |= rsp.crc_status << RTE_BBDEV_CRC_ERROR;
+	op->turbo_dec.iter_count = (uint8_t) rsp.iter_cnt;
+	/* Check if this is the last desc in batch (Atomic Queue) */
+	if (desc->req.last_desc_in_batch) {
+		(*aq_dequeued)++;
+		desc->req.last_desc_in_batch = 0;
+	}
+	desc->rsp.val = ACC_DMA_DESC_TYPE;
+	desc->rsp.add_info_0 = 0;
+	desc->rsp.add_info_1 = 0;
+	*ref_op = op;
+
+	/* One CB (op) was successfully dequeued */
+	return 1;
+}
+
+/* Dequeue one decode operations from ACC200 device in CB mode */
+static inline int
+dequeue_ldpc_dec_one_op_cb(struct rte_bbdev_queue_data *q_data,
+		struct acc_queue *q, struct rte_bbdev_dec_op **ref_op,
+		uint16_t dequeued_cbs, uint32_t *aq_dequeued)
+{
+	union acc_dma_desc *desc, atom_desc;
+	union acc_dma_rsp_desc rsp;
+	struct rte_bbdev_dec_op *op;
+
+	desc = q->ring_addr + ((q->sw_ring_tail + dequeued_cbs)
+			& q->sw_ring_wrap_mask);
+	atom_desc.atom_hdr = __atomic_load_n((uint64_t *)desc,
+			__ATOMIC_RELAXED);
+
+	/* Check fdone bit */
+	if (!(atom_desc.rsp.val & ACC_FDONE))
+		return -1;
+
+	rsp.val = atom_desc.rsp.val;
+	rte_bbdev_log_debug("Resp. desc %p: %x %x %x\n", desc,
+			rsp.val, desc->rsp.add_info_0,
+			desc->rsp.add_info_1);
+
+	/* Dequeue */
+	op = desc->req.op_addr;
+
+	/* Clearing status, it will be set based on response */
+	op->status = 0;
+	op->status |= rsp.input_err << RTE_BBDEV_DATA_ERROR;
+	op->status |= rsp.dma_err << RTE_BBDEV_DRV_ERROR;
+	op->status |= rsp.fcw_err << RTE_BBDEV_DRV_ERROR;
+	if (op->status != 0)
+		q_data->queue_stats.dequeue_err_count++;
+
+	op->status |= rsp.crc_status << RTE_BBDEV_CRC_ERROR;
+	if (op->ldpc_dec.hard_output.length > 0 && !rsp.synd_ok)
+		op->status |= 1 << RTE_BBDEV_SYNDROME_ERROR;
+
+	if (check_bit(op->ldpc_dec.op_flags,
+			RTE_BBDEV_LDPC_CRC_TYPE_24A_CHECK)  ||
+			check_bit(op->ldpc_dec.op_flags,
+			RTE_BBDEV_LDPC_CRC_TYPE_16_CHECK)) {
+		if (desc->rsp.add_info_1 != 0)
+			op->status |= 1 << RTE_BBDEV_CRC_ERROR;
+	}
+
+	op->ldpc_dec.iter_count = (uint8_t) rsp.iter_cnt;
+
+	/* Check if this is the last desc in batch (Atomic Queue) */
+	if (desc->req.last_desc_in_batch) {
+		(*aq_dequeued)++;
+		desc->req.last_desc_in_batch = 0;
+	}
+
+	desc->rsp.val = ACC_DMA_DESC_TYPE;
+	desc->rsp.add_info_0 = 0;
+	desc->rsp.add_info_1 = 0;
+
+	*ref_op = op;
+
+	/* One CB (op) was successfully dequeued */
+	return 1;
+}
+
+/* Dequeue one decode operations from ACC200 device in TB mode. */
+static inline int
+dequeue_dec_one_op_tb(struct acc_queue *q, struct rte_bbdev_dec_op **ref_op,
+		uint16_t dequeued_cbs, uint32_t *aq_dequeued)
+{
+	union acc_dma_desc *desc, *last_desc, atom_desc;
+	union acc_dma_rsp_desc rsp;
+	struct rte_bbdev_dec_op *op;
+	uint8_t cbs_in_tb = 1, cb_idx = 0;
+	uint32_t tb_crc_check = 0;
+
+	desc = q->ring_addr + ((q->sw_ring_tail + dequeued_cbs)
+			& q->sw_ring_wrap_mask);
+	atom_desc.atom_hdr = __atomic_load_n((uint64_t *)desc,
+			__ATOMIC_RELAXED);
+
+	/* Check fdone bit */
+	if (!(atom_desc.rsp.val & ACC_FDONE))
+		return -1;
+
+	/* Dequeue */
+	op = desc->req.op_addr;
+
+	/* Get number of CBs in dequeued TB */
+	cbs_in_tb = desc->req.cbs_in_tb;
+	/* Get last CB */
+	last_desc = q->ring_addr + ((q->sw_ring_tail
+			+ dequeued_cbs + cbs_in_tb - 1)
+			& q->sw_ring_wrap_mask);
+	/* Check if last CB in TB is ready to dequeue (and thus
+	 * the whole TB) - checking sdone bit. If not return.
+	 */
+	atom_desc.atom_hdr = __atomic_load_n((uint64_t *)last_desc,
+			__ATOMIC_RELAXED);
+	if (!(atom_desc.rsp.val & ACC_SDONE))
+		return -1;
+
+	/* Clearing status, it will be set based on response */
+	op->status = 0;
+
+	/* Read remaining CBs if exists */
+	while (cb_idx < cbs_in_tb) {
+		desc = q->ring_addr + ((q->sw_ring_tail + dequeued_cbs)
+				& q->sw_ring_wrap_mask);
+		atom_desc.atom_hdr = __atomic_load_n((uint64_t *)desc,
+				__ATOMIC_RELAXED);
+		rsp.val = atom_desc.rsp.val;
+		rte_bbdev_log_debug("Resp. desc %p: %x %x %x", desc,
+				rsp.val, desc->rsp.add_info_0,
+				desc->rsp.add_info_1);
+
+		op->status |= ((rsp.input_err)
+				? (1 << RTE_BBDEV_DATA_ERROR) : 0);
+		op->status |= ((rsp.dma_err) ? (1 << RTE_BBDEV_DRV_ERROR) : 0);
+		op->status |= ((rsp.fcw_err) ? (1 << RTE_BBDEV_DRV_ERROR) : 0);
+
+		if (check_bit(op->ldpc_dec.op_flags,
+				RTE_BBDEV_LDPC_CRC_TYPE_24A_CHECK))
+			tb_crc_check ^= desc->rsp.add_info_1;
+
+		/* CRC invalid if error exists */
+		if (!op->status)
+			op->status |= rsp.crc_status << RTE_BBDEV_CRC_ERROR;
+		op->turbo_dec.iter_count = RTE_MAX((uint8_t) rsp.iter_cnt,
+				op->turbo_dec.iter_count);
+
+		/* Check if this is the last desc in batch (Atomic Queue) */
+		if (desc->req.last_desc_in_batch) {
+			(*aq_dequeued)++;
+			desc->req.last_desc_in_batch = 0;
+		}
+		desc->rsp.val = ACC_DMA_DESC_TYPE;
+		desc->rsp.add_info_0 = 0;
+		desc->rsp.add_info_1 = 0;
+		dequeued_cbs++;
+		cb_idx++;
+	}
+
+	if (check_bit(op->ldpc_dec.op_flags,
+			RTE_BBDEV_LDPC_CRC_TYPE_24A_CHECK)) {
+		rte_bbdev_log_debug("TB-CRC Check %x\n", tb_crc_check);
+		if (tb_crc_check > 0)
+			op->status |= 1 << RTE_BBDEV_CRC_ERROR;
+	}
+
+	*ref_op = op;
+
+	return cb_idx;
+}
+
+/* Dequeue LDPC encode operations from ACC200 device. */
+static uint16_t
+acc200_dequeue_ldpc_enc(struct rte_bbdev_queue_data *q_data,
+		struct rte_bbdev_enc_op **ops, uint16_t num)
+{
+	struct acc_queue *q = q_data->queue_private;
+	uint32_t avail = acc_ring_avail_deq(q);
+	uint32_t aq_dequeued = 0;
+	uint16_t i, dequeued_ops = 0, dequeued_descs = 0;
+	int ret;
+	struct rte_bbdev_enc_op *op;
+	if (avail == 0)
+		return 0;
+	op = (q->ring_addr + (q->sw_ring_tail &
+			q->sw_ring_wrap_mask))->req.op_addr;
+#ifdef RTE_LIBRTE_BBDEV_DEBUG
+	if (unlikely(ops == NULL || q == NULL || op == NULL))
+		return 0;
+#endif
+	int cbm = op->ldpc_enc.code_block_mode;
+
+	for (i = 0; i < avail; i++) {
+		if (cbm == RTE_BBDEV_TRANSPORT_BLOCK)
+			ret = dequeue_enc_one_op_tb(q, &ops[dequeued_ops],
+					&dequeued_ops, &aq_dequeued,
+					&dequeued_descs);
+		else
+			ret = dequeue_enc_one_op_cb(q, &ops[dequeued_ops],
+					&dequeued_ops, &aq_dequeued,
+					&dequeued_descs);
+		if (ret < 0)
+			break;
+		if (dequeued_ops >= num)
+			break;
+	}
+
+	q->aq_dequeued += aq_dequeued;
+	q->sw_ring_tail += dequeued_descs;
+
+	/* Update enqueue stats */
+	q_data->queue_stats.dequeued_count += dequeued_ops;
+
+	return dequeued_ops;
+}
+
+/* Dequeue decode operations from ACC200 device. */
+static uint16_t
+acc200_dequeue_ldpc_dec(struct rte_bbdev_queue_data *q_data,
+		struct rte_bbdev_dec_op **ops, uint16_t num)
+{
+	struct acc_queue *q = q_data->queue_private;
+	uint16_t dequeue_num;
+	uint32_t avail = acc_ring_avail_deq(q);
+	uint32_t aq_dequeued = 0;
+	uint16_t i;
+	uint16_t dequeued_cbs = 0;
+	struct rte_bbdev_dec_op *op;
+	int ret;
+
+#ifdef RTE_LIBRTE_BBDEV_DEBUG
+	if (unlikely(ops == 0 && q == NULL))
+		return 0;
+#endif
+
+	dequeue_num = RTE_MIN(avail, num);
+
+	for (i = 0; i < dequeue_num; ++i) {
+		op = (q->ring_addr + ((q->sw_ring_tail + dequeued_cbs)
+			& q->sw_ring_wrap_mask))->req.op_addr;
+		if (op->ldpc_dec.code_block_mode == RTE_BBDEV_TRANSPORT_BLOCK)
+			ret = dequeue_dec_one_op_tb(q, &ops[i], dequeued_cbs,
+					&aq_dequeued);
+		else
+			ret = dequeue_ldpc_dec_one_op_cb(
+					q_data, q, &ops[i], dequeued_cbs,
+					&aq_dequeued);
+
+		if (ret <= 0)
+			break;
+		dequeued_cbs += ret;
+	}
+
+	q->aq_dequeued += aq_dequeued;
+	q->sw_ring_tail += dequeued_cbs;
+
+	/* Update enqueue stats */
+	q_data->queue_stats.dequeued_count += i;
+
+	return i;
+}
+
 /* Initialization Function */
 static void
 acc200_bbdev_init(struct rte_bbdev *dev, struct rte_pci_driver *drv)
@@ -677,6 +2191,10 @@
 	struct rte_pci_device *pci_dev = RTE_DEV_TO_PCI(dev->device);
 
 	dev->dev_ops = &acc200_bbdev_ops;
+	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;
 
 	((struct acc_device *) dev->data->dev_private)->pf_device =
 			!strcmp(drv->driver.name,
Signature · 1 line
1.8.3.1
#11 lore raw

PATCH v3 7/13 baseband/acc200: add LTE processing functions

In reply to Nic Chautru

From: Nicolas Chautru <[email protected]>

Add functions and capability for 4G FEC

---
 drivers/baseband/acc200/rte_acc200_pmd.c | 894 ++++++++++++++++++++++++++++++-
 1 file changed, 874 insertions(+), 20 deletions(-)
drivers/baseband/acc200/rte_acc200_pmd.c +874 -20
index def5ed7..9c3388f 100644
@@ -641,6 +641,46 @@
 	int i;
 	static const struct rte_bbdev_op_cap bbdev_capabilities[] = {
 		{
+			.type = RTE_BBDEV_OP_TURBO_DEC,
+			.cap.turbo_dec = {
+				.capability_flags =
+					RTE_BBDEV_TURBO_SUBBLOCK_DEINTERLEAVE |
+					RTE_BBDEV_TURBO_CRC_TYPE_24B |
+					RTE_BBDEV_TURBO_EQUALIZER |
+					RTE_BBDEV_TURBO_SOFT_OUT_SATURATE |
+					RTE_BBDEV_TURBO_HALF_ITERATION_EVEN |
+					RTE_BBDEV_TURBO_CONTINUE_CRC_MATCH |
+					RTE_BBDEV_TURBO_SOFT_OUTPUT |
+					RTE_BBDEV_TURBO_EARLY_TERMINATION |
+					RTE_BBDEV_TURBO_NEG_LLR_1_BIT_IN |
+					RTE_BBDEV_TURBO_NEG_LLR_1_BIT_SOFT_OUT |
+					RTE_BBDEV_TURBO_MAP_DEC |
+					RTE_BBDEV_TURBO_DEC_TB_CRC_24B_KEEP |
+					RTE_BBDEV_TURBO_DEC_SCATTER_GATHER,
+				.max_llr_modulus = INT8_MAX,
+				.num_buffers_src =
+						RTE_BBDEV_TURBO_MAX_CODE_BLOCKS,
+				.num_buffers_hard_out =
+						RTE_BBDEV_TURBO_MAX_CODE_BLOCKS,
+				.num_buffers_soft_out =
+						RTE_BBDEV_TURBO_MAX_CODE_BLOCKS,
+			}
+		},
+		{
+			.type = RTE_BBDEV_OP_TURBO_ENC,
+			.cap.turbo_enc = {
+				.capability_flags =
+					RTE_BBDEV_TURBO_CRC_24B_ATTACH |
+					RTE_BBDEV_TURBO_RV_INDEX_BYPASS |
+					RTE_BBDEV_TURBO_RATE_MATCH |
+					RTE_BBDEV_TURBO_ENC_SCATTER_GATHER,
+				.num_buffers_src =
+						RTE_BBDEV_TURBO_MAX_CODE_BLOCKS,
+				.num_buffers_dst =
+						RTE_BBDEV_TURBO_MAX_CODE_BLOCKS,
+			}
+		},
+		{
 			.type   = RTE_BBDEV_OP_LDPC_ENC,
 			.cap.ldpc_enc = {
 				.capability_flags =
@@ -691,15 +731,17 @@
 
 	/* Exposed number of queues */
 	dev_info->num_queues[RTE_BBDEV_OP_NONE] = 0;
-	dev_info->num_queues[RTE_BBDEV_OP_TURBO_DEC] = 0;
-	dev_info->num_queues[RTE_BBDEV_OP_TURBO_ENC] = 0;
+	dev_info->num_queues[RTE_BBDEV_OP_TURBO_DEC] = d->acc_conf.q_ul_4g.num_aqs_per_groups *
+			d->acc_conf.q_ul_4g.num_qgroups;
+	dev_info->num_queues[RTE_BBDEV_OP_TURBO_ENC] = d->acc_conf.q_dl_4g.num_aqs_per_groups *
+			d->acc_conf.q_dl_4g.num_qgroups;
 	dev_info->num_queues[RTE_BBDEV_OP_LDPC_DEC] = d->acc_conf.q_ul_5g.num_aqs_per_groups *
 			d->acc_conf.q_ul_5g.num_qgroups;
 	dev_info->num_queues[RTE_BBDEV_OP_LDPC_ENC] = d->acc_conf.q_dl_5g.num_aqs_per_groups *
 			d->acc_conf.q_dl_5g.num_qgroups;
 	dev_info->num_queues[RTE_BBDEV_OP_FFT] = 0;
-	dev_info->queue_priority[RTE_BBDEV_OP_TURBO_DEC] = 0;
-	dev_info->queue_priority[RTE_BBDEV_OP_TURBO_ENC] = 0;
+	dev_info->queue_priority[RTE_BBDEV_OP_TURBO_DEC] = d->acc_conf.q_ul_4g.num_qgroups;
+	dev_info->queue_priority[RTE_BBDEV_OP_TURBO_ENC] = d->acc_conf.q_dl_4g.num_qgroups;
 	dev_info->queue_priority[RTE_BBDEV_OP_LDPC_DEC] = d->acc_conf.q_ul_5g.num_qgroups;
 	dev_info->queue_priority[RTE_BBDEV_OP_LDPC_ENC] = d->acc_conf.q_dl_5g.num_qgroups;
 	dev_info->queue_priority[RTE_BBDEV_OP_FFT] = 0;
@@ -744,6 +786,70 @@
 	{.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)
+{
+	fcw->fcw_ver = 1;
+	fcw->num_maps = ACC_FCW_TD_AUTOMAP;
+	fcw->bypass_sb_deint = !check_bit(op->turbo_dec.op_flags,
+			RTE_BBDEV_TURBO_SUBBLOCK_DEINTERLEAVE);
+	if (op->turbo_dec.code_block_mode == RTE_BBDEV_TRANSPORT_BLOCK) {
+		/* FIXME for TB block */
+		fcw->k_pos = op->turbo_dec.tb_params.k_pos;
+		fcw->k_neg = op->turbo_dec.tb_params.k_neg;
+	} else {
+		fcw->k_pos = op->turbo_dec.cb_params.k;
+		fcw->k_neg = op->turbo_dec.cb_params.k;
+	}
+	fcw->c = 1;
+	fcw->c_neg = 1;
+	if (check_bit(op->turbo_dec.op_flags, RTE_BBDEV_TURBO_SOFT_OUTPUT)) {
+		fcw->soft_output_en = 1;
+		fcw->sw_soft_out_dis = 0;
+		fcw->sw_et_cont = check_bit(op->turbo_dec.op_flags,
+				RTE_BBDEV_TURBO_CONTINUE_CRC_MATCH);
+		fcw->sw_soft_out_saturation = check_bit(op->turbo_dec.op_flags,
+				RTE_BBDEV_TURBO_SOFT_OUT_SATURATE);
+		if (check_bit(op->turbo_dec.op_flags,
+				RTE_BBDEV_TURBO_EQUALIZER)) {
+			fcw->bypass_teq = 0;
+			fcw->ea = op->turbo_dec.cb_params.e;
+			fcw->eb = op->turbo_dec.cb_params.e;
+			if (op->turbo_dec.rv_index == 0)
+				fcw->k0_start_col = ACC_FCW_TD_RVIDX_0;
+			else if (op->turbo_dec.rv_index == 1)
+				fcw->k0_start_col = ACC_FCW_TD_RVIDX_1;
+			else if (op->turbo_dec.rv_index == 2)
+				fcw->k0_start_col = ACC_FCW_TD_RVIDX_2;
+			else
+				fcw->k0_start_col = ACC_FCW_TD_RVIDX_3;
+		} else {
+			fcw->bypass_teq = 1;
+			fcw->eb = 64; /* avoid undefined value */
+		}
+	} else {
+		fcw->soft_output_en = 0;
+		fcw->sw_soft_out_dis = 1;
+		fcw->bypass_teq = 0;
+	}
+
+	fcw->code_block_mode = 1; /* FIXME */
+	fcw->turbo_crc_type = check_bit(op->turbo_dec.op_flags,
+			RTE_BBDEV_TURBO_CRC_TYPE_24B);
+
+	fcw->ext_td_cold_reg_en = 1;
+	fcw->raw_decoder_input_on = 0;
+	fcw->max_iter = RTE_MAX((uint8_t) op->turbo_dec.iter_max, 2);
+	fcw->min_iter = 2;
+	fcw->half_iter_on = !check_bit(op->turbo_dec.op_flags,
+			RTE_BBDEV_TURBO_HALF_ITERATION_EVEN);
+
+	fcw->early_stop_en = check_bit(op->turbo_dec.op_flags,
+			RTE_BBDEV_TURBO_EARLY_TERMINATION) & !fcw->soft_output_en;
+	fcw->ext_scale = 0xF;
+}
+
 /* Fill in a frame control word for LDPC decoding. */
 static inline void
 acc200_fcw_ld_fill(struct rte_bbdev_dec_op *op, struct acc_fcw_ld *fcw,
@@ -870,6 +976,89 @@
 }
 
 static inline int
+acc200_dma_desc_te_fill(struct rte_bbdev_enc_op *op,
+		struct acc_dma_req_desc *desc, struct rte_mbuf **input,
+		struct rte_mbuf *output, uint32_t *in_offset,
+		uint32_t *out_offset, uint32_t *out_length,
+		uint32_t *mbuf_total_left, uint32_t *seg_total_left, uint8_t r)
+{
+	int next_triplet = 1; /* FCW already done */
+	uint32_t e, ea, eb, length;
+	uint16_t k, k_neg, k_pos;
+	uint8_t cab, c_neg;
+
+	desc->word0 = ACC_DMA_DESC_TYPE;
+	desc->word1 = 0; /**< Timestamp could be disabled */
+	desc->word2 = 0;
+	desc->word3 = 0;
+	desc->numCBs = 1;
+
+	if (op->turbo_enc.code_block_mode == RTE_BBDEV_TRANSPORT_BLOCK) {
+		ea = op->turbo_enc.tb_params.ea;
+		eb = op->turbo_enc.tb_params.eb;
+		cab = op->turbo_enc.tb_params.cab;
+		k_neg = op->turbo_enc.tb_params.k_neg;
+		k_pos = op->turbo_enc.tb_params.k_pos;
+		c_neg = op->turbo_enc.tb_params.c_neg;
+		e = (r < cab) ? ea : eb;
+		k = (r < c_neg) ? k_neg : k_pos;
+	} else {
+		e = op->turbo_enc.cb_params.e;
+		k = op->turbo_enc.cb_params.k;
+	}
+
+	if (check_bit(op->turbo_enc.op_flags, RTE_BBDEV_TURBO_CRC_24B_ATTACH))
+		length = (k - 24) >> 3;
+	else
+		length = k >> 3;
+
+	if (unlikely((*mbuf_total_left == 0) || (*mbuf_total_left < length))) {
+		rte_bbdev_log(ERR,
+				"Mismatch between mbuf length and included CB sizes: mbuf len %u, cb len %u",
+				*mbuf_total_left, length);
+		return -1;
+	}
+
+	next_triplet = acc_dma_fill_blk_type_in(desc, input, in_offset,
+			length, seg_total_left, next_triplet,
+			check_bit(op->turbo_enc.op_flags,
+			RTE_BBDEV_TURBO_ENC_SCATTER_GATHER));
+	if (unlikely(next_triplet < 0)) {
+		rte_bbdev_log(ERR,
+				"Mismatch between data to process and mbuf data length in bbdev_op: %p",
+				op);
+		return -1;
+	}
+	desc->data_ptrs[next_triplet - 1].last = 1;
+	desc->m2dlen = next_triplet;
+	*mbuf_total_left -= length;
+
+	/* Set output length */
+	if (check_bit(op->turbo_enc.op_flags, RTE_BBDEV_TURBO_RATE_MATCH))
+		/* Integer round up division by 8 */
+		*out_length = (e + 7) >> 3;
+	else
+		*out_length = (k >> 3) * 3 + 2;
+
+	next_triplet = acc_dma_fill_blk_type(desc, output, *out_offset,
+			*out_length, next_triplet, ACC_DMA_BLKID_OUT_ENC);
+	if (unlikely(next_triplet < 0)) {
+		rte_bbdev_log(ERR,
+				"Mismatch between data to process and mbuf data length in bbdev_op: %p",
+				op);
+		return -1;
+	}
+	op->turbo_enc.output.length += *out_length;
+	*out_offset += *out_length;
+	desc->data_ptrs[next_triplet - 1].last = 1;
+	desc->d2mlen = next_triplet - desc->m2dlen;
+
+	desc->op_addr = op;
+
+	return 0;
+}
+
+static inline int
 acc200_dma_desc_le_fill(struct rte_bbdev_enc_op *op,
 		struct acc_dma_req_desc *desc, struct rte_mbuf **input,
 		struct rte_mbuf *output, uint32_t *in_offset,
@@ -929,6 +1118,122 @@
 }
 
 static inline int
+acc200_dma_desc_td_fill(struct rte_bbdev_dec_op *op,
+		struct acc_dma_req_desc *desc, struct rte_mbuf **input,
+		struct rte_mbuf *h_output, struct rte_mbuf *s_output,
+		uint32_t *in_offset, uint32_t *h_out_offset,
+		uint32_t *s_out_offset, uint32_t *h_out_length,
+		uint32_t *s_out_length, uint32_t *mbuf_total_left,
+		uint32_t *seg_total_left, uint8_t r)
+{
+	int next_triplet = 1; /* FCW already done */
+	uint16_t k;
+	uint16_t crc24_overlap = 0;
+	uint32_t e, kw;
+
+	desc->word0 = ACC_DMA_DESC_TYPE;
+	desc->word1 = 0; /**< Timestamp could be disabled */
+	desc->word2 = 0;
+	desc->word3 = 0;
+	desc->numCBs = 1;
+
+	if (op->turbo_dec.code_block_mode == RTE_BBDEV_TRANSPORT_BLOCK) {
+		k = (r < op->turbo_dec.tb_params.c_neg)
+			? op->turbo_dec.tb_params.k_neg
+			: op->turbo_dec.tb_params.k_pos;
+		e = (r < op->turbo_dec.tb_params.cab)
+			? op->turbo_dec.tb_params.ea
+			: op->turbo_dec.tb_params.eb;
+	} else {
+		k = op->turbo_dec.cb_params.k;
+		e = op->turbo_dec.cb_params.e;
+	}
+
+	if ((op->turbo_dec.code_block_mode == RTE_BBDEV_TRANSPORT_BLOCK)
+		&& !check_bit(op->turbo_dec.op_flags,
+		RTE_BBDEV_TURBO_DEC_TB_CRC_24B_KEEP))
+		crc24_overlap = 24;
+
+	/* Calculates circular buffer size.
+	 * According to 3gpp 36.212 section 5.1.4.2
+	 *   Kw = 3 * Kpi,
+	 * where:
+	 *   Kpi = nCol * nRow
+	 * where nCol is 32 and nRow can be calculated from:
+	 *   D =< nCol * nRow
+	 * where D is the size of each output from turbo encoder block (k + 4).
+	 */
+	kw = RTE_ALIGN_CEIL(k + 4, 32) * 3;
+
+	if (unlikely((*mbuf_total_left == 0) || (*mbuf_total_left < kw))) {
+		rte_bbdev_log(ERR,
+				"Mismatch between mbuf length and included CB sizes: mbuf len %u, cb len %u",
+				*mbuf_total_left, kw);
+		return -1;
+	}
+
+	next_triplet = acc_dma_fill_blk_type_in(desc, input, in_offset, kw,
+			seg_total_left, next_triplet,
+			check_bit(op->turbo_dec.op_flags,
+			RTE_BBDEV_TURBO_DEC_SCATTER_GATHER));
+	if (unlikely(next_triplet < 0)) {
+		rte_bbdev_log(ERR,
+				"Mismatch between data to process and mbuf data length in bbdev_op: %p",
+				op);
+		return -1;
+	}
+	desc->data_ptrs[next_triplet - 1].last = 1;
+	desc->m2dlen = next_triplet;
+	*mbuf_total_left -= kw;
+	*h_out_length = ((k - crc24_overlap) >> 3);
+	next_triplet = acc_dma_fill_blk_type(
+			desc, h_output, *h_out_offset,
+			*h_out_length, next_triplet, ACC_DMA_BLKID_OUT_HARD);
+	if (unlikely(next_triplet < 0)) {
+		rte_bbdev_log(ERR,
+				"Mismatch between data to process and mbuf data length in bbdev_op: %p",
+				op);
+		return -1;
+	}
+
+	op->turbo_dec.hard_output.length += *h_out_length;
+	*h_out_offset += *h_out_length;
+
+	/* Soft output */
+	if (check_bit(op->turbo_dec.op_flags, RTE_BBDEV_TURBO_SOFT_OUTPUT)) {
+		if (op->turbo_dec.soft_output.data == 0) {
+			rte_bbdev_log(ERR, "Soft output is not defined");
+			return -1;
+		}
+		if (check_bit(op->turbo_dec.op_flags,
+				RTE_BBDEV_TURBO_EQUALIZER))
+			*s_out_length = e;
+		else
+			*s_out_length = (k * 3) + 12;
+
+		next_triplet = acc_dma_fill_blk_type(desc, s_output,
+				*s_out_offset, *s_out_length, next_triplet,
+				ACC_DMA_BLKID_OUT_SOFT);
+		if (unlikely(next_triplet < 0)) {
+			rte_bbdev_log(ERR,
+					"Mismatch between data to process and mbuf data length in bbdev_op: %p",
+					op);
+			return -1;
+		}
+
+		op->turbo_dec.soft_output.length += *s_out_length;
+		*s_out_offset += *s_out_length;
+	}
+
+	desc->data_ptrs[next_triplet - 1].last = 1;
+	desc->d2mlen = next_triplet - desc->m2dlen;
+
+	desc->op_addr = op;
+
+	return 0;
+}
+
+static inline int
 acc200_dma_desc_ld_fill(struct rte_bbdev_dec_op *op,
 		struct acc_dma_req_desc *desc,
 		struct rte_mbuf **input, struct rte_mbuf *h_output,
@@ -1100,6 +1405,51 @@
 	desc->op_addr = op;
 }
 
+/* Enqueue one encode operations for ACC200 device in CB mode */
+static inline int
+enqueue_enc_one_op_cb(struct acc_queue *q, struct rte_bbdev_enc_op *op,
+		uint16_t total_enqueued_cbs)
+{
+	union acc_dma_desc *desc = NULL;
+	int ret;
+	uint32_t in_offset, out_offset, out_length, mbuf_total_left,
+		seg_total_left;
+	struct rte_mbuf *input, *output_head, *output;
+
+	uint16_t desc_idx = ((q->sw_ring_head + total_enqueued_cbs)
+			& q->sw_ring_wrap_mask);
+	desc = q->ring_addr + desc_idx;
+	acc_fcw_te_fill(op, &desc->req.fcw_te);
+
+	input = op->turbo_enc.input.data;
+	output_head = output = op->turbo_enc.output.data;
+	in_offset = op->turbo_enc.input.offset;
+	out_offset = op->turbo_enc.output.offset;
+	out_length = 0;
+	mbuf_total_left = op->turbo_enc.input.length;
+	seg_total_left = rte_pktmbuf_data_len(op->turbo_enc.input.data)
+			- in_offset;
+
+	ret = acc200_dma_desc_te_fill(op, &desc->req, &input, output,
+			&in_offset, &out_offset, &out_length, &mbuf_total_left,
+			&seg_total_left, 0);
+
+	if (unlikely(ret < 0))
+		return ret;
+
+	mbuf_append(output_head, output, out_length);
+
+#ifdef RTE_LIBRTE_BBDEV_DEBUG
+	rte_memdump(stderr, "FCW", &desc->req.fcw_te,
+			sizeof(desc->req.fcw_te) - 8);
+	rte_memdump(stderr, "Req Desc.", desc, sizeof(*desc));
+	if (check_mbuf_total_left(mbuf_total_left) != 0)
+		return -EINVAL;
+#endif
+	/* One CB (one op) was successfully prepared to enqueue */
+	return 1;
+}
+
 /* Enqueue one encode operations for ACC200 device in CB mode
  * multiplexed on the same descriptor
  */
@@ -1262,6 +1612,84 @@
 	return 1;
 }
 
+
+/* Enqueue one encode operations for ACC200 device in TB mode. */
+static inline int
+enqueue_enc_one_op_tb(struct acc_queue *q, struct rte_bbdev_enc_op *op,
+		uint16_t total_enqueued_cbs, uint8_t cbs_in_tb)
+{
+	union acc_dma_desc *desc = NULL;
+	int ret;
+	uint8_t r, c;
+	uint32_t in_offset, out_offset, out_length, mbuf_total_left,
+		seg_total_left;
+	struct rte_mbuf *input, *output_head, *output;
+	uint16_t current_enqueued_cbs = 0;
+
+	uint16_t desc_idx = ((q->sw_ring_head + total_enqueued_cbs)
+			& q->sw_ring_wrap_mask);
+	desc = q->ring_addr + desc_idx;
+	uint64_t fcw_offset = (desc_idx << 8) + ACC_DESC_FCW_OFFSET;
+	acc_fcw_te_fill(op, &desc->req.fcw_te);
+
+	input = op->turbo_enc.input.data;
+	output_head = output = op->turbo_enc.output.data;
+	in_offset = op->turbo_enc.input.offset;
+	out_offset = op->turbo_enc.output.offset;
+	out_length = 0;
+	mbuf_total_left = op->turbo_enc.input.length;
+
+	c = op->turbo_enc.tb_params.c;
+	r = op->turbo_enc.tb_params.r;
+
+	while (mbuf_total_left > 0 && r < c) {
+		seg_total_left = rte_pktmbuf_data_len(input) - in_offset;
+		/* Set up DMA descriptor */
+		desc = q->ring_addr + ((q->sw_ring_head + total_enqueued_cbs)
+				& q->sw_ring_wrap_mask);
+		desc->req.data_ptrs[0].address = q->ring_addr_iova + fcw_offset;
+		desc->req.data_ptrs[0].blen = ACC_FCW_TE_BLEN;
+
+		ret = acc200_dma_desc_te_fill(op, &desc->req, &input, output,
+				&in_offset, &out_offset, &out_length,
+				&mbuf_total_left, &seg_total_left, r);
+		if (unlikely(ret < 0))
+			return ret;
+		mbuf_append(output_head, output, out_length);
+
+		/* Set total number of CBs in TB */
+		desc->req.cbs_in_tb = cbs_in_tb;
+#ifdef RTE_LIBRTE_BBDEV_DEBUG
+		rte_memdump(stderr, "FCW", &desc->req.fcw_te,
+				sizeof(desc->req.fcw_te) - 8);
+		rte_memdump(stderr, "Req Desc.", desc, sizeof(*desc));
+#endif
+
+		if (seg_total_left == 0) {
+			/* Go to the next mbuf */
+			input = input->next;
+			in_offset = 0;
+			output = output->next;
+			out_offset = 0;
+		}
+
+		total_enqueued_cbs++;
+		current_enqueued_cbs++;
+		r++;
+	}
+
+#ifdef RTE_LIBRTE_BBDEV_DEBUG
+	if (check_mbuf_total_left(mbuf_total_left) != 0)
+		return -EINVAL;
+#endif
+
+	/* Set SDone on last CB descriptor for TB mode. */
+	desc->req.sdone_enable = 1;
+	desc->req.irq_enable = q->irq_enable;
+
+	return current_enqueued_cbs;
+}
+
 /* Enqueue one encode operations for ACC200 device in TB mode.
  * returns the number of descs used
  */
@@ -1328,6 +1756,69 @@
 
 /** Enqueue one decode operations for ACC200 device in CB mode */
 static inline int
+enqueue_dec_one_op_cb(struct acc_queue *q, struct rte_bbdev_dec_op *op,
+		uint16_t total_enqueued_cbs)
+{
+	union acc_dma_desc *desc = NULL;
+	int ret;
+	uint32_t in_offset, h_out_offset, s_out_offset, s_out_length,
+		h_out_length, mbuf_total_left, seg_total_left;
+	struct rte_mbuf *input, *h_output_head, *h_output,
+		*s_output_head, *s_output;
+
+	uint16_t desc_idx = ((q->sw_ring_head + total_enqueued_cbs)
+			& q->sw_ring_wrap_mask);
+	desc = q->ring_addr + desc_idx;
+	acc200_fcw_td_fill(op, &desc->req.fcw_td);
+
+	input = op->turbo_dec.input.data;
+	h_output_head = h_output = op->turbo_dec.hard_output.data;
+	s_output_head = s_output = op->turbo_dec.soft_output.data;
+	in_offset = op->turbo_dec.input.offset;
+	h_out_offset = op->turbo_dec.hard_output.offset;
+	s_out_offset = op->turbo_dec.soft_output.offset;
+	h_out_length = s_out_length = 0;
+	mbuf_total_left = op->turbo_dec.input.length;
+	seg_total_left = rte_pktmbuf_data_len(input) - in_offset;
+
+#ifdef RTE_LIBRTE_BBDEV_DEBUG
+	if (unlikely(input == NULL)) {
+		rte_bbdev_log(ERR, "Invalid mbuf pointer");
+		return -EFAULT;
+	}
+#endif
+
+	/* Set up DMA descriptor */
+	desc = q->ring_addr + ((q->sw_ring_head + total_enqueued_cbs)
+			& q->sw_ring_wrap_mask);
+
+	ret = acc200_dma_desc_td_fill(op, &desc->req, &input, h_output,
+			s_output, &in_offset, &h_out_offset, &s_out_offset,
+			&h_out_length, &s_out_length, &mbuf_total_left,
+			&seg_total_left, 0);
+
+	if (unlikely(ret < 0))
+		return ret;
+
+	/* Hard output */
+	mbuf_append(h_output_head, h_output, h_out_length);
+
+	/* Soft output */
+	if (check_bit(op->turbo_dec.op_flags, RTE_BBDEV_TURBO_SOFT_OUTPUT))
+		mbuf_append(s_output_head, s_output, s_out_length);
+
+#ifdef RTE_LIBRTE_BBDEV_DEBUG
+	rte_memdump(stderr, "FCW", &desc->req.fcw_td,
+			sizeof(desc->req.fcw_td));
+	rte_memdump(stderr, "Req Desc.", desc, sizeof(*desc));
+#endif
+
+	/* One CB (one op) was successfully prepared to enqueue */
+	return 1;
+}
+
+/** Enqueue one decode operations for ACC200 device in CB mode */
+static inline int
 enqueue_ldpc_dec_one_op_cb(struct acc_queue *q, struct rte_bbdev_dec_op *op,
 		uint16_t total_enqueued_cbs, bool same_op)
 {
@@ -1525,10 +2016,147 @@
 	return current_enqueued_cbs;
 }
 
-/** Enqueue encode operations for ACC200 device in CB mode. */
-static inline uint16_t
-acc200_enqueue_ldpc_enc_cb(struct rte_bbdev_queue_data *q_data,
-		struct rte_bbdev_enc_op **ops, uint16_t num)
+/* Enqueue one decode operations for ACC200 device in TB mode */
+static inline int
+enqueue_dec_one_op_tb(struct acc_queue *q, struct rte_bbdev_dec_op *op,
+		uint16_t total_enqueued_cbs, uint8_t cbs_in_tb)
+{
+	union acc_dma_desc *desc = NULL;
+	int ret;
+	uint8_t r, c;
+	uint32_t in_offset, h_out_offset, s_out_offset, s_out_length,
+		h_out_length, mbuf_total_left, seg_total_left;
+	struct rte_mbuf *input, *h_output_head, *h_output,
+		*s_output_head, *s_output;
+	uint16_t current_enqueued_cbs = 0;
+
+	uint16_t desc_idx = ((q->sw_ring_head + total_enqueued_cbs)
+			& q->sw_ring_wrap_mask);
+	desc = q->ring_addr + desc_idx;
+	uint64_t fcw_offset = (desc_idx << 8) + ACC_DESC_FCW_OFFSET;
+	acc200_fcw_td_fill(op, &desc->req.fcw_td);
+
+	input = op->turbo_dec.input.data;
+	h_output_head = h_output = op->turbo_dec.hard_output.data;
+	s_output_head = s_output = op->turbo_dec.soft_output.data;
+	in_offset = op->turbo_dec.input.offset;
+	h_out_offset = op->turbo_dec.hard_output.offset;
+	s_out_offset = op->turbo_dec.soft_output.offset;
+	h_out_length = s_out_length = 0;
+	mbuf_total_left = op->turbo_dec.input.length;
+	c = op->turbo_dec.tb_params.c;
+	r = op->turbo_dec.tb_params.r;
+
+	while (mbuf_total_left > 0 && r < c) {
+
+		seg_total_left = rte_pktmbuf_data_len(input) - in_offset;
+
+		/* Set up DMA descriptor */
+		desc = q->ring_addr + ((q->sw_ring_head + total_enqueued_cbs)
+				& q->sw_ring_wrap_mask);
+		desc->req.data_ptrs[0].address = q->ring_addr_iova + fcw_offset;
+		desc->req.data_ptrs[0].blen = ACC_FCW_TD_BLEN;
+		ret = acc200_dma_desc_td_fill(op, &desc->req, &input,
+				h_output, s_output, &in_offset, &h_out_offset,
+				&s_out_offset, &h_out_length, &s_out_length,
+				&mbuf_total_left, &seg_total_left, r);
+
+		if (unlikely(ret < 0))
+			return ret;
+
+		/* Hard output */
+		mbuf_append(h_output_head, h_output, h_out_length);
+
+		/* Soft output */
+		if (check_bit(op->turbo_dec.op_flags,
+				RTE_BBDEV_TURBO_SOFT_OUTPUT))
+			mbuf_append(s_output_head, s_output, s_out_length);
+
+		/* Set total number of CBs in TB */
+		desc->req.cbs_in_tb = cbs_in_tb;
+#ifdef RTE_LIBRTE_BBDEV_DEBUG
+		rte_memdump(stderr, "FCW", &desc->req.fcw_td,
+				sizeof(desc->req.fcw_td) - 8);
+		rte_memdump(stderr, "Req Desc.", desc, sizeof(*desc));
+#endif
+
+		if (seg_total_left == 0) {
+			/* Go to the next mbuf */
+			input = input->next;
+			in_offset = 0;
+			h_output = h_output->next;
+			h_out_offset = 0;
+
+			if (check_bit(op->turbo_dec.op_flags,
+					RTE_BBDEV_TURBO_SOFT_OUTPUT)) {
+				s_output = s_output->next;
+				s_out_offset = 0;
+			}
+		}
+
+		total_enqueued_cbs++;
+		current_enqueued_cbs++;
+		r++;
+	}
+
+#ifdef RTE_LIBRTE_BBDEV_DEBUG
+	if (check_mbuf_total_left(mbuf_total_left) != 0)
+		return -EINVAL;
+#endif
+	/* Set SDone on last CB descriptor for TB mode */
+	desc->req.sdone_enable = 1;
+	desc->req.irq_enable = q->irq_enable;
+
+	return current_enqueued_cbs;
+}
+
+/* Enqueue encode operations for ACC200 device in CB mode. */
+static uint16_t
+acc200_enqueue_enc_cb(struct rte_bbdev_queue_data *q_data,
+		struct rte_bbdev_enc_op **ops, uint16_t num)
+{
+	struct acc_queue *q = q_data->queue_private;
+	int32_t avail = acc_ring_avail_enq(q);
+	uint16_t i;
+	union acc_dma_desc *desc;
+	int ret;
+
+	for (i = 0; i < num; ++i) {
+		/* Check if there are available space for further processing */
+		if (unlikely(avail - 1 < 0)) {
+			acc_enqueue_ring_full(q_data);
+			break;
+		}
+		avail -= 1;
+
+		ret = enqueue_enc_one_op_cb(q, ops[i], i);
+		if (ret < 0) {
+			acc_enqueue_invalid(q_data);
+			break;
+		}
+	}
+
+	if (unlikely(i == 0))
+		return 0; /* Nothing to enqueue */
+
+	/* Set SDone in last CB in enqueued ops for CB mode*/
+	desc = q->ring_addr + ((q->sw_ring_head + i - 1)
+			& q->sw_ring_wrap_mask);
+	desc->req.sdone_enable = 1;
+	desc->req.irq_enable = q->irq_enable;
+
+	acc_dma_enqueue(q, i, &q_data->queue_stats);
+
+	/* Update stats */
+	q_data->queue_stats.enqueued_count += i;
+	q_data->queue_stats.enqueue_err_count += num - i;
+	return i;
+}
+
+/** Enqueue encode operations for ACC200 device in CB mode. */
+static inline uint16_t
+acc200_enqueue_ldpc_enc_cb(struct rte_bbdev_queue_data *q_data,
+		struct rte_bbdev_enc_op **ops, uint16_t num)
 {
 	struct acc_queue *q = q_data->queue_private;
 	int32_t avail = acc_ring_avail_enq(q);
@@ -1583,6 +2211,45 @@
 	return i;
 }
 
+/* Enqueue encode operations for ACC200 device in TB mode. */
+static uint16_t
+acc200_enqueue_enc_tb(struct rte_bbdev_queue_data *q_data,
+		struct rte_bbdev_enc_op **ops, uint16_t num)
+{
+	struct acc_queue *q = q_data->queue_private;
+	int32_t avail = acc_ring_avail_enq(q);
+	uint16_t i, enqueued_cbs = 0;
+	uint8_t cbs_in_tb;
+	int ret;
+
+	for (i = 0; i < num; ++i) {
+		cbs_in_tb = get_num_cbs_in_tb_enc(&ops[i]->turbo_enc);
+		/* Check if there are available space for further processing */
+		if (unlikely((avail - cbs_in_tb < 0) || (cbs_in_tb == 0))) {
+			acc_enqueue_ring_full(q_data);
+			break;
+		}
+		avail -= cbs_in_tb;
+
+		ret = enqueue_enc_one_op_tb(q, ops[i], enqueued_cbs, cbs_in_tb);
+		if (ret <= 0) {
+			acc_enqueue_invalid(q_data);
+			break;
+		}
+		enqueued_cbs += ret;
+	}
+	if (unlikely(enqueued_cbs == 0))
+		return 0; /* Nothing to enqueue */
+
+	acc_dma_enqueue(q, enqueued_cbs, &q_data->queue_stats);
+
+	/* Update stats */
+	q_data->queue_stats.enqueued_count += i;
+	q_data->queue_stats.enqueue_err_count += num - i;
+
+	return i;
+}
+
 /* Enqueue LDPC encode operations for ACC200 device in TB mode. */
 static uint16_t
 acc200_enqueue_ldpc_enc_tb(struct rte_bbdev_queue_data *q_data,
@@ -1623,18 +2290,18 @@
 	return i;
 }
 
-/* Check room in AQ for the enqueues batches into Qmgr */
-static int32_t
-acc200_aq_avail(struct rte_bbdev_queue_data *q_data, uint16_t num_ops)
+/* Enqueue encode operations for ACC200 device. */
+static uint16_t
+acc200_enqueue_enc(struct rte_bbdev_queue_data *q_data,
+		struct rte_bbdev_enc_op **ops, uint16_t num)
 {
-	struct acc_queue *q = q_data->queue_private;
-	int32_t aq_avail = q->aq_depth -
-			((q->aq_enqueued - q->aq_dequeued +
-			ACC_MAX_QUEUE_DEPTH) % ACC_MAX_QUEUE_DEPTH)
-			- (num_ops >> 7);
-	if (aq_avail <= 0)
-		acc_enqueue_queue_full(q_data);
-	return aq_avail;
+	int32_t aq_avail = acc_aq_avail(q_data, num);
+	if (unlikely((aq_avail <= 0) || (num == 0)))
+		return 0;
+	if (ops[0]->turbo_enc.code_block_mode == RTE_BBDEV_TRANSPORT_BLOCK)
+		return acc200_enqueue_enc_tb(q_data, ops, num);
+	else
+		return acc200_enqueue_enc_cb(q_data, ops, num);
 }
 
 /* Enqueue encode operations for ACC200 device. */
@@ -1652,6 +2319,47 @@
 		return acc200_enqueue_ldpc_enc_cb(q_data, ops, num);
 }
 
+
+/* Enqueue decode operations for ACC200 device in CB mode */
+static uint16_t
+acc200_enqueue_dec_cb(struct rte_bbdev_queue_data *q_data,
+		struct rte_bbdev_dec_op **ops, uint16_t num)
+{
+	struct acc_queue *q = q_data->queue_private;
+	int32_t avail = acc_ring_avail_enq(q);
+	uint16_t i;
+	union acc_dma_desc *desc;
+	int ret;
+
+	for (i = 0; i < num; ++i) {
+		/* Check if there are available space for further processing */
+		if (unlikely(avail - 1 < 0))
+			break;
+		avail -= 1;
+
+		ret = enqueue_dec_one_op_cb(q, ops[i], i);
+		if (ret < 0)
+			break;
+	}
+
+	if (unlikely(i == 0))
+		return 0; /* Nothing to enqueue */
+
+	/* Set SDone in last CB in enqueued ops for CB mode*/
+	desc = q->ring_addr + ((q->sw_ring_head + i - 1)
+			& q->sw_ring_wrap_mask);
+	desc->req.sdone_enable = 1;
+	desc->req.irq_enable = q->irq_enable;
+
+	acc_dma_enqueue(q, i, &q_data->queue_stats);
+
+	/* Update stats */
+	q_data->queue_stats.enqueued_count += i;
+	q_data->queue_stats.enqueue_err_count += num - i;
+
+	return i;
+}
+
 /* Enqueue decode operations for ACC200 device in TB mode */
 static uint16_t
 acc200_enqueue_ldpc_dec_tb(struct rte_bbdev_queue_data *q_data,
@@ -1740,12 +2448,64 @@
 	return i;
 }
 
+
+/* Enqueue decode operations for ACC200 device in TB mode */
+static uint16_t
+acc200_enqueue_dec_tb(struct rte_bbdev_queue_data *q_data,
+		struct rte_bbdev_dec_op **ops, uint16_t num)
+{
+	struct acc_queue *q = q_data->queue_private;
+	int32_t avail = acc_ring_avail_enq(q);
+	uint16_t i, enqueued_cbs = 0;
+	uint8_t cbs_in_tb;
+	int ret;
+
+	for (i = 0; i < num; ++i) {
+		cbs_in_tb = get_num_cbs_in_tb_dec(&ops[i]->turbo_dec);
+		/* Check if there are available space for further processing */
+		if (unlikely((avail - cbs_in_tb < 0) || (cbs_in_tb == 0))) {
+			acc_enqueue_ring_full(q_data);
+			break;
+		}
+		avail -= cbs_in_tb;
+
+		ret = enqueue_dec_one_op_tb(q, ops[i], enqueued_cbs, cbs_in_tb);
+		if (ret <= 0) {
+			acc_enqueue_invalid(q_data);
+			break;
+		}
+		enqueued_cbs += ret;
+	}
+
+	acc_dma_enqueue(q, enqueued_cbs, &q_data->queue_stats);
+
+	/* Update stats */
+	q_data->queue_stats.enqueued_count += i;
+	q_data->queue_stats.enqueue_err_count += num - i;
+
+	return i;
+}
+
+/* Enqueue decode operations for ACC200 device. */
+static uint16_t
+acc200_enqueue_dec(struct rte_bbdev_queue_data *q_data,
+		struct rte_bbdev_dec_op **ops, uint16_t num)
+{
+	int32_t aq_avail = acc_aq_avail(q_data, num);
+	if (unlikely((aq_avail <= 0) || (num == 0)))
+		return 0;
+	if (ops[0]->turbo_dec.code_block_mode == RTE_BBDEV_TRANSPORT_BLOCK)
+		return acc200_enqueue_dec_tb(q_data, ops, num);
+	else
+		return acc200_enqueue_dec_cb(q_data, ops, num);
+}
+
 /* Enqueue decode operations for ACC200 device. */
 static uint16_t
 acc200_enqueue_ldpc_dec(struct rte_bbdev_queue_data *q_data,
 		struct rte_bbdev_dec_op **ops, uint16_t num)
 {
-	int32_t aq_avail = acc200_aq_avail(q_data, num);
+	int32_t aq_avail = acc_aq_avail(q_data, num);
 	if (unlikely((aq_avail <= 0) || (num == 0)))
 		return 0;
 	if (ops[0]->ldpc_dec.code_block_mode == RTE_BBDEV_TRANSPORT_BLOCK)
@@ -2093,6 +2853,51 @@
 	return cb_idx;
 }
 
+/* Dequeue encode operations from ACC200 device. */
+static uint16_t
+acc200_dequeue_enc(struct rte_bbdev_queue_data *q_data,
+		struct rte_bbdev_enc_op **ops, uint16_t num)
+{
+	struct acc_queue *q = q_data->queue_private;
+	uint32_t avail = acc_ring_avail_deq(q);
+	uint32_t aq_dequeued = 0;
+	uint16_t i, dequeued_ops = 0, dequeued_descs = 0;
+	int ret;
+	struct rte_bbdev_enc_op *op;
+	if (avail == 0)
+		return 0;
+	op = (q->ring_addr + (q->sw_ring_tail &
+			q->sw_ring_wrap_mask))->req.op_addr;
+#ifdef RTE_LIBRTE_BBDEV_DEBUG
+	if (unlikely(ops == NULL || q == NULL || op == NULL))
+		return 0;
+#endif
+	int cbm = op->turbo_enc.code_block_mode;
+
+	for (i = 0; i < num; i++) {
+		if (cbm == RTE_BBDEV_TRANSPORT_BLOCK)
+			ret = dequeue_enc_one_op_tb(q, &ops[dequeued_ops],
+					&dequeued_ops, &aq_dequeued,
+					&dequeued_descs);
+		else
+			ret = dequeue_enc_one_op_cb(q, &ops[dequeued_ops],
+					&dequeued_ops, &aq_dequeued,
+					&dequeued_descs);
+		if (ret < 0)
+			break;
+		if (dequeued_ops >= num)
+			break;
+	}
+
+	q->aq_dequeued += aq_dequeued;
+	q->sw_ring_tail += dequeued_descs;
+
+	/* Update enqueue stats */
+	q_data->queue_stats.dequeued_count += dequeued_ops;
+
+	return dequeued_ops;
+}
+
 /* Dequeue LDPC encode operations from ACC200 device. */
 static uint16_t
 acc200_dequeue_ldpc_enc(struct rte_bbdev_queue_data *q_data,
@@ -2140,6 +2945,51 @@
 
 /* Dequeue decode operations from ACC200 device. */
 static uint16_t
+acc200_dequeue_dec(struct rte_bbdev_queue_data *q_data,
+		struct rte_bbdev_dec_op **ops, uint16_t num)
+{
+	struct acc_queue *q = q_data->queue_private;
+	uint16_t dequeue_num;
+	uint32_t avail = acc_ring_avail_deq(q);
+	uint32_t aq_dequeued = 0;
+	uint16_t i;
+	uint16_t dequeued_cbs = 0;
+	struct rte_bbdev_dec_op *op;
+	int ret;
+
+#ifdef RTE_LIBRTE_BBDEV_DEBUG
+	if (unlikely(ops == 0 && q == NULL))
+		return 0;
+#endif
+
+	dequeue_num = (avail < num) ? avail : num;
+
+	for (i = 0; i < dequeue_num; ++i) {
+		op = (q->ring_addr + ((q->sw_ring_tail + dequeued_cbs)
+			& q->sw_ring_wrap_mask))->req.op_addr;
+		if (op->turbo_dec.code_block_mode == RTE_BBDEV_TRANSPORT_BLOCK)
+			ret = dequeue_dec_one_op_tb(q, &ops[i], dequeued_cbs,
+					&aq_dequeued);
+		else
+			ret = dequeue_dec_one_op_cb(q_data, q, &ops[i],
+					dequeued_cbs, &aq_dequeued);
+
+		if (ret <= 0)
+			break;
+		dequeued_cbs += ret;
+	}
+
+	q->aq_dequeued += aq_dequeued;
+	q->sw_ring_tail += dequeued_cbs;
+
+	/* Update enqueue stats */
+	q_data->queue_stats.dequeued_count += i;
+
+	return i;
+}
+
+/* Dequeue decode operations from ACC200 device. */
+static uint16_t
 acc200_dequeue_ldpc_dec(struct rte_bbdev_queue_data *q_data,
 		struct rte_bbdev_dec_op **ops, uint16_t num)
 {
@@ -2191,6 +3041,10 @@
 	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;
Signature · 1 line
1.8.3.1
#12 lore raw

PATCH v3 8/13 baseband/acc200: add support for FFT operations

In reply to Nic Chautru

From: Nicolas Chautru <[email protected]>

Add functions and capability for FFT processing

---
 drivers/baseband/acc200/rte_acc200_pmd.c | 251 ++++++++++++++++++++++++++++++-
 1 file changed, 249 insertions(+), 2 deletions(-)
drivers/baseband/acc200/rte_acc200_pmd.c +249 -2
index 9c3388f..483dce8 100644
@@ -717,6 +717,21 @@
 			.num_buffers_soft_out = 0,
 			}
 		},
+		{
+			.type	= RTE_BBDEV_OP_FFT,
+			.cap.fft = {
+				.capability_flags =
+						RTE_BBDEV_FFT_WINDOWING |
+						RTE_BBDEV_FFT_CS_ADJUSTMENT |
+						RTE_BBDEV_FFT_DFT_BYPASS |
+						RTE_BBDEV_FFT_IDFT_BYPASS |
+						RTE_BBDEV_FFT_WINDOWING_BYPASS,
+				.num_buffers_src =
+						RTE_BBDEV_LDPC_MAX_CODE_BLOCKS,
+				.num_buffers_dst =
+						RTE_BBDEV_LDPC_MAX_CODE_BLOCKS,
+			}
+		},
 		RTE_BBDEV_END_OF_CAPABILITIES_LIST()
 	};
 
@@ -739,12 +754,13 @@
 			d->acc_conf.q_ul_5g.num_qgroups;
 	dev_info->num_queues[RTE_BBDEV_OP_LDPC_ENC] = d->acc_conf.q_dl_5g.num_aqs_per_groups *
 			d->acc_conf.q_dl_5g.num_qgroups;
-	dev_info->num_queues[RTE_BBDEV_OP_FFT] = 0;
+	dev_info->num_queues[RTE_BBDEV_OP_FFT] = d->acc_conf.q_fft.num_aqs_per_groups *
+			d->acc_conf.q_fft.num_qgroups;
 	dev_info->queue_priority[RTE_BBDEV_OP_TURBO_DEC] = d->acc_conf.q_ul_4g.num_qgroups;
 	dev_info->queue_priority[RTE_BBDEV_OP_TURBO_ENC] = d->acc_conf.q_dl_4g.num_qgroups;
 	dev_info->queue_priority[RTE_BBDEV_OP_LDPC_DEC] = d->acc_conf.q_ul_5g.num_qgroups;
 	dev_info->queue_priority[RTE_BBDEV_OP_LDPC_ENC] = d->acc_conf.q_dl_5g.num_qgroups;
-	dev_info->queue_priority[RTE_BBDEV_OP_FFT] = 0;
+	dev_info->queue_priority[RTE_BBDEV_OP_FFT] = d->acc_conf.q_fft.num_qgroups;
 	dev_info->max_num_queues = 0;
 	for (i = RTE_BBDEV_OP_NONE; i <= RTE_BBDEV_OP_FFT; i++)
 		dev_info->max_num_queues += dev_info->num_queues[i];
@@ -3034,6 +3050,235 @@
 	return i;
 }
 
+/* Fill in a frame control word for FFT processing. */
+static inline void
+acc200_fcw_fft_fill(struct rte_bbdev_fft_op *op, struct acc_fcw_fft *fcw)
+{
+	fcw->in_frame_size = op->fft.input_sequence_size;
+	fcw->leading_pad_size = op->fft.input_leading_padding;
+	fcw->out_frame_size = op->fft.output_sequence_size;
+	fcw->leading_depad_size = op->fft.output_leading_depadding;
+	fcw->cs_window_sel = op->fft.window_index[0] +
+			(op->fft.window_index[1] << 8) +
+			(op->fft.window_index[2] << 16) +
+			(op->fft.window_index[3] << 24);
+	fcw->cs_window_sel2 = op->fft.window_index[4] +
+			(op->fft.window_index[5] << 8);
+	fcw->cs_enable_bmap = op->fft.cs_bitmap;
+	fcw->num_antennas = op->fft.num_antennas_log2;
+	fcw->idft_size = op->fft.idft_log2;
+	fcw->dft_size = op->fft.dft_log2;
+	fcw->cs_offset = op->fft.cs_time_adjustment;
+	fcw->idft_shift = op->fft.idft_shift;
+	fcw->dft_shift = op->fft.dft_shift;
+	fcw->cs_multiplier = op->fft.ncs_reciprocal;
+	if (check_bit(op->fft.op_flags,
+			RTE_BBDEV_FFT_IDFT_BYPASS)) {
+		if (check_bit(op->fft.op_flags,
+				RTE_BBDEV_FFT_WINDOWING_BYPASS))
+			fcw->bypass = 2;
+		else
+			fcw->bypass = 1;
+	} else if (check_bit(op->fft.op_flags,
+			RTE_BBDEV_FFT_DFT_BYPASS))
+		fcw->bypass = 3;
+	else
+		fcw->bypass = 0;
+}
+
+static inline int
+acc200_dma_desc_fft_fill(struct rte_bbdev_fft_op *op,
+		struct acc_dma_req_desc *desc,
+		struct rte_mbuf *input, struct rte_mbuf *output,
+		uint32_t *in_offset, uint32_t *out_offset)
+{
+	/* FCW already done */
+	acc_header_init(desc);
+	desc->data_ptrs[1].address =
+			rte_pktmbuf_iova_offset(input, *in_offset);
+	desc->data_ptrs[1].blen = op->fft.input_sequence_size * 4;
+	desc->data_ptrs[1].blkid = ACC_DMA_BLKID_IN;
+	desc->data_ptrs[1].last = 1;
+	desc->data_ptrs[1].dma_ext = 0;
+	desc->data_ptrs[2].address =
+			rte_pktmbuf_iova_offset(output, *out_offset);
+	desc->data_ptrs[2].blen = op->fft.output_sequence_size * 4;
+	desc->data_ptrs[2].blkid = ACC_DMA_BLKID_OUT_HARD;
+	desc->data_ptrs[2].last = 1;
+	desc->data_ptrs[2].dma_ext = 0;
+	desc->m2dlen = 2;
+	desc->d2mlen = 1;
+	desc->ib_ant_offset = op->fft.input_sequence_size;
+	desc->num_ant = op->fft.num_antennas_log2 - 3;
+	int num_cs = 0, i;
+	for (i = 0; i < 12; i++)
+		if (check_bit(op->fft.cs_bitmap, 1 << i))
+			num_cs++;
+	desc->num_cs = num_cs;
+	desc->ob_cyc_offset = op->fft.output_sequence_size;
+	desc->ob_ant_offset = op->fft.output_sequence_size * num_cs;
+	desc->op_addr = op;
+	return 0;
+}
+
+
+/** Enqueue one FFT operation for ACC200 device*/
+static inline int
+enqueue_fft_one_op(struct acc_queue *q, struct rte_bbdev_fft_op *op,
+		uint16_t total_enqueued_cbs)
+{
+	union acc_dma_desc *desc;
+	uint16_t desc_idx = ((q->sw_ring_head + total_enqueued_cbs)
+			& q->sw_ring_wrap_mask);
+	desc = q->ring_addr + desc_idx;
+	struct rte_mbuf *input, *output;
+	uint32_t in_offset, out_offset;
+	input = op->fft.base_input.data;
+	output = op->fft.base_output.data;
+	in_offset = op->fft.base_input.offset;
+	out_offset = op->fft.base_output.offset;
+#ifdef RTE_LIBRTE_BBDEV_DEBUG
+	if (unlikely(input == NULL)) {
+		rte_bbdev_log(ERR, "Invalid mbuf pointer");
+		return -EFAULT;
+	}
+#endif
+	struct acc_fcw_fft *fcw;
+	fcw = &desc->req.fcw_fft;
+	acc200_fcw_fft_fill(op, fcw);
+	acc200_dma_desc_fft_fill(op, &desc->req, input, output,
+			&in_offset, &out_offset);
+#ifdef RTE_LIBRTE_BBDEV_DEBUG
+	rte_memdump(stderr, "FCW", &desc->req.fcw_fft,
+			sizeof(desc->req.fcw_fft));
+	rte_memdump(stderr, "Req Desc.", desc, sizeof(*desc));
+#endif
+	return 1;
+}
+
+/* Enqueue decode operations for ACC200 device. */
+static uint16_t
+acc200_enqueue_fft(struct rte_bbdev_queue_data *q_data,
+		struct rte_bbdev_fft_op **ops, uint16_t num)
+{
+	int32_t aq_avail = acc_aq_avail(q_data, num);
+	if (unlikely((aq_avail <= 0) || (num == 0)))
+		return 0;
+	struct acc_queue *q = q_data->queue_private;
+	int32_t avail = acc_ring_avail_enq(q);
+	uint16_t i;
+	union acc_dma_desc *desc;
+	int ret;
+	for (i = 0; i < num; ++i) {
+		/* Check if there are available space for further processing */
+		if (unlikely(avail < 1))
+			break;
+		avail -= 1;
+		ret = enqueue_fft_one_op(q, ops[i], i);
+		if (ret < 0)
+			break;
+	}
+
+	if (unlikely(i == 0))
+		return 0; /* Nothing to enqueue */
+
+	/* Set SDone in last CB in enqueued ops for CB mode*/
+	desc = q->ring_addr + ((q->sw_ring_head + i - 1)
+			& q->sw_ring_wrap_mask);
+
+	desc->req.sdone_enable = 1;
+	desc->req.irq_enable = q->irq_enable;
+	acc_dma_enqueue(q, i, &q_data->queue_stats);
+
+	/* Update stats */
+	q_data->queue_stats.enqueued_count += i;
+	q_data->queue_stats.enqueue_err_count += num - i;
+	return i;
+}
+
+
+/* Dequeue one FFT operations from ACC200 device */
+static inline int
+dequeue_fft_one_op(struct rte_bbdev_queue_data *q_data,
+		struct acc_queue *q, struct rte_bbdev_fft_op **ref_op,
+		uint16_t dequeued_cbs, uint32_t *aq_dequeued)
+{
+	union acc_dma_desc *desc, atom_desc;
+	union acc_dma_rsp_desc rsp;
+	struct rte_bbdev_fft_op *op;
+
+	desc = q->ring_addr + ((q->sw_ring_tail + dequeued_cbs)
+			& q->sw_ring_wrap_mask);
+	atom_desc.atom_hdr = __atomic_load_n((uint64_t *)desc,
+			__ATOMIC_RELAXED);
+
+	/* Check fdone bit */
+	if (!(atom_desc.rsp.val & ACC_FDONE))
+		return -1;
+
+	rsp.val = atom_desc.rsp.val;
+#ifdef RTE_LIBRTE_BBDEV_DEBUG
+	rte_memdump(stderr, "Resp", &desc->rsp.val,
+			sizeof(desc->rsp.val));
+#endif
+	/* Dequeue */
+	op = desc->req.op_addr;
+
+	/* Clearing status, it will be set based on response */
+	op->status = 0;
+	op->status |= rsp.input_err << RTE_BBDEV_DATA_ERROR;
+	op->status |= rsp.dma_err << RTE_BBDEV_DRV_ERROR;
+	op->status |= rsp.fcw_err << RTE_BBDEV_DRV_ERROR;
+	if (op->status != 0)
+		q_data->queue_stats.dequeue_err_count++;
+
+	/* Check if this is the last desc in batch (Atomic Queue) */
+	if (desc->req.last_desc_in_batch) {
+		(*aq_dequeued)++;
+		desc->req.last_desc_in_batch = 0;
+	}
+	desc->rsp.val = ACC_DMA_DESC_TYPE;
+	desc->rsp.add_info_0 = 0;
+	*ref_op = op;
+	/* One CB (op) was successfully dequeued */
+	return 1;
+}
+
+
+/* Dequeue FFT operations from ACC200 device. */
+static uint16_t
+acc200_dequeue_fft(struct rte_bbdev_queue_data *q_data,
+		struct rte_bbdev_fft_op **ops, uint16_t num)
+{
+	struct acc_queue *q = q_data->queue_private;
+	uint16_t dequeue_num, i, dequeued_cbs = 0;
+	uint32_t avail = acc_ring_avail_deq(q);
+	uint32_t aq_dequeued = 0;
+	int ret;
+
+#ifdef RTE_LIBRTE_BBDEV_DEBUG
+	if (unlikely(ops == 0 && q == NULL))
+		return 0;
+#endif
+
+	dequeue_num = RTE_MIN(avail, num);
+
+	for (i = 0; i < dequeue_num; ++i) {
+		ret = dequeue_fft_one_op(
+				q_data, q, &ops[i], dequeued_cbs,
+				&aq_dequeued);
+		if (ret <= 0)
+			break;
+		dequeued_cbs += ret;
+	}
+
+	q->aq_dequeued += aq_dequeued;
+	q->sw_ring_tail += dequeued_cbs;
+	/* Update enqueue stats */
+	q_data->queue_stats.dequeued_count += i;
+	return i;
+}
+
 /* Initialization Function */
 static void
 acc200_bbdev_init(struct rte_bbdev *dev, struct rte_pci_driver *drv)
@@ -3049,6 +3294,8 @@
 	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,
Signature · 1 line
1.8.3.1
#13 lore raw

PATCH v3 9/13 baseband/acc200: support interrupt

In reply to Nic Chautru

From: Nicolas Chautru <[email protected]>

Adding support for capability and functions for MSI/MSI-X interrupt and underlying information ring.

---
 drivers/baseband/acc200/rte_acc200_pmd.c | 346 ++++++++++++++++++++++++++++++-
 1 file changed, 344 insertions(+), 2 deletions(-)
drivers/baseband/acc200/rte_acc200_pmd.c +344 -2
index 483dce8..8fe5704 100644
@@ -220,6 +220,193 @@
 			acc_conf->q_fft.aq_depth_log2);
 }
 
+/* Checks PF Info Ring to find the interrupt cause and handles it accordingly */
+static inline void
+acc200_check_ir(struct acc_device *acc200_dev)
+{
+	volatile union acc_info_ring_data *ring_data;
+	uint16_t info_ring_head = acc200_dev->info_ring_head;
+	if (acc200_dev->info_ring == NULL)
+		return;
+
+	ring_data = acc200_dev->info_ring + (acc200_dev->info_ring_head &
+			ACC_INFO_RING_MASK);
+
+	while (ring_data->valid) {
+		if ((ring_data->int_nb < ACC200_PF_INT_DMA_DL_DESC_IRQ) || (
+				ring_data->int_nb >
+				ACC200_PF_INT_DMA_DL5G_DESC_IRQ)) {
+			rte_bbdev_log(WARNING, "InfoRing: ITR:%d Info:0x%x",
+				ring_data->int_nb, ring_data->detailed_info);
+			/* Initialize Info Ring entry and move forward */
+			ring_data->val = 0;
+		}
+		info_ring_head++;
+		ring_data = acc200_dev->info_ring +
+				(info_ring_head & ACC_INFO_RING_MASK);
+	}
+}
+
+/* Checks PF Info Ring to find the interrupt cause and handles it accordingly */
+static inline void
+acc200_pf_interrupt_handler(struct rte_bbdev *dev)
+{
+	struct acc_device *acc200_dev = dev->data->dev_private;
+	volatile union acc_info_ring_data *ring_data;
+	struct acc_deq_intr_details deq_intr_det;
+
+	ring_data = acc200_dev->info_ring + (acc200_dev->info_ring_head &
+			ACC_INFO_RING_MASK);
+
+	while (ring_data->valid) {
+
+		rte_bbdev_log_debug(
+				"ACC200 PF Interrupt received, Info Ring data: 0x%x -> %d",
+				ring_data->val, ring_data->int_nb);
+
+		switch (ring_data->int_nb) {
+		case ACC200_PF_INT_DMA_DL_DESC_IRQ:
+		case ACC200_PF_INT_DMA_UL_DESC_IRQ:
+		case ACC200_PF_INT_DMA_FFT_DESC_IRQ:
+		case ACC200_PF_INT_DMA_UL5G_DESC_IRQ:
+		case ACC200_PF_INT_DMA_DL5G_DESC_IRQ:
+			deq_intr_det.queue_id = get_queue_id_from_ring_info(
+					dev->data, *ring_data);
+			if (deq_intr_det.queue_id == UINT16_MAX) {
+				rte_bbdev_log(ERR,
+						"Couldn't find queue: aq_id: %u, qg_id: %u, vf_id: %u",
+						ring_data->aq_id,
+						ring_data->qg_id,
+						ring_data->vf_id);
+				return;
+			}
+			rte_bbdev_pmd_callback_process(dev,
+					RTE_BBDEV_EVENT_DEQUEUE, &deq_intr_det);
+			break;
+		default:
+			rte_bbdev_pmd_callback_process(dev,
+					RTE_BBDEV_EVENT_ERROR, NULL);
+			break;
+		}
+
+		/* Initialize Info Ring entry and move forward */
+		ring_data->val = 0;
+		++acc200_dev->info_ring_head;
+		ring_data = acc200_dev->info_ring +
+				(acc200_dev->info_ring_head & ACC_INFO_RING_MASK);
+	}
+}
+
+/* Checks VF Info Ring to find the interrupt cause and handles it accordingly */
+static inline void
+acc200_vf_interrupt_handler(struct rte_bbdev *dev)
+{
+	struct acc_device *acc200_dev = dev->data->dev_private;
+	volatile union acc_info_ring_data *ring_data;
+	struct acc_deq_intr_details deq_intr_det;
+
+	ring_data = acc200_dev->info_ring + (acc200_dev->info_ring_head & ACC_INFO_RING_MASK);
+
+	while (ring_data->valid) {
+
+		rte_bbdev_log_debug(
+				"ACC200 VF Interrupt received, Info Ring data: 0x%x\n",
+				ring_data->val);
+
+		switch (ring_data->int_nb) {
+		case ACC200_VF_INT_DMA_DL_DESC_IRQ:
+		case ACC200_VF_INT_DMA_UL_DESC_IRQ:
+		case ACC200_VF_INT_DMA_FFT_DESC_IRQ:
+		case ACC200_VF_INT_DMA_UL5G_DESC_IRQ:
+		case ACC200_VF_INT_DMA_DL5G_DESC_IRQ:
+			/* VFs are not aware of their vf_id - it's set to 0 in
+			 * queue structures.
+			 */
+			ring_data->vf_id = 0;
+			deq_intr_det.queue_id = get_queue_id_from_ring_info(
+					dev->data, *ring_data);
+			if (deq_intr_det.queue_id == UINT16_MAX) {
+				rte_bbdev_log(ERR,
+						"Couldn't find queue: aq_id: %u, qg_id: %u",
+						ring_data->aq_id,
+						ring_data->qg_id);
+				return;
+			}
+			rte_bbdev_pmd_callback_process(dev,
+					RTE_BBDEV_EVENT_DEQUEUE, &deq_intr_det);
+			break;
+		default:
+			rte_bbdev_pmd_callback_process(dev,
+					RTE_BBDEV_EVENT_ERROR, NULL);
+			break;
+		}
+
+		/* Initialize Info Ring entry and move forward */
+		ring_data->valid = 0;
+		++acc200_dev->info_ring_head;
+		ring_data = acc200_dev->info_ring + (acc200_dev->info_ring_head
+				& ACC_INFO_RING_MASK);
+	}
+}
+
+/* Interrupt handler triggered by ACC200 dev for handling specific interrupt */
+static void
+acc200_dev_interrupt_handler(void *cb_arg)
+{
+	struct rte_bbdev *dev = cb_arg;
+	struct acc_device *acc200_dev = dev->data->dev_private;
+
+	/* Read info ring */
+	if (acc200_dev->pf_device)
+		acc200_pf_interrupt_handler(dev);
+	else
+		acc200_vf_interrupt_handler(dev);
+}
+
+/* Allocate and setup inforing */
+static int
+allocate_info_ring(struct rte_bbdev *dev)
+{
+	struct acc_device *d = dev->data->dev_private;
+	const struct acc200_registry_addr *reg_addr;
+	rte_iova_t info_ring_iova;
+	uint32_t phys_low, phys_high;
+
+	if (d->info_ring != NULL)
+		return 0; /* Already configured */
+
+	/* Choose correct registry addresses for the device type */
+	if (d->pf_device)
+		reg_addr = &pf_reg_addr;
+	else
+		reg_addr = &vf_reg_addr;
+	/* Allocate InfoRing */
+	if (d->info_ring == NULL)
+		d->info_ring = rte_zmalloc_socket("Info Ring",
+				ACC_INFO_RING_NUM_ENTRIES *
+				sizeof(*d->info_ring), RTE_CACHE_LINE_SIZE,
+				dev->data->socket_id);
+	if (d->info_ring == NULL) {
+		rte_bbdev_log(ERR,
+				"Failed to allocate Info Ring for %s:%u",
+				dev->device->driver->name,
+				dev->data->dev_id);
+		return -ENOMEM;
+	}
+	info_ring_iova = rte_malloc_virt2iova(d->info_ring);
+
+	/* Setup Info Ring */
+	phys_high = (uint32_t)(info_ring_iova >> 32);
+	phys_low  = (uint32_t)(info_ring_iova);
+	acc_reg_write(d, reg_addr->info_ring_hi, phys_high);
+	acc_reg_write(d, reg_addr->info_ring_lo, phys_low);
+	acc_reg_write(d, reg_addr->info_ring_en, ACC200_REG_IRQ_EN_ALL);
+	d->info_ring_head = (acc_reg_read(d, reg_addr->info_ring_ptr) &
+			0xFFF) / sizeof(union acc_info_ring_data);
+	return 0;
+}
+
+
 /* Allocate 64MB memory used for all software rings */
 static int
 acc200_setup_queues(struct rte_bbdev *dev, uint16_t num_queues, int socket_id)
@@ -227,6 +414,7 @@
 	uint32_t phys_low, phys_high, value;
 	struct acc_device *d = dev->data->dev_private;
 	const struct acc200_registry_addr *reg_addr;
+	int ret;
 
 	if (d->pf_device && !d->acc_conf.pf_mode_en) {
 		rte_bbdev_log(NOTICE,
@@ -327,6 +515,14 @@
 	acc_reg_write(d, reg_addr->tail_ptrs_fft_hi, phys_high);
 	acc_reg_write(d, reg_addr->tail_ptrs_fft_lo, phys_low);
 
+	ret = allocate_info_ring(dev);
+	if (ret < 0) {
+		rte_bbdev_log(ERR, "Failed to allocate info_ring for %s:%u",
+				dev->device->driver->name,
+				dev->data->dev_id);
+		/* Continue */
+	}
+
 	if (d->harq_layout == NULL)
 		d->harq_layout = rte_zmalloc_socket("HARQ Layout",
 				ACC_HARQ_LAYOUT * sizeof(*d->harq_layout),
@@ -349,17 +545,121 @@
 	return 0;
 }
 
+static int
+acc200_intr_enable(struct rte_bbdev *dev)
+{
+	int ret;
+	struct acc_device *d = dev->data->dev_private;
+	/*
+	 * MSI/MSI-X are supported
+	 * Option controlled by vfio-intr through EAL parameter
+	 */
+	if (rte_intr_type_get(dev->intr_handle) == RTE_INTR_HANDLE_VFIO_MSI) {
+
+		ret = allocate_info_ring(dev);
+		if (ret < 0) {
+			rte_bbdev_log(ERR,
+					"Couldn't allocate info ring for device: %s",
+					dev->data->name);
+			return ret;
+		}
+		ret = rte_intr_enable(dev->intr_handle);
+		if (ret < 0) {
+			rte_bbdev_log(ERR,
+					"Couldn't enable interrupts for device: %s",
+					dev->data->name);
+			rte_free(d->info_ring);
+			return ret;
+		}
+		ret = rte_intr_callback_register(dev->intr_handle,
+				acc200_dev_interrupt_handler, dev);
+		if (ret < 0) {
+			rte_bbdev_log(ERR,
+					"Couldn't register interrupt callback for device: %s",
+					dev->data->name);
+			rte_free(d->info_ring);
+			return ret;
+		}
+
+		return 0;
+	} else if (rte_intr_type_get(dev->intr_handle) == RTE_INTR_HANDLE_VFIO_MSIX) {
+
+		ret = allocate_info_ring(dev);
+		if (ret < 0) {
+			rte_bbdev_log(ERR,
+					"Couldn't allocate info ring for device: %s",
+					dev->data->name);
+			return ret;
+		}
+
+		int i, max_queues;
+		struct acc_device *acc200_dev = dev->data->dev_private;
+
+		if (acc200_dev->pf_device)
+			max_queues = ACC200_MAX_PF_MSIX;
+		else
+			max_queues = ACC200_MAX_VF_MSIX;
+
+		if (rte_intr_efd_enable(dev->intr_handle, max_queues)) {
+			rte_bbdev_log(ERR, "Failed to create fds for %u queues",
+					dev->data->num_queues);
+			return -1;
+		}
+
+		for (i = 0; i < max_queues; ++i) {
+			if (rte_intr_efds_index_set(dev->intr_handle, i,
+					rte_intr_fd_get(dev->intr_handle)))
+				return -rte_errno;
+		}
+
+		if (rte_intr_vec_list_alloc(dev->intr_handle, "intr_vec",
+				dev->data->num_queues)) {
+			rte_bbdev_log(ERR, "Failed to allocate %u vectors",
+					dev->data->num_queues);
+			return -ENOMEM;
+		}
+
+		ret = rte_intr_enable(dev->intr_handle);
+
+		if (ret < 0) {
+			rte_bbdev_log(ERR,
+					"Couldn't enable interrupts for device: %s",
+					dev->data->name);
+			rte_free(d->info_ring);
+			return ret;
+		}
+		ret = rte_intr_callback_register(dev->intr_handle,
+				acc200_dev_interrupt_handler, dev);
+		if (ret < 0) {
+			rte_bbdev_log(ERR,
+					"Couldn't register interrupt callback for device: %s",
+					dev->data->name);
+			rte_free(d->info_ring);
+			return ret;
+		}
+
+		return 0;
+	}
+
+	rte_bbdev_log(ERR, "ACC200 (%s) supports only VFIO MSI/MSI-X interrupts\n",
+			dev->data->name);
+	return -ENOTSUP;
+}
+
 /* Free memory used for software rings */
 static int
 acc200_dev_close(struct rte_bbdev *dev)
 {
 	struct acc_device *d = dev->data->dev_private;
+	acc200_check_ir(d);
 	if (d->sw_rings_base != NULL) {
 		rte_free(d->tail_ptrs);
+		rte_free(d->info_ring);
 		rte_free(d->sw_rings_base);
 		rte_free(d->harq_layout);
 		d->sw_rings_base = NULL;
 		d->tail_ptrs = NULL;
+		d->info_ring = NULL;
 		d->harq_layout = NULL;
 	}
 	/* Ensure all in flight HW transactions are completed */
@@ -652,6 +952,7 @@
 					RTE_BBDEV_TURBO_CONTINUE_CRC_MATCH |
 					RTE_BBDEV_TURBO_SOFT_OUTPUT |
 					RTE_BBDEV_TURBO_EARLY_TERMINATION |
+					RTE_BBDEV_TURBO_DEC_INTERRUPTS |
 					RTE_BBDEV_TURBO_NEG_LLR_1_BIT_IN |
 					RTE_BBDEV_TURBO_NEG_LLR_1_BIT_SOFT_OUT |
 					RTE_BBDEV_TURBO_MAP_DEC |
@@ -673,6 +974,7 @@
 					RTE_BBDEV_TURBO_CRC_24B_ATTACH |
 					RTE_BBDEV_TURBO_RV_INDEX_BYPASS |
 					RTE_BBDEV_TURBO_RATE_MATCH |
+					RTE_BBDEV_TURBO_ENC_INTERRUPTS |
 					RTE_BBDEV_TURBO_ENC_SCATTER_GATHER,
 				.num_buffers_src =
 						RTE_BBDEV_TURBO_MAX_CODE_BLOCKS,
@@ -686,7 +988,8 @@
 				.capability_flags =
 					RTE_BBDEV_LDPC_RATE_MATCH |
 					RTE_BBDEV_LDPC_CRC_24B_ATTACH |
-					RTE_BBDEV_LDPC_INTERLEAVER_BYPASS,
+					RTE_BBDEV_LDPC_INTERLEAVER_BYPASS |
+					RTE_BBDEV_LDPC_ENC_INTERRUPTS,
 				.num_buffers_src =
 						RTE_BBDEV_LDPC_MAX_CODE_BLOCKS,
 				.num_buffers_dst =
@@ -707,7 +1010,8 @@
 				RTE_BBDEV_LDPC_DEINTERLEAVER_BYPASS |
 				RTE_BBDEV_LDPC_DEC_SCATTER_GATHER |
 				RTE_BBDEV_LDPC_HARQ_6BIT_COMPRESSION |
-				RTE_BBDEV_LDPC_LLR_COMPRESSION,
+				RTE_BBDEV_LDPC_LLR_COMPRESSION |
+				RTE_BBDEV_LDPC_DEC_INTERRUPTS,
 			.llr_size = 8,
 			.llr_decimals = 1,
 			.num_buffers_src =
@@ -775,15 +1079,46 @@
 	dev_info->min_alignment = 1;
 	dev_info->capabilities = bbdev_capabilities;
 	dev_info->harq_buffer_size = 0;
+
+	acc200_check_ir(d);
+}
+
+static int
+acc200_queue_intr_enable(struct rte_bbdev *dev, uint16_t queue_id)
+{
+	struct acc_queue *q = dev->data->queues[queue_id].queue_private;
+
+	if (rte_intr_type_get(dev->intr_handle) != RTE_INTR_HANDLE_VFIO_MSI &&
+			rte_intr_type_get(dev->intr_handle) != RTE_INTR_HANDLE_VFIO_MSIX)
+		return -ENOTSUP;
+
+	q->irq_enable = 1;
+	return 0;
+}
+
+static int
+acc200_queue_intr_disable(struct rte_bbdev *dev, uint16_t queue_id)
+{
+	struct acc_queue *q = dev->data->queues[queue_id].queue_private;
+
+	if (rte_intr_type_get(dev->intr_handle) != RTE_INTR_HANDLE_VFIO_MSI &&
+			rte_intr_type_get(dev->intr_handle) != RTE_INTR_HANDLE_VFIO_MSIX)
+		return -ENOTSUP;
+
+	q->irq_enable = 0;
+	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 = acc_queue_stop,
+	.queue_intr_enable = acc200_queue_intr_enable,
+	.queue_intr_disable = acc200_queue_intr_disable
 };
 
 /* ACC200 PCI PF address map */
@@ -2694,6 +3029,7 @@
 	if (op->status != 0) {
 		/* These errors are not expected */
 		q_data->queue_stats.dequeue_err_count++;
+		acc200_check_ir(q->d);
 	}
 
 	/* CRC invalid if error exists */
@@ -2763,6 +3099,9 @@
 
 	op->ldpc_dec.iter_count = (uint8_t) rsp.iter_cnt;
 
+	if (op->status & (1 << RTE_BBDEV_DRV_ERROR))
+		acc200_check_ir(q->d);
+
 	/* Check if this is the last desc in batch (Atomic Queue) */
 	if (desc->req.last_desc_in_batch) {
 		(*aq_dequeued)++;
@@ -3232,6 +3571,9 @@
 	if (op->status != 0)
 		q_data->queue_stats.dequeue_err_count++;
 
+	if (op->status & (1 << RTE_BBDEV_DRV_ERROR))
+		acc200_check_ir(q->d);
+
 	/* Check if this is the last desc in batch (Atomic Queue) */
 	if (desc->req.last_desc_in_batch) {
 		(*aq_dequeued)++;
Signature · 1 line
1.8.3.1
#14 lore raw

PATCH v3 10/13 baseband/acc200: add device status and vf2pf comms

In reply to Nic Chautru

From: Nicolas Chautru <[email protected]>

Add support to expose the device status seen from the host through v2pf mailbox communication.

---
 drivers/baseband/acc200/rte_acc200_pmd.c | 61 +++++++++++++++++++++++---------
 1 file changed, 44 insertions(+), 17 deletions(-)
drivers/baseband/acc200/rte_acc200_pmd.c +44 -17
index 8fe5704..a969679 100644
@@ -201,23 +201,47 @@
 	rte_bbdev_log_debug(
 			"%s Config LLR SIGN IN/OUT %s %s QG %u %u %u %u %u AQ %u %u %u %u %u Len %u %u %u %u %u\n",
 			(d->pf_device) ? "PF" : "VF",
-			(acc_conf->input_pos_llr_1_bit) ? "POS" : "NEG",
-			(acc_conf->output_pos_llr_1_bit) ? "POS" : "NEG",
-			acc_conf->q_ul_4g.num_qgroups,
-			acc_conf->q_dl_4g.num_qgroups,
-			acc_conf->q_ul_5g.num_qgroups,
-			acc_conf->q_dl_5g.num_qgroups,
-			acc_conf->q_fft.num_qgroups,
-			acc_conf->q_ul_4g.num_aqs_per_groups,
-			acc_conf->q_dl_4g.num_aqs_per_groups,
-			acc_conf->q_ul_5g.num_aqs_per_groups,
-			acc_conf->q_dl_5g.num_aqs_per_groups,
-			acc_conf->q_fft.num_aqs_per_groups,
-			acc_conf->q_ul_4g.aq_depth_log2,
-			acc_conf->q_dl_4g.aq_depth_log2,
-			acc_conf->q_ul_5g.aq_depth_log2,
-			acc_conf->q_dl_5g.aq_depth_log2,
-			acc_conf->q_fft.aq_depth_log2);
+			(acc200_conf->input_pos_llr_1_bit) ? "POS" : "NEG",
+			(acc200_conf->output_pos_llr_1_bit) ? "POS" : "NEG",
+			acc200_conf->q_ul_4g.num_qgroups,
+			acc200_conf->q_dl_4g.num_qgroups,
+			acc200_conf->q_ul_5g.num_qgroups,
+			acc200_conf->q_dl_5g.num_qgroups,
+			acc200_conf->q_fft.num_qgroups,
+			acc200_conf->q_ul_4g.num_aqs_per_groups,
+			acc200_conf->q_dl_4g.num_aqs_per_groups,
+			acc200_conf->q_ul_5g.num_aqs_per_groups,
+			acc200_conf->q_dl_5g.num_aqs_per_groups,
+			acc200_conf->q_fft.num_aqs_per_groups,
+			acc200_conf->q_ul_4g.aq_depth_log2,
+			acc200_conf->q_dl_4g.aq_depth_log2,
+			acc200_conf->q_ul_5g.aq_depth_log2,
+			acc200_conf->q_dl_5g.aq_depth_log2,
+			acc200_conf->q_fft.aq_depth_log2);
+}
+
+static inline void
+acc200_vf2pf(struct acc_device *d, unsigned int payload)
+{
+	acc_reg_write(d, HWVfHiVfToPfDbellVf, payload);
+}
+
+/* Request device status information */
+static inline uint32_t
+acc200_device_status(struct rte_bbdev *dev)
+{
+	struct acc_device *d = dev->data->dev_private;
+	uint32_t reg, time_out = 0;
+	if (d->pf_device)
+		return RTE_BBDEV_DEV_NOT_SUPPORTED;
+	acc200_vf2pf(d, ACC_VF2PF_STATUS_REQUEST);
+	reg = acc_reg_read(d, HWVfHiPfToVfDbellVf);
+	while ((time_out < ACC200_STATUS_TO) && (reg == RTE_BBDEV_DEV_NOSTATUS)) {
+		usleep(ACC200_STATUS_WAIT); /*< Wait or VF->PF->VF Comms */
+		reg = acc_reg_read(d, HWVfHiPfToVfDbellVf);
+		time_out++;
+	}
+	return reg;
 }
 
 /* Checks PF Info Ring to find the interrupt cause and handles it accordingly */
@@ -537,6 +561,7 @@
 
 	/* Mark as configured properly */
 	d->configured = true;
+	acc200_vf2pf(d, ACC_VF2PF_USING_VF);
 
 	rte_bbdev_log_debug(
 			"ACC200 (%s) configured  sw_rings = %p, sw_rings_iova = %#"
@@ -1047,6 +1072,8 @@
 
 	/* Read and save the populated config from ACC200 registers */
 	fetch_acc200_config(dev);
+	/* Check the status of device */
+	dev_info->device_status = acc200_device_status(dev);
 
 	/* Exposed number of queues */
 	dev_info->num_queues[RTE_BBDEV_OP_NONE] = 0;
Signature · 1 line
1.8.3.1
#15 lore raw

PATCH v3 11/13 baseband/acc200: add PF configure companion function

In reply to Nic Chautru

From: Nicolas Chautru <[email protected]>

Add configure function notably to configure the device from the PF within DPDK and bbdev-test (without external dependency).

---
 app/test-bbdev/meson.build               |   3 +
 app/test-bbdev/test_bbdev_perf.c         |  76 ++++++
 drivers/baseband/acc200/meson.build      |   2 +
 drivers/baseband/acc200/rte_acc200_cfg.h |  21 ++
 drivers/baseband/acc200/rte_acc200_pmd.c | 453 +++++++++++++++++++++++++++++++
 drivers/baseband/acc200/version.map      |   7 +
 6 files changed, 562 insertions(+)
app/test-bbdev/meson.build +3 -0
index 76d4c26..1ffaa54 100644
@@ -23,6 +23,9 @@ endif
 if dpdk_conf.has('RTE_BASEBAND_ACC100')
     deps += ['baseband_acc100']
 endif
+if dpdk_conf.has('RTE_BASEBAND_ACC200')
+    deps += ['baseband_acc200']
+endif
 if dpdk_conf.has('RTE_LIBRTE_PMD_BBDEV_LA12XX')
     deps += ['baseband_la12xx']
 endif
app/test-bbdev/test_bbdev_perf.c +76 -0

88 lines not on this page · raw message

drivers/baseband/acc200/meson.build +2 -0
index 7ec8679..b964c21 100644
@@ -4,3 +4,5 @@
 deps += ['bbdev', 'bus_vdev', 'ring', 'pci', 'bus_pci']
 
 sources = files('rte_acc200_pmd.c')
+
+headers = files('rte_acc200_cfg.h')
drivers/baseband/acc200/rte_acc200_cfg.h +21 -0
index 9ae96c6..9fefd5c 100644
@@ -24,4 +24,25 @@
 extern "C" {
 #endif
 
+/**
+ * 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.
+ */
+__rte_experimental
+int
+rte_acc200_configure(const char *dev_name, struct rte_acc_conf *conf);
+
+#ifdef __cplusplus
+}
+#endif
+
 #endif /* _RTE_ACC200_CFG_H_ */
drivers/baseband/acc200/rte_acc200_pmd.c +453 -0

468 lines not on this page · raw message

drivers/baseband/acc200/version.map +7 -0
index c2e0723..9542f2b 100644
@@ -1,3 +1,10 @@
 DPDK_22 {
 	local: *;
 };
+
+EXPERIMENTAL {
+	global:
+
+	rte_acc200_configure;
+
+};
Signature · 1 line
1.8.3.1
#16 lore raw

PATCH v3 12/13 baseband/acc: rename and merge directories into acc

In reply to Nic Chautru

Using a common directory for the ACC100 and ACC200 PMDs into acc directory.

---
 MAINTAINERS                                  |    3 +-
 app/test-bbdev/meson.build                   |    7 +-
 app/test-bbdev/test_bbdev_perf.c             |    9 +-
 drivers/baseband/acc/acc100_pf_enum.h        |  147 +
 drivers/baseband/acc/acc100_pmd.h            |  177 +
 drivers/baseband/acc/acc100_vf_enum.h        |   73 +
 drivers/baseband/acc/acc101_pmd.h            |   40 +
 drivers/baseband/acc/acc200_pf_enum.h        |  108 +
 drivers/baseband/acc/acc200_pmd.h            |  196 ++
 drivers/baseband/acc/acc200_vf_enum.h        |   83 +
 drivers/baseband/acc/acc_common.h            | 1388 ++++++++
 drivers/baseband/acc/meson.build             |    8 +
 drivers/baseband/acc/rte_acc100_cfg.h        |   49 +
 drivers/baseband/acc/rte_acc100_pmd.c        | 4578 ++++++++++++++++++++++++++
 drivers/baseband/acc/rte_acc200_cfg.h        |   48 +
 drivers/baseband/acc/rte_acc200_pmd.c        | 4195 +++++++++++++++++++++++
 drivers/baseband/acc/rte_acc_common_cfg.h    |  101 +
 drivers/baseband/acc/version.map             |   10 +
 drivers/baseband/acc100/acc100_pf_enum.h     |  147 -
 drivers/baseband/acc100/acc100_pmd.h         |  177 -
 drivers/baseband/acc100/acc100_vf_enum.h     |   73 -
 drivers/baseband/acc100/acc101_pmd.h         |   40 -
 drivers/baseband/acc100/acc_common.h         | 1388 --------
 drivers/baseband/acc100/meson.build          |    8 -
 drivers/baseband/acc100/rte_acc100_cfg.h     |   49 -
 drivers/baseband/acc100/rte_acc100_pmd.c     | 4578 --------------------------
 drivers/baseband/acc100/rte_acc_common_cfg.h |  101 -
 drivers/baseband/acc100/version.map          |    9 -
 drivers/baseband/acc200/acc200_pf_enum.h     |  108 -
 drivers/baseband/acc200/acc200_pmd.h         |  196 --
 drivers/baseband/acc200/acc200_vf_enum.h     |   83 -
 drivers/baseband/acc200/meson.build          |    8 -
 drivers/baseband/acc200/rte_acc200_cfg.h     |   48 -
 drivers/baseband/acc200/rte_acc200_pmd.c     | 4195 -----------------------
 drivers/baseband/acc200/version.map          |   10 -
 drivers/baseband/meson.build                 |    3 +-
 36 files changed, 11207 insertions(+), 11234 deletions(-)
 create mode 100644 drivers/baseband/acc/acc100_pf_enum.h
 create mode 100644 drivers/baseband/acc/acc100_pmd.h
 create mode 100644 drivers/baseband/acc/acc100_vf_enum.h
 create mode 100644 drivers/baseband/acc/acc101_pmd.h
 create mode 100644 drivers/baseband/acc/acc200_pf_enum.h
 create mode 100644 drivers/baseband/acc/acc200_pmd.h
 create mode 100644 drivers/baseband/acc/acc200_vf_enum.h
 create mode 100644 drivers/baseband/acc/acc_common.h
 create mode 100644 drivers/baseband/acc/meson.build
 create mode 100644 drivers/baseband/acc/rte_acc100_cfg.h
 create mode 100644 drivers/baseband/acc/rte_acc100_pmd.c
 create mode 100644 drivers/baseband/acc/rte_acc200_cfg.h
 create mode 100644 drivers/baseband/acc/rte_acc200_pmd.c
 create mode 100644 drivers/baseband/acc/rte_acc_common_cfg.h
 create mode 100644 drivers/baseband/acc/version.map
 delete mode 100644 drivers/baseband/acc100/acc100_pf_enum.h
 delete mode 100644 drivers/baseband/acc100/acc100_pmd.h
 delete mode 100644 drivers/baseband/acc100/acc100_vf_enum.h
 delete mode 100644 drivers/baseband/acc100/acc101_pmd.h
 delete mode 100644 drivers/baseband/acc100/acc_common.h
 delete mode 100644 drivers/baseband/acc100/meson.build
 delete mode 100644 drivers/baseband/acc100/rte_acc100_cfg.h
 delete mode 100644 drivers/baseband/acc100/rte_acc100_pmd.c
 delete mode 100644 drivers/baseband/acc100/rte_acc_common_cfg.h
 delete mode 100644 drivers/baseband/acc100/version.map
 delete mode 100644 drivers/baseband/acc200/acc200_pf_enum.h
 delete mode 100644 drivers/baseband/acc200/acc200_pmd.h
 delete mode 100644 drivers/baseband/acc200/acc200_vf_enum.h
 delete mode 100644 drivers/baseband/acc200/meson.build
 delete mode 100644 drivers/baseband/acc200/rte_acc200_cfg.h
 delete mode 100644 drivers/baseband/acc200/rte_acc200_pmd.c
 delete mode 100644 drivers/baseband/acc200/version.map
MAINTAINERS +1 -2
index 2abaf45..39b769d 100644
@@ -1336,11 +1336,10 @@ F: doc/guides/bbdevs/features/fpga_lte_fec.ini
 F: drivers/baseband/fpga_5gnr_fec/
 F: doc/guides/bbdevs/fpga_5gnr_fec.rst
 F: doc/guides/bbdevs/features/fpga_5gnr_fec.ini
-F: drivers/baseband/acc100/
+F: drivers/baseband/acc/
 F: doc/guides/bbdevs/acc100.rst
 F: doc/guides/bbdevs/features/acc100.ini
 F: doc/guides/bbdevs/features/acc101.ini
-F: drivers/baseband/acc200/
 F: doc/guides/bbdevs/acc200.rst
 F: doc/guides/bbdevs/features/acc200.ini
 
app/test-bbdev/meson.build +2 -5
index 1ffaa54..cd6a508 100644
@@ -20,11 +20,8 @@ endif
 if dpdk_conf.has('RTE_BASEBAND_FPGA_5GNR_FEC')
     deps += ['baseband_fpga_5gnr_fec']
 endif
-if dpdk_conf.has('RTE_BASEBAND_ACC100')
-    deps += ['baseband_acc100']
-endif
-if dpdk_conf.has('RTE_BASEBAND_ACC200')
-    deps += ['baseband_acc200']
+if dpdk_conf.has('RTE_BASEBAND_ACC')
+    deps += ['baseband_acc']
 endif
 if dpdk_conf.has('RTE_LIBRTE_PMD_BBDEV_LA12XX')
     deps += ['baseband_la12xx']
app/test-bbdev/test_bbdev_perf.c +2 -7
index 8886143..ec6ee2a 100644
@@ -52,7 +52,7 @@
 #define DL_5G_LOAD_BALANCE 128
 #endif
 
-#ifdef RTE_BASEBAND_ACC100
+#ifdef RTE_BASEBAND_ACC
 #include <rte_acc100_cfg.h>
 #define ACC100PF_DRIVER_NAME   ("intel_acc100_pf")
 #define ACC100VF_DRIVER_NAME   ("intel_acc100_vf")
@@ -62,9 +62,6 @@
 #define ACC100_QMGR_INVALID_IDX -1
 #define ACC100_QMGR_RR 1
 #define ACC100_QOS_GBR 0
-#endif
-
-#ifdef RTE_BASEBAND_ACC200
 #include <rte_acc200_cfg.h>
 #define ACC200PF_DRIVER_NAME   ("intel_acc200_pf")
 #define ACC200VF_DRIVER_NAME   ("intel_acc200_vf")
@@ -717,7 +714,7 @@ typedef int (test_case_function)(struct active_device *ad,
 				info->dev_name);
 	}
 #endif
-#ifdef RTE_BASEBAND_ACC100
+#ifdef RTE_BASEBAND_ACC
 	if ((get_init_device() == true) &&
 			(!strcmp(info->drv.driver_name, ACC100PF_DRIVER_NAME))) {
 		struct rte_acc_conf conf;
@@ -773,8 +770,6 @@ typedef int (test_case_function)(struct active_device *ad,
 				"Failed to configure ACC100 PF for bbdev %s",
 				info->dev_name);
 	}
-#endif
-#ifdef RTE_BASEBAND_ACC200
 	if ((get_init_device() == true) &&
 		(!strcmp(info->drv.driver_name, ACC200PF_DRIVER_NAME))) {
 		struct rte_acc_conf conf;
drivers/baseband/acc/acc100_pf_enum.h new file +147 -0

147 lines not on this page · raw message

drivers/baseband/acc/acc100_pmd.h new file +177 -0

177 lines not on this page · raw message

drivers/baseband/acc/acc100_vf_enum.h new file +73 -0

73 lines not on this page · raw message

drivers/baseband/acc/acc101_pmd.h new file +40 -0
new file mode 100644
index 0000000..37df008
@@ -0,0 +1,40 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2022 Intel Corporation
+ */
+
+/* ACC101 PCI vendor & device IDs */
+#define ACC101_VENDOR_ID           (0x8086)
+#define ACC101_PF_DEVICE_ID        (0x57c4)
+#define ACC101_VF_DEVICE_ID        (0x57c5)
+
+/* Number of Virtual Functions ACC101 supports */
+#define ACC101_NUM_VFS                  16
+#define ACC101_NUM_QGRPS                8
+#define ACC101_NUM_AQS                  16
+
+#define ACC101_WORDS_IN_ARAM_SIZE (128 * 1024 / 4)
+
+/* Mapping of signals for the available engines */
+#define ACC101_SIG_UL_5G      0
+#define ACC101_SIG_UL_5G_LAST 8
+#define ACC101_SIG_DL_5G      13
+#define ACC101_SIG_DL_5G_LAST 15
+#define ACC101_SIG_UL_4G      16
+#define ACC101_SIG_UL_4G_LAST 19
+#define ACC101_SIG_DL_4G      27
+#define ACC101_SIG_DL_4G_LAST 31
+#define ACC101_NUM_ACCS       5
+
+/* ACC101 Configuration */
+#define ACC101_CFG_DMA_ERROR    0x3D7
+#define ACC101_CFG_AXI_CACHE    0x11
+#define ACC101_CFG_QMGR_HI_P    0x0F0F
+#define ACC101_CFG_PCI_AXI      0xC003
+#define ACC101_CFG_PCI_BRIDGE   0x40006033
+#define ACC101_GPEX_AXIMAP_NUM  17
+#define ACC101_CLOCK_GATING_EN  0x30000
+#define ACC101_DMA_INBOUND      0x104
+/* DDR Size per VF - 512MB by default
+ * Can be increased up to 4 GB with single PF/VF
+ */
+#define ACC101_HARQ_DDR         (512 * 1)
drivers/baseband/acc/acc200_pf_enum.h new file +108 -0

108 lines not on this page · raw message

drivers/baseband/acc/acc200_pmd.h new file +196 -0

196 lines not on this page · raw message

drivers/baseband/acc/acc200_vf_enum.h new file +83 -0

83 lines not on this page · raw message

drivers/baseband/acc/acc_common.h new file +1388 -0

1,388 lines not on this page · raw message

drivers/baseband/acc/meson.build new file +8 -0
new file mode 100644
index 0000000..7ae162a
@@ -0,0 +1,8 @@
+# SPDX-License-Identifier: BSD-3-Clause
+# Copyright(c) 2020 Intel Corporation
+
+deps += ['bbdev', 'bus_vdev', 'ring', 'pci', 'bus_pci']
+
+sources = files('rte_acc100_pmd.c', 'rte_acc200_pmd.c')
+
+headers = files('rte_acc100_cfg.h', 'rte_acc200_cfg.h')
drivers/baseband/acc/rte_acc100_cfg.h new file +49 -0

49 lines not on this page · raw message

drivers/baseband/acc/rte_acc100_pmd.c new file +4578 -0

673 lines not on this page · raw message

drivers/baseband/acc/rte_acc200_cfg.h new file +48 -0

48 lines not on this page · raw message

drivers/baseband/acc/rte_acc200_pmd.c new file +4195 -0

4,195 lines not on this page · raw message

drivers/baseband/acc/rte_acc_common_cfg.h new file +101 -0

101 lines not on this page · raw message

drivers/baseband/acc/version.map new file +10 -0
new file mode 100644
index 0000000..27fbbe3

Lines of this file are not shown. View the raw message.

drivers/baseband/acc100/acc100_pf_enum.h deleted +0 -147

147 lines not on this page · raw message

drivers/baseband/acc100/acc100_pmd.h deleted +0 -177

177 lines not on this page · raw message

drivers/baseband/acc100/acc100_vf_enum.h deleted +0 -73

73 lines not on this page · raw message

drivers/baseband/acc100/acc101_pmd.h deleted +0 -40
deleted file mode 100644
index 37df008..0000000

Lines of this file are not shown. View the raw message.

drivers/baseband/acc100/acc_common.h deleted +0 -1388

1,388 lines not on this page · raw message

drivers/baseband/acc100/meson.build deleted +0 -8
deleted file mode 100644
index 9a1a3b8..0000000

Lines of this file are not shown. View the raw message.

drivers/baseband/acc100/rte_acc100_cfg.h deleted +0 -49

49 lines not on this page · raw message

drivers/baseband/acc100/rte_acc100_pmd.c deleted +0 -4578

4,578 lines not on this page · raw message

drivers/baseband/acc100/rte_acc_common_cfg.h deleted +0 -101

101 lines not on this page · raw message

drivers/baseband/acc100/version.map deleted +0 -9
deleted file mode 100644
index b4ff13e..0000000

Lines of this file are not shown. View the raw message.

drivers/baseband/acc200/acc200_pf_enum.h deleted +0 -108

108 lines not on this page · raw message

drivers/baseband/acc200/acc200_pmd.h deleted +0 -196

196 lines not on this page · raw message

drivers/baseband/acc200/acc200_vf_enum.h deleted +0 -83

83 lines not on this page · raw message

drivers/baseband/acc200/meson.build deleted +0 -8
deleted file mode 100644
index b964c21..0000000

Lines of this file are not shown. View the raw message.

drivers/baseband/acc200/rte_acc200_cfg.h deleted +0 -48

48 lines not on this page · raw message

drivers/baseband/acc200/rte_acc200_pmd.c deleted +0 -4195

4,195 lines not on this page · raw message

drivers/baseband/acc200/version.map deleted +0 -10
deleted file mode 100644
index 9542f2b..0000000

Lines of this file are not shown. View the raw message.

drivers/baseband/meson.build +1 -2
index 343f83a..1d732da 100644

Lines of this file are not shown. View the raw message.

The rest of this diff is not shown. View the raw message.

Signature · 1 line
1.8.3.1

Part of the diff is not shown here. View the raw message.

#17 lore raw

PATCH v3 13/13 baseband/acc: simplify meson dependency

In reply to Nic Chautru

Removing some of libraries from the external dependency captured in meson build file.

---
 drivers/baseband/acc/meson.build | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/baseband/acc/meson.build +1 -1
index 7ae162a..bece3a6 100644
@@ -1,7 +1,7 @@
 # SPDX-License-Identifier: BSD-3-Clause
 # Copyright(c) 2020 Intel Corporation
 
-deps += ['bbdev', 'bus_vdev', 'ring', 'pci', 'bus_pci']
+deps += ['bbdev', 'bus_pci']
 
 sources = files('rte_acc100_pmd.c', 'rte_acc200_pmd.c')
 
Signature · 1 line
1.8.3.1