Loading drivers/infiniband/core/core_priv.h +0 −3 Original line number Diff line number Diff line Loading @@ -72,9 +72,6 @@ void ib_device_unregister_sysfs(struct ib_device *device); void ib_cache_setup(void); void ib_cache_cleanup(void); int ib_resolve_eth_dmac(struct ib_qp *qp, struct ib_qp_attr *qp_attr, int *qp_attr_mask); typedef void (*roce_netdev_callback)(struct ib_device *device, u8 port, struct net_device *idev, void *cookie); Loading drivers/infiniband/core/uverbs.h +1 −0 Original line number Diff line number Diff line Loading @@ -289,5 +289,6 @@ IB_UVERBS_DECLARE_EX_CMD(modify_wq); IB_UVERBS_DECLARE_EX_CMD(destroy_wq); IB_UVERBS_DECLARE_EX_CMD(create_rwq_ind_table); IB_UVERBS_DECLARE_EX_CMD(destroy_rwq_ind_table); IB_UVERBS_DECLARE_EX_CMD(modify_qp); #endif /* UVERBS_H */ drivers/infiniband/core/uverbs_cmd.c +155 −74 Original line number Diff line number Diff line Loading @@ -2328,94 +2328,88 @@ static int modify_qp_mask(enum ib_qp_type qp_type, int mask) } } ssize_t ib_uverbs_modify_qp(struct ib_uverbs_file *file, struct ib_device *ib_dev, const char __user *buf, int in_len, int out_len) static int modify_qp(struct ib_uverbs_file *file, struct ib_uverbs_ex_modify_qp *cmd, struct ib_udata *udata) { struct ib_uverbs_modify_qp cmd; struct ib_udata udata; struct ib_qp *qp; struct ib_qp_attr *attr; struct ib_qp *qp; 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->base.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->base.qp_state; attr->cur_qp_state = cmd->base.cur_qp_state; attr->path_mtu = cmd->base.path_mtu; attr->path_mig_state = cmd->base.path_mig_state; attr->qkey = cmd->base.qkey; attr->rq_psn = cmd->base.rq_psn; attr->sq_psn = cmd->base.sq_psn; attr->dest_qp_num = cmd->base.dest_qp_num; attr->qp_access_flags = cmd->base.qp_access_flags; attr->pkey_index = cmd->base.pkey_index; attr->alt_pkey_index = cmd->base.alt_pkey_index; attr->en_sqd_async_notify = cmd->base.en_sqd_async_notify; attr->max_rd_atomic = cmd->base.max_rd_atomic; attr->max_dest_rd_atomic = cmd->base.max_dest_rd_atomic; attr->min_rnr_timer = cmd->base.min_rnr_timer; attr->port_num = cmd->base.port_num; attr->timeout = cmd->base.timeout; attr->retry_cnt = cmd->base.retry_cnt; attr->rnr_retry = cmd->base.rnr_retry; attr->alt_port_num = cmd->base.alt_port_num; attr->alt_timeout = cmd->base.alt_timeout; attr->rate_limit = cmd->rate_limit; memcpy(attr->ah_attr.grh.dgid.raw, cmd->base.dest.dgid, 16); attr->ah_attr.grh.flow_label = cmd->base.dest.flow_label; attr->ah_attr.grh.sgid_index = cmd->base.dest.sgid_index; attr->ah_attr.grh.hop_limit = cmd->base.dest.hop_limit; attr->ah_attr.grh.traffic_class = cmd->base.dest.traffic_class; attr->ah_attr.dlid = cmd->base.dest.dlid; attr->ah_attr.sl = cmd->base.dest.sl; attr->ah_attr.src_path_bits = cmd->base.dest.src_path_bits; attr->ah_attr.static_rate = cmd->base.dest.static_rate; attr->ah_attr.ah_flags = cmd->base.dest.is_global ? IB_AH_GRH : 0; attr->ah_attr.port_num = cmd->base.dest.port_num; memcpy(attr->alt_ah_attr.grh.dgid.raw, cmd->base.alt_dest.dgid, 16); attr->alt_ah_attr.grh.flow_label = cmd->base.alt_dest.flow_label; attr->alt_ah_attr.grh.sgid_index = cmd->base.alt_dest.sgid_index; attr->alt_ah_attr.grh.hop_limit = cmd->base.alt_dest.hop_limit; attr->alt_ah_attr.grh.traffic_class = cmd->base.alt_dest.traffic_class; attr->alt_ah_attr.dlid = cmd->base.alt_dest.dlid; attr->alt_ah_attr.sl = cmd->base.alt_dest.sl; attr->alt_ah_attr.src_path_bits = cmd->base.alt_dest.src_path_bits; attr->alt_ah_attr.static_rate = cmd->base.alt_dest.static_rate; attr->alt_ah_attr.ah_flags = cmd->base.alt_dest.is_global ? IB_AH_GRH : 0; attr->alt_ah_attr.port_num = cmd->base.alt_dest.port_num; if (qp->real_qp == qp) { ret = ib_resolve_eth_dmac(qp, attr, &cmd.attr_mask); if (cmd->base.attr_mask & IB_QP_AV) { ret = ib_resolve_eth_dmac(qp->device, &attr->ah_attr); if (ret) goto release_qp; } ret = qp->device->modify_qp(qp, attr, modify_qp_mask(qp->qp_type, cmd.attr_mask), &udata); modify_qp_mask(qp->qp_type, cmd->base.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->base.attr_mask)); } if (ret) goto release_qp; ret = in_len; release_qp: put_qp_read(qp); Loading @@ -2425,6 +2419,68 @@ ssize_t ib_uverbs_modify_qp(struct ib_uverbs_file *file, return ret; } ssize_t ib_uverbs_modify_qp(struct ib_uverbs_file *file, struct ib_device *ib_dev, const char __user *buf, int in_len, int out_len) { struct ib_uverbs_ex_modify_qp cmd = {}; struct ib_udata udata; int ret; if (copy_from_user(&cmd.base, buf, sizeof(cmd.base))) return -EFAULT; if (cmd.base.attr_mask & ~((IB_USER_LEGACY_LAST_QP_ATTR_MASK << 1) - 1)) return -EOPNOTSUPP; INIT_UDATA(&udata, buf + sizeof(cmd.base), NULL, in_len - sizeof(cmd.base), out_len); ret = modify_qp(file, &cmd, &udata); if (ret) return ret; return in_len; } int ib_uverbs_ex_modify_qp(struct ib_uverbs_file *file, struct ib_device *ib_dev, struct ib_udata *ucore, struct ib_udata *uhw) { struct ib_uverbs_ex_modify_qp cmd = {}; int ret; /* * Last bit is reserved for extending the attr_mask by * using another field. */ BUILD_BUG_ON(IB_USER_LAST_QP_ATTR_MASK == (1 << 31)); if (ucore->inlen < sizeof(cmd.base)) return -EINVAL; ret = ib_copy_from_udata(&cmd, ucore, min(sizeof(cmd), ucore->inlen)); if (ret) return ret; if (cmd.base.attr_mask & ~((IB_USER_LAST_QP_ATTR_MASK << 1) - 1)) return -EOPNOTSUPP; if (ucore->inlen > sizeof(cmd)) { if (ib_is_udata_cleared(ucore, sizeof(cmd), ucore->inlen - sizeof(cmd))) return -EOPNOTSUPP; } ret = modify_qp(file, &cmd, uhw); return ret; } ssize_t ib_uverbs_destroy_qp(struct ib_uverbs_file *file, struct ib_device *ib_dev, const char __user *buf, int in_len, Loading Loading @@ -2875,6 +2931,7 @@ ssize_t ib_uverbs_create_ah(struct ib_uverbs_file *file, struct ib_ah *ah; struct ib_ah_attr attr; int ret; struct ib_udata udata; if (out_len < sizeof resp) return -ENOSPC; Loading @@ -2882,6 +2939,10 @@ ssize_t ib_uverbs_create_ah(struct ib_uverbs_file *file, if (copy_from_user(&cmd, buf, sizeof cmd)) return -EFAULT; INIT_UDATA(&udata, buf + sizeof(cmd), (unsigned long)cmd.response + sizeof(resp), in_len - sizeof(cmd), out_len - sizeof(resp)); uobj = kmalloc(sizeof *uobj, GFP_KERNEL); if (!uobj) return -ENOMEM; Loading @@ -2908,12 +2969,16 @@ ssize_t ib_uverbs_create_ah(struct ib_uverbs_file *file, memset(&attr.dmac, 0, sizeof(attr.dmac)); memcpy(attr.grh.dgid.raw, cmd.attr.grh.dgid, 16); ah = ib_create_ah(pd, &attr); ah = pd->device->create_ah(pd, &attr, &udata); if (IS_ERR(ah)) { ret = PTR_ERR(ah); goto err_put; } ah->device = pd->device; ah->pd = pd; atomic_inc(&pd->usecnt); ah->uobject = uobj; uobj->object = ah; Loading Loading @@ -3124,8 +3189,10 @@ static int kern_spec_to_ib_spec(struct ib_uverbs_flow_spec *kern_spec, kern_spec_val = (void *)kern_spec + sizeof(struct ib_uverbs_flow_spec_hdr); kern_spec_mask = kern_spec_val + kern_filter_sz; if (ib_spec->type == (IB_FLOW_SPEC_INNER | IB_FLOW_SPEC_VXLAN_TUNNEL)) return -EINVAL; switch (ib_spec->type) { switch (ib_spec->type & ~IB_FLOW_SPEC_INNER) { case IB_FLOW_SPEC_ETH: ib_filter_sz = offsetof(struct ib_flow_eth_filter, real_sz); actual_filter_sz = spec_filter_size(kern_spec_mask, Loading Loading @@ -3175,6 +3242,21 @@ static int kern_spec_to_ib_spec(struct ib_uverbs_flow_spec *kern_spec, memcpy(&ib_spec->tcp_udp.val, kern_spec_val, actual_filter_sz); memcpy(&ib_spec->tcp_udp.mask, kern_spec_mask, actual_filter_sz); break; case IB_FLOW_SPEC_VXLAN_TUNNEL: ib_filter_sz = offsetof(struct ib_flow_tunnel_filter, real_sz); actual_filter_sz = spec_filter_size(kern_spec_mask, kern_filter_sz, ib_filter_sz); if (actual_filter_sz <= 0) return -EINVAL; ib_spec->tunnel.size = sizeof(struct ib_flow_spec_tunnel); memcpy(&ib_spec->tunnel.val, kern_spec_val, actual_filter_sz); memcpy(&ib_spec->tunnel.mask, kern_spec_mask, actual_filter_sz); if ((ntohl(ib_spec->tunnel.mask.tunnel_id)) >= BIT(24) || (ntohl(ib_spec->tunnel.val.tunnel_id)) >= BIT(24)) return -EINVAL; break; default: return -EINVAL; } Loading Loading @@ -3745,7 +3827,6 @@ int ib_uverbs_ex_create_flow(struct ib_uverbs_file *file, err = PTR_ERR(flow_id); goto err_free; } flow_id->qp = qp; flow_id->uobject = uobj; uobj->object = flow_id; Loading drivers/infiniband/core/uverbs_main.c +1 −0 Original line number Diff line number Diff line Loading @@ -137,6 +137,7 @@ static int (*uverbs_ex_cmd_table[])(struct ib_uverbs_file *file, [IB_USER_VERBS_EX_CMD_DESTROY_WQ] = ib_uverbs_ex_destroy_wq, [IB_USER_VERBS_EX_CMD_CREATE_RWQ_IND_TBL] = ib_uverbs_ex_create_rwq_ind_table, [IB_USER_VERBS_EX_CMD_DESTROY_RWQ_IND_TBL] = ib_uverbs_ex_destroy_rwq_ind_table, [IB_USER_VERBS_EX_CMD_MODIFY_QP] = ib_uverbs_ex_modify_qp, }; static void ib_uverbs_add_one(struct ib_device *device); Loading drivers/infiniband/core/verbs.c +57 −51 Original line number Diff line number Diff line Loading @@ -315,7 +315,7 @@ struct ib_ah *ib_create_ah(struct ib_pd *pd, struct ib_ah_attr *ah_attr) { struct ib_ah *ah; ah = pd->device->create_ah(pd, ah_attr); ah = pd->device->create_ah(pd, ah_attr, NULL); if (!IS_ERR(ah)) { ah->device = pd->device; Loading @@ -328,7 +328,7 @@ struct ib_ah *ib_create_ah(struct ib_pd *pd, struct ib_ah_attr *ah_attr) } EXPORT_SYMBOL(ib_create_ah); static int ib_get_header_version(const union rdma_network_hdr *hdr) int ib_get_rdma_header_version(const union rdma_network_hdr *hdr) { const struct iphdr *ip4h = (struct iphdr *)&hdr->roce4grh; struct iphdr ip4h_checked; Loading Loading @@ -359,6 +359,7 @@ static int ib_get_header_version(const union rdma_network_hdr *hdr) return 4; return 6; } EXPORT_SYMBOL(ib_get_rdma_header_version); static enum rdma_network_type ib_get_net_type_by_grh(struct ib_device *device, u8 port_num, Loading @@ -369,7 +370,7 @@ static enum rdma_network_type ib_get_net_type_by_grh(struct ib_device *device, if (rdma_protocol_ib(device, port_num)) return RDMA_NETWORK_IB; grh_version = ib_get_header_version((union rdma_network_hdr *)grh); grh_version = ib_get_rdma_header_version((union rdma_network_hdr *)grh); if (grh_version == 4) return RDMA_NETWORK_IPV4; Loading Loading @@ -415,7 +416,7 @@ static int get_sgid_index_from_eth(struct ib_device *device, u8 port_num, &context, gid_index); } static int get_gids_from_rdma_hdr(union rdma_network_hdr *hdr, int ib_get_gids_from_rdma_hdr(const union rdma_network_hdr *hdr, enum rdma_network_type net_type, union ib_gid *sgid, union ib_gid *dgid) { Loading Loading @@ -447,6 +448,7 @@ static int get_gids_from_rdma_hdr(union rdma_network_hdr *hdr, return -EINVAL; } } EXPORT_SYMBOL(ib_get_gids_from_rdma_hdr); int ib_init_ah_from_wc(struct ib_device *device, u8 port_num, const struct ib_wc *wc, const struct ib_grh *grh, Loading @@ -469,7 +471,7 @@ int ib_init_ah_from_wc(struct ib_device *device, u8 port_num, net_type = ib_get_net_type_by_grh(device, port_num, grh); gid_type = ib_network_to_gid_type(net_type); } ret = get_gids_from_rdma_hdr((union rdma_network_hdr *)grh, net_type, ret = ib_get_gids_from_rdma_hdr((union rdma_network_hdr *)grh, net_type, &sgid, &dgid); if (ret) return ret; Loading Loading @@ -1014,6 +1016,7 @@ static const struct { IB_QP_QKEY), [IB_QPT_GSI] = (IB_QP_CUR_STATE | IB_QP_QKEY), [IB_QPT_RAW_PACKET] = IB_QP_RATE_LIMIT, } } }, Loading Loading @@ -1047,6 +1050,7 @@ static const struct { IB_QP_QKEY), [IB_QPT_GSI] = (IB_QP_CUR_STATE | IB_QP_QKEY), [IB_QPT_RAW_PACKET] = IB_QP_RATE_LIMIT, } }, [IB_QPS_SQD] = { Loading Loading @@ -1196,31 +1200,30 @@ int ib_modify_qp_is_ok(enum ib_qp_state cur_state, enum ib_qp_state next_state, } EXPORT_SYMBOL(ib_modify_qp_is_ok); int ib_resolve_eth_dmac(struct ib_qp *qp, struct ib_qp_attr *qp_attr, int *qp_attr_mask) int ib_resolve_eth_dmac(struct ib_device *device, struct ib_ah_attr *ah_attr) { int ret = 0; if (*qp_attr_mask & IB_QP_AV) { if (qp_attr->ah_attr.port_num < rdma_start_port(qp->device) || qp_attr->ah_attr.port_num > rdma_end_port(qp->device)) if (ah_attr->port_num < rdma_start_port(device) || ah_attr->port_num > rdma_end_port(device)) return -EINVAL; if (!rdma_cap_eth_ah(qp->device, qp_attr->ah_attr.port_num)) if (!rdma_cap_eth_ah(device, ah_attr->port_num)) return 0; if (rdma_link_local_addr((struct in6_addr *)qp_attr->ah_attr.grh.dgid.raw)) { rdma_get_ll_mac((struct in6_addr *)qp_attr->ah_attr.grh.dgid.raw, qp_attr->ah_attr.dmac); if (rdma_link_local_addr((struct in6_addr *)ah_attr->grh.dgid.raw)) { rdma_get_ll_mac((struct in6_addr *)ah_attr->grh.dgid.raw, ah_attr->dmac); } else { union ib_gid sgid; struct ib_gid_attr sgid_attr; int ifindex; int hop_limit; ret = ib_query_gid(qp->device, qp_attr->ah_attr.port_num, qp_attr->ah_attr.grh.sgid_index, ret = ib_query_gid(device, ah_attr->port_num, ah_attr->grh.sgid_index, &sgid, &sgid_attr); if (ret || !sgid_attr.ndev) { Loading @@ -1232,30 +1235,31 @@ int ib_resolve_eth_dmac(struct ib_qp *qp, ifindex = sgid_attr.ndev->ifindex; ret = rdma_addr_find_l2_eth_by_grh(&sgid, &qp_attr->ah_attr.grh.dgid, qp_attr->ah_attr.dmac, &ah_attr->grh.dgid, ah_attr->dmac, NULL, &ifindex, &hop_limit); dev_put(sgid_attr.ndev); qp_attr->ah_attr.grh.hop_limit = hop_limit; } ah_attr->grh.hop_limit = hop_limit; } out: return ret; } EXPORT_SYMBOL(ib_resolve_eth_dmac); int ib_modify_qp(struct ib_qp *qp, struct ib_qp_attr *qp_attr, int qp_attr_mask) { if (qp_attr_mask & IB_QP_AV) { int ret; ret = ib_resolve_eth_dmac(qp, qp_attr, &qp_attr_mask); ret = ib_resolve_eth_dmac(qp->device, &qp_attr->ah_attr); if (ret) return ret; } return qp->device->modify_qp(qp->real_qp, qp_attr, qp_attr_mask, NULL); } Loading Loading @@ -1734,8 +1738,10 @@ struct ib_flow *ib_create_flow(struct ib_qp *qp, return ERR_PTR(-ENOSYS); flow_id = qp->device->create_flow(qp, flow_attr, domain); if (!IS_ERR(flow_id)) if (!IS_ERR(flow_id)) { atomic_inc(&qp->usecnt); flow_id->qp = qp; } return flow_id; } EXPORT_SYMBOL(ib_create_flow); Loading Loading
drivers/infiniband/core/core_priv.h +0 −3 Original line number Diff line number Diff line Loading @@ -72,9 +72,6 @@ void ib_device_unregister_sysfs(struct ib_device *device); void ib_cache_setup(void); void ib_cache_cleanup(void); int ib_resolve_eth_dmac(struct ib_qp *qp, struct ib_qp_attr *qp_attr, int *qp_attr_mask); typedef void (*roce_netdev_callback)(struct ib_device *device, u8 port, struct net_device *idev, void *cookie); Loading
drivers/infiniband/core/uverbs.h +1 −0 Original line number Diff line number Diff line Loading @@ -289,5 +289,6 @@ IB_UVERBS_DECLARE_EX_CMD(modify_wq); IB_UVERBS_DECLARE_EX_CMD(destroy_wq); IB_UVERBS_DECLARE_EX_CMD(create_rwq_ind_table); IB_UVERBS_DECLARE_EX_CMD(destroy_rwq_ind_table); IB_UVERBS_DECLARE_EX_CMD(modify_qp); #endif /* UVERBS_H */
drivers/infiniband/core/uverbs_cmd.c +155 −74 Original line number Diff line number Diff line Loading @@ -2328,94 +2328,88 @@ static int modify_qp_mask(enum ib_qp_type qp_type, int mask) } } ssize_t ib_uverbs_modify_qp(struct ib_uverbs_file *file, struct ib_device *ib_dev, const char __user *buf, int in_len, int out_len) static int modify_qp(struct ib_uverbs_file *file, struct ib_uverbs_ex_modify_qp *cmd, struct ib_udata *udata) { struct ib_uverbs_modify_qp cmd; struct ib_udata udata; struct ib_qp *qp; struct ib_qp_attr *attr; struct ib_qp *qp; 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->base.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->base.qp_state; attr->cur_qp_state = cmd->base.cur_qp_state; attr->path_mtu = cmd->base.path_mtu; attr->path_mig_state = cmd->base.path_mig_state; attr->qkey = cmd->base.qkey; attr->rq_psn = cmd->base.rq_psn; attr->sq_psn = cmd->base.sq_psn; attr->dest_qp_num = cmd->base.dest_qp_num; attr->qp_access_flags = cmd->base.qp_access_flags; attr->pkey_index = cmd->base.pkey_index; attr->alt_pkey_index = cmd->base.alt_pkey_index; attr->en_sqd_async_notify = cmd->base.en_sqd_async_notify; attr->max_rd_atomic = cmd->base.max_rd_atomic; attr->max_dest_rd_atomic = cmd->base.max_dest_rd_atomic; attr->min_rnr_timer = cmd->base.min_rnr_timer; attr->port_num = cmd->base.port_num; attr->timeout = cmd->base.timeout; attr->retry_cnt = cmd->base.retry_cnt; attr->rnr_retry = cmd->base.rnr_retry; attr->alt_port_num = cmd->base.alt_port_num; attr->alt_timeout = cmd->base.alt_timeout; attr->rate_limit = cmd->rate_limit; memcpy(attr->ah_attr.grh.dgid.raw, cmd->base.dest.dgid, 16); attr->ah_attr.grh.flow_label = cmd->base.dest.flow_label; attr->ah_attr.grh.sgid_index = cmd->base.dest.sgid_index; attr->ah_attr.grh.hop_limit = cmd->base.dest.hop_limit; attr->ah_attr.grh.traffic_class = cmd->base.dest.traffic_class; attr->ah_attr.dlid = cmd->base.dest.dlid; attr->ah_attr.sl = cmd->base.dest.sl; attr->ah_attr.src_path_bits = cmd->base.dest.src_path_bits; attr->ah_attr.static_rate = cmd->base.dest.static_rate; attr->ah_attr.ah_flags = cmd->base.dest.is_global ? IB_AH_GRH : 0; attr->ah_attr.port_num = cmd->base.dest.port_num; memcpy(attr->alt_ah_attr.grh.dgid.raw, cmd->base.alt_dest.dgid, 16); attr->alt_ah_attr.grh.flow_label = cmd->base.alt_dest.flow_label; attr->alt_ah_attr.grh.sgid_index = cmd->base.alt_dest.sgid_index; attr->alt_ah_attr.grh.hop_limit = cmd->base.alt_dest.hop_limit; attr->alt_ah_attr.grh.traffic_class = cmd->base.alt_dest.traffic_class; attr->alt_ah_attr.dlid = cmd->base.alt_dest.dlid; attr->alt_ah_attr.sl = cmd->base.alt_dest.sl; attr->alt_ah_attr.src_path_bits = cmd->base.alt_dest.src_path_bits; attr->alt_ah_attr.static_rate = cmd->base.alt_dest.static_rate; attr->alt_ah_attr.ah_flags = cmd->base.alt_dest.is_global ? IB_AH_GRH : 0; attr->alt_ah_attr.port_num = cmd->base.alt_dest.port_num; if (qp->real_qp == qp) { ret = ib_resolve_eth_dmac(qp, attr, &cmd.attr_mask); if (cmd->base.attr_mask & IB_QP_AV) { ret = ib_resolve_eth_dmac(qp->device, &attr->ah_attr); if (ret) goto release_qp; } ret = qp->device->modify_qp(qp, attr, modify_qp_mask(qp->qp_type, cmd.attr_mask), &udata); modify_qp_mask(qp->qp_type, cmd->base.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->base.attr_mask)); } if (ret) goto release_qp; ret = in_len; release_qp: put_qp_read(qp); Loading @@ -2425,6 +2419,68 @@ ssize_t ib_uverbs_modify_qp(struct ib_uverbs_file *file, return ret; } ssize_t ib_uverbs_modify_qp(struct ib_uverbs_file *file, struct ib_device *ib_dev, const char __user *buf, int in_len, int out_len) { struct ib_uverbs_ex_modify_qp cmd = {}; struct ib_udata udata; int ret; if (copy_from_user(&cmd.base, buf, sizeof(cmd.base))) return -EFAULT; if (cmd.base.attr_mask & ~((IB_USER_LEGACY_LAST_QP_ATTR_MASK << 1) - 1)) return -EOPNOTSUPP; INIT_UDATA(&udata, buf + sizeof(cmd.base), NULL, in_len - sizeof(cmd.base), out_len); ret = modify_qp(file, &cmd, &udata); if (ret) return ret; return in_len; } int ib_uverbs_ex_modify_qp(struct ib_uverbs_file *file, struct ib_device *ib_dev, struct ib_udata *ucore, struct ib_udata *uhw) { struct ib_uverbs_ex_modify_qp cmd = {}; int ret; /* * Last bit is reserved for extending the attr_mask by * using another field. */ BUILD_BUG_ON(IB_USER_LAST_QP_ATTR_MASK == (1 << 31)); if (ucore->inlen < sizeof(cmd.base)) return -EINVAL; ret = ib_copy_from_udata(&cmd, ucore, min(sizeof(cmd), ucore->inlen)); if (ret) return ret; if (cmd.base.attr_mask & ~((IB_USER_LAST_QP_ATTR_MASK << 1) - 1)) return -EOPNOTSUPP; if (ucore->inlen > sizeof(cmd)) { if (ib_is_udata_cleared(ucore, sizeof(cmd), ucore->inlen - sizeof(cmd))) return -EOPNOTSUPP; } ret = modify_qp(file, &cmd, uhw); return ret; } ssize_t ib_uverbs_destroy_qp(struct ib_uverbs_file *file, struct ib_device *ib_dev, const char __user *buf, int in_len, Loading Loading @@ -2875,6 +2931,7 @@ ssize_t ib_uverbs_create_ah(struct ib_uverbs_file *file, struct ib_ah *ah; struct ib_ah_attr attr; int ret; struct ib_udata udata; if (out_len < sizeof resp) return -ENOSPC; Loading @@ -2882,6 +2939,10 @@ ssize_t ib_uverbs_create_ah(struct ib_uverbs_file *file, if (copy_from_user(&cmd, buf, sizeof cmd)) return -EFAULT; INIT_UDATA(&udata, buf + sizeof(cmd), (unsigned long)cmd.response + sizeof(resp), in_len - sizeof(cmd), out_len - sizeof(resp)); uobj = kmalloc(sizeof *uobj, GFP_KERNEL); if (!uobj) return -ENOMEM; Loading @@ -2908,12 +2969,16 @@ ssize_t ib_uverbs_create_ah(struct ib_uverbs_file *file, memset(&attr.dmac, 0, sizeof(attr.dmac)); memcpy(attr.grh.dgid.raw, cmd.attr.grh.dgid, 16); ah = ib_create_ah(pd, &attr); ah = pd->device->create_ah(pd, &attr, &udata); if (IS_ERR(ah)) { ret = PTR_ERR(ah); goto err_put; } ah->device = pd->device; ah->pd = pd; atomic_inc(&pd->usecnt); ah->uobject = uobj; uobj->object = ah; Loading Loading @@ -3124,8 +3189,10 @@ static int kern_spec_to_ib_spec(struct ib_uverbs_flow_spec *kern_spec, kern_spec_val = (void *)kern_spec + sizeof(struct ib_uverbs_flow_spec_hdr); kern_spec_mask = kern_spec_val + kern_filter_sz; if (ib_spec->type == (IB_FLOW_SPEC_INNER | IB_FLOW_SPEC_VXLAN_TUNNEL)) return -EINVAL; switch (ib_spec->type) { switch (ib_spec->type & ~IB_FLOW_SPEC_INNER) { case IB_FLOW_SPEC_ETH: ib_filter_sz = offsetof(struct ib_flow_eth_filter, real_sz); actual_filter_sz = spec_filter_size(kern_spec_mask, Loading Loading @@ -3175,6 +3242,21 @@ static int kern_spec_to_ib_spec(struct ib_uverbs_flow_spec *kern_spec, memcpy(&ib_spec->tcp_udp.val, kern_spec_val, actual_filter_sz); memcpy(&ib_spec->tcp_udp.mask, kern_spec_mask, actual_filter_sz); break; case IB_FLOW_SPEC_VXLAN_TUNNEL: ib_filter_sz = offsetof(struct ib_flow_tunnel_filter, real_sz); actual_filter_sz = spec_filter_size(kern_spec_mask, kern_filter_sz, ib_filter_sz); if (actual_filter_sz <= 0) return -EINVAL; ib_spec->tunnel.size = sizeof(struct ib_flow_spec_tunnel); memcpy(&ib_spec->tunnel.val, kern_spec_val, actual_filter_sz); memcpy(&ib_spec->tunnel.mask, kern_spec_mask, actual_filter_sz); if ((ntohl(ib_spec->tunnel.mask.tunnel_id)) >= BIT(24) || (ntohl(ib_spec->tunnel.val.tunnel_id)) >= BIT(24)) return -EINVAL; break; default: return -EINVAL; } Loading Loading @@ -3745,7 +3827,6 @@ int ib_uverbs_ex_create_flow(struct ib_uverbs_file *file, err = PTR_ERR(flow_id); goto err_free; } flow_id->qp = qp; flow_id->uobject = uobj; uobj->object = flow_id; Loading
drivers/infiniband/core/uverbs_main.c +1 −0 Original line number Diff line number Diff line Loading @@ -137,6 +137,7 @@ static int (*uverbs_ex_cmd_table[])(struct ib_uverbs_file *file, [IB_USER_VERBS_EX_CMD_DESTROY_WQ] = ib_uverbs_ex_destroy_wq, [IB_USER_VERBS_EX_CMD_CREATE_RWQ_IND_TBL] = ib_uverbs_ex_create_rwq_ind_table, [IB_USER_VERBS_EX_CMD_DESTROY_RWQ_IND_TBL] = ib_uverbs_ex_destroy_rwq_ind_table, [IB_USER_VERBS_EX_CMD_MODIFY_QP] = ib_uverbs_ex_modify_qp, }; static void ib_uverbs_add_one(struct ib_device *device); Loading
drivers/infiniband/core/verbs.c +57 −51 Original line number Diff line number Diff line Loading @@ -315,7 +315,7 @@ struct ib_ah *ib_create_ah(struct ib_pd *pd, struct ib_ah_attr *ah_attr) { struct ib_ah *ah; ah = pd->device->create_ah(pd, ah_attr); ah = pd->device->create_ah(pd, ah_attr, NULL); if (!IS_ERR(ah)) { ah->device = pd->device; Loading @@ -328,7 +328,7 @@ struct ib_ah *ib_create_ah(struct ib_pd *pd, struct ib_ah_attr *ah_attr) } EXPORT_SYMBOL(ib_create_ah); static int ib_get_header_version(const union rdma_network_hdr *hdr) int ib_get_rdma_header_version(const union rdma_network_hdr *hdr) { const struct iphdr *ip4h = (struct iphdr *)&hdr->roce4grh; struct iphdr ip4h_checked; Loading Loading @@ -359,6 +359,7 @@ static int ib_get_header_version(const union rdma_network_hdr *hdr) return 4; return 6; } EXPORT_SYMBOL(ib_get_rdma_header_version); static enum rdma_network_type ib_get_net_type_by_grh(struct ib_device *device, u8 port_num, Loading @@ -369,7 +370,7 @@ static enum rdma_network_type ib_get_net_type_by_grh(struct ib_device *device, if (rdma_protocol_ib(device, port_num)) return RDMA_NETWORK_IB; grh_version = ib_get_header_version((union rdma_network_hdr *)grh); grh_version = ib_get_rdma_header_version((union rdma_network_hdr *)grh); if (grh_version == 4) return RDMA_NETWORK_IPV4; Loading Loading @@ -415,7 +416,7 @@ static int get_sgid_index_from_eth(struct ib_device *device, u8 port_num, &context, gid_index); } static int get_gids_from_rdma_hdr(union rdma_network_hdr *hdr, int ib_get_gids_from_rdma_hdr(const union rdma_network_hdr *hdr, enum rdma_network_type net_type, union ib_gid *sgid, union ib_gid *dgid) { Loading Loading @@ -447,6 +448,7 @@ static int get_gids_from_rdma_hdr(union rdma_network_hdr *hdr, return -EINVAL; } } EXPORT_SYMBOL(ib_get_gids_from_rdma_hdr); int ib_init_ah_from_wc(struct ib_device *device, u8 port_num, const struct ib_wc *wc, const struct ib_grh *grh, Loading @@ -469,7 +471,7 @@ int ib_init_ah_from_wc(struct ib_device *device, u8 port_num, net_type = ib_get_net_type_by_grh(device, port_num, grh); gid_type = ib_network_to_gid_type(net_type); } ret = get_gids_from_rdma_hdr((union rdma_network_hdr *)grh, net_type, ret = ib_get_gids_from_rdma_hdr((union rdma_network_hdr *)grh, net_type, &sgid, &dgid); if (ret) return ret; Loading Loading @@ -1014,6 +1016,7 @@ static const struct { IB_QP_QKEY), [IB_QPT_GSI] = (IB_QP_CUR_STATE | IB_QP_QKEY), [IB_QPT_RAW_PACKET] = IB_QP_RATE_LIMIT, } } }, Loading Loading @@ -1047,6 +1050,7 @@ static const struct { IB_QP_QKEY), [IB_QPT_GSI] = (IB_QP_CUR_STATE | IB_QP_QKEY), [IB_QPT_RAW_PACKET] = IB_QP_RATE_LIMIT, } }, [IB_QPS_SQD] = { Loading Loading @@ -1196,31 +1200,30 @@ int ib_modify_qp_is_ok(enum ib_qp_state cur_state, enum ib_qp_state next_state, } EXPORT_SYMBOL(ib_modify_qp_is_ok); int ib_resolve_eth_dmac(struct ib_qp *qp, struct ib_qp_attr *qp_attr, int *qp_attr_mask) int ib_resolve_eth_dmac(struct ib_device *device, struct ib_ah_attr *ah_attr) { int ret = 0; if (*qp_attr_mask & IB_QP_AV) { if (qp_attr->ah_attr.port_num < rdma_start_port(qp->device) || qp_attr->ah_attr.port_num > rdma_end_port(qp->device)) if (ah_attr->port_num < rdma_start_port(device) || ah_attr->port_num > rdma_end_port(device)) return -EINVAL; if (!rdma_cap_eth_ah(qp->device, qp_attr->ah_attr.port_num)) if (!rdma_cap_eth_ah(device, ah_attr->port_num)) return 0; if (rdma_link_local_addr((struct in6_addr *)qp_attr->ah_attr.grh.dgid.raw)) { rdma_get_ll_mac((struct in6_addr *)qp_attr->ah_attr.grh.dgid.raw, qp_attr->ah_attr.dmac); if (rdma_link_local_addr((struct in6_addr *)ah_attr->grh.dgid.raw)) { rdma_get_ll_mac((struct in6_addr *)ah_attr->grh.dgid.raw, ah_attr->dmac); } else { union ib_gid sgid; struct ib_gid_attr sgid_attr; int ifindex; int hop_limit; ret = ib_query_gid(qp->device, qp_attr->ah_attr.port_num, qp_attr->ah_attr.grh.sgid_index, ret = ib_query_gid(device, ah_attr->port_num, ah_attr->grh.sgid_index, &sgid, &sgid_attr); if (ret || !sgid_attr.ndev) { Loading @@ -1232,30 +1235,31 @@ int ib_resolve_eth_dmac(struct ib_qp *qp, ifindex = sgid_attr.ndev->ifindex; ret = rdma_addr_find_l2_eth_by_grh(&sgid, &qp_attr->ah_attr.grh.dgid, qp_attr->ah_attr.dmac, &ah_attr->grh.dgid, ah_attr->dmac, NULL, &ifindex, &hop_limit); dev_put(sgid_attr.ndev); qp_attr->ah_attr.grh.hop_limit = hop_limit; } ah_attr->grh.hop_limit = hop_limit; } out: return ret; } EXPORT_SYMBOL(ib_resolve_eth_dmac); int ib_modify_qp(struct ib_qp *qp, struct ib_qp_attr *qp_attr, int qp_attr_mask) { if (qp_attr_mask & IB_QP_AV) { int ret; ret = ib_resolve_eth_dmac(qp, qp_attr, &qp_attr_mask); ret = ib_resolve_eth_dmac(qp->device, &qp_attr->ah_attr); if (ret) return ret; } return qp->device->modify_qp(qp->real_qp, qp_attr, qp_attr_mask, NULL); } Loading Loading @@ -1734,8 +1738,10 @@ struct ib_flow *ib_create_flow(struct ib_qp *qp, return ERR_PTR(-ENOSYS); flow_id = qp->device->create_flow(qp, flow_attr, domain); if (!IS_ERR(flow_id)) if (!IS_ERR(flow_id)) { atomic_inc(&qp->usecnt); flow_id->qp = qp; } return flow_id; } EXPORT_SYMBOL(ib_create_flow); Loading