.. | .. |
---|
201 | 201 | const struct iommu_ops *ops = dev->bus->iommu_ops; |
---|
202 | 202 | struct iommu_device *iommu_dev; |
---|
203 | 203 | struct iommu_group *group; |
---|
| 204 | + static DEFINE_MUTEX(iommu_probe_device_lock); |
---|
204 | 205 | int ret; |
---|
205 | 206 | |
---|
206 | 207 | if (!ops) |
---|
207 | 208 | return -ENODEV; |
---|
208 | | - |
---|
209 | | - if (!dev_iommu_get(dev)) |
---|
210 | | - return -ENOMEM; |
---|
| 209 | + /* |
---|
| 210 | + * Serialise to avoid races between IOMMU drivers registering in |
---|
| 211 | + * parallel and/or the "replay" calls from ACPI/OF code via client |
---|
| 212 | + * driver probe. Once the latter have been cleaned up we should |
---|
| 213 | + * probably be able to use device_lock() here to minimise the scope, |
---|
| 214 | + * but for now enforcing a simple global ordering is fine. |
---|
| 215 | + */ |
---|
| 216 | + mutex_lock(&iommu_probe_device_lock); |
---|
| 217 | + if (!dev_iommu_get(dev)) { |
---|
| 218 | + ret = -ENOMEM; |
---|
| 219 | + goto err_unlock; |
---|
| 220 | + } |
---|
211 | 221 | |
---|
212 | 222 | if (!try_module_get(ops->owner)) { |
---|
213 | 223 | ret = -EINVAL; |
---|
.. | .. |
---|
227 | 237 | ret = PTR_ERR(group); |
---|
228 | 238 | goto out_release; |
---|
229 | 239 | } |
---|
230 | | - iommu_group_put(group); |
---|
231 | 240 | |
---|
| 241 | + mutex_lock(&group->mutex); |
---|
232 | 242 | if (group_list && !group->default_domain && list_empty(&group->entry)) |
---|
233 | 243 | list_add_tail(&group->entry, group_list); |
---|
| 244 | + mutex_unlock(&group->mutex); |
---|
| 245 | + iommu_group_put(group); |
---|
234 | 246 | |
---|
| 247 | + mutex_unlock(&iommu_probe_device_lock); |
---|
235 | 248 | iommu_device_link(iommu_dev, dev); |
---|
236 | 249 | |
---|
237 | 250 | return 0; |
---|
.. | .. |
---|
244 | 257 | |
---|
245 | 258 | err_free: |
---|
246 | 259 | dev_iommu_free(dev); |
---|
| 260 | + |
---|
| 261 | +err_unlock: |
---|
| 262 | + mutex_unlock(&iommu_probe_device_lock); |
---|
247 | 263 | |
---|
248 | 264 | return ret; |
---|
249 | 265 | } |
---|
.. | .. |
---|
1766 | 1782 | return ret; |
---|
1767 | 1783 | |
---|
1768 | 1784 | list_for_each_entry_safe(group, next, &group_list, entry) { |
---|
| 1785 | + mutex_lock(&group->mutex); |
---|
| 1786 | + |
---|
1769 | 1787 | /* Remove item from the list */ |
---|
1770 | 1788 | list_del_init(&group->entry); |
---|
1771 | | - |
---|
1772 | | - mutex_lock(&group->mutex); |
---|
1773 | 1789 | |
---|
1774 | 1790 | /* Try to allocate default domain */ |
---|
1775 | 1791 | probe_alloc_default_domain(bus, group); |
---|