lkml.org 
[lkml]   [2016]   [Nov]   [14]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH v7 5/7] iommu/exynos: Rework and fix internal locking
    Date
    This patch reworks locking in the exynos_iommu_attach/detach_device
    functions to ensure that all entries of the sysmmu_drvdata and
    exynos_iommu_owner structure are updated under the respective spinlocks,
    while runtime pm functions are called without any spinlocks held.

    Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com>
    ---
    drivers/iommu/exynos-iommu.c | 27 +++++++++++++++++++--------
    1 file changed, 19 insertions(+), 8 deletions(-)

    diff --git a/drivers/iommu/exynos-iommu.c b/drivers/iommu/exynos-iommu.c
    index 28e570b..a959443 100644
    --- a/drivers/iommu/exynos-iommu.c
    +++ b/drivers/iommu/exynos-iommu.c
    @@ -731,10 +731,12 @@ static void exynos_iommu_domain_free(struct iommu_domain *iommu_domain)
    spin_lock_irqsave(&domain->lock, flags);

    list_for_each_entry_safe(data, next, &domain->clients, domain_node) {
    + spin_lock(&data->lock);
    __sysmmu_disable(data);
    data->pgtable = 0;
    data->domain = NULL;
    list_del_init(&data->domain_node);
    + spin_unlock(&data->lock);
    }

    spin_unlock_irqrestore(&domain->lock, flags);
    @@ -772,17 +774,22 @@ static void exynos_iommu_detach_device(struct iommu_domain *iommu_domain,
    if (!has_sysmmu(dev) || owner->domain != iommu_domain)
    return;

    + list_for_each_entry(data, &owner->controllers, owner_node) {
    + __sysmmu_disable(data);
    + pm_runtime_put(data->sysmmu);
    + }
    +
    spin_lock_irqsave(&domain->lock, flags);
    list_for_each_entry_safe(data, next, &domain->clients, domain_node) {
    - __sysmmu_disable(data);
    + spin_lock(&data->lock);
    data->pgtable = 0;
    data->domain = NULL;
    list_del_init(&data->domain_node);
    - pm_runtime_put(data->sysmmu);
    + spin_unlock(&data->lock);
    }
    + owner->domain = NULL;
    spin_unlock_irqrestore(&domain->lock, flags);

    - owner->domain = NULL;

    dev_dbg(dev, "%s: Detached IOMMU with pgtable %pa\n", __func__,
    &pagetable);
    @@ -803,18 +810,22 @@ static int exynos_iommu_attach_device(struct iommu_domain *iommu_domain,
    if (owner->domain)
    exynos_iommu_detach_device(owner->domain, dev);

    + spin_lock_irqsave(&domain->lock, flags);
    list_for_each_entry(data, &owner->controllers, owner_node) {
    + spin_lock(&data->lock);
    data->pgtable = pagetable;
    data->domain = domain;
    + list_add_tail(&data->domain_node, &domain->clients);
    + spin_unlock(&data->lock);
    + }
    + owner->domain = iommu_domain;
    + spin_unlock_irqrestore(&domain->lock, flags);
    +
    + list_for_each_entry(data, &owner->controllers, owner_node) {
    pm_runtime_get_sync(data->sysmmu);
    __sysmmu_enable(data);
    -
    - spin_lock_irqsave(&domain->lock, flags);
    - list_add_tail(&data->domain_node, &domain->clients);
    - spin_unlock_irqrestore(&domain->lock, flags);
    }

    - owner->domain = iommu_domain;
    dev_dbg(dev, "%s: Attached IOMMU with pgtable %pa\n", __func__,
    &pagetable);

    --
    1.9.1
    \
     
     \ /
      Last update: 2016-11-14 11:13    [W:4.835 / U:0.008 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site