Merge branch 'uverbs_dev_cleanups' into rdma.git for-next
For dependencies, branch based on rdma.git 'for-rc' of https://git.kernel.org/pub/scm/linux/kernel/git/rdma/rdma.git/ Pull 'uverbs_dev_cleanups' from Leon Romanovsky: ==================== Reuse the char device code interfaces to simplify ib_uverbs_device creation and destruction. As part of this series, we are sending fix to cleanup path, which was discovered during internal review, The fix definitely can go to -rc, but it means that this series will be dependent on rdma-rc. ==================== * branch 'uverbs_dev_cleanups': RDMA/uverbs: Use device.groups to initialize device attributes RDMA/uverbs: Use cdev_device_add() instead of cdev_add() RDMA/core: Depend on device_add() to add device attributes RDMA/uverbs: Fix error cleanup path of ib_uverbs_add_one() Resolved conflict in ib_device_unregister_sysfs() Signed-off-by: Jason Gunthorpe <jgg@mellanox.com>
This commit is contained in:
@@ -882,6 +882,8 @@ static int __uverbs_cleanup_ufile(struct ib_uverbs_file *ufile,
|
||||
WARN_ON(uverbs_try_lock_object(obj, UVERBS_LOOKUP_WRITE));
|
||||
if (!uverbs_destroy_uobject(obj, reason))
|
||||
ret = 0;
|
||||
else
|
||||
atomic_set(&obj->usecnt, 0);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
@@ -1183,7 +1183,7 @@ err_put:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static ssize_t show_node_type(struct device *device,
|
||||
static ssize_t node_type_show(struct device *device,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct ib_device *dev = container_of(device, struct ib_device, dev);
|
||||
@@ -1198,8 +1198,9 @@ static ssize_t show_node_type(struct device *device,
|
||||
default: return sprintf(buf, "%d: <unknown>\n", dev->node_type);
|
||||
}
|
||||
}
|
||||
static DEVICE_ATTR_RO(node_type);
|
||||
|
||||
static ssize_t show_sys_image_guid(struct device *device,
|
||||
static ssize_t sys_image_guid_show(struct device *device,
|
||||
struct device_attribute *dev_attr, char *buf)
|
||||
{
|
||||
struct ib_device *dev = container_of(device, struct ib_device, dev);
|
||||
@@ -1210,8 +1211,9 @@ static ssize_t show_sys_image_guid(struct device *device,
|
||||
be16_to_cpu(((__be16 *) &dev->attrs.sys_image_guid)[2]),
|
||||
be16_to_cpu(((__be16 *) &dev->attrs.sys_image_guid)[3]));
|
||||
}
|
||||
static DEVICE_ATTR_RO(sys_image_guid);
|
||||
|
||||
static ssize_t show_node_guid(struct device *device,
|
||||
static ssize_t node_guid_show(struct device *device,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct ib_device *dev = container_of(device, struct ib_device, dev);
|
||||
@@ -1222,8 +1224,9 @@ static ssize_t show_node_guid(struct device *device,
|
||||
be16_to_cpu(((__be16 *) &dev->node_guid)[2]),
|
||||
be16_to_cpu(((__be16 *) &dev->node_guid)[3]));
|
||||
}
|
||||
static DEVICE_ATTR_RO(node_guid);
|
||||
|
||||
static ssize_t show_node_desc(struct device *device,
|
||||
static ssize_t node_desc_show(struct device *device,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct ib_device *dev = container_of(device, struct ib_device, dev);
|
||||
@@ -1231,9 +1234,9 @@ static ssize_t show_node_desc(struct device *device,
|
||||
return sprintf(buf, "%.64s\n", dev->node_desc);
|
||||
}
|
||||
|
||||
static ssize_t set_node_desc(struct device *device,
|
||||
struct device_attribute *attr,
|
||||
const char *buf, size_t count)
|
||||
static ssize_t node_desc_store(struct device *device,
|
||||
struct device_attribute *attr,
|
||||
const char *buf, size_t count)
|
||||
{
|
||||
struct ib_device *dev = container_of(device, struct ib_device, dev);
|
||||
struct ib_device_modify desc = {};
|
||||
@@ -1249,8 +1252,9 @@ static ssize_t set_node_desc(struct device *device,
|
||||
|
||||
return count;
|
||||
}
|
||||
static DEVICE_ATTR_RW(node_desc);
|
||||
|
||||
static ssize_t show_fw_ver(struct device *device, struct device_attribute *attr,
|
||||
static ssize_t fw_ver_show(struct device *device, struct device_attribute *attr,
|
||||
char *buf)
|
||||
{
|
||||
struct ib_device *dev = container_of(device, struct ib_device, dev);
|
||||
@@ -1259,19 +1263,19 @@ static ssize_t show_fw_ver(struct device *device, struct device_attribute *attr,
|
||||
strlcat(buf, "\n", IB_FW_VERSION_NAME_MAX);
|
||||
return strlen(buf);
|
||||
}
|
||||
static DEVICE_ATTR_RO(fw_ver);
|
||||
|
||||
static DEVICE_ATTR(node_type, S_IRUGO, show_node_type, NULL);
|
||||
static DEVICE_ATTR(sys_image_guid, S_IRUGO, show_sys_image_guid, NULL);
|
||||
static DEVICE_ATTR(node_guid, S_IRUGO, show_node_guid, NULL);
|
||||
static DEVICE_ATTR(node_desc, S_IRUGO | S_IWUSR, show_node_desc, set_node_desc);
|
||||
static DEVICE_ATTR(fw_ver, S_IRUGO, show_fw_ver, NULL);
|
||||
static struct attribute *ib_dev_attrs[] = {
|
||||
&dev_attr_node_type.attr,
|
||||
&dev_attr_node_guid.attr,
|
||||
&dev_attr_sys_image_guid.attr,
|
||||
&dev_attr_fw_ver.attr,
|
||||
&dev_attr_node_desc.attr,
|
||||
NULL,
|
||||
};
|
||||
|
||||
static struct device_attribute *ib_class_attributes[] = {
|
||||
&dev_attr_node_type,
|
||||
&dev_attr_sys_image_guid,
|
||||
&dev_attr_node_guid,
|
||||
&dev_attr_node_desc,
|
||||
&dev_attr_fw_ver,
|
||||
static const struct attribute_group dev_attr_group = {
|
||||
.attrs = ib_dev_attrs,
|
||||
};
|
||||
|
||||
static void free_port_list_attributes(struct ib_device *device)
|
||||
@@ -1311,16 +1315,13 @@ int ib_device_register_sysfs(struct ib_device *device,
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
device->groups[0] = &dev_attr_group;
|
||||
class_dev->groups = device->groups;
|
||||
|
||||
ret = device_add(class_dev);
|
||||
if (ret)
|
||||
goto err;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(ib_class_attributes); ++i) {
|
||||
ret = device_create_file(class_dev, ib_class_attributes[i]);
|
||||
if (ret)
|
||||
goto err_unregister;
|
||||
}
|
||||
|
||||
device->ports_parent = kobject_create_and_add("ports",
|
||||
&class_dev->kobj);
|
||||
if (!device->ports_parent) {
|
||||
@@ -1347,18 +1348,13 @@ int ib_device_register_sysfs(struct ib_device *device,
|
||||
|
||||
err_put:
|
||||
free_port_list_attributes(device);
|
||||
|
||||
err_unregister:
|
||||
device_del(class_dev);
|
||||
|
||||
err:
|
||||
return ret;
|
||||
}
|
||||
|
||||
void ib_device_unregister_sysfs(struct ib_device *device)
|
||||
{
|
||||
int i;
|
||||
|
||||
/* Hold device until ib_dealloc_device() */
|
||||
get_device(&device->dev);
|
||||
|
||||
@@ -1369,8 +1365,5 @@ void ib_device_unregister_sysfs(struct ib_device *device)
|
||||
free_hsag(&device->dev.kobj, device->hw_stats_ag);
|
||||
}
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(ib_class_attributes); ++i)
|
||||
device_remove_file(&device->dev, ib_class_attributes[i]);
|
||||
|
||||
device_unregister(&device->dev);
|
||||
}
|
||||
|
@@ -124,6 +124,8 @@ static DEFINE_MUTEX(mut);
|
||||
static DEFINE_IDR(ctx_idr);
|
||||
static DEFINE_IDR(multicast_idr);
|
||||
|
||||
static const struct file_operations ucma_fops;
|
||||
|
||||
static inline struct ucma_context *_ucma_find_context(int id,
|
||||
struct ucma_file *file)
|
||||
{
|
||||
@@ -1581,6 +1583,10 @@ static ssize_t ucma_migrate_id(struct ucma_file *new_file,
|
||||
f = fdget(cmd.fd);
|
||||
if (!f.file)
|
||||
return -ENOENT;
|
||||
if (f.file->f_op != &ucma_fops) {
|
||||
ret = -EINVAL;
|
||||
goto file_put;
|
||||
}
|
||||
|
||||
/* Validate current fd and prevent destruction of id. */
|
||||
ctx = ucma_get_ctx(f.file->private_data, cmd.id);
|
||||
|
@@ -100,13 +100,14 @@ struct ib_uverbs_device {
|
||||
atomic_t refcount;
|
||||
int num_comp_vectors;
|
||||
struct completion comp;
|
||||
struct device *dev;
|
||||
struct device dev;
|
||||
/* First group for device attributes, NULL terminated array */
|
||||
const struct attribute_group *groups[2];
|
||||
struct ib_device __rcu *ib_dev;
|
||||
int devnum;
|
||||
struct cdev cdev;
|
||||
struct rb_root xrcd_tree;
|
||||
struct mutex xrcd_tree_mutex;
|
||||
struct kobject kobj;
|
||||
struct srcu_struct disassociate_srcu;
|
||||
struct mutex lists_mutex; /* protect lists */
|
||||
struct list_head uverbs_file_list;
|
||||
|
@@ -169,20 +169,16 @@ int uverbs_dealloc_mw(struct ib_mw *mw)
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void ib_uverbs_release_dev(struct kobject *kobj)
|
||||
static void ib_uverbs_release_dev(struct device *device)
|
||||
{
|
||||
struct ib_uverbs_device *dev =
|
||||
container_of(kobj, struct ib_uverbs_device, kobj);
|
||||
container_of(device, struct ib_uverbs_device, dev);
|
||||
|
||||
uverbs_destroy_api(dev->uapi);
|
||||
cleanup_srcu_struct(&dev->disassociate_srcu);
|
||||
kfree(dev);
|
||||
}
|
||||
|
||||
static struct kobj_type ib_uverbs_dev_ktype = {
|
||||
.release = ib_uverbs_release_dev,
|
||||
};
|
||||
|
||||
static void ib_uverbs_release_async_event_file(struct kref *ref)
|
||||
{
|
||||
struct ib_uverbs_async_event_file *file =
|
||||
@@ -265,7 +261,7 @@ void ib_uverbs_release_file(struct kref *ref)
|
||||
if (atomic_dec_and_test(&file->device->refcount))
|
||||
ib_uverbs_comp_dev(file->device);
|
||||
|
||||
kobject_put(&file->device->kobj);
|
||||
put_device(&file->device->dev);
|
||||
kfree(file);
|
||||
}
|
||||
|
||||
@@ -838,6 +834,7 @@ static int ib_uverbs_open(struct inode *inode, struct file *filp)
|
||||
if (!atomic_inc_not_zero(&dev->refcount))
|
||||
return -ENXIO;
|
||||
|
||||
get_device(&dev->dev);
|
||||
srcu_key = srcu_read_lock(&dev->disassociate_srcu);
|
||||
mutex_lock(&dev->lists_mutex);
|
||||
ib_dev = srcu_dereference(dev->ib_dev,
|
||||
@@ -877,7 +874,6 @@ static int ib_uverbs_open(struct inode *inode, struct file *filp)
|
||||
init_rwsem(&file->hw_destroy_rwsem);
|
||||
|
||||
filp->private_data = file;
|
||||
kobject_get(&dev->kobj);
|
||||
list_add_tail(&file->list, &dev->uverbs_file_list);
|
||||
mutex_unlock(&dev->lists_mutex);
|
||||
srcu_read_unlock(&dev->disassociate_srcu, srcu_key);
|
||||
@@ -898,6 +894,7 @@ err:
|
||||
if (atomic_dec_and_test(&dev->refcount))
|
||||
ib_uverbs_comp_dev(dev);
|
||||
|
||||
put_device(&dev->dev);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -950,17 +947,15 @@ static struct ib_client uverbs_client = {
|
||||
.remove = ib_uverbs_remove_one
|
||||
};
|
||||
|
||||
static ssize_t show_ibdev(struct device *device, struct device_attribute *attr,
|
||||
static ssize_t ibdev_show(struct device *device, struct device_attribute *attr,
|
||||
char *buf)
|
||||
{
|
||||
struct ib_uverbs_device *dev =
|
||||
container_of(device, struct ib_uverbs_device, dev);
|
||||
int ret = -ENODEV;
|
||||
int srcu_key;
|
||||
struct ib_uverbs_device *dev = dev_get_drvdata(device);
|
||||
struct ib_device *ib_dev;
|
||||
|
||||
if (!dev)
|
||||
return -ENODEV;
|
||||
|
||||
srcu_key = srcu_read_lock(&dev->disassociate_srcu);
|
||||
ib_dev = srcu_dereference(dev->ib_dev, &dev->disassociate_srcu);
|
||||
if (ib_dev)
|
||||
@@ -969,18 +964,17 @@ static ssize_t show_ibdev(struct device *device, struct device_attribute *attr,
|
||||
|
||||
return ret;
|
||||
}
|
||||
static DEVICE_ATTR(ibdev, S_IRUGO, show_ibdev, NULL);
|
||||
static DEVICE_ATTR_RO(ibdev);
|
||||
|
||||
static ssize_t show_dev_abi_version(struct device *device,
|
||||
struct device_attribute *attr, char *buf)
|
||||
static ssize_t abi_version_show(struct device *device,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct ib_uverbs_device *dev = dev_get_drvdata(device);
|
||||
struct ib_uverbs_device *dev =
|
||||
container_of(device, struct ib_uverbs_device, dev);
|
||||
int ret = -ENODEV;
|
||||
int srcu_key;
|
||||
struct ib_device *ib_dev;
|
||||
|
||||
if (!dev)
|
||||
return -ENODEV;
|
||||
srcu_key = srcu_read_lock(&dev->disassociate_srcu);
|
||||
ib_dev = srcu_dereference(dev->ib_dev, &dev->disassociate_srcu);
|
||||
if (ib_dev)
|
||||
@@ -989,7 +983,17 @@ static ssize_t show_dev_abi_version(struct device *device,
|
||||
|
||||
return ret;
|
||||
}
|
||||
static DEVICE_ATTR(abi_version, S_IRUGO, show_dev_abi_version, NULL);
|
||||
static DEVICE_ATTR_RO(abi_version);
|
||||
|
||||
static struct attribute *ib_dev_attrs[] = {
|
||||
&dev_attr_abi_version.attr,
|
||||
&dev_attr_ibdev.attr,
|
||||
NULL,
|
||||
};
|
||||
|
||||
static const struct attribute_group dev_attr_group = {
|
||||
.attrs = ib_dev_attrs,
|
||||
};
|
||||
|
||||
static CLASS_ATTR_STRING(abi_version, S_IRUGO,
|
||||
__stringify(IB_USER_VERBS_ABI_VERSION));
|
||||
@@ -1031,7 +1035,6 @@ static void ib_uverbs_add_one(struct ib_device *device)
|
||||
init_completion(&uverbs_dev->comp);
|
||||
uverbs_dev->xrcd_tree = RB_ROOT;
|
||||
mutex_init(&uverbs_dev->xrcd_tree_mutex);
|
||||
kobject_init(&uverbs_dev->kobj, &ib_uverbs_dev_ktype);
|
||||
mutex_init(&uverbs_dev->lists_mutex);
|
||||
INIT_LIST_HEAD(&uverbs_dev->uverbs_file_list);
|
||||
INIT_LIST_HEAD(&uverbs_dev->uverbs_events_file_list);
|
||||
@@ -1050,43 +1053,37 @@ static void ib_uverbs_add_one(struct ib_device *device)
|
||||
uverbs_dev->num_comp_vectors = device->num_comp_vectors;
|
||||
|
||||
if (ib_uverbs_create_uapi(device, uverbs_dev))
|
||||
goto err;
|
||||
goto err_uapi;
|
||||
|
||||
cdev_init(&uverbs_dev->cdev, NULL);
|
||||
device_initialize(&uverbs_dev->dev);
|
||||
uverbs_dev->dev.class = uverbs_class;
|
||||
uverbs_dev->dev.parent = device->dev.parent;
|
||||
uverbs_dev->dev.devt = base;
|
||||
uverbs_dev->dev.release = ib_uverbs_release_dev;
|
||||
uverbs_dev->groups[0] = &dev_attr_group;
|
||||
uverbs_dev->dev.groups = uverbs_dev->groups;
|
||||
dev_set_name(&uverbs_dev->dev, "uverbs%d", uverbs_dev->devnum);
|
||||
|
||||
cdev_init(&uverbs_dev->cdev,
|
||||
device->mmap ? &uverbs_mmap_fops : &uverbs_fops);
|
||||
uverbs_dev->cdev.owner = THIS_MODULE;
|
||||
uverbs_dev->cdev.ops = device->mmap ? &uverbs_mmap_fops : &uverbs_fops;
|
||||
cdev_set_parent(&uverbs_dev->cdev, &uverbs_dev->kobj);
|
||||
kobject_set_name(&uverbs_dev->cdev.kobj, "uverbs%d", uverbs_dev->devnum);
|
||||
if (cdev_add(&uverbs_dev->cdev, base, 1))
|
||||
goto err_cdev;
|
||||
|
||||
uverbs_dev->dev = device_create(uverbs_class, device->dev.parent,
|
||||
uverbs_dev->cdev.dev, uverbs_dev,
|
||||
"uverbs%d", uverbs_dev->devnum);
|
||||
if (IS_ERR(uverbs_dev->dev))
|
||||
ret = cdev_device_add(&uverbs_dev->cdev, &uverbs_dev->dev);
|
||||
if (ret)
|
||||
goto err_cdev;
|
||||
|
||||
if (device_create_file(uverbs_dev->dev, &dev_attr_ibdev))
|
||||
goto err_class;
|
||||
if (device_create_file(uverbs_dev->dev, &dev_attr_abi_version))
|
||||
goto err_class;
|
||||
|
||||
ib_set_client_data(device, &uverbs_client, uverbs_dev);
|
||||
|
||||
return;
|
||||
|
||||
err_class:
|
||||
device_destroy(uverbs_class, uverbs_dev->cdev.dev);
|
||||
|
||||
err_cdev:
|
||||
cdev_del(&uverbs_dev->cdev);
|
||||
put_device(&uverbs_dev->dev);
|
||||
err_uapi:
|
||||
clear_bit(devnum, dev_map);
|
||||
|
||||
err:
|
||||
if (atomic_dec_and_test(&uverbs_dev->refcount))
|
||||
ib_uverbs_comp_dev(uverbs_dev);
|
||||
wait_for_completion(&uverbs_dev->comp);
|
||||
kobject_put(&uverbs_dev->kobj);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1156,9 +1153,7 @@ static void ib_uverbs_remove_one(struct ib_device *device, void *client_data)
|
||||
if (!uverbs_dev)
|
||||
return;
|
||||
|
||||
dev_set_drvdata(uverbs_dev->dev, NULL);
|
||||
device_destroy(uverbs_class, uverbs_dev->cdev.dev);
|
||||
cdev_del(&uverbs_dev->cdev);
|
||||
cdev_device_del(&uverbs_dev->cdev, &uverbs_dev->dev);
|
||||
clear_bit(uverbs_dev->devnum, dev_map);
|
||||
|
||||
if (device->disassociate_ucontext) {
|
||||
@@ -1182,7 +1177,7 @@ static void ib_uverbs_remove_one(struct ib_device *device, void *client_data)
|
||||
if (wait_clients)
|
||||
wait_for_completion(&uverbs_dev->comp);
|
||||
|
||||
kobject_put(&uverbs_dev->kobj);
|
||||
put_device(&uverbs_dev->dev);
|
||||
}
|
||||
|
||||
static char *uverbs_devnode(struct device *dev, umode_t *mode)
|
||||
|
@@ -833,6 +833,8 @@ int bnxt_re_destroy_qp(struct ib_qp *ib_qp)
|
||||
"Failed to destroy Shadow QP");
|
||||
return rc;
|
||||
}
|
||||
bnxt_qplib_free_qp_res(&rdev->qplib_res,
|
||||
&rdev->qp1_sqp->qplib_qp);
|
||||
mutex_lock(&rdev->qp_lock);
|
||||
list_del(&rdev->qp1_sqp->list);
|
||||
atomic_dec(&rdev->qp_count);
|
||||
|
@@ -196,7 +196,7 @@ static int bnxt_qplib_alloc_qp_hdr_buf(struct bnxt_qplib_res *res,
|
||||
struct bnxt_qplib_qp *qp)
|
||||
{
|
||||
struct bnxt_qplib_q *rq = &qp->rq;
|
||||
struct bnxt_qplib_q *sq = &qp->rq;
|
||||
struct bnxt_qplib_q *sq = &qp->sq;
|
||||
int rc = 0;
|
||||
|
||||
if (qp->sq_hdr_buf_size && sq->hwq.max_elements) {
|
||||
|
@@ -1685,6 +1685,12 @@ static void flush_qp(struct c4iw_qp *qhp)
|
||||
schp = to_c4iw_cq(qhp->ibqp.send_cq);
|
||||
|
||||
if (qhp->ibqp.uobject) {
|
||||
|
||||
/* for user qps, qhp->wq.flushed is protected by qhp->mutex */
|
||||
if (qhp->wq.flushed)
|
||||
return;
|
||||
|
||||
qhp->wq.flushed = 1;
|
||||
t4_set_wq_in_error(&qhp->wq, 0);
|
||||
t4_set_cq_in_error(&rchp->cq);
|
||||
spin_lock_irqsave(&rchp->comp_handler_lock, flag);
|
||||
|
@@ -1027,12 +1027,14 @@ static int ipoib_cm_rep_handler(struct ib_cm_id *cm_id,
|
||||
|
||||
skb_queue_head_init(&skqueue);
|
||||
|
||||
netif_tx_lock_bh(p->dev);
|
||||
spin_lock_irq(&priv->lock);
|
||||
set_bit(IPOIB_FLAG_OPER_UP, &p->flags);
|
||||
if (p->neigh)
|
||||
while ((skb = __skb_dequeue(&p->neigh->queue)))
|
||||
__skb_queue_tail(&skqueue, skb);
|
||||
spin_unlock_irq(&priv->lock);
|
||||
netif_tx_unlock_bh(p->dev);
|
||||
|
||||
while ((skb = __skb_dequeue(&skqueue))) {
|
||||
skb->dev = p->dev;
|
||||
|
Reference in New Issue
Block a user