diff options
| author | Mark Brown <broonie@kernel.org> | 2020-12-28 17:20:00 +0300 | 
|---|---|---|
| committer | Mark Brown <broonie@kernel.org> | 2020-12-28 17:20:00 +0300 | 
| commit | 2ae6f64ce1ce304b502461fdfe0b96c8171ae2cc (patch) | |
| tree | 88e987c447daf2c29e2d4c15e58d1029b0cc78c2 /drivers/infiniband/core | |
| parent | 3b66e4a8e58a85af3212c7117d7a29c9ef6679a2 (diff) | |
| parent | 5c8fe583cce542aa0b84adc939ce85293de36e5e (diff) | |
| download | linux-2ae6f64ce1ce304b502461fdfe0b96c8171ae2cc.tar.xz | |
Merge tag 'v5.11-rc1' into regulator-5.11
Linux 5.11-rc1
Diffstat (limited to 'drivers/infiniband/core')
33 files changed, 633 insertions, 466 deletions
diff --git a/drivers/infiniband/core/cache.c b/drivers/infiniband/core/cache.c index 8017c40dd110..7989b7e1d1c0 100644 --- a/drivers/infiniband/core/cache.c +++ b/drivers/infiniband/core/cache.c @@ -1269,9 +1269,6 @@ ssize_t rdma_query_gid_table(struct ib_device *device,  	unsigned long flags;  	rdma_for_each_port(device, port_num) { -		if (!rdma_ib_or_roce(device, port_num)) -			continue; -  		table = rdma_gid_table(device, port_num);  		read_lock_irqsave(&table->rwlock, flags);  		for (i = 0; i < table->sz; i++) { diff --git a/drivers/infiniband/core/cm.c b/drivers/infiniband/core/cm.c index 5740d1ba3568..98165589c8ab 100644 --- a/drivers/infiniband/core/cm.c +++ b/drivers/infiniband/core/cm.c @@ -859,8 +859,8 @@ static struct cm_id_private *cm_alloc_id_priv(struct ib_device *device,  	atomic_set(&cm_id_priv->work_count, -1);  	refcount_set(&cm_id_priv->refcount, 1); -	ret = xa_alloc_cyclic_irq(&cm.local_id_table, &id, NULL, xa_limit_32b, -				  &cm.local_id_next, GFP_KERNEL); +	ret = xa_alloc_cyclic(&cm.local_id_table, &id, NULL, xa_limit_32b, +			      &cm.local_id_next, GFP_KERNEL);  	if (ret < 0)  		goto error;  	cm_id_priv->id.local_id = (__force __be32)id ^ cm.random_id_operand; @@ -878,8 +878,8 @@ error:   */  static void cm_finalize_id(struct cm_id_private *cm_id_priv)  { -	xa_store_irq(&cm.local_id_table, cm_local_id(cm_id_priv->id.local_id), -		     cm_id_priv, GFP_KERNEL); +	xa_store(&cm.local_id_table, cm_local_id(cm_id_priv->id.local_id), +		 cm_id_priv, GFP_ATOMIC);  }  struct ib_cm_id *ib_create_cm_id(struct ib_device *device, @@ -1169,7 +1169,7 @@ retest:  	spin_unlock(&cm.lock);  	spin_unlock_irq(&cm_id_priv->lock); -	xa_erase_irq(&cm.local_id_table, cm_local_id(cm_id->local_id)); +	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);  	while ((work = cm_dequeue_work(cm_id_priv)) != NULL) @@ -1251,7 +1251,8 @@ out:  EXPORT_SYMBOL(ib_cm_listen);  /** - * Create a new listening ib_cm_id and listen on the given service ID. + * ib_cm_insert_listen - Create a new listening ib_cm_id and listen on + *			 the given service ID.   *   * If there's an existing ID listening on that same device and service ID,   * return it. @@ -1522,6 +1523,7 @@ int ib_send_cm_req(struct ib_cm_id *cm_id,  							    id.local_id);  	if (IS_ERR(cm_id_priv->timewait_info)) {  		ret = PTR_ERR(cm_id_priv->timewait_info); +		cm_id_priv->timewait_info = NULL;  		goto out;  	} @@ -1764,7 +1766,7 @@ static u16 cm_get_bth_pkey(struct cm_work *work)  }  /** - * Convert OPA SGID to IB SGID + * cm_opa_to_ib_sgid - Convert OPA SGID to IB SGID   * ULPs (such as IPoIB) do not understand OPA GIDs and will   * reject them as the local_gid will not match the sgid. Therefore,   * change the pathrec's SGID to an IB SGID. @@ -2114,6 +2116,7 @@ static int cm_req_handler(struct cm_work *work)  							    id.local_id);  	if (IS_ERR(cm_id_priv->timewait_info)) {  		ret = PTR_ERR(cm_id_priv->timewait_info); +		cm_id_priv->timewait_info = NULL;  		goto destroy;  	}  	cm_id_priv->timewait_info->work.remote_id = cm_id_priv->id.remote_id; @@ -4271,8 +4274,8 @@ static ssize_t cm_show_counter(struct kobject *obj, struct attribute *attr,  	group = container_of(obj, struct cm_counter_group, obj);  	cm_attr = container_of(attr, struct cm_counter_attribute, attr); -	return sprintf(buf, "%ld\n", -		       atomic_long_read(&group->counter[cm_attr->index])); +	return sysfs_emit(buf, "%ld\n", +			  atomic_long_read(&group->counter[cm_attr->index]));  }  static const struct sysfs_ops cm_counter_ops = { @@ -4482,7 +4485,7 @@ static int __init ib_cm_init(void)  	cm.remote_id_table = RB_ROOT;  	cm.remote_qp_table = RB_ROOT;  	cm.remote_sidr_table = RB_ROOT; -	xa_init_flags(&cm.local_id_table, XA_FLAGS_ALLOC | XA_FLAGS_LOCK_IRQ); +	xa_init_flags(&cm.local_id_table, XA_FLAGS_ALLOC);  	get_random_bytes(&cm.random_id_operand, sizeof cm.random_id_operand);  	INIT_LIST_HEAD(&cm.timewait_list); diff --git a/drivers/infiniband/core/cma.c b/drivers/infiniband/core/cma.c index a77750b8954d..c51b84b2d2f3 100644 --- a/drivers/infiniband/core/cma.c +++ b/drivers/infiniband/core/cma.c @@ -477,6 +477,10 @@ static void cma_release_dev(struct rdma_id_private *id_priv)  	list_del(&id_priv->list);  	cma_dev_put(id_priv->cma_dev);  	id_priv->cma_dev = NULL; +	if (id_priv->id.route.addr.dev_addr.sgid_attr) { +		rdma_put_gid_attr(id_priv->id.route.addr.dev_addr.sgid_attr); +		id_priv->id.route.addr.dev_addr.sgid_attr = NULL; +	}  	mutex_unlock(&lock);  } @@ -1861,9 +1865,6 @@ static void _destroy_id(struct rdma_id_private *id_priv,  	kfree(id_priv->id.route.path_rec); -	if (id_priv->id.route.addr.dev_addr.sgid_attr) -		rdma_put_gid_attr(id_priv->id.route.addr.dev_addr.sgid_attr); -  	put_net(id_priv->id.route.addr.dev_addr.net);  	rdma_restrack_del(&id_priv->res);  	kfree(id_priv); @@ -2495,8 +2496,9 @@ static int cma_listen_handler(struct rdma_cm_id *id,  	return id_priv->id.event_handler(id, event);  } -static void cma_listen_on_dev(struct rdma_id_private *id_priv, -			      struct cma_device *cma_dev) +static int cma_listen_on_dev(struct rdma_id_private *id_priv, +			     struct cma_device *cma_dev, +			     struct rdma_id_private **to_destroy)  {  	struct rdma_id_private *dev_id_priv;  	struct net *net = id_priv->id.route.addr.dev_addr.net; @@ -2504,21 +2506,21 @@ static void cma_listen_on_dev(struct rdma_id_private *id_priv,  	lockdep_assert_held(&lock); +	*to_destroy = NULL;  	if (cma_family(id_priv) == AF_IB && !rdma_cap_ib_cm(cma_dev->device, 1)) -		return; +		return 0;  	dev_id_priv =  		__rdma_create_id(net, cma_listen_handler, id_priv,  				 id_priv->id.ps, id_priv->id.qp_type, id_priv);  	if (IS_ERR(dev_id_priv)) -		return; +		return PTR_ERR(dev_id_priv);  	dev_id_priv->state = RDMA_CM_ADDR_BOUND;  	memcpy(cma_src_addr(dev_id_priv), cma_src_addr(id_priv),  	       rdma_addr_size(cma_src_addr(id_priv)));  	_cma_attach_to_dev(dev_id_priv, cma_dev); -	list_add_tail(&dev_id_priv->listen_list, &id_priv->listen_list);  	cma_id_get(id_priv);  	dev_id_priv->internal_id = 1;  	dev_id_priv->afonly = id_priv->afonly; @@ -2527,19 +2529,42 @@ static void cma_listen_on_dev(struct rdma_id_private *id_priv,  	ret = rdma_listen(&dev_id_priv->id, id_priv->backlog);  	if (ret) -		dev_warn(&cma_dev->device->dev, -			 "RDMA CMA: cma_listen_on_dev, error %d\n", ret); +		goto err_listen; +	list_add_tail(&dev_id_priv->listen_list, &id_priv->listen_list); +	return 0; +err_listen: +	/* Caller must destroy this after releasing lock */ +	*to_destroy = dev_id_priv; +	dev_warn(&cma_dev->device->dev, "RDMA CMA: %s, error %d\n", __func__, ret); +	return ret;  } -static void cma_listen_on_all(struct rdma_id_private *id_priv) +static int cma_listen_on_all(struct rdma_id_private *id_priv)  { +	struct rdma_id_private *to_destroy;  	struct cma_device *cma_dev; +	int ret;  	mutex_lock(&lock);  	list_add_tail(&id_priv->list, &listen_any_list); -	list_for_each_entry(cma_dev, &dev_list, list) -		cma_listen_on_dev(id_priv, cma_dev); +	list_for_each_entry(cma_dev, &dev_list, list) { +		ret = cma_listen_on_dev(id_priv, cma_dev, &to_destroy); +		if (ret) { +			/* Prevent racing with cma_process_remove() */ +			if (to_destroy) +				list_del_init(&to_destroy->list); +			goto err_listen; +		} +	}  	mutex_unlock(&lock); +	return 0; + +err_listen: +	list_del(&id_priv->list); +	mutex_unlock(&lock); +	if (to_destroy) +		rdma_destroy_id(&to_destroy->id); +	return ret;  }  void rdma_set_service_type(struct rdma_cm_id *id, int tos) @@ -3692,8 +3717,11 @@ int rdma_listen(struct rdma_cm_id *id, int backlog)  			ret = -ENOSYS;  			goto err;  		} -	} else -		cma_listen_on_all(id_priv); +	} else { +		ret = cma_listen_on_all(id_priv); +		if (ret) +			goto err; +	}  	return 0;  err: @@ -4773,69 +4801,6 @@ static struct notifier_block cma_nb = {  	.notifier_call = cma_netdev_callback  }; -static int cma_add_one(struct ib_device *device) -{ -	struct cma_device *cma_dev; -	struct rdma_id_private *id_priv; -	unsigned int i; -	unsigned long supported_gids = 0; -	int ret; - -	cma_dev = kmalloc(sizeof *cma_dev, GFP_KERNEL); -	if (!cma_dev) -		return -ENOMEM; - -	cma_dev->device = device; -	cma_dev->default_gid_type = kcalloc(device->phys_port_cnt, -					    sizeof(*cma_dev->default_gid_type), -					    GFP_KERNEL); -	if (!cma_dev->default_gid_type) { -		ret = -ENOMEM; -		goto free_cma_dev; -	} - -	cma_dev->default_roce_tos = kcalloc(device->phys_port_cnt, -					    sizeof(*cma_dev->default_roce_tos), -					    GFP_KERNEL); -	if (!cma_dev->default_roce_tos) { -		ret = -ENOMEM; -		goto free_gid_type; -	} - -	rdma_for_each_port (device, i) { -		supported_gids = roce_gid_type_mask_support(device, i); -		WARN_ON(!supported_gids); -		if (supported_gids & (1 << CMA_PREFERRED_ROCE_GID_TYPE)) -			cma_dev->default_gid_type[i - rdma_start_port(device)] = -				CMA_PREFERRED_ROCE_GID_TYPE; -		else -			cma_dev->default_gid_type[i - rdma_start_port(device)] = -				find_first_bit(&supported_gids, BITS_PER_LONG); -		cma_dev->default_roce_tos[i - rdma_start_port(device)] = 0; -	} - -	init_completion(&cma_dev->comp); -	refcount_set(&cma_dev->refcount, 1); -	INIT_LIST_HEAD(&cma_dev->id_list); -	ib_set_client_data(device, &cma_client, cma_dev); - -	mutex_lock(&lock); -	list_add_tail(&cma_dev->list, &dev_list); -	list_for_each_entry(id_priv, &listen_any_list, list) -		cma_listen_on_dev(id_priv, cma_dev); -	mutex_unlock(&lock); - -	trace_cm_add_one(device); -	return 0; - -free_gid_type: -	kfree(cma_dev->default_gid_type); - -free_cma_dev: -	kfree(cma_dev); -	return ret; -} -  static void cma_send_device_removal_put(struct rdma_id_private *id_priv)  {  	struct rdma_cm_event event = { .event = RDMA_CM_EVENT_DEVICE_REMOVAL }; @@ -4898,6 +4863,80 @@ static void cma_process_remove(struct cma_device *cma_dev)  	wait_for_completion(&cma_dev->comp);  } +static int cma_add_one(struct ib_device *device) +{ +	struct rdma_id_private *to_destroy; +	struct cma_device *cma_dev; +	struct rdma_id_private *id_priv; +	unsigned int i; +	unsigned long supported_gids = 0; +	int ret; + +	cma_dev = kmalloc(sizeof(*cma_dev), GFP_KERNEL); +	if (!cma_dev) +		return -ENOMEM; + +	cma_dev->device = device; +	cma_dev->default_gid_type = kcalloc(device->phys_port_cnt, +					    sizeof(*cma_dev->default_gid_type), +					    GFP_KERNEL); +	if (!cma_dev->default_gid_type) { +		ret = -ENOMEM; +		goto free_cma_dev; +	} + +	cma_dev->default_roce_tos = kcalloc(device->phys_port_cnt, +					    sizeof(*cma_dev->default_roce_tos), +					    GFP_KERNEL); +	if (!cma_dev->default_roce_tos) { +		ret = -ENOMEM; +		goto free_gid_type; +	} + +	rdma_for_each_port (device, i) { +		supported_gids = roce_gid_type_mask_support(device, i); +		WARN_ON(!supported_gids); +		if (supported_gids & (1 << CMA_PREFERRED_ROCE_GID_TYPE)) +			cma_dev->default_gid_type[i - rdma_start_port(device)] = +				CMA_PREFERRED_ROCE_GID_TYPE; +		else +			cma_dev->default_gid_type[i - rdma_start_port(device)] = +				find_first_bit(&supported_gids, BITS_PER_LONG); +		cma_dev->default_roce_tos[i - rdma_start_port(device)] = 0; +	} + +	init_completion(&cma_dev->comp); +	refcount_set(&cma_dev->refcount, 1); +	INIT_LIST_HEAD(&cma_dev->id_list); +	ib_set_client_data(device, &cma_client, cma_dev); + +	mutex_lock(&lock); +	list_add_tail(&cma_dev->list, &dev_list); +	list_for_each_entry(id_priv, &listen_any_list, list) { +		ret = cma_listen_on_dev(id_priv, cma_dev, &to_destroy); +		if (ret) +			goto free_listen; +	} +	mutex_unlock(&lock); + +	trace_cm_add_one(device); +	return 0; + +free_listen: +	list_del(&cma_dev->list); +	mutex_unlock(&lock); + +	/* cma_process_remove() will delete to_destroy */ +	cma_process_remove(cma_dev); +	kfree(cma_dev->default_roce_tos); +free_gid_type: +	kfree(cma_dev->default_gid_type); + +free_cma_dev: +	kfree(cma_dev); +	return ret; +} +  static void cma_remove_one(struct ib_device *device, void *client_data)  {  	struct cma_device *cma_dev = client_data; diff --git a/drivers/infiniband/core/cma_configfs.c b/drivers/infiniband/core/cma_configfs.c index 7ec4af2ed87a..7f70e5a7de10 100644 --- a/drivers/infiniband/core/cma_configfs.c +++ b/drivers/infiniband/core/cma_configfs.c @@ -115,7 +115,7 @@ static ssize_t default_roce_mode_show(struct config_item *item,  	if (gid_type < 0)  		return gid_type; -	return sprintf(buf, "%s\n", ib_cache_gid_type_str(gid_type)); +	return sysfs_emit(buf, "%s\n", ib_cache_gid_type_str(gid_type));  }  static ssize_t default_roce_mode_store(struct config_item *item, @@ -157,7 +157,7 @@ static ssize_t default_roce_tos_show(struct config_item *item, char *buf)  	tos = cma_get_default_roce_tos(cma_dev, group->port_num);  	cma_configfs_params_put(cma_dev); -	return sprintf(buf, "%u\n", tos); +	return sysfs_emit(buf, "%u\n", tos);  }  static ssize_t default_roce_tos_store(struct config_item *item, diff --git a/drivers/infiniband/core/core_priv.h b/drivers/infiniband/core/core_priv.h index e84b0fedaacb..315f7a297eee 100644 --- a/drivers/infiniband/core/core_priv.h +++ b/drivers/infiniband/core/core_priv.h @@ -318,15 +318,12 @@ struct ib_device *ib_device_get_by_index(const struct net *net, u32 index);  void nldev_init(void);  void nldev_exit(void); -static inline struct ib_qp *_ib_create_qp(struct ib_device *dev, -					  struct ib_pd *pd, -					  struct ib_qp_init_attr *attr, -					  struct ib_udata *udata, -					  struct ib_uqp_object *uobj) +static inline struct ib_qp * +_ib_create_qp(struct ib_device *dev, struct ib_pd *pd, +	      struct ib_qp_init_attr *attr, struct ib_udata *udata, +	      struct ib_uqp_object *uobj, const char *caller)  { -	enum ib_qp_type qp_type = attr->qp_type;  	struct ib_qp *qp; -	bool is_xrc;  	if (!dev->ops.create_qp)  		return ERR_PTR(-EOPNOTSUPP); @@ -347,6 +344,7 @@ static inline struct ib_qp *_ib_create_qp(struct ib_device *dev,  	qp->srq = attr->srq;  	qp->rwq_ind_tbl = attr->rwq_ind_tbl;  	qp->event_handler = attr->event_handler; +	qp->port = attr->port_num;  	atomic_set(&qp->usecnt, 0);  	spin_lock_init(&qp->mr_lock); @@ -354,16 +352,9 @@ static inline struct ib_qp *_ib_create_qp(struct ib_device *dev,  	INIT_LIST_HEAD(&qp->sig_mrs);  	rdma_restrack_new(&qp->res, RDMA_RESTRACK_QP); -	/* -	 * We don't track XRC QPs for now, because they don't have PD -	 * and more importantly they are created internaly by driver, -	 * see mlx5 create_dev_resources() as an example. -	 */ -	is_xrc = qp_type == IB_QPT_XRC_INI || qp_type == IB_QPT_XRC_TGT; -	if ((qp_type < IB_QPT_MAX && !is_xrc) || qp_type == IB_QPT_DRIVER) { -		rdma_restrack_parent_name(&qp->res, &pd->res); -		rdma_restrack_add(&qp->res); -	} +	WARN_ONCE(!udata && !caller, "Missing kernel QP owner"); +	rdma_restrack_set_name(&qp->res, udata ? NULL : caller); +	rdma_restrack_add(&qp->res);  	return qp;  } @@ -411,7 +402,6 @@ void rdma_umap_priv_init(struct rdma_umap_priv *priv,  			 struct vm_area_struct *vma,  			 struct rdma_user_mmap_entry *entry); -void ib_cq_pool_init(struct ib_device *dev); -void ib_cq_pool_destroy(struct ib_device *dev); +void ib_cq_pool_cleanup(struct ib_device *dev);  #endif /* _CORE_PRIV_H */ diff --git a/drivers/infiniband/core/counters.c b/drivers/infiniband/core/counters.c index e4ff0d3328b6..92745522250e 100644 --- a/drivers/infiniband/core/counters.c +++ b/drivers/infiniband/core/counters.c @@ -64,8 +64,40 @@ out:  	return ret;  } -static struct rdma_counter *rdma_counter_alloc(struct ib_device *dev, u8 port, -					       enum rdma_nl_counter_mode mode) +static void auto_mode_init_counter(struct rdma_counter *counter, +				   const struct ib_qp *qp, +				   enum rdma_nl_counter_mask new_mask) +{ +	struct auto_mode_param *param = &counter->mode.param; + +	counter->mode.mode = RDMA_COUNTER_MODE_AUTO; +	counter->mode.mask = new_mask; + +	if (new_mask & RDMA_COUNTER_MASK_QP_TYPE) +		param->qp_type = qp->qp_type; +} + +static int __rdma_counter_bind_qp(struct rdma_counter *counter, +				  struct ib_qp *qp) +{ +	int ret; + +	if (qp->counter) +		return -EINVAL; + +	if (!qp->device->ops.counter_bind_qp) +		return -EOPNOTSUPP; + +	mutex_lock(&counter->lock); +	ret = qp->device->ops.counter_bind_qp(counter, qp); +	mutex_unlock(&counter->lock); + +	return ret; +} + +static struct rdma_counter *alloc_and_bind(struct ib_device *dev, u8 port, +					   struct ib_qp *qp, +					   enum rdma_nl_counter_mode mode)  {  	struct rdma_port_counter *port_counter;  	struct rdma_counter *counter; @@ -88,11 +120,22 @@ static struct rdma_counter *rdma_counter_alloc(struct ib_device *dev, u8 port,  	port_counter = &dev->port_data[port].port_counter;  	mutex_lock(&port_counter->lock); -	if (mode == RDMA_COUNTER_MODE_MANUAL) { +	switch (mode) { +	case RDMA_COUNTER_MODE_MANUAL:  		ret = __counter_set_mode(&port_counter->mode,  					 RDMA_COUNTER_MODE_MANUAL, 0); -		if (ret) +		if (ret) { +			mutex_unlock(&port_counter->lock);  			goto err_mode; +		} +		break; +	case RDMA_COUNTER_MODE_AUTO: +		auto_mode_init_counter(counter, qp, port_counter->mode.mask); +		break; +	default: +		ret = -EOPNOTSUPP; +		mutex_unlock(&port_counter->lock); +		goto err_mode;  	}  	port_counter->num_counters++; @@ -102,10 +145,15 @@ static struct rdma_counter *rdma_counter_alloc(struct ib_device *dev, u8 port,  	kref_init(&counter->kref);  	mutex_init(&counter->lock); +	ret = __rdma_counter_bind_qp(counter, qp); +	if (ret) +		goto err_mode; + +	rdma_restrack_parent_name(&counter->res, &qp->res); +	rdma_restrack_add(&counter->res);  	return counter;  err_mode: -	mutex_unlock(&port_counter->lock);  	kfree(counter->stats);  err_stats:  	rdma_restrack_put(&counter->res); @@ -132,19 +180,6 @@ static void rdma_counter_free(struct rdma_counter *counter)  	kfree(counter);  } -static void auto_mode_init_counter(struct rdma_counter *counter, -				   const struct ib_qp *qp, -				   enum rdma_nl_counter_mask new_mask) -{ -	struct auto_mode_param *param = &counter->mode.param; - -	counter->mode.mode = RDMA_COUNTER_MODE_AUTO; -	counter->mode.mask = new_mask; - -	if (new_mask & RDMA_COUNTER_MASK_QP_TYPE) -		param->qp_type = qp->qp_type; -} -  static bool auto_mode_match(struct ib_qp *qp, struct rdma_counter *counter,  			    enum rdma_nl_counter_mask auto_mask)  { @@ -161,24 +196,6 @@ static bool auto_mode_match(struct ib_qp *qp, struct rdma_counter *counter,  	return match;  } -static int __rdma_counter_bind_qp(struct rdma_counter *counter, -				  struct ib_qp *qp) -{ -	int ret; - -	if (qp->counter) -		return -EINVAL; - -	if (!qp->device->ops.counter_bind_qp) -		return -EOPNOTSUPP; - -	mutex_lock(&counter->lock); -	ret = qp->device->ops.counter_bind_qp(counter, qp); -	mutex_unlock(&counter->lock); - -	return ret; -} -  static int __rdma_counter_unbind_qp(struct ib_qp *qp)  {  	struct rdma_counter *counter = qp->counter; @@ -247,13 +264,6 @@ next:  	return counter;  } -static void rdma_counter_res_add(struct rdma_counter *counter, -				 struct ib_qp *qp) -{ -	rdma_restrack_parent_name(&counter->res, &qp->res); -	rdma_restrack_add(&counter->res); -} -  static void counter_release(struct kref *kref)  {  	struct rdma_counter *counter; @@ -275,7 +285,7 @@ int rdma_counter_bind_qp_auto(struct ib_qp *qp, u8 port)  	struct rdma_counter *counter;  	int ret; -	if (!qp->res.valid || rdma_is_kernel_res(&qp->res)) +	if (!rdma_restrack_is_tracked(&qp->res) || rdma_is_kernel_res(&qp->res))  		return 0;  	if (!rdma_is_port_valid(dev, port)) @@ -293,19 +303,9 @@ int rdma_counter_bind_qp_auto(struct ib_qp *qp, u8 port)  			return ret;  		}  	} else { -		counter = rdma_counter_alloc(dev, port, RDMA_COUNTER_MODE_AUTO); +		counter = alloc_and_bind(dev, port, qp, RDMA_COUNTER_MODE_AUTO);  		if (!counter)  			return -ENOMEM; - -		auto_mode_init_counter(counter, qp, port_counter->mode.mask); - -		ret = __rdma_counter_bind_qp(counter, qp); -		if (ret) { -			rdma_counter_free(counter); -			return ret; -		} - -		rdma_counter_res_add(counter, qp);  	}  	return 0; @@ -419,15 +419,6 @@ err:  	return NULL;  } -static int rdma_counter_bind_qp_manual(struct rdma_counter *counter, -				       struct ib_qp *qp) -{ -	if ((counter->device != qp->device) || (counter->port != qp->port)) -		return -EINVAL; - -	return __rdma_counter_bind_qp(counter, qp); -} -  static struct rdma_counter *rdma_get_counter_by_id(struct ib_device *dev,  						   u32 counter_id)  { @@ -475,7 +466,12 @@ int rdma_counter_bind_qpn(struct ib_device *dev, u8 port,  		goto err_task;  	} -	ret = rdma_counter_bind_qp_manual(counter, qp); +	if ((counter->device != qp->device) || (counter->port != qp->port)) { +		ret = -EINVAL; +		goto err_task; +	} + +	ret = __rdma_counter_bind_qp(counter, qp);  	if (ret)  		goto err_task; @@ -520,26 +516,18 @@ int rdma_counter_bind_qpn_alloc(struct ib_device *dev, u8 port,  		goto err;  	} -	counter = rdma_counter_alloc(dev, port, RDMA_COUNTER_MODE_MANUAL); +	counter = alloc_and_bind(dev, port, qp, RDMA_COUNTER_MODE_MANUAL);  	if (!counter) {  		ret = -ENOMEM;  		goto err;  	} -	ret = rdma_counter_bind_qp_manual(counter, qp); -	if (ret) -		goto err_bind; -  	if (counter_id)  		*counter_id = counter->id; -	rdma_counter_res_add(counter, qp); -  	rdma_restrack_put(&qp->res); -	return ret; +	return 0; -err_bind: -	rdma_counter_free(counter);  err:  	rdma_restrack_put(&qp->res);  	return ret; diff --git a/drivers/infiniband/core/cq.c b/drivers/infiniband/core/cq.c index 12ebacf52958..433b426729d4 100644 --- a/drivers/infiniband/core/cq.c +++ b/drivers/infiniband/core/cq.c @@ -123,7 +123,7 @@ static int __ib_process_cq(struct ib_cq *cq, int budget, struct ib_wc *wcs,  }  /** - * ib_process_direct_cq - process a CQ in caller context + * ib_process_cq_direct - process a CQ in caller context   * @cq:		CQ to process   * @budget:	number of CQEs to poll for   * @@ -197,7 +197,7 @@ static void ib_cq_completion_workqueue(struct ib_cq *cq, void *private)  }  /** - * __ib_alloc_cq        allocate a completion queue + * __ib_alloc_cq - allocate a completion queue   * @dev:		device to allocate the CQ for   * @private:		driver private data, accessible from cq->cq_context   * @nr_cqe:		number of CQEs to allocate @@ -349,16 +349,7 @@ void ib_free_cq(struct ib_cq *cq)  }  EXPORT_SYMBOL(ib_free_cq); -void ib_cq_pool_init(struct ib_device *dev) -{ -	unsigned int i; - -	spin_lock_init(&dev->cq_pools_lock); -	for (i = 0; i < ARRAY_SIZE(dev->cq_pools); i++) -		INIT_LIST_HEAD(&dev->cq_pools[i]); -} - -void ib_cq_pool_destroy(struct ib_device *dev) +void ib_cq_pool_cleanup(struct ib_device *dev)  {  	struct ib_cq *cq, *n;  	unsigned int i; @@ -367,6 +358,7 @@ void ib_cq_pool_destroy(struct ib_device *dev)  		list_for_each_entry_safe(cq, n, &dev->cq_pools[i],  					 pool_entry) {  			WARN_ON(cq->cqe_used); +			list_del(&cq->pool_entry);  			cq->shared = false;  			ib_free_cq(cq);  		} diff --git a/drivers/infiniband/core/device.c b/drivers/infiniband/core/device.c index a3b1fc84cdca..e96f979e6d52 100644 --- a/drivers/infiniband/core/device.c +++ b/drivers/infiniband/core/device.c @@ -284,6 +284,7 @@ static void ib_device_check_mandatory(struct ib_device *device)  		IB_MANDATORY_FUNC(poll_cq),  		IB_MANDATORY_FUNC(req_notify_cq),  		IB_MANDATORY_FUNC(get_dma_mr), +		IB_MANDATORY_FUNC(reg_user_mr),  		IB_MANDATORY_FUNC(dereg_mr),  		IB_MANDATORY_FUNC(get_port_immutable)  	}; @@ -569,6 +570,7 @@ static void rdma_init_coredev(struct ib_core_device *coredev,  struct ib_device *_ib_alloc_device(size_t size)  {  	struct ib_device *device; +	unsigned int i;  	if (WARN_ON(size < sizeof(struct ib_device)))  		return NULL; @@ -600,6 +602,41 @@ struct ib_device *_ib_alloc_device(size_t size)  	init_completion(&device->unreg_completion);  	INIT_WORK(&device->unregistration_work, ib_unregister_work); +	spin_lock_init(&device->cq_pools_lock); +	for (i = 0; i < ARRAY_SIZE(device->cq_pools); i++) +		INIT_LIST_HEAD(&device->cq_pools[i]); + +	device->uverbs_cmd_mask = +		BIT_ULL(IB_USER_VERBS_CMD_ALLOC_MW) | +		BIT_ULL(IB_USER_VERBS_CMD_ALLOC_PD) | +		BIT_ULL(IB_USER_VERBS_CMD_ATTACH_MCAST) | +		BIT_ULL(IB_USER_VERBS_CMD_CLOSE_XRCD) | +		BIT_ULL(IB_USER_VERBS_CMD_CREATE_AH) | +		BIT_ULL(IB_USER_VERBS_CMD_CREATE_COMP_CHANNEL) | +		BIT_ULL(IB_USER_VERBS_CMD_CREATE_CQ) | +		BIT_ULL(IB_USER_VERBS_CMD_CREATE_QP) | +		BIT_ULL(IB_USER_VERBS_CMD_CREATE_SRQ) | +		BIT_ULL(IB_USER_VERBS_CMD_CREATE_XSRQ) | +		BIT_ULL(IB_USER_VERBS_CMD_DEALLOC_MW) | +		BIT_ULL(IB_USER_VERBS_CMD_DEALLOC_PD) | +		BIT_ULL(IB_USER_VERBS_CMD_DEREG_MR) | +		BIT_ULL(IB_USER_VERBS_CMD_DESTROY_AH) | +		BIT_ULL(IB_USER_VERBS_CMD_DESTROY_CQ) | +		BIT_ULL(IB_USER_VERBS_CMD_DESTROY_QP) | +		BIT_ULL(IB_USER_VERBS_CMD_DESTROY_SRQ) | +		BIT_ULL(IB_USER_VERBS_CMD_DETACH_MCAST) | +		BIT_ULL(IB_USER_VERBS_CMD_GET_CONTEXT) | +		BIT_ULL(IB_USER_VERBS_CMD_MODIFY_QP) | +		BIT_ULL(IB_USER_VERBS_CMD_MODIFY_SRQ) | +		BIT_ULL(IB_USER_VERBS_CMD_OPEN_QP) | +		BIT_ULL(IB_USER_VERBS_CMD_OPEN_XRCD) | +		BIT_ULL(IB_USER_VERBS_CMD_QUERY_DEVICE) | +		BIT_ULL(IB_USER_VERBS_CMD_QUERY_PORT) | +		BIT_ULL(IB_USER_VERBS_CMD_QUERY_QP) | +		BIT_ULL(IB_USER_VERBS_CMD_QUERY_SRQ) | +		BIT_ULL(IB_USER_VERBS_CMD_REG_MR) | +		BIT_ULL(IB_USER_VERBS_CMD_REREG_MR) | +		BIT_ULL(IB_USER_VERBS_CMD_RESIZE_CQ);  	return device;  }  EXPORT_SYMBOL(_ib_alloc_device); @@ -1177,25 +1214,6 @@ out:  	return ret;  } -static void setup_dma_device(struct ib_device *device, -			     struct device *dma_device) -{ -	/* -	 * If the caller does not provide a DMA capable device then the IB -	 * device will be used. In this case the caller should fully setup the -	 * ibdev for DMA. This usually means using dma_virt_ops. -	 */ -#ifdef CONFIG_DMA_VIRT_OPS -	if (!dma_device) { -		device->dev.dma_ops = &dma_virt_ops; -		dma_device = &device->dev; -	} -#endif -	WARN_ON(!dma_device); -	device->dma_device = dma_device; -	WARN_ON(!device->dma_device->dma_parms); -} -  /*   * setup_device() allocates memory and sets up data that requires calling the   * device ops, this is the only reason these actions are not done during @@ -1249,7 +1267,7 @@ static void disable_device(struct ib_device *device)  		remove_client_context(device, cid);  	} -	ib_cq_pool_destroy(device); +	ib_cq_pool_cleanup(device);  	/* Pairs with refcount_set in enable_device */  	ib_device_put(device); @@ -1294,8 +1312,6 @@ static int enable_device_and_get(struct ib_device *device)  			goto out;  	} -	ib_cq_pool_init(device); -  	down_read(&clients_rwsem);  	xa_for_each_marked (&clients, index, client, CLIENT_REGISTERED) {  		ret = add_client_context(device, client); @@ -1341,7 +1357,14 @@ int ib_register_device(struct ib_device *device, const char *name,  	if (ret)  		return ret; -	setup_dma_device(device, dma_device); +	/* +	 * If the caller does not provide a DMA capable device then the IB core +	 * will set up ib_sge and scatterlist structures that stash the kernel +	 * virtual address into the address field. +	 */ +	WARN_ON(dma_device && !dma_device->dma_parms); +	device->dma_device = dma_device; +  	ret = setup_device(device);  	if (ret)  		return ret; @@ -1374,9 +1397,6 @@ int ib_register_device(struct ib_device *device, const char *name,  	}  	ret = enable_device_and_get(device); -	dev_set_uevent_suppress(&device->dev, false); -	/* Mark for userspace that device is ready */ -	kobject_uevent(&device->dev.kobj, KOBJ_ADD);  	if (ret) {  		void (*dealloc_fn)(struct ib_device *); @@ -1396,8 +1416,12 @@ int ib_register_device(struct ib_device *device, const char *name,  		ib_device_put(device);  		__ib_unregister_device(device);  		device->ops.dealloc_driver = dealloc_fn; +		dev_set_uevent_suppress(&device->dev, false);  		return ret;  	} +	dev_set_uevent_suppress(&device->dev, false); +	/* Mark for userspace that device is ready */ +	kobject_uevent(&device->dev.kobj, KOBJ_ADD);  	ib_device_put(device);  	return 0; @@ -2576,6 +2600,7 @@ void ib_set_device_ops(struct ib_device *dev, const struct ib_device_ops *ops)  	SET_DEVICE_OP(dev_ops, create_qp);  	SET_DEVICE_OP(dev_ops, create_rwq_ind_table);  	SET_DEVICE_OP(dev_ops, create_srq); +	SET_DEVICE_OP(dev_ops, create_user_ah);  	SET_DEVICE_OP(dev_ops, create_wq);  	SET_DEVICE_OP(dev_ops, dealloc_dm);  	SET_DEVICE_OP(dev_ops, dealloc_driver); @@ -2675,6 +2700,21 @@ void ib_set_device_ops(struct ib_device *dev, const struct ib_device_ops *ops)  }  EXPORT_SYMBOL(ib_set_device_ops); +#ifdef CONFIG_INFINIBAND_VIRT_DMA +int ib_dma_virt_map_sg(struct ib_device *dev, struct scatterlist *sg, int nents) +{ +	struct scatterlist *s; +	int i; + +	for_each_sg(sg, s, nents, i) { +		sg_dma_address(s) = (uintptr_t)sg_virt(s); +		sg_dma_len(s) = s->length; +	} +	return nents; +} +EXPORT_SYMBOL(ib_dma_virt_map_sg); +#endif /* CONFIG_INFINIBAND_VIRT_DMA */ +  static const struct rdma_nl_cbs ibnl_ls_cb_table[RDMA_NL_LS_NUM_OPS] = {  	[RDMA_NL_LS_OP_RESOLVE] = {  		.doit = ib_nl_handle_resolve_resp, diff --git a/drivers/infiniband/core/iwpm_util.h b/drivers/infiniband/core/iwpm_util.h index 1bf87d9fd0bd..eeb8e6010907 100644 --- a/drivers/infiniband/core/iwpm_util.h +++ b/drivers/infiniband/core/iwpm_util.h @@ -141,7 +141,7 @@ int iwpm_wait_complete_req(struct iwpm_nlmsg_request *nlmsg_request);  int iwpm_get_nlmsg_seq(void);  /** - * iwpm_add_reminfo - Add remote address info of the connecting peer + * iwpm_add_remote_info - Add remote address info of the connecting peer   *                    to the remote info hash table   * @reminfo: The remote info to be added   */ diff --git a/drivers/infiniband/core/nldev.c b/drivers/infiniband/core/nldev.c index 12d29d54a081..08366e254b1d 100644 --- a/drivers/infiniband/core/nldev.c +++ b/drivers/infiniband/core/nldev.c @@ -932,7 +932,7 @@ static int nldev_set_doit(struct sk_buff *skb, struct nlmsghdr *nlh,  	if (tb[RDMA_NLDEV_ATTR_DEV_NAME]) {  		char name[IB_DEVICE_NAME_MAX] = {}; -		nla_strlcpy(name, tb[RDMA_NLDEV_ATTR_DEV_NAME], +		nla_strscpy(name, tb[RDMA_NLDEV_ATTR_DEV_NAME],  			    IB_DEVICE_NAME_MAX);  		if (strlen(name) == 0) {  			err = -EINVAL; @@ -1529,13 +1529,13 @@ static int nldev_newlink(struct sk_buff *skb, struct nlmsghdr *nlh,  	    !tb[RDMA_NLDEV_ATTR_LINK_TYPE] || !tb[RDMA_NLDEV_ATTR_NDEV_NAME])  		return -EINVAL; -	nla_strlcpy(ibdev_name, tb[RDMA_NLDEV_ATTR_DEV_NAME], +	nla_strscpy(ibdev_name, tb[RDMA_NLDEV_ATTR_DEV_NAME],  		    sizeof(ibdev_name));  	if (strchr(ibdev_name, '%') || strlen(ibdev_name) == 0)  		return -EINVAL; -	nla_strlcpy(type, tb[RDMA_NLDEV_ATTR_LINK_TYPE], sizeof(type)); -	nla_strlcpy(ndev_name, tb[RDMA_NLDEV_ATTR_NDEV_NAME], +	nla_strscpy(type, tb[RDMA_NLDEV_ATTR_LINK_TYPE], sizeof(type)); +	nla_strscpy(ndev_name, tb[RDMA_NLDEV_ATTR_NDEV_NAME],  		    sizeof(ndev_name));  	ndev = dev_get_by_name(sock_net(skb->sk), ndev_name); @@ -1602,7 +1602,7 @@ static int nldev_get_chardev(struct sk_buff *skb, struct nlmsghdr *nlh,  	if (err || !tb[RDMA_NLDEV_ATTR_CHARDEV_TYPE])  		return -EINVAL; -	nla_strlcpy(client_name, tb[RDMA_NLDEV_ATTR_CHARDEV_TYPE], +	nla_strscpy(client_name, tb[RDMA_NLDEV_ATTR_CHARDEV_TYPE],  		    sizeof(client_name));  	if (tb[RDMA_NLDEV_ATTR_DEV_INDEX]) { diff --git a/drivers/infiniband/core/rdma_core.c b/drivers/infiniband/core/rdma_core.c index ffe11b03724c..75eafd9208aa 100644 --- a/drivers/infiniband/core/rdma_core.c +++ b/drivers/infiniband/core/rdma_core.c @@ -137,15 +137,9 @@ static int uverbs_destroy_uobject(struct ib_uobject *uobj,  	} else if (uobj->object) {  		ret = uobj->uapi_object->type_class->destroy_hw(uobj, reason,  								attrs); -		if (ret) { -			if (ib_is_destroy_retryable(ret, reason, uobj)) -				return ret; - -			/* Nothing to be done, dangle the memory and move on */ -			WARN(true, -			     "ib_uverbs: failed to remove uobject id %d, driver err=%d", -			     uobj->id, ret); -		} +		if (ret) +			/* Nothing to be done, wait till ucontext will clean it */ +			return ret;  		uobj->object = NULL;  	} @@ -543,12 +537,7 @@ static int __must_check destroy_hw_idr_uobject(struct ib_uobject *uobj,  			     struct uverbs_obj_idr_type, type);  	int ret = idr_type->destroy_object(uobj, why, attrs); -	/* -	 * We can only fail gracefully if the user requested to destroy the -	 * object or when a retry may be called upon an error. -	 * In the rest of the cases, just remove whatever you can. -	 */ -	if (ib_is_destroy_retryable(ret, why, uobj)) +	if (ret)  		return ret;  	if (why == RDMA_REMOVE_ABORT) @@ -581,11 +570,8 @@ static int __must_check destroy_hw_fd_uobject(struct ib_uobject *uobj,  {  	const struct uverbs_obj_fd_type *fd_type = container_of(  		uobj->uapi_object->type_attrs, struct uverbs_obj_fd_type, type); -	int ret = fd_type->destroy_object(uobj, why); - -	if (ib_is_destroy_retryable(ret, why, uobj)) -		return ret; +	fd_type->destroy_object(uobj, why);  	return 0;  } @@ -609,6 +595,27 @@ static void alloc_commit_idr_uobject(struct ib_uobject *uobj)  	WARN_ON(old != NULL);  } +static void swap_idr_uobjects(struct ib_uobject *obj_old, +			     struct ib_uobject *obj_new) +{ +	struct ib_uverbs_file *ufile = obj_old->ufile; +	void *old; + +	/* +	 * New must be an object that been allocated but not yet committed, this +	 * moves the pre-committed state to obj_old, new still must be comitted. +	 */ +	old = xa_cmpxchg(&ufile->idr, obj_old->id, obj_old, XA_ZERO_ENTRY, +			 GFP_KERNEL); +	if (WARN_ON(old != obj_old)) +		return; + +	swap(obj_old->id, obj_new->id); + +	old = xa_cmpxchg(&ufile->idr, obj_old->id, NULL, obj_old, GFP_KERNEL); +	WARN_ON(old != NULL); +} +  static void alloc_commit_fd_uobject(struct ib_uobject *uobj)  {  	int fd = uobj->id; @@ -655,6 +662,35 @@ void rdma_alloc_commit_uobject(struct ib_uobject *uobj,  }  /* + * new_uobj will be assigned to the handle currently used by to_uobj, and + * to_uobj will be destroyed. + * + * Upon return the caller must do: + *    rdma_alloc_commit_uobject(new_uobj) + *    uobj_put_destroy(to_uobj) + * + * to_uobj must have a write get but the put mode switches to destroy once + * this is called. + */ +void rdma_assign_uobject(struct ib_uobject *to_uobj, struct ib_uobject *new_uobj, +			struct uverbs_attr_bundle *attrs) +{ +	assert_uverbs_usecnt(new_uobj, UVERBS_LOOKUP_WRITE); + +	if (WARN_ON(to_uobj->uapi_object != new_uobj->uapi_object || +		    !to_uobj->uapi_object->type_class->swap_uobjects)) +		return; + +	to_uobj->uapi_object->type_class->swap_uobjects(to_uobj, new_uobj); + +	/* +	 * If this fails then the uobject is still completely valid (though with +	 * a new ID) and we leak it until context close. +	 */ +	uverbs_destroy_uobject(to_uobj, RDMA_REMOVE_DESTROY, attrs); +} + +/*   * This consumes the kref for uobj. It is up to the caller to unwind the HW   * object and anything else connected to uobj before calling this.   */ @@ -761,6 +797,7 @@ const struct uverbs_obj_type_class uverbs_idr_class = {  	.lookup_put = lookup_put_idr_uobject,  	.destroy_hw = destroy_hw_idr_uobject,  	.remove_handle = remove_handle_idr_uobject, +	.swap_uobjects = swap_idr_uobjects,  };  EXPORT_SYMBOL(uverbs_idr_class); @@ -863,11 +900,18 @@ static int __uverbs_cleanup_ufile(struct ib_uverbs_file *ufile,  		 * racing with a lookup_get.  		 */  		WARN_ON(uverbs_try_lock_object(obj, UVERBS_LOOKUP_WRITE)); +		if (reason == RDMA_REMOVE_DRIVER_FAILURE) +			obj->object = NULL;  		if (!uverbs_destroy_uobject(obj, reason, &attrs))  			ret = 0;  		else  			atomic_set(&obj->usecnt, 0);  	} + +	if (reason == RDMA_REMOVE_DRIVER_FAILURE) { +		WARN_ON(!list_empty(&ufile->uobjects)); +		return 0; +	}  	return ret;  } @@ -889,21 +933,12 @@ void uverbs_destroy_ufile_hw(struct ib_uverbs_file *ufile,  	if (!ufile->ucontext)  		goto done; -	ufile->ucontext->cleanup_retryable = true; -	while (!list_empty(&ufile->uobjects)) -		if (__uverbs_cleanup_ufile(ufile, reason)) { -			/* -			 * No entry was cleaned-up successfully during this -			 * iteration. It is a driver bug to fail destruction. -			 */ -			WARN_ON(!list_empty(&ufile->uobjects)); -			break; -		} - -	ufile->ucontext->cleanup_retryable = false; -	if (!list_empty(&ufile->uobjects)) -		__uverbs_cleanup_ufile(ufile, reason); +	while (!list_empty(&ufile->uobjects) && +	       !__uverbs_cleanup_ufile(ufile, reason)) { +	} +	if (WARN_ON(!list_empty(&ufile->uobjects))) +		__uverbs_cleanup_ufile(ufile, RDMA_REMOVE_DRIVER_FAILURE);  	ufile_destroy_ucontext(ufile, reason);  done: diff --git a/drivers/infiniband/core/restrack.c b/drivers/infiniband/core/restrack.c index 4aeeaaed0f17..e0a41c867002 100644 --- a/drivers/infiniband/core/restrack.c +++ b/drivers/infiniband/core/restrack.c @@ -221,19 +221,29 @@ void rdma_restrack_add(struct rdma_restrack_entry *res)  {  	struct ib_device *dev = res_to_dev(res);  	struct rdma_restrack_root *rt; -	int ret; +	int ret = 0;  	if (!dev)  		return; +	if (res->no_track) +		goto out; +  	rt = &dev->res[res->type];  	if (res->type == RDMA_RESTRACK_QP) {  		/* Special case to ensure that LQPN points to right QP */  		struct ib_qp *qp = container_of(res, struct ib_qp, res); -		ret = xa_insert(&rt->xa, qp->qp_num, res, GFP_KERNEL); -		res->id = ret ? 0 : qp->qp_num; +		WARN_ONCE(qp->qp_num >> 24 || qp->port >> 8, +			  "QP number 0x%0X and port 0x%0X", qp->qp_num, +			  qp->port); +		res->id = qp->qp_num; +		if (qp->qp_type == IB_QPT_SMI || qp->qp_type == IB_QPT_GSI) +			res->id |= qp->port << 24; +		ret = xa_insert(&rt->xa, res->id, res, GFP_KERNEL); +		if (ret) +			res->id = 0;  	} else if (res->type == RDMA_RESTRACK_COUNTER) {  		/* Special case to ensure that cntn points to right counter */  		struct rdma_counter *counter; @@ -246,6 +256,7 @@ void rdma_restrack_add(struct rdma_restrack_entry *res)  				      &rt->next_id, GFP_KERNEL);  	} +out:  	if (!ret)  		res->valid = true;  } @@ -318,6 +329,9 @@ void rdma_restrack_del(struct rdma_restrack_entry *res)  		return;  	} +	if (res->no_track) +		goto out; +  	dev = res_to_dev(res);  	if (WARN_ON(!dev))  		return; @@ -328,8 +342,9 @@ void rdma_restrack_del(struct rdma_restrack_entry *res)  	if (res->type == RDMA_RESTRACK_MR || res->type == RDMA_RESTRACK_QP)  		return;  	WARN_ON(old != res); -	res->valid = false; +out: +	res->valid = false;  	rdma_restrack_put(res);  	wait_for_completion(&res->comp);  } diff --git a/drivers/infiniband/core/rw.c b/drivers/infiniband/core/rw.c index 13f43ab7220b..a96030b784eb 100644 --- a/drivers/infiniband/core/rw.c +++ b/drivers/infiniband/core/rw.c @@ -285,8 +285,11 @@ static void rdma_rw_unmap_sg(struct ib_device *dev, struct scatterlist *sg,  static int rdma_rw_map_sg(struct ib_device *dev, struct scatterlist *sg,  			  u32 sg_cnt, enum dma_data_direction dir)  { -	if (is_pci_p2pdma_page(sg_page(sg))) +	if (is_pci_p2pdma_page(sg_page(sg))) { +		if (WARN_ON_ONCE(ib_uses_virt_dma(dev))) +			return 0;  		return pci_p2pdma_map_sg(dev->dma_device, sg, sg_cnt, dir); +	}  	return ib_dma_map_sg(dev, sg, sg_cnt, dir);  } diff --git a/drivers/infiniband/core/sa_query.c b/drivers/infiniband/core/sa_query.c index 8c930bf1df89..89a831fa1885 100644 --- a/drivers/infiniband/core/sa_query.c +++ b/drivers/infiniband/core/sa_query.c @@ -1435,7 +1435,8 @@ enum opa_pr_supported {  };  /** - * Check if current PR query can be an OPA query. + * opa_pr_query_possible - Check if current PR query can be an OPA query. + *   * Retuns PR_NOT_SUPPORTED if a path record query is not   * possible, PR_OPA_SUPPORTED if an OPA path record query   * is possible and PR_IB_SUPPORTED if an IB path record diff --git a/drivers/infiniband/core/sysfs.c b/drivers/infiniband/core/sysfs.c index 914cddea525d..b8abb30f80df 100644 --- a/drivers/infiniband/core/sysfs.c +++ b/drivers/infiniband/core/sysfs.c @@ -165,9 +165,11 @@ static ssize_t state_show(struct ib_port *p, struct port_attribute *unused,  	if (ret)  		return ret; -	return sprintf(buf, "%d: %s\n", attr.state, -		       attr.state >= 0 && attr.state < ARRAY_SIZE(state_name) ? -		       state_name[attr.state] : "UNKNOWN"); +	return sysfs_emit(buf, "%d: %s\n", attr.state, +			  attr.state >= 0 && +					  attr.state < ARRAY_SIZE(state_name) ? +				  state_name[attr.state] : +				  "UNKNOWN");  }  static ssize_t lid_show(struct ib_port *p, struct port_attribute *unused, @@ -180,7 +182,7 @@ static ssize_t lid_show(struct ib_port *p, struct port_attribute *unused,  	if (ret)  		return ret; -	return sprintf(buf, "0x%x\n", attr.lid); +	return sysfs_emit(buf, "0x%x\n", attr.lid);  }  static ssize_t lid_mask_count_show(struct ib_port *p, @@ -194,7 +196,7 @@ static ssize_t lid_mask_count_show(struct ib_port *p,  	if (ret)  		return ret; -	return sprintf(buf, "%d\n", attr.lmc); +	return sysfs_emit(buf, "%d\n", attr.lmc);  }  static ssize_t sm_lid_show(struct ib_port *p, struct port_attribute *unused, @@ -207,7 +209,7 @@ static ssize_t sm_lid_show(struct ib_port *p, struct port_attribute *unused,  	if (ret)  		return ret; -	return sprintf(buf, "0x%x\n", attr.sm_lid); +	return sysfs_emit(buf, "0x%x\n", attr.sm_lid);  }  static ssize_t sm_sl_show(struct ib_port *p, struct port_attribute *unused, @@ -220,7 +222,7 @@ static ssize_t sm_sl_show(struct ib_port *p, struct port_attribute *unused,  	if (ret)  		return ret; -	return sprintf(buf, "%d\n", attr.sm_sl); +	return sysfs_emit(buf, "%d\n", attr.sm_sl);  }  static ssize_t cap_mask_show(struct ib_port *p, struct port_attribute *unused, @@ -233,7 +235,7 @@ static ssize_t cap_mask_show(struct ib_port *p, struct port_attribute *unused,  	if (ret)  		return ret; -	return sprintf(buf, "0x%08x\n", attr.port_cap_flags); +	return sysfs_emit(buf, "0x%08x\n", attr.port_cap_flags);  }  static ssize_t rate_show(struct ib_port *p, struct port_attribute *unused, @@ -273,6 +275,10 @@ static ssize_t rate_show(struct ib_port *p, struct port_attribute *unused,  		speed = " HDR";  		rate = 500;  		break; +	case IB_SPEED_NDR: +		speed = " NDR"; +		rate = 1000; +		break;  	case IB_SPEED_SDR:  	default:		/* default to SDR for invalid rates */  		speed = " SDR"; @@ -284,9 +290,9 @@ static ssize_t rate_show(struct ib_port *p, struct port_attribute *unused,  	if (rate < 0)  		return -EINVAL; -	return sprintf(buf, "%d%s Gb/sec (%dX%s)\n", -		       rate / 10, rate % 10 ? ".5" : "", -		       ib_width_enum_to_int(attr.active_width), speed); +	return sysfs_emit(buf, "%d%s Gb/sec (%dX%s)\n", rate / 10, +			  rate % 10 ? ".5" : "", +			  ib_width_enum_to_int(attr.active_width), speed);  }  static const char *phys_state_to_str(enum ib_port_phys_state phys_state) @@ -318,21 +324,28 @@ static ssize_t phys_state_show(struct ib_port *p, struct port_attribute *unused,  	if (ret)  		return ret; -	return sprintf(buf, "%d: %s\n", attr.phys_state, -		       phys_state_to_str(attr.phys_state)); +	return sysfs_emit(buf, "%d: %s\n", attr.phys_state, +			  phys_state_to_str(attr.phys_state));  }  static ssize_t link_layer_show(struct ib_port *p, struct port_attribute *unused,  			       char *buf)  { +	const char *output; +  	switch (rdma_port_get_link_layer(p->ibdev, p->port_num)) {  	case IB_LINK_LAYER_INFINIBAND: -		return sprintf(buf, "%s\n", "InfiniBand"); +		output = "InfiniBand"; +		break;  	case IB_LINK_LAYER_ETHERNET: -		return sprintf(buf, "%s\n", "Ethernet"); +		output = "Ethernet"; +		break;  	default: -		return sprintf(buf, "%s\n", "Unknown"); +		output = "Unknown"; +		break;  	} + +	return sysfs_emit(buf, "%s\n", output);  }  static PORT_ATTR_RO(state); @@ -358,27 +371,28 @@ static struct attribute *port_default_attrs[] = {  	NULL  }; -static size_t print_ndev(const struct ib_gid_attr *gid_attr, char *buf) +static ssize_t print_ndev(const struct ib_gid_attr *gid_attr, char *buf)  {  	struct net_device *ndev; -	size_t ret = -EINVAL; +	int ret = -EINVAL;  	rcu_read_lock();  	ndev = rcu_dereference(gid_attr->ndev);  	if (ndev) -		ret = sprintf(buf, "%s\n", ndev->name); +		ret = sysfs_emit(buf, "%s\n", ndev->name);  	rcu_read_unlock();  	return ret;  } -static size_t print_gid_type(const struct ib_gid_attr *gid_attr, char *buf) +static ssize_t print_gid_type(const struct ib_gid_attr *gid_attr, char *buf)  { -	return sprintf(buf, "%s\n", ib_cache_gid_type_str(gid_attr->gid_type)); +	return sysfs_emit(buf, "%s\n", +			  ib_cache_gid_type_str(gid_attr->gid_type));  }  static ssize_t _show_port_gid_attr(  	struct ib_port *p, struct port_attribute *attr, char *buf, -	size_t (*print)(const struct ib_gid_attr *gid_attr, char *buf)) +	ssize_t (*print)(const struct ib_gid_attr *gid_attr, char *buf))  {  	struct port_table_attribute *tab_attr =  		container_of(attr, struct port_table_attribute, attr); @@ -401,7 +415,7 @@ static ssize_t show_port_gid(struct ib_port *p, struct port_attribute *attr,  	struct port_table_attribute *tab_attr =  		container_of(attr, struct port_table_attribute, attr);  	const struct ib_gid_attr *gid_attr; -	ssize_t ret; +	int len;  	gid_attr = rdma_get_gid_attr(p->ibdev, p->port_num, tab_attr->index);  	if (IS_ERR(gid_attr)) { @@ -416,12 +430,12 @@ static ssize_t show_port_gid(struct ib_port *p, struct port_attribute *attr,  		 * space throwing such error on fail to read gid, return zero  		 * GID as before. This maintains backward compatibility.  		 */ -		return sprintf(buf, "%pI6\n", zgid.raw); +		return sysfs_emit(buf, "%pI6\n", zgid.raw);  	} -	ret = sprintf(buf, "%pI6\n", gid_attr->gid.raw); +	len = sysfs_emit(buf, "%pI6\n", gid_attr->gid.raw);  	rdma_put_gid_attr(gid_attr); -	return ret; +	return len;  }  static ssize_t show_port_gid_attr_ndev(struct ib_port *p, @@ -443,13 +457,13 @@ static ssize_t show_port_pkey(struct ib_port *p, struct port_attribute *attr,  	struct port_table_attribute *tab_attr =  		container_of(attr, struct port_table_attribute, attr);  	u16 pkey; -	ssize_t ret; +	int ret;  	ret = ib_query_pkey(p->ibdev, p->port_num, tab_attr->index, &pkey);  	if (ret)  		return ret; -	return sprintf(buf, "0x%04x\n", pkey); +	return sysfs_emit(buf, "0x%04x\n", pkey);  }  #define PORT_PMA_ATTR(_name, _counter, _width, _offset)			\ @@ -521,8 +535,9 @@ static ssize_t show_pma_counter(struct ib_port *p, struct port_attribute *attr,  		container_of(attr, struct port_table_attribute, attr);  	int offset = tab_attr->index & 0xffff;  	int width  = (tab_attr->index >> 16) & 0xff; -	ssize_t ret; +	int ret;  	u8 data[8]; +	int len;  	ret = get_perf_mad(p->ibdev, p->port_num, tab_attr->attr_id, &data,  			40 + offset / 8, sizeof(data)); @@ -531,30 +546,27 @@ static ssize_t show_pma_counter(struct ib_port *p, struct port_attribute *attr,  	switch (width) {  	case 4: -		ret = sprintf(buf, "%u\n", (*data >> -					    (4 - (offset % 8))) & 0xf); +		len = sysfs_emit(buf, "%u\n", +				 (*data >> (4 - (offset % 8))) & 0xf);  		break;  	case 8: -		ret = sprintf(buf, "%u\n", *data); +		len = sysfs_emit(buf, "%u\n", *data);  		break;  	case 16: -		ret = sprintf(buf, "%u\n", -			      be16_to_cpup((__be16 *)data)); +		len = sysfs_emit(buf, "%u\n", be16_to_cpup((__be16 *)data));  		break;  	case 32: -		ret = sprintf(buf, "%u\n", -			      be32_to_cpup((__be32 *)data)); +		len = sysfs_emit(buf, "%u\n", be32_to_cpup((__be32 *)data));  		break;  	case 64: -		ret = sprintf(buf, "%llu\n", -				be64_to_cpup((__be64 *)data)); +		len = sysfs_emit(buf, "%llu\n", be64_to_cpup((__be64 *)data));  		break; -  	default: -		ret = 0; +		len = 0; +		break;  	} -	return ret; +	return len;  }  static PORT_PMA_ATTR(symbol_error		    ,  0, 16,  32); @@ -815,12 +827,12 @@ static int update_hw_stats(struct ib_device *dev, struct rdma_hw_stats *stats,  	return 0;  } -static ssize_t print_hw_stat(struct ib_device *dev, int port_num, -			     struct rdma_hw_stats *stats, int index, char *buf) +static int print_hw_stat(struct ib_device *dev, int port_num, +			 struct rdma_hw_stats *stats, int index, char *buf)  {  	u64 v = rdma_counter_get_hwstat_value(dev, port_num, index); -	return sprintf(buf, "%llu\n", stats->value[index] + v); +	return sysfs_emit(buf, "%llu\n", stats->value[index] + v);  }  static ssize_t show_hw_stats(struct kobject *kobj, struct attribute *attr, @@ -877,7 +889,7 @@ static ssize_t show_stats_lifespan(struct kobject *kobj,  	msecs = jiffies_to_msecs(stats->lifespan);  	mutex_unlock(&stats->lock); -	return sprintf(buf, "%d\n", msecs); +	return sysfs_emit(buf, "%d\n", msecs);  }  static ssize_t set_stats_lifespan(struct kobject *kobj, @@ -1224,21 +1236,34 @@ err_put:  	return ret;  } +static const char *node_type_string(int node_type) +{ +	switch (node_type) { +	case RDMA_NODE_IB_CA: +		return "CA"; +	case RDMA_NODE_IB_SWITCH: +		return "switch"; +	case RDMA_NODE_IB_ROUTER: +		return "router"; +	case RDMA_NODE_RNIC: +		return "RNIC"; +	case RDMA_NODE_USNIC: +		return "usNIC"; +	case RDMA_NODE_USNIC_UDP: +		return "usNIC UDP"; +	case RDMA_NODE_UNSPECIFIED: +		return "unspecified"; +	} +	return "<unknown>"; +} +  static ssize_t node_type_show(struct device *device,  			      struct device_attribute *attr, char *buf)  {  	struct ib_device *dev = rdma_device_to_ibdev(device); -	switch (dev->node_type) { -	case RDMA_NODE_IB_CA:	  return sprintf(buf, "%d: CA\n", dev->node_type); -	case RDMA_NODE_RNIC:	  return sprintf(buf, "%d: RNIC\n", dev->node_type); -	case RDMA_NODE_USNIC:	  return sprintf(buf, "%d: usNIC\n", dev->node_type); -	case RDMA_NODE_USNIC_UDP: return sprintf(buf, "%d: usNIC UDP\n", dev->node_type); -	case RDMA_NODE_UNSPECIFIED: return sprintf(buf, "%d: unspecified\n", dev->node_type); -	case RDMA_NODE_IB_SWITCH: return sprintf(buf, "%d: switch\n", dev->node_type); -	case RDMA_NODE_IB_ROUTER: return sprintf(buf, "%d: router\n", dev->node_type); -	default:		  return sprintf(buf, "%d: <unknown>\n", dev->node_type); -	} +	return sysfs_emit(buf, "%d: %s\n", dev->node_type, +			  node_type_string(dev->node_type));  }  static DEVICE_ATTR_RO(node_type); @@ -1246,12 +1271,13 @@ static ssize_t sys_image_guid_show(struct device *device,  				   struct device_attribute *dev_attr, char *buf)  {  	struct ib_device *dev = rdma_device_to_ibdev(device); +	__be16 *guid = (__be16 *)&dev->attrs.sys_image_guid; -	return sprintf(buf, "%04x:%04x:%04x:%04x\n", -		       be16_to_cpu(((__be16 *) &dev->attrs.sys_image_guid)[0]), -		       be16_to_cpu(((__be16 *) &dev->attrs.sys_image_guid)[1]), -		       be16_to_cpu(((__be16 *) &dev->attrs.sys_image_guid)[2]), -		       be16_to_cpu(((__be16 *) &dev->attrs.sys_image_guid)[3])); +	return sysfs_emit(buf, "%04x:%04x:%04x:%04x\n", +			  be16_to_cpu(guid[0]), +			  be16_to_cpu(guid[1]), +			  be16_to_cpu(guid[2]), +			  be16_to_cpu(guid[3]));  }  static DEVICE_ATTR_RO(sys_image_guid); @@ -1259,12 +1285,13 @@ static ssize_t node_guid_show(struct device *device,  			      struct device_attribute *attr, char *buf)  {  	struct ib_device *dev = rdma_device_to_ibdev(device); +	__be16 *node_guid = (__be16 *)&dev->node_guid; -	return sprintf(buf, "%04x:%04x:%04x:%04x\n", -		       be16_to_cpu(((__be16 *) &dev->node_guid)[0]), -		       be16_to_cpu(((__be16 *) &dev->node_guid)[1]), -		       be16_to_cpu(((__be16 *) &dev->node_guid)[2]), -		       be16_to_cpu(((__be16 *) &dev->node_guid)[3])); +	return sysfs_emit(buf, "%04x:%04x:%04x:%04x\n", +			  be16_to_cpu(node_guid[0]), +			  be16_to_cpu(node_guid[1]), +			  be16_to_cpu(node_guid[2]), +			  be16_to_cpu(node_guid[3]));  }  static DEVICE_ATTR_RO(node_guid); @@ -1273,7 +1300,7 @@ static ssize_t node_desc_show(struct device *device,  {  	struct ib_device *dev = rdma_device_to_ibdev(device); -	return sprintf(buf, "%.64s\n", dev->node_desc); +	return sysfs_emit(buf, "%.64s\n", dev->node_desc);  }  static ssize_t node_desc_store(struct device *device, @@ -1300,10 +1327,11 @@ static ssize_t fw_ver_show(struct device *device, struct device_attribute *attr,  			   char *buf)  {  	struct ib_device *dev = rdma_device_to_ibdev(device); +	char version[IB_FW_VERSION_NAME_MAX] = {}; + +	ib_get_device_fw_str(dev, version); -	ib_get_device_fw_str(dev, buf); -	strlcat(buf, "\n", IB_FW_VERSION_NAME_MAX); -	return strlen(buf); +	return sysfs_emit(buf, "%s\n", version);  }  static DEVICE_ATTR_RO(fw_ver); diff --git a/drivers/infiniband/core/ucma.c b/drivers/infiniband/core/ucma.c index ffe2563ad345..7dab9a27a145 100644 --- a/drivers/infiniband/core/ucma.c +++ b/drivers/infiniband/core/ucma.c @@ -1825,7 +1825,7 @@ static ssize_t show_abi_version(struct device *dev,  				struct device_attribute *attr,  				char *buf)  { -	return sprintf(buf, "%d\n", RDMA_USER_CM_ABI_VERSION); +	return sysfs_emit(buf, "%d\n", RDMA_USER_CM_ABI_VERSION);  }  static DEVICE_ATTR(abi_version, S_IRUGO, show_abi_version, NULL); diff --git a/drivers/infiniband/core/umem.c b/drivers/infiniband/core/umem.c index e9fecbdf391b..7ca4112e3e8f 100644 --- a/drivers/infiniband/core/umem.c +++ b/drivers/infiniband/core/umem.c @@ -84,6 +84,15 @@ unsigned long ib_umem_find_best_pgsz(struct ib_umem *umem,  	dma_addr_t mask;  	int i; +	if (umem->is_odp) { +		unsigned int page_size = BIT(to_ib_umem_odp(umem)->page_shift); + +		/* ODP must always be self consistent. */ +		if (!(pgsz_bitmap & page_size)) +			return 0; +		return page_size; +	} +  	/* rdma_for_each_block() has a bug if the page size is smaller than the  	 * page size used to build the umem. For now prevent smaller page sizes  	 * from being returned. @@ -220,10 +229,10 @@ struct ib_umem *ib_umem_get(struct ib_device *device, unsigned long addr,  		cur_base += ret * PAGE_SIZE;  		npages -= ret; -		sg = __sg_alloc_table_from_pages( -			&umem->sg_head, page_list, ret, 0, ret << PAGE_SHIFT, -			dma_get_max_seg_size(device->dma_device), sg, npages, -			GFP_KERNEL); +		sg = __sg_alloc_table_from_pages(&umem->sg_head, page_list, ret, +				0, ret << PAGE_SHIFT, +				ib_dma_max_seg_size(device), sg, npages, +				GFP_KERNEL);  		umem->sg_nents = umem->sg_head.nents;  		if (IS_ERR(sg)) {  			unpin_user_pages_dirty_lock(page_list, ret, 0); diff --git a/drivers/infiniband/core/user_mad.c b/drivers/infiniband/core/user_mad.c index b0d0b522cc76..19104a675691 100644 --- a/drivers/infiniband/core/user_mad.c +++ b/drivers/infiniband/core/user_mad.c @@ -1191,7 +1191,7 @@ static ssize_t ibdev_show(struct device *dev, struct device_attribute *attr,  	if (!port)  		return -ENODEV; -	return sprintf(buf, "%s\n", dev_name(&port->ib_dev->dev)); +	return sysfs_emit(buf, "%s\n", dev_name(&port->ib_dev->dev));  }  static DEVICE_ATTR_RO(ibdev); @@ -1203,7 +1203,7 @@ static ssize_t port_show(struct device *dev, struct device_attribute *attr,  	if (!port)  		return -ENODEV; -	return sprintf(buf, "%d\n", port->port_num); +	return sysfs_emit(buf, "%d\n", port->port_num);  }  static DEVICE_ATTR_RO(port); @@ -1222,7 +1222,7 @@ static char *umad_devnode(struct device *dev, umode_t *mode)  static ssize_t abi_version_show(struct class *class,  				struct class_attribute *attr, char *buf)  { -	return sprintf(buf, "%d\n", IB_USER_MAD_ABI_VERSION); +	return sysfs_emit(buf, "%d\n", IB_USER_MAD_ABI_VERSION);  }  static CLASS_ATTR_RO(abi_version); diff --git a/drivers/infiniband/core/uverbs_cmd.c b/drivers/infiniband/core/uverbs_cmd.c index 418d133a8fb0..98a5d36813ff 100644 --- a/drivers/infiniband/core/uverbs_cmd.c +++ b/drivers/infiniband/core/uverbs_cmd.c @@ -681,8 +681,7 @@ int ib_uverbs_dealloc_xrcd(struct ib_uobject *uobject, struct ib_xrcd *xrcd,  		return 0;  	ret = ib_dealloc_xrcd_user(xrcd, &attrs->driver_udata); - -	if (ib_is_destroy_retryable(ret, why, uobject)) { +	if (ret) {  		atomic_inc(&xrcd->usecnt);  		return ret;  	} @@ -690,7 +689,7 @@ int ib_uverbs_dealloc_xrcd(struct ib_uobject *uobject, struct ib_xrcd *xrcd,  	if (inode)  		xrcd_table_delete(dev, inode); -	return ret; +	return 0;  }  static int ib_uverbs_reg_mr(struct uverbs_attr_bundle *attrs) @@ -710,29 +709,20 @@ static int ib_uverbs_reg_mr(struct uverbs_attr_bundle *attrs)  	if ((cmd.start & ~PAGE_MASK) != (cmd.hca_va & ~PAGE_MASK))  		return -EINVAL; -	ret = ib_check_mr_access(cmd.access_flags); -	if (ret) -		return ret; -  	uobj = uobj_alloc(UVERBS_OBJECT_MR, attrs, &ib_dev);  	if (IS_ERR(uobj))  		return PTR_ERR(uobj); +	ret = ib_check_mr_access(ib_dev, cmd.access_flags); +	if (ret) +		goto err_free; +  	pd = uobj_get_obj_read(pd, UVERBS_OBJECT_PD, cmd.pd_handle, attrs);  	if (!pd) {  		ret = -EINVAL;  		goto err_free;  	} -	if (cmd.access_flags & IB_ACCESS_ON_DEMAND) { -		if (!(pd->device->attrs.device_cap_flags & -		      IB_DEVICE_ON_DEMAND_PAGING)) { -			pr_debug("ODP support not available\n"); -			ret = -EINVAL; -			goto err_put; -		} -	} -  	mr = pd->device->ops.reg_user_mr(pd, cmd.start, cmd.length, cmd.hca_va,  					 cmd.access_flags,  					 &attrs->driver_udata); @@ -774,23 +764,28 @@ static int ib_uverbs_rereg_mr(struct uverbs_attr_bundle *attrs)  {  	struct ib_uverbs_rereg_mr      cmd;  	struct ib_uverbs_rereg_mr_resp resp; -	struct ib_pd                *pd = NULL;  	struct ib_mr                *mr; -	struct ib_pd		    *old_pd;  	int                          ret;  	struct ib_uobject	    *uobj; +	struct ib_uobject *new_uobj; +	struct ib_device *ib_dev; +	struct ib_pd *orig_pd; +	struct ib_pd *new_pd; +	struct ib_mr *new_mr;  	ret = uverbs_request(attrs, &cmd, sizeof(cmd));  	if (ret)  		return ret; -	if (cmd.flags & ~IB_MR_REREG_SUPPORTED || !cmd.flags) +	if (!cmd.flags)  		return -EINVAL; +	if (cmd.flags & ~IB_MR_REREG_SUPPORTED) +		return -EOPNOTSUPP; +  	if ((cmd.flags & IB_MR_REREG_TRANS) && -	    (!cmd.start || !cmd.hca_va || 0 >= cmd.length || -	     (cmd.start & ~PAGE_MASK) != (cmd.hca_va & ~PAGE_MASK))) -			return -EINVAL; +	    (cmd.start & ~PAGE_MASK) != (cmd.hca_va & ~PAGE_MASK)) +		return -EINVAL;  	uobj = uobj_get_write(UVERBS_OBJECT_MR, cmd.mr_handle, attrs);  	if (IS_ERR(uobj)) @@ -804,36 +799,74 @@ static int ib_uverbs_rereg_mr(struct uverbs_attr_bundle *attrs)  	}  	if (cmd.flags & IB_MR_REREG_ACCESS) { -		ret = ib_check_mr_access(cmd.access_flags); +		ret = ib_check_mr_access(mr->device, cmd.access_flags);  		if (ret)  			goto put_uobjs;  	} +	orig_pd = mr->pd;  	if (cmd.flags & IB_MR_REREG_PD) { -		pd = uobj_get_obj_read(pd, UVERBS_OBJECT_PD, cmd.pd_handle, -				       attrs); -		if (!pd) { +		new_pd = uobj_get_obj_read(pd, UVERBS_OBJECT_PD, cmd.pd_handle, +					   attrs); +		if (!new_pd) {  			ret = -EINVAL;  			goto put_uobjs;  		} +	} else { +		new_pd = mr->pd;  	} -	old_pd = mr->pd; -	ret = mr->device->ops.rereg_user_mr(mr, cmd.flags, cmd.start, -					    cmd.length, cmd.hca_va, -					    cmd.access_flags, pd, -					    &attrs->driver_udata); -	if (ret) +	/* +	 * The driver might create a new HW object as part of the rereg, we need +	 * to have a uobject ready to hold it. +	 */ +	new_uobj = uobj_alloc(UVERBS_OBJECT_MR, attrs, &ib_dev); +	if (IS_ERR(new_uobj)) { +		ret = PTR_ERR(new_uobj);  		goto put_uobj_pd; - -	if (cmd.flags & IB_MR_REREG_PD) { -		atomic_inc(&pd->usecnt); -		mr->pd = pd; -		atomic_dec(&old_pd->usecnt);  	} -	if (cmd.flags & IB_MR_REREG_TRANS) -		mr->iova = cmd.hca_va; +	new_mr = ib_dev->ops.rereg_user_mr(mr, cmd.flags, cmd.start, cmd.length, +					   cmd.hca_va, cmd.access_flags, new_pd, +					   &attrs->driver_udata); +	if (IS_ERR(new_mr)) { +		ret = PTR_ERR(new_mr); +		goto put_new_uobj; +	} +	if (new_mr) { +		new_mr->device = new_pd->device; +		new_mr->pd = new_pd; +		new_mr->type = IB_MR_TYPE_USER; +		new_mr->dm = NULL; +		new_mr->sig_attrs = NULL; +		new_mr->uobject = uobj; +		atomic_inc(&new_pd->usecnt); +		new_mr->iova = cmd.hca_va; +		new_uobj->object = new_mr; + +		rdma_restrack_new(&new_mr->res, RDMA_RESTRACK_MR); +		rdma_restrack_set_name(&new_mr->res, NULL); +		rdma_restrack_add(&new_mr->res); + +		/* +		 * The new uobj for the new HW object is put into the same spot +		 * in the IDR and the old uobj & HW object is deleted. +		 */ +		rdma_assign_uobject(uobj, new_uobj, attrs); +		rdma_alloc_commit_uobject(new_uobj, attrs); +		uobj_put_destroy(uobj); +		new_uobj = NULL; +		uobj = NULL; +		mr = new_mr; +	} else { +		if (cmd.flags & IB_MR_REREG_PD) { +			atomic_dec(&orig_pd->usecnt); +			mr->pd = new_pd; +			atomic_inc(&new_pd->usecnt); +		} +		if (cmd.flags & IB_MR_REREG_TRANS) +			mr->iova = cmd.hca_va; +	}  	memset(&resp, 0, sizeof(resp));  	resp.lkey      = mr->lkey; @@ -841,12 +874,16 @@ static int ib_uverbs_rereg_mr(struct uverbs_attr_bundle *attrs)  	ret = uverbs_response(attrs, &resp, sizeof(resp)); +put_new_uobj: +	if (new_uobj) +		uobj_alloc_abort(new_uobj, attrs);  put_uobj_pd:  	if (cmd.flags & IB_MR_REREG_PD) -		uobj_put_obj_read(pd); +		uobj_put_obj_read(new_pd);  put_uobjs: -	uobj_put_write(uobj); +	if (uobj) +		uobj_put_write(uobj);  	return ret;  } @@ -1401,8 +1438,8 @@ static int create_qp(struct uverbs_attr_bundle *attrs,  	if (cmd->qp_type == IB_QPT_XRC_TGT)  		qp = ib_create_qp(pd, &attr);  	else -		qp = _ib_create_qp(device, pd, &attr, &attrs->driver_udata, -				   obj); +		qp = _ib_create_qp(device, pd, &attr, &attrs->driver_udata, obj, +				   NULL);  	if (IS_ERR(qp)) {  		ret = PTR_ERR(qp); @@ -1906,8 +1943,7 @@ static int ib_uverbs_modify_qp(struct uverbs_attr_bundle *attrs)  	if (ret)  		return ret; -	if (cmd.base.attr_mask & -	    ~((IB_USER_LEGACY_LAST_QP_ATTR_MASK << 1) - 1)) +	if (cmd.base.attr_mask & ~IB_QP_ATTR_STANDARD_BITS)  		return -EOPNOTSUPP;  	return modify_qp(attrs, &cmd); @@ -1929,10 +1965,7 @@ static int ib_uverbs_ex_modify_qp(struct uverbs_attr_bundle *attrs)  	 * Last bit is reserved for extending the attr_mask by  	 * using another field.  	 */ -	BUILD_BUG_ON(IB_USER_LAST_QP_ATTR_MASK == (1ULL << 31)); - -	if (cmd.base.attr_mask & -	    ~((IB_USER_LAST_QP_ATTR_MASK << 1) - 1)) +	if (cmd.base.attr_mask & ~(IB_QP_ATTR_STANDARD_BITS | IB_QP_RATE_LIMIT))  		return -EOPNOTSUPP;  	ret = modify_qp(attrs, &cmd); @@ -3693,13 +3726,13 @@ const struct uapi_definition uverbs_def_write_intf[] = {  				     ib_uverbs_create_ah,  				     UAPI_DEF_WRITE_UDATA_IO(  					     struct ib_uverbs_create_ah, -					     struct ib_uverbs_create_ah_resp), -				     UAPI_DEF_METHOD_NEEDS_FN(create_ah)), +					     struct ib_uverbs_create_ah_resp)),  		DECLARE_UVERBS_WRITE(  			IB_USER_VERBS_CMD_DESTROY_AH,  			ib_uverbs_destroy_ah, -			UAPI_DEF_WRITE_I(struct ib_uverbs_destroy_ah), -			UAPI_DEF_METHOD_NEEDS_FN(destroy_ah))), +			UAPI_DEF_WRITE_I(struct ib_uverbs_destroy_ah)), +		UAPI_DEF_OBJ_NEEDS_FN(create_user_ah), +		UAPI_DEF_OBJ_NEEDS_FN(destroy_ah)),  	DECLARE_UVERBS_OBJECT(  		UVERBS_OBJECT_COMP_CHANNEL, @@ -3753,7 +3786,7 @@ const struct uapi_definition uverbs_def_write_intf[] = {  			IB_USER_VERBS_EX_CMD_MODIFY_CQ,  			ib_uverbs_ex_modify_cq,  			UAPI_DEF_WRITE_I(struct ib_uverbs_ex_modify_cq), -			UAPI_DEF_METHOD_NEEDS_FN(create_cq))), +			UAPI_DEF_METHOD_NEEDS_FN(modify_cq))),  	DECLARE_UVERBS_OBJECT(  		UVERBS_OBJECT_DEVICE, @@ -3999,8 +4032,7 @@ const struct uapi_definition uverbs_def_write_intf[] = {  		DECLARE_UVERBS_WRITE(  			IB_USER_VERBS_CMD_CLOSE_XRCD,  			ib_uverbs_close_xrcd, -			UAPI_DEF_WRITE_I(struct ib_uverbs_close_xrcd), -			UAPI_DEF_METHOD_NEEDS_FN(dealloc_xrcd)), +			UAPI_DEF_WRITE_I(struct ib_uverbs_close_xrcd)),  		DECLARE_UVERBS_WRITE(IB_USER_VERBS_CMD_OPEN_QP,  				     ib_uverbs_open_qp,  				     UAPI_DEF_WRITE_UDATA_IO( @@ -4010,8 +4042,9 @@ const struct uapi_definition uverbs_def_write_intf[] = {  				     ib_uverbs_open_xrcd,  				     UAPI_DEF_WRITE_UDATA_IO(  					     struct ib_uverbs_open_xrcd, -					     struct ib_uverbs_open_xrcd_resp), -				     UAPI_DEF_METHOD_NEEDS_FN(alloc_xrcd))), +					     struct ib_uverbs_open_xrcd_resp)), +		UAPI_DEF_OBJ_NEEDS_FN(alloc_xrcd), +		UAPI_DEF_OBJ_NEEDS_FN(dealloc_xrcd)),  	{},  }; diff --git a/drivers/infiniband/core/uverbs_main.c b/drivers/infiniband/core/uverbs_main.c index 4bb7c642f80c..f173ecd102dc 100644 --- a/drivers/infiniband/core/uverbs_main.c +++ b/drivers/infiniband/core/uverbs_main.c @@ -1046,7 +1046,7 @@ static ssize_t ibdev_show(struct device *device, struct device_attribute *attr,  	srcu_key = srcu_read_lock(&dev->disassociate_srcu);  	ib_dev = srcu_dereference(dev->ib_dev, &dev->disassociate_srcu);  	if (ib_dev) -		ret = sprintf(buf, "%s\n", dev_name(&ib_dev->dev)); +		ret = sysfs_emit(buf, "%s\n", dev_name(&ib_dev->dev));  	srcu_read_unlock(&dev->disassociate_srcu, srcu_key);  	return ret; @@ -1065,7 +1065,7 @@ static ssize_t abi_version_show(struct device *device,  	srcu_key = srcu_read_lock(&dev->disassociate_srcu);  	ib_dev = srcu_dereference(dev->ib_dev, &dev->disassociate_srcu);  	if (ib_dev) -		ret = sprintf(buf, "%u\n", ib_dev->ops.uverbs_abi_ver); +		ret = sysfs_emit(buf, "%u\n", ib_dev->ops.uverbs_abi_ver);  	srcu_read_unlock(&dev->disassociate_srcu, srcu_key);  	return ret; diff --git a/drivers/infiniband/core/uverbs_std_types.c b/drivers/infiniband/core/uverbs_std_types.c index 0658101fca00..13776a66e2e4 100644 --- a/drivers/infiniband/core/uverbs_std_types.c +++ b/drivers/infiniband/core/uverbs_std_types.c @@ -88,7 +88,7 @@ static int uverbs_free_rwq_ind_tbl(struct ib_uobject *uobject,  		return -EBUSY;  	ret = rwq_ind_tbl->device->ops.destroy_rwq_ind_table(rwq_ind_tbl); -	if (ib_is_destroy_retryable(ret, why, uobject)) +	if (ret)  		return ret;  	for (i = 0; i < table_size; i++) @@ -96,7 +96,7 @@ static int uverbs_free_rwq_ind_tbl(struct ib_uobject *uobject,  	kfree(rwq_ind_tbl);  	kfree(ind_tbl); -	return ret; +	return 0;  }  static int uverbs_free_xrcd(struct ib_uobject *uobject, @@ -108,9 +108,8 @@ static int uverbs_free_xrcd(struct ib_uobject *uobject,  		container_of(uobject, struct ib_uxrcd_object, uobject);  	int ret; -	ret = ib_destroy_usecnt(&uxrcd->refcnt, why, uobject); -	if (ret) -		return ret; +	if (atomic_read(&uxrcd->refcnt)) +		return -EBUSY;  	mutex_lock(&attrs->ufile->device->xrcd_tree_mutex);  	ret = ib_uverbs_dealloc_xrcd(uobject, xrcd, why, attrs); @@ -124,11 +123,9 @@ static int uverbs_free_pd(struct ib_uobject *uobject,  			  struct uverbs_attr_bundle *attrs)  {  	struct ib_pd *pd = uobject->object; -	int ret; -	ret = ib_destroy_usecnt(&pd->usecnt, why, uobject); -	if (ret) -		return ret; +	if (atomic_read(&pd->usecnt)) +		return -EBUSY;  	return ib_dealloc_pd_user(pd, &attrs->driver_udata);  } @@ -157,7 +154,7 @@ void ib_uverbs_free_event_queue(struct ib_uverbs_event_queue *event_queue)  	spin_unlock_irq(&event_queue->lock);  } -static int +static void  uverbs_completion_event_file_destroy_uobj(struct ib_uobject *uobj,  					  enum rdma_remove_reason why)  { @@ -166,7 +163,6 @@ uverbs_completion_event_file_destroy_uobj(struct ib_uobject *uobj,  			     uobj);  	ib_uverbs_free_event_queue(&file->ev_queue); -	return 0;  }  int uverbs_destroy_def_handler(struct uverbs_attr_bundle *attrs) diff --git a/drivers/infiniband/core/uverbs_std_types_async_fd.c b/drivers/infiniband/core/uverbs_std_types_async_fd.c index 61899eaf1f91..cc24cfdf7aee 100644 --- a/drivers/infiniband/core/uverbs_std_types_async_fd.c +++ b/drivers/infiniband/core/uverbs_std_types_async_fd.c @@ -19,8 +19,8 @@ static int UVERBS_HANDLER(UVERBS_METHOD_ASYNC_EVENT_ALLOC)(  	return 0;  } -static int uverbs_async_event_destroy_uobj(struct ib_uobject *uobj, -					   enum rdma_remove_reason why) +static void uverbs_async_event_destroy_uobj(struct ib_uobject *uobj, +					    enum rdma_remove_reason why)  {  	struct ib_uverbs_async_event_file *event_file =  		container_of(uobj, struct ib_uverbs_async_event_file, uobj); @@ -30,7 +30,6 @@ static int uverbs_async_event_destroy_uobj(struct ib_uobject *uobj,  	if (why == RDMA_REMOVE_DRIVER_REMOVE)  		ib_uverbs_async_handler(event_file, 0, IB_EVENT_DEVICE_FATAL,  					NULL, NULL); -	return 0;  }  int uverbs_async_event_release(struct inode *inode, struct file *filp) diff --git a/drivers/infiniband/core/uverbs_std_types_counters.c b/drivers/infiniband/core/uverbs_std_types_counters.c index b3c6c066b601..999da9c79866 100644 --- a/drivers/infiniband/core/uverbs_std_types_counters.c +++ b/drivers/infiniband/core/uverbs_std_types_counters.c @@ -42,9 +42,8 @@ static int uverbs_free_counters(struct ib_uobject *uobject,  	struct ib_counters *counters = uobject->object;  	int ret; -	ret = ib_destroy_usecnt(&counters->usecnt, why, uobject); -	if (ret) -		return ret; +	if (atomic_read(&counters->usecnt)) +		return -EBUSY;  	ret = counters->device->ops.destroy_counters(counters);  	if (ret) diff --git a/drivers/infiniband/core/uverbs_std_types_cq.c b/drivers/infiniband/core/uverbs_std_types_cq.c index 8dabd05988b2..370ad7c83f88 100644 --- a/drivers/infiniband/core/uverbs_std_types_cq.c +++ b/drivers/infiniband/core/uverbs_std_types_cq.c @@ -46,7 +46,7 @@ static int uverbs_free_cq(struct ib_uobject *uobject,  	int ret;  	ret = ib_destroy_cq_user(cq, &attrs->driver_udata); -	if (ib_is_destroy_retryable(ret, why, uobject)) +	if (ret)  		return ret;  	ib_uverbs_release_ucq( @@ -55,7 +55,7 @@ static int uverbs_free_cq(struct ib_uobject *uobject,  					ev_queue) :  			   NULL,  		ucq); -	return ret; +	return 0;  }  static int UVERBS_HANDLER(UVERBS_METHOD_CQ_CREATE)( diff --git a/drivers/infiniband/core/uverbs_std_types_device.c b/drivers/infiniband/core/uverbs_std_types_device.c index 302f898c5833..9ec6971056fa 100644 --- a/drivers/infiniband/core/uverbs_std_types_device.c +++ b/drivers/infiniband/core/uverbs_std_types_device.c @@ -317,8 +317,7 @@ static int UVERBS_HANDLER(UVERBS_METHOD_QUERY_GID_TABLE)(  	struct ib_device *ib_dev;  	size_t user_entry_size;  	ssize_t num_entries; -	size_t max_entries; -	size_t num_bytes; +	int max_entries;  	u32 flags;  	int ret; @@ -336,19 +335,16 @@ static int UVERBS_HANDLER(UVERBS_METHOD_QUERY_GID_TABLE)(  		attrs, UVERBS_ATTR_QUERY_GID_TABLE_RESP_ENTRIES,  		user_entry_size);  	if (max_entries <= 0) -		return -EINVAL; +		return max_entries ?: -EINVAL;  	ucontext = ib_uverbs_get_ucontext(attrs);  	if (IS_ERR(ucontext))  		return PTR_ERR(ucontext);  	ib_dev = ucontext->device; -	if (check_mul_overflow(max_entries, sizeof(*entries), &num_bytes)) -		return -EINVAL; - -	entries = uverbs_zalloc(attrs, num_bytes); -	if (!entries) -		return -ENOMEM; +	entries = uverbs_kcalloc(attrs, max_entries, sizeof(*entries)); +	if (IS_ERR(entries)) +		return PTR_ERR(entries);  	num_entries = rdma_query_gid_table(ib_dev, entries, max_entries);  	if (num_entries < 0) diff --git a/drivers/infiniband/core/uverbs_std_types_dm.c b/drivers/infiniband/core/uverbs_std_types_dm.c index d5a1de33c2c9..98c522cf86d6 100644 --- a/drivers/infiniband/core/uverbs_std_types_dm.c +++ b/drivers/infiniband/core/uverbs_std_types_dm.c @@ -39,11 +39,9 @@ static int uverbs_free_dm(struct ib_uobject *uobject,  			  struct uverbs_attr_bundle *attrs)  {  	struct ib_dm *dm = uobject->object; -	int ret; -	ret = ib_destroy_usecnt(&dm->usecnt, why, uobject); -	if (ret) -		return ret; +	if (atomic_read(&dm->usecnt)) +		return -EBUSY;  	return dm->device->ops.dealloc_dm(dm, attrs);  } diff --git a/drivers/infiniband/core/uverbs_std_types_flow_action.c b/drivers/infiniband/core/uverbs_std_types_flow_action.c index 459cf165b231..d42ed7ff223e 100644 --- a/drivers/infiniband/core/uverbs_std_types_flow_action.c +++ b/drivers/infiniband/core/uverbs_std_types_flow_action.c @@ -39,11 +39,9 @@ static int uverbs_free_flow_action(struct ib_uobject *uobject,  				   struct uverbs_attr_bundle *attrs)  {  	struct ib_flow_action *action = uobject->object; -	int ret; -	ret = ib_destroy_usecnt(&action->usecnt, why, uobject); -	if (ret) -		return ret; +	if (atomic_read(&action->usecnt)) +		return -EBUSY;  	return action->device->ops.destroy_flow_action(action);  } diff --git a/drivers/infiniband/core/uverbs_std_types_mr.c b/drivers/infiniband/core/uverbs_std_types_mr.c index 9b22bb553e8b..dd4e76b26c74 100644 --- a/drivers/infiniband/core/uverbs_std_types_mr.c +++ b/drivers/infiniband/core/uverbs_std_types_mr.c @@ -33,6 +33,7 @@  #include "rdma_core.h"  #include "uverbs.h"  #include <rdma/uverbs_std_types.h> +#include "restrack.h"  static int uverbs_free_mr(struct ib_uobject *uobject,  			  enum rdma_remove_reason why, @@ -114,7 +115,7 @@ static int UVERBS_HANDLER(UVERBS_METHOD_DM_MR_REG)(  	if (!(attr.access_flags & IB_ZERO_BASED))  		return -EINVAL; -	ret = ib_check_mr_access(attr.access_flags); +	ret = ib_check_mr_access(ib_dev, attr.access_flags);  	if (ret)  		return ret; @@ -134,6 +135,9 @@ static int UVERBS_HANDLER(UVERBS_METHOD_DM_MR_REG)(  	atomic_inc(&pd->usecnt);  	atomic_inc(&dm->usecnt); +	rdma_restrack_new(&mr->res, RDMA_RESTRACK_MR); +	rdma_restrack_set_name(&mr->res, NULL); +	rdma_restrack_add(&mr->res);  	uobj->object = mr;  	uverbs_finalize_uobj_create(attrs, UVERBS_ATTR_REG_DM_MR_HANDLE); diff --git a/drivers/infiniband/core/uverbs_std_types_qp.c b/drivers/infiniband/core/uverbs_std_types_qp.c index 3bf8dcdfe7eb..c00cfb5ed387 100644 --- a/drivers/infiniband/core/uverbs_std_types_qp.c +++ b/drivers/infiniband/core/uverbs_std_types_qp.c @@ -32,14 +32,14 @@ static int uverbs_free_qp(struct ib_uobject *uobject,  	}  	ret = ib_destroy_qp_user(qp, &attrs->driver_udata); -	if (ib_is_destroy_retryable(ret, why, uobject)) +	if (ret)  		return ret;  	if (uqp->uxrcd)  		atomic_dec(&uqp->uxrcd->refcnt);  	ib_uverbs_release_uevent(&uqp->uevent); -	return ret; +	return 0;  }  static int check_creation_flags(enum ib_qp_type qp_type, @@ -251,8 +251,8 @@ static int UVERBS_HANDLER(UVERBS_METHOD_QP_CREATE)(  	if (attr.qp_type == IB_QPT_XRC_TGT)  		qp = ib_create_qp(pd, &attr);  	else -		qp = _ib_create_qp(device, pd, &attr, &attrs->driver_udata, -				   obj); +		qp = _ib_create_qp(device, pd, &attr, &attrs->driver_udata, obj, +				   NULL);  	if (IS_ERR(qp)) {  		ret = PTR_ERR(qp); diff --git a/drivers/infiniband/core/uverbs_std_types_srq.c b/drivers/infiniband/core/uverbs_std_types_srq.c index c0ecbba26bf4..e5513f828bdc 100644 --- a/drivers/infiniband/core/uverbs_std_types_srq.c +++ b/drivers/infiniband/core/uverbs_std_types_srq.c @@ -18,7 +18,7 @@ static int uverbs_free_srq(struct ib_uobject *uobject,  	int ret;  	ret = ib_destroy_srq_user(srq, &attrs->driver_udata); -	if (ib_is_destroy_retryable(ret, why, uobject)) +	if (ret)  		return ret;  	if (srq_type == IB_SRQT_XRC) { @@ -30,7 +30,7 @@ static int uverbs_free_srq(struct ib_uobject *uobject,  	}  	ib_uverbs_release_uevent(uevent); -	return ret; +	return 0;  }  static int UVERBS_HANDLER(UVERBS_METHOD_SRQ_CREATE)( diff --git a/drivers/infiniband/core/uverbs_std_types_wq.c b/drivers/infiniband/core/uverbs_std_types_wq.c index f2e6a625724a..7ded8339346f 100644 --- a/drivers/infiniband/core/uverbs_std_types_wq.c +++ b/drivers/infiniband/core/uverbs_std_types_wq.c @@ -17,11 +17,11 @@ static int uverbs_free_wq(struct ib_uobject *uobject,  	int ret;  	ret = ib_destroy_wq_user(wq, &attrs->driver_udata); -	if (ib_is_destroy_retryable(ret, why, uobject)) +	if (ret)  		return ret;  	ib_uverbs_release_uevent(&uwq->uevent); -	return ret; +	return 0;  }  static int UVERBS_HANDLER(UVERBS_METHOD_WQ_CREATE)( diff --git a/drivers/infiniband/core/uverbs_uapi.c b/drivers/infiniband/core/uverbs_uapi.c index 5addc8fae3f3..62f5bcb712cf 100644 --- a/drivers/infiniband/core/uverbs_uapi.c +++ b/drivers/infiniband/core/uverbs_uapi.c @@ -79,10 +79,7 @@ static int uapi_create_write(struct uverbs_api *uapi,  	method_elm->is_ex = def->write.is_ex;  	method_elm->handler = def->func_write; -	if (def->write.is_ex) -		method_elm->disabled = !(ibdev->uverbs_ex_cmd_mask & -					 BIT_ULL(def->write.command_num)); -	else +	if (!def->write.is_ex)  		method_elm->disabled = !(ibdev->uverbs_cmd_mask &  					 BIT_ULL(def->write.command_num)); diff --git a/drivers/infiniband/core/verbs.c b/drivers/infiniband/core/verbs.c index 740f8454b6b4..9137a25bb521 100644 --- a/drivers/infiniband/core/verbs.c +++ b/drivers/infiniband/core/verbs.c @@ -244,7 +244,7 @@ EXPORT_SYMBOL(rdma_port_get_link_layer);  /* Protection domains */  /** - * ib_alloc_pd - Allocates an unused protection domain. + * __ib_alloc_pd - Allocates an unused protection domain.   * @device: The device on which to allocate the protection domain.   * @flags: protection domain flags   * @caller: caller's build-time module name @@ -516,7 +516,7 @@ static struct ib_ah *_rdma_create_ah(struct ib_pd *pd,  	might_sleep_if(flags & RDMA_CREATE_AH_SLEEPABLE); -	if (!device->ops.create_ah) +	if (!udata && !device->ops.create_ah)  		return ERR_PTR(-EOPNOTSUPP);  	ah = rdma_zalloc_drv_obj_gfp( @@ -533,7 +533,10 @@ static struct ib_ah *_rdma_create_ah(struct ib_pd *pd,  	init_attr.flags = flags;  	init_attr.xmit_slave = xmit_slave; -	ret = device->ops.create_ah(ah, &init_attr, udata); +	if (udata) +		ret = device->ops.create_user_ah(ah, &init_attr, udata); +	else +		ret = device->ops.create_ah(ah, &init_attr, NULL);  	if (ret) {  		kfree(ah);  		return ERR_PTR(ret); @@ -1188,17 +1191,19 @@ static struct ib_qp *create_xrc_qp_user(struct ib_qp *qp,  }  /** - * ib_create_qp - Creates a kernel QP associated with the specified protection + * ib_create_named_qp - Creates a kernel QP associated with the specified protection   *   domain.   * @pd: The protection domain associated with the QP.   * @qp_init_attr: A list of initial attributes required to create the   *   QP.  If QP creation succeeds, then the attributes are updated to   *   the actual capabilities of the created QP. + * @caller: caller's build-time module name   *   * NOTE: for user qp use ib_create_qp_user with valid udata!   */ -struct ib_qp *ib_create_qp(struct ib_pd *pd, -			   struct ib_qp_init_attr *qp_init_attr) +struct ib_qp *ib_create_named_qp(struct ib_pd *pd, +				 struct ib_qp_init_attr *qp_init_attr, +				 const char *caller)  {  	struct ib_device *device = pd ? pd->device : qp_init_attr->xrcd->device;  	struct ib_qp *qp; @@ -1223,7 +1228,7 @@ struct ib_qp *ib_create_qp(struct ib_pd *pd,  	if (qp_init_attr->cap.max_rdma_ctxs)  		rdma_rw_init_qp(device, qp_init_attr); -	qp = _ib_create_qp(device, pd, qp_init_attr, NULL, NULL); +	qp = _ib_create_qp(device, pd, qp_init_attr, NULL, NULL, caller);  	if (IS_ERR(qp))  		return qp; @@ -1289,7 +1294,7 @@ err:  	return ERR_PTR(ret);  } -EXPORT_SYMBOL(ib_create_qp); +EXPORT_SYMBOL(ib_create_named_qp);  static const struct {  	int			valid; @@ -1662,7 +1667,7 @@ static bool is_qp_type_connected(const struct ib_qp *qp)  		qp->qp_type == IB_QPT_XRC_TGT);  } -/** +/*   * IB core internal function to perform QP attributes modification.   */  static int _ib_modify_qp(struct ib_qp *qp, struct ib_qp_attr *attr, @@ -1698,8 +1703,10 @@ static int _ib_modify_qp(struct ib_qp *qp, struct ib_qp_attr *attr,  			slave = rdma_lag_get_ah_roce_slave(qp->device,  							   &attr->ah_attr,  							   GFP_KERNEL); -			if (IS_ERR(slave)) +			if (IS_ERR(slave)) { +				ret = PTR_ERR(slave);  				goto out_av; +			}  			attr->xmit_slave = slave;  		}  	}  | 
