[v1,1/2] bbdev: add new function to dump debug information

Message ID 20240701223424.427588-2-nicolas.chautru@intel.com (mailing list archive)
State Superseded
Delegated to: Maxime Coquelin
Headers
Series bbdev: dump debug information |

Checks

Context Check Description
ci/checkpatch warning coding style issues

Commit Message

Nicolas Chautru July 1, 2024, 10:34 p.m. UTC
This provides a new API to dump more debug information
related to the status on a given bbdev queue.
Some of this information is visible at bbdev level.
This also provides a new option dev op, to print more
information at the lower PMD level.
This helps user to troubleshoot issues related to
previous operations provided into a queue causing
possible hard-to-debug negative scenarios.

Signed-off-by: Nicolas Chautru <nicolas.chautru@intel.com>
---
 lib/bbdev/rte_bbdev.c     | 214 ++++++++++++++++++++++++++++++++++++++
 lib/bbdev/rte_bbdev.h     |  41 ++++++++
 lib/bbdev/rte_bbdev_pmd.h |   9 ++
 lib/bbdev/version.map     |   4 +
 4 files changed, 268 insertions(+)
  

Comments

Hemant Agrawal July 2, 2024, 10:53 a.m. UTC | #1
Hi Nicolas,

     Few comments inline.

On 02-07-2024 04:04, Nicolas Chautru wrote:
> This provides a new API to dump more debug information
> related to the status on a given bbdev queue.
> Some of this information is visible at bbdev level.
> This also provides a new option dev op, to print more
> information at the lower PMD level.
> This helps user to troubleshoot issues related to
> previous operations provided into a queue causing
> possible hard-to-debug negative scenarios.
>
> Signed-off-by: Nicolas Chautru <nicolas.chautru@intel.com>
> ---
>   lib/bbdev/rte_bbdev.c     | 214 ++++++++++++++++++++++++++++++++++++++
>   lib/bbdev/rte_bbdev.h     |  41 ++++++++
>   lib/bbdev/rte_bbdev_pmd.h |   9 ++
>   lib/bbdev/version.map     |   4 +
>   4 files changed, 268 insertions(+)
>
> diff --git a/lib/bbdev/rte_bbdev.c b/lib/bbdev/rte_bbdev.c
> index 13bde3c25b..81c031fc09 100644
> --- a/lib/bbdev/rte_bbdev.c
> +++ b/lib/bbdev/rte_bbdev.c
> @@ -1190,3 +1190,217 @@ rte_bbdev_enqueue_status_str(enum rte_bbdev_enqueue_status status)
>   	rte_bbdev_log(ERR, "Invalid enqueue status");
>   	return NULL;
>   }
> +
> +
> +int
> +rte_bbdev_queue_ops_dump(uint16_t dev_id, uint16_t queue_id, FILE *f)
> +{
> +	struct rte_bbdev_queue_data *q_data;
> +	struct rte_bbdev_stats *stats;
> +	uint16_t i;
> +	struct rte_bbdev *dev = get_dev(dev_id);
> +
> +	VALID_DEV_OR_RET_ERR(dev, dev_id);
> +	VALID_QUEUE_OR_RET_ERR(queue_id, dev);
> +	VALID_DEV_OPS_OR_RET_ERR(dev, dev_id);
> +	VALID_FUNC_OR_RET_ERR(dev->dev_ops->queue_ops_dump, dev_id);
> +
> +	q_data = &dev->data->queues[queue_id];
> +
> +	if (f == NULL)
> +		return -EINVAL;
> +
> +	fprintf(f, "Dump of operations on %s queue %d\n",
> +			dev->data->name, queue_id);
> +	fprintf(f, "  Last Enqueue Status %s\n",
> +			rte_bbdev_enqueue_status_str(q_data->enqueue_status));
> +	for (i = 0; i < 4; i++)

It shall be RTE_BBDEV_ENQ_STATUS_SIZE_MAX instead of 4 ?


> +		if (q_data->queue_stats.enqueue_status_count[i] > 0)
> +			fprintf(f, "  Enqueue Status Counters %s %" PRIu64 "\n",
> +					rte_bbdev_enqueue_status_str(i),
> +					q_data->queue_stats.enqueue_status_count[i]);
> +	stats = &dev->data->queues[queue_id].queue_stats;
> +
> +	fprintf(f, "  Enqueue Count %" PRIu64 " Warning %" PRIu64 " Error %" PRIu64 "\n",
> +			stats->enqueued_count, stats->enqueue_warn_count,
> +			stats->enqueue_err_count);
> +	fprintf(f, "  Dequeue Count %" PRIu64 " Warning %" PRIu64 " Error %" PRIu64 "\n",
> +			stats->dequeued_count, stats->dequeue_warn_count,
> +			stats->dequeue_err_count);
> +
why not print acc_offload_cycles aas well?
> +	return dev->dev_ops->queue_ops_dump(dev, queue_id, f);
> +}
> +
> +char *
> +rte_bbdev_ops_param_string(void *op, enum rte_bbdev_op_type op_type)
> +{
> +	static char str[1024];
> +	static char partial[1024];
> +	struct rte_bbdev_dec_op *op_dec;
> +	struct rte_bbdev_enc_op *op_enc;
> +	struct rte_bbdev_fft_op *op_fft;
> +	struct rte_bbdev_mldts_op *op_mldts;
> +
> +	rte_iova_t add0 = 0, add1 = 0, add2 = 0, add3 = 0, add4 = 0;
> +
> +	if (op == NULL) {
> +		snprintf(str, sizeof(str), "Invalid Operation pointer\n");
> +		return str;
> +	}
> +
how about also covering mempool and opaque_data pointer - they may also 
be helpful in debugging?
  
Nicolas Chautru July 2, 2024, 6:55 p.m. UTC | #2
Hi Hemant, 

> -----Original Message-----
> From: Hemant Agrawal <hemant.agrawal@oss.nxp.com>
> Sent: Tuesday, July 2, 2024 3:54 AM
> To: Chautru, Nicolas <nicolas.chautru@intel.com>; dev@dpdk.org;
> maxime.coquelin@redhat.com
> Cc: hemant.agrawal@nxp.com; Marchand, David
> <david.marchand@redhat.com>; Vargas, Hernan
> <hernan.vargas@intel.com>
> Subject: Re: [PATCH v1 1/2] bbdev: add new function to dump debug
> information
> 
> Hi Nicolas,
> 
>      Few comments inline.
> 
> On 02-07-2024 04:04, Nicolas Chautru wrote:
> > This provides a new API to dump more debug information related to the
> > status on a given bbdev queue.
> > Some of this information is visible at bbdev level.
> > This also provides a new option dev op, to print more information at
> > the lower PMD level.
> > This helps user to troubleshoot issues related to previous operations
> > provided into a queue causing possible hard-to-debug negative
> > scenarios.
> >
> > Signed-off-by: Nicolas Chautru <nicolas.chautru@intel.com>
> > ---
> >   lib/bbdev/rte_bbdev.c     | 214
> ++++++++++++++++++++++++++++++++++++++
> >   lib/bbdev/rte_bbdev.h     |  41 ++++++++
> >   lib/bbdev/rte_bbdev_pmd.h |   9 ++
> >   lib/bbdev/version.map     |   4 +
> >   4 files changed, 268 insertions(+)
> >
> > diff --git a/lib/bbdev/rte_bbdev.c b/lib/bbdev/rte_bbdev.c index
> > 13bde3c25b..81c031fc09 100644
> > --- a/lib/bbdev/rte_bbdev.c
> > +++ b/lib/bbdev/rte_bbdev.c
> > @@ -1190,3 +1190,217 @@ rte_bbdev_enqueue_status_str(enum
> rte_bbdev_enqueue_status status)
> >   	rte_bbdev_log(ERR, "Invalid enqueue status");
> >   	return NULL;
> >   }
> > +
> > +
> > +int
> > +rte_bbdev_queue_ops_dump(uint16_t dev_id, uint16_t queue_id, FILE
> *f)
> > +{
> > +	struct rte_bbdev_queue_data *q_data;
> > +	struct rte_bbdev_stats *stats;
> > +	uint16_t i;
> > +	struct rte_bbdev *dev = get_dev(dev_id);
> > +
> > +	VALID_DEV_OR_RET_ERR(dev, dev_id);
> > +	VALID_QUEUE_OR_RET_ERR(queue_id, dev);
> > +	VALID_DEV_OPS_OR_RET_ERR(dev, dev_id);
> > +	VALID_FUNC_OR_RET_ERR(dev->dev_ops->queue_ops_dump,
> dev_id);
> > +
> > +	q_data = &dev->data->queues[queue_id];
> > +
> > +	if (f == NULL)
> > +		return -EINVAL;
> > +
> > +	fprintf(f, "Dump of operations on %s queue %d\n",
> > +			dev->data->name, queue_id);
> > +	fprintf(f, "  Last Enqueue Status %s\n",
> > +			rte_bbdev_enqueue_status_str(q_data-
> >enqueue_status));
> > +	for (i = 0; i < 4; i++)
> 
> It shall be RTE_BBDEV_ENQ_STATUS_SIZE_MAX instead of 4 ?

Thanks, I can update this in the v2.

> 
> 
> > +		if (q_data->queue_stats.enqueue_status_count[i] > 0)
> > +			fprintf(f, "  Enqueue Status Counters %s %" PRIu64
> "\n",
> > +					rte_bbdev_enqueue_status_str(i),
> > +					q_data-
> >queue_stats.enqueue_status_count[i]);
> > +	stats = &dev->data->queues[queue_id].queue_stats;
> > +
> > +	fprintf(f, "  Enqueue Count %" PRIu64 " Warning %" PRIu64 " Error %"
> PRIu64 "\n",
> > +			stats->enqueued_count, stats-
> >enqueue_warn_count,
> > +			stats->enqueue_err_count);
> > +	fprintf(f, "  Dequeue Count %" PRIu64 " Warning %" PRIu64 " Error %"
> PRIu64 "\n",
> > +			stats->dequeued_count, stats-
> >dequeue_warn_count,
> > +			stats->dequeue_err_count);
> > +
> why not print acc_offload_cycles aas well?

I don’t personally find them necessarily useful for this kind. 
But still if you believe these might help sometimes, no problem I can add them in the v2. Kindly confirm your preference. 

> > +	return dev->dev_ops->queue_ops_dump(dev, queue_id, f); }
> > +
> > +char *
> > +rte_bbdev_ops_param_string(void *op, enum rte_bbdev_op_type
> op_type)
> > +{
> > +	static char str[1024];
> > +	static char partial[1024];
> > +	struct rte_bbdev_dec_op *op_dec;
> > +	struct rte_bbdev_enc_op *op_enc;
> > +	struct rte_bbdev_fft_op *op_fft;
> > +	struct rte_bbdev_mldts_op *op_mldts;
> > +
> > +	rte_iova_t add0 = 0, add1 = 0, add2 = 0, add3 = 0, add4 = 0;
> > +
> > +	if (op == NULL) {
> > +		snprintf(str, sizeof(str), "Invalid Operation pointer\n");
> > +		return str;
> > +	}
> > +
> how about also covering mempool and opaque_data pointer - they may also
> be helpful in debugging?

What have got in mind specifically?
Note that underlying memory may not always trace to actual mempool (due to signal processing sizes not always fitting with mbuf size requirements, some mbuf are sometimes indirectly constructed).
Any specific suggestion welcome though.


Thanks, 
Nic
  
Hemant Agrawal July 3, 2024, 4:24 a.m. UTC | #3
On 03-07-2024 00:25, Chautru, Nicolas wrote:
> Hi Hemant,
>
>> -----Original Message-----
>> From: Hemant Agrawal <hemant.agrawal@oss.nxp.com>
>> Sent: Tuesday, July 2, 2024 3:54 AM
>> To: Chautru, Nicolas <nicolas.chautru@intel.com>; dev@dpdk.org;
>> maxime.coquelin@redhat.com
>> Cc: hemant.agrawal@nxp.com; Marchand, David
>> <david.marchand@redhat.com>; Vargas, Hernan
>> <hernan.vargas@intel.com>
>> Subject: Re: [PATCH v1 1/2] bbdev: add new function to dump debug
>> information
>>
>> Hi Nicolas,
>>
>>       Few comments inline.
>>
>> On 02-07-2024 04:04, Nicolas Chautru wrote:
>>> This provides a new API to dump more debug information related to the
>>> status on a given bbdev queue.
>>> Some of this information is visible at bbdev level.
>>> This also provides a new option dev op, to print more information at
>>> the lower PMD level.
>>> This helps user to troubleshoot issues related to previous operations
>>> provided into a queue causing possible hard-to-debug negative
>>> scenarios.
>>>
>>> Signed-off-by: Nicolas Chautru <nicolas.chautru@intel.com>
>>> ---
>>>    lib/bbdev/rte_bbdev.c     | 214
>> ++++++++++++++++++++++++++++++++++++++
>>>    lib/bbdev/rte_bbdev.h     |  41 ++++++++
>>>    lib/bbdev/rte_bbdev_pmd.h |   9 ++
>>>    lib/bbdev/version.map     |   4 +
>>>    4 files changed, 268 insertions(+)
>>>
>>> diff --git a/lib/bbdev/rte_bbdev.c b/lib/bbdev/rte_bbdev.c index
>>> 13bde3c25b..81c031fc09 100644
>>> --- a/lib/bbdev/rte_bbdev.c
>>> +++ b/lib/bbdev/rte_bbdev.c
>>> @@ -1190,3 +1190,217 @@ rte_bbdev_enqueue_status_str(enum
>> rte_bbdev_enqueue_status status)
>>>    	rte_bbdev_log(ERR, "Invalid enqueue status");
>>>    	return NULL;
>>>    }
>>> +
>>> +
>>> +int
>>> +rte_bbdev_queue_ops_dump(uint16_t dev_id, uint16_t queue_id, FILE
>> *f)
>>> +{
>>> +	struct rte_bbdev_queue_data *q_data;
>>> +	struct rte_bbdev_stats *stats;
>>> +	uint16_t i;
>>> +	struct rte_bbdev *dev = get_dev(dev_id);
>>> +
>>> +	VALID_DEV_OR_RET_ERR(dev, dev_id);
>>> +	VALID_QUEUE_OR_RET_ERR(queue_id, dev);
>>> +	VALID_DEV_OPS_OR_RET_ERR(dev, dev_id);
>>> +	VALID_FUNC_OR_RET_ERR(dev->dev_ops->queue_ops_dump,
>> dev_id);
>>> +
>>> +	q_data = &dev->data->queues[queue_id];
>>> +
>>> +	if (f == NULL)
>>> +		return -EINVAL;
>>> +
>>> +	fprintf(f, "Dump of operations on %s queue %d\n",
>>> +			dev->data->name, queue_id);
>>> +	fprintf(f, "  Last Enqueue Status %s\n",
>>> +			rte_bbdev_enqueue_status_str(q_data-
>>> enqueue_status));
>>> +	for (i = 0; i < 4; i++)
>> It shall be RTE_BBDEV_ENQ_STATUS_SIZE_MAX instead of 4 ?
> Thanks, I can update this in the v2.
>
>>
>>> +		if (q_data->queue_stats.enqueue_status_count[i] > 0)
>>> +			fprintf(f, "  Enqueue Status Counters %s %" PRIu64
>> "\n",
>>> +					rte_bbdev_enqueue_status_str(i),
>>> +					q_data-
>>> queue_stats.enqueue_status_count[i]);
>>> +	stats = &dev->data->queues[queue_id].queue_stats;
>>> +
>>> +	fprintf(f, "  Enqueue Count %" PRIu64 " Warning %" PRIu64 " Error %"
>> PRIu64 "\n",
>>> +			stats->enqueued_count, stats-
>>> enqueue_warn_count,
>>> +			stats->enqueue_err_count);
>>> +	fprintf(f, "  Dequeue Count %" PRIu64 " Warning %" PRIu64 " Error %"
>> PRIu64 "\n",
>>> +			stats->dequeued_count, stats-
>>> dequeue_warn_count,
>>> +			stats->dequeue_err_count);
>>> +
>> why not print acc_offload_cycles aas well?
> I don’t personally find them necessarily useful for this kind.
> But still if you believe these might help sometimes, no problem I can add them in the v2. Kindly confirm your preference.
This is the only remaining element in the structure not getting dumped. 
If you think, it is not useful at all - you may leave it.
>
>>> +	return dev->dev_ops->queue_ops_dump(dev, queue_id, f); }
>>> +
>>> +char *
>>> +rte_bbdev_ops_param_string(void *op, enum rte_bbdev_op_type
>> op_type)
>>> +{
>>> +	static char str[1024];
>>> +	static char partial[1024];
>>> +	struct rte_bbdev_dec_op *op_dec;
>>> +	struct rte_bbdev_enc_op *op_enc;
>>> +	struct rte_bbdev_fft_op *op_fft;
>>> +	struct rte_bbdev_mldts_op *op_mldts;
>>> +
>>> +	rte_iova_t add0 = 0, add1 = 0, add2 = 0, add3 = 0, add4 = 0;
>>> +
>>> +	if (op == NULL) {
>>> +		snprintf(str, sizeof(str), "Invalid Operation pointer\n");
>>> +		return str;
>>> +	}
>>> +
>> how about also covering mempool and opaque_data pointer - they may also
>> be helpful in debugging?
> What have got in mind specifically?
> Note that underlying memory may not always trace to actual mempool (due to signal processing sizes not always fitting with mbuf size requirements, some mbuf are sometimes indirectly constructed).
> Any specific suggestion welcome though.

Yes, It is understood that underlying mbufs may not belong to this 
mempool .  However, being a library function the underlying PMD 
implementations may be different.  I see no harm in to dump most/all of 
the elements, they may be helpful in debugging.



>
>
> Thanks,
> Nic
>
  
Maxime Coquelin Aug. 29, 2024, 8:08 a.m. UTC | #4
On 7/2/24 20:55, Chautru, Nicolas wrote:
> Hi Hemant,
> 
>> -----Original Message-----
>> From: Hemant Agrawal <hemant.agrawal@oss.nxp.com>
>> Sent: Tuesday, July 2, 2024 3:54 AM
>> To: Chautru, Nicolas <nicolas.chautru@intel.com>; dev@dpdk.org;
>> maxime.coquelin@redhat.com
>> Cc: hemant.agrawal@nxp.com; Marchand, David
>> <david.marchand@redhat.com>; Vargas, Hernan
>> <hernan.vargas@intel.com>
>> Subject: Re: [PATCH v1 1/2] bbdev: add new function to dump debug
>> information
>>
>> Hi Nicolas,
>>
>>       Few comments inline.
>>
>> On 02-07-2024 04:04, Nicolas Chautru wrote:
>>> This provides a new API to dump more debug information related to the
>>> status on a given bbdev queue.
>>> Some of this information is visible at bbdev level.
>>> This also provides a new option dev op, to print more information at
>>> the lower PMD level.
>>> This helps user to troubleshoot issues related to previous operations
>>> provided into a queue causing possible hard-to-debug negative
>>> scenarios.
>>>
>>> Signed-off-by: Nicolas Chautru <nicolas.chautru@intel.com>
>>> ---
>>>    lib/bbdev/rte_bbdev.c     | 214
>> ++++++++++++++++++++++++++++++++++++++
>>>    lib/bbdev/rte_bbdev.h     |  41 ++++++++
>>>    lib/bbdev/rte_bbdev_pmd.h |   9 ++
>>>    lib/bbdev/version.map     |   4 +
>>>    4 files changed, 268 insertions(+)
>>>
>>> diff --git a/lib/bbdev/rte_bbdev.c b/lib/bbdev/rte_bbdev.c index
>>> 13bde3c25b..81c031fc09 100644
>>> --- a/lib/bbdev/rte_bbdev.c
>>> +++ b/lib/bbdev/rte_bbdev.c
>>> @@ -1190,3 +1190,217 @@ rte_bbdev_enqueue_status_str(enum
>> rte_bbdev_enqueue_status status)
>>>    	rte_bbdev_log(ERR, "Invalid enqueue status");
>>>    	return NULL;
>>>    }
>>> +
>>> +
>>> +int
>>> +rte_bbdev_queue_ops_dump(uint16_t dev_id, uint16_t queue_id, FILE
>> *f)
>>> +{
>>> +	struct rte_bbdev_queue_data *q_data;
>>> +	struct rte_bbdev_stats *stats;
>>> +	uint16_t i;
>>> +	struct rte_bbdev *dev = get_dev(dev_id);
>>> +
>>> +	VALID_DEV_OR_RET_ERR(dev, dev_id);
>>> +	VALID_QUEUE_OR_RET_ERR(queue_id, dev);
>>> +	VALID_DEV_OPS_OR_RET_ERR(dev, dev_id);
>>> +	VALID_FUNC_OR_RET_ERR(dev->dev_ops->queue_ops_dump,
>> dev_id);
>>> +
>>> +	q_data = &dev->data->queues[queue_id];
>>> +
>>> +	if (f == NULL)
>>> +		return -EINVAL;
>>> +
>>> +	fprintf(f, "Dump of operations on %s queue %d\n",
>>> +			dev->data->name, queue_id);
>>> +	fprintf(f, "  Last Enqueue Status %s\n",
>>> +			rte_bbdev_enqueue_status_str(q_data-
>>> enqueue_status));
>>> +	for (i = 0; i < 4; i++)
>>
>> It shall be RTE_BBDEV_ENQ_STATUS_SIZE_MAX instead of 4 ?
> 
> Thanks, I can update this in the v2.
> 

Hi Nicolas,

could you please send a v2 addressing Hemant's comments?

Thanks,
Maxime
  

Patch

diff --git a/lib/bbdev/rte_bbdev.c b/lib/bbdev/rte_bbdev.c
index 13bde3c25b..81c031fc09 100644
--- a/lib/bbdev/rte_bbdev.c
+++ b/lib/bbdev/rte_bbdev.c
@@ -1190,3 +1190,217 @@  rte_bbdev_enqueue_status_str(enum rte_bbdev_enqueue_status status)
 	rte_bbdev_log(ERR, "Invalid enqueue status");
 	return NULL;
 }
+
+
+int
+rte_bbdev_queue_ops_dump(uint16_t dev_id, uint16_t queue_id, FILE *f)
+{
+	struct rte_bbdev_queue_data *q_data;
+	struct rte_bbdev_stats *stats;
+	uint16_t i;
+	struct rte_bbdev *dev = get_dev(dev_id);
+
+	VALID_DEV_OR_RET_ERR(dev, dev_id);
+	VALID_QUEUE_OR_RET_ERR(queue_id, dev);
+	VALID_DEV_OPS_OR_RET_ERR(dev, dev_id);
+	VALID_FUNC_OR_RET_ERR(dev->dev_ops->queue_ops_dump, dev_id);
+
+	q_data = &dev->data->queues[queue_id];
+
+	if (f == NULL)
+		return -EINVAL;
+
+	fprintf(f, "Dump of operations on %s queue %d\n",
+			dev->data->name, queue_id);
+	fprintf(f, "  Last Enqueue Status %s\n",
+			rte_bbdev_enqueue_status_str(q_data->enqueue_status));
+	for (i = 0; i < 4; i++)
+		if (q_data->queue_stats.enqueue_status_count[i] > 0)
+			fprintf(f, "  Enqueue Status Counters %s %" PRIu64 "\n",
+					rte_bbdev_enqueue_status_str(i),
+					q_data->queue_stats.enqueue_status_count[i]);
+	stats = &dev->data->queues[queue_id].queue_stats;
+
+	fprintf(f, "  Enqueue Count %" PRIu64 " Warning %" PRIu64 " Error %" PRIu64 "\n",
+			stats->enqueued_count, stats->enqueue_warn_count,
+			stats->enqueue_err_count);
+	fprintf(f, "  Dequeue Count %" PRIu64 " Warning %" PRIu64 " Error %" PRIu64 "\n",
+			stats->dequeued_count, stats->dequeue_warn_count,
+			stats->dequeue_err_count);
+
+	return dev->dev_ops->queue_ops_dump(dev, queue_id, f);
+}
+
+char *
+rte_bbdev_ops_param_string(void *op, enum rte_bbdev_op_type op_type)
+{
+	static char str[1024];
+	static char partial[1024];
+	struct rte_bbdev_dec_op *op_dec;
+	struct rte_bbdev_enc_op *op_enc;
+	struct rte_bbdev_fft_op *op_fft;
+	struct rte_bbdev_mldts_op *op_mldts;
+
+	rte_iova_t add0 = 0, add1 = 0, add2 = 0, add3 = 0, add4 = 0;
+
+	if (op == NULL) {
+		snprintf(str, sizeof(str), "Invalid Operation pointer\n");
+		return str;
+	}
+
+	if (op_type == RTE_BBDEV_OP_LDPC_DEC) {
+		op_dec = op;
+		if (op_dec->ldpc_dec.code_block_mode == RTE_BBDEV_TRANSPORT_BLOCK)
+			snprintf(partial, sizeof(partial), "C %d Cab %d Ea %d Eb %d r %d",
+					op_dec->ldpc_dec.tb_params.c,
+					op_dec->ldpc_dec.tb_params.cab,
+					op_dec->ldpc_dec.tb_params.ea,
+					op_dec->ldpc_dec.tb_params.eb,
+					op_dec->ldpc_dec.tb_params.r);
+		else
+			snprintf(partial, sizeof(partial), "E %d", op_dec->ldpc_dec.cb_params.e);
+		if (op_dec->ldpc_dec.input.data != NULL)
+			add0 = rte_pktmbuf_iova_offset(op_dec->ldpc_dec.input.data, 0);
+		if (op_dec->ldpc_dec.hard_output.data != NULL)
+			add1 = rte_pktmbuf_iova_offset(op_dec->ldpc_dec.hard_output.data, 0);
+		if (op_dec->ldpc_dec.soft_output.data != NULL)
+			add2 = rte_pktmbuf_iova_offset(op_dec->ldpc_dec.soft_output.data, 0);
+		if (op_dec->ldpc_dec.harq_combined_input.data != NULL)
+			add3 = rte_pktmbuf_iova_offset(op_dec->ldpc_dec.harq_combined_input.data,
+					0);
+		if (op_dec->ldpc_dec.harq_combined_output.data != NULL)
+			add4 = rte_pktmbuf_iova_offset(op_dec->ldpc_dec.harq_combined_output.data,
+					0);
+		snprintf(str, sizeof(str), "op %x st %x BG %d Zc %d Ncb %d qm %d F %d Rv %d It %d It %d "
+			"HARQin %d in %" PRIx64 " ho %" PRIx64 " so %" PRIx64 " hi %" PRIx64 " "
+			"ho %" PRIx64 " %s\n",
+			op_dec->ldpc_dec.op_flags, op_dec->status,
+			op_dec->ldpc_dec.basegraph, op_dec->ldpc_dec.z_c,
+			op_dec->ldpc_dec.n_cb, op_dec->ldpc_dec.q_m,
+			op_dec->ldpc_dec.n_filler, op_dec->ldpc_dec.rv_index,
+			op_dec->ldpc_dec.iter_max, op_dec->ldpc_dec.iter_count,
+			op_dec->ldpc_dec.harq_combined_input.length,
+			add0, add1, add2, add3, add4, partial);
+	} else if (op_type == RTE_BBDEV_OP_TURBO_DEC) {
+		op_dec = op;
+		if (op_dec->turbo_dec.code_block_mode == RTE_BBDEV_TRANSPORT_BLOCK)
+			snprintf(partial, sizeof(partial), "C %d Cab %d Ea %d Eb %d r %d K %d",
+					op_dec->turbo_dec.tb_params.c,
+					op_dec->turbo_dec.tb_params.cab,
+					op_dec->turbo_dec.tb_params.ea,
+					op_dec->turbo_dec.tb_params.eb,
+					op_dec->turbo_dec.tb_params.r,
+					op_dec->turbo_dec.tb_params.k_neg);
+		else
+			snprintf(partial, sizeof(partial), "E %d K %d",
+					op_dec->turbo_dec.cb_params.e,
+					op_dec->turbo_dec.cb_params.k);
+		if (op_dec->turbo_dec.input.data != NULL)
+			add0 = rte_pktmbuf_iova_offset(op_dec->turbo_dec.input.data, 0);
+		if (op_dec->turbo_dec.hard_output.data != NULL)
+			add1 = rte_pktmbuf_iova_offset(op_dec->turbo_dec.hard_output.data, 0);
+		if (op_dec->turbo_dec.soft_output.data != NULL)
+			add2 = rte_pktmbuf_iova_offset(op_dec->turbo_dec.soft_output.data, 0);
+		snprintf(str, sizeof(str), "op %x st %x CBM %d Iter %d map %d Rv %d ext %d "
+				"in %" PRIx64 " ho %" PRIx64 " so %" PRIx64 " %s\n",
+				op_dec->turbo_dec.op_flags, op_dec->status,
+				op_dec->turbo_dec.code_block_mode,
+				op_dec->turbo_dec.iter_max, op_dec->turbo_dec.num_maps,
+				op_dec->turbo_dec.rv_index, op_dec->turbo_dec.ext_scale,
+				add0, add1, add2, partial);
+	} else if (op_type == RTE_BBDEV_OP_LDPC_ENC) {
+		op_enc = op;
+		if (op_enc->ldpc_enc.code_block_mode == RTE_BBDEV_TRANSPORT_BLOCK)
+			snprintf(partial, sizeof(partial), "C %d Cab %d Ea %d Eb %d r %d",
+					op_enc->ldpc_enc.tb_params.c,
+					op_enc->ldpc_enc.tb_params.cab,
+					op_enc->ldpc_enc.tb_params.ea,
+					op_enc->ldpc_enc.tb_params.eb,
+					op_enc->ldpc_enc.tb_params.r);
+		else
+			snprintf(partial, sizeof(partial), "E %d",
+					op_enc->ldpc_enc.cb_params.e);
+		if (op_enc->ldpc_enc.input.data != NULL)
+			add0 = rte_pktmbuf_iova_offset(op_enc->ldpc_enc.input.data, 0);
+		if (op_enc->ldpc_enc.output.data != NULL)
+			add1 = rte_pktmbuf_iova_offset(op_enc->ldpc_enc.output.data, 0);
+		snprintf(str, sizeof(str), "op %x st %x BG %d Zc %d Ncb %d q_m %d F %d Rv %d "
+				"in %" PRIx64 " out %" PRIx64 " %s\n",
+				op_enc->ldpc_enc.op_flags, op_enc->status,
+				op_enc->ldpc_enc.basegraph, op_enc->ldpc_enc.z_c,
+				op_enc->ldpc_enc.n_cb, op_enc->ldpc_enc.q_m,
+				op_enc->ldpc_enc.n_filler, op_enc->ldpc_enc.rv_index,
+				add0, add1, partial);
+	} else if (op_type == RTE_BBDEV_OP_TURBO_ENC) {
+		op_enc = op;
+		if (op_enc->turbo_enc.code_block_mode == RTE_BBDEV_TRANSPORT_BLOCK)
+			snprintf(partial, sizeof(partial),
+					"C %d Cab %d Ea %d Eb %d r %d K %d Ncb %d",
+					op_enc->turbo_enc.tb_params.c,
+					op_enc->turbo_enc.tb_params.cab,
+					op_enc->turbo_enc.tb_params.ea,
+					op_enc->turbo_enc.tb_params.eb,
+					op_enc->turbo_enc.tb_params.r,
+					op_enc->turbo_enc.tb_params.k_neg,
+					op_enc->turbo_enc.tb_params.ncb_neg);
+		else
+			snprintf(partial, sizeof(partial), "E %d K %d",
+					op_enc->turbo_enc.cb_params.e,
+					op_enc->turbo_enc.cb_params.k);
+		if (op_enc->turbo_enc.input.data != NULL)
+			add0 = rte_pktmbuf_iova_offset(op_enc->turbo_enc.input.data, 0);
+		if (op_enc->turbo_enc.output.data != NULL)
+			add1 = rte_pktmbuf_iova_offset(op_enc->turbo_enc.output.data, 0);
+		snprintf(str, sizeof(str), "op %x st %x CBM %d Rv %d In %" PRIx64 " Out %" PRIx64 " %s\n",
+				op_enc->turbo_enc.op_flags, op_enc->status,
+				op_enc->turbo_enc.code_block_mode, op_enc->turbo_enc.rv_index,
+				add0, add1, partial);
+	} else if (op_type == RTE_BBDEV_OP_FFT) {
+		op_fft = op;
+		if (op_fft->fft.base_input.data != NULL)
+			add0 = rte_pktmbuf_iova_offset(op_fft->fft.base_input.data, 0);
+		if (op_fft->fft.base_output.data != NULL)
+			add1 = rte_pktmbuf_iova_offset(op_fft->fft.base_output.data, 0);
+		if (op_fft->fft.dewindowing_input.data != NULL)
+			add2 = rte_pktmbuf_iova_offset(op_fft->fft.dewindowing_input.data, 0);
+		if (op_fft->fft.power_meas_output.data != NULL)
+			add3 = rte_pktmbuf_iova_offset(op_fft->fft.power_meas_output.data, 0);
+		snprintf(str, sizeof(str), "op %x st %x in %d inl %d out %d outl %d cs %x ants %d "
+				"idft %d dft %d cst %d ish %d dsh %d ncs %d pwsh %d fp16 %d fr %d "
+				"outde %d in %" PRIx64 " out %" PRIx64 " dw %" PRIx64 " "
+				"pm %" PRIx64 "\n",
+				op_fft->fft.op_flags, op_fft->status,
+				op_fft->fft.input_sequence_size, op_fft->fft.input_leading_padding,
+				op_fft->fft.output_sequence_size,
+				op_fft->fft.output_leading_depadding,
+				op_fft->fft.cs_bitmap, op_fft->fft.num_antennas_log2,
+				op_fft->fft.idft_log2, op_fft->fft.dft_log2,
+				op_fft->fft.cs_time_adjustment,
+				op_fft->fft.idft_shift, op_fft->fft.dft_shift,
+				op_fft->fft.ncs_reciprocal, op_fft->fft.power_shift,
+				op_fft->fft.fp16_exp_adjust, op_fft->fft.freq_resample_mode,
+				op_fft->fft.output_depadded_size, add0, add1, add2, add3);
+	} else if (op_type == RTE_BBDEV_OP_MLDTS) {
+		op_mldts = op;
+		if (op_mldts->mldts.qhy_input.data != NULL)
+			add0 = rte_pktmbuf_iova_offset(op_mldts->mldts.qhy_input.data, 0);
+		if (op_mldts->mldts.r_input.data != NULL)
+			add1 = rte_pktmbuf_iova_offset(op_mldts->mldts.r_input.data, 0);
+		if (op_mldts->mldts.output.data != NULL)
+			add2 = rte_pktmbuf_iova_offset(op_mldts->mldts.output.data, 0);
+		snprintf(str, sizeof(str),
+				"op %x st %x rbs %d lay %d rrep %d crep%d qm %d %d %d %d "
+				"qhy %" PRIx64 " r %" PRIx64 " out %" PRIx64 "\n",
+				op_mldts->mldts.op_flags, op_mldts->status,
+				op_mldts->mldts.num_rbs, op_mldts->mldts.num_layers,
+				op_mldts->mldts.r_rep, op_mldts->mldts.c_rep,
+				op_mldts->mldts.q_m[0], op_mldts->mldts.q_m[1],
+				op_mldts->mldts.q_m[2], op_mldts->mldts.q_m[3],
+				add0, add1, add2);
+
+	} else {
+		snprintf(str, sizeof(str), "Invalid Operation type %d\n", op_type);
+	}
+
+	return str;
+}
diff --git a/lib/bbdev/rte_bbdev.h b/lib/bbdev/rte_bbdev.h
index 0cbfdd1c95..8623b0725b 100644
--- a/lib/bbdev/rte_bbdev.h
+++ b/lib/bbdev/rte_bbdev.h
@@ -1061,6 +1061,47 @@  rte_bbdev_device_status_str(enum rte_bbdev_device_status status);
 const char*
 rte_bbdev_enqueue_status_str(enum rte_bbdev_enqueue_status status);
 
+/**
+ * Dump operations info from device to a file.
+ * This API is used for debugging provided input operations, not a dataplane API.
+ *
+ *  @param dev_id
+ *    The device identifier.
+ *
+ *  @param queue_index
+ *    Index of queue.
+ *
+ *  @param file
+ *    A pointer to a file for output.
+ *
+ * @returns
+ *   - 0 on success
+ *   - ENOTSUP if interrupts are not supported by the identified device
+ *   - negative value on failure - as returned from PMD
+ *
+ */
+__rte_experimental
+int
+rte_bbdev_queue_ops_dump(uint16_t dev_id, uint16_t queue_index, FILE *file);
+
+
+/**
+ * String of parameters related to the parameters of an an operation of a given type.
+ *
+ *  @param op
+ *    Pointer to an operation.
+ *
+ *  @param op_type
+ *    Operation type enum.
+ *
+ * @returns
+ *   String describing the provided operation.
+ *
+ */
+__rte_experimental
+char *
+rte_bbdev_ops_param_string(void *op, enum rte_bbdev_op_type op_type);
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/lib/bbdev/rte_bbdev_pmd.h b/lib/bbdev/rte_bbdev_pmd.h
index 442b23943d..c21a7f0c1e 100644
--- a/lib/bbdev/rte_bbdev_pmd.h
+++ b/lib/bbdev/rte_bbdev_pmd.h
@@ -133,6 +133,13 @@  typedef int (*rte_bbdev_queue_intr_enable_t)(struct rte_bbdev *dev,
 typedef int (*rte_bbdev_queue_intr_disable_t)(struct rte_bbdev *dev,
 				    uint16_t queue_id);
 
+/*
+ * @internal
+ * Function to dump previous operations on a queue of a device.
+ */
+typedef int (*rte_bbdev_queue_ops_dump_t)(struct rte_bbdev *dev,
+		uint16_t queue_id, FILE *file);
+
 /**
  * Operations implemented by drivers. Fields marked as "Required" must be
  * provided by a driver for a device to have basic functionality. "Optional"
@@ -170,6 +177,8 @@  struct rte_bbdev_ops {
 	rte_bbdev_queue_intr_enable_t queue_intr_enable;
 	/** Disable queue interrupt. Optional */
 	rte_bbdev_queue_intr_disable_t queue_intr_disable;
+	/** Dump operations on the queue. Optional */
+	rte_bbdev_queue_ops_dump_t queue_ops_dump;
 };
 
 /**
diff --git a/lib/bbdev/version.map b/lib/bbdev/version.map
index 1840d2b2a4..0d037a93ca 100644
--- a/lib/bbdev/version.map
+++ b/lib/bbdev/version.map
@@ -54,4 +54,8 @@  EXPERIMENTAL {
 	rte_bbdev_enqueue_mldts_ops;
 	rte_bbdev_mldts_op_alloc_bulk;
 	rte_bbdev_mldts_op_free_bulk;
+
+	# added in 24.11
+	rte_bbdev_queue_ops_dump;
+	rte_bbdev_ops_param_string;
 };