mm/hmm: heterogeneous memory management (HMM for short)
[sfrench/cifs-2.6.git] / mm / hmm.c
1 /*
2  * Copyright 2013 Red Hat Inc.
3  *
4  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation; either version 2 of the License, or
7  * (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * Authors: Jérôme Glisse <jglisse@redhat.com>
15  */
16 /*
17  * Refer to include/linux/hmm.h for information about heterogeneous memory
18  * management or HMM for short.
19  */
20 #include <linux/mm.h>
21 #include <linux/hmm.h>
22 #include <linux/slab.h>
23 #include <linux/sched.h>
24
25
26 #ifdef CONFIG_HMM
27 /*
28  * struct hmm - HMM per mm struct
29  *
30  * @mm: mm struct this HMM struct is bound to
31  */
32 struct hmm {
33         struct mm_struct        *mm;
34 };
35
36 /*
37  * hmm_register - register HMM against an mm (HMM internal)
38  *
39  * @mm: mm struct to attach to
40  *
41  * This is not intended to be used directly by device drivers. It allocates an
42  * HMM struct if mm does not have one, and initializes it.
43  */
44 static struct hmm *hmm_register(struct mm_struct *mm)
45 {
46         if (!mm->hmm) {
47                 struct hmm *hmm = NULL;
48
49                 hmm = kmalloc(sizeof(*hmm), GFP_KERNEL);
50                 if (!hmm)
51                         return NULL;
52                 hmm->mm = mm;
53
54                 spin_lock(&mm->page_table_lock);
55                 if (!mm->hmm)
56                         mm->hmm = hmm;
57                 else
58                         kfree(hmm);
59                 spin_unlock(&mm->page_table_lock);
60         }
61
62         /*
63          * The hmm struct can only be freed once the mm_struct goes away,
64          * hence we should always have pre-allocated an new hmm struct
65          * above.
66          */
67         return mm->hmm;
68 }
69
70 void hmm_mm_destroy(struct mm_struct *mm)
71 {
72         kfree(mm->hmm);
73 }
74 #endif /* CONFIG_HMM */