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); |
