2021-08-23 04:26:22 +00:00
|
|
|
/* SPDX-License-Identifier: GPL-2.0 or BSD-3-Clause */
|
2016-07-01 23:01:06 +00:00
|
|
|
/*
|
IB/{hfi1, rdmavt, qib}: Implement CQ completion vector support
Currently the driver doesn't support completion vectors. These
are used to indicate which sets of CQs should be grouped together
into the same vector. A vector is a CQ processing thread that
runs on a specific CPU.
If an application has several CQs bound to different completion
vectors, and each completion vector runs on different CPUs, then
the completion queue workload is balanced. This helps scale as more
nodes are used.
Implement CQ completion vector support using a global workqueue
where a CQ entry is queued to the CPU corresponding to the CQ's
completion vector. Since the workqueue is global, it's guaranteed
to always be there when queueing CQ entries; Therefore, the RCU
locking for cq->rdi->worker in the hot path is superfluous.
Each completion vector is assigned to a different CPU. The number of
completion vectors available is computed by taking the number of
online, physical CPUs from the local NUMA node and subtracting the
CPUs used for kernel receive queues and the general interrupt.
Special use cases:
* If there are no CPUs left for completion vectors, the same CPU
for the general interrupt is used; Therefore, there would only
be one completion vector available.
* For multi-HFI systems, the number of completion vectors available
for each device is the total number of completion vectors in
the local NUMA node divided by the number of devices in the same
NUMA node. If there's a division remainder, the first device to
get initialized gets an extra completion vector.
Upon a CQ creation, an invalid completion vector could be specified.
Handle it as follows:
* If the completion vector is less than 0, set it to 0.
* Set the completion vector to the result of the passed completion
vector moded with the number of device completion vectors
available.
Reviewed-by: Mike Marciniszyn <mike.marciniszyn@intel.com>
Signed-off-by: Sebastian Sanchez <sebastian.sanchez@intel.com>
Signed-off-by: Dennis Dalessandro <dennis.dalessandro@intel.com>
Signed-off-by: Doug Ledford <dledford@redhat.com>
2018-05-02 13:43:55 +00:00
|
|
|
* Copyright(c) 2015 - 2018 Intel Corporation.
|
2016-07-01 23:01:06 +00:00
|
|
|
*/
|
2021-08-23 04:26:22 +00:00
|
|
|
|
2016-07-01 23:01:06 +00:00
|
|
|
#if !defined(__HFI1_TRACE_EXTRA_H) || defined(TRACE_HEADER_MULTI_READ)
|
|
|
|
#define __HFI1_TRACE_EXTRA_H
|
|
|
|
|
|
|
|
#include <linux/tracepoint.h>
|
|
|
|
#include <linux/trace_seq.h>
|
|
|
|
|
|
|
|
#include "hfi.h"
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Note:
|
|
|
|
* This produces a REALLY ugly trace in the console output when the string is
|
|
|
|
* too long.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#undef TRACE_SYSTEM
|
|
|
|
#define TRACE_SYSTEM hfi1_dbg
|
|
|
|
|
|
|
|
#define MAX_MSG_LEN 512
|
|
|
|
|
|
|
|
DECLARE_EVENT_CLASS(hfi1_trace_template,
|
|
|
|
TP_PROTO(const char *function, struct va_format *vaf),
|
|
|
|
TP_ARGS(function, vaf),
|
|
|
|
TP_STRUCT__entry(__string(function, function)
|
|
|
|
__dynamic_array(char, msg, MAX_MSG_LEN)
|
|
|
|
),
|
|
|
|
TP_fast_assign(__assign_str(function, function);
|
|
|
|
WARN_ON_ONCE(vsnprintf
|
|
|
|
(__get_dynamic_array(msg),
|
|
|
|
MAX_MSG_LEN, vaf->fmt,
|
|
|
|
*vaf->va) >=
|
|
|
|
MAX_MSG_LEN);
|
|
|
|
),
|
|
|
|
TP_printk("(%s) %s",
|
|
|
|
__get_str(function),
|
|
|
|
__get_str(msg))
|
|
|
|
);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* It may be nice to macroize the __hfi1_trace but the va_* stuff requires an
|
|
|
|
* actual function to work and can not be in a macro.
|
|
|
|
*/
|
|
|
|
#define __hfi1_trace_def(lvl) \
|
2019-03-27 23:50:50 +00:00
|
|
|
void __printf(2, 3) __hfi1_trace_##lvl(const char *funct, char *fmt, ...); \
|
2016-07-01 23:01:06 +00:00
|
|
|
\
|
|
|
|
DEFINE_EVENT(hfi1_trace_template, hfi1_ ##lvl, \
|
|
|
|
TP_PROTO(const char *function, struct va_format *vaf), \
|
|
|
|
TP_ARGS(function, vaf))
|
|
|
|
|
|
|
|
#define __hfi1_trace_fn(lvl) \
|
2019-03-27 23:50:50 +00:00
|
|
|
void __printf(2, 3) __hfi1_trace_##lvl(const char *func, char *fmt, ...)\
|
2016-07-01 23:01:06 +00:00
|
|
|
{ \
|
|
|
|
struct va_format vaf = { \
|
|
|
|
.fmt = fmt, \
|
|
|
|
}; \
|
|
|
|
va_list args; \
|
|
|
|
\
|
|
|
|
va_start(args, fmt); \
|
|
|
|
vaf.va = &args; \
|
|
|
|
trace_hfi1_ ##lvl(func, &vaf); \
|
|
|
|
va_end(args); \
|
|
|
|
return; \
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* To create a new trace level simply define it below and as a __hfi1_trace_fn
|
|
|
|
* in trace.c. This will create all the hooks for calling
|
|
|
|
* hfi1_cdbg(LVL, fmt, ...); as well as take care of all
|
|
|
|
* the debugfs stuff.
|
|
|
|
*/
|
IB/{hfi1, rdmavt, qib}: Implement CQ completion vector support
Currently the driver doesn't support completion vectors. These
are used to indicate which sets of CQs should be grouped together
into the same vector. A vector is a CQ processing thread that
runs on a specific CPU.
If an application has several CQs bound to different completion
vectors, and each completion vector runs on different CPUs, then
the completion queue workload is balanced. This helps scale as more
nodes are used.
Implement CQ completion vector support using a global workqueue
where a CQ entry is queued to the CPU corresponding to the CQ's
completion vector. Since the workqueue is global, it's guaranteed
to always be there when queueing CQ entries; Therefore, the RCU
locking for cq->rdi->worker in the hot path is superfluous.
Each completion vector is assigned to a different CPU. The number of
completion vectors available is computed by taking the number of
online, physical CPUs from the local NUMA node and subtracting the
CPUs used for kernel receive queues and the general interrupt.
Special use cases:
* If there are no CPUs left for completion vectors, the same CPU
for the general interrupt is used; Therefore, there would only
be one completion vector available.
* For multi-HFI systems, the number of completion vectors available
for each device is the total number of completion vectors in
the local NUMA node divided by the number of devices in the same
NUMA node. If there's a division remainder, the first device to
get initialized gets an extra completion vector.
Upon a CQ creation, an invalid completion vector could be specified.
Handle it as follows:
* If the completion vector is less than 0, set it to 0.
* Set the completion vector to the result of the passed completion
vector moded with the number of device completion vectors
available.
Reviewed-by: Mike Marciniszyn <mike.marciniszyn@intel.com>
Signed-off-by: Sebastian Sanchez <sebastian.sanchez@intel.com>
Signed-off-by: Dennis Dalessandro <dennis.dalessandro@intel.com>
Signed-off-by: Doug Ledford <dledford@redhat.com>
2018-05-02 13:43:55 +00:00
|
|
|
__hfi1_trace_def(AFFINITY);
|
2016-07-01 23:01:06 +00:00
|
|
|
__hfi1_trace_def(PKT);
|
|
|
|
__hfi1_trace_def(PROC);
|
|
|
|
__hfi1_trace_def(SDMA);
|
|
|
|
__hfi1_trace_def(LINKVERB);
|
|
|
|
__hfi1_trace_def(DEBUG);
|
|
|
|
__hfi1_trace_def(SNOOP);
|
|
|
|
__hfi1_trace_def(CNTR);
|
|
|
|
__hfi1_trace_def(PIO);
|
|
|
|
__hfi1_trace_def(DC8051);
|
|
|
|
__hfi1_trace_def(FIRMWARE);
|
|
|
|
__hfi1_trace_def(RCVCTRL);
|
|
|
|
__hfi1_trace_def(TID);
|
|
|
|
__hfi1_trace_def(MMU);
|
|
|
|
__hfi1_trace_def(IOCTL);
|
|
|
|
|
|
|
|
#define hfi1_cdbg(which, fmt, ...) \
|
|
|
|
__hfi1_trace_##which(__func__, fmt, ##__VA_ARGS__)
|
|
|
|
|
|
|
|
#define hfi1_dbg(fmt, ...) \
|
|
|
|
hfi1_cdbg(DEBUG, fmt, ##__VA_ARGS__)
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Define HFI1_EARLY_DBG at compile time or here to enable early trace
|
|
|
|
* messages. Do not check in an enablement for this.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#ifdef HFI1_EARLY_DBG
|
|
|
|
#define hfi1_dbg_early(fmt, ...) \
|
|
|
|
trace_printk(fmt, ##__VA_ARGS__)
|
|
|
|
#else
|
|
|
|
#define hfi1_dbg_early(fmt, ...)
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#endif /* __HFI1_TRACE_EXTRA_H */
|
|
|
|
|
|
|
|
#undef TRACE_INCLUDE_PATH
|
|
|
|
#undef TRACE_INCLUDE_FILE
|
|
|
|
#define TRACE_INCLUDE_PATH .
|
|
|
|
#define TRACE_INCLUDE_FILE trace_dbg
|
|
|
|
#include <trace/define_trace.h>
|