diff mbox series

[V5,1/6] IB/MAD: Add send path trace points

Message ID 20190225051204.3784-2-ira.weiny@intel.com (mailing list archive)
State Changes Requested
Headers show
Series [V5,1/6] IB/MAD: Add send path trace points | expand

Commit Message

Ira Weiny Feb. 25, 2019, 5:11 a.m. UTC
From: Ira Weiny <ira.weiny@intel.com>

Use the standard Linux trace mechanism to trace MADs being sent.  4 trace
points are added, when the MAD is posted to the qp, when the MAD is
completed, if a MAD is resent, and when the MAD completes in error.

Signed-off-by: Ira Weiny <ira.weiny@intel.com>

---
Changes since v4:
	Clean up for checkpatch
	Remove helper function trace_create_mad_addr and if check

Changes since v3:
	Change dev_name to dev_index

Changes since v2:
	Change license text to SPDX tag
	Change dev_name to string from array
	Reorder fields for more compact ring buffer utilization
	Use a defined roce address type for safer memcpy/memset

Changes since v1:
	Update MAINTAINERS with tracing file

 MAINTAINERS                   |   1 +
 drivers/infiniband/core/mad.c |  42 +++++++-
 include/trace/events/ib_mad.h | 183 ++++++++++++++++++++++++++++++++++
 3 files changed, 225 insertions(+), 1 deletion(-)
 create mode 100644 include/trace/events/ib_mad.h

Comments

Steven Rostedt Feb. 25, 2019, 4:36 p.m. UTC | #1
On Sun, 24 Feb 2019 21:11:59 -0800
ira.weiny@intel.com wrote:

>  INGENIC JZ4780 DMA Driver
>  M:	Zubair Lutfullah Kakakhel <Zubair.Kakakhel@imgtec.com>
> diff --git a/drivers/infiniband/core/mad.c b/drivers/infiniband/core/mad.c
> index e742a6a2c138..d5cd90fecda7 100644
> --- a/drivers/infiniband/core/mad.c
> +++ b/drivers/infiniband/core/mad.c
> @@ -3,7 +3,7 @@
>   * Copyright (c) 2005 Intel Corporation.  All rights reserved.
>   * Copyright (c) 2005 Mellanox Technologies Ltd.  All rights reserved.
>   * Copyright (c) 2009 HNR Consulting. All rights reserved.
> - * Copyright (c) 2014 Intel Corporation.  All rights reserved.
> + * Copyright (c) 2014,2018 Intel Corporation.  All rights reserved.
>   *
>   * This software is available to you under a choice of one of two
>   * licenses.  You may choose to be licensed under the terms of the GNU
> @@ -51,6 +51,41 @@
>  #include "opa_smi.h"
>  #include "agent.h"
>  
> +static void create_mad_addr_info(struct ib_mad_send_wr_private *mad_send_wr,
> +				 struct ib_mad_qp_info *qp_info,
> +				 u32 *dlid, u8 *sl, u16 *pkey, u32 *rqpn,
> +				 u32 *rqkey)
> +{

Instead of passing in a bunch of addresses, you may be able to pass in
the entry structure directly.

	struct trace_event_raw_ib_mad_send_template *entry

(defined from DECLARE_EVENT_CLASS(name, ...

 struct trace_event_raw_##name .. )

And just assign everything as:

	entry->dlid = x, ...

-- Steve


> +	struct ib_device *dev = qp_info->port_priv->device;
> +	u8 pnum = qp_info->port_priv->port_num;
> +	struct ib_ud_wr *wr = &mad_send_wr->send_wr;
> +	struct rdma_ah_attr attr;
> +
> +	memset(&attr, 0, sizeof(attr));
> +	rdma_query_ah(wr->ah, &attr);
> +
> +	/* These are common */
> +	*sl = attr.sl;
> +	ib_query_pkey(dev, pnum, wr->pkey_index, pkey);
> +	*rqpn = wr->remote_qpn;
> +	*rqkey = wr->remote_qkey;
> +
> +	switch (attr.type) {
> +	case RDMA_AH_ATTR_TYPE_IB:
> +		*dlid = attr.ib.dlid;
> +		break;
> +	case RDMA_AH_ATTR_TYPE_OPA:
> +		*dlid = attr.opa.dlid;
> +		break;
> +	case RDMA_AH_ATTR_TYPE_ROCE:
> +	case RDMA_AH_ATTR_TYPE_UNDEFINED:
> +		*dlid = 0;
> +		break;
> +	}
> +}
> +#define CREATE_TRACE_POINTS
> +#include <trace/events/ib_mad.h>
> +
>  static int mad_sendq_size = IB_MAD_QP_SEND_SIZE;
>  static int mad_recvq_size = IB_MAD_QP_RECV_SIZE;
>  
> @@ -1223,6 +1258,7 @@ int ib_send_mad(struct ib_mad_send_wr_private
> *mad_send_wr) 
>  	spin_lock_irqsave(&qp_info->send_queue.lock, flags);
>  	if (qp_info->send_queue.count <
> qp_info->send_queue.max_active) {
> +		trace_ib_mad_ib_send_mad(mad_send_wr, qp_info);
>  		ret = ib_post_send(mad_agent->qp,
> &mad_send_wr->send_wr.wr, NULL);
>  		list = &qp_info->send_queue.list;
> @@ -2496,6 +2532,8 @@ static void ib_mad_send_done(struct ib_cq *cq,
> struct ib_wc *wc) send_queue = mad_list->mad_queue;
>  	qp_info = send_queue->qp_info;
>  
> +	trace_ib_mad_send_done_handler(mad_send_wr, wc);
> +
>  retry:
>  	ib_dma_unmap_single(mad_send_wr->send_buf.mad_agent->device,
>  			    mad_send_wr->header_mapping,
> @@ -2527,6 +2565,7 @@ static void ib_mad_send_done(struct ib_cq *cq,
> struct ib_wc *wc) ib_mad_complete_send_wr(mad_send_wr, &mad_send_wc);
>  
>  	if (queued_send_wr) {
> +		trace_ib_mad_send_done_resend(queued_send_wr,
> qp_info); ret = ib_post_send(qp_info->qp, &queued_send_wr->send_wr.wr,
>  				   NULL);
>  		if (ret) {
> @@ -2574,6 +2613,7 @@ static bool ib_mad_send_error(struct
> ib_mad_port_private *port_priv, if (mad_send_wr->retry) {
>  			/* Repost send */
>  			mad_send_wr->retry = 0;
> +			trace_ib_mad_error_handler(mad_send_wr,
> qp_info); ret = ib_post_send(qp_info->qp, &mad_send_wr->send_wr.wr,
>  					   NULL);
>  			if (!ret)
> diff --git a/include/trace/events/ib_mad.h
> b/include/trace/events/ib_mad.h new file mode 100644
> index 000000000000..09c72ca1e857
> --- /dev/null
> +++ b/include/trace/events/ib_mad.h
> @@ -0,0 +1,183 @@
> +/* SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB */
> +
> +/*
> + * Copyright (c) 2018 Intel Corporation.  All rights reserved.
> + */
> +
> +#undef TRACE_SYSTEM
> +#define TRACE_SYSTEM ib_mad
> +
> +#if !defined(_TRACE_IB_MAD_H) || defined(TRACE_HEADER_MULTI_READ)
> +#define _TRACE_IB_MAD_H
> +
> +#include <linux/tracepoint.h>
> +#include <rdma/ib_mad.h>
> +
> +DECLARE_EVENT_CLASS(ib_mad_send_template,
> +	TP_PROTO(struct ib_mad_send_wr_private *wr,
> +		 struct ib_mad_qp_info *qp_info),
> +	TP_ARGS(wr, qp_info),
> +
> +	TP_STRUCT__entry(
> +		__field(u8,             base_version)
> +		__field(u8,             mgmt_class)
> +		__field(u8,             class_version)
> +		__field(u8,             port_num)
> +		__field(u32,            qp_num)
> +		__field(u8,             method)
> +		__field(u8,             sl)
> +		__field(u16,            attr_id)
> +		__field(u32,            attr_mod)
> +		__field(u64,            wrtid)
> +		__field(u64,            tid)
> +		__field(u16,            status)
> +		__field(u16,            class_specific)
> +		__field(u32,            length)
> +		__field(u32,            dlid)
> +		__field(u32,            rqpn)
> +		__field(u32,            rqkey)
> +		__field(u32,            dev_index)
> +		__field(void *,         agent_priv)
> +		__field(unsigned long,  timeout)
> +		__field(int,            retries_left)
> +		__field(int,            max_retries)
> +		__field(int,            retry)
> +		__field(u16,            pkey)
> +	),
> +
> +	TP_fast_assign(
> +		__entry->dev_index =
> wr->mad_agent_priv->agent.device->index;
> +		__entry->port_num =
> wr->mad_agent_priv->agent.port_num;
> +		__entry->qp_num =
> wr->mad_agent_priv->qp_info->qp->qp_num;
> +		__entry->agent_priv = wr->mad_agent_priv;
> +		__entry->wrtid = wr->tid;
> +		__entry->max_retries = wr->max_retries;
> +		__entry->retries_left = wr->retries_left;
> +		__entry->retry = wr->retry;
> +		__entry->timeout = wr->timeout;
> +		__entry->length = wr->send_buf.hdr_len +
> +				  wr->send_buf.data_len;
> +		__entry->base_version =
> +			((struct ib_mad_hdr
> *)wr->send_buf.mad)->base_version;
> +		__entry->mgmt_class =
> +			((struct ib_mad_hdr
> *)wr->send_buf.mad)->mgmt_class;
> +		__entry->class_version =
> +			((struct ib_mad_hdr
> *)wr->send_buf.mad)->class_version;
> +		__entry->method =
> +			((struct ib_mad_hdr
> *)wr->send_buf.mad)->method;
> +		__entry->status =
> +			((struct ib_mad_hdr
> *)wr->send_buf.mad)->status;
> +		__entry->class_specific =
> +			((struct ib_mad_hdr
> *)wr->send_buf.mad)->class_specific;
> +		__entry->tid = ((struct ib_mad_hdr
> *)wr->send_buf.mad)->tid;
> +		__entry->attr_id =
> +			((struct ib_mad_hdr
> *)wr->send_buf.mad)->attr_id;
> +		__entry->attr_mod =
> +			((struct ib_mad_hdr
> *)wr->send_buf.mad)->attr_mod;
> +		create_mad_addr_info(wr, qp_info,
> +				     &__entry->dlid, &__entry->sl,
> +				     &__entry->pkey, &__entry->rqpn,
> +				     &__entry->rqkey);
> +	),
> +
> +	TP_printk("%d:%d QP%d agent %p: " \
> +		  "wrtid 0x%llx; %d/%d retries(%d); timeout %lu
> length %d : " \
> +		  "hdr : base_ver 0x%x class 0x%x class_ver 0x%x " \
> +		  "method 0x%x status 0x%x class_specific 0x%x tid
> 0x%llx " \
> +		  "attr_id 0x%x attr_mod 0x%x  => dlid 0x%08x sl %d
> "\
> +		  "pkey 0x%x rpqn 0x%x rqpkey 0x%x",
> +		__entry->dev_index, __entry->port_num,
> __entry->qp_num,
> +		__entry->agent_priv, be64_to_cpu(__entry->wrtid),
> +		__entry->retries_left, __entry->max_retries,
> +		__entry->retry, __entry->timeout, __entry->length,
> +		__entry->base_version, __entry->mgmt_class,
> +		__entry->class_version,
> +		__entry->method, be16_to_cpu(__entry->status),
> +		be16_to_cpu(__entry->class_specific),
> +		be64_to_cpu(__entry->tid),
> be16_to_cpu(__entry->attr_id),
> +		be32_to_cpu(__entry->attr_mod),
> +		be32_to_cpu(__entry->dlid), __entry->sl,
> __entry->pkey,
> +		__entry->rqpn, __entry->rqkey
> +	)
> +);
> +
> +DEFINE_EVENT(ib_mad_send_template, ib_mad_error_handler,
> +	TP_PROTO(struct ib_mad_send_wr_private *wr,
> +		 struct ib_mad_qp_info *qp_info),
> +	TP_ARGS(wr, qp_info));
> +DEFINE_EVENT(ib_mad_send_template, ib_mad_ib_send_mad,
> +	TP_PROTO(struct ib_mad_send_wr_private *wr,
> +		 struct ib_mad_qp_info *qp_info),
> +	TP_ARGS(wr, qp_info));
> +DEFINE_EVENT(ib_mad_send_template, ib_mad_send_done_resend,
> +	TP_PROTO(struct ib_mad_send_wr_private *wr,
> +		 struct ib_mad_qp_info *qp_info),
> +	TP_ARGS(wr, qp_info));
> +
Alexei Starovoitov Feb. 26, 2019, 5:52 a.m. UTC | #2
On Mon, Feb 25, 2019 at 11:36:40AM -0500, Steven Rostedt wrote:
> On Sun, 24 Feb 2019 21:11:59 -0800
> ira.weiny@intel.com wrote:
> 
> >  INGENIC JZ4780 DMA Driver
> >  M:	Zubair Lutfullah Kakakhel <Zubair.Kakakhel@imgtec.com>
> > diff --git a/drivers/infiniband/core/mad.c b/drivers/infiniband/core/mad.c
> > index e742a6a2c138..d5cd90fecda7 100644
> > --- a/drivers/infiniband/core/mad.c
> > +++ b/drivers/infiniband/core/mad.c
> > @@ -3,7 +3,7 @@
> >   * Copyright (c) 2005 Intel Corporation.  All rights reserved.
> >   * Copyright (c) 2005 Mellanox Technologies Ltd.  All rights reserved.
> >   * Copyright (c) 2009 HNR Consulting. All rights reserved.
> > - * Copyright (c) 2014 Intel Corporation.  All rights reserved.
> > + * Copyright (c) 2014,2018 Intel Corporation.  All rights reserved.
> >   *
> >   * This software is available to you under a choice of one of two
> >   * licenses.  You may choose to be licensed under the terms of the GNU
> > @@ -51,6 +51,41 @@
> >  #include "opa_smi.h"
> >  #include "agent.h"
> >  
> > +static void create_mad_addr_info(struct ib_mad_send_wr_private *mad_send_wr,
> > +				 struct ib_mad_qp_info *qp_info,
> > +				 u32 *dlid, u8 *sl, u16 *pkey, u32 *rqpn,
> > +				 u32 *rqkey)
> > +{
> 
> Instead of passing in a bunch of addresses, you may be able to pass in
> the entry structure directly.
> 
> 	struct trace_event_raw_ib_mad_send_template *entry
> 
> (defined from DECLARE_EVENT_CLASS(name, ...
> 
>  struct trace_event_raw_##name .. )
> 
> And just assign everything as:
> 
> 	entry->dlid = x, ...

raw_tracepoint requires all args to fit into u64.
bpf prog cannot access it otherwise.
Also struct by value is pretty slow on some archs.
Pointer to struct is always preferred.
Steven Rostedt Feb. 26, 2019, 6:13 a.m. UTC | #3
On Mon, 25 Feb 2019 21:52:46 -0800
Alexei Starovoitov <alexei.starovoitov@gmail.com> wrote:

> On Mon, Feb 25, 2019 at 11:36:40AM -0500, Steven Rostedt wrote:
> > On Sun, 24 Feb 2019 21:11:59 -0800
> > ira.weiny@intel.com wrote:
> >   
> > >  INGENIC JZ4780 DMA Driver
> > >  M:	Zubair Lutfullah Kakakhel <Zubair.Kakakhel@imgtec.com>
> > > diff --git a/drivers/infiniband/core/mad.c b/drivers/infiniband/core/mad.c
> > > index e742a6a2c138..d5cd90fecda7 100644
> > > --- a/drivers/infiniband/core/mad.c
> > > +++ b/drivers/infiniband/core/mad.c
> > > @@ -3,7 +3,7 @@
> > >   * Copyright (c) 2005 Intel Corporation.  All rights reserved.
> > >   * Copyright (c) 2005 Mellanox Technologies Ltd.  All rights reserved.
> > >   * Copyright (c) 2009 HNR Consulting. All rights reserved.
> > > - * Copyright (c) 2014 Intel Corporation.  All rights reserved.
> > > + * Copyright (c) 2014,2018 Intel Corporation.  All rights reserved.
> > >   *
> > >   * This software is available to you under a choice of one of two
> > >   * licenses.  You may choose to be licensed under the terms of the GNU
> > > @@ -51,6 +51,41 @@
> > >  #include "opa_smi.h"
> > >  #include "agent.h"
> > >  
> > > +static void create_mad_addr_info(struct ib_mad_send_wr_private *mad_send_wr,
> > > +				 struct ib_mad_qp_info *qp_info,
> > > +				 u32 *dlid, u8 *sl, u16 *pkey, u32 *rqpn,
> > > +				 u32 *rqkey)
> > > +{  
> > 
> > Instead of passing in a bunch of addresses, you may be able to pass in
> > the entry structure directly.
> > 
> > 	struct trace_event_raw_ib_mad_send_template *entry
> > 
> > (defined from DECLARE_EVENT_CLASS(name, ...
> > 
> >  struct trace_event_raw_##name .. )
> > 
> > And just assign everything as:
> > 
> > 	entry->dlid = x, ...  
> 
> raw_tracepoint requires all args to fit into u64.
> bpf prog cannot access it otherwise.
> Also struct by value is pretty slow on some archs.
> Pointer to struct is always preferred.

I meant passing in the pointer, not the value. It wouldn't make sense
otherwise, because the entire  point of create_mad_addr_info(), is to
update the __entry structure. How would passing in the value do that?


Instead of:

+		create_mad_addr_info(wr, qp_info,
+				     &__entry->dlid, &__entry->sl,
+				     &__entry->pkey, &__entry->rqpn,
+				     &__entry->rqkey);

You do:

	create_mad_addr_info(wr, qp_info, __entry);

And then in that function you assign the values directly to the structure.

-- Steve
Ira Weiny Feb. 26, 2019, 4:19 p.m. UTC | #4
On Tue, Feb 26, 2019 at 01:13:17AM -0500, Steven Rostedt wrote:
> On Mon, 25 Feb 2019 21:52:46 -0800
> Alexei Starovoitov <alexei.starovoitov@gmail.com> wrote:
> 
> > On Mon, Feb 25, 2019 at 11:36:40AM -0500, Steven Rostedt wrote:
> > > On Sun, 24 Feb 2019 21:11:59 -0800
> > > ira.weiny@intel.com wrote:
> > > >  
> > > > +static void create_mad_addr_info(struct ib_mad_send_wr_private *mad_send_wr,
> > > > +				 struct ib_mad_qp_info *qp_info,
> > > > +				 u32 *dlid, u8 *sl, u16 *pkey, u32 *rqpn,
> > > > +				 u32 *rqkey)
> > > > +{  
> > > 
> > > Instead of passing in a bunch of addresses, you may be able to pass in
> > > the entry structure directly.
> > > 
> > > 	struct trace_event_raw_ib_mad_send_template *entry
> > > 
> > > (defined from DECLARE_EVENT_CLASS(name, ...
> > > 
> > >  struct trace_event_raw_##name .. )
> > > 
> > > And just assign everything as:
> > > 
> > > 	entry->dlid = x, ...  
> > 
> > raw_tracepoint requires all args to fit into u64.
> > bpf prog cannot access it otherwise.
> > Also struct by value is pretty slow on some archs.
> > Pointer to struct is always preferred.
> 
> I meant passing in the pointer, not the value. It wouldn't make sense
> otherwise, because the entire  point of create_mad_addr_info(), is to
> update the __entry structure. How would passing in the value do that?
> 
> 
> Instead of:
> 
> +		create_mad_addr_info(wr, qp_info,
> +				     &__entry->dlid, &__entry->sl,
> +				     &__entry->pkey, &__entry->rqpn,
> +				     &__entry->rqkey);
> 
> You do:
> 
> 	create_mad_addr_info(wr, qp_info, __entry);
> 
> And then in that function you assign the values directly to the structure.

Is there any reason this is preferred over what I did?  I'm not seeing the
benefit?

Ira

> 
> -- Steve
> 
>
Steven Rostedt Feb. 26, 2019, 6:33 p.m. UTC | #5
On Tue, 26 Feb 2019 08:19:56 -0800
Ira Weiny <ira.weiny@intel.com> wrote:


> > Instead of:
> > 
> > +		create_mad_addr_info(wr, qp_info,
> > +				     &__entry->dlid, &__entry->sl,
> > +				     &__entry->pkey, &__entry->rqpn,
> > +				     &__entry->rqkey);
> > 
> > You do:
> > 
> > 	create_mad_addr_info(wr, qp_info, __entry);
> > 
> > And then in that function you assign the values directly to the structure.  
> 
> Is there any reason this is preferred over what I did?  I'm not seeing the
> benefit?
> 

Matters if gcc optimizes it into a static inline (which you may not
want, because that goes directly into the code that calls the trace
points, for each event in that class. Thus, I believe it is a true
function call. In which, it is passing 7 arguments, on x86, that
requires storing on the stack, and takes time to set up and tear down.

Passing the function pointer directly, makes it only use 3 arguments
(all in registers) and is much faster, especially, if this is a fast
path).

Do a disassemble of both approaches to see what I mean.

-- Steve
Ira Weiny Feb. 27, 2019, 2:51 a.m. UTC | #6
On Tue, Feb 26, 2019 at 01:33:30PM -0500, Steven Rostedt wrote:
> On Tue, 26 Feb 2019 08:19:56 -0800
> Ira Weiny <ira.weiny@intel.com> wrote:
> 
> 
> > > Instead of:
> > > 
> > > +		create_mad_addr_info(wr, qp_info,
> > > +				     &__entry->dlid, &__entry->sl,
> > > +				     &__entry->pkey, &__entry->rqpn,
> > > +				     &__entry->rqkey);
> > > 
> > > You do:
> > > 
> > > 	create_mad_addr_info(wr, qp_info, __entry);
> > > 
> > > And then in that function you assign the values directly to the structure.  
> > 
> > Is there any reason this is preferred over what I did?  I'm not seeing the
> > benefit?
> > 
> 
> Matters if gcc optimizes it into a static inline (which you may not
> want, because that goes directly into the code that calls the trace
> points, for each event in that class. Thus, I believe it is a true
> function call. In which, it is passing 7 arguments, on x86, that
> requires storing on the stack, and takes time to set up and tear down.
> 
> Passing the function pointer directly, makes it only use 3 arguments
> (all in registers) and is much faster, especially, if this is a fast
> path).
> 
> Do a disassemble of both approaches to see what I mean.

Right...  However, this results in quite the chicken and the egg problem
because calling create_mad_addr_info() within the definition of
trace_event_raw_ib_mad_send_template results in errors that I'm
declaring the structure in the parameter list...

:-/

I've tried moving create_mad_addr_info() around a bit and a couple of things
with void pointers but the best I can get is that I'm dereferencing an
incomplete type because the output of the preprocessor always seems to put at
least 1 call of create_mad_addr_info() prior to the struct definition.

Is there an example of this somewhere?  This code is not that performance
critical but I am curious at this point.

Ira

> 
> -- Steve
Steven Rostedt Feb. 28, 2019, 2:10 a.m. UTC | #7
On Tue, 26 Feb 2019 18:51:37 -0800
Ira Weiny <ira.weiny@intel.com> wrote:


> > Do a disassemble of both approaches to see what I mean.  
> 
> Right...  However, this results in quite the chicken and the egg problem
> because calling create_mad_addr_info() within the definition of
> trace_event_raw_ib_mad_send_template results in errors that I'm
> declaring the structure in the parameter list...

Just adding:

struct trace_event_raw_ib_mad_send_template;

Before the macro should fix it.

> 
> :-/
> 
> I've tried moving create_mad_addr_info() around a bit and a couple of things
> with void pointers but the best I can get is that I'm dereferencing an
> incomplete type because the output of the preprocessor always seems to put at
> least 1 call of create_mad_addr_info() prior to the struct definition.
> 
> Is there an example of this somewhere?  This code is not that performance
> critical but I am curious at this point.

Not really, this is a unique case where you have a single function
updating several parameters.

-- Steve
Ira Weiny Feb. 28, 2019, 9:57 p.m. UTC | #8
On Wed, Feb 27, 2019 at 09:10:05PM -0500, Steven Rostedt wrote:
> On Tue, 26 Feb 2019 18:51:37 -0800
> Ira Weiny <ira.weiny@intel.com> wrote:
> 
> 
> > > Do a disassemble of both approaches to see what I mean.  
> > 
> > Right...  However, this results in quite the chicken and the egg problem
> > because calling create_mad_addr_info() within the definition of
> > trace_event_raw_ib_mad_send_template results in errors that I'm
> > declaring the structure in the parameter list...
> 
> Just adding:
> 
> struct trace_event_raw_ib_mad_send_template;
> 
> Before the macro should fix it.

Ok the key was to pre-declare both the struct and create_mad_addr_info() as
shown below.

Jason I'm going to send this as a follow on to the series.

Ira


From 5fcbff09a0b076c165dd3f9fd65df7558df9c58b Mon Sep 17 00:00:00 2001
From: Ira Weiny <ira.weiny@intel.com>
Date: Wed, 27 Feb 2019 19:16:35 -0500
Subject: [PATCH] IB/mad: Use trace struct in create_mad_addr_info() helper

Using a structure pointer is more efficient in the helper.

Signed-off-by: Ira Weiny <ira.weiny@intel.com>
---
 drivers/infiniband/core/mad.c | 26 ++++++++++++++------------
 include/trace/events/ib_mad.h | 10 ++++++----
 2 files changed, 20 insertions(+), 16 deletions(-)

diff --git a/drivers/infiniband/core/mad.c b/drivers/infiniband/core/mad.c
index 87eff3f3f887..0a6136dded47 100644
--- a/drivers/infiniband/core/mad.c
+++ b/drivers/infiniband/core/mad.c
@@ -51,11 +51,14 @@
 #include "opa_smi.h"
 #include "agent.h"
 
+#define CREATE_TRACE_POINTS
+#include <trace/events/ib_mad.h>
+
 static void create_mad_addr_info(struct ib_mad_send_wr_private *mad_send_wr,
-				 struct ib_mad_qp_info *qp_info,
-				 u32 *dlid, u8 *sl, u16 *pkey, u32 *rqpn,
-				 u32 *rqkey)
+			struct ib_mad_qp_info *qp_info,
+			struct trace_event_raw_ib_mad_send_template *entry)
 {
+	u16 pkey;
 	struct ib_device *dev = qp_info->port_priv->device;
 	u8 pnum = qp_info->port_priv->port_num;
 	struct ib_ud_wr *wr = &mad_send_wr->send_wr;
@@ -65,26 +68,25 @@ static void create_mad_addr_info(struct ib_mad_send_wr_private *mad_send_wr,
 	rdma_query_ah(wr->ah, &attr);
 
 	/* These are common */
-	*sl = attr.sl;
-	ib_query_pkey(dev, pnum, wr->pkey_index, pkey);
-	*rqpn = wr->remote_qpn;
-	*rqkey = wr->remote_qkey;
+	entry->sl = attr.sl;
+	ib_query_pkey(dev, pnum, wr->pkey_index, &pkey);
+	entry->pkey = pkey;
+	entry->rqpn = wr->remote_qpn;
+	entry->rqkey = wr->remote_qkey;
 
 	switch (attr.type) {
 	case RDMA_AH_ATTR_TYPE_IB:
-		*dlid = attr.ib.dlid;
+		entry->dlid = attr.ib.dlid;
 		break;
 	case RDMA_AH_ATTR_TYPE_OPA:
-		*dlid = attr.opa.dlid;
+		entry->dlid = attr.opa.dlid;
 		break;
 	case RDMA_AH_ATTR_TYPE_ROCE:
 	case RDMA_AH_ATTR_TYPE_UNDEFINED:
-		*dlid = 0;
+		entry->dlid = 0;
 		break;
 	}
 }
-#define CREATE_TRACE_POINTS
-#include <trace/events/ib_mad.h>
 
 static int mad_sendq_size = IB_MAD_QP_SEND_SIZE;
 static int mad_recvq_size = IB_MAD_QP_RECV_SIZE;
diff --git a/include/trace/events/ib_mad.h b/include/trace/events/ib_mad.h
index 7f2486535d04..cccb2cf4a8f7 100644
--- a/include/trace/events/ib_mad.h
+++ b/include/trace/events/ib_mad.h
@@ -13,6 +13,11 @@
 #include <linux/tracepoint.h>
 #include <rdma/ib_mad.h>
 
+struct trace_event_raw_ib_mad_send_template;
+static void create_mad_addr_info(struct ib_mad_send_wr_private *mad_send_wr,
+			struct ib_mad_qp_info *qp_info,
+			struct trace_event_raw_ib_mad_send_template *entry);
+
 DECLARE_EVENT_CLASS(ib_mad_send_template,
 	TP_PROTO(struct ib_mad_send_wr_private *wr,
 		 struct ib_mad_qp_info *qp_info),
@@ -74,10 +79,7 @@ DECLARE_EVENT_CLASS(ib_mad_send_template,
 			((struct ib_mad_hdr *)wr->send_buf.mad)->attr_id;
 		__entry->attr_mod =
 			((struct ib_mad_hdr *)wr->send_buf.mad)->attr_mod;
-		create_mad_addr_info(wr, qp_info,
-				     &__entry->dlid, &__entry->sl,
-				     &__entry->pkey, &__entry->rqpn,
-				     &__entry->rqkey);
+		create_mad_addr_info(wr, qp_info, __entry);
 	),
 
 	TP_printk("%d:%d QP%d agent %p: " \
diff mbox series

Patch

diff --git a/MAINTAINERS b/MAINTAINERS
index 459bed632ebb..6ad8f3f7a580 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -7506,6 +7506,7 @@  F:	drivers/infiniband/
 F:	include/uapi/linux/if_infiniband.h
 F:	include/uapi/rdma/
 F:	include/rdma/
+F:	include/trace/events/ib_mad.h
 
 INGENIC JZ4780 DMA Driver
 M:	Zubair Lutfullah Kakakhel <Zubair.Kakakhel@imgtec.com>
diff --git a/drivers/infiniband/core/mad.c b/drivers/infiniband/core/mad.c
index e742a6a2c138..d5cd90fecda7 100644
--- a/drivers/infiniband/core/mad.c
+++ b/drivers/infiniband/core/mad.c
@@ -3,7 +3,7 @@ 
  * Copyright (c) 2005 Intel Corporation.  All rights reserved.
  * Copyright (c) 2005 Mellanox Technologies Ltd.  All rights reserved.
  * Copyright (c) 2009 HNR Consulting. All rights reserved.
- * Copyright (c) 2014 Intel Corporation.  All rights reserved.
+ * Copyright (c) 2014,2018 Intel Corporation.  All rights reserved.
  *
  * This software is available to you under a choice of one of two
  * licenses.  You may choose to be licensed under the terms of the GNU
@@ -51,6 +51,41 @@ 
 #include "opa_smi.h"
 #include "agent.h"
 
+static void create_mad_addr_info(struct ib_mad_send_wr_private *mad_send_wr,
+				 struct ib_mad_qp_info *qp_info,
+				 u32 *dlid, u8 *sl, u16 *pkey, u32 *rqpn,
+				 u32 *rqkey)
+{
+	struct ib_device *dev = qp_info->port_priv->device;
+	u8 pnum = qp_info->port_priv->port_num;
+	struct ib_ud_wr *wr = &mad_send_wr->send_wr;
+	struct rdma_ah_attr attr;
+
+	memset(&attr, 0, sizeof(attr));
+	rdma_query_ah(wr->ah, &attr);
+
+	/* These are common */
+	*sl = attr.sl;
+	ib_query_pkey(dev, pnum, wr->pkey_index, pkey);
+	*rqpn = wr->remote_qpn;
+	*rqkey = wr->remote_qkey;
+
+	switch (attr.type) {
+	case RDMA_AH_ATTR_TYPE_IB:
+		*dlid = attr.ib.dlid;
+		break;
+	case RDMA_AH_ATTR_TYPE_OPA:
+		*dlid = attr.opa.dlid;
+		break;
+	case RDMA_AH_ATTR_TYPE_ROCE:
+	case RDMA_AH_ATTR_TYPE_UNDEFINED:
+		*dlid = 0;
+		break;
+	}
+}
+#define CREATE_TRACE_POINTS
+#include <trace/events/ib_mad.h>
+
 static int mad_sendq_size = IB_MAD_QP_SEND_SIZE;
 static int mad_recvq_size = IB_MAD_QP_RECV_SIZE;
 
@@ -1223,6 +1258,7 @@  int ib_send_mad(struct ib_mad_send_wr_private *mad_send_wr)
 
 	spin_lock_irqsave(&qp_info->send_queue.lock, flags);
 	if (qp_info->send_queue.count < qp_info->send_queue.max_active) {
+		trace_ib_mad_ib_send_mad(mad_send_wr, qp_info);
 		ret = ib_post_send(mad_agent->qp, &mad_send_wr->send_wr.wr,
 				   NULL);
 		list = &qp_info->send_queue.list;
@@ -2496,6 +2532,8 @@  static void ib_mad_send_done(struct ib_cq *cq, struct ib_wc *wc)
 	send_queue = mad_list->mad_queue;
 	qp_info = send_queue->qp_info;
 
+	trace_ib_mad_send_done_handler(mad_send_wr, wc);
+
 retry:
 	ib_dma_unmap_single(mad_send_wr->send_buf.mad_agent->device,
 			    mad_send_wr->header_mapping,
@@ -2527,6 +2565,7 @@  static void ib_mad_send_done(struct ib_cq *cq, struct ib_wc *wc)
 	ib_mad_complete_send_wr(mad_send_wr, &mad_send_wc);
 
 	if (queued_send_wr) {
+		trace_ib_mad_send_done_resend(queued_send_wr, qp_info);
 		ret = ib_post_send(qp_info->qp, &queued_send_wr->send_wr.wr,
 				   NULL);
 		if (ret) {
@@ -2574,6 +2613,7 @@  static bool ib_mad_send_error(struct ib_mad_port_private *port_priv,
 		if (mad_send_wr->retry) {
 			/* Repost send */
 			mad_send_wr->retry = 0;
+			trace_ib_mad_error_handler(mad_send_wr, qp_info);
 			ret = ib_post_send(qp_info->qp, &mad_send_wr->send_wr.wr,
 					   NULL);
 			if (!ret)
diff --git a/include/trace/events/ib_mad.h b/include/trace/events/ib_mad.h
new file mode 100644
index 000000000000..09c72ca1e857
--- /dev/null
+++ b/include/trace/events/ib_mad.h
@@ -0,0 +1,183 @@ 
+/* SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB */
+
+/*
+ * Copyright (c) 2018 Intel Corporation.  All rights reserved.
+ */
+
+#undef TRACE_SYSTEM
+#define TRACE_SYSTEM ib_mad
+
+#if !defined(_TRACE_IB_MAD_H) || defined(TRACE_HEADER_MULTI_READ)
+#define _TRACE_IB_MAD_H
+
+#include <linux/tracepoint.h>
+#include <rdma/ib_mad.h>
+
+DECLARE_EVENT_CLASS(ib_mad_send_template,
+	TP_PROTO(struct ib_mad_send_wr_private *wr,
+		 struct ib_mad_qp_info *qp_info),
+	TP_ARGS(wr, qp_info),
+
+	TP_STRUCT__entry(
+		__field(u8,             base_version)
+		__field(u8,             mgmt_class)
+		__field(u8,             class_version)
+		__field(u8,             port_num)
+		__field(u32,            qp_num)
+		__field(u8,             method)
+		__field(u8,             sl)
+		__field(u16,            attr_id)
+		__field(u32,            attr_mod)
+		__field(u64,            wrtid)
+		__field(u64,            tid)
+		__field(u16,            status)
+		__field(u16,            class_specific)
+		__field(u32,            length)
+		__field(u32,            dlid)
+		__field(u32,            rqpn)
+		__field(u32,            rqkey)
+		__field(u32,            dev_index)
+		__field(void *,         agent_priv)
+		__field(unsigned long,  timeout)
+		__field(int,            retries_left)
+		__field(int,            max_retries)
+		__field(int,            retry)
+		__field(u16,            pkey)
+	),
+
+	TP_fast_assign(
+		__entry->dev_index = wr->mad_agent_priv->agent.device->index;
+		__entry->port_num = wr->mad_agent_priv->agent.port_num;
+		__entry->qp_num = wr->mad_agent_priv->qp_info->qp->qp_num;
+		__entry->agent_priv = wr->mad_agent_priv;
+		__entry->wrtid = wr->tid;
+		__entry->max_retries = wr->max_retries;
+		__entry->retries_left = wr->retries_left;
+		__entry->retry = wr->retry;
+		__entry->timeout = wr->timeout;
+		__entry->length = wr->send_buf.hdr_len +
+				  wr->send_buf.data_len;
+		__entry->base_version =
+			((struct ib_mad_hdr *)wr->send_buf.mad)->base_version;
+		__entry->mgmt_class =
+			((struct ib_mad_hdr *)wr->send_buf.mad)->mgmt_class;
+		__entry->class_version =
+			((struct ib_mad_hdr *)wr->send_buf.mad)->class_version;
+		__entry->method =
+			((struct ib_mad_hdr *)wr->send_buf.mad)->method;
+		__entry->status =
+			((struct ib_mad_hdr *)wr->send_buf.mad)->status;
+		__entry->class_specific =
+			((struct ib_mad_hdr *)wr->send_buf.mad)->class_specific;
+		__entry->tid = ((struct ib_mad_hdr *)wr->send_buf.mad)->tid;
+		__entry->attr_id =
+			((struct ib_mad_hdr *)wr->send_buf.mad)->attr_id;
+		__entry->attr_mod =
+			((struct ib_mad_hdr *)wr->send_buf.mad)->attr_mod;
+		create_mad_addr_info(wr, qp_info,
+				     &__entry->dlid, &__entry->sl,
+				     &__entry->pkey, &__entry->rqpn,
+				     &__entry->rqkey);
+	),
+
+	TP_printk("%d:%d QP%d agent %p: " \
+		  "wrtid 0x%llx; %d/%d retries(%d); timeout %lu length %d : " \
+		  "hdr : base_ver 0x%x class 0x%x class_ver 0x%x " \
+		  "method 0x%x status 0x%x class_specific 0x%x tid 0x%llx " \
+		  "attr_id 0x%x attr_mod 0x%x  => dlid 0x%08x sl %d "\
+		  "pkey 0x%x rpqn 0x%x rqpkey 0x%x",
+		__entry->dev_index, __entry->port_num, __entry->qp_num,
+		__entry->agent_priv, be64_to_cpu(__entry->wrtid),
+		__entry->retries_left, __entry->max_retries,
+		__entry->retry, __entry->timeout, __entry->length,
+		__entry->base_version, __entry->mgmt_class,
+		__entry->class_version,
+		__entry->method, be16_to_cpu(__entry->status),
+		be16_to_cpu(__entry->class_specific),
+		be64_to_cpu(__entry->tid), be16_to_cpu(__entry->attr_id),
+		be32_to_cpu(__entry->attr_mod),
+		be32_to_cpu(__entry->dlid), __entry->sl, __entry->pkey,
+		__entry->rqpn, __entry->rqkey
+	)
+);
+
+DEFINE_EVENT(ib_mad_send_template, ib_mad_error_handler,
+	TP_PROTO(struct ib_mad_send_wr_private *wr,
+		 struct ib_mad_qp_info *qp_info),
+	TP_ARGS(wr, qp_info));
+DEFINE_EVENT(ib_mad_send_template, ib_mad_ib_send_mad,
+	TP_PROTO(struct ib_mad_send_wr_private *wr,
+		 struct ib_mad_qp_info *qp_info),
+	TP_ARGS(wr, qp_info));
+DEFINE_EVENT(ib_mad_send_template, ib_mad_send_done_resend,
+	TP_PROTO(struct ib_mad_send_wr_private *wr,
+		 struct ib_mad_qp_info *qp_info),
+	TP_ARGS(wr, qp_info));
+
+TRACE_EVENT(ib_mad_send_done_handler,
+	TP_PROTO(struct ib_mad_send_wr_private *wr, struct ib_wc *wc),
+	TP_ARGS(wr, wc),
+
+	TP_STRUCT__entry(
+		__field(u8,             port_num)
+		__field(u8,             base_version)
+		__field(u8,             mgmt_class)
+		__field(u8,             class_version)
+		__field(u32,            qp_num)
+		__field(u64,            wrtid)
+		__field(u16,            status)
+		__field(u16,            wc_status)
+		__field(u32,            length)
+		__field(void *,         agent_priv)
+		__field(unsigned long,  timeout)
+		__field(u32,            dev_index)
+		__field(int,            retries_left)
+		__field(int,            max_retries)
+		__field(int,            retry)
+		__field(u8,             method)
+	),
+
+	TP_fast_assign(
+		__entry->dev_index = wr->mad_agent_priv->agent.device->index;
+		__entry->port_num = wr->mad_agent_priv->agent.port_num;
+		__entry->qp_num = wr->mad_agent_priv->qp_info->qp->qp_num;
+		__entry->agent_priv = wr->mad_agent_priv;
+		__entry->wrtid = wr->tid;
+		__entry->max_retries = wr->max_retries;
+		__entry->retries_left = wr->retries_left;
+		__entry->retry = wr->retry;
+		__entry->timeout = wr->timeout;
+		__entry->base_version =
+			((struct ib_mad_hdr *)wr->send_buf.mad)->base_version;
+		__entry->mgmt_class =
+			((struct ib_mad_hdr *)wr->send_buf.mad)->mgmt_class;
+		__entry->class_version =
+			((struct ib_mad_hdr *)wr->send_buf.mad)->class_version;
+		__entry->method =
+			((struct ib_mad_hdr *)wr->send_buf.mad)->method;
+		__entry->status =
+			((struct ib_mad_hdr *)wr->send_buf.mad)->status;
+		__entry->wc_status = wc->status;
+		__entry->length = wc->byte_len;
+	),
+
+	TP_printk("%d:%d QP%d : SEND WC Status %d : agent %p: " \
+		  "wrtid 0x%llx %d/%d retries(%d) timeout %lu length %d: " \
+		  "hdr : base_ver 0x%x class 0x%x class_ver 0x%x " \
+		  "method 0x%x status 0x%x",
+		__entry->dev_index, __entry->port_num, __entry->qp_num,
+		__entry->wc_status,
+		__entry->agent_priv, be64_to_cpu(__entry->wrtid),
+		__entry->retries_left, __entry->max_retries,
+		__entry->retry, __entry->timeout,
+		__entry->length,
+		__entry->base_version, __entry->mgmt_class,
+		__entry->class_version, __entry->method,
+		be16_to_cpu(__entry->status)
+	)
+);
+
+
+#endif /* _TRACE_IB_MAD_H */
+
+#include <trace/define_trace.h>