aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/video/fbcmap.c28
-rw-r--r--include/linux/fb.h1
2 files changed, 21 insertions, 8 deletions
diff --git a/drivers/video/fbcmap.c b/drivers/video/fbcmap.c
index a79b9762901e..affdf3e32cf3 100644
--- a/drivers/video/fbcmap.c
+++ b/drivers/video/fbcmap.c
@@ -88,26 +88,27 @@ static const struct fb_cmap default_16_colors = {
88 * 88 *
89 */ 89 */
90 90
91int fb_alloc_cmap(struct fb_cmap *cmap, int len, int transp) 91int fb_alloc_cmap_gfp(struct fb_cmap *cmap, int len, int transp, gfp_t flags)
92{ 92{
93 int size = len * sizeof(u16); 93 int size = len * sizeof(u16);
94 int ret = -ENOMEM;
94 95
95 if (cmap->len != len) { 96 if (cmap->len != len) {
96 fb_dealloc_cmap(cmap); 97 fb_dealloc_cmap(cmap);
97 if (!len) 98 if (!len)
98 return 0; 99 return 0;
99 100
100 cmap->red = kmalloc(size, GFP_ATOMIC); 101 cmap->red = kmalloc(size, flags);
101 if (!cmap->red) 102 if (!cmap->red)
102 goto fail; 103 goto fail;
103 cmap->green = kmalloc(size, GFP_ATOMIC); 104 cmap->green = kmalloc(size, flags);
104 if (!cmap->green) 105 if (!cmap->green)
105 goto fail; 106 goto fail;
106 cmap->blue = kmalloc(size, GFP_ATOMIC); 107 cmap->blue = kmalloc(size, flags);
107 if (!cmap->blue) 108 if (!cmap->blue)
108 goto fail; 109 goto fail;
109 if (transp) { 110 if (transp) {
110 cmap->transp = kmalloc(size, GFP_ATOMIC); 111 cmap->transp = kmalloc(size, flags);
111 if (!cmap->transp) 112 if (!cmap->transp)
112 goto fail; 113 goto fail;
113 } else { 114 } else {
@@ -116,12 +117,19 @@ int fb_alloc_cmap(struct fb_cmap *cmap, int len, int transp)
116 } 117 }
117 cmap->start = 0; 118 cmap->start = 0;
118 cmap->len = len; 119 cmap->len = len;
119 fb_copy_cmap(fb_default_cmap(len), cmap); 120 ret = fb_copy_cmap(fb_default_cmap(len), cmap);
121 if (ret)
122 goto fail;
120 return 0; 123 return 0;
121 124
122fail: 125fail:
123 fb_dealloc_cmap(cmap); 126 fb_dealloc_cmap(cmap);
124 return -ENOMEM; 127 return ret;
128}
129
130int fb_alloc_cmap(struct fb_cmap *cmap, int len, int transp)
131{
132 return fb_alloc_cmap_gfp(cmap, len, transp, GFP_ATOMIC);
125} 133}
126 134
127/** 135/**
@@ -256,8 +264,12 @@ int fb_set_user_cmap(struct fb_cmap_user *cmap, struct fb_info *info)
256 int rc, size = cmap->len * sizeof(u16); 264 int rc, size = cmap->len * sizeof(u16);
257 struct fb_cmap umap; 265 struct fb_cmap umap;
258 266
267 if (size < 0 || size < cmap->len)
268 return -E2BIG;
269
259 memset(&umap, 0, sizeof(struct fb_cmap)); 270 memset(&umap, 0, sizeof(struct fb_cmap));
260 rc = fb_alloc_cmap(&umap, cmap->len, cmap->transp != NULL); 271 rc = fb_alloc_cmap_gfp(&umap, cmap->len, cmap->transp != NULL,
272 GFP_KERNEL);
261 if (rc) 273 if (rc)
262 return rc; 274 return rc;
263 if (copy_from_user(umap.red, cmap->red, size) || 275 if (copy_from_user(umap.red, cmap->red, size) ||
diff --git a/include/linux/fb.h b/include/linux/fb.h
index 7fca3dc4e475..d1631d37e9e0 100644
--- a/include/linux/fb.h
+++ b/include/linux/fb.h
@@ -1122,6 +1122,7 @@ extern const struct fb_videomode *fb_find_best_display(const struct fb_monspecs
1122 1122
1123/* drivers/video/fbcmap.c */ 1123/* drivers/video/fbcmap.c */
1124extern int fb_alloc_cmap(struct fb_cmap *cmap, int len, int transp); 1124extern int fb_alloc_cmap(struct fb_cmap *cmap, int len, int transp);
1125extern int fb_alloc_cmap_gfp(struct fb_cmap *cmap, int len, int transp, gfp_t flags);
1125extern void fb_dealloc_cmap(struct fb_cmap *cmap); 1126extern void fb_dealloc_cmap(struct fb_cmap *cmap);
1126extern int fb_copy_cmap(const struct fb_cmap *from, struct fb_cmap *to); 1127extern int fb_copy_cmap(const struct fb_cmap *from, struct fb_cmap *to);
1127extern int fb_cmap_to_user(const struct fb_cmap *from, struct fb_cmap_user *to); 1128extern int fb_cmap_to_user(const struct fb_cmap *from, struct fb_cmap_user *to);