* [PATCH for-next 1/5] IB/core: Add DC transport support
[not found] ` <1415289159-4376-1-git-send-email-eli-VPRAkNaXOzVWk0Htik3J/w@public.gmane.org>
@ 2014-11-06 15:52 ` Eli Cohen
[not found] ` <1415289159-4376-2-git-send-email-eli-VPRAkNaXOzVWk0Htik3J/w@public.gmane.org>
2014-11-06 15:52 ` [PATCH for-next 2/5] IB/uverbs: Add userspace interface to DC verbs Eli Cohen
` (3 subsequent siblings)
4 siblings, 1 reply; 8+ messages in thread
From: Eli Cohen @ 2014-11-06 15:52 UTC (permalink / raw)
To: roland-DgEjT+Ai2ygdnm+yROfE0A
Cc: linux-rdma-u79uwXL29TY76Z2rM5mHXA,
ogerlitz-VPRAkNaXOzVWk0Htik3J/w, richardg-VPRAkNaXOzVWk0Htik3J/w,
yevgenyp-VPRAkNaXOzVWk0Htik3J/w, Eli Cohen
The Dynamically Connected (DC) Transport Service provides a reliable
datagram-like model that allows a single sender to target multiple destinations
from the same QP, keeping the communication resource footprint essentially
independent of system size. DC supports RDMA read and write operations, as well
as atomic variable updates. With this transport a DC initiator QP may be used
to target multiple remote DC Targets, in one or more remote processes. As far
as reachability is concerned, the DC model is somewhat similar to the
Unreliable Datagram (UD) model in the sense that each WR submitted to the DC SQ
carries the information that identifies the remote destination. DC contexts are
then dynamically tied to each other across the network to create a temporary
RC-equivalent connection that is used to reliably deliver one or more messages.
This dynamic connection is created in-band and pipelined with the subsequent
data communication thus eliminating most of the cost associated with the 3-way
handshake off the Connection Manager protocol used for connecting RC QPs. When
all WRs posted to that remote network address are acknowledged, the initiator
sends a disconnect request to the responder, thereby releasing the responder
resources.
A DC initiator is yet another type of QP identified by a new transport type,
IB_QPT_DC_INI. The target is end is presented by a new object of type ib_dct.
This patch extend the verbs API with the following new APIs:
ib_create_dc - Create a DC target
ib_destroy_dct - Destroy a DC target
ib_query_dct - query DC target
ib_arm_dct - Arm a DC target to generate asynchronous event on DC key
violation. Once a event is generated, the DC target moves to a fired state and
will not generated further key violation events unless re-armed.
ib_modify_qp_ex - is an extension to ib_modify_qp which allows to pass the 64
bit DC key.
Signed-off-by: Eli Cohen <eli-VPRAkNaXOzVWk0Htik3J/w@public.gmane.org>
---
drivers/infiniband/core/verbs.c | 87 +++++++++++++++++++++++++++++++++++++++++
include/rdma/ib_verbs.h | 87 ++++++++++++++++++++++++++++++++++++++++-
2 files changed, 172 insertions(+), 2 deletions(-)
diff --git a/drivers/infiniband/core/verbs.c b/drivers/infiniband/core/verbs.c
index c2b89cc5dbca..c2b2d00c9794 100644
--- a/drivers/infiniband/core/verbs.c
+++ b/drivers/infiniband/core/verbs.c
@@ -521,6 +521,9 @@ static const struct {
[IB_QPT_RC] = (IB_QP_PKEY_INDEX |
IB_QP_PORT |
IB_QP_ACCESS_FLAGS),
+ [IB_QPT_DC_INI] = (IB_QP_PKEY_INDEX |
+ IB_QP_PORT |
+ IB_QP_DC_KEY),
[IB_QPT_XRC_INI] = (IB_QP_PKEY_INDEX |
IB_QP_PORT |
IB_QP_ACCESS_FLAGS),
@@ -549,6 +552,9 @@ static const struct {
[IB_QPT_RC] = (IB_QP_PKEY_INDEX |
IB_QP_PORT |
IB_QP_ACCESS_FLAGS),
+ [IB_QPT_DC_INI] = (IB_QP_PKEY_INDEX |
+ IB_QP_PORT |
+ IB_QP_DC_KEY),
[IB_QPT_XRC_INI] = (IB_QP_PKEY_INDEX |
IB_QP_PORT |
IB_QP_ACCESS_FLAGS),
@@ -574,6 +580,8 @@ static const struct {
IB_QP_RQ_PSN |
IB_QP_MAX_DEST_RD_ATOMIC |
IB_QP_MIN_RNR_TIMER),
+ [IB_QPT_DC_INI] = (IB_QP_AV |
+ IB_QP_PATH_MTU),
[IB_QPT_XRC_INI] = (IB_QP_AV |
IB_QP_PATH_MTU |
IB_QP_DEST_QPN |
@@ -600,6 +608,8 @@ static const struct {
[IB_QPT_RC] = (IB_QP_ALT_PATH |
IB_QP_ACCESS_FLAGS |
IB_QP_PKEY_INDEX),
+ [IB_QPT_DC_INI] = (IB_QP_PKEY_INDEX |
+ IB_QP_DC_KEY),
[IB_QPT_XRC_INI] = (IB_QP_ALT_PATH |
IB_QP_ACCESS_FLAGS |
IB_QP_PKEY_INDEX),
@@ -640,6 +650,10 @@ static const struct {
IB_QP_RNR_RETRY |
IB_QP_SQ_PSN |
IB_QP_MAX_QP_RD_ATOMIC),
+ [IB_QPT_DC_INI] = (IB_QP_TIMEOUT |
+ IB_QP_RETRY_CNT |
+ IB_QP_RNR_RETRY |
+ IB_QP_MAX_QP_RD_ATOMIC),
[IB_QPT_XRC_INI] = (IB_QP_TIMEOUT |
IB_QP_RETRY_CNT |
IB_QP_RNR_RETRY |
@@ -662,6 +676,10 @@ static const struct {
IB_QP_ACCESS_FLAGS |
IB_QP_MIN_RNR_TIMER |
IB_QP_PATH_MIG_STATE),
+ [IB_QPT_DC_INI] = (IB_QP_CUR_STATE |
+ IB_QP_ALT_PATH |
+ IB_QP_MIN_RNR_TIMER |
+ IB_QP_PATH_MIG_STATE),
[IB_QPT_XRC_INI] = (IB_QP_CUR_STATE |
IB_QP_ALT_PATH |
IB_QP_ACCESS_FLAGS |
@@ -695,6 +713,10 @@ static const struct {
IB_QP_ALT_PATH |
IB_QP_PATH_MIG_STATE |
IB_QP_MIN_RNR_TIMER),
+ [IB_QPT_DC_INI] = (IB_QP_CUR_STATE |
+ IB_QP_ALT_PATH |
+ IB_QP_PATH_MIG_STATE |
+ IB_QP_MIN_RNR_TIMER),
[IB_QPT_XRC_INI] = (IB_QP_CUR_STATE |
IB_QP_ACCESS_FLAGS |
IB_QP_ALT_PATH |
@@ -1438,6 +1460,71 @@ int ib_destroy_flow(struct ib_flow *flow_id)
}
EXPORT_SYMBOL(ib_destroy_flow);
+struct ib_dct *ib_create_dct(struct ib_pd *pd, struct ib_dct_init_attr *attr,
+ struct ib_udata *uhw)
+{
+ struct ib_dct *dct;
+
+ if (!pd->device->create_dct)
+ return ERR_PTR(-ENOSYS);
+
+ dct = pd->device->create_dct(pd, attr, uhw);
+ if (!IS_ERR(dct)) {
+ dct->pd = pd;
+ dct->srq = attr->srq;
+ dct->cq = attr->cq;
+ atomic_inc(&dct->srq->usecnt);
+ atomic_inc(&dct->cq->usecnt);
+ atomic_inc(&dct->pd->usecnt);
+ }
+
+ return dct;
+}
+EXPORT_SYMBOL(ib_create_dct);
+
+int ib_destroy_dct(struct ib_dct *dct, struct ib_udata *uhw)
+{
+ struct ib_srq *srq;
+ struct ib_cq *cq;
+ struct ib_pd *pd;
+ int err;
+
+ if (!dct->device->destroy_dct)
+ return -ENOSYS;
+
+ srq = dct->srq;
+ cq = dct->cq;
+ pd = dct->pd;
+ err = dct->device->destroy_dct(dct, uhw);
+ if (!err) {
+ atomic_dec(&srq->usecnt);
+ atomic_dec(&cq->usecnt);
+ atomic_dec(&pd->usecnt);
+ }
+
+ return err;
+}
+EXPORT_SYMBOL(ib_destroy_dct);
+
+int ib_query_dct(struct ib_dct *dct, struct ib_dct_attr *attr,
+ struct ib_udata *uhw)
+{
+ if (!dct->device->query_dct)
+ return -ENOSYS;
+
+ return dct->device->query_dct(dct, attr, uhw);
+}
+EXPORT_SYMBOL(ib_query_dct);
+
+int ib_arm_dct(struct ib_dct *dct, struct ib_udata *uhw)
+{
+ if (!dct->device->arm_dct)
+ return -ENOSYS;
+
+ return dct->device->arm_dct(dct, uhw);
+}
+EXPORT_SYMBOL(ib_arm_dct);
+
int ib_check_mr_status(struct ib_mr *mr, u32 check_mask,
struct ib_mr_status *mr_status)
{
diff --git a/include/rdma/ib_verbs.h b/include/rdma/ib_verbs.h
index 2b65e31ca298..9c67cffe1ecc 100644
--- a/include/rdma/ib_verbs.h
+++ b/include/rdma/ib_verbs.h
@@ -123,7 +123,14 @@ enum ib_device_cap_flags {
IB_DEVICE_MEM_WINDOW_TYPE_2A = (1<<23),
IB_DEVICE_MEM_WINDOW_TYPE_2B = (1<<24),
IB_DEVICE_MANAGED_FLOW_STEERING = (1<<29),
- IB_DEVICE_SIGNATURE_HANDOVER = (1<<30)
+ IB_DEVICE_SIGNATURE_HANDOVER = (1<<30),
+ IB_DEVICE_DC_TRANSPORT = ((u64)1<<32),
+};
+
+enum {
+ IB_DCT_STATE_ACTIVE,
+ IB_DCT_STATE_DRAINING,
+ IB_DCT_STATE_DRAINED
};
enum ib_signature_prot_cap {
@@ -155,7 +162,7 @@ struct ib_device_attr {
u32 hw_ver;
int max_qp;
int max_qp_wr;
- int device_cap_flags;
+ u64 device_cap_flags;
int max_sge;
int max_sge_rd;
int max_cq;
@@ -191,6 +198,8 @@ struct ib_device_attr {
u32 log_atomic_arg_sizes; /* bit-mask of supported sizes */
u32 max_fa_bit_boundary;
u32 log_max_atomic_inline;
+ uint32_t dc_rd_req;
+ uint32_t dc_rd_res;
};
enum ib_mtu {
@@ -391,6 +400,9 @@ enum ib_event_type {
IB_EVENT_QP_LAST_WQE_REACHED,
IB_EVENT_CLIENT_REREGISTER,
IB_EVENT_GID_CHANGE,
+ IB_EVENT_DCT_KEY_VIOLATION,
+ IB_EVENT_DCT_ACCESS_ERR,
+ IB_EVENT_DCT_REQ_ERR,
};
struct ib_event {
@@ -399,6 +411,7 @@ struct ib_event {
struct ib_cq *cq;
struct ib_qp *qp;
struct ib_srq *srq;
+ struct ib_dct *dct;
u8 port_num;
} element;
enum ib_event_type event;
@@ -762,6 +775,7 @@ enum ib_qp_type {
IB_QPT_RAW_PACKET = 8,
IB_QPT_XRC_INI = 9,
IB_QPT_XRC_TGT,
+ IB_QPT_DC_INI,
IB_QPT_MAX,
/* Reserve a range for qp types internal to the low level driver.
* These qp types will not be visible at the IB core layer, so the
@@ -878,6 +892,7 @@ enum ib_qp_attr_mask {
IB_QP_ALT_SMAC = (1<<22),
IB_QP_VID = (1<<23),
IB_QP_ALT_VID = (1<<24),
+ IB_QP_DC_KEY = (1<<25),
};
enum ib_qp_state {
@@ -931,6 +946,7 @@ struct ib_qp_attr {
u8 alt_smac[ETH_ALEN];
u16 vlan_id;
u16 alt_vlan_id;
+ u64 dct_key;
};
enum ib_wr_opcode {
@@ -1393,6 +1409,58 @@ struct ib_cache {
u8 *lmc_cache;
};
+struct ib_dct {
+ struct ib_device *device;
+ struct ib_uobject *uobject;
+ struct ib_pd *pd;
+ struct ib_cq *cq;
+ struct ib_srq *srq;
+ void *dct_context;
+ u32 dct_num;
+
+ void (*event_handler)(struct ib_event *, void *);
+};
+
+enum {
+ IB_DCT_CREATE_FLAGS_MASK = 0,
+};
+
+struct ib_dct_init_attr {
+ struct ib_pd *pd;
+ struct ib_cq *cq;
+ struct ib_srq *srq;
+ u64 dc_key;
+ u8 port;
+ u32 access_flags;
+ u8 min_rnr_timer;
+ u8 tclass;
+ u32 flow_label;
+ enum ib_mtu mtu;
+ u8 pkey_index;
+ u8 gid_index;
+ u8 hop_limit;
+ u32 create_flags;
+ u32 inline_size;
+ void *dct_context;
+
+ void (*event_handler)(struct ib_event *, void *);
+};
+
+struct ib_dct_attr {
+ u64 dc_key;
+ u8 port;
+ u32 access_flags;
+ u8 min_rnr_timer;
+ u8 tclass;
+ u32 flow_label;
+ enum ib_mtu mtu;
+ u8 pkey_index;
+ u8 gid_index;
+ u8 hop_limit;
+ u32 key_violations;
+ u8 state;
+};
+
struct ib_dma_mapping_ops {
int (*mapping_error)(struct ib_device *dev,
u64 dma_addr);
@@ -1612,6 +1680,15 @@ struct ib_device {
int (*destroy_flow)(struct ib_flow *flow_id);
int (*check_mr_status)(struct ib_mr *mr, u32 check_mask,
struct ib_mr_status *mr_status);
+ struct ib_dct * (*create_dct)(struct ib_pd *pd,
+ struct ib_dct_init_attr *attr,
+ struct ib_udata *uhw);
+ int (*destroy_dct)(struct ib_dct *dct,
+ struct ib_udata *uhw);
+ int (*query_dct)(struct ib_dct *dct,
+ struct ib_dct_attr *attr,
+ struct ib_udata *uhw);
+ int (*arm_dct)(struct ib_dct *dct, struct ib_udata *uhw);
struct ib_dma_mapping_ops *dma_ops;
@@ -2602,6 +2679,12 @@ int ib_dealloc_xrcd(struct ib_xrcd *xrcd);
struct ib_flow *ib_create_flow(struct ib_qp *qp,
struct ib_flow_attr *flow_attr, int domain);
int ib_destroy_flow(struct ib_flow *flow_id);
+struct ib_dct *ib_create_dct(struct ib_pd *pd, struct ib_dct_init_attr *attr,
+ struct ib_udata *uhw);
+int ib_destroy_dct(struct ib_dct *dct, struct ib_udata *uhw);
+int ib_query_dct(struct ib_dct *dct, struct ib_dct_attr *attr,
+ struct ib_udata *uhw);
+int ib_arm_dct(struct ib_dct *dct, struct ib_udata *uhw);
static inline int ib_check_mr_access(int flags)
{
--
2.1.2
--
To unsubscribe from this list: send the line "unsubscribe linux-rdma" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply related [flat|nested] 8+ messages in thread* [PATCH for-next 2/5] IB/uverbs: Add userspace interface to DC verbs
[not found] ` <1415289159-4376-1-git-send-email-eli-VPRAkNaXOzVWk0Htik3J/w@public.gmane.org>
2014-11-06 15:52 ` [PATCH for-next 1/5] IB/core: Add DC transport support Eli Cohen
@ 2014-11-06 15:52 ` Eli Cohen
2014-11-06 15:52 ` [PATCH for-next 3/5] mlx5_core: Add DC support at mlx5 core layer Eli Cohen
` (2 subsequent siblings)
4 siblings, 0 replies; 8+ messages in thread
From: Eli Cohen @ 2014-11-06 15:52 UTC (permalink / raw)
To: roland-DgEjT+Ai2ygdnm+yROfE0A
Cc: linux-rdma-u79uwXL29TY76Z2rM5mHXA,
ogerlitz-VPRAkNaXOzVWk0Htik3J/w, richardg-VPRAkNaXOzVWk0Htik3J/w,
yevgenyp-VPRAkNaXOzVWk0Htik3J/w, Eli Cohen
Signed-off-by: Eli Cohen <eli-VPRAkNaXOzVWk0Htik3J/w@public.gmane.org>
---
drivers/infiniband/core/uverbs.h | 11 +
drivers/infiniband/core/uverbs_cmd.c | 474 +++++++++++++++++++++++++++++-----
drivers/infiniband/core/uverbs_main.c | 35 ++-
include/rdma/ib_verbs.h | 1 +
include/uapi/rdma/ib_user_verbs.h | 126 ++++++++-
5 files changed, 584 insertions(+), 63 deletions(-)
diff --git a/drivers/infiniband/core/uverbs.h b/drivers/infiniband/core/uverbs.h
index b716b0815644..3343696df6b1 100644
--- a/drivers/infiniband/core/uverbs.h
+++ b/drivers/infiniband/core/uverbs.h
@@ -163,6 +163,10 @@ struct ib_ucq_object {
u32 async_events_reported;
};
+struct ib_udct_object {
+ struct ib_uevent_object uevent;
+};
+
extern spinlock_t ib_uverbs_idr_lock;
extern struct idr ib_uverbs_pd_idr;
extern struct idr ib_uverbs_mr_idr;
@@ -173,6 +177,7 @@ extern struct idr ib_uverbs_qp_idr;
extern struct idr ib_uverbs_srq_idr;
extern struct idr ib_uverbs_xrcd_idr;
extern struct idr ib_uverbs_rule_idr;
+extern struct idr ib_uverbs_dct_idr;
void idr_remove_uobj(struct idr *idp, struct ib_uobject *uobj);
@@ -189,6 +194,7 @@ void ib_uverbs_release_uevent(struct ib_uverbs_file *file,
void ib_uverbs_comp_handler(struct ib_cq *cq, void *cq_context);
void ib_uverbs_cq_event_handler(struct ib_event *event, void *context_ptr);
void ib_uverbs_qp_event_handler(struct ib_event *event, void *context_ptr);
+void ib_uverbs_dct_event_handler(struct ib_event *event, void *context_ptr);
void ib_uverbs_srq_event_handler(struct ib_event *event, void *context_ptr);
void ib_uverbs_event_handler(struct ib_event_handler *handler,
struct ib_event *event);
@@ -259,5 +265,10 @@ IB_UVERBS_DECLARE_CMD(close_xrcd);
IB_UVERBS_DECLARE_EX_CMD(create_flow);
IB_UVERBS_DECLARE_EX_CMD(destroy_flow);
IB_UVERBS_DECLARE_EX_CMD(query_device);
+IB_UVERBS_DECLARE_EX_CMD(create_dct);
+IB_UVERBS_DECLARE_EX_CMD(destroy_dct);
+IB_UVERBS_DECLARE_EX_CMD(query_dct);
+IB_UVERBS_DECLARE_EX_CMD(arm_dct);
+IB_UVERBS_DECLARE_EX_CMD(modify_qp);
#endif /* UVERBS_H */
diff --git a/drivers/infiniband/core/uverbs_cmd.c b/drivers/infiniband/core/uverbs_cmd.c
index 0bc215fa2a85..e2a1f691315c 100644
--- a/drivers/infiniband/core/uverbs_cmd.c
+++ b/drivers/infiniband/core/uverbs_cmd.c
@@ -56,6 +56,7 @@ static struct uverbs_lock_class ah_lock_class = { .name = "AH-uobj" };
static struct uverbs_lock_class srq_lock_class = { .name = "SRQ-uobj" };
static struct uverbs_lock_class xrcd_lock_class = { .name = "XRCD-uobj" };
static struct uverbs_lock_class rule_lock_class = { .name = "RULE-uobj" };
+static struct uverbs_lock_class dct_lock_class = { .name = "DCT-uobj" };
/*
* The ib_uobject locking scheme is as follows:
@@ -258,6 +259,16 @@ static void put_qp_write(struct ib_qp *qp)
put_uobj_write(qp->uobject);
}
+static struct ib_dct *idr_read_dct(int dct_handle, struct ib_ucontext *context)
+{
+ return idr_read_obj(&ib_uverbs_dct_idr, dct_handle, context, 0);
+}
+
+static void put_dct_read(struct ib_dct *dct)
+{
+ put_uobj_read(dct->uobject);
+}
+
static struct ib_srq *idr_read_srq(int srq_handle, struct ib_ucontext *context)
{
return idr_read_obj(&ib_uverbs_srq_idr, srq_handle, context, 0);
@@ -325,6 +336,7 @@ ssize_t ib_uverbs_get_context(struct ib_uverbs_file *file,
INIT_LIST_HEAD(&ucontext->ah_list);
INIT_LIST_HEAD(&ucontext->xrcd_list);
INIT_LIST_HEAD(&ucontext->rule_list);
+ INIT_LIST_HEAD(&ucontext->dct_list);
ucontext->closing = 0;
resp.num_comp_vectors = file->device->num_comp_vectors;
@@ -1990,86 +2002,79 @@ static int modify_qp_mask(enum ib_qp_type qp_type, int mask)
}
}
-ssize_t ib_uverbs_modify_qp(struct ib_uverbs_file *file,
- const char __user *buf, int in_len,
- int out_len)
+static ssize_t modify_qp(struct ib_uverbs_file *file,
+ struct ib_uverbs_modify_qp_ex *cmd,
+ struct ib_udata *udata)
{
- struct ib_uverbs_modify_qp cmd;
- struct ib_udata udata;
struct ib_qp *qp;
struct ib_qp_attr *attr;
int ret;
- if (copy_from_user(&cmd, buf, sizeof cmd))
- return -EFAULT;
-
- INIT_UDATA(&udata, buf + sizeof cmd, NULL, in_len - sizeof cmd,
- out_len);
-
attr = kmalloc(sizeof *attr, GFP_KERNEL);
if (!attr)
return -ENOMEM;
- qp = idr_read_qp(cmd.qp_handle, file->ucontext);
+ qp = idr_read_qp(cmd->qp_handle, file->ucontext);
if (!qp) {
ret = -EINVAL;
goto out;
}
- attr->qp_state = cmd.qp_state;
- attr->cur_qp_state = cmd.cur_qp_state;
- attr->path_mtu = cmd.path_mtu;
- attr->path_mig_state = cmd.path_mig_state;
- attr->qkey = cmd.qkey;
- attr->rq_psn = cmd.rq_psn;
- attr->sq_psn = cmd.sq_psn;
- attr->dest_qp_num = cmd.dest_qp_num;
- attr->qp_access_flags = cmd.qp_access_flags;
- attr->pkey_index = cmd.pkey_index;
- attr->alt_pkey_index = cmd.alt_pkey_index;
- attr->en_sqd_async_notify = cmd.en_sqd_async_notify;
- attr->max_rd_atomic = cmd.max_rd_atomic;
- attr->max_dest_rd_atomic = cmd.max_dest_rd_atomic;
- attr->min_rnr_timer = cmd.min_rnr_timer;
- attr->port_num = cmd.port_num;
- attr->timeout = cmd.timeout;
- attr->retry_cnt = cmd.retry_cnt;
- attr->rnr_retry = cmd.rnr_retry;
- attr->alt_port_num = cmd.alt_port_num;
- attr->alt_timeout = cmd.alt_timeout;
-
- memcpy(attr->ah_attr.grh.dgid.raw, cmd.dest.dgid, 16);
- attr->ah_attr.grh.flow_label = cmd.dest.flow_label;
- attr->ah_attr.grh.sgid_index = cmd.dest.sgid_index;
- attr->ah_attr.grh.hop_limit = cmd.dest.hop_limit;
- attr->ah_attr.grh.traffic_class = cmd.dest.traffic_class;
- attr->ah_attr.dlid = cmd.dest.dlid;
- attr->ah_attr.sl = cmd.dest.sl;
- attr->ah_attr.src_path_bits = cmd.dest.src_path_bits;
- attr->ah_attr.static_rate = cmd.dest.static_rate;
- attr->ah_attr.ah_flags = cmd.dest.is_global ? IB_AH_GRH : 0;
- attr->ah_attr.port_num = cmd.dest.port_num;
-
- memcpy(attr->alt_ah_attr.grh.dgid.raw, cmd.alt_dest.dgid, 16);
- attr->alt_ah_attr.grh.flow_label = cmd.alt_dest.flow_label;
- attr->alt_ah_attr.grh.sgid_index = cmd.alt_dest.sgid_index;
- attr->alt_ah_attr.grh.hop_limit = cmd.alt_dest.hop_limit;
- attr->alt_ah_attr.grh.traffic_class = cmd.alt_dest.traffic_class;
- attr->alt_ah_attr.dlid = cmd.alt_dest.dlid;
- attr->alt_ah_attr.sl = cmd.alt_dest.sl;
- attr->alt_ah_attr.src_path_bits = cmd.alt_dest.src_path_bits;
- attr->alt_ah_attr.static_rate = cmd.alt_dest.static_rate;
- attr->alt_ah_attr.ah_flags = cmd.alt_dest.is_global ? IB_AH_GRH : 0;
- attr->alt_ah_attr.port_num = cmd.alt_dest.port_num;
+ attr->qp_state = cmd->qp_state;
+ attr->cur_qp_state = cmd->cur_qp_state;
+ attr->path_mtu = cmd->path_mtu;
+ attr->path_mig_state = cmd->path_mig_state;
+ attr->qkey = cmd->qkey;
+ attr->rq_psn = cmd->rq_psn;
+ attr->sq_psn = cmd->sq_psn;
+ attr->dest_qp_num = cmd->dest_qp_num;
+ attr->qp_access_flags = cmd->qp_access_flags;
+ attr->pkey_index = cmd->pkey_index;
+ attr->alt_pkey_index = cmd->alt_pkey_index;
+ attr->en_sqd_async_notify = cmd->en_sqd_async_notify;
+ attr->max_rd_atomic = cmd->max_rd_atomic;
+ attr->max_dest_rd_atomic = cmd->max_dest_rd_atomic;
+ attr->min_rnr_timer = cmd->min_rnr_timer;
+ attr->port_num = cmd->port_num;
+ attr->timeout = cmd->timeout;
+ attr->retry_cnt = cmd->retry_cnt;
+ attr->rnr_retry = cmd->rnr_retry;
+ attr->alt_port_num = cmd->alt_port_num;
+ attr->alt_timeout = cmd->alt_timeout;
+ attr->dct_key = cmd->dct_key;
+
+ memcpy(attr->ah_attr.grh.dgid.raw, cmd->dest.dgid, 16);
+ attr->ah_attr.grh.flow_label = cmd->dest.flow_label;
+ attr->ah_attr.grh.sgid_index = cmd->dest.sgid_index;
+ attr->ah_attr.grh.hop_limit = cmd->dest.hop_limit;
+ attr->ah_attr.grh.traffic_class = cmd->dest.traffic_class;
+ attr->ah_attr.dlid = cmd->dest.dlid;
+ attr->ah_attr.sl = cmd->dest.sl;
+ attr->ah_attr.src_path_bits = cmd->dest.src_path_bits;
+ attr->ah_attr.static_rate = cmd->dest.static_rate;
+ attr->ah_attr.ah_flags = cmd->dest.is_global ? IB_AH_GRH : 0;
+ attr->ah_attr.port_num = cmd->dest.port_num;
+
+ memcpy(attr->alt_ah_attr.grh.dgid.raw, cmd->alt_dest.dgid, 16);
+ attr->alt_ah_attr.grh.flow_label = cmd->alt_dest.flow_label;
+ attr->alt_ah_attr.grh.sgid_index = cmd->alt_dest.sgid_index;
+ attr->alt_ah_attr.grh.hop_limit = cmd->alt_dest.hop_limit;
+ attr->alt_ah_attr.grh.traffic_class = cmd->alt_dest.traffic_class;
+ attr->alt_ah_attr.dlid = cmd->alt_dest.dlid;
+ attr->alt_ah_attr.sl = cmd->alt_dest.sl;
+ attr->alt_ah_attr.src_path_bits = cmd->alt_dest.src_path_bits;
+ attr->alt_ah_attr.static_rate = cmd->alt_dest.static_rate;
+ attr->alt_ah_attr.ah_flags = cmd->alt_dest.is_global ? IB_AH_GRH : 0;
+ attr->alt_ah_attr.port_num = cmd->alt_dest.port_num;
if (qp->real_qp == qp) {
- ret = ib_resolve_eth_l2_attrs(qp, attr, &cmd.attr_mask);
+ ret = ib_resolve_eth_l2_attrs(qp, attr, &cmd->attr_mask);
if (ret)
goto out;
ret = qp->device->modify_qp(qp, attr,
- modify_qp_mask(qp->qp_type, cmd.attr_mask), &udata);
+ modify_qp_mask(qp->qp_type, cmd->attr_mask), udata);
} else {
- ret = ib_modify_qp(qp, attr, modify_qp_mask(qp->qp_type, cmd.attr_mask));
+ ret = ib_modify_qp(qp, attr, modify_qp_mask(qp->qp_type, cmd->attr_mask));
}
put_qp_read(qp);
@@ -2077,7 +2082,7 @@ ssize_t ib_uverbs_modify_qp(struct ib_uverbs_file *file,
if (ret)
goto out;
- ret = in_len;
+ return 0;
out:
kfree(attr);
@@ -2085,6 +2090,30 @@ out:
return ret;
}
+ssize_t ib_uverbs_modify_qp(struct ib_uverbs_file *file,
+ const char __user *buf, int in_len,
+ int out_len)
+{
+ struct ib_uverbs_modify_qp_ex xcmd;
+ struct ib_uverbs_modify_qp cmd;
+ struct ib_udata udata;
+ int ret;
+
+ if (copy_from_user(&cmd, buf, sizeof(cmd)))
+ return -EFAULT;
+
+ INIT_UDATA(&udata, buf + sizeof(cmd), NULL, in_len - sizeof(cmd),
+ out_len);
+
+ memset(&xcmd, 0, sizeof(xcmd));
+ memcpy(&xcmd.dest, &cmd, sizeof(cmd));
+ ret = modify_qp(file, &xcmd, &udata);
+ if (ret)
+ return ret;
+
+ return in_len;
+}
+
ssize_t ib_uverbs_destroy_qp(struct ib_uverbs_file *file,
const char __user *buf, int in_len,
int out_len)
@@ -3300,9 +3329,332 @@ int ib_uverbs_ex_query_device(struct ib_uverbs_file *file,
resp.atomics.max_fa_bit_boundary = 0;
resp.atomics.log_max_atomic_inline = 0;
}
+ if (cmd.comp_mask & IB_UVERBS_EX_QUERY_DEV_CAP_FLAGS2) {
+ resp.device_cap_flags2 = (__u32)(attr.device_cap_flags >> 32);
+ resp.comp_mask |= IB_UVERBS_EX_QUERY_DEV_CAP_FLAGS2;
+ }
+
+ if (cmd.comp_mask & IB_UVERBS_EX_QUERY_DEV_DC_PARAMS) {
+ resp.dc_rd_req = attr.dc_rd_req;
+ resp.dc_rd_res = attr.dc_rd_res;
+ resp.comp_mask |= IB_UVERBS_EX_QUERY_DEV_DC_PARAMS;
+ }
+
+ err = ib_copy_to_udata(ucore, &resp, sizeof(resp));
+ if (err)
+ return err;
+
+ return 0;
+}
+
+int ib_uverbs_ex_create_dct(struct ib_uverbs_file *file,
+ struct ib_udata *ucore,
+ struct ib_udata *uhw)
+{
+ int out_len = ucore->outlen + uhw->outlen;
+ struct ib_uverbs_create_dct *cmd;
+ struct ib_uverbs_create_dct_resp resp;
+ struct ib_udct_object *obj;
+ struct ib_dct *dct;
+ int err;
+ struct ib_dct_init_attr *attr;
+ struct ib_pd *pd = NULL;
+ struct ib_cq *cq = NULL;
+ struct ib_srq *srq = NULL;
+
+ if (out_len < sizeof(resp))
+ return -ENOSPC;
+
+ cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
+ attr = kzalloc(sizeof(*attr), GFP_KERNEL);
+ if (!attr || !cmd) {
+ err = -ENOMEM;
+ goto err_cmd_attr;
+ }
+
+ err = ib_copy_from_udata(cmd, ucore, sizeof(*cmd));
+ if (err)
+ goto err_cmd_attr;
+
+ if (cmd->comp_mask) {
+ err = -EINVAL;
+ goto err_cmd_attr;
+ }
+
+ obj = kmalloc(sizeof(*obj), GFP_KERNEL);
+ if (!obj) {
+ err = -ENOMEM;
+ goto err_cmd_attr;
+ }
+
+ init_uobj(&obj->uevent.uobject, cmd->user_handle, file->ucontext,
+ &dct_lock_class);
+ down_write(&obj->uevent.uobject.mutex);
+
+ srq = idr_read_srq(cmd->srq_handle, file->ucontext);
+ if (!srq) {
+ err = -EINVAL;
+ goto err_put;
+ }
+
+ cq = idr_read_cq(cmd->cq_handle, file->ucontext, 0);
+ if (!cq) {
+ err = -EINVAL;
+ goto err_put;
+ }
+
+ pd = idr_read_pd(cmd->pd_handle, file->ucontext);
+ if (!pd) {
+ err = -EINVAL;
+ goto err_put;
+ }
+
+ if (cmd->create_flags & ~IB_DCT_CREATE_FLAGS_MASK) {
+ err = -EINVAL;
+ goto err_put;
+ }
+
+ attr->cq = cq;
+ attr->access_flags = cmd->access_flags;
+ attr->min_rnr_timer = cmd->min_rnr_timer;
+ attr->srq = srq;
+ attr->tclass = cmd->tclass;
+ attr->flow_label = cmd->flow_label;
+ attr->dc_key = cmd->dc_key;
+ attr->mtu = cmd->mtu;
+ attr->port = cmd->port;
+ attr->pkey_index = cmd->pkey_index;
+ attr->gid_index = cmd->gid_index;
+ attr->hop_limit = cmd->hop_limit;
+ attr->create_flags = cmd->create_flags;
+ attr->inline_size = cmd->inline_size;
+ attr->event_handler = ib_uverbs_dct_event_handler;
+ attr->dct_context = file;
+
+ obj->uevent.events_reported = 0;
+ INIT_LIST_HEAD(&obj->uevent.event_list);
+ dct = ib_create_dct(pd, attr, uhw);
+ if (IS_ERR(dct)) {
+ err = PTR_ERR(dct);
+ goto err_put;
+ }
+
+ dct->device = file->device->ib_dev;
+ dct->uobject = &obj->uevent.uobject;
+ dct->event_handler = attr->event_handler;
+ dct->dct_context = attr->dct_context;
+
+ obj->uevent.uobject.object = dct;
+ err = idr_add_uobj(&ib_uverbs_dct_idr, &obj->uevent.uobject);
+ if (err)
+ goto err_dct;
+
+ memset(&resp, 0, sizeof(resp));
+ resp.dct_handle = obj->uevent.uobject.id;
+ resp.dctn = dct->dct_num;
+ resp.inline_size = attr->inline_size;
+
+ err = ib_copy_to_udata(ucore, &resp, sizeof(resp));
+ if (err)
+ goto err_copy;
+
+ mutex_lock(&file->mutex);
+ list_add_tail(&obj->uevent.uobject.list, &file->ucontext->dct_list);
+ mutex_unlock(&file->mutex);
+
+ obj->uevent.uobject.live = 1;
+
+ put_pd_read(pd);
+ put_cq_read(cq);
+ put_srq_read(srq);
+
+ up_write(&obj->uevent.uobject.mutex);
+ kfree(attr);
+ kfree(cmd);
+
+ return 0;
+
+err_copy:
+ idr_remove_uobj(&ib_uverbs_dct_idr, &obj->uevent.uobject);
+
+err_dct:
+ ib_destroy_dct(dct, uhw);
+
+err_put:
+ if (pd)
+ put_pd_read(pd);
+ if (cq)
+ put_cq_read(cq);
+ if (srq)
+ put_srq_read(srq);
+
+ put_uobj_write(&obj->uevent.uobject);
+
+err_cmd_attr:
+ kfree(attr);
+ kfree(cmd);
+ return err;
+}
+
+int ib_uverbs_ex_destroy_dct(struct ib_uverbs_file *file,
+ struct ib_udata *ucore,
+ struct ib_udata *uhw)
+{
+ int out_len = ucore->outlen + uhw->outlen;
+ struct ib_uverbs_destroy_dct cmd;
+ struct ib_uverbs_destroy_dct_resp resp;
+ struct ib_uobject *uobj;
+ struct ib_udct_object *obj;
+ struct ib_dct *dct;
+ int err;
+
+ if (out_len < sizeof(resp))
+ return -ENOSPC;
+
+ err = ib_copy_from_udata(&cmd, ucore, sizeof(cmd));
+ if (err)
+ return err;
+
+ if (cmd.comp_mask)
+ return -EINVAL;
+
+ uobj = idr_write_uobj(&ib_uverbs_dct_idr, cmd.dct_handle, file->ucontext);
+ if (!uobj)
+ return -EINVAL;
+
+ dct = uobj->object;
+ obj = container_of(uobj, struct ib_udct_object, uevent.uobject);
+
+ err = ib_destroy_dct(dct, uhw);
+ if (!err)
+ uobj->live = 0;
+
+ put_uobj_write(uobj);
+
+ if (err)
+ return err;
+
+ idr_remove_uobj(&ib_uverbs_dct_idr, uobj);
+
+ mutex_lock(&file->mutex);
+ list_del(&uobj->list);
+ mutex_unlock(&file->mutex);
+
+ memset(&resp, 0, sizeof(resp));
+ resp.events_reported = obj->uevent.events_reported;
+
+ put_uobj(uobj);
+
err = ib_copy_to_udata(ucore, &resp, sizeof(resp));
if (err)
return err;
return 0;
}
+
+int ib_uverbs_ex_arm_dct(struct ib_uverbs_file *file,
+ struct ib_udata *ucore,
+ struct ib_udata *uhw)
+{
+ struct ib_uverbs_arm_dct cmd;
+ struct ib_dct *dct;
+ int err;
+
+ err = ib_copy_from_udata(&cmd, ucore, sizeof(cmd));
+ if (err)
+ return err;
+
+ if (cmd.comp_mask)
+ return -EINVAL;
+
+ dct = idr_read_dct(cmd.dct_handle, file->ucontext);
+ if (!dct)
+ return -EINVAL;
+
+ err = ib_arm_dct(dct, uhw);
+ put_dct_read(dct);
+ if (err)
+ return err;
+
+ return err;
+}
+
+int ib_uverbs_ex_query_dct(struct ib_uverbs_file *file,
+ struct ib_udata *ucore,
+ struct ib_udata *uhw)
+{
+ int out_len = ucore->outlen + uhw->outlen;
+ struct ib_uverbs_query_dct cmd;
+ struct ib_uverbs_query_dct_resp resp;
+ struct ib_dct *dct;
+ struct ib_dct_attr *attr;
+ int err;
+
+ if (out_len < sizeof(resp))
+ return -ENOSPC;
+
+ err = ib_copy_from_udata(&cmd, ucore, sizeof(cmd));
+ if (err)
+ return err;
+
+ if (cmd.comp_mask)
+ return -EINVAL;
+
+ attr = kmalloc(sizeof(*attr), GFP_KERNEL);
+ if (!attr) {
+ err = -ENOMEM;
+ goto out;
+ }
+
+ dct = idr_read_dct(cmd.dct_handle, file->ucontext);
+ if (!dct) {
+ err = -EINVAL;
+ goto out;
+ }
+
+ err = ib_query_dct(dct, attr, uhw);
+
+ put_dct_read(dct);
+
+ if (err)
+ goto out;
+
+ memset(&resp, 0, sizeof(resp));
+
+ resp.dc_key = attr->dc_key;
+ resp.access_flags = attr->access_flags;
+ resp.flow_label = attr->flow_label;
+ resp.key_violations = attr->key_violations;
+ resp.port = attr->port;
+ resp.min_rnr_timer = attr->min_rnr_timer;
+ resp.tclass = attr->tclass;
+ resp.mtu = attr->mtu;
+ resp.pkey_index = attr->pkey_index;
+ resp.gid_index = attr->gid_index;
+ resp.hop_limit = attr->hop_limit;
+ resp.state = attr->state;
+
+ err = ib_copy_to_udata(ucore, &resp, sizeof(resp));
+
+out:
+ kfree(attr);
+
+ return err;
+}
+
+int ib_uverbs_ex_modify_qp(struct ib_uverbs_file *file,
+ struct ib_udata *ucore,
+ struct ib_udata *uhw)
+{
+ struct ib_uverbs_modify_qp_ex cmd;
+ int err;
+
+ err = ib_copy_from_udata(&cmd, ucore, sizeof(cmd));
+ if (err)
+ return err;
+
+ if (cmd.comp_mask > IB_UVERBS_EX_MODIFY_QP_MAX_MASK)
+ return -EINVAL;
+
+ return modify_qp(file, &cmd, ucore);
+}
diff --git a/drivers/infiniband/core/uverbs_main.c b/drivers/infiniband/core/uverbs_main.c
index 974025028790..64ba9afd97f4 100644
--- a/drivers/infiniband/core/uverbs_main.c
+++ b/drivers/infiniband/core/uverbs_main.c
@@ -74,6 +74,7 @@ DEFINE_IDR(ib_uverbs_qp_idr);
DEFINE_IDR(ib_uverbs_srq_idr);
DEFINE_IDR(ib_uverbs_xrcd_idr);
DEFINE_IDR(ib_uverbs_rule_idr);
+DEFINE_IDR(ib_uverbs_dct_idr);
static DEFINE_SPINLOCK(map_lock);
static DECLARE_BITMAP(dev_map, IB_UVERBS_MAX_DEVICES);
@@ -123,7 +124,12 @@ static int (*uverbs_ex_cmd_table[])(struct ib_uverbs_file *file,
struct ib_udata *uhw) = {
[IB_USER_VERBS_EX_CMD_CREATE_FLOW] = ib_uverbs_ex_create_flow,
[IB_USER_VERBS_EX_CMD_DESTROY_FLOW] = ib_uverbs_ex_destroy_flow,
- [IB_USER_VERBS_EX_CMD_QUERY_DEVICE] = ib_uverbs_ex_query_device
+ [IB_USER_VERBS_EX_CMD_QUERY_DEVICE] = ib_uverbs_ex_query_device,
+ [IB_USER_VERBS_EX_CMD_CREATE_DCT] = ib_uverbs_ex_create_dct,
+ [IB_USER_VERBS_EX_CMD_DESTROY_DCT] = ib_uverbs_ex_destroy_dct,
+ [IB_USER_VERBS_EX_CMD_QUERY_DCT] = ib_uverbs_ex_query_dct,
+ [IB_USER_VERBS_EX_CMD_ARM_DCT] = ib_uverbs_ex_arm_dct,
+ [IB_USER_VERBS_EX_CMD_MODIFY_QP] = ib_uverbs_ex_modify_qp,
};
static void ib_uverbs_add_one(struct ib_device *device);
@@ -199,6 +205,7 @@ static int ib_uverbs_cleanup_ucontext(struct ib_uverbs_file *file,
struct ib_ucontext *context)
{
struct ib_uobject *uobj, *tmp;
+ int err;
if (!context)
return 0;
@@ -246,6 +253,20 @@ static int ib_uverbs_cleanup_ucontext(struct ib_uverbs_file *file,
kfree(uqp);
}
+ list_for_each_entry_safe(uobj, tmp, &context->dct_list, list) {
+ struct ib_dct *dct = uobj->object;
+ struct ib_udct_object *udct =
+ container_of(uobj, struct ib_udct_object, uevent.uobject);
+
+ idr_remove_uobj(&ib_uverbs_dct_idr, uobj);
+
+ err = ib_destroy_dct(dct, NULL);
+ if (err)
+ pr_warn("destroying uverbs dct failed: err %d\n", err);
+
+ kfree(udct);
+ }
+
list_for_each_entry_safe(uobj, tmp, &context->cq_list, list) {
struct ib_cq *cq = uobj->object;
struct ib_uverbs_event_file *ev_file = cq->cq_context;
@@ -516,6 +537,18 @@ void ib_uverbs_qp_event_handler(struct ib_event *event, void *context_ptr)
&uobj->events_reported);
}
+void ib_uverbs_dct_event_handler(struct ib_event *event, void *context_ptr)
+{
+ struct ib_uevent_object *uobj;
+
+ uobj = container_of(event->element.dct->uobject,
+ struct ib_uevent_object, uobject);
+
+ ib_uverbs_async_handler(context_ptr, uobj->uobject.user_handle,
+ event->event, &uobj->event_list,
+ &uobj->events_reported);
+}
+
void ib_uverbs_srq_event_handler(struct ib_event *event, void *context_ptr)
{
struct ib_uevent_object *uobj;
diff --git a/include/rdma/ib_verbs.h b/include/rdma/ib_verbs.h
index 9c67cffe1ecc..97eb232ce05b 100644
--- a/include/rdma/ib_verbs.h
+++ b/include/rdma/ib_verbs.h
@@ -1147,6 +1147,7 @@ struct ib_ucontext {
struct list_head ah_list;
struct list_head xrcd_list;
struct list_head rule_list;
+ struct list_head dct_list;
int closing;
};
diff --git a/include/uapi/rdma/ib_user_verbs.h b/include/uapi/rdma/ib_user_verbs.h
index ec98fe636f2b..4db0607b0654 100644
--- a/include/uapi/rdma/ib_user_verbs.h
+++ b/include/uapi/rdma/ib_user_verbs.h
@@ -91,8 +91,13 @@ enum {
enum {
IB_USER_VERBS_EX_CMD_QUERY_DEVICE = IB_USER_VERBS_CMD_QUERY_DEVICE,
+ IB_USER_VERBS_EX_CMD_MODIFY_QP = IB_USER_VERBS_CMD_MODIFY_QP,
IB_USER_VERBS_EX_CMD_CREATE_FLOW = IB_USER_VERBS_CMD_THRESHOLD,
IB_USER_VERBS_EX_CMD_DESTROY_FLOW,
+ IB_USER_VERBS_EX_CMD_CREATE_DCT,
+ IB_USER_VERBS_EX_CMD_DESTROY_DCT,
+ IB_USER_VERBS_EX_CMD_QUERY_DCT,
+ IB_USER_VERBS_EX_CMD_ARM_DCT,
};
/*
@@ -204,7 +209,9 @@ struct ib_uverbs_query_device_resp {
enum {
IB_UVERBS_EX_QUERY_DEV_MASKED_ATOMIC = 1 << 0,
- IB_UVERBS_EX_QUERY_DEV_LAST = 1 << 1,
+ IB_UVERBS_EX_QUERY_DEV_CAP_FLAGS2 = 1 << 1,
+ IB_UVERBS_EX_QUERY_DEV_DC_PARAMS = 1 << 2,
+ IB_UVERBS_EX_QUERY_DEV_LAST = 1 << 3,
IB_UVERBS_EX_QUERY_DEV_MAX_MASK = IB_UVERBS_EX_QUERY_DEV_LAST - 1,
};
@@ -223,6 +230,9 @@ struct ib_uverbs_ex_query_device_resp {
struct ib_uverbs_query_device_resp base;
__u32 comp_mask;
struct ib_uverbs_ex_atomic_caps atomics;
+ __u32 device_cap_flags2;
+ __u32 dc_rd_req;
+ __u32 dc_rd_res;
};
struct ib_uverbs_query_port {
@@ -613,6 +623,46 @@ struct ib_uverbs_modify_qp {
struct ib_uverbs_modify_qp_resp {
};
+enum {
+ IB_UVERBS_EX_MODIFY_QP_DCT_KEY = 1 << 0,
+ IB_UVERBS_EX_MODIFY_QP_MAX_MASK = (1 << (0 /*last shift value */ + 1)) - 1,
+};
+
+struct ib_uverbs_modify_qp_ex {
+ __u32 comp_mask;
+ struct ib_uverbs_qp_dest dest;
+ struct ib_uverbs_qp_dest alt_dest;
+ __u32 qp_handle;
+ __u32 attr_mask;
+ __u32 qkey;
+ __u32 rq_psn;
+ __u32 sq_psn;
+ __u32 dest_qp_num;
+ __u32 qp_access_flags;
+ __u16 pkey_index;
+ __u16 alt_pkey_index;
+ __u8 qp_state;
+ __u8 cur_qp_state;
+ __u8 path_mtu;
+ __u8 path_mig_state;
+ __u8 en_sqd_async_notify;
+ __u8 max_rd_atomic;
+ __u8 max_dest_rd_atomic;
+ __u8 min_rnr_timer;
+ __u8 port_num;
+ __u8 timeout;
+ __u8 retry_cnt;
+ __u8 rnr_retry;
+ __u8 alt_port_num;
+ __u8 alt_timeout;
+ __u8 reserved[6];
+ __u64 dct_key;
+ __u64 driver_data[0];
+};
+
+struct ib_uverbs_modify_qp_ex_resp {
+};
+
struct ib_uverbs_destroy_qp {
__u64 response;
__u32 qp_handle;
@@ -901,4 +951,78 @@ struct ib_uverbs_destroy_srq_resp {
__u32 events_reported;
};
+struct ib_uverbs_create_dct {
+ __u32 comp_mask;
+ __u32 reserved;
+ __u64 user_handle;
+ __u32 pd_handle;
+ __u32 cq_handle;
+ __u32 srq_handle;
+ __u32 access_flags;
+ __u64 dc_key;
+ __u32 flow_label;
+ __u8 min_rnr_timer;
+ __u8 tclass;
+ __u8 port;
+ __u8 pkey_index;
+ __u8 gid_index;
+ __u8 hop_limit;
+ __u8 mtu;
+ __u8 reserved0;
+ __u32 create_flags;
+ __u32 inline_size;
+ __u32 reserved1;
+ __u32 driver_data[0];
+};
+
+struct ib_uverbs_create_dct_resp {
+ __u32 comp_mask;
+ __u32 dct_handle;
+ __u32 dctn;
+ __u32 inline_size;
+ __u64 rsvd;
+};
+
+struct ib_uverbs_destroy_dct {
+ __u32 comp_mask;
+ __u32 dct_handle;
+ __u32 reserved;
+};
+
+struct ib_uverbs_destroy_dct_resp {
+ __u32 events_reported;
+ __u32 reserved;
+};
+
+struct ib_uverbs_query_dct {
+ __u32 comp_mask;
+ __u32 dct_handle;
+ __u32 reserved;
+ __u32 driver_data[0];
+};
+
+struct ib_uverbs_query_dct_resp {
+ __u64 dc_key;
+ __u32 access_flags;
+ __u32 flow_label;
+ __u32 key_violations;
+ __u8 port;
+ __u8 min_rnr_timer;
+ __u8 tclass;
+ __u8 mtu;
+ __u8 pkey_index;
+ __u8 gid_index;
+ __u8 hop_limit;
+ __u8 state;
+ __u32 rsvd;
+ __u32 driver_data[0];
+};
+
+struct ib_uverbs_arm_dct {
+ __u32 comp_mask;
+ __u32 dct_handle;
+ __u32 reserved;
+ __u32 driver_data[0];
+};
+
#endif /* IB_USER_VERBS_H */
--
2.1.2
--
To unsubscribe from this list: send the line "unsubscribe linux-rdma" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply related [flat|nested] 8+ messages in thread* [PATCH for-next 3/5] mlx5_core: Add DC support at mlx5 core layer
[not found] ` <1415289159-4376-1-git-send-email-eli-VPRAkNaXOzVWk0Htik3J/w@public.gmane.org>
2014-11-06 15:52 ` [PATCH for-next 1/5] IB/core: Add DC transport support Eli Cohen
2014-11-06 15:52 ` [PATCH for-next 2/5] IB/uverbs: Add userspace interface to DC verbs Eli Cohen
@ 2014-11-06 15:52 ` Eli Cohen
2014-11-06 15:52 ` [PATCH for-next 4/5] mlx5_ib: Add support for DC Eli Cohen
2014-11-06 15:52 ` [PATCH for-next 5/5] mlx5_core: Update mlx5_command_str with DC commands Eli Cohen
4 siblings, 0 replies; 8+ messages in thread
From: Eli Cohen @ 2014-11-06 15:52 UTC (permalink / raw)
To: roland-DgEjT+Ai2ygdnm+yROfE0A
Cc: linux-rdma-u79uwXL29TY76Z2rM5mHXA,
ogerlitz-VPRAkNaXOzVWk0Htik3J/w, richardg-VPRAkNaXOzVWk0Htik3J/w,
yevgenyp-VPRAkNaXOzVWk0Htik3J/w, Eli Cohen
Update debugfs, implement DC commands and handle events.
Signed-off-by: Eli Cohen <eli-VPRAkNaXOzVWk0Htik3J/w@public.gmane.org>
---
drivers/net/ethernet/mellanox/mlx5/core/debugfs.c | 110 +++++++++++++
drivers/net/ethernet/mellanox/mlx5/core/eq.c | 15 +-
drivers/net/ethernet/mellanox/mlx5/core/main.c | 6 +
drivers/net/ethernet/mellanox/mlx5/core/qp.c | 185 ++++++++++++++++++++++
include/linux/mlx5/device.h | 12 ++
include/linux/mlx5/driver.h | 24 ++-
include/linux/mlx5/mlx5_ifc.h | 179 +++++++++++++++++++++
include/linux/mlx5/qp.h | 39 ++++-
8 files changed, 566 insertions(+), 4 deletions(-)
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/debugfs.c b/drivers/net/ethernet/mellanox/mlx5/core/debugfs.c
index 10e1f1a18255..3e115dee235a 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/debugfs.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/debugfs.c
@@ -35,6 +35,7 @@
#include <linux/mlx5/qp.h>
#include <linux/mlx5/cq.h>
#include <linux/mlx5/driver.h>
+#include <linux/mlx5/mlx5_ifc.h>
#include "mlx5_core.h"
enum {
@@ -62,6 +63,22 @@ static char *qp_fields[] = {
};
enum {
+ DCT_PID,
+ DCT_STATE,
+ DCT_MTU,
+ DCT_KEY_VIOL,
+ DCT_CQN,
+};
+
+static char *dct_fields[] = {
+ [DCT_PID] = "pid",
+ [DCT_STATE] = "state",
+ [DCT_MTU] = "mtu",
+ [DCT_KEY_VIOL] = "key_violations",
+ [DCT_CQN] = "cqn",
+};
+
+enum {
EQ_NUM_EQES,
EQ_INTR,
EQ_LOG_PG_SZ,
@@ -122,6 +139,26 @@ void mlx5_qp_debugfs_cleanup(struct mlx5_core_dev *dev)
debugfs_remove_recursive(dev->priv.qp_debugfs);
}
+int mlx5_dct_debugfs_init(struct mlx5_core_dev *dev)
+{
+ if (!mlx5_debugfs_root)
+ return 0;
+
+ dev->priv.dct_debugfs = debugfs_create_dir("DCTs", dev->priv.dbg_root);
+ if (!dev->priv.dct_debugfs)
+ return -ENOMEM;
+
+ return 0;
+}
+
+void mlx5_dct_debugfs_cleanup(struct mlx5_core_dev *dev)
+{
+ if (!mlx5_debugfs_root)
+ return;
+
+ debugfs_remove_recursive(dev->priv.dct_debugfs);
+}
+
int mlx5_eq_debugfs_init(struct mlx5_core_dev *dev)
{
if (!mlx5_debugfs_root)
@@ -355,6 +392,51 @@ out:
return param;
}
+static u64 dct_read_field(struct mlx5_core_dev *dev, struct mlx5_core_dct *dct,
+ int index, int *is_str)
+{
+ void *out;
+ void *dctc;
+ int out_sz = MLX5_ST_SZ_BYTES(query_dct_out);
+ u64 param = 0;
+ int err;
+
+ out = kzalloc(out_sz, GFP_KERNEL);
+ if (!out)
+ return param;
+
+ err = mlx5_core_dct_query(dev, dct, out);
+ if (err) {
+ mlx5_core_warn(dev, "failed to query dct\n");
+ goto out;
+ }
+
+ dctc = MLX5_ADDR_OF(query_dct_out, out, dct_context_entry);
+ *is_str = 0;
+ switch (index) {
+ case DCT_PID:
+ param = dct->pid;
+ break;
+ case DCT_STATE:
+ param = (u64)mlx5_dct_state_str(MLX5_GET(dctc, dctc, state));
+ *is_str = 1;
+ break;
+ case DCT_MTU:
+ param = ib_mtu_enum_to_int(MLX5_GET(dctc, dctc, mtu));
+ break;
+ case DCT_KEY_VIOL:
+ param = MLX5_GET(dctc, dctc, dc_access_key_violation_count);
+ break;
+ case DCT_CQN:
+ param = MLX5_GET(dctc, dctc, cqn);
+ break;
+ }
+
+out:
+ kfree(out);
+ return param;
+}
+
static u64 eq_read_field(struct mlx5_core_dev *dev, struct mlx5_eq *eq,
int index)
{
@@ -457,6 +539,10 @@ static ssize_t dbg_read(struct file *filp, char __user *buf, size_t count,
field = cq_read_field(d->dev, d->object, desc->i);
break;
+ case MLX5_DBG_RSC_DCT:
+ field = dct_read_field(d->dev, d->object, desc->i, &is_str);
+ break;
+
default:
mlx5_core_warn(d->dev, "invalid resource type %d\n", d->type);
return -EINVAL;
@@ -558,6 +644,30 @@ void mlx5_debug_qp_remove(struct mlx5_core_dev *dev, struct mlx5_core_qp *qp)
rem_res_tree(qp->dbg);
}
+int mlx5_debug_dct_add(struct mlx5_core_dev *dev, struct mlx5_core_dct *dct)
+{
+ int err;
+
+ if (!mlx5_debugfs_root)
+ return 0;
+
+ err = add_res_tree(dev, MLX5_DBG_RSC_DCT, dev->priv.dct_debugfs,
+ &dct->dbg, dct->dctn, dct_fields,
+ ARRAY_SIZE(dct_fields), dct);
+ if (err)
+ dct->dbg = NULL;
+
+ return err;
+}
+
+void mlx5_debug_dct_remove(struct mlx5_core_dev *dev, struct mlx5_core_dct *dct)
+{
+ if (!mlx5_debugfs_root)
+ return;
+
+ if (dct->dbg)
+ rem_res_tree(dct->dbg);
+}
int mlx5_debug_eq_add(struct mlx5_core_dev *dev, struct mlx5_eq *eq)
{
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/eq.c b/drivers/net/ethernet/mellanox/mlx5/core/eq.c
index ad2c96a02a53..941077ea7a7a 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/eq.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/eq.c
@@ -68,7 +68,9 @@ enum {
(1ull << MLX5_EVENT_TYPE_PORT_CHANGE) | \
(1ull << MLX5_EVENT_TYPE_SRQ_CATAS_ERROR) | \
(1ull << MLX5_EVENT_TYPE_SRQ_LAST_WQE) | \
- (1ull << MLX5_EVENT_TYPE_SRQ_RQ_LIMIT))
+ (1ull << MLX5_EVENT_TYPE_SRQ_RQ_LIMIT) | \
+ (1ull << MLX5_EVENT_TYPE_DCT_DRAINED) | \
+ (1ull << MLX5_EVENT_TYPE_DCT_KEY_VIOLATION))
struct map_eq_in {
u64 mask;
@@ -157,6 +159,11 @@ static const char *eqe_type_str(u8 type)
return "MLX5_EVENT_TYPE_CMD";
case MLX5_EVENT_TYPE_PAGE_REQUEST:
return "MLX5_EVENT_TYPE_PAGE_REQUEST";
+ case MLX5_EVENT_TYPE_DCT_DRAINED:
+ return "MLX5_EVENT_TYPE_DCT_DRAINED";
+ case MLX5_EVENT_TYPE_DCT_KEY_VIOLATION:
+ return "MLX5_EVENT_TYPE_DCT_KEY_VIOLATION";
+
default:
return "Unrecognized event";
}
@@ -216,6 +223,12 @@ static int mlx5_eq_int(struct mlx5_core_dev *dev, struct mlx5_eq *eq)
mlx5_cq_completion(dev, cqn);
break;
+ case MLX5_EVENT_TYPE_DCT_DRAINED:
+ case MLX5_EVENT_TYPE_DCT_KEY_VIOLATION:
+ rsn = be32_to_cpu(eqe->data.dct.dctn) & 0xffffff;
+ mlx5_rsc_event(dev, rsn, eqe->type);
+ break;
+
case MLX5_EVENT_TYPE_PATH_MIG:
case MLX5_EVENT_TYPE_COMM_EST:
case MLX5_EVENT_TYPE_SQ_DRAINED:
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/main.c b/drivers/net/ethernet/mellanox/mlx5/core/main.c
index ecc6341e728a..44864d584660 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/main.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/main.c
@@ -434,6 +434,9 @@ static int handle_hca_cap(struct mlx5_core_dev *dev)
/* disable checksum */
cur_caps->gen.flags &= ~MLX5_DEV_CAP_FLAG_CMDIF_CSUM;
+ if (max_caps->gen.flags & MLX5_DEV_CAP_FLAG_DCT)
+ cur_caps->gen.flags |= MLX5_DEV_CAP_FLAG_DCT;
+
copy_rw_fields(MLX5_ADDR_OF(set_hca_cap_in, set_ctx, hca_capability_struct),
cur_caps);
err = set_caps(dev, set_ctx, set_sz);
@@ -640,6 +643,7 @@ static int mlx5_dev_init(struct mlx5_core_dev *dev, struct pci_dev *pdev)
mlx5_init_qp_table(dev);
mlx5_init_srq_table(dev);
mlx5_init_mr_table(dev);
+ mlx5_init_dct_table(dev);
return 0;
@@ -692,6 +696,8 @@ static void mlx5_dev_cleanup(struct mlx5_core_dev *dev)
{
struct mlx5_priv *priv = &dev->priv;
+ mlx5_cleanup_dct_table(dev);
+ mlx5_cleanup_mr_table(dev);
mlx5_cleanup_srq_table(dev);
mlx5_cleanup_qp_table(dev);
mlx5_cleanup_cq_table(dev);
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/qp.c b/drivers/net/ethernet/mellanox/mlx5/core/qp.c
index 5261a2b0da43..65e0df5880f8 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/qp.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/qp.c
@@ -36,6 +36,7 @@
#include <linux/mlx5/cmd.h>
#include <linux/mlx5/qp.h>
#include <linux/mlx5/driver.h>
+#include <linux/mlx5/mlx5_ifc.h>
#include "mlx5_core.h"
@@ -70,6 +71,7 @@ void mlx5_core_put_rsc(struct mlx5_core_rsc_common *common)
void mlx5_rsc_event(struct mlx5_core_dev *dev, u32 rsn, int event_type)
{
struct mlx5_core_rsc_common *common = mlx5_get_rsc(dev, rsn);
+ struct mlx5_core_dct *dct;
struct mlx5_core_qp *qp;
if (!common)
@@ -81,6 +83,14 @@ void mlx5_rsc_event(struct mlx5_core_dev *dev, u32 rsn, int event_type)
qp->event(qp, event_type);
break;
+ case MLX5_RES_DCT:
+ dct = (struct mlx5_core_dct *)common;
+ if (event_type == MLX5_EVENT_TYPE_DCT_DRAINED)
+ complete(&dct->drained);
+ else
+ dct->event(dct, event_type);
+ break;
+
default:
mlx5_core_warn(dev, "invalid resource type for 0x%x\n", rsn);
}
@@ -259,6 +269,16 @@ void mlx5_cleanup_qp_table(struct mlx5_core_dev *dev)
mlx5_qp_debugfs_cleanup(dev);
}
+void mlx5_init_dct_table(struct mlx5_core_dev *dev)
+{
+ mlx5_dct_debugfs_init(dev);
+}
+
+void mlx5_cleanup_dct_table(struct mlx5_core_dev *dev)
+{
+ mlx5_dct_debugfs_cleanup(dev);
+}
+
int mlx5_core_qp_query(struct mlx5_core_dev *dev, struct mlx5_core_qp *qp,
struct mlx5_query_qp_mbox_out *out, int outlen)
{
@@ -322,3 +342,168 @@ int mlx5_core_xrcd_dealloc(struct mlx5_core_dev *dev, u32 xrcdn)
return err;
}
EXPORT_SYMBOL_GPL(mlx5_core_xrcd_dealloc);
+
+int mlx5_core_create_dct(struct mlx5_core_dev *dev,
+ struct mlx5_core_dct *dct,
+ void *in)
+{
+ struct mlx5_qp_table *table = &dev->priv.qp_table;
+ const int in_sz = MLX5_ST_SZ_BYTES(create_dct_in);
+ u8 out[MLX5_ST_SZ_BYTES(create_dct_out)];
+ u8 din[MLX5_ST_SZ_BYTES(destroy_dct_in)];
+ u8 dout[MLX5_ST_SZ_BYTES(destroy_dct_out)];
+ int err;
+
+ init_completion(&dct->drained);
+ memset(&out, 0, sizeof(out));
+ MLX5_SET(create_dct_in, in, opcode, MLX5_CMD_OP_CREATE_DCT);
+
+ err = mlx5_cmd_exec(dev, in, in_sz, out, sizeof(out));
+ if (err) {
+ mlx5_core_warn(dev, "create DCT failed, ret %d", err);
+ return err;
+ }
+
+ if (mlx5_get_out_cmd_status(out))
+ return mlx5_cmd_status_to_err_v2(out);
+
+ dct->dctn = MLX5_GET(create_dct_out, out, dct_number);
+
+ dct->common.res = MLX5_RES_DCT;
+ spin_lock_irq(&table->lock);
+ err = radix_tree_insert(&table->tree, dct->dctn, dct);
+ spin_unlock_irq(&table->lock);
+ if (err) {
+ mlx5_core_warn(dev, "err %d", err);
+ goto err_cmd;
+ }
+
+ err = mlx5_debug_dct_add(dev, dct);
+ if (err)
+ mlx5_core_dbg(dev, "failed adding DCT 0x%x to debug file system\n",
+ dct->dctn);
+
+ dct->pid = current->pid;
+ atomic_set(&dct->common.refcount, 1);
+ init_completion(&dct->common.free);
+
+ return 0;
+
+err_cmd:
+ memset(din, 0, sizeof(din));
+ memset(dout, 0, sizeof(dout));
+ MLX5_SET(destroy_dct_in, din, opcode, MLX5_CMD_OP_DESTROY_DCT);
+ MLX5_SET(destroy_dct_in, din, dct_number, dct->dctn);
+ if (mlx5_cmd_exec(dev, din, sizeof(din), out, sizeof(dout)))
+ mlx5_core_warn(dev, "destroy DCT failed\n");
+
+ return err;
+}
+EXPORT_SYMBOL_GPL(mlx5_core_create_dct);
+
+static int mlx5_core_drain_dct(struct mlx5_core_dev *dev,
+ struct mlx5_core_dct *dct)
+{
+ u8 out[MLX5_ST_SZ_BYTES(drain_dct_out)];
+ u8 in[MLX5_ST_SZ_BYTES(drain_dct_in)];
+ int err;
+
+ memset(&in, 0, sizeof(in));
+ memset(&out, 0, sizeof(out));
+ MLX5_SET(drain_dct_in, in, opcode, MLX5_CMD_OP_DRAIN_DCT);
+ MLX5_SET(drain_dct_in, in, dct_number, dct->dctn);
+ err = mlx5_cmd_exec(dev, &in, sizeof(in), &out, sizeof(out));
+ if (err)
+ return err;
+
+ if (mlx5_get_out_cmd_status(out))
+ return mlx5_cmd_status_to_err_v2(out);
+
+ return 0;
+}
+
+int mlx5_core_destroy_dct(struct mlx5_core_dev *dev,
+ struct mlx5_core_dct *dct)
+{
+ struct mlx5_qp_table *table = &dev->priv.qp_table;
+ u8 out[MLX5_ST_SZ_BYTES(destroy_dct_out)];
+ u8 in[MLX5_ST_SZ_BYTES(destroy_dct_in)];
+ unsigned long flags;
+ int err;
+
+ err = mlx5_core_drain_dct(dev, dct);
+ if (err) {
+ mlx5_core_warn(dev, "failed drain DCT 0x%x\n", dct->dctn);
+ return err;
+ }
+
+ wait_for_completion(&dct->drained);
+
+ mlx5_debug_dct_remove(dev, dct);
+
+ spin_lock_irqsave(&table->lock, flags);
+ if (radix_tree_delete(&table->tree, dct->dctn) != dct)
+ mlx5_core_warn(dev, "dct delete differs\n");
+ spin_unlock_irqrestore(&table->lock, flags);
+
+ mlx5_core_put_rsc(&dct->common);
+ wait_for_completion(&dct->common.free);
+
+ memset(in, 0, sizeof(in));
+ memset(out, 0, sizeof(out));
+ MLX5_SET(destroy_dct_in, in, opcode, MLX5_CMD_OP_DESTROY_DCT);
+ MLX5_SET(destroy_dct_in, in, dct_number, dct->dctn);
+ err = mlx5_cmd_exec(dev, &in, sizeof(in), &out, sizeof(out));
+ if (err)
+ return err;
+
+ if (mlx5_get_out_cmd_status(out))
+ return mlx5_cmd_status_to_err_v2(out);
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(mlx5_core_destroy_dct);
+
+int mlx5_core_dct_query(struct mlx5_core_dev *dev, struct mlx5_core_dct *dct,
+ void *out)
+{
+ u8 in[MLX5_ST_SZ_BYTES(query_dct_in)];
+ int out_sz = MLX5_ST_SZ_BYTES(query_dct_out);
+ int err;
+
+ memset(in, 0, sizeof(in));
+ memset(out, 0, out_sz);
+ MLX5_SET(query_dct_in, in, opcode, MLX5_CMD_OP_QUERY_DCT);
+ MLX5_SET(query_dct_in, in, dct_number, dct->dctn);
+ err = mlx5_cmd_exec(dev, &in, sizeof(in), out, out_sz);
+ if (err)
+ return err;
+
+ if (mlx5_get_out_cmd_status(out))
+ return mlx5_cmd_status_to_err_v2(out);
+
+ return err;
+}
+EXPORT_SYMBOL_GPL(mlx5_core_dct_query);
+
+int mlx5_core_arm_dct(struct mlx5_core_dev *dev, struct mlx5_core_dct *dct)
+{
+ u8 out[MLX5_ST_SZ_BYTES(arm_dct_out)];
+ u8 in[MLX5_ST_SZ_BYTES(arm_dct_in)];
+ int err;
+
+ memset(in, 0, sizeof(in));
+ memset(out, 0, sizeof(out));
+
+ MLX5_SET(arm_dct_in, in, opcode, MLX5_CMD_OP_ARM_DCT_FOR_KEY_VIOLATION);
+ MLX5_SET(arm_dct_in, in, dct_number, dct->dctn);
+ err = mlx5_cmd_exec(dev, &in, sizeof(in), &out, sizeof(out));
+ if (err)
+ return err;
+
+ if (mlx5_get_out_cmd_status(out))
+ return mlx5_cmd_status_to_err_v2(out);
+
+ return err;
+}
+EXPORT_SYMBOL_GPL(mlx5_core_arm_dct);
diff --git a/include/linux/mlx5/device.h b/include/linux/mlx5/device.h
index 6e9661105dfa..40db09d6c828 100644
--- a/include/linux/mlx5/device.h
+++ b/include/linux/mlx5/device.h
@@ -206,6 +206,8 @@ enum mlx5_event {
MLX5_EVENT_TYPE_CMD = 0x0a,
MLX5_EVENT_TYPE_PAGE_REQUEST = 0xb,
+ MLX5_EVENT_TYPE_DCT_DRAINED = 0x1c,
+ MLX5_EVENT_TYPE_DCT_KEY_VIOLATION = 0x1d,
};
enum {
@@ -241,6 +243,10 @@ enum {
};
enum {
+ MLX5_DCT_CS_RES_64 = 2,
+};
+
+enum {
MLX5_OPCODE_NOP = 0x00,
MLX5_OPCODE_SEND_INVAL = 0x01,
MLX5_OPCODE_RDMA_WRITE = 0x08,
@@ -449,6 +455,11 @@ struct mlx5_eqe_page_req {
__be32 rsvd1[5];
};
+struct mlx5_eqe_dct {
+ __be32 reserved[6];
+ __be32 dctn;
+};
+
union ev_data {
__be32 raw[7];
struct mlx5_eqe_cmd cmd;
@@ -460,6 +471,7 @@ union ev_data {
struct mlx5_eqe_congestion cong;
struct mlx5_eqe_stall_vl stall_vl;
struct mlx5_eqe_page_req req_pages;
+ struct mlx5_eqe_dct dct;
} __packed;
struct mlx5_eqe {
diff --git a/include/linux/mlx5/driver.h b/include/linux/mlx5/driver.h
index bdca5d94e6fc..47177f6c6f95 100644
--- a/include/linux/mlx5/driver.h
+++ b/include/linux/mlx5/driver.h
@@ -116,7 +116,6 @@ enum {
MLX5_REG_PUDE = 0x5009,
MLX5_REG_PMPE = 0x5010,
MLX5_REG_PELC = 0x500e,
- MLX5_REG_PMLP = 0, /* TBD */
MLX5_REG_NODE_DESC = 0x6001,
MLX5_REG_HOST_ENDIANNESS = 0x7004,
};
@@ -125,6 +124,7 @@ enum dbg_rsc_type {
MLX5_DBG_RSC_QP,
MLX5_DBG_RSC_EQ,
MLX5_DBG_RSC_CQ,
+ MLX5_DBG_RSC_DCT,
};
struct mlx5_field_desc {
@@ -393,6 +393,7 @@ struct mlx5_core_mr {
enum mlx5_res_type {
MLX5_RES_QP,
+ MLX5_RES_DCT,
};
struct mlx5_core_rsc_common {
@@ -401,6 +402,16 @@ struct mlx5_core_rsc_common {
struct completion free;
};
+struct mlx5_core_dct {
+ struct mlx5_core_rsc_common common; /* must be first */
+ int dctn;
+ struct completion drained;
+ struct mlx5_rsc_debug *dbg;
+ int pid;
+
+ void (*event)(struct mlx5_core_dct *, enum mlx5_event);
+};
+
struct mlx5_core_srq {
u32 srqn;
int max;
@@ -498,6 +509,10 @@ struct mlx5_priv {
struct dentry *cmdif_debugfs;
/* end: qp staff */
+ /* start: dct stuff */
+ struct dentry *dct_debugfs;
+ /* end: dct stuff */
+
/* start: cq staff */
struct mlx5_cq_table cq_table;
/* end: cq staff */
@@ -764,6 +779,8 @@ int mlx5_core_create_psv(struct mlx5_core_dev *dev, u32 pdn,
int npsvs, u32 *sig_index);
int mlx5_core_destroy_psv(struct mlx5_core_dev *dev, int psv_num);
void mlx5_core_put_rsc(struct mlx5_core_rsc_common *common);
+int mlx5_dct_debugfs_init(struct mlx5_core_dev *dev);
+void mlx5_dct_debugfs_cleanup(struct mlx5_core_dev *dev);
static inline u32 mlx5_mkey_to_idx(u32 mkey)
{
@@ -832,4 +849,9 @@ static inline const char *caps_opmod_str(u16 opmod)
}
}
+static inline int mlx5_get_out_cmd_status(void *ptr)
+{
+ return *(u8 *)ptr;
+}
+
#endif /* MLX5_DRIVER_H */
diff --git a/include/linux/mlx5/mlx5_ifc.h b/include/linux/mlx5/mlx5_ifc.h
index a3e6148066ce..5b0feb248220 100644
--- a/include/linux/mlx5/mlx5_ifc.h
+++ b/include/linux/mlx5/mlx5_ifc.h
@@ -366,4 +366,183 @@ struct mlx5_ifc_atomic_cap_bits {
u8 reserved_6[0x720];
};
+struct mlx5_ifc_create_dct_out_bits {
+ u8 status[0x8];
+ u8 reserved_0[0x18];
+
+ u8 syndrome[0x20];
+
+ u8 reserved_1[0x8];
+ u8 dct_number[0x18];
+
+ u8 reserved_2[0x20];
+};
+
+struct mlx5_ifc_dctc_bits {
+ u8 reserved_0[0x4];
+ u8 state[0x4];
+ u8 reserved_1[0x18];
+
+ u8 reserved_2[0x8];
+ u8 sw_context[0x18];
+
+ u8 reserved_3[0x8];
+ u8 cqn[0x18];
+
+ u8 counter_set_id[0x8];
+ u8 atomic_mode[0x4];
+ u8 rre[0x1];
+ u8 rwe[0x1];
+ u8 rae[0x1];
+ u8 atomic_like_write_en[0x1];
+ u8 latency_sensitive[0x1];
+ u8 rlky[0x1];
+ u8 free_ar[0x1];
+ u8 reserved_4[0xd];
+
+ u8 reserved_5[0x8];
+ u8 cs_res[0x8];
+ u8 reserved_6[0x3];
+ u8 min_rnr_nak[0x5];
+ u8 reserved_7[0x8];
+
+ u8 reserved_8[0x8];
+ u8 srqn[0x18];
+
+ u8 reserved_9[0x8];
+ u8 pd[0x18];
+
+ u8 tclass[0x8];
+ u8 reserved_10[0x4];
+ u8 flow_label[0x14];
+
+ u8 dc_access_key[0x40];
+
+ u8 reserved_11[0x5];
+ u8 mtu[0x3];
+ u8 port[0x8];
+ u8 pkey_index[0x10];
+
+ u8 reserved_12[0x8];
+ u8 my_addr_index[0x8];
+ u8 reserved_13[0x8];
+ u8 hop_limit[0x8];
+
+ u8 dc_access_key_violation_count[0x20];
+
+ u8 reserved_14[0x14];
+ u8 dei_cfi[0x1];
+ u8 eth_prio[0x3];
+ u8 ecn[0x2];
+ u8 dscp[0x6];
+
+ u8 reserved_15[0x40];
+};
+
+struct mlx5_ifc_create_dct_in_bits {
+ u8 opcode[0x10];
+ u8 reserved_0[0x10];
+
+ u8 reserved_1[0x10];
+ u8 op_mod[0x10];
+
+ u8 reserved_2[0x40];
+
+ struct mlx5_ifc_dctc_bits dct_context_entry;
+
+ u8 reserved_3[0x180];
+};
+
+struct mlx5_ifc_drain_dct_out_bits {
+ u8 status[0x8];
+ u8 reserved_0[0x18];
+
+ u8 syndrome[0x20];
+
+ u8 reserved_1[0x40];
+};
+
+struct mlx5_ifc_drain_dct_in_bits {
+ u8 opcode[0x10];
+ u8 reserved_0[0x10];
+
+ u8 reserved_1[0x10];
+ u8 op_mod[0x10];
+
+ u8 reserved_2[0x8];
+ u8 dct_number[0x18];
+
+ u8 reserved_3[0x20];
+};
+
+struct mlx5_ifc_destroy_dct_out_bits {
+ u8 status[0x8];
+ u8 reserved_0[0x18];
+
+ u8 syndrome[0x20];
+
+ u8 reserved_1[0x40];
+};
+
+struct mlx5_ifc_destroy_dct_in_bits {
+ u8 opcode[0x10];
+ u8 reserved_0[0x10];
+
+ u8 reserved_1[0x10];
+ u8 op_mod[0x10];
+
+ u8 reserved_2[0x8];
+ u8 dct_number[0x18];
+
+ u8 reserved_3[0x20];
+};
+
+struct mlx5_ifc_query_dct_out_bits {
+ u8 status[0x8];
+ u8 reserved_0[0x18];
+
+ u8 syndrome[0x20];
+
+ u8 reserved_1[0x40];
+
+ struct mlx5_ifc_dctc_bits dct_context_entry;
+
+ u8 reserved_2[0x180];
+};
+
+struct mlx5_ifc_query_dct_in_bits {
+ u8 opcode[0x10];
+ u8 reserved_0[0x10];
+
+ u8 reserved_1[0x10];
+ u8 op_mod[0x10];
+
+ u8 reserved_2[0x8];
+ u8 dct_number[0x18];
+
+ u8 reserved_3[0x20];
+};
+
+struct mlx5_ifc_arm_dct_out_bits {
+ u8 status[0x8];
+ u8 reserved_0[0x18];
+
+ u8 syndrome[0x20];
+
+ u8 reserved_1[0x40];
+};
+
+struct mlx5_ifc_arm_dct_in_bits {
+ u8 opcode[0x10];
+ u8 reserved_0[0x10];
+
+ u8 reserved_1[0x10];
+ u8 op_mod[0x10];
+
+ u8 reserved_2[0x8];
+ u8 dct_number[0x18];
+
+ u8 reserved_3[0x20];
+};
+
#endif /* MLX5_IFC_H */
diff --git a/include/linux/mlx5/qp.h b/include/linux/mlx5/qp.h
index 3fa075daeb1d..094160d59d99 100644
--- a/include/linux/mlx5/qp.h
+++ b/include/linux/mlx5/qp.h
@@ -91,8 +91,7 @@ enum {
MLX5_QP_ST_UD = 0x2,
MLX5_QP_ST_XRC = 0x3,
MLX5_QP_ST_MLX = 0x4,
- MLX5_QP_ST_DCI = 0x5,
- MLX5_QP_ST_DCT = 0x6,
+ MLX5_QP_ST_DC = 0x5,
MLX5_QP_ST_QP0 = 0x7,
MLX5_QP_ST_QP1 = 0x8,
MLX5_QP_ST_RAW_ETHERTYPE = 0x9,
@@ -130,6 +129,12 @@ enum {
};
enum {
+ MLX5_DCT_BIT_RRE = 1 << 19,
+ MLX5_DCT_BIT_RWE = 1 << 18,
+ MLX5_DCT_BIT_RAE = 1 << 17,
+};
+
+enum {
MLX5_WQE_CTRL_CQ_UPDATE = 2 << 2,
MLX5_WQE_CTRL_SOLICITED = 1 << 1,
};
@@ -160,6 +165,12 @@ enum {
};
enum {
+ MLX5_DCT_STATE_ACTIVE = 0,
+ MLX5_DCT_STATE_DRAINING = 1,
+ MLX5_DCT_STATE_DRAINED = 2
+};
+
+enum {
MLX5_RCV_DBR = 0,
MLX5_SND_DBR = 1,
};
@@ -547,8 +558,20 @@ int mlx5_core_xrcd_alloc(struct mlx5_core_dev *dev, u32 *xrcdn);
int mlx5_core_xrcd_dealloc(struct mlx5_core_dev *dev, u32 xrcdn);
void mlx5_init_qp_table(struct mlx5_core_dev *dev);
void mlx5_cleanup_qp_table(struct mlx5_core_dev *dev);
+void mlx5_init_dct_table(struct mlx5_core_dev *dev);
+void mlx5_cleanup_dct_table(struct mlx5_core_dev *dev);
int mlx5_debug_qp_add(struct mlx5_core_dev *dev, struct mlx5_core_qp *qp);
void mlx5_debug_qp_remove(struct mlx5_core_dev *dev, struct mlx5_core_qp *qp);
+int mlx5_core_create_dct(struct mlx5_core_dev *dev,
+ struct mlx5_core_dct *dct,
+ void *in);
+int mlx5_core_destroy_dct(struct mlx5_core_dev *dev,
+ struct mlx5_core_dct *dct);
+int mlx5_core_dct_query(struct mlx5_core_dev *dev, struct mlx5_core_dct *dct,
+ void *out);
+int mlx5_core_arm_dct(struct mlx5_core_dev *dev, struct mlx5_core_dct *dct);
+int mlx5_debug_dct_add(struct mlx5_core_dev *dev, struct mlx5_core_dct *dct);
+void mlx5_debug_dct_remove(struct mlx5_core_dev *dev, struct mlx5_core_dct *dct);
static inline const char *mlx5_qp_type_str(int type)
{
@@ -595,4 +618,16 @@ static inline const char *mlx5_qp_state_str(int state)
}
}
+static inline const char *mlx5_dct_state_str(int state)
+{
+ switch (state) {
+ case MLX5_DCT_STATE_ACTIVE:
+ return "ACTIVE";
+ case MLX5_DCT_STATE_DRAINING:
+ return "DRAINING";
+ case MLX5_DCT_STATE_DRAINED:
+ return "DRAINED";
+ default: return "Invalid DCT state";
+ }
+}
#endif /* MLX5_QP_H */
--
2.1.2
--
To unsubscribe from this list: send the line "unsubscribe linux-rdma" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply related [flat|nested] 8+ messages in thread* [PATCH for-next 4/5] mlx5_ib: Add support for DC
[not found] ` <1415289159-4376-1-git-send-email-eli-VPRAkNaXOzVWk0Htik3J/w@public.gmane.org>
` (2 preceding siblings ...)
2014-11-06 15:52 ` [PATCH for-next 3/5] mlx5_core: Add DC support at mlx5 core layer Eli Cohen
@ 2014-11-06 15:52 ` Eli Cohen
2014-11-06 15:52 ` [PATCH for-next 5/5] mlx5_core: Update mlx5_command_str with DC commands Eli Cohen
4 siblings, 0 replies; 8+ messages in thread
From: Eli Cohen @ 2014-11-06 15:52 UTC (permalink / raw)
To: roland-DgEjT+Ai2ygdnm+yROfE0A
Cc: linux-rdma-u79uwXL29TY76Z2rM5mHXA,
ogerlitz-VPRAkNaXOzVWk0Htik3J/w, richardg-VPRAkNaXOzVWk0Htik3J/w,
yevgenyp-VPRAkNaXOzVWk0Htik3J/w, Eli Cohen
Signed-off-by: Eli Cohen <eli-VPRAkNaXOzVWk0Htik3J/w@public.gmane.org>
---
drivers/infiniband/hw/mlx5/main.c | 19 +++
drivers/infiniband/hw/mlx5/mlx5_ib.h | 24 +++
drivers/infiniband/hw/mlx5/qp.c | 289 ++++++++++++++++++++++++++++++++++-
drivers/infiniband/hw/mlx5/user.h | 41 +++++
4 files changed, 370 insertions(+), 3 deletions(-)
diff --git a/drivers/infiniband/hw/mlx5/main.c b/drivers/infiniband/hw/mlx5/main.c
index 3c6fa99c4256..c805385d878d 100644
--- a/drivers/infiniband/hw/mlx5/main.c
+++ b/drivers/infiniband/hw/mlx5/main.c
@@ -283,6 +283,11 @@ static int mlx5_ib_query_device(struct ib_device *ibdev,
props->max_total_mcast_qp_attach = props->max_mcast_qp_attach *
props->max_mcast_grp;
props->max_map_per_fmr = INT_MAX; /* no limit in ConnectIB */
+ if (gen->flags & MLX5_DEV_CAP_FLAG_DCT) {
+ props->device_cap_flags |= IB_DEVICE_DC_TRANSPORT;
+ props->dc_rd_req = 1 << gen->log_max_ra_req_dc;
+ props->dc_rd_res = 1 << gen->log_max_ra_res_dc;
+ }
out:
kfree(in_mad);
@@ -1405,6 +1410,8 @@ static void *mlx5_ib_add(struct mlx5_core_dev *mdev)
dev->ib_dev.alloc_fast_reg_page_list = mlx5_ib_alloc_fast_reg_page_list;
dev->ib_dev.free_fast_reg_page_list = mlx5_ib_free_fast_reg_page_list;
dev->ib_dev.check_mr_status = mlx5_ib_check_mr_status;
+ dev->ib_dev.uverbs_ex_cmd_mask |=
+ (1ull << IB_USER_VERBS_EX_CMD_MODIFY_QP);
if (mdev->caps.gen.flags & MLX5_DEV_CAP_FLAG_XRC) {
dev->ib_dev.alloc_xrcd = mlx5_ib_alloc_xrcd;
@@ -1417,6 +1424,18 @@ static void *mlx5_ib_add(struct mlx5_core_dev *mdev)
dev->ib_dev.uverbs_ex_cmd_mask |=
(1ull << IB_USER_VERBS_EX_CMD_QUERY_DEVICE);
+ if (mdev->caps.gen.flags & MLX5_DEV_CAP_FLAG_DCT) {
+ dev->ib_dev.create_dct = mlx5_ib_create_dct;
+ dev->ib_dev.destroy_dct = mlx5_ib_destroy_dct;
+ dev->ib_dev.query_dct = mlx5_ib_query_dct;
+ dev->ib_dev.arm_dct = mlx5_ib_arm_dct;
+ dev->ib_dev.uverbs_ex_cmd_mask |=
+ (1ull << IB_USER_VERBS_EX_CMD_CREATE_DCT) |
+ (1ull << IB_USER_VERBS_EX_CMD_DESTROY_DCT) |
+ (1ull << IB_USER_VERBS_EX_CMD_QUERY_DCT) |
+ (1ull << IB_USER_VERBS_EX_CMD_ARM_DCT);
+ }
+
err = init_node_data(dev);
if (err)
goto err_eqs;
diff --git a/drivers/infiniband/hw/mlx5/mlx5_ib.h b/drivers/infiniband/hw/mlx5/mlx5_ib.h
index 386780f0d1e1..5a78f2c60867 100644
--- a/drivers/infiniband/hw/mlx5/mlx5_ib.h
+++ b/drivers/infiniband/hw/mlx5/mlx5_ib.h
@@ -194,6 +194,11 @@ struct mlx5_ib_qp {
bool signature_en;
};
+struct mlx5_ib_dct {
+ struct ib_dct ibdct;
+ struct mlx5_core_dct mdct;
+};
+
struct mlx5_ib_cq_buf {
struct mlx5_buf buf;
struct ib_umem *umem;
@@ -444,6 +449,16 @@ static inline struct mlx5_ib_fast_reg_page_list *to_mfrpl(struct ib_fast_reg_pag
return container_of(ibfrpl, struct mlx5_ib_fast_reg_page_list, ibfrpl);
}
+static inline struct mlx5_ib_dct *to_mibdct(struct mlx5_core_dct *mdct)
+{
+ return container_of(mdct, struct mlx5_ib_dct, mdct);
+}
+
+static inline struct mlx5_ib_dct *to_mdct(struct ib_dct *ibdct)
+{
+ return container_of(ibdct, struct mlx5_ib_dct, ibdct);
+}
+
struct mlx5_ib_ah {
struct ib_ah ibah;
struct mlx5_av av;
@@ -482,6 +497,8 @@ struct ib_qp *mlx5_ib_create_qp(struct ib_pd *pd,
struct ib_udata *udata);
int mlx5_ib_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr,
int attr_mask, struct ib_udata *udata);
+int mlx5_ib_modify_qp_ex(struct ib_qp *ibqp, struct ib_qp_attr *attr,
+ int attr_mask, struct ib_udata *udata);
int mlx5_ib_query_qp(struct ib_qp *ibqp, struct ib_qp_attr *qp_attr, int qp_attr_mask,
struct ib_qp_init_attr *qp_init_attr);
int mlx5_ib_destroy_qp(struct ib_qp *qp);
@@ -524,6 +541,13 @@ struct ib_xrcd *mlx5_ib_alloc_xrcd(struct ib_device *ibdev,
struct ib_ucontext *context,
struct ib_udata *udata);
int mlx5_ib_dealloc_xrcd(struct ib_xrcd *xrcd);
+struct ib_dct *mlx5_ib_create_dct(struct ib_pd *pd,
+ struct ib_dct_init_attr *attr,
+ struct ib_udata *uhw);
+int mlx5_ib_destroy_dct(struct ib_dct *dct, struct ib_udata *uhw);
+int mlx5_ib_query_dct(struct ib_dct *dct, struct ib_dct_attr *attr,
+ struct ib_udata *uhw);
+int mlx5_ib_arm_dct(struct ib_dct *dct, struct ib_udata *uhw);
int mlx5_vector2eqn(struct mlx5_ib_dev *dev, int vector, int *eqn, int *irqn);
int mlx5_ib_get_buf_offset(u64 addr, int page_shift, u32 *offset);
int mlx5_query_ext_port_caps(struct mlx5_ib_dev *dev, u8 port);
diff --git a/drivers/infiniband/hw/mlx5/qp.c b/drivers/infiniband/hw/mlx5/qp.c
index 47ca93ce214f..cc514de33444 100644
--- a/drivers/infiniband/hw/mlx5/qp.c
+++ b/drivers/infiniband/hw/mlx5/qp.c
@@ -32,6 +32,7 @@
#include <linux/module.h>
#include <rdma/ib_umem.h>
+#include <linux/mlx5/mlx5_ifc.h>
#include "mlx5_ib.h"
#include "user.h"
@@ -155,6 +156,34 @@ static void mlx5_ib_qp_event(struct mlx5_core_qp *qp, int type)
}
}
+static void mlx5_ib_dct_event(struct mlx5_core_dct *dct, enum mlx5_event type)
+{
+ struct ib_dct *ibdct = &to_mibdct(dct)->ibdct;
+ struct ib_event event;
+
+ if (ibdct->event_handler) {
+ event.device = ibdct->device;
+ event.element.dct = ibdct;
+ switch (type) {
+ case MLX5_EVENT_TYPE_WQ_INVAL_REQ_ERROR:
+ event.event = IB_EVENT_DCT_REQ_ERR;
+ break;
+ case MLX5_EVENT_TYPE_WQ_ACCESS_ERROR:
+ event.event = IB_EVENT_DCT_ACCESS_ERR;
+ break;
+ case MLX5_EVENT_TYPE_DCT_KEY_VIOLATION:
+ event.event = IB_EVENT_DCT_KEY_VIOLATION;
+ break;
+ default:
+ pr_warn("mlx5_ib: Unexpected event type %d on DCT %06x\n",
+ type, dct->dctn);
+ return;
+ }
+
+ ibdct->event_handler(&event, ibdct->dct_context);
+ }
+}
+
static int set_rq_size(struct mlx5_ib_dev *dev, struct ib_qp_cap *cap,
int has_rq, struct mlx5_ib_qp *qp, struct mlx5_ib_create_qp *ucmd)
{
@@ -516,6 +545,7 @@ static int to_mlx5_st(enum ib_qp_type type)
{
switch (type) {
case IB_QPT_RC: return MLX5_QP_ST_RC;
+ case IB_QPT_DC_INI: return MLX5_QP_ST_DC;
case IB_QPT_UC: return MLX5_QP_ST_UC;
case IB_QPT_UD: return MLX5_QP_ST_UD;
case MLX5_IB_QPT_REG_UMR: return MLX5_QP_ST_REG_UMR;
@@ -785,8 +815,10 @@ static void destroy_qp_kernel(struct mlx5_ib_dev *dev, struct mlx5_ib_qp *qp)
static __be32 get_rx_type(struct mlx5_ib_qp *qp, struct ib_qp_init_attr *attr)
{
- if (attr->srq || (attr->qp_type == IB_QPT_XRC_TGT) ||
- (attr->qp_type == IB_QPT_XRC_INI))
+ enum ib_qp_type qt = attr->qp_type;
+
+ if (attr->srq || (qt == IB_QPT_XRC_TGT) || (qt == IB_QPT_XRC_INI) ||
+ (qt == IB_QPT_DC_INI))
return cpu_to_be32(MLX5_SRQ_RQ);
else if (!qp->has_rq)
return cpu_to_be32(MLX5_ZERO_LEN_RQ);
@@ -1065,6 +1097,7 @@ static void get_cqs(struct mlx5_ib_qp *qp,
break;
case MLX5_IB_QPT_REG_UMR:
case IB_QPT_XRC_INI:
+ case IB_QPT_DC_INI:
*send_cq = to_mcq(qp->ibqp.send_cq);
*recv_cq = NULL;
break;
@@ -1150,6 +1183,8 @@ static const char *ib_qp_type_str(enum ib_qp_type type)
return "IB_QPT_XRC_TGT";
case IB_QPT_RAW_PACKET:
return "IB_QPT_RAW_PACKET";
+ case IB_QPT_DC_INI:
+ return "IB_QPT_DC_INI";
case MLX5_IB_QPT_REG_UMR:
return "MLX5_IB_QPT_REG_UMR";
case IB_QPT_MAX:
@@ -1197,6 +1232,7 @@ struct ib_qp *mlx5_ib_create_qp(struct ib_pd *pd,
/* fall through */
case IB_QPT_RC:
+ case IB_QPT_DC_INI:
case IB_QPT_UC:
case IB_QPT_UD:
case IB_QPT_SMI:
@@ -1581,6 +1617,9 @@ static int __mlx5_ib_modify_qp(struct ib_qp *ibqp,
if (attr_mask & IB_QP_DEST_QPN)
context->log_pg_sz_remote_qpn = cpu_to_be32(attr->dest_qp_num);
+ if (attr_mask & IB_QP_DC_KEY)
+ context->dc_access_key = cpu_to_be64(attr->dct_key);
+
if (attr_mask & IB_QP_PKEY_INDEX)
context->pri_path.pkey_index = attr->pkey_index;
@@ -2972,7 +3011,9 @@ int mlx5_ib_query_qp(struct ib_qp *ibqp, struct ib_qp_attr *qp_attr, int qp_attr
qp_attr->qp_access_flags =
to_ib_qp_access_flags(be32_to_cpu(context->params2));
- if (qp->ibqp.qp_type == IB_QPT_RC || qp->ibqp.qp_type == IB_QPT_UC) {
+ if (qp->ibqp.qp_type == IB_QPT_RC ||
+ qp->ibqp.qp_type == IB_QPT_UC ||
+ qp->ibqp.qp_type == IB_QPT_DC_INI) {
to_ib_ah_attr(dev, &qp_attr->ah_attr, &context->pri_path);
to_ib_ah_attr(dev, &qp_attr->alt_ah_attr, &context->alt_path);
qp_attr->alt_pkey_index = context->alt_path.pkey_index & 0x7f;
@@ -3071,3 +3112,245 @@ int mlx5_ib_dealloc_xrcd(struct ib_xrcd *xrcd)
return 0;
}
+
+static void set_dct_access(void *dctx, struct mlx5_ib_dev *dev, u32 ib_flags)
+{
+ if (ib_flags & IB_ACCESS_REMOTE_READ)
+ MLX5_SET(dctc, dctx, rre, 1);
+
+ if (ib_flags & IB_ACCESS_REMOTE_WRITE)
+ MLX5_SET(dctc, dctx, rwe, 1);
+
+ if (ib_flags & IB_ACCESS_REMOTE_ATOMIC) {
+ MLX5_SET(dctc, dctx, rre, 1);
+ MLX5_SET(dctc, dctx, rwe, 1);
+ MLX5_SET(dctc, dctx, rae, 1);
+ }
+}
+
+struct ib_dct *mlx5_ib_create_dct(struct ib_pd *pd,
+ struct ib_dct_init_attr *attr,
+ struct ib_udata *uhw)
+{
+ void *in;
+ int in_sz = MLX5_ST_SZ_BYTES(create_dct_in);
+ void *dctx;
+ struct mlx5_ib_dev *dev;
+ struct mlx5_ib_dct *dct;
+ struct mlx5_ib_create_dct ucmd;
+ struct mlx5_ib_create_dct_resp resp;
+ int cqe_sz;
+ u32 cqn;
+ int err;
+
+ if (uhw) {
+ err = ib_copy_from_udata(&ucmd, uhw, sizeof(ucmd));
+ if (err) {
+ mlx5_ib_dbg(dev, "copy failed\n");
+ return ERR_PTR(err);
+ }
+
+ if (ucmd.reserved0 || ucmd.reserved1)
+ return ERR_PTR(-EINVAL);
+ }
+ dev = to_mdev(pd->device);
+ dct = kzalloc(sizeof(*dct), GFP_KERNEL);
+ if (!dct)
+ return ERR_PTR(-ENOMEM);
+
+ in = kzalloc(in_sz, GFP_KERNEL);
+ if (!in) {
+ err = -ENOMEM;
+ goto err_alloc;
+ }
+
+ dctx = MLX5_ADDR_OF(create_dct_in, in, dct_context_entry);
+
+ cqn = to_mcq(attr->cq)->mcq.cqn;
+ MLX5_SET(dctc, dctx, cqn, cqn);
+ set_dct_access(dctx, dev, attr->access_flags);
+
+ if (attr->inline_size) {
+ cqe_sz = mlx5_ib_get_cqe_size(dev, attr->cq);
+ if (cqe_sz == 128) {
+ MLX5_SET(dctc, dctx, cs_res, MLX5_DCT_CS_RES_64);
+ attr->inline_size = 64;
+ } else {
+ attr->inline_size = 0;
+ }
+ }
+ MLX5_SET(dctc, dctx, min_rnr_nak, attr->min_rnr_timer);
+ MLX5_SET(dctc, dctx, srqn, to_msrq(attr->srq)->msrq.srqn);
+ MLX5_SET(dctc, dctx, pd, to_mpd(pd)->pdn);
+ MLX5_SET(dctc, dctx, tclass, attr->tclass);
+ MLX5_SET(dctc, dctx, flow_label, attr->flow_label);
+ MLX5_SET64(dctc, dctx, dc_access_key, attr->dc_key);
+ MLX5_SET(dctc, dctx, mtu, attr->mtu);
+ MLX5_SET(dctc, dctx, port, attr->port);
+ MLX5_SET(dctc, dctx, pkey_index, attr->pkey_index);
+ MLX5_SET(dctc, dctx, my_addr_index, attr->gid_index);
+ MLX5_SET(dctc, dctx, hop_limit, attr->hop_limit);
+
+ err = mlx5_core_create_dct(dev->mdev, &dct->mdct, in);
+ if (err)
+ goto err_alloc;
+
+ dct->ibdct.dct_num = dct->mdct.dctn;
+ dct->mdct.event = mlx5_ib_dct_event;
+ kfree(in);
+
+ if (uhw) {
+ memset(&resp, 0, sizeof(resp));
+ err = ib_copy_to_udata(uhw, &resp, sizeof(resp));
+ if (err) {
+ mlx5_ib_dbg(dev, "copy failed\n");
+ return ERR_PTR(err);
+ }
+ }
+
+ return &dct->ibdct;
+
+err_alloc:
+ kfree(in);
+ kfree(dct);
+ return ERR_PTR(err);
+}
+
+int mlx5_ib_destroy_dct(struct ib_dct *dct, struct ib_udata *uhw)
+{
+ struct mlx5_ib_dev *dev = to_mdev(dct->device);
+ struct mlx5_ib_dct *mdct = to_mdct(dct);
+ struct mlx5_ib_destroy_dct ucmd;
+ struct mlx5_ib_destroy_dct_resp resp;
+ int err;
+
+ if (uhw) {
+ err = ib_copy_from_udata(&ucmd, uhw, sizeof(ucmd));
+ if (err) {
+ mlx5_ib_dbg(dev, "copy failed\n");
+ return err;
+ }
+
+ if (ucmd.reserved0 || ucmd.reserved1)
+ return -EINVAL;
+ }
+ err = mlx5_core_destroy_dct(dev->mdev, &mdct->mdct);
+ if (!err)
+ kfree(mdct);
+
+ if (uhw) {
+ memset(&resp, 0, sizeof(resp));
+ err = ib_copy_to_udata(uhw, &resp, sizeof(resp));
+ if (err)
+ mlx5_ib_dbg(dev, "copy failed\n");
+ }
+
+ return err;
+}
+
+static void dct_to_ib_access(void *out, u32 *access_flags)
+{
+ u32 flags = 0;
+ void *dctc = MLX5_ADDR_OF(query_dct_out, out, dct_context_entry);
+
+ if (MLX5_GET(dctc, dctc, rre))
+ flags |= IB_ACCESS_REMOTE_READ;
+ if (MLX5_GET(dctc, dctc, rwe))
+ flags |= IB_ACCESS_REMOTE_WRITE;
+ if (MLX5_GET(dctc, dctc, atomic_mode) == MLX5_ATOMIC_MODE_CX)
+ flags |= IB_ACCESS_REMOTE_ATOMIC;
+
+ *access_flags = flags;
+}
+
+int mlx5_ib_query_dct(struct ib_dct *dct, struct ib_dct_attr *attr,
+ struct ib_udata *uhw)
+{
+ struct mlx5_ib_dev *dev = to_mdev(dct->device);
+ struct mlx5_ib_dct *mdct = to_mdct(dct);
+ int out_sz = MLX5_ST_SZ_BYTES(query_dct_out);
+ struct mlx5_ib_query_dct ucmd;
+ struct mlx5_ib_query_dct_resp resp;
+ void *dctc;
+ void *out;
+ int err;
+
+ if (uhw) {
+ err = ib_copy_from_udata(&ucmd, uhw, sizeof(ucmd));
+ if (err) {
+ mlx5_ib_dbg(dev, "copy failed\n");
+ return err;
+ }
+
+ if (ucmd.reserved0 || ucmd.reserved1)
+ return -EINVAL;
+ }
+
+ out = kzalloc(out_sz, GFP_KERNEL);
+ if (!out)
+ return -ENOMEM;
+
+ err = mlx5_core_dct_query(dev->mdev, &mdct->mdct, out);
+ if (err)
+ goto out;
+
+ dctc = MLX5_ADDR_OF(query_dct_out, out, dct_context_entry);
+
+ attr->dc_key = MLX5_GET64(dctc, dctc, dc_access_key);
+ attr->port = MLX5_GET(dctc, dctc, port);
+ dct_to_ib_access(out, &attr->access_flags);
+ attr->min_rnr_timer = MLX5_GET(dctc, dctc, min_rnr_nak);
+ attr->tclass = MLX5_GET(dctc, dctc, tclass);
+ attr->flow_label = MLX5_GET(dctc, dctc, flow_label);
+ attr->mtu = MLX5_GET(dctc, dctc, mtu);
+ attr->pkey_index = MLX5_GET(dctc, dctc, pkey_index);
+ attr->gid_index = MLX5_GET(dctc, dctc, my_addr_index);
+ attr->hop_limit = MLX5_GET(dctc, dctc, hop_limit);
+ attr->key_violations = MLX5_GET(dctc, dctc, dc_access_key_violation_count);
+ attr->state = MLX5_GET(dctc, dctc, state);
+
+ if (uhw) {
+ memset(&resp, 0, sizeof(resp));
+ err = ib_copy_to_udata(uhw, &resp, sizeof(resp));
+ if (err)
+ mlx5_ib_dbg(dev, "copy failed\n");
+ }
+
+out:
+ kfree(out);
+ return err;
+}
+
+int mlx5_ib_arm_dct(struct ib_dct *dct, struct ib_udata *uhw)
+{
+ struct mlx5_ib_dev *dev = to_mdev(dct->device);
+ struct mlx5_ib_dct *mdct = to_mdct(dct);
+ struct mlx5_ib_arm_dct ucmd;
+ struct mlx5_ib_arm_dct_resp resp;
+ int err;
+
+ if (uhw) {
+ err = ib_copy_from_udata(&ucmd, uhw, sizeof(ucmd));
+ if (err) {
+ mlx5_ib_dbg(dev, "copy failed\n");
+ return err;
+ }
+
+ if (ucmd.reserved0 || ucmd.reserved1)
+ return -EINVAL;
+ }
+
+ err = mlx5_core_arm_dct(dev->mdev, &mdct->mdct);
+ if (err)
+ goto out;
+
+ if (uhw) {
+ memset(&resp, 0, sizeof(resp));
+ err = ib_copy_to_udata(uhw, &resp, sizeof(resp));
+ if (err)
+ mlx5_ib_dbg(dev, "copy failed\n");
+ }
+
+out:
+ return err;
+}
diff --git a/drivers/infiniband/hw/mlx5/user.h b/drivers/infiniband/hw/mlx5/user.h
index d0ba264ac1ed..1aecd0ac9844 100644
--- a/drivers/infiniband/hw/mlx5/user.h
+++ b/drivers/infiniband/hw/mlx5/user.h
@@ -130,4 +130,45 @@ struct mlx5_ib_create_qp {
struct mlx5_ib_create_qp_resp {
__u32 uuar_index;
};
+
+struct mlx5_ib_arm_dct {
+ __u64 reserved0;
+ __u64 reserved1;
+};
+
+struct mlx5_ib_arm_dct_resp {
+ __u64 reserved0;
+ __u64 reserved1;
+};
+
+struct mlx5_ib_create_dct {
+ __u64 reserved0;
+ __u64 reserved1;
+};
+
+struct mlx5_ib_create_dct_resp {
+ __u64 reserved0;
+ __u64 reserved1;
+};
+
+struct mlx5_ib_destroy_dct {
+ __u64 reserved0;
+ __u64 reserved1;
+};
+
+struct mlx5_ib_destroy_dct_resp {
+ __u64 reserved0;
+ __u64 reserved1;
+};
+
+struct mlx5_ib_query_dct {
+ __u64 reserved0;
+ __u64 reserved1;
+};
+
+struct mlx5_ib_query_dct_resp {
+ __u64 reserved0;
+ __u64 reserved1;
+};
+
#endif /* MLX5_IB_USER_H */
--
2.1.2
--
To unsubscribe from this list: send the line "unsubscribe linux-rdma" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply related [flat|nested] 8+ messages in thread* [PATCH for-next 5/5] mlx5_core: Update mlx5_command_str with DC commands
[not found] ` <1415289159-4376-1-git-send-email-eli-VPRAkNaXOzVWk0Htik3J/w@public.gmane.org>
` (3 preceding siblings ...)
2014-11-06 15:52 ` [PATCH for-next 4/5] mlx5_ib: Add support for DC Eli Cohen
@ 2014-11-06 15:52 ` Eli Cohen
4 siblings, 0 replies; 8+ messages in thread
From: Eli Cohen @ 2014-11-06 15:52 UTC (permalink / raw)
To: roland-DgEjT+Ai2ygdnm+yROfE0A
Cc: linux-rdma-u79uwXL29TY76Z2rM5mHXA,
ogerlitz-VPRAkNaXOzVWk0Htik3J/w, richardg-VPRAkNaXOzVWk0Htik3J/w,
yevgenyp-VPRAkNaXOzVWk0Htik3J/w, Eli Cohen
Add support for DC commands and make a few other minor fixes.
Signed-off-by: Eli Cohen <eli-VPRAkNaXOzVWk0Htik3J/w@public.gmane.org>
---
drivers/net/ethernet/mellanox/mlx5/core/cmd.c | 21 ++++++++++++++++++---
1 file changed, 18 insertions(+), 3 deletions(-)
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/cmd.c b/drivers/net/ethernet/mellanox/mlx5/core/cmd.c
index 368c6c5ea014..37786ea6ad6c 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/cmd.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/cmd.c
@@ -289,10 +289,10 @@ const char *mlx5_command_str(int command)
return "TEARDOWN_HCA";
case MLX5_CMD_OP_ENABLE_HCA:
- return "MLX5_CMD_OP_ENABLE_HCA";
+ return "ENABLE_HCA";
case MLX5_CMD_OP_DISABLE_HCA:
- return "MLX5_CMD_OP_DISABLE_HCA";
+ return "DISABLE_HCA";
case MLX5_CMD_OP_QUERY_PAGES:
return "QUERY_PAGES";
@@ -390,6 +390,21 @@ const char *mlx5_command_str(int command)
case MLX5_CMD_OP_RESIZE_SRQ:
return "RESIZE_SRQ";
+ case MLX5_CMD_OP_CREATE_DCT:
+ return "CREATE_DCT";
+
+ case MLX5_CMD_OP_DESTROY_DCT:
+ return "DESTROY_DCT";
+
+ case MLX5_CMD_OP_DRAIN_DCT:
+ return "DRAIN_DCT";
+
+ case MLX5_CMD_OP_QUERY_DCT:
+ return "QUERY_DCT";
+
+ case MLX5_CMD_OP_ARM_DCT_FOR_KEY_VIOLATION:
+ return "ARM_DCT";
+
case MLX5_CMD_OP_ALLOC_PD:
return "ALLOC_PD";
@@ -415,7 +430,7 @@ const char *mlx5_command_str(int command)
return "DEALLOC_XRCD";
case MLX5_CMD_OP_ACCESS_REG:
- return "MLX5_CMD_OP_ACCESS_REG";
+ return "ACCESS_REG";
default: return "unknown command opcode";
}
--
2.1.2
--
To unsubscribe from this list: send the line "unsubscribe linux-rdma" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply related [flat|nested] 8+ messages in thread