Commit 6207b37e authored by Linus Torvalds's avatar Linus Torvalds
Browse files
Pull rdma updates from Jason Gunthorpe:
 "Very small update this cycle:

   - Minor code improvements in fi, rxe, ipoib, mana, cxgb4, mlx5,
     irdma, rxe, rtrs, mana

   - Simplify the hns hem mechanism

   - Fix EFA's MSI-X allocation in resource constrained configurations

   - Fix a KASN splat in srpt

   - Narrow hns's congestion control selection to QPs granularity and
     allow userspace to select it

   - Solve a parallel module loading race between the CM module and a
     driver module

   - Flexible array cleanup

   - Dump hns's SCC Conext to 'rdma res' for debugging

   - Make mana build page lists for HW objects that require a 0 offset
     correctly

   - Stuck CM ID debugging"

* tag 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/rdma/rdma: (29 commits)
  RDMA/cm: add timeout to cm_destroy_id wait
  RDMA/mana_ib: Use virtual address in dma regions for MRs
  RDMA/mana_ib: Fix bug in creation of dma regions
  RDMA/hns: Append SCC context to the raw dump of QPC
  RDMA/uverbs: Avoid -Wflex-array-member-not-at-end warnings
  RDMA/hns: Support userspace configuring congestion control algorithm with QP granularity
  RDMA/rtrs-clt: Check strnlen return len in sysfs mpath_policy_store()
  RDMA/uverbs: Remove flexible arrays from struct *_filter
  RDMA/device: Fix a race between mad_client and cm_client init
  RDMA/hns: Fix mis-modifying default congestion control algorithm
  RDMA/rxe: Remove unused 'iova' parameter from rxe_mr_init_user
  RDMA/srpt: Do not register event handler until srpt device is fully setup
  RDMA/irdma: Remove duplicate assignment
  RDMA/efa: Limit EQs to available MSI-X vectors
  RDMA/mlx5: Delete unused mlx5_ib_copy_pas prototype
  RDMA/cxgb4: Delete unused c4iw_ep_redirect prototype
  RDMA/mana_ib: Introduce mana_ib_install_cq_cb helper function
  RDMA/mana_ib: Introduce mana_ib_get_netdev helper function
  RDMA/mana_ib: Introduce mdev_to_gc helper function
  RDMA/hns: Simplify 'struct hns_roce_hem' allocation
  ...
parents 65b64246 96d9cbe2
Loading
Loading
Loading
Loading
+19 −1
Original line number Diff line number Diff line
@@ -34,6 +34,7 @@ MODULE_AUTHOR("Sean Hefty");
MODULE_DESCRIPTION("InfiniBand CM");
MODULE_LICENSE("Dual BSD/GPL");

#define CM_DESTROY_ID_WAIT_TIMEOUT 10000 /* msecs */
static const char * const ibcm_rej_reason_strs[] = {
	[IB_CM_REJ_NO_QP]			= "no QP",
	[IB_CM_REJ_NO_EEC]			= "no EEC",
@@ -1025,10 +1026,20 @@ static void cm_reset_to_idle(struct cm_id_private *cm_id_priv)
	}
}

static noinline void cm_destroy_id_wait_timeout(struct ib_cm_id *cm_id)
{
	struct cm_id_private *cm_id_priv;

	cm_id_priv = container_of(cm_id, struct cm_id_private, id);
	pr_err("%s: cm_id=%p timed out. state=%d refcnt=%d\n", __func__,
	       cm_id, cm_id->state, refcount_read(&cm_id_priv->refcount));
}

static void cm_destroy_id(struct ib_cm_id *cm_id, int err)
{
	struct cm_id_private *cm_id_priv;
	struct cm_work *work;
	int ret;

	cm_id_priv = container_of(cm_id, struct cm_id_private, id);
	spin_lock_irq(&cm_id_priv->lock);
@@ -1135,7 +1146,14 @@ static void cm_destroy_id(struct ib_cm_id *cm_id, int err)

	xa_erase(&cm.local_id_table, cm_local_id(cm_id->local_id));
	cm_deref_id(cm_id_priv);
	wait_for_completion(&cm_id_priv->comp);
	do {
		ret = wait_for_completion_timeout(&cm_id_priv->comp,
						  msecs_to_jiffies(
						  CM_DESTROY_ID_WAIT_TIMEOUT));
		if (!ret) /* timeout happened */
			cm_destroy_id_wait_timeout(cm_id);
	} while (!ret);

	while ((work = cm_dequeue_work(cm_id_priv)) != NULL)
		cm_free_work(work);

+22 −15
Original line number Diff line number Diff line
@@ -1730,7 +1730,7 @@ static int assign_client_id(struct ib_client *client)
{
	int ret;

	down_write(&clients_rwsem);
	lockdep_assert_held(&clients_rwsem);
	/*
	 * The add/remove callbacks must be called in FIFO/LIFO order. To
	 * achieve this we assign client_ids so they are sorted in
@@ -1739,14 +1739,11 @@ static int assign_client_id(struct ib_client *client)
	client->client_id = highest_client_id;
	ret = xa_insert(&clients, client->client_id, client, GFP_KERNEL);
	if (ret)
		goto out;
		return ret;

	highest_client_id++;
	xa_set_mark(&clients, client->client_id, CLIENT_REGISTERED);

out:
	up_write(&clients_rwsem);
	return ret;
	return 0;
}

static void remove_client_id(struct ib_client *client)
@@ -1776,26 +1773,36 @@ int ib_register_client(struct ib_client *client)
{
	struct ib_device *device;
	unsigned long index;
	bool need_unreg = false;
	int ret;

	refcount_set(&client->uses, 1);
	init_completion(&client->uses_zero);

	/*
	 * The devices_rwsem is held in write mode to ensure that a racing
	 * ib_register_device() sees a consisent view of clients and devices.
	 */
	down_write(&devices_rwsem);
	down_write(&clients_rwsem);
	ret = assign_client_id(client);
	if (ret)
		return ret;
		goto out;

	down_read(&devices_rwsem);
	need_unreg = true;
	xa_for_each_marked (&devices, index, device, DEVICE_REGISTERED) {
		ret = add_client_context(device, client);
		if (ret) {
			up_read(&devices_rwsem);
		if (ret)
			goto out;
	}
	ret = 0;
out:
	up_write(&clients_rwsem);
	up_write(&devices_rwsem);
	if (need_unreg && ret)
		ib_unregister_client(client);
	return ret;
}
	}
	up_read(&devices_rwsem);
	return 0;
}
EXPORT_SYMBOL(ib_register_client);

/**
+8 −8
Original line number Diff line number Diff line
@@ -2737,7 +2737,7 @@ int ib_uverbs_kern_spec_to_ib_spec_filter(enum ib_flow_spec_type 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);
		ib_filter_sz = sizeof(struct ib_flow_eth_filter);
		actual_filter_sz = spec_filter_size(kern_spec_mask,
						    kern_filter_sz,
						    ib_filter_sz);
@@ -2748,7 +2748,7 @@ int ib_uverbs_kern_spec_to_ib_spec_filter(enum ib_flow_spec_type type,
		memcpy(&ib_spec->eth.mask, kern_spec_mask, actual_filter_sz);
		break;
	case IB_FLOW_SPEC_IPV4:
		ib_filter_sz = offsetof(struct ib_flow_ipv4_filter, real_sz);
		ib_filter_sz = sizeof(struct ib_flow_ipv4_filter);
		actual_filter_sz = spec_filter_size(kern_spec_mask,
						    kern_filter_sz,
						    ib_filter_sz);
@@ -2759,7 +2759,7 @@ int ib_uverbs_kern_spec_to_ib_spec_filter(enum ib_flow_spec_type type,
		memcpy(&ib_spec->ipv4.mask, kern_spec_mask, actual_filter_sz);
		break;
	case IB_FLOW_SPEC_IPV6:
		ib_filter_sz = offsetof(struct ib_flow_ipv6_filter, real_sz);
		ib_filter_sz = sizeof(struct ib_flow_ipv6_filter);
		actual_filter_sz = spec_filter_size(kern_spec_mask,
						    kern_filter_sz,
						    ib_filter_sz);
@@ -2775,7 +2775,7 @@ int ib_uverbs_kern_spec_to_ib_spec_filter(enum ib_flow_spec_type type,
		break;
	case IB_FLOW_SPEC_TCP:
	case IB_FLOW_SPEC_UDP:
		ib_filter_sz = offsetof(struct ib_flow_tcp_udp_filter, real_sz);
		ib_filter_sz = sizeof(struct ib_flow_tcp_udp_filter);
		actual_filter_sz = spec_filter_size(kern_spec_mask,
						    kern_filter_sz,
						    ib_filter_sz);
@@ -2786,7 +2786,7 @@ int ib_uverbs_kern_spec_to_ib_spec_filter(enum ib_flow_spec_type type,
		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);
		ib_filter_sz = sizeof(struct ib_flow_tunnel_filter);
		actual_filter_sz = spec_filter_size(kern_spec_mask,
						    kern_filter_sz,
						    ib_filter_sz);
@@ -2801,7 +2801,7 @@ int ib_uverbs_kern_spec_to_ib_spec_filter(enum ib_flow_spec_type type,
			return -EINVAL;
		break;
	case IB_FLOW_SPEC_ESP:
		ib_filter_sz = offsetof(struct ib_flow_esp_filter, real_sz);
		ib_filter_sz = sizeof(struct ib_flow_esp_filter);
		actual_filter_sz = spec_filter_size(kern_spec_mask,
						    kern_filter_sz,
						    ib_filter_sz);
@@ -2812,7 +2812,7 @@ int ib_uverbs_kern_spec_to_ib_spec_filter(enum ib_flow_spec_type type,
		memcpy(&ib_spec->esp.mask, kern_spec_mask, actual_filter_sz);
		break;
	case IB_FLOW_SPEC_GRE:
		ib_filter_sz = offsetof(struct ib_flow_gre_filter, real_sz);
		ib_filter_sz = sizeof(struct ib_flow_gre_filter);
		actual_filter_sz = spec_filter_size(kern_spec_mask,
						    kern_filter_sz,
						    ib_filter_sz);
@@ -2823,7 +2823,7 @@ int ib_uverbs_kern_spec_to_ib_spec_filter(enum ib_flow_spec_type type,
		memcpy(&ib_spec->gre.mask, kern_spec_mask, actual_filter_sz);
		break;
	case IB_FLOW_SPEC_MPLS:
		ib_filter_sz = offsetof(struct ib_flow_mpls_filter, real_sz);
		ib_filter_sz = sizeof(struct ib_flow_mpls_filter);
		actual_filter_sz = spec_filter_size(kern_spec_mask,
						    kern_filter_sz,
						    ib_filter_sz);
+45 −33
Original line number Diff line number Diff line
@@ -36,13 +36,15 @@
#include "uverbs.h"

struct bundle_alloc_head {
	struct_group_tagged(bundle_alloc_head_hdr, hdr,
		struct bundle_alloc_head *next;
	);
	u8 data[];
};

struct bundle_priv {
	/* Must be first */
	struct bundle_alloc_head alloc_head;
	struct bundle_alloc_head_hdr alloc_head;
	struct bundle_alloc_head *allocated_mem;
	size_t internal_avail;
	size_t internal_used;
@@ -64,7 +66,7 @@ struct bundle_priv {
	 * Must be last. bundle ends in a flex array which overlaps
	 * internal_buffer.
	 */
	struct uverbs_attr_bundle bundle;
	struct uverbs_attr_bundle_hdr bundle;
	u64 internal_buffer[32];
};

@@ -77,9 +79,10 @@ void uapi_compute_bundle_size(struct uverbs_api_ioctl_method *method_elm,
			      unsigned int num_attrs)
{
	struct bundle_priv *pbundle;
	struct uverbs_attr_bundle *bundle;
	size_t bundle_size =
		offsetof(struct bundle_priv, internal_buffer) +
		sizeof(*pbundle->bundle.attrs) * method_elm->key_bitmap_len +
		sizeof(*bundle->attrs) * method_elm->key_bitmap_len +
		sizeof(*pbundle->uattrs) * num_attrs;

	method_elm->use_stack = bundle_size <= sizeof(*pbundle);
@@ -107,7 +110,7 @@ __malloc void *_uverbs_alloc(struct uverbs_attr_bundle *bundle, size_t size,
			     gfp_t flags)
{
	struct bundle_priv *pbundle =
		container_of(bundle, struct bundle_priv, bundle);
		container_of(&bundle->hdr, struct bundle_priv, bundle);
	size_t new_used;
	void *res;

@@ -149,7 +152,7 @@ static int uverbs_set_output(const struct uverbs_attr_bundle *bundle,
			     const struct uverbs_attr *attr)
{
	struct bundle_priv *pbundle =
		container_of(bundle, struct bundle_priv, bundle);
		container_of(&bundle->hdr, struct bundle_priv, bundle);
	u16 flags;

	flags = pbundle->uattrs[attr->ptr_attr.uattr_idx].flags |
@@ -166,6 +169,8 @@ static int uverbs_process_idrs_array(struct bundle_priv *pbundle,
				     struct ib_uverbs_attr *uattr,
				     u32 attr_bkey)
{
	struct uverbs_attr_bundle *bundle =
		container_of(&pbundle->bundle, struct uverbs_attr_bundle, hdr);
	const struct uverbs_attr_spec *spec = &attr_uapi->spec;
	size_t array_len;
	u32 *idr_vals;
@@ -184,7 +189,7 @@ static int uverbs_process_idrs_array(struct bundle_priv *pbundle,
		return -EINVAL;

	attr->uobjects =
		uverbs_alloc(&pbundle->bundle,
		uverbs_alloc(bundle,
			     array_size(array_len, sizeof(*attr->uobjects)));
	if (IS_ERR(attr->uobjects))
		return PTR_ERR(attr->uobjects);
@@ -209,7 +214,7 @@ static int uverbs_process_idrs_array(struct bundle_priv *pbundle,
	for (i = 0; i != array_len; i++) {
		attr->uobjects[i] = uverbs_get_uobject_from_file(
			spec->u2.objs_arr.obj_type, spec->u2.objs_arr.access,
			idr_vals[i], &pbundle->bundle);
			idr_vals[i], bundle);
		if (IS_ERR(attr->uobjects[i])) {
			ret = PTR_ERR(attr->uobjects[i]);
			break;
@@ -240,7 +245,9 @@ static int uverbs_process_attr(struct bundle_priv *pbundle,
			       struct ib_uverbs_attr *uattr, u32 attr_bkey)
{
	const struct uverbs_attr_spec *spec = &attr_uapi->spec;
	struct uverbs_attr *e = &pbundle->bundle.attrs[attr_bkey];
	struct uverbs_attr_bundle *bundle =
		container_of(&pbundle->bundle, struct uverbs_attr_bundle, hdr);
	struct uverbs_attr *e = &bundle->attrs[attr_bkey];
	const struct uverbs_attr_spec *val_spec = spec;
	struct uverbs_obj_attr *o_attr;

@@ -288,7 +295,7 @@ static int uverbs_process_attr(struct bundle_priv *pbundle,
		if (val_spec->alloc_and_copy && !uverbs_attr_ptr_is_inline(e)) {
			void *p;

			p = uverbs_alloc(&pbundle->bundle, uattr->len);
			p = uverbs_alloc(bundle, uattr->len);
			if (IS_ERR(p))
				return PTR_ERR(p);

@@ -321,7 +328,7 @@ static int uverbs_process_attr(struct bundle_priv *pbundle,
		 */
		o_attr->uobject = uverbs_get_uobject_from_file(
			spec->u.obj.obj_type, spec->u.obj.access,
			uattr->data_s64, &pbundle->bundle);
			uattr->data_s64, bundle);
		if (IS_ERR(o_attr->uobject))
			return PTR_ERR(o_attr->uobject);
		__set_bit(attr_bkey, pbundle->uobj_finalize);
@@ -422,6 +429,8 @@ static int ib_uverbs_run_method(struct bundle_priv *pbundle,
				unsigned int num_attrs)
{
	int (*handler)(struct uverbs_attr_bundle *attrs);
	struct uverbs_attr_bundle *bundle =
		container_of(&pbundle->bundle, struct uverbs_attr_bundle, hdr);
	size_t uattrs_size = array_size(sizeof(*pbundle->uattrs), num_attrs);
	unsigned int destroy_bkey = pbundle->method_elm->destroy_bkey;
	unsigned int i;
@@ -434,7 +443,7 @@ static int ib_uverbs_run_method(struct bundle_priv *pbundle,
	if (!handler)
		return -EIO;

	pbundle->uattrs = uverbs_alloc(&pbundle->bundle, uattrs_size);
	pbundle->uattrs = uverbs_alloc(bundle, uattrs_size);
	if (IS_ERR(pbundle->uattrs))
		return PTR_ERR(pbundle->uattrs);
	if (copy_from_user(pbundle->uattrs, pbundle->user_attrs, uattrs_size))
@@ -453,25 +462,23 @@ static int ib_uverbs_run_method(struct bundle_priv *pbundle,
		return -EINVAL;

	if (pbundle->method_elm->has_udata)
		uverbs_fill_udata(&pbundle->bundle,
				  &pbundle->bundle.driver_udata,
		uverbs_fill_udata(bundle, &pbundle->bundle.driver_udata,
				  UVERBS_ATTR_UHW_IN, UVERBS_ATTR_UHW_OUT);
	else
		pbundle->bundle.driver_udata = (struct ib_udata){};

	if (destroy_bkey != UVERBS_API_ATTR_BKEY_LEN) {
		struct uverbs_obj_attr *destroy_attr =
			&pbundle->bundle.attrs[destroy_bkey].obj_attr;
		struct uverbs_obj_attr *destroy_attr = &bundle->attrs[destroy_bkey].obj_attr;

		ret = uobj_destroy(destroy_attr->uobject, &pbundle->bundle);
		ret = uobj_destroy(destroy_attr->uobject, bundle);
		if (ret)
			return ret;
		__clear_bit(destroy_bkey, pbundle->uobj_finalize);

		ret = handler(&pbundle->bundle);
		ret = handler(bundle);
		uobj_put_destroy(destroy_attr->uobject);
	} else {
		ret = handler(&pbundle->bundle);
		ret = handler(bundle);
	}

	/*
@@ -481,10 +488,10 @@ static int ib_uverbs_run_method(struct bundle_priv *pbundle,
	 */
	if (!ret && pbundle->method_elm->has_udata) {
		const struct uverbs_attr *attr =
			uverbs_attr_get(&pbundle->bundle, UVERBS_ATTR_UHW_OUT);
			uverbs_attr_get(bundle, UVERBS_ATTR_UHW_OUT);

		if (!IS_ERR(attr))
			ret = uverbs_set_output(&pbundle->bundle, attr);
			ret = uverbs_set_output(bundle, attr);
	}

	/*
@@ -501,6 +508,8 @@ static int ib_uverbs_run_method(struct bundle_priv *pbundle,
static void bundle_destroy(struct bundle_priv *pbundle, bool commit)
{
	unsigned int key_bitmap_len = pbundle->method_elm->key_bitmap_len;
	struct uverbs_attr_bundle *bundle =
		container_of(&pbundle->bundle, struct uverbs_attr_bundle, hdr);
	struct bundle_alloc_head *memblock;
	unsigned int i;

@@ -508,20 +517,19 @@ static void bundle_destroy(struct bundle_priv *pbundle, bool commit)
	i = -1;
	while ((i = find_next_bit(pbundle->uobj_finalize, key_bitmap_len,
				  i + 1)) < key_bitmap_len) {
		struct uverbs_attr *attr = &pbundle->bundle.attrs[i];
		struct uverbs_attr *attr = &bundle->attrs[i];

		uverbs_finalize_object(
			attr->obj_attr.uobject,
			attr->obj_attr.attr_elm->spec.u.obj.access,
			test_bit(i, pbundle->uobj_hw_obj_valid),
			commit,
			&pbundle->bundle);
			commit, bundle);
	}

	i = -1;
	while ((i = find_next_bit(pbundle->spec_finalize, key_bitmap_len,
				  i + 1)) < key_bitmap_len) {
		struct uverbs_attr *attr = &pbundle->bundle.attrs[i];
		struct uverbs_attr *attr = &bundle->attrs[i];
		const struct uverbs_api_attr *attr_uapi;
		void __rcu **slot;

@@ -535,7 +543,7 @@ static void bundle_destroy(struct bundle_priv *pbundle, bool commit)

		if (attr_uapi->spec.type == UVERBS_ATTR_TYPE_IDRS_ARRAY) {
			uverbs_free_idrs_array(attr_uapi, &attr->objs_arr_attr,
					       commit, &pbundle->bundle);
					       commit, bundle);
		}
	}

@@ -578,7 +586,8 @@ static int ib_uverbs_cmd_verbs(struct ib_uverbs_file *ufile,
			method_elm->bundle_size -
			offsetof(struct bundle_priv, internal_buffer);
		pbundle->alloc_head.next = NULL;
		pbundle->allocated_mem = &pbundle->alloc_head;
		pbundle->allocated_mem = container_of(&pbundle->alloc_head,
						struct bundle_alloc_head, hdr);
	} else {
		pbundle = &onstack;
		pbundle->internal_avail = sizeof(pbundle->internal_buffer);
@@ -596,7 +605,8 @@ static int ib_uverbs_cmd_verbs(struct ib_uverbs_file *ufile,
	pbundle->user_attrs = user_attrs;

	pbundle->internal_used = ALIGN(pbundle->method_elm->key_bitmap_len *
					       sizeof(*pbundle->bundle.attrs),
					       sizeof(*container_of(&pbundle->bundle,
							struct uverbs_attr_bundle, hdr)->attrs),
					       sizeof(*pbundle->internal_buffer));
	memset(pbundle->bundle.attr_present, 0,
	       sizeof(pbundle->bundle.attr_present));
@@ -700,11 +710,13 @@ void uverbs_fill_udata(struct uverbs_attr_bundle *bundle,
		       unsigned int attr_out)
{
	struct bundle_priv *pbundle =
		container_of(bundle, struct bundle_priv, bundle);
		container_of(&bundle->hdr, struct bundle_priv, bundle);
	struct uverbs_attr_bundle *bundle_aux =
		container_of(&pbundle->bundle, struct uverbs_attr_bundle, hdr);
	const struct uverbs_attr *in =
		uverbs_attr_get(&pbundle->bundle, attr_in);
		uverbs_attr_get(bundle_aux, attr_in);
	const struct uverbs_attr *out =
		uverbs_attr_get(&pbundle->bundle, attr_out);
		uverbs_attr_get(bundle_aux, attr_out);

	if (!IS_ERR(in)) {
		udata->inlen = in->ptr_attr.len;
@@ -829,7 +841,7 @@ void uverbs_finalize_uobj_create(const struct uverbs_attr_bundle *bundle,
				 u16 idx)
{
	struct bundle_priv *pbundle =
		container_of(bundle, struct bundle_priv, bundle);
		container_of(&bundle->hdr, struct bundle_priv, bundle);

	__set_bit(uapi_bkey_attr(uapi_key_attr(idx)),
		  pbundle->uobj_hw_obj_valid);
+0 −2
Original line number Diff line number Diff line
@@ -930,8 +930,6 @@ void c4iw_id_table_free(struct c4iw_id_table *alloc);

typedef int (*c4iw_handler_func)(struct c4iw_dev *dev, struct sk_buff *skb);

int c4iw_ep_redirect(void *ctx, struct dst_entry *old, struct dst_entry *new,
		     struct l2t_entry *l2t);
void c4iw_put_qpid(struct c4iw_rdev *rdev, u32 qpid,
		   struct c4iw_dev_ucontext *uctx);
u32 c4iw_get_resource(struct c4iw_id_table *id_table);
Loading