summaryrefslogtreecommitdiff
path: root/arch/s390/mm
diff options
context:
space:
mode:
Diffstat (limited to 'arch/s390/mm')
-rw-r--r--arch/s390/mm/gmap.c7
1 files changed, 4 insertions, 3 deletions
diff --git a/arch/s390/mm/gmap.c b/arch/s390/mm/gmap.c
index 6695a09..b02d0d0 100644
--- a/arch/s390/mm/gmap.c
+++ b/arch/s390/mm/gmap.c
@@ -173,6 +173,9 @@ static void gmap_free(struct gmap *gmap)
{
struct page *page, *next;
+ /* Flush tlb of all gmaps (if not already done for shadows) */
+ if (!(gmap_is_shadow(gmap) && gmap->removed))
+ gmap_flush_tlb(gmap);
/* Free all segment & region tables. */
list_for_each_entry_safe(page, next, &gmap->crst_list, lru)
__free_pages(page, 2);
@@ -226,13 +229,10 @@ void gmap_remove(struct gmap *gmap)
{
struct gmap *sg, *next;
- /* Flush tlb. */
- gmap_flush_tlb(gmap);
/* Remove all shadow gmaps linked to this gmap */
if (!list_empty(&gmap->children)) {
spin_lock(&gmap->shadow_lock);
list_for_each_entry_safe(sg, next, &gmap->children, list) {
- gmap_flush_tlb(sg);
list_del(&sg->list);
gmap_put(sg);
}
@@ -1360,6 +1360,7 @@ static void gmap_unshadow(struct gmap *sg)
return;
sg->removed = 1;
gmap_call_notifier(sg, 0, -1UL);
+ gmap_flush_tlb(sg);
table = (unsigned long *)(sg->asce & _ASCE_ORIGIN);
switch (sg->asce & _ASCE_TYPE_MASK) {
case _ASCE_TYPE_REGION1: