diff options
Diffstat (limited to 'kernel')
-rw-r--r-- | kernel/relay.c | 35 |
1 files changed, 32 insertions, 3 deletions
diff --git a/kernel/relay.c b/kernel/relay.c index d6204a485818..bc24dcdc570f 100644 --- a/kernel/relay.c +++ b/kernel/relay.c | |||
@@ -65,6 +65,35 @@ static struct vm_operations_struct relay_file_mmap_ops = { | |||
65 | .close = relay_file_mmap_close, | 65 | .close = relay_file_mmap_close, |
66 | }; | 66 | }; |
67 | 67 | ||
68 | /* | ||
69 | * allocate an array of pointers of struct page | ||
70 | */ | ||
71 | static struct page **relay_alloc_page_array(unsigned int n_pages) | ||
72 | { | ||
73 | struct page **array; | ||
74 | size_t pa_size = n_pages * sizeof(struct page *); | ||
75 | |||
76 | if (pa_size > PAGE_SIZE) { | ||
77 | array = vmalloc(pa_size); | ||
78 | if (array) | ||
79 | memset(array, 0, pa_size); | ||
80 | } else { | ||
81 | array = kzalloc(pa_size, GFP_KERNEL); | ||
82 | } | ||
83 | return array; | ||
84 | } | ||
85 | |||
86 | /* | ||
87 | * free an array of pointers of struct page | ||
88 | */ | ||
89 | static void relay_free_page_array(struct page **array) | ||
90 | { | ||
91 | if (is_vmalloc_addr(array)) | ||
92 | vfree(array); | ||
93 | else | ||
94 | kfree(array); | ||
95 | } | ||
96 | |||
68 | /** | 97 | /** |
69 | * relay_mmap_buf: - mmap channel buffer to process address space | 98 | * relay_mmap_buf: - mmap channel buffer to process address space |
70 | * @buf: relay channel buffer | 99 | * @buf: relay channel buffer |
@@ -109,7 +138,7 @@ static void *relay_alloc_buf(struct rchan_buf *buf, size_t *size) | |||
109 | *size = PAGE_ALIGN(*size); | 138 | *size = PAGE_ALIGN(*size); |
110 | n_pages = *size >> PAGE_SHIFT; | 139 | n_pages = *size >> PAGE_SHIFT; |
111 | 140 | ||
112 | buf->page_array = kcalloc(n_pages, sizeof(struct page *), GFP_KERNEL); | 141 | buf->page_array = relay_alloc_page_array(n_pages); |
113 | if (!buf->page_array) | 142 | if (!buf->page_array) |
114 | return NULL; | 143 | return NULL; |
115 | 144 | ||
@@ -130,7 +159,7 @@ static void *relay_alloc_buf(struct rchan_buf *buf, size_t *size) | |||
130 | depopulate: | 159 | depopulate: |
131 | for (j = 0; j < i; j++) | 160 | for (j = 0; j < i; j++) |
132 | __free_page(buf->page_array[j]); | 161 | __free_page(buf->page_array[j]); |
133 | kfree(buf->page_array); | 162 | relay_free_page_array(buf->page_array); |
134 | return NULL; | 163 | return NULL; |
135 | } | 164 | } |
136 | 165 | ||
@@ -189,7 +218,7 @@ static void relay_destroy_buf(struct rchan_buf *buf) | |||
189 | vunmap(buf->start); | 218 | vunmap(buf->start); |
190 | for (i = 0; i < buf->page_count; i++) | 219 | for (i = 0; i < buf->page_count; i++) |
191 | __free_page(buf->page_array[i]); | 220 | __free_page(buf->page_array[i]); |
192 | kfree(buf->page_array); | 221 | relay_free_page_array(buf->page_array); |
193 | } | 222 | } |
194 | chan->buf[buf->cpu] = NULL; | 223 | chan->buf[buf->cpu] = NULL; |
195 | kfree(buf->padding); | 224 | kfree(buf->padding); |