diff options
Diffstat (limited to 'drivers/video/fbcmap.c')
-rw-r--r-- | drivers/video/fbcmap.c | 68 |
1 files changed, 43 insertions, 25 deletions
diff --git a/drivers/video/fbcmap.c b/drivers/video/fbcmap.c index f53b9f1d6aba..affdf3e32cf3 100644 --- a/drivers/video/fbcmap.c +++ b/drivers/video/fbcmap.c | |||
@@ -88,34 +88,48 @@ 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 | 94 | int ret = -ENOMEM; | |
95 | if (cmap->len != len) { | 95 | |
96 | fb_dealloc_cmap(cmap); | 96 | if (cmap->len != len) { |
97 | if (!len) | 97 | fb_dealloc_cmap(cmap); |
98 | return 0; | 98 | if (!len) |
99 | if (!(cmap->red = kmalloc(size, GFP_ATOMIC))) | 99 | return 0; |
100 | goto fail; | 100 | |
101 | if (!(cmap->green = kmalloc(size, GFP_ATOMIC))) | 101 | cmap->red = kmalloc(size, flags); |
102 | goto fail; | 102 | if (!cmap->red) |
103 | if (!(cmap->blue = kmalloc(size, GFP_ATOMIC))) | 103 | goto fail; |
104 | goto fail; | 104 | cmap->green = kmalloc(size, flags); |
105 | if (transp) { | 105 | if (!cmap->green) |
106 | if (!(cmap->transp = kmalloc(size, GFP_ATOMIC))) | 106 | goto fail; |
107 | cmap->blue = kmalloc(size, flags); | ||
108 | if (!cmap->blue) | ||
109 | goto fail; | ||
110 | if (transp) { | ||
111 | cmap->transp = kmalloc(size, flags); | ||
112 | if (!cmap->transp) | ||
113 | goto fail; | ||
114 | } else { | ||
115 | cmap->transp = NULL; | ||
116 | } | ||
117 | } | ||
118 | cmap->start = 0; | ||
119 | cmap->len = len; | ||
120 | ret = fb_copy_cmap(fb_default_cmap(len), cmap); | ||
121 | if (ret) | ||
107 | goto fail; | 122 | goto fail; |
108 | } else | 123 | return 0; |
109 | cmap->transp = NULL; | ||
110 | } | ||
111 | cmap->start = 0; | ||
112 | cmap->len = len; | ||
113 | fb_copy_cmap(fb_default_cmap(len), cmap); | ||
114 | return 0; | ||
115 | 124 | ||
116 | fail: | 125 | fail: |
117 | fb_dealloc_cmap(cmap); | 126 | fb_dealloc_cmap(cmap); |
118 | 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); | ||
119 | } | 133 | } |
120 | 134 | ||
121 | /** | 135 | /** |
@@ -250,8 +264,12 @@ int fb_set_user_cmap(struct fb_cmap_user *cmap, struct fb_info *info) | |||
250 | int rc, size = cmap->len * sizeof(u16); | 264 | int rc, size = cmap->len * sizeof(u16); |
251 | struct fb_cmap umap; | 265 | struct fb_cmap umap; |
252 | 266 | ||
267 | if (size < 0 || size < cmap->len) | ||
268 | return -E2BIG; | ||
269 | |||
253 | memset(&umap, 0, sizeof(struct fb_cmap)); | 270 | memset(&umap, 0, sizeof(struct fb_cmap)); |
254 | 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); | ||
255 | if (rc) | 273 | if (rc) |
256 | return rc; | 274 | return rc; |
257 | if (copy_from_user(umap.red, cmap->red, size) || | 275 | if (copy_from_user(umap.red, cmap->red, size) || |