[v10,10/10] baseband/acc100: add configure function

Message ID 1601522084-151443-11-git-send-email-nicolas.chautru@intel.com (mailing list archive)
State Superseded, archived
Delegated to: akhil goyal
Headers
Series bbdev PMD ACC100 |

Checks

Context Check Description
ci/checkpatch success coding style OK
ci/Intel-compilation success Compilation OK
ci/iol-broadcom-Functional success Functional Testing PASS
ci/iol-intel-Functional success Functional Testing PASS
ci/iol-testing success Testing PASS

Commit Message

Chautru, Nicolas Oct. 1, 2020, 3:14 a.m. UTC
  Add configure function to configure the PF from within
the bbdev-test itself without external application
configuration the device.

Signed-off-by: Nicolas Chautru <nicolas.chautru@intel.com>
Acked-by: Liu Tianjiao <Tianjiao.liu@intel.com>
---
 app/test-bbdev/test_bbdev_perf.c                   |  71 +++
 doc/guides/rel_notes/release_20_11.rst             |   5 +
 drivers/baseband/acc100/meson.build                |   2 +
 drivers/baseband/acc100/rte_acc100_cfg.h           |  17 +
 drivers/baseband/acc100/rte_acc100_pmd.c           | 523 ++++++++++++++++++++-
 drivers/baseband/acc100/rte_acc100_pmd.h           |   1 +
 .../acc100/rte_pmd_bbdev_acc100_version.map        |   7 +
 7 files changed, 621 insertions(+), 5 deletions(-)
  

Comments

Maxime Coquelin Oct. 1, 2020, 2:11 p.m. UTC | #1
Hi Nicolas,

On 10/1/20 5:14 AM, Nicolas Chautru wrote:
> diff --git a/drivers/baseband/acc100/rte_pmd_bbdev_acc100_version.map b/drivers/baseband/acc100/rte_pmd_bbdev_acc100_version.map
> index 4a76d1d..91c234d 100644
> --- a/drivers/baseband/acc100/rte_pmd_bbdev_acc100_version.map
> +++ b/drivers/baseband/acc100/rte_pmd_bbdev_acc100_version.map
> @@ -1,3 +1,10 @@
>  DPDK_21 {
>  	local: *;
>  };
> +
> +EXPERIMENTAL {
> +	global:
> +
> +	acc100_configure;
> +
> +};
> -- 

Ideally we should not need to have device specific APIs, but at least it
should be prefixed with "rte_".

Regards,
Maxime
  
Chautru, Nicolas Oct. 1, 2020, 3:36 p.m. UTC | #2
Hi Maxime, 

> -----Original Message-----
> From: Maxime Coquelin <maxime.coquelin@redhat.com>
> Sent: Thursday, October 1, 2020 7:11 AM
> To: Chautru, Nicolas <nicolas.chautru@intel.com>; dev@dpdk.org;
> akhil.goyal@nxp.com
> Cc: Richardson, Bruce <bruce.richardson@intel.com>; Xu, Rosen
> <rosen.xu@intel.com>; trix@redhat.com; Yigit, Ferruh
> <ferruh.yigit@intel.com>; Liu, Tianjiao <tianjiao.liu@intel.com>
> Subject: Re: [dpdk-dev] [PATCH v10 10/10] baseband/acc100: add configure
> function
> 
> Hi Nicolas,
> 
> On 10/1/20 5:14 AM, Nicolas Chautru wrote:
> > diff --git a/drivers/baseband/acc100/rte_pmd_bbdev_acc100_version.map
> > b/drivers/baseband/acc100/rte_pmd_bbdev_acc100_version.map
> > index 4a76d1d..91c234d 100644
> > --- a/drivers/baseband/acc100/rte_pmd_bbdev_acc100_version.map
> > +++ b/drivers/baseband/acc100/rte_pmd_bbdev_acc100_version.map
> > @@ -1,3 +1,10 @@
> >  DPDK_21 {
> >  	local: *;
> >  };
> > +
> > +EXPERIMENTAL {
> > +	global:
> > +
> > +	acc100_configure;
> > +
> > +};
> > --
> 
> Ideally we should not need to have device specific APIs, but at least it should
> be prefixed with "rte_".

Currently this is already like that for other bbdev PMDs. 
So I would tend to prefer consistency over all in that context. 
You could argue or not whether this is PMD function or a companion exposed function, but again if this should change it should change for all PMDs to avoid discrepencies.
If really this is deemed required this can be pushed as an extra patch covering all PMD, but probably not for 20.11.
What do you think?

> 
> Regards,
> Maxime
  
Maxime Coquelin Oct. 1, 2020, 3:43 p.m. UTC | #3
On 10/1/20 5:36 PM, Chautru, Nicolas wrote:
> Hi Maxime, 
> 
>> -----Original Message-----
>> From: Maxime Coquelin <maxime.coquelin@redhat.com>
>> Sent: Thursday, October 1, 2020 7:11 AM
>> To: Chautru, Nicolas <nicolas.chautru@intel.com>; dev@dpdk.org;
>> akhil.goyal@nxp.com
>> Cc: Richardson, Bruce <bruce.richardson@intel.com>; Xu, Rosen
>> <rosen.xu@intel.com>; trix@redhat.com; Yigit, Ferruh
>> <ferruh.yigit@intel.com>; Liu, Tianjiao <tianjiao.liu@intel.com>
>> Subject: Re: [dpdk-dev] [PATCH v10 10/10] baseband/acc100: add configure
>> function
>>
>> Hi Nicolas,
>>
>> On 10/1/20 5:14 AM, Nicolas Chautru wrote:
>>> diff --git a/drivers/baseband/acc100/rte_pmd_bbdev_acc100_version.map
>>> b/drivers/baseband/acc100/rte_pmd_bbdev_acc100_version.map
>>> index 4a76d1d..91c234d 100644
>>> --- a/drivers/baseband/acc100/rte_pmd_bbdev_acc100_version.map
>>> +++ b/drivers/baseband/acc100/rte_pmd_bbdev_acc100_version.map
>>> @@ -1,3 +1,10 @@
>>>  DPDK_21 {
>>>  	local: *;
>>>  };
>>> +
>>> +EXPERIMENTAL {
>>> +	global:
>>> +
>>> +	acc100_configure;
>>> +
>>> +};
>>> --
>>
>> Ideally we should not need to have device specific APIs, but at least it should
>> be prefixed with "rte_".
> 
> Currently this is already like that for other bbdev PMDs. 
> So I would tend to prefer consistency over all in that context. 
> You could argue or not whether this is PMD function or a companion exposed function, but again if this should change it should change for all PMDs to avoid discrepencies.
> If really this is deemed required this can be pushed as an extra patch covering all PMD, but probably not for 20.11.
> What do you think?

Better to fix the API now to avoid namespace pollution, including the
other comments I made regarding API on patch 3.
That's not a big change, it can be done in v20.11 in my opinion.

Thanks,
Maxime

>>
>> Regards,
>> Maxime
>
  
Chautru, Nicolas Oct. 1, 2020, 7:50 p.m. UTC | #4
Hi Maxime, 

> From: Maxime Coquelin <maxime.coquelin@redhat.com>
> On 10/1/20 5:36 PM, Chautru, Nicolas wrote:
> > Hi Maxime,
> >> From: Maxime Coquelin <maxime.coquelin@redhat.com>
> >> Hi Nicolas,
> >>
> >> On 10/1/20 5:14 AM, Nicolas Chautru wrote:
> >>> diff --git
> >>> a/drivers/baseband/acc100/rte_pmd_bbdev_acc100_version.map
> >>> b/drivers/baseband/acc100/rte_pmd_bbdev_acc100_version.map
> >>> index 4a76d1d..91c234d 100644
> >>> --- a/drivers/baseband/acc100/rte_pmd_bbdev_acc100_version.map
> >>> +++ b/drivers/baseband/acc100/rte_pmd_bbdev_acc100_version.map
> >>> @@ -1,3 +1,10 @@
> >>>  DPDK_21 {
> >>>  	local: *;
> >>>  };
> >>> +
> >>> +EXPERIMENTAL {
> >>> +	global:
> >>> +
> >>> +	acc100_configure;
> >>> +
> >>> +};
> >>> --
> >>
> >> Ideally we should not need to have device specific APIs, but at least
> >> it should be prefixed with "rte_".
> >
> > Currently this is already like that for other bbdev PMDs.
> > So I would tend to prefer consistency over all in that context.
> > You could argue or not whether this is PMD function or a companion
> exposed function, but again if this should change it should change for all
> PMDs to avoid discrepencies.
> > If really this is deemed required this can be pushed as an extra patch
> covering all PMD, but probably not for 20.11.
> > What do you think?
> 
> Better to fix the API now to avoid namespace pollution, including the other
> comments I made regarding API on patch 3.
> That's not a big change, it can be done in v20.11 in my opinion.

ok fair enough, thanks

> 
> Thanks,
> Maxime
> 
> >>
> >> Regards,
> >> Maxime
> >
  
Maxime Coquelin Oct. 1, 2020, 9:44 p.m. UTC | #5
On 10/1/20 9:50 PM, Chautru, Nicolas wrote:
> Hi Maxime, 
> 
>> From: Maxime Coquelin <maxime.coquelin@redhat.com>
>> On 10/1/20 5:36 PM, Chautru, Nicolas wrote:
>>> Hi Maxime,
>>>> From: Maxime Coquelin <maxime.coquelin@redhat.com>
>>>> Hi Nicolas,
>>>>
>>>> On 10/1/20 5:14 AM, Nicolas Chautru wrote:
>>>>> diff --git
>>>>> a/drivers/baseband/acc100/rte_pmd_bbdev_acc100_version.map
>>>>> b/drivers/baseband/acc100/rte_pmd_bbdev_acc100_version.map
>>>>> index 4a76d1d..91c234d 100644
>>>>> --- a/drivers/baseband/acc100/rte_pmd_bbdev_acc100_version.map
>>>>> +++ b/drivers/baseband/acc100/rte_pmd_bbdev_acc100_version.map
>>>>> @@ -1,3 +1,10 @@
>>>>>  DPDK_21 {
>>>>>  	local: *;
>>>>>  };
>>>>> +
>>>>> +EXPERIMENTAL {
>>>>> +	global:
>>>>> +
>>>>> +	acc100_configure;
>>>>> +
>>>>> +};
>>>>> --
>>>>
>>>> Ideally we should not need to have device specific APIs, but at least
>>>> it should be prefixed with "rte_".
>>>
>>> Currently this is already like that for other bbdev PMDs.
>>> So I would tend to prefer consistency over all in that context.
>>> You could argue or not whether this is PMD function or a companion
>> exposed function, but again if this should change it should change for all
>> PMDs to avoid discrepencies.
>>> If really this is deemed required this can be pushed as an extra patch
>> covering all PMD, but probably not for 20.11.
>>> What do you think?
>>
>> Better to fix the API now to avoid namespace pollution, including the other
>> comments I made regarding API on patch 3.
>> That's not a big change, it can be done in v20.11 in my opinion.
> 
> ok fair enough, thanks

Thanks Nicolas!

I can send a patch tomorrow to fix the other baseband driver API, it
should not be an issue given it is experimental.

Maxime

>>
>> Thanks,
>> Maxime
>>
>>>>
>>>> Regards,
>>>> Maxime
>>>
>
  

Patch

diff --git a/app/test-bbdev/test_bbdev_perf.c b/app/test-bbdev/test_bbdev_perf.c
index 45c0d62..77903bd 100644
--- a/app/test-bbdev/test_bbdev_perf.c
+++ b/app/test-bbdev/test_bbdev_perf.c
@@ -52,6 +52,18 @@ 
 #define FLR_5G_TIMEOUT 610
 #endif
 
+#ifdef RTE_LIBRTE_PMD_BBDEV_ACC100
+#include <rte_acc100_cfg.h>
+#define ACC100PF_DRIVER_NAME   ("intel_acc100_pf")
+#define ACC100VF_DRIVER_NAME   ("intel_acc100_vf")
+#define ACC100_QMGR_NUM_AQS 16
+#define ACC100_QMGR_NUM_QGS 2
+#define ACC100_QMGR_AQ_DEPTH 5
+#define ACC100_QMGR_INVALID_IDX -1
+#define ACC100_QMGR_RR 1
+#define ACC100_QOS_GBR 0
+#endif
+
 #define OPS_CACHE_SIZE 256U
 #define OPS_POOL_SIZE_MIN 511U /* 0.5K per queue */
 
@@ -653,6 +665,65 @@  typedef int (test_case_function)(struct active_device *ad,
 				info->dev_name);
 	}
 #endif
+#ifdef RTE_LIBRTE_PMD_BBDEV_ACC100
+	if ((get_init_device() == true) &&
+		(!strcmp(info->drv.driver_name, ACC100PF_DRIVER_NAME))) {
+		struct acc100_conf conf;
+		unsigned int i;
+
+		printf("Configure ACC100 FEC Driver %s with default values\n",
+				info->drv.driver_name);
+
+		/* clear default configuration before initialization */
+		memset(&conf, 0, sizeof(struct acc100_conf));
+
+		/* Always set in PF mode for built-in configuration */
+		conf.pf_mode_en = true;
+		for (i = 0; i < RTE_ACC100_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;
+			conf.arb_ul_4g[i].gbr_threshold1 = ACC100_QOS_GBR;
+			conf.arb_ul_4g[i].gbr_threshold1 = ACC100_QOS_GBR;
+			conf.arb_ul_4g[i].round_robin_weight = ACC100_QMGR_RR;
+			conf.arb_dl_5g[i].gbr_threshold1 = ACC100_QOS_GBR;
+			conf.arb_dl_5g[i].gbr_threshold1 = ACC100_QOS_GBR;
+			conf.arb_dl_5g[i].round_robin_weight = ACC100_QMGR_RR;
+			conf.arb_ul_5g[i].gbr_threshold1 = ACC100_QOS_GBR;
+			conf.arb_ul_5g[i].gbr_threshold1 = ACC100_QOS_GBR;
+			conf.arb_ul_5g[i].round_robin_weight = ACC100_QMGR_RR;
+		}
+
+		conf.input_pos_llr_1_bit = true;
+		conf.output_pos_llr_1_bit = true;
+		conf.num_vf_bundles = 1; /**< Number of VF bundles to setup */
+
+		conf.q_ul_4g.num_qgroups = ACC100_QMGR_NUM_QGS;
+		conf.q_ul_4g.first_qgroup_index = ACC100_QMGR_INVALID_IDX;
+		conf.q_ul_4g.num_aqs_per_groups = ACC100_QMGR_NUM_AQS;
+		conf.q_ul_4g.aq_depth_log2 = ACC100_QMGR_AQ_DEPTH;
+		conf.q_dl_4g.num_qgroups = ACC100_QMGR_NUM_QGS;
+		conf.q_dl_4g.first_qgroup_index = ACC100_QMGR_INVALID_IDX;
+		conf.q_dl_4g.num_aqs_per_groups = ACC100_QMGR_NUM_AQS;
+		conf.q_dl_4g.aq_depth_log2 = ACC100_QMGR_AQ_DEPTH;
+		conf.q_ul_5g.num_qgroups = ACC100_QMGR_NUM_QGS;
+		conf.q_ul_5g.first_qgroup_index = ACC100_QMGR_INVALID_IDX;
+		conf.q_ul_5g.num_aqs_per_groups = ACC100_QMGR_NUM_AQS;
+		conf.q_ul_5g.aq_depth_log2 = ACC100_QMGR_AQ_DEPTH;
+		conf.q_dl_5g.num_qgroups = ACC100_QMGR_NUM_QGS;
+		conf.q_dl_5g.first_qgroup_index = ACC100_QMGR_INVALID_IDX;
+		conf.q_dl_5g.num_aqs_per_groups = ACC100_QMGR_NUM_AQS;
+		conf.q_dl_5g.aq_depth_log2 = ACC100_QMGR_AQ_DEPTH;
+
+		/* setup PF with configuration information */
+		ret = acc100_configure(info->dev_name, &conf);
+		TEST_ASSERT_SUCCESS(ret,
+				"Failed to configure ACC100 PF for bbdev %s",
+				info->dev_name);
+	}
+#endif
+	/* Let's refresh this now this is configured */
+	rte_bbdev_info_get(dev_id, info);
 	nb_queues = RTE_MIN(rte_lcore_count(), info->drv.max_num_queues);
 	nb_queues = RTE_MIN(nb_queues, (unsigned int) MAX_QUEUES);
 
diff --git a/doc/guides/rel_notes/release_20_11.rst b/doc/guides/rel_notes/release_20_11.rst
index 73ac08f..c8d0586 100644
--- a/doc/guides/rel_notes/release_20_11.rst
+++ b/doc/guides/rel_notes/release_20_11.rst
@@ -55,6 +55,11 @@  New Features
      Also, make sure to start the actual text at the margin.
      =======================================================
 
+* **Added Intel ACC100 bbdev PMD.**
+
+  Added a new ``acc100`` bbdev driver for the Intel\ |reg| ACC100 accelerator
+  also known as Mount Bryce.  See the
+  :doc:`../bbdevs/acc100` BBDEV guide for more details on this new driver.
 
 Removed Items
 -------------
diff --git a/drivers/baseband/acc100/meson.build b/drivers/baseband/acc100/meson.build
index 8afafc2..7ac44dc 100644
--- a/drivers/baseband/acc100/meson.build
+++ b/drivers/baseband/acc100/meson.build
@@ -4,3 +4,5 @@ 
 deps += ['bbdev', 'bus_vdev', 'ring', 'pci', 'bus_pci']
 
 sources = files('rte_acc100_pmd.c')
+
+install_headers('rte_acc100_cfg.h')
diff --git a/drivers/baseband/acc100/rte_acc100_cfg.h b/drivers/baseband/acc100/rte_acc100_cfg.h
index 73bbe36..7f523bc 100644
--- a/drivers/baseband/acc100/rte_acc100_cfg.h
+++ b/drivers/baseband/acc100/rte_acc100_cfg.h
@@ -89,6 +89,23 @@  struct acc100_conf {
 	struct rte_arbitration_t arb_dl_5g[RTE_ACC100_NUM_VFS];
 };
 
+/**
+ * Configure a ACC100 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 ACC100 HW.
+ *
+ * @return
+ *   Zero on success, negative value on failure.
+ */
+__rte_experimental
+int
+acc100_configure(const char *dev_name, struct acc100_conf *conf);
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/drivers/baseband/acc100/rte_acc100_pmd.c b/drivers/baseband/acc100/rte_acc100_pmd.c
index 4640b6e..8552694 100644
--- a/drivers/baseband/acc100/rte_acc100_pmd.c
+++ b/drivers/baseband/acc100/rte_acc100_pmd.c
@@ -38,10 +38,10 @@ 
 
 /* Write a register of a ACC100 device */
 static inline void
-acc100_reg_write(struct acc100_device *d, uint32_t offset, uint32_t payload)
+acc100_reg_write(struct acc100_device *d, uint32_t offset, uint32_t value)
 {
 	void *reg_addr = RTE_PTR_ADD(d->mmio_base, offset);
-	mmio_write(reg_addr, payload);
+	mmio_write(reg_addr, value);
 	usleep(ACC100_LONG_WAIT);
 }
 
@@ -85,6 +85,26 @@ 
 
 enum {UL_4G = 0, UL_5G, DL_4G, DL_5G, NUM_ACC};
 
+/* Return the accelerator enum for a Queue Group Index */
+static inline int
+accFromQgid(int qg_idx, const struct acc100_conf *acc100_conf)
+{
+	int accQg[ACC100_NUM_QGRPS];
+	int NumQGroupsPerFn[NUM_ACC];
+	int acc, qgIdx, qgIndex = 0;
+	for (qgIdx = 0; qgIdx < ACC100_NUM_QGRPS; qgIdx++)
+		accQg[qgIdx] = 0;
+	NumQGroupsPerFn[UL_4G] = acc100_conf->q_ul_4g.num_qgroups;
+	NumQGroupsPerFn[UL_5G] = acc100_conf->q_ul_5g.num_qgroups;
+	NumQGroupsPerFn[DL_4G] = acc100_conf->q_dl_4g.num_qgroups;
+	NumQGroupsPerFn[DL_5G] = acc100_conf->q_dl_5g.num_qgroups;
+	for (acc = UL_4G;  acc < NUM_ACC; acc++)
+		for (qgIdx = 0; qgIdx < NumQGroupsPerFn[acc]; qgIdx++)
+			accQg[qgIndex++] = acc;
+	acc = accQg[qg_idx];
+	return acc;
+}
+
 /* Return the queue topology for a Queue Group Index */
 static inline void
 qtopFromAcc(struct rte_q_topology_t **qtop, int acc_enum,
@@ -113,6 +133,30 @@ 
 	*qtop = p_qtop;
 }
 
+/* Return the AQ depth for a Queue Group Index */
+static inline int
+aqDepth(int qg_idx, struct acc100_conf *acc100_conf)
+{
+	struct rte_q_topology_t *q_top = NULL;
+	int acc_enum = accFromQgid(qg_idx, acc100_conf);
+	qtopFromAcc(&q_top, acc_enum, acc100_conf);
+	if (unlikely(q_top == NULL))
+		return 0;
+	return q_top->aq_depth_log2;
+}
+
+/* Return the AQ depth for a Queue Group Index */
+static inline int
+aqNum(int qg_idx, struct acc100_conf *acc100_conf)
+{
+	struct rte_q_topology_t *q_top = NULL;
+	int acc_enum = accFromQgid(qg_idx, acc100_conf);
+	qtopFromAcc(&q_top, acc_enum, acc100_conf);
+	if (unlikely(q_top == NULL))
+		return 0;
+	return q_top->num_aqs_per_groups;
+}
+
 static void
 initQTop(struct acc100_conf *acc100_conf)
 {
@@ -554,7 +598,7 @@ 
 static int
 acc100_setup_queues(struct rte_bbdev *dev, uint16_t num_queues, int socket_id)
 {
-	uint32_t phys_low, phys_high, payload;
+	uint32_t phys_low, phys_high, value;
 	struct acc100_device *d = dev->data->dev_private;
 	const struct acc100_registry_addr *reg_addr;
 	int ret;
@@ -613,8 +657,8 @@ 
 	 * Configure Ring Size to the max queue ring size
 	 * (used for wrapping purpose)
 	 */
-	payload = log2_basic(d->sw_ring_size / 64);
-	acc100_reg_write(d, reg_addr->ring_size, payload);
+	value = log2_basic(d->sw_ring_size / 64);
+	acc100_reg_write(d, reg_addr->ring_size, value);
 
 	/* Configure tail pointer for use when SDONE enabled */
 	d->tail_ptrs = rte_zmalloc_socket(
@@ -4216,3 +4260,472 @@  static int acc100_pci_remove(struct rte_pci_device *pci_dev)
 RTE_PMD_REGISTER_PCI_TABLE(ACC100PF_DRIVER_NAME, pci_id_acc100_pf_map);
 RTE_PMD_REGISTER_PCI(ACC100VF_DRIVER_NAME, acc100_pci_vf_driver);
 RTE_PMD_REGISTER_PCI_TABLE(ACC100VF_DRIVER_NAME, pci_id_acc100_vf_map);
+
+/*
+ * Implementation to fix the power on status of some 5GUL engines
+ * This requires DMA permission if ported outside DPDK
+ */
+static void
+poweron_cleanup(struct rte_bbdev *bbdev, struct acc100_device *d,
+		struct acc100_conf *conf)
+{
+	int i, template_idx, qg_idx;
+	uint32_t address, status, value;
+	printf("Need to clear power-on 5GUL status in internal memory\n");
+	/* Reset LDPC Cores */
+	for (i = 0; i < ACC100_ENGINES_MAX; i++)
+		acc100_reg_write(d, HWPfFecUl5gCntrlReg +
+				ACC100_ENGINE_OFFSET * i, ACC100_RESET_HI);
+	usleep(ACC100_LONG_WAIT);
+	for (i = 0; i < ACC100_ENGINES_MAX; i++)
+		acc100_reg_write(d, HWPfFecUl5gCntrlReg +
+				ACC100_ENGINE_OFFSET * i, ACC100_RESET_LO);
+	usleep(ACC100_LONG_WAIT);
+	/* Prepare dummy workload */
+	alloc_2x64mb_sw_rings_mem(bbdev, d, 0);
+	/* Set base addresses */
+	uint32_t phys_high = (uint32_t)(d->sw_rings_phys >> 32);
+	uint32_t phys_low  = (uint32_t)(d->sw_rings_phys &
+			~(ACC100_SIZE_64MBYTE-1));
+	acc100_reg_write(d, HWPfDmaFec5GulDescBaseHiRegVf, phys_high);
+	acc100_reg_write(d, HWPfDmaFec5GulDescBaseLoRegVf, phys_low);
+
+	/* Descriptor for a dummy 5GUL code block processing*/
+	union acc100_dma_desc *desc = NULL;
+	desc = d->sw_rings;
+	desc->req.data_ptrs[0].address = d->sw_rings_phys +
+			ACC100_DESC_FCW_OFFSET;
+	desc->req.data_ptrs[0].blen = ACC100_FCW_LD_BLEN;
+	desc->req.data_ptrs[0].blkid = ACC100_DMA_BLKID_FCW;
+	desc->req.data_ptrs[0].last = 0;
+	desc->req.data_ptrs[0].dma_ext = 0;
+	desc->req.data_ptrs[1].address = d->sw_rings_phys + 512;
+	desc->req.data_ptrs[1].blkid = ACC100_DMA_BLKID_IN;
+	desc->req.data_ptrs[1].last = 1;
+	desc->req.data_ptrs[1].dma_ext = 0;
+	desc->req.data_ptrs[1].blen = 44;
+	desc->req.data_ptrs[2].address = d->sw_rings_phys + 1024;
+	desc->req.data_ptrs[2].blkid = ACC100_DMA_BLKID_OUT_ENC;
+	desc->req.data_ptrs[2].last = 1;
+	desc->req.data_ptrs[2].dma_ext = 0;
+	desc->req.data_ptrs[2].blen = 5;
+	/* Dummy FCW */
+	desc->req.fcw_ld.FCWversion = ACC100_FCW_VER;
+	desc->req.fcw_ld.qm = 1;
+	desc->req.fcw_ld.nfiller = 30;
+	desc->req.fcw_ld.BG = 2 - 1;
+	desc->req.fcw_ld.Zc = 7;
+	desc->req.fcw_ld.ncb = 350;
+	desc->req.fcw_ld.rm_e = 4;
+	desc->req.fcw_ld.itmax = 10;
+	desc->req.fcw_ld.gain_i = 1;
+	desc->req.fcw_ld.gain_h = 1;
+
+	int engines_to_restart[ACC100_SIG_UL_5G_LAST + 1] = {0};
+	int num_failed_engine = 0;
+	/* Detect engines in undefined state */
+	for (template_idx = ACC100_SIG_UL_5G;
+			template_idx <= ACC100_SIG_UL_5G_LAST;
+			template_idx++) {
+		/* Check engine power-on status */
+		address = HwPfFecUl5gIbDebugReg +
+				ACC100_ENGINE_OFFSET * template_idx;
+		status = (acc100_reg_read(d, address) >> 4) & 0xF;
+		if (status == 0) {
+			engines_to_restart[num_failed_engine] = template_idx;
+			num_failed_engine++;
+		}
+	}
+
+	int numQqsAcc = conf->q_ul_5g.num_qgroups;
+	int numQgs = conf->q_ul_5g.num_qgroups;
+	value = 0;
+	for (qg_idx = numQqsAcc; qg_idx < (numQgs + numQqsAcc); qg_idx++)
+		value |= (1 << qg_idx);
+	/* Force each engine which is in unspecified state */
+	for (i = 0; i < num_failed_engine; i++) {
+		int failed_engine = engines_to_restart[i];
+		printf("Force engine %d\n", failed_engine);
+		for (template_idx = ACC100_SIG_UL_5G;
+				template_idx <= ACC100_SIG_UL_5G_LAST;
+				template_idx++) {
+			address = HWPfQmgrGrpTmplateReg4Indx
+					+ ACC100_BYTES_IN_WORD * template_idx;
+			if (template_idx == failed_engine)
+				acc100_reg_write(d, address, value);
+			else
+				acc100_reg_write(d, address, 0);
+		}
+		/* Reset descriptor header */
+		desc->req.word0 = ACC100_DMA_DESC_TYPE;
+		desc->req.word1 = 0;
+		desc->req.word2 = 0;
+		desc->req.word3 = 0;
+		desc->req.numCBs = 1;
+		desc->req.m2dlen = 2;
+		desc->req.d2mlen = 1;
+		/* Enqueue the code block for processing */
+		union acc100_enqueue_reg_fmt enq_req;
+		enq_req.val = 0;
+		enq_req.addr_offset = ACC100_DESC_OFFSET;
+		enq_req.num_elem = 1;
+		enq_req.req_elem_addr = 0;
+		rte_wmb();
+		acc100_reg_write(d, HWPfQmgrIngressAq + 0x100, enq_req.val);
+		usleep(ACC100_LONG_WAIT * 100);
+		if (desc->req.word0 != 2)
+			printf("DMA Response %#"PRIx32"\n", desc->req.word0);
+	}
+
+	/* Reset LDPC Cores */
+	for (i = 0; i < ACC100_ENGINES_MAX; i++)
+		acc100_reg_write(d, HWPfFecUl5gCntrlReg +
+				ACC100_ENGINE_OFFSET * i,
+				ACC100_RESET_HI);
+	usleep(ACC100_LONG_WAIT);
+	for (i = 0; i < ACC100_ENGINES_MAX; i++)
+		acc100_reg_write(d, HWPfFecUl5gCntrlReg +
+				ACC100_ENGINE_OFFSET * i,
+				ACC100_RESET_LO);
+	usleep(ACC100_LONG_WAIT);
+	acc100_reg_write(d, HWPfHi5GHardResetReg, ACC100_RESET_HARD);
+	usleep(ACC100_LONG_WAIT);
+	int numEngines = 0;
+	/* Check engine power-on status again */
+	for (template_idx = ACC100_SIG_UL_5G;
+			template_idx <= ACC100_SIG_UL_5G_LAST;
+			template_idx++) {
+		address = HwPfFecUl5gIbDebugReg +
+				ACC100_ENGINE_OFFSET * template_idx;
+		status = (acc100_reg_read(d, address) >> 4) & 0xF;
+		address = HWPfQmgrGrpTmplateReg4Indx
+				+ ACC100_BYTES_IN_WORD * template_idx;
+		if (status == 1) {
+			acc100_reg_write(d, address, value);
+			numEngines++;
+		} else
+			acc100_reg_write(d, address, 0);
+	}
+	printf("Number of 5GUL engines %d\n", numEngines);
+
+	if (d->sw_rings_base != NULL)
+		rte_free(d->sw_rings_base);
+	usleep(ACC100_LONG_WAIT);
+}
+
+/* Initial configuration of a ACC100 device prior to running configure() */
+int
+acc100_configure(const char *dev_name, struct acc100_conf *conf)
+{
+	rte_bbdev_log(INFO, "acc100_configure");
+	uint32_t value, address, status;
+	int qg_idx, template_idx, vf_idx, acc, i;
+	struct rte_bbdev *bbdev = rte_bbdev_get_named_dev(dev_name);
+
+	/* Compile time checks */
+	RTE_BUILD_BUG_ON(sizeof(struct acc100_dma_req_desc) != 256);
+	RTE_BUILD_BUG_ON(sizeof(union acc100_dma_desc) != 256);
+	RTE_BUILD_BUG_ON(sizeof(struct acc100_fcw_td) != 24);
+	RTE_BUILD_BUG_ON(sizeof(struct acc100_fcw_te) != 32);
+
+	if (bbdev == NULL) {
+		rte_bbdev_log(ERR,
+		"Invalid dev_name (%s), or device is not yet initialised",
+		dev_name);
+		return -ENODEV;
+	}
+	struct acc100_device *d = bbdev->data->dev_private;
+
+	/* Store configuration */
+	rte_memcpy(&d->acc100_conf, conf, sizeof(d->acc100_conf));
+
+	/* PCIe Bridge configuration */
+	acc100_reg_write(d, HwPfPcieGpexBridgeControl, ACC100_CFG_PCI_BRIDGE);
+	for (i = 1; i < ACC100_GPEX_AXIMAP_NUM; i++)
+		acc100_reg_write(d,
+				HwPfPcieGpexAxiAddrMappingWindowPexBaseHigh
+				+ i * 16, 0);
+
+	/* Prevent blocking AXI read on BRESP for AXI Write */
+	address = HwPfPcieGpexAxiPioControl;
+	value = ACC100_CFG_PCI_AXI;
+	acc100_reg_write(d, address, value);
+
+	/* 5GDL PLL phase shift */
+	acc100_reg_write(d, HWPfChaDl5gPllPhshft0, 0x1);
+
+	/* Explicitly releasing AXI as this may be stopped after PF FLR/BME */
+	address = HWPfDmaAxiControl;
+	value = 1;
+	acc100_reg_write(d, address, value);
+
+	/* DDR Configuration */
+	address = HWPfDdrBcTim6;
+	value = acc100_reg_read(d, address);
+	value &= 0xFFFFFFFB; /* Bit 2 */
+#ifdef ACC100_DDR_ECC_ENABLE
+	value |= 0x4;
+#endif
+	acc100_reg_write(d, address, value);
+	address = HWPfDdrPhyDqsCountNum;
+#ifdef ACC100_DDR_ECC_ENABLE
+	value = 9;
+#else
+	value = 8;
+#endif
+	acc100_reg_write(d, address, value);
+
+	/* Set default descriptor signature */
+	address = HWPfDmaDescriptorSignatuture;
+	value = 0;
+	acc100_reg_write(d, address, value);
+
+	/* Enable the Error Detection in DMA */
+	value = ACC100_CFG_DMA_ERROR;
+	address = HWPfDmaErrorDetectionEn;
+	acc100_reg_write(d, address, value);
+
+	/* AXI Cache configuration */
+	value = ACC100_CFG_AXI_CACHE;
+	address = HWPfDmaAxcacheReg;
+	acc100_reg_write(d, address, value);
+
+	/* Default DMA Configuration (Qmgr Enabled) */
+	address = HWPfDmaConfig0Reg;
+	value = 0;
+	acc100_reg_write(d, address, value);
+	address = HWPfDmaQmanen;
+	value = 0;
+	acc100_reg_write(d, address, value);
+
+	/* Default RLIM/ALEN configuration */
+	address = HWPfDmaConfig1Reg;
+	value = (1 << 31) + (23 << 8) + (1 << 6) + 7;
+	acc100_reg_write(d, address, value);
+
+	/* Configure DMA Qmanager addresses */
+	address = HWPfDmaQmgrAddrReg;
+	value = HWPfQmgrEgressQueuesTemplate;
+	acc100_reg_write(d, address, value);
+
+	/* ===== Qmgr Configuration ===== */
+	/* Configuration of the AQueue Depth QMGR_GRP_0_DEPTH_LOG2 for UL */
+	int totalQgs = conf->q_ul_4g.num_qgroups +
+			conf->q_ul_5g.num_qgroups +
+			conf->q_dl_4g.num_qgroups +
+			conf->q_dl_5g.num_qgroups;
+	for (qg_idx = 0; qg_idx < totalQgs; qg_idx++) {
+		address = HWPfQmgrDepthLog2Grp +
+		ACC100_BYTES_IN_WORD * qg_idx;
+		value = aqDepth(qg_idx, conf);
+		acc100_reg_write(d, address, value);
+		address = HWPfQmgrTholdGrp +
+		ACC100_BYTES_IN_WORD * qg_idx;
+		value = (1 << 16) + (1 << (aqDepth(qg_idx, conf) - 1));
+		acc100_reg_write(d, address, value);
+	}
+
+	/* Template Priority in incremental order */
+	for (template_idx = 0; template_idx < ACC100_NUM_TMPL;
+			template_idx++) {
+		address = HWPfQmgrGrpTmplateReg0Indx +
+		ACC100_BYTES_IN_WORD * (template_idx % 8);
+		value = ACC100_TMPL_PRI_0;
+		acc100_reg_write(d, address, value);
+		address = HWPfQmgrGrpTmplateReg1Indx +
+		ACC100_BYTES_IN_WORD * (template_idx % 8);
+		value = ACC100_TMPL_PRI_1;
+		acc100_reg_write(d, address, value);
+		address = HWPfQmgrGrpTmplateReg2indx +
+		ACC100_BYTES_IN_WORD * (template_idx % 8);
+		value = ACC100_TMPL_PRI_2;
+		acc100_reg_write(d, address, value);
+		address = HWPfQmgrGrpTmplateReg3Indx +
+		ACC100_BYTES_IN_WORD * (template_idx % 8);
+		value = ACC100_TMPL_PRI_3;
+		acc100_reg_write(d, address, value);
+	}
+
+	address = HWPfQmgrGrpPriority;
+	value = ACC100_CFG_QMGR_HI_P;
+	acc100_reg_write(d, address, value);
+
+	/* Template Configuration */
+	for (template_idx = 0; template_idx < ACC100_NUM_TMPL;
+			template_idx++) {
+		value = 0;
+		address = HWPfQmgrGrpTmplateReg4Indx
+				+ ACC100_BYTES_IN_WORD * template_idx;
+		acc100_reg_write(d, address, value);
+	}
+	/* 4GUL */
+	int numQgs = conf->q_ul_4g.num_qgroups;
+	int numQqsAcc = 0;
+	value = 0;
+	for (qg_idx = numQqsAcc; qg_idx < (numQgs + numQqsAcc); qg_idx++)
+		value |= (1 << qg_idx);
+	for (template_idx = ACC100_SIG_UL_4G;
+			template_idx <= ACC100_SIG_UL_4G_LAST;
+			template_idx++) {
+		address = HWPfQmgrGrpTmplateReg4Indx
+				+ ACC100_BYTES_IN_WORD * template_idx;
+		acc100_reg_write(d, address, value);
+	}
+	/* 5GUL */
+	numQqsAcc += numQgs;
+	numQgs	= conf->q_ul_5g.num_qgroups;
+	value = 0;
+	int numEngines = 0;
+	for (qg_idx = numQqsAcc; qg_idx < (numQgs + numQqsAcc); qg_idx++)
+		value |= (1 << qg_idx);
+	for (template_idx = ACC100_SIG_UL_5G;
+			template_idx <= ACC100_SIG_UL_5G_LAST;
+			template_idx++) {
+		/* Check engine power-on status */
+		address = HwPfFecUl5gIbDebugReg +
+				ACC100_ENGINE_OFFSET * template_idx;
+		status = (acc100_reg_read(d, address) >> 4) & 0xF;
+		address = HWPfQmgrGrpTmplateReg4Indx
+				+ ACC100_BYTES_IN_WORD * template_idx;
+		if (status == 1) {
+			acc100_reg_write(d, address, value);
+			numEngines++;
+		} else
+			acc100_reg_write(d, address, 0);
+#if RTE_ACC100_SINGLE_FEC == 1
+		value = 0;
+#endif
+	}
+	printf("Number of 5GUL engines %d\n", numEngines);
+	/* 4GDL */
+	numQqsAcc += numQgs;
+	numQgs	= conf->q_dl_4g.num_qgroups;
+	value = 0;
+	for (qg_idx = numQqsAcc; qg_idx < (numQgs + numQqsAcc); qg_idx++)
+		value |= (1 << qg_idx);
+	for (template_idx = ACC100_SIG_DL_4G;
+			template_idx <= ACC100_SIG_DL_4G_LAST;
+			template_idx++) {
+		address = HWPfQmgrGrpTmplateReg4Indx
+				+ ACC100_BYTES_IN_WORD * template_idx;
+		acc100_reg_write(d, address, value);
+#if RTE_ACC100_SINGLE_FEC == 1
+			value = 0;
+#endif
+	}
+	/* 5GDL */
+	numQqsAcc += numQgs;
+	numQgs	= conf->q_dl_5g.num_qgroups;
+	value = 0;
+	for (qg_idx = numQqsAcc; qg_idx < (numQgs + numQqsAcc); qg_idx++)
+		value |= (1 << qg_idx);
+	for (template_idx = ACC100_SIG_DL_5G;
+			template_idx <= ACC100_SIG_DL_5G_LAST;
+			template_idx++) {
+		address = HWPfQmgrGrpTmplateReg4Indx
+				+ ACC100_BYTES_IN_WORD * template_idx;
+		acc100_reg_write(d, address, value);
+#if RTE_ACC100_SINGLE_FEC == 1
+		value = 0;
+#endif
+	}
+
+	/* Queue Group Function mapping */
+	int qman_func_id[5] = {0, 2, 1, 3, 4};
+	address = HWPfQmgrGrpFunction0;
+	value = 0;
+	for (qg_idx = 0; qg_idx < 8; qg_idx++) {
+		acc = accFromQgid(qg_idx, conf);
+		value |= qman_func_id[acc]<<(qg_idx * 4);
+	}
+	acc100_reg_write(d, address, value);
+
+	/* Configuration of the Arbitration QGroup depth to 1 */
+	for (qg_idx = 0; qg_idx < totalQgs; qg_idx++) {
+		address = HWPfQmgrArbQDepthGrp +
+		ACC100_BYTES_IN_WORD * qg_idx;
+		value = 0;
+		acc100_reg_write(d, address, value);
+	}
+
+	/* Enabling AQueues through the Queue hierarchy*/
+	for (vf_idx = 0; vf_idx < ACC100_NUM_VFS; vf_idx++) {
+		for (qg_idx = 0; qg_idx < ACC100_NUM_QGRPS; qg_idx++) {
+			value = 0;
+			if (vf_idx < conf->num_vf_bundles &&
+					qg_idx < totalQgs)
+				value = (1 << aqNum(qg_idx, conf)) - 1;
+			address = HWPfQmgrAqEnableVf
+					+ vf_idx * ACC100_BYTES_IN_WORD;
+			value += (qg_idx << 16);
+			acc100_reg_write(d, address, value);
+		}
+	}
+
+	/* This pointer to ARAM (256kB) is shifted by 2 (4B per register) */
+	uint32_t aram_address = 0;
+	for (qg_idx = 0; qg_idx < totalQgs; qg_idx++) {
+		for (vf_idx = 0; vf_idx < conf->num_vf_bundles; vf_idx++) {
+			address = HWPfQmgrVfBaseAddr + vf_idx
+					* ACC100_BYTES_IN_WORD + qg_idx
+					* ACC100_BYTES_IN_WORD * 64;
+			value = aram_address;
+			acc100_reg_write(d, address, value);
+			/* Offset ARAM Address for next memory bank
+			 * - increment of 4B
+			 */
+			aram_address += aqNum(qg_idx, conf) *
+					(1 << aqDepth(qg_idx, conf));
+		}
+	}
+
+	if (aram_address > ACC100_WORDS_IN_ARAM_SIZE) {
+		rte_bbdev_log(ERR, "ARAM Configuration not fitting %d %d\n",
+				aram_address, ACC100_WORDS_IN_ARAM_SIZE);
+		return -EINVAL;
+	}
+
+	/* ==== HI Configuration ==== */
+
+	/* Prevent Block on Transmit Error */
+	address = HWPfHiBlockTransmitOnErrorEn;
+	value = 0;
+	acc100_reg_write(d, address, value);
+	/* Prevents to drop MSI */
+	address = HWPfHiMsiDropEnableReg;
+	value = 0;
+	acc100_reg_write(d, address, value);
+	/* Set the PF Mode register */
+	address = HWPfHiPfMode;
+	value = (conf->pf_mode_en) ? ACC100_PF_VAL : 0;
+	acc100_reg_write(d, address, value);
+	/* Enable Error Detection in HW */
+	address = HWPfDmaErrorDetectionEn;
+	value = 0x3D7;
+	acc100_reg_write(d, address, value);
+
+	/* QoS overflow init */
+	value = 1;
+	address = HWPfQosmonAEvalOverflow0;
+	acc100_reg_write(d, address, value);
+	address = HWPfQosmonBEvalOverflow0;
+	acc100_reg_write(d, address, value);
+
+	/* HARQ DDR Configuration */
+	unsigned int ddrSizeInMb = 512; /* Fixed to 512 MB per VF for now */
+	for (vf_idx = 0; vf_idx < conf->num_vf_bundles; vf_idx++) {
+		address = HWPfDmaVfDdrBaseRw + vf_idx
+				* 0x10;
+		value = ((vf_idx * (ddrSizeInMb / 64)) << 16) +
+				(ddrSizeInMb - 1);
+		acc100_reg_write(d, address, value);
+	}
+	usleep(ACC100_LONG_WAIT);
+
+	/* Workaround in case some 5GUL engines are in an unexpected state */
+	if (numEngines < (ACC100_SIG_UL_5G_LAST + 1))
+		poweron_cleanup(bbdev, d, conf);
+
+	rte_bbdev_log_debug("PF Tip configuration complete for %s", dev_name);
+	return 0;
+}
diff --git a/drivers/baseband/acc100/rte_acc100_pmd.h b/drivers/baseband/acc100/rte_acc100_pmd.h
index a61cc71..2acfd10 100644
--- a/drivers/baseband/acc100/rte_acc100_pmd.h
+++ b/drivers/baseband/acc100/rte_acc100_pmd.h
@@ -158,6 +158,7 @@ 
 #define ACC100_RESET_HARD       0x1FF
 #define ACC100_ENGINES_MAX      9
 #define ACC100_LONG_WAIT        1000
+#define ACC100_GPEX_AXIMAP_NUM  17
 
 /* ACC100 DMA Descriptor triplet */
 struct acc100_dma_triplet {
diff --git a/drivers/baseband/acc100/rte_pmd_bbdev_acc100_version.map b/drivers/baseband/acc100/rte_pmd_bbdev_acc100_version.map
index 4a76d1d..91c234d 100644
--- a/drivers/baseband/acc100/rte_pmd_bbdev_acc100_version.map
+++ b/drivers/baseband/acc100/rte_pmd_bbdev_acc100_version.map
@@ -1,3 +1,10 @@ 
 DPDK_21 {
 	local: *;
 };
+
+EXPERIMENTAL {
+	global:
+
+	acc100_configure;
+
+};