aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/iommu/iommu.c')
-rw-r--r--drivers/iommu/iommu.c37
1 files changed, 24 insertions, 13 deletions
diff --git a/drivers/iommu/iommu.c b/drivers/iommu/iommu.c
index 515bb8b80952..a070fa39521a 100644
--- a/drivers/iommu/iommu.c
+++ b/drivers/iommu/iommu.c
@@ -391,36 +391,30 @@ int iommu_group_add_device(struct iommu_group *group, struct device *dev)
391 device->dev = dev; 391 device->dev = dev;
392 392
393 ret = sysfs_create_link(&dev->kobj, &group->kobj, "iommu_group"); 393 ret = sysfs_create_link(&dev->kobj, &group->kobj, "iommu_group");
394 if (ret) { 394 if (ret)
395 kfree(device); 395 goto err_free_device;
396 return ret;
397 }
398 396
399 device->name = kasprintf(GFP_KERNEL, "%s", kobject_name(&dev->kobj)); 397 device->name = kasprintf(GFP_KERNEL, "%s", kobject_name(&dev->kobj));
400rename: 398rename:
401 if (!device->name) { 399 if (!device->name) {
402 sysfs_remove_link(&dev->kobj, "iommu_group"); 400 ret = -ENOMEM;
403 kfree(device); 401 goto err_remove_link;
404 return -ENOMEM;
405 } 402 }
406 403
407 ret = sysfs_create_link_nowarn(group->devices_kobj, 404 ret = sysfs_create_link_nowarn(group->devices_kobj,
408 &dev->kobj, device->name); 405 &dev->kobj, device->name);
409 if (ret) { 406 if (ret) {
410 kfree(device->name);
411 if (ret == -EEXIST && i >= 0) { 407 if (ret == -EEXIST && i >= 0) {
412 /* 408 /*
413 * Account for the slim chance of collision 409 * Account for the slim chance of collision
414 * and append an instance to the name. 410 * and append an instance to the name.
415 */ 411 */
412 kfree(device->name);
416 device->name = kasprintf(GFP_KERNEL, "%s.%d", 413 device->name = kasprintf(GFP_KERNEL, "%s.%d",
417 kobject_name(&dev->kobj), i++); 414 kobject_name(&dev->kobj), i++);
418 goto rename; 415 goto rename;
419 } 416 }
420 417 goto err_free_name;
421 sysfs_remove_link(&dev->kobj, "iommu_group");
422 kfree(device);
423 return ret;
424 } 418 }
425 419
426 kobject_get(group->devices_kobj); 420 kobject_get(group->devices_kobj);
@@ -432,8 +426,10 @@ rename:
432 mutex_lock(&group->mutex); 426 mutex_lock(&group->mutex);
433 list_add_tail(&device->list, &group->devices); 427 list_add_tail(&device->list, &group->devices);
434 if (group->domain) 428 if (group->domain)
435 __iommu_attach_device(group->domain, dev); 429 ret = __iommu_attach_device(group->domain, dev);
436 mutex_unlock(&group->mutex); 430 mutex_unlock(&group->mutex);
431 if (ret)
432 goto err_put_group;
437 433
438 /* Notify any listeners about change to group. */ 434 /* Notify any listeners about change to group. */
439 blocking_notifier_call_chain(&group->notifier, 435 blocking_notifier_call_chain(&group->notifier,
@@ -444,6 +440,21 @@ rename:
444 pr_info("Adding device %s to group %d\n", dev_name(dev), group->id); 440 pr_info("Adding device %s to group %d\n", dev_name(dev), group->id);
445 441
446 return 0; 442 return 0;
443
444err_put_group:
445 mutex_lock(&group->mutex);
446 list_del(&device->list);
447 mutex_unlock(&group->mutex);
448 dev->iommu_group = NULL;
449 kobject_put(group->devices_kobj);
450err_free_name:
451 kfree(device->name);
452err_remove_link:
453 sysfs_remove_link(&dev->kobj, "iommu_group");
454err_free_device:
455 kfree(device);
456 pr_err("Failed to add device %s to group %d: %d\n", dev_name(dev), group->id, ret);
457 return ret;
447} 458}
448EXPORT_SYMBOL_GPL(iommu_group_add_device); 459EXPORT_SYMBOL_GPL(iommu_group_add_device);
449 460