diff options
-rw-r--r-- | drivers/video/fbcmap.c | 28 | ||||
-rw-r--r-- | include/linux/fb.h | 1 |
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 | ||
91 | int fb_alloc_cmap(struct fb_cmap *cmap, int len, int transp) | 91 | int 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 | ||
122 | fail: | 125 | fail: |
123 | fb_dealloc_cmap(cmap); | 126 | fb_dealloc_cmap(cmap); |
124 | return -ENOMEM; | 127 | return ret; |
128 | } | ||
129 | |||
130 | int 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 */ |
1124 | extern int fb_alloc_cmap(struct fb_cmap *cmap, int len, int transp); | 1124 | extern int fb_alloc_cmap(struct fb_cmap *cmap, int len, int transp); |
1125 | extern int fb_alloc_cmap_gfp(struct fb_cmap *cmap, int len, int transp, gfp_t flags); | ||
1125 | extern void fb_dealloc_cmap(struct fb_cmap *cmap); | 1126 | extern void fb_dealloc_cmap(struct fb_cmap *cmap); |
1126 | extern int fb_copy_cmap(const struct fb_cmap *from, struct fb_cmap *to); | 1127 | extern int fb_copy_cmap(const struct fb_cmap *from, struct fb_cmap *to); |
1127 | extern int fb_cmap_to_user(const struct fb_cmap *from, struct fb_cmap_user *to); | 1128 | extern int fb_cmap_to_user(const struct fb_cmap *from, struct fb_cmap_user *to); |