Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 86ef0bea authored by Doug Ledford's avatar Doug Ledford
Browse files

Merge branch 'mlx' into merge-test

parents 253f8b22 7ceb740c
Loading
Loading
Loading
Loading
+0 −3
Original line number Diff line number Diff line
@@ -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);

+1 −0
Original line number Diff line number Diff line
@@ -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 */
+155 −74
Original line number Diff line number Diff line
@@ -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);

@@ -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,
@@ -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;
@@ -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;
@@ -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;

@@ -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,
@@ -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;
	}
@@ -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;

+1 −0
Original line number Diff line number Diff line
@@ -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);
+57 −51
Original line number Diff line number Diff line
@@ -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;
@@ -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;
@@ -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,
@@ -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;
@@ -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)
{
@@ -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,
@@ -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;
@@ -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,
			 }
		}
	},
@@ -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]   = {
@@ -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) {
@@ -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);
}
@@ -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