aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2017-08-27 20:10:34 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2017-08-27 20:10:34 -0400
commit2c25833c426b85ed40fc0120b5020a6fb836538f (patch)
tree044ea78b73a4b695bda58e5d421ee0c26e252a49
parent80f73b2da09af8ba94c07c8f34774f4f79330321 (diff)
parent2926a2aa5c14fb2add75e6584845b1c03022235f (diff)
Merge tag 'iommu-fixes-v4.13-rc6' of git://git.kernel.org/pub/scm/linux/kernel/git/joro/iommu
Pull IOMMU fix from Joerg Roedel: "Another fix, this time in common IOMMU sysfs code. In the conversion from the old iommu sysfs-code to the iommu_device_register interface, I missed to update the release path for the struct device associated with an IOMMU. It freed the 'struct device', which was a pointer before, but is now embedded in another struct. Freeing from the middle of allocated memory had all kinds of nasty side effects when an IOMMU was unplugged. Unfortunatly nobody unplugged and IOMMU until now, so this was not discovered earlier. The fix is to make the 'struct device' a pointer again" * tag 'iommu-fixes-v4.13-rc6' of git://git.kernel.org/pub/scm/linux/kernel/git/joro/iommu: iommu: Fix wrong freeing of iommu_device->dev
-rw-r--r--drivers/iommu/amd_iommu_types.h4
-rw-r--r--drivers/iommu/intel-iommu.c4
-rw-r--r--drivers/iommu/iommu-sysfs.c32
-rw-r--r--include/linux/iommu.h12
4 files changed, 37 insertions, 15 deletions
diff --git a/drivers/iommu/amd_iommu_types.h b/drivers/iommu/amd_iommu_types.h
index 294a409e283b..d6b873b57054 100644
--- a/drivers/iommu/amd_iommu_types.h
+++ b/drivers/iommu/amd_iommu_types.h
@@ -574,7 +574,9 @@ struct amd_iommu {
574 574
575static inline struct amd_iommu *dev_to_amd_iommu(struct device *dev) 575static inline struct amd_iommu *dev_to_amd_iommu(struct device *dev)
576{ 576{
577 return container_of(dev, struct amd_iommu, iommu.dev); 577 struct iommu_device *iommu = dev_to_iommu_device(dev);
578
579 return container_of(iommu, struct amd_iommu, iommu);
578} 580}
579 581
580#define ACPIHID_UID_LEN 256 582#define ACPIHID_UID_LEN 256
diff --git a/drivers/iommu/intel-iommu.c b/drivers/iommu/intel-iommu.c
index 687f18f65cea..3e8636f1220e 100644
--- a/drivers/iommu/intel-iommu.c
+++ b/drivers/iommu/intel-iommu.c
@@ -4736,7 +4736,9 @@ static void intel_disable_iommus(void)
4736 4736
4737static inline struct intel_iommu *dev_to_intel_iommu(struct device *dev) 4737static inline struct intel_iommu *dev_to_intel_iommu(struct device *dev)
4738{ 4738{
4739 return container_of(dev, struct intel_iommu, iommu.dev); 4739 struct iommu_device *iommu_dev = dev_to_iommu_device(dev);
4740
4741 return container_of(iommu_dev, struct intel_iommu, iommu);
4740} 4742}
4741 4743
4742static ssize_t intel_iommu_show_version(struct device *dev, 4744static ssize_t intel_iommu_show_version(struct device *dev,
diff --git a/drivers/iommu/iommu-sysfs.c b/drivers/iommu/iommu-sysfs.c
index c58351ed61c1..36d1a7ce7fc4 100644
--- a/drivers/iommu/iommu-sysfs.c
+++ b/drivers/iommu/iommu-sysfs.c
@@ -62,32 +62,40 @@ int iommu_device_sysfs_add(struct iommu_device *iommu,
62 va_list vargs; 62 va_list vargs;
63 int ret; 63 int ret;
64 64
65 device_initialize(&iommu->dev); 65 iommu->dev = kzalloc(sizeof(*iommu->dev), GFP_KERNEL);
66 if (!iommu->dev)
67 return -ENOMEM;
66 68
67 iommu->dev.class = &iommu_class; 69 device_initialize(iommu->dev);
68 iommu->dev.parent = parent; 70
69 iommu->dev.groups = groups; 71 iommu->dev->class = &iommu_class;
72 iommu->dev->parent = parent;
73 iommu->dev->groups = groups;
70 74
71 va_start(vargs, fmt); 75 va_start(vargs, fmt);
72 ret = kobject_set_name_vargs(&iommu->dev.kobj, fmt, vargs); 76 ret = kobject_set_name_vargs(&iommu->dev->kobj, fmt, vargs);
73 va_end(vargs); 77 va_end(vargs);
74 if (ret) 78 if (ret)
75 goto error; 79 goto error;
76 80
77 ret = device_add(&iommu->dev); 81 ret = device_add(iommu->dev);
78 if (ret) 82 if (ret)
79 goto error; 83 goto error;
80 84
85 dev_set_drvdata(iommu->dev, iommu);
86
81 return 0; 87 return 0;
82 88
83error: 89error:
84 put_device(&iommu->dev); 90 put_device(iommu->dev);
85 return ret; 91 return ret;
86} 92}
87 93
88void iommu_device_sysfs_remove(struct iommu_device *iommu) 94void iommu_device_sysfs_remove(struct iommu_device *iommu)
89{ 95{
90 device_unregister(&iommu->dev); 96 dev_set_drvdata(iommu->dev, NULL);
97 device_unregister(iommu->dev);
98 iommu->dev = NULL;
91} 99}
92/* 100/*
93 * IOMMU drivers can indicate a device is managed by a given IOMMU using 101 * IOMMU drivers can indicate a device is managed by a given IOMMU using
@@ -102,14 +110,14 @@ int iommu_device_link(struct iommu_device *iommu, struct device *link)
102 if (!iommu || IS_ERR(iommu)) 110 if (!iommu || IS_ERR(iommu))
103 return -ENODEV; 111 return -ENODEV;
104 112
105 ret = sysfs_add_link_to_group(&iommu->dev.kobj, "devices", 113 ret = sysfs_add_link_to_group(&iommu->dev->kobj, "devices",
106 &link->kobj, dev_name(link)); 114 &link->kobj, dev_name(link));
107 if (ret) 115 if (ret)
108 return ret; 116 return ret;
109 117
110 ret = sysfs_create_link_nowarn(&link->kobj, &iommu->dev.kobj, "iommu"); 118 ret = sysfs_create_link_nowarn(&link->kobj, &iommu->dev->kobj, "iommu");
111 if (ret) 119 if (ret)
112 sysfs_remove_link_from_group(&iommu->dev.kobj, "devices", 120 sysfs_remove_link_from_group(&iommu->dev->kobj, "devices",
113 dev_name(link)); 121 dev_name(link));
114 122
115 return ret; 123 return ret;
@@ -121,5 +129,5 @@ void iommu_device_unlink(struct iommu_device *iommu, struct device *link)
121 return; 129 return;
122 130
123 sysfs_remove_link(&link->kobj, "iommu"); 131 sysfs_remove_link(&link->kobj, "iommu");
124 sysfs_remove_link_from_group(&iommu->dev.kobj, "devices", dev_name(link)); 132 sysfs_remove_link_from_group(&iommu->dev->kobj, "devices", dev_name(link));
125} 133}
diff --git a/include/linux/iommu.h b/include/linux/iommu.h
index 2cb54adc4a33..176f7569d874 100644
--- a/include/linux/iommu.h
+++ b/include/linux/iommu.h
@@ -240,7 +240,7 @@ struct iommu_device {
240 struct list_head list; 240 struct list_head list;
241 const struct iommu_ops *ops; 241 const struct iommu_ops *ops;
242 struct fwnode_handle *fwnode; 242 struct fwnode_handle *fwnode;
243 struct device dev; 243 struct device *dev;
244}; 244};
245 245
246int iommu_device_register(struct iommu_device *iommu); 246int iommu_device_register(struct iommu_device *iommu);
@@ -265,6 +265,11 @@ static inline void iommu_device_set_fwnode(struct iommu_device *iommu,
265 iommu->fwnode = fwnode; 265 iommu->fwnode = fwnode;
266} 266}
267 267
268static inline struct iommu_device *dev_to_iommu_device(struct device *dev)
269{
270 return (struct iommu_device *)dev_get_drvdata(dev);
271}
272
268#define IOMMU_GROUP_NOTIFY_ADD_DEVICE 1 /* Device added */ 273#define IOMMU_GROUP_NOTIFY_ADD_DEVICE 1 /* Device added */
269#define IOMMU_GROUP_NOTIFY_DEL_DEVICE 2 /* Pre Device removed */ 274#define IOMMU_GROUP_NOTIFY_DEL_DEVICE 2 /* Pre Device removed */
270#define IOMMU_GROUP_NOTIFY_BIND_DRIVER 3 /* Pre Driver bind */ 275#define IOMMU_GROUP_NOTIFY_BIND_DRIVER 3 /* Pre Driver bind */
@@ -589,6 +594,11 @@ static inline void iommu_device_set_fwnode(struct iommu_device *iommu,
589{ 594{
590} 595}
591 596
597static inline struct iommu_device *dev_to_iommu_device(struct device *dev)
598{
599 return NULL;
600}
601
592static inline void iommu_device_unregister(struct iommu_device *iommu) 602static inline void iommu_device_unregister(struct iommu_device *iommu)
593{ 603{
594} 604}