>Thus, usage is:
>Either: create/modify/query/destroy_xrc_rcv_qp
>Or: create/modify/query/reg/unreg_xrc_rcv_qp
I think the latter usage explains why you added checks to prevent duplicate
registration. Was there a reason not to use Roland's suggestion of dropping
create/destroy and having only reg/unreg? (I must have missed this.)
>+ssize_t ib_uverbs_modify_xrc_rcv_qp(struct ib_uverbs_file *file,
>+ const char __user *buf, int in_len,
>+ int out_len)
>+{
>+ struct ib_uverbs_modify_xrc_rcv_qp cmd;
>+ struct ib_qp_attr *attr;
>+ struct ib_xrcd *xrcd;
>+ struct ib_uobject *xrcd_uobj;
>+ int err;
>+
>+ if (copy_from_user(&cmd, buf, sizeof cmd))
>+ return -EFAULT;
>+
>+ attr = kzalloc(sizeof *attr, GFP_KERNEL);
>+ if (!attr)
>+ return -ENOMEM;
>+
>+ xrcd = idr_read_xrcd(cmd.xrc_domain_handle, file->ucontext, &xrcd_uobj);
>+ if (!xrcd) {
>+ kfree(attr);
>+ return -EINVAL;
>+ }
>+
>+ attr->qp_state = cmd.qp_state;
>+ attr->cur_qp_state = cmd.cur_qp_state;
>+ attr->qp_access_flags = cmd.qp_access_flags;
>+ attr->pkey_index = cmd.pkey_index;
>+ attr->port_num = cmd.port_num;
>+ 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->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;
see comment below
>+
>+ err = xrcd->device->modify_xrc_rcv_qp(xrcd, cmd.qp_num, attr,
>cmd.attr_mask);
>+ put_uobj_read(xrcd_uobj);
>+ kfree(attr);
>+ return err ? err : in_len;
>+}
>+
>+ssize_t ib_uverbs_query_xrc_rcv_qp(struct ib_uverbs_file *file,
>+ const char __user *buf, int in_len,
>+ int out_len)
>+{
>+ struct ib_uverbs_query_xrc_rcv_qp cmd;
>+ struct ib_uverbs_query_qp_resp resp;
>+ struct ib_qp_attr *attr;
>+ struct ib_qp_init_attr *init_attr;
>+ struct ib_xrcd *xrcd;
>+ struct ib_uobject *xrcd_uobj;
>+ int ret;
>+
>+ if (copy_from_user(&cmd, buf, sizeof cmd))
>+ return -EFAULT;
>+
>+ attr = kmalloc(sizeof *attr, GFP_KERNEL);
>+ init_attr = kmalloc(sizeof *init_attr, GFP_KERNEL);
>+ if (!attr || !init_attr) {
>+ ret = -ENOMEM;
>+ goto out;
>+ }
>+
>+ xrcd = idr_read_xrcd(cmd.xrc_domain_handle, file->ucontext, &xrcd_uobj);
>+ if (!xrcd) {
>+ ret = -EINVAL;
>+ goto out;
>+ }
>+
>+ ret = xrcd->device->query_xrc_rcv_qp(xrcd, cmd.qp_num, attr,
>+ cmd.attr_mask, init_attr);
>+
>+ put_uobj_read(xrcd_uobj);
>+
>+ if (ret)
>+ goto out;
>+
>+ memset(&resp, 0, sizeof resp);
>+ resp.qp_state = attr->qp_state;
>+ resp.cur_qp_state = attr->cur_qp_state;
>+ resp.path_mtu = attr->path_mtu;
>+ resp.path_mig_state = attr->path_mig_state;
>+ resp.qkey = attr->qkey;
>+ resp.rq_psn = attr->rq_psn;
>+ resp.sq_psn = attr->sq_psn;
>+ resp.dest_qp_num = attr->dest_qp_num;
>+ resp.qp_access_flags = attr->qp_access_flags;
>+ resp.pkey_index = attr->pkey_index;
>+ resp.alt_pkey_index = attr->alt_pkey_index;
>+ resp.sq_draining = attr->sq_draining;
>+ resp.max_rd_atomic = attr->max_rd_atomic;
>+ resp.max_dest_rd_atomic = attr->max_dest_rd_atomic;
>+ resp.min_rnr_timer = attr->min_rnr_timer;
>+ resp.port_num = attr->port_num;
>+ resp.timeout = attr->timeout;
>+ resp.retry_cnt = attr->retry_cnt;
>+ resp.rnr_retry = attr->rnr_retry;
>+ resp.alt_port_num = attr->alt_port_num;
>+ resp.alt_timeout = attr->alt_timeout;
>+
>+ memcpy(resp.dest.dgid, attr->ah_attr.grh.dgid.raw, 16);
>+ resp.dest.flow_label = attr->ah_attr.grh.flow_label;
>+ resp.dest.sgid_index = attr->ah_attr.grh.sgid_index;
>+ resp.dest.hop_limit = attr->ah_attr.grh.hop_limit;
>+ resp.dest.traffic_class = attr->ah_attr.grh.traffic_class;
>+ resp.dest.dlid = attr->ah_attr.dlid;
>+ resp.dest.sl = attr->ah_attr.sl;
>+ resp.dest.src_path_bits = attr->ah_attr.src_path_bits;
>+ resp.dest.static_rate = attr->ah_attr.static_rate;
>+ resp.dest.is_global = !!(attr->ah_attr.ah_flags & IB_AH_GRH);
>+ resp.dest.port_num = attr->ah_attr.port_num;
>+
>+ memcpy(resp.alt_dest.dgid, attr->alt_ah_attr.grh.dgid.raw, 16);
>+ resp.alt_dest.flow_label = attr->alt_ah_attr.grh.flow_label;
>+ resp.alt_dest.sgid_index = attr->alt_ah_attr.grh.sgid_index;
>+ resp.alt_dest.hop_limit = attr->alt_ah_attr.grh.hop_limit;
>+ resp.alt_dest.traffic_class = attr->alt_ah_attr.grh.traffic_class;
>+ resp.alt_dest.dlid = attr->alt_ah_attr.dlid;
>+ resp.alt_dest.sl = attr->alt_ah_attr.sl;
>+ resp.alt_dest.src_path_bits = attr->alt_ah_attr.src_path_bits;
>+ resp.alt_dest.static_rate = attr->alt_ah_attr.static_rate;
>+ resp.alt_dest.is_global = !!(attr->alt_ah_attr.ah_flags &
IB_AH_GRH);
>+ resp.alt_dest.port_num = attr->alt_ah_attr.port_num;
>+
>+ resp.max_send_wr = init_attr->cap.max_send_wr;
>+ resp.max_recv_wr = init_attr->cap.max_recv_wr;
>+ resp.max_send_sge = init_attr->cap.max_send_sge;
>+ resp.max_recv_sge = init_attr->cap.max_recv_sge;
>+ resp.max_inline_data = init_attr->cap.max_inline_data;
>+ resp.sq_sig_all = init_attr->sq_sig_type ==
IB_SIGNAL_ALL_WR;
see comment below
>+
>+ if (copy_to_user((void __user *) (unsigned long) cmd.response,
>+ &resp, sizeof resp))
>+ ret = -EFAULT;
>+
>+out:
>+ kfree(attr);
>+ kfree(init_attr);
>+
>+ return ret ? ret : in_len;
>+}
>+
>+struct ib_uverbs_create_xrc_rcv_qp {
>+ __u64 response;
>+ __u64 user_handle;
>+ __u32 xrcd_handle;
>+ __u8 reserved1[28];
>+ __u64 driver_data[0];
>+};
>+
>+struct ib_uverbs_create_xrc_rcv_qp_resp {
>+ __u32 qpn;
>+ __u32 reserved;
>+};
>+
>+struct ib_uverbs_modify_xrc_rcv_qp {
>+ __u32 xrc_domain_handle;
>+ __u32 qp_num;
>+ struct ib_uverbs_qp_dest dest;
>+ struct ib_uverbs_qp_dest alt_dest;
>+ __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 driver_data[0];
>+};
This structure is almost identical to ib_uverbs_modify_qp. It replaces
qp_handle with qp_num and adds xrc_domain_handle. (Passing the qpn in as the
qp_handle makes sense.) We should be able to extract out common code with
ib_uverbs_modify_qp and ib_uverbs_query_qp.
>+
>+struct ib_uverbs_query_xrc_rcv_qp {
>+ __u64 response;
>+ __u32 xrc_domain_handle;
>+ __u32 qp_num;
>+ __u32 attr_mask;
>+ __u32 reserved;
>+ __u64 driver_data[0];
>+};
>+
>+struct ib_uverbs_destroy_xrc_rcv_qp {
>+ __u32 xrc_domain_handle;
>+ __u32 qp_num;
>+ __u64 driver_data[0];
>+};
>+
>+struct ib_uverbs_reg_xrc_rcv_qp {
>+ __u32 xrc_domain_handle;
>+ __u32 qp_num;
>+ __u64 driver_data[0];
>+};
>+
>+struct ib_uverbs_unreg_xrc_rcv_qp {
>+ __u32 xrc_domain_handle;
>+ __u32 qp_num;
>+ __u64 driver_data[0];
>+};
It's a little odd to see the same structure layout defined 3 times.
- Sean
--
To unsubscribe from this list: send the line "unsubscribe linux-rdma" in
the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html