aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/vfio/mdev/mdev_core.c94
-rw-r--r--drivers/vfio/mdev/mdev_private.h2
-rw-r--r--drivers/vfio/mdev/mdev_sysfs.c2
3 files changed, 27 insertions, 71 deletions
diff --git a/drivers/vfio/mdev/mdev_core.c b/drivers/vfio/mdev/mdev_core.c
index 3cc1a05fde1c..0bef0cae1d4b 100644
--- a/drivers/vfio/mdev/mdev_core.c
+++ b/drivers/vfio/mdev/mdev_core.c
@@ -102,55 +102,10 @@ static void mdev_put_parent(struct mdev_parent *parent)
102 kref_put(&parent->ref, mdev_release_parent); 102 kref_put(&parent->ref, mdev_release_parent);
103} 103}
104 104
105static int mdev_device_create_ops(struct kobject *kobj,
106 struct mdev_device *mdev)
107{
108 struct mdev_parent *parent = mdev->parent;
109 int ret;
110
111 ret = parent->ops->create(kobj, mdev);
112 if (ret)
113 return ret;
114
115 ret = sysfs_create_groups(&mdev->dev.kobj,
116 parent->ops->mdev_attr_groups);
117 if (ret)
118 parent->ops->remove(mdev);
119
120 return ret;
121}
122
123/*
124 * mdev_device_remove_ops gets called from sysfs's 'remove' and when parent
125 * device is being unregistered from mdev device framework.
126 * - 'force_remove' is set to 'false' when called from sysfs's 'remove' which
127 * indicates that if the mdev device is active, used by VMM or userspace
128 * application, vendor driver could return error then don't remove the device.
129 * - 'force_remove' is set to 'true' when called from mdev_unregister_device()
130 * which indicate that parent device is being removed from mdev device
131 * framework so remove mdev device forcefully.
132 */
133static int mdev_device_remove_ops(struct mdev_device *mdev, bool force_remove)
134{
135 struct mdev_parent *parent = mdev->parent;
136 int ret;
137
138 /*
139 * Vendor driver can return error if VMM or userspace application is
140 * using this mdev device.
141 */
142 ret = parent->ops->remove(mdev);
143 if (ret && !force_remove)
144 return ret;
145
146 sysfs_remove_groups(&mdev->dev.kobj, parent->ops->mdev_attr_groups);
147 return 0;
148}
149
150static int mdev_device_remove_cb(struct device *dev, void *data) 105static int mdev_device_remove_cb(struct device *dev, void *data)
151{ 106{
152 if (dev_is_mdev(dev)) 107 if (dev_is_mdev(dev))
153 mdev_device_remove(dev, true); 108 mdev_device_remove(dev);
154 109
155 return 0; 110 return 0;
156} 111}
@@ -310,41 +265,43 @@ int mdev_device_create(struct kobject *kobj,
310 265
311 mdev->parent = parent; 266 mdev->parent = parent;
312 267
268 device_initialize(&mdev->dev);
313 mdev->dev.parent = dev; 269 mdev->dev.parent = dev;
314 mdev->dev.bus = &mdev_bus_type; 270 mdev->dev.bus = &mdev_bus_type;
315 mdev->dev.release = mdev_device_release; 271 mdev->dev.release = mdev_device_release;
316 dev_set_name(&mdev->dev, "%pUl", uuid); 272 dev_set_name(&mdev->dev, "%pUl", uuid);
273 mdev->dev.groups = parent->ops->mdev_attr_groups;
274 mdev->type_kobj = kobj;
317 275
318 ret = device_register(&mdev->dev); 276 ret = parent->ops->create(kobj, mdev);
319 if (ret) { 277 if (ret)
320 put_device(&mdev->dev); 278 goto ops_create_fail;
321 goto mdev_fail;
322 }
323 279
324 ret = mdev_device_create_ops(kobj, mdev); 280 ret = device_add(&mdev->dev);
325 if (ret) 281 if (ret)
326 goto create_fail; 282 goto add_fail;
327 283
328 ret = mdev_create_sysfs_files(&mdev->dev, type); 284 ret = mdev_create_sysfs_files(&mdev->dev, type);
329 if (ret) { 285 if (ret)
330 mdev_device_remove_ops(mdev, true); 286 goto sysfs_fail;
331 goto create_fail;
332 }
333 287
334 mdev->type_kobj = kobj;
335 mdev->active = true; 288 mdev->active = true;
336 dev_dbg(&mdev->dev, "MDEV: created\n"); 289 dev_dbg(&mdev->dev, "MDEV: created\n");
337 290
338 return 0; 291 return 0;
339 292
340create_fail: 293sysfs_fail:
341 device_unregister(&mdev->dev); 294 device_del(&mdev->dev);
295add_fail:
296 parent->ops->remove(mdev);
297ops_create_fail:
298 put_device(&mdev->dev);
342mdev_fail: 299mdev_fail:
343 mdev_put_parent(parent); 300 mdev_put_parent(parent);
344 return ret; 301 return ret;
345} 302}
346 303
347int mdev_device_remove(struct device *dev, bool force_remove) 304int mdev_device_remove(struct device *dev)
348{ 305{
349 struct mdev_device *mdev, *tmp; 306 struct mdev_device *mdev, *tmp;
350 struct mdev_parent *parent; 307 struct mdev_parent *parent;
@@ -373,16 +330,15 @@ int mdev_device_remove(struct device *dev, bool force_remove)
373 mutex_unlock(&mdev_list_lock); 330 mutex_unlock(&mdev_list_lock);
374 331
375 type = to_mdev_type(mdev->type_kobj); 332 type = to_mdev_type(mdev->type_kobj);
333 mdev_remove_sysfs_files(dev, type);
334 device_del(&mdev->dev);
376 parent = mdev->parent; 335 parent = mdev->parent;
336 ret = parent->ops->remove(mdev);
337 if (ret)
338 dev_err(&mdev->dev, "Remove failed: err=%d\n", ret);
377 339
378 ret = mdev_device_remove_ops(mdev, force_remove); 340 /* Balances with device_initialize() */
379 if (ret) { 341 put_device(&mdev->dev);
380 mdev->active = true;
381 return ret;
382 }
383
384 mdev_remove_sysfs_files(dev, type);
385 device_unregister(dev);
386 mdev_put_parent(parent); 342 mdev_put_parent(parent);
387 343
388 return 0; 344 return 0;
diff --git a/drivers/vfio/mdev/mdev_private.h b/drivers/vfio/mdev/mdev_private.h
index 36cbbdb754de..924ed2274941 100644
--- a/drivers/vfio/mdev/mdev_private.h
+++ b/drivers/vfio/mdev/mdev_private.h
@@ -60,6 +60,6 @@ void mdev_remove_sysfs_files(struct device *dev, struct mdev_type *type);
60 60
61int mdev_device_create(struct kobject *kobj, 61int mdev_device_create(struct kobject *kobj,
62 struct device *dev, const guid_t *uuid); 62 struct device *dev, const guid_t *uuid);
63int mdev_device_remove(struct device *dev, bool force_remove); 63int mdev_device_remove(struct device *dev);
64 64
65#endif /* MDEV_PRIVATE_H */ 65#endif /* MDEV_PRIVATE_H */
diff --git a/drivers/vfio/mdev/mdev_sysfs.c b/drivers/vfio/mdev/mdev_sysfs.c
index cbf94b8165ea..9f774b91d275 100644
--- a/drivers/vfio/mdev/mdev_sysfs.c
+++ b/drivers/vfio/mdev/mdev_sysfs.c
@@ -236,7 +236,7 @@ static ssize_t remove_store(struct device *dev, struct device_attribute *attr,
236 if (val && device_remove_file_self(dev, attr)) { 236 if (val && device_remove_file_self(dev, attr)) {
237 int ret; 237 int ret;
238 238
239 ret = mdev_device_remove(dev, false); 239 ret = mdev_device_remove(dev);
240 if (ret) { 240 if (ret) {
241 device_create_file(dev, attr); 241 device_create_file(dev, attr);
242 return ret; 242 return ret;