diff options
Diffstat (limited to 'drivers/infiniband/core/uverbs_main.c')
-rw-r--r-- | drivers/infiniband/core/uverbs_main.c | 91 |
1 files changed, 43 insertions, 48 deletions
diff --git a/drivers/infiniband/core/uverbs_main.c b/drivers/infiniband/core/uverbs_main.c index 823beca448e1..16e5f714ca53 100644 --- a/drivers/infiniband/core/uverbs_main.c +++ b/drivers/infiniband/core/uverbs_main.c | |||
@@ -169,20 +169,16 @@ int uverbs_dealloc_mw(struct ib_mw *mw) | |||
169 | return ret; | 169 | return ret; |
170 | } | 170 | } |
171 | 171 | ||
172 | static void ib_uverbs_release_dev(struct kobject *kobj) | 172 | static void ib_uverbs_release_dev(struct device *device) |
173 | { | 173 | { |
174 | struct ib_uverbs_device *dev = | 174 | struct ib_uverbs_device *dev = |
175 | container_of(kobj, struct ib_uverbs_device, kobj); | 175 | container_of(device, struct ib_uverbs_device, dev); |
176 | 176 | ||
177 | uverbs_destroy_api(dev->uapi); | 177 | uverbs_destroy_api(dev->uapi); |
178 | cleanup_srcu_struct(&dev->disassociate_srcu); | 178 | cleanup_srcu_struct(&dev->disassociate_srcu); |
179 | kfree(dev); | 179 | kfree(dev); |
180 | } | 180 | } |
181 | 181 | ||
182 | static struct kobj_type ib_uverbs_dev_ktype = { | ||
183 | .release = ib_uverbs_release_dev, | ||
184 | }; | ||
185 | |||
186 | static void ib_uverbs_release_async_event_file(struct kref *ref) | 182 | static void ib_uverbs_release_async_event_file(struct kref *ref) |
187 | { | 183 | { |
188 | struct ib_uverbs_async_event_file *file = | 184 | struct ib_uverbs_async_event_file *file = |
@@ -265,7 +261,7 @@ void ib_uverbs_release_file(struct kref *ref) | |||
265 | if (atomic_dec_and_test(&file->device->refcount)) | 261 | if (atomic_dec_and_test(&file->device->refcount)) |
266 | ib_uverbs_comp_dev(file->device); | 262 | ib_uverbs_comp_dev(file->device); |
267 | 263 | ||
268 | kobject_put(&file->device->kobj); | 264 | put_device(&file->device->dev); |
269 | kfree(file); | 265 | kfree(file); |
270 | } | 266 | } |
271 | 267 | ||
@@ -838,6 +834,7 @@ static int ib_uverbs_open(struct inode *inode, struct file *filp) | |||
838 | if (!atomic_inc_not_zero(&dev->refcount)) | 834 | if (!atomic_inc_not_zero(&dev->refcount)) |
839 | return -ENXIO; | 835 | return -ENXIO; |
840 | 836 | ||
837 | get_device(&dev->dev); | ||
841 | srcu_key = srcu_read_lock(&dev->disassociate_srcu); | 838 | srcu_key = srcu_read_lock(&dev->disassociate_srcu); |
842 | mutex_lock(&dev->lists_mutex); | 839 | mutex_lock(&dev->lists_mutex); |
843 | ib_dev = srcu_dereference(dev->ib_dev, | 840 | ib_dev = srcu_dereference(dev->ib_dev, |
@@ -877,7 +874,6 @@ static int ib_uverbs_open(struct inode *inode, struct file *filp) | |||
877 | init_rwsem(&file->hw_destroy_rwsem); | 874 | init_rwsem(&file->hw_destroy_rwsem); |
878 | 875 | ||
879 | filp->private_data = file; | 876 | filp->private_data = file; |
880 | kobject_get(&dev->kobj); | ||
881 | list_add_tail(&file->list, &dev->uverbs_file_list); | 877 | list_add_tail(&file->list, &dev->uverbs_file_list); |
882 | mutex_unlock(&dev->lists_mutex); | 878 | mutex_unlock(&dev->lists_mutex); |
883 | srcu_read_unlock(&dev->disassociate_srcu, srcu_key); | 879 | srcu_read_unlock(&dev->disassociate_srcu, srcu_key); |
@@ -898,6 +894,7 @@ err: | |||
898 | if (atomic_dec_and_test(&dev->refcount)) | 894 | if (atomic_dec_and_test(&dev->refcount)) |
899 | ib_uverbs_comp_dev(dev); | 895 | ib_uverbs_comp_dev(dev); |
900 | 896 | ||
897 | put_device(&dev->dev); | ||
901 | return ret; | 898 | return ret; |
902 | } | 899 | } |
903 | 900 | ||
@@ -950,17 +947,15 @@ static struct ib_client uverbs_client = { | |||
950 | .remove = ib_uverbs_remove_one | 947 | .remove = ib_uverbs_remove_one |
951 | }; | 948 | }; |
952 | 949 | ||
953 | static ssize_t show_ibdev(struct device *device, struct device_attribute *attr, | 950 | static ssize_t ibdev_show(struct device *device, struct device_attribute *attr, |
954 | char *buf) | 951 | char *buf) |
955 | { | 952 | { |
953 | struct ib_uverbs_device *dev = | ||
954 | container_of(device, struct ib_uverbs_device, dev); | ||
956 | int ret = -ENODEV; | 955 | int ret = -ENODEV; |
957 | int srcu_key; | 956 | int srcu_key; |
958 | struct ib_uverbs_device *dev = dev_get_drvdata(device); | ||
959 | struct ib_device *ib_dev; | 957 | struct ib_device *ib_dev; |
960 | 958 | ||
961 | if (!dev) | ||
962 | return -ENODEV; | ||
963 | |||
964 | srcu_key = srcu_read_lock(&dev->disassociate_srcu); | 959 | srcu_key = srcu_read_lock(&dev->disassociate_srcu); |
965 | ib_dev = srcu_dereference(dev->ib_dev, &dev->disassociate_srcu); | 960 | ib_dev = srcu_dereference(dev->ib_dev, &dev->disassociate_srcu); |
966 | if (ib_dev) | 961 | if (ib_dev) |
@@ -969,18 +964,17 @@ static ssize_t show_ibdev(struct device *device, struct device_attribute *attr, | |||
969 | 964 | ||
970 | return ret; | 965 | return ret; |
971 | } | 966 | } |
972 | static DEVICE_ATTR(ibdev, S_IRUGO, show_ibdev, NULL); | 967 | static DEVICE_ATTR_RO(ibdev); |
973 | 968 | ||
974 | static ssize_t show_dev_abi_version(struct device *device, | 969 | static ssize_t abi_version_show(struct device *device, |
975 | struct device_attribute *attr, char *buf) | 970 | struct device_attribute *attr, char *buf) |
976 | { | 971 | { |
977 | struct ib_uverbs_device *dev = dev_get_drvdata(device); | 972 | struct ib_uverbs_device *dev = |
973 | container_of(device, struct ib_uverbs_device, dev); | ||
978 | int ret = -ENODEV; | 974 | int ret = -ENODEV; |
979 | int srcu_key; | 975 | int srcu_key; |
980 | struct ib_device *ib_dev; | 976 | struct ib_device *ib_dev; |
981 | 977 | ||
982 | if (!dev) | ||
983 | return -ENODEV; | ||
984 | srcu_key = srcu_read_lock(&dev->disassociate_srcu); | 978 | srcu_key = srcu_read_lock(&dev->disassociate_srcu); |
985 | ib_dev = srcu_dereference(dev->ib_dev, &dev->disassociate_srcu); | 979 | ib_dev = srcu_dereference(dev->ib_dev, &dev->disassociate_srcu); |
986 | if (ib_dev) | 980 | if (ib_dev) |
@@ -989,7 +983,17 @@ static ssize_t show_dev_abi_version(struct device *device, | |||
989 | 983 | ||
990 | return ret; | 984 | return ret; |
991 | } | 985 | } |
992 | static DEVICE_ATTR(abi_version, S_IRUGO, show_dev_abi_version, NULL); | 986 | static DEVICE_ATTR_RO(abi_version); |
987 | |||
988 | static struct attribute *ib_dev_attrs[] = { | ||
989 | &dev_attr_abi_version.attr, | ||
990 | &dev_attr_ibdev.attr, | ||
991 | NULL, | ||
992 | }; | ||
993 | |||
994 | static const struct attribute_group dev_attr_group = { | ||
995 | .attrs = ib_dev_attrs, | ||
996 | }; | ||
993 | 997 | ||
994 | static CLASS_ATTR_STRING(abi_version, S_IRUGO, | 998 | static CLASS_ATTR_STRING(abi_version, S_IRUGO, |
995 | __stringify(IB_USER_VERBS_ABI_VERSION)); | 999 | __stringify(IB_USER_VERBS_ABI_VERSION)); |
@@ -1031,7 +1035,6 @@ static void ib_uverbs_add_one(struct ib_device *device) | |||
1031 | init_completion(&uverbs_dev->comp); | 1035 | init_completion(&uverbs_dev->comp); |
1032 | uverbs_dev->xrcd_tree = RB_ROOT; | 1036 | uverbs_dev->xrcd_tree = RB_ROOT; |
1033 | mutex_init(&uverbs_dev->xrcd_tree_mutex); | 1037 | mutex_init(&uverbs_dev->xrcd_tree_mutex); |
1034 | kobject_init(&uverbs_dev->kobj, &ib_uverbs_dev_ktype); | ||
1035 | mutex_init(&uverbs_dev->lists_mutex); | 1038 | mutex_init(&uverbs_dev->lists_mutex); |
1036 | INIT_LIST_HEAD(&uverbs_dev->uverbs_file_list); | 1039 | INIT_LIST_HEAD(&uverbs_dev->uverbs_file_list); |
1037 | INIT_LIST_HEAD(&uverbs_dev->uverbs_events_file_list); | 1040 | INIT_LIST_HEAD(&uverbs_dev->uverbs_events_file_list); |
@@ -1050,43 +1053,37 @@ static void ib_uverbs_add_one(struct ib_device *device) | |||
1050 | uverbs_dev->num_comp_vectors = device->num_comp_vectors; | 1053 | uverbs_dev->num_comp_vectors = device->num_comp_vectors; |
1051 | 1054 | ||
1052 | if (ib_uverbs_create_uapi(device, uverbs_dev)) | 1055 | if (ib_uverbs_create_uapi(device, uverbs_dev)) |
1053 | goto err; | 1056 | goto err_uapi; |
1054 | 1057 | ||
1055 | cdev_init(&uverbs_dev->cdev, NULL); | 1058 | device_initialize(&uverbs_dev->dev); |
1059 | uverbs_dev->dev.class = uverbs_class; | ||
1060 | uverbs_dev->dev.parent = device->dev.parent; | ||
1061 | uverbs_dev->dev.devt = base; | ||
1062 | uverbs_dev->dev.release = ib_uverbs_release_dev; | ||
1063 | uverbs_dev->groups[0] = &dev_attr_group; | ||
1064 | uverbs_dev->dev.groups = uverbs_dev->groups; | ||
1065 | dev_set_name(&uverbs_dev->dev, "uverbs%d", uverbs_dev->devnum); | ||
1066 | |||
1067 | cdev_init(&uverbs_dev->cdev, | ||
1068 | device->mmap ? &uverbs_mmap_fops : &uverbs_fops); | ||
1056 | uverbs_dev->cdev.owner = THIS_MODULE; | 1069 | uverbs_dev->cdev.owner = THIS_MODULE; |
1057 | uverbs_dev->cdev.ops = device->mmap ? &uverbs_mmap_fops : &uverbs_fops; | ||
1058 | cdev_set_parent(&uverbs_dev->cdev, &uverbs_dev->kobj); | ||
1059 | kobject_set_name(&uverbs_dev->cdev.kobj, "uverbs%d", uverbs_dev->devnum); | ||
1060 | if (cdev_add(&uverbs_dev->cdev, base, 1)) | ||
1061 | goto err_cdev; | ||
1062 | 1070 | ||
1063 | uverbs_dev->dev = device_create(uverbs_class, device->dev.parent, | 1071 | ret = cdev_device_add(&uverbs_dev->cdev, &uverbs_dev->dev); |
1064 | uverbs_dev->cdev.dev, uverbs_dev, | 1072 | if (ret) |
1065 | "uverbs%d", uverbs_dev->devnum); | ||
1066 | if (IS_ERR(uverbs_dev->dev)) | ||
1067 | goto err_cdev; | 1073 | goto err_cdev; |
1068 | 1074 | ||
1069 | if (device_create_file(uverbs_dev->dev, &dev_attr_ibdev)) | ||
1070 | goto err_class; | ||
1071 | if (device_create_file(uverbs_dev->dev, &dev_attr_abi_version)) | ||
1072 | goto err_class; | ||
1073 | |||
1074 | ib_set_client_data(device, &uverbs_client, uverbs_dev); | 1075 | ib_set_client_data(device, &uverbs_client, uverbs_dev); |
1075 | |||
1076 | return; | 1076 | return; |
1077 | 1077 | ||
1078 | err_class: | ||
1079 | device_destroy(uverbs_class, uverbs_dev->cdev.dev); | ||
1080 | |||
1081 | err_cdev: | 1078 | err_cdev: |
1082 | cdev_del(&uverbs_dev->cdev); | 1079 | cdev_del(&uverbs_dev->cdev); |
1080 | put_device(&uverbs_dev->dev); | ||
1081 | err_uapi: | ||
1083 | clear_bit(devnum, dev_map); | 1082 | clear_bit(devnum, dev_map); |
1084 | |||
1085 | err: | 1083 | err: |
1086 | if (atomic_dec_and_test(&uverbs_dev->refcount)) | 1084 | if (atomic_dec_and_test(&uverbs_dev->refcount)) |
1087 | ib_uverbs_comp_dev(uverbs_dev); | 1085 | ib_uverbs_comp_dev(uverbs_dev); |
1088 | wait_for_completion(&uverbs_dev->comp); | 1086 | wait_for_completion(&uverbs_dev->comp); |
1089 | kobject_put(&uverbs_dev->kobj); | ||
1090 | return; | 1087 | return; |
1091 | } | 1088 | } |
1092 | 1089 | ||
@@ -1156,9 +1153,7 @@ static void ib_uverbs_remove_one(struct ib_device *device, void *client_data) | |||
1156 | if (!uverbs_dev) | 1153 | if (!uverbs_dev) |
1157 | return; | 1154 | return; |
1158 | 1155 | ||
1159 | dev_set_drvdata(uverbs_dev->dev, NULL); | 1156 | cdev_device_del(&uverbs_dev->cdev, &uverbs_dev->dev); |
1160 | device_destroy(uverbs_class, uverbs_dev->cdev.dev); | ||
1161 | cdev_del(&uverbs_dev->cdev); | ||
1162 | clear_bit(uverbs_dev->devnum, dev_map); | 1157 | clear_bit(uverbs_dev->devnum, dev_map); |
1163 | 1158 | ||
1164 | if (device->disassociate_ucontext) { | 1159 | if (device->disassociate_ucontext) { |
@@ -1182,7 +1177,7 @@ static void ib_uverbs_remove_one(struct ib_device *device, void *client_data) | |||
1182 | if (wait_clients) | 1177 | if (wait_clients) |
1183 | wait_for_completion(&uverbs_dev->comp); | 1178 | wait_for_completion(&uverbs_dev->comp); |
1184 | 1179 | ||
1185 | kobject_put(&uverbs_dev->kobj); | 1180 | put_device(&uverbs_dev->dev); |
1186 | } | 1181 | } |
1187 | 1182 | ||
1188 | static char *uverbs_devnode(struct device *dev, umode_t *mode) | 1183 | static char *uverbs_devnode(struct device *dev, umode_t *mode) |