From: Ville Syrjälä <ville.syrjala@xxxxxxxxxxxxxxx> Should have been fixed by commit 6d03bbff456b ("hwmon: (coretemp) Simplify platform device handling") ? This reverts commit c7dec68ee19c4671f0110dfd3e3ff40069f75d66. Signed-off-by: Ville Syrjälä <ville.syrjala@xxxxxxxxxxxxxxx> --- drivers/iommu/iova.c | 28 ++++++++++++++++++++++++++++ include/linux/cpuhotplug.h | 1 + include/linux/iova.h | 1 + 3 files changed, 30 insertions(+) diff --git a/drivers/iommu/iova.c b/drivers/iommu/iova.c index 6cc35b018f21..10b964600948 100644 --- a/drivers/iommu/iova.c +++ b/drivers/iommu/iova.c @@ -31,6 +31,16 @@ unsigned long iova_rcache_range(void) return PAGE_SIZE << (IOVA_RANGE_CACHE_MAX_SIZE - 1); } +static int iova_cpuhp_dead(unsigned int cpu, struct hlist_node *node) +{ + struct iova_domain *iovad; + + iovad = hlist_entry_safe(node, struct iova_domain, cpuhp_dead); + + free_cpu_cached_iovas(cpu, iovad); + return 0; +} + static void free_global_cached_iovas(struct iova_domain *iovad); static struct iova *to_iova(struct rb_node *node) @@ -245,10 +255,21 @@ int iova_cache_get(void) { mutex_lock(&iova_cache_mutex); if (!iova_cache_users) { + int ret; + + ret = cpuhp_setup_state_multi(CPUHP_IOMMU_IOVA_DEAD, "iommu/iova:dead", NULL, + iova_cpuhp_dead); + if (ret) { + mutex_unlock(&iova_cache_mutex); + pr_err("Couldn't register cpuhp handler\n"); + return ret; + } + iova_cache = kmem_cache_create( "iommu_iova", sizeof(struct iova), 0, SLAB_HWCACHE_ALIGN, NULL); if (!iova_cache) { + cpuhp_remove_multi_state(CPUHP_IOMMU_IOVA_DEAD); mutex_unlock(&iova_cache_mutex); pr_err("Couldn't create iova cache\n"); return -ENOMEM; @@ -271,6 +292,7 @@ void iova_cache_put(void) } iova_cache_users--; if (!iova_cache_users) { + cpuhp_remove_multi_state(CPUHP_IOMMU_IOVA_DEAD); kmem_cache_destroy(iova_cache); } mutex_unlock(&iova_cache_mutex); @@ -473,6 +495,8 @@ EXPORT_SYMBOL_GPL(free_iova_fast); static void iova_domain_free_rcaches(struct iova_domain *iovad) { + cpuhp_state_remove_instance_nocalls(CPUHP_IOMMU_IOVA_DEAD, + &iovad->cpuhp_dead); free_iova_rcaches(iovad); } @@ -730,6 +754,10 @@ int iova_domain_init_rcaches(struct iova_domain *iovad) } } + ret = cpuhp_state_add_instance_nocalls(CPUHP_IOMMU_IOVA_DEAD, + &iovad->cpuhp_dead); + if (ret) + goto out_err; return 0; out_err: diff --git a/include/linux/cpuhotplug.h b/include/linux/cpuhotplug.h index 82d49ebed7ca..068f7738be22 100644 --- a/include/linux/cpuhotplug.h +++ b/include/linux/cpuhotplug.h @@ -95,6 +95,7 @@ enum cpuhp_state { CPUHP_PAGE_ALLOC, CPUHP_NET_DEV_DEAD, CPUHP_PCI_XGENE_DEAD, + CPUHP_IOMMU_IOVA_DEAD, CPUHP_LUSTRE_CFS_DEAD, CPUHP_AP_ARM_CACHE_B15_RAC_DEAD, CPUHP_PADATA_DEAD, diff --git a/include/linux/iova.h b/include/linux/iova.h index 6fe3374e8dd6..83c00fac2acb 100644 --- a/include/linux/iova.h +++ b/include/linux/iova.h @@ -37,6 +37,7 @@ struct iova_domain { struct iova anchor; /* rbtree lookup anchor */ struct iova_rcache *rcaches; + struct hlist_node cpuhp_dead; }; static inline unsigned long iova_size(struct iova *iova) -- 2.41.0