| .. | .. |
|---|
| 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); |
|---|