Merge branch 'hwmon-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/groec...
[cascardo/linux.git] / drivers / video / fbcmap.c
index a79b976..affdf3e 100644 (file)
@@ -88,26 +88,27 @@ static const struct fb_cmap default_16_colors = {
  *
  */
 
-int fb_alloc_cmap(struct fb_cmap *cmap, int len, int transp)
+int fb_alloc_cmap_gfp(struct fb_cmap *cmap, int len, int transp, gfp_t flags)
 {
        int size = len * sizeof(u16);
+       int ret = -ENOMEM;
 
        if (cmap->len != len) {
                fb_dealloc_cmap(cmap);
                if (!len)
                        return 0;
 
-               cmap->red = kmalloc(size, GFP_ATOMIC);
+               cmap->red = kmalloc(size, flags);
                if (!cmap->red)
                        goto fail;
-               cmap->green = kmalloc(size, GFP_ATOMIC);
+               cmap->green = kmalloc(size, flags);
                if (!cmap->green)
                        goto fail;
-               cmap->blue = kmalloc(size, GFP_ATOMIC);
+               cmap->blue = kmalloc(size, flags);
                if (!cmap->blue)
                        goto fail;
                if (transp) {
-                       cmap->transp = kmalloc(size, GFP_ATOMIC);
+                       cmap->transp = kmalloc(size, flags);
                        if (!cmap->transp)
                                goto fail;
                } else {
@@ -116,12 +117,19 @@ int fb_alloc_cmap(struct fb_cmap *cmap, int len, int transp)
        }
        cmap->start = 0;
        cmap->len = len;
-       fb_copy_cmap(fb_default_cmap(len), cmap);
+       ret = fb_copy_cmap(fb_default_cmap(len), cmap);
+       if (ret)
+               goto fail;
        return 0;
 
 fail:
        fb_dealloc_cmap(cmap);
-       return -ENOMEM;
+       return ret;
+}
+
+int fb_alloc_cmap(struct fb_cmap *cmap, int len, int transp)
+{
+       return fb_alloc_cmap_gfp(cmap, len, transp, GFP_ATOMIC);
 }
 
 /**
@@ -256,8 +264,12 @@ int fb_set_user_cmap(struct fb_cmap_user *cmap, struct fb_info *info)
        int rc, size = cmap->len * sizeof(u16);
        struct fb_cmap umap;
 
+       if (size < 0 || size < cmap->len)
+               return -E2BIG;
+
        memset(&umap, 0, sizeof(struct fb_cmap));
-       rc = fb_alloc_cmap(&umap, cmap->len, cmap->transp != NULL);
+       rc = fb_alloc_cmap_gfp(&umap, cmap->len, cmap->transp != NULL,
+                               GFP_KERNEL);
        if (rc)
                return rc;
        if (copy_from_user(umap.red, cmap->red, size) ||