LCOV - code coverage report
Current view: top level - drivers/video/fbdev/core - fbmem.c (source / functions) Hit Total Coverage
Test: combined.info Lines: 9 842 1.1 %
Date: 2022-04-01 14:17:54 Functions: 1 43 2.3 %
Branches: 3 620 0.5 %

           Branch data     Line data    Source code
       1                 :            : /*
       2                 :            :  *  linux/drivers/video/fbmem.c
       3                 :            :  *
       4                 :            :  *  Copyright (C) 1994 Martin Schaller
       5                 :            :  *
       6                 :            :  *      2001 - Documented with DocBook
       7                 :            :  *      - Brad Douglas <brad@neruo.com>
       8                 :            :  *
       9                 :            :  * This file is subject to the terms and conditions of the GNU General Public
      10                 :            :  * License.  See the file COPYING in the main directory of this archive
      11                 :            :  * for more details.
      12                 :            :  */
      13                 :            : 
      14                 :            : #include <linux/module.h>
      15                 :            : 
      16                 :            : #include <linux/compat.h>
      17                 :            : #include <linux/types.h>
      18                 :            : #include <linux/errno.h>
      19                 :            : #include <linux/kernel.h>
      20                 :            : #include <linux/major.h>
      21                 :            : #include <linux/slab.h>
      22                 :            : #include <linux/mm.h>
      23                 :            : #include <linux/mman.h>
      24                 :            : #include <linux/vt.h>
      25                 :            : #include <linux/init.h>
      26                 :            : #include <linux/linux_logo.h>
      27                 :            : #include <linux/proc_fs.h>
      28                 :            : #include <linux/seq_file.h>
      29                 :            : #include <linux/console.h>
      30                 :            : #include <linux/kmod.h>
      31                 :            : #include <linux/err.h>
      32                 :            : #include <linux/device.h>
      33                 :            : #include <linux/efi.h>
      34                 :            : #include <linux/fb.h>
      35                 :            : #include <linux/fbcon.h>
      36                 :            : #include <linux/mem_encrypt.h>
      37                 :            : #include <linux/pci.h>
      38                 :            : 
      39                 :            : #include <asm/fb.h>
      40                 :            : 
      41                 :            : 
      42                 :            :     /*
      43                 :            :      *  Frame buffer device initialization and setup routines
      44                 :            :      */
      45                 :            : 
      46                 :            : #define FBPIXMAPSIZE    (1024 * 8)
      47                 :            : 
      48                 :            : static DEFINE_MUTEX(registration_lock);
      49                 :            : 
      50                 :            : struct fb_info *registered_fb[FB_MAX] __read_mostly;
      51                 :            : EXPORT_SYMBOL(registered_fb);
      52                 :            : 
      53                 :            : int num_registered_fb __read_mostly;
      54                 :            : EXPORT_SYMBOL(num_registered_fb);
      55                 :            : 
      56                 :            : bool fb_center_logo __read_mostly;
      57                 :            : 
      58                 :            : int fb_logo_count __read_mostly = -1;
      59                 :            : 
      60                 :          0 : static struct fb_info *get_fb_info(unsigned int idx)
      61                 :            : {
      62                 :          0 :         struct fb_info *fb_info;
      63                 :            : 
      64         [ #  # ]:          0 :         if (idx >= FB_MAX)
      65                 :            :                 return ERR_PTR(-ENODEV);
      66                 :            : 
      67                 :          0 :         mutex_lock(&registration_lock);
      68                 :          0 :         fb_info = registered_fb[idx];
      69         [ #  # ]:          0 :         if (fb_info)
      70                 :          0 :                 atomic_inc(&fb_info->count);
      71                 :          0 :         mutex_unlock(&registration_lock);
      72                 :            : 
      73                 :          0 :         return fb_info;
      74                 :            : }
      75                 :            : 
      76                 :          0 : static void put_fb_info(struct fb_info *fb_info)
      77                 :            : {
      78         [ #  # ]:          0 :         if (!atomic_dec_and_test(&fb_info->count))
      79                 :            :                 return;
      80         [ #  # ]:          0 :         if (fb_info->fbops->fb_destroy)
      81                 :          0 :                 fb_info->fbops->fb_destroy(fb_info);
      82                 :            : }
      83                 :            : 
      84                 :            : /*
      85                 :            :  * Helpers
      86                 :            :  */
      87                 :            : 
      88                 :          0 : int fb_get_color_depth(struct fb_var_screeninfo *var,
      89                 :            :                        struct fb_fix_screeninfo *fix)
      90                 :            : {
      91                 :          0 :         int depth = 0;
      92                 :            : 
      93         [ #  # ]:          0 :         if (fix->visual == FB_VISUAL_MONO01 ||
      94                 :            :             fix->visual == FB_VISUAL_MONO10)
      95                 :            :                 depth = 1;
      96                 :            :         else {
      97   [ #  #  #  #  :          0 :                 if (var->green.length == var->blue.length &&
                   #  # ]
      98   [ #  #  #  #  :          0 :                     var->green.length == var->red.length &&
                   #  # ]
      99   [ #  #  #  #  :          0 :                     var->green.offset == var->blue.offset &&
                   #  # ]
     100   [ #  #  #  #  :          0 :                     var->green.offset == var->red.offset)
                   #  # ]
     101                 :          0 :                         depth = var->green.length;
     102                 :            :                 else
     103                 :          0 :                         depth = var->green.length + var->red.length +
     104                 :            :                                 var->blue.length;
     105                 :            :         }
     106                 :            : 
     107                 :          0 :         return depth;
     108                 :            : }
     109                 :            : EXPORT_SYMBOL(fb_get_color_depth);
     110                 :            : 
     111                 :            : /*
     112                 :            :  * Data padding functions.
     113                 :            :  */
     114                 :          0 : void fb_pad_aligned_buffer(u8 *dst, u32 d_pitch, u8 *src, u32 s_pitch, u32 height)
     115                 :            : {
     116                 :          0 :         __fb_pad_aligned_buffer(dst, d_pitch, src, s_pitch, height);
     117                 :          0 : }
     118                 :            : EXPORT_SYMBOL(fb_pad_aligned_buffer);
     119                 :            : 
     120                 :          0 : void fb_pad_unaligned_buffer(u8 *dst, u32 d_pitch, u8 *src, u32 idx, u32 height,
     121                 :            :                                 u32 shift_high, u32 shift_low, u32 mod)
     122                 :            : {
     123                 :          0 :         u8 mask = (u8) (0xfff << shift_high), tmp;
     124                 :          0 :         int i, j;
     125                 :            : 
     126         [ #  # ]:          0 :         for (i = height; i--; ) {
     127         [ #  # ]:          0 :                 for (j = 0; j < idx; j++) {
     128                 :          0 :                         tmp = dst[j];
     129                 :          0 :                         tmp &= mask;
     130                 :          0 :                         tmp |= *src >> shift_low;
     131                 :          0 :                         dst[j] = tmp;
     132                 :          0 :                         tmp = *src << shift_high;
     133                 :          0 :                         dst[j+1] = tmp;
     134                 :          0 :                         src++;
     135                 :            :                 }
     136                 :          0 :                 tmp = dst[idx];
     137                 :          0 :                 tmp &= mask;
     138                 :          0 :                 tmp |= *src >> shift_low;
     139                 :          0 :                 dst[idx] = tmp;
     140         [ #  # ]:          0 :                 if (shift_high < mod) {
     141                 :          0 :                         tmp = *src << shift_high;
     142                 :          0 :                         dst[idx+1] = tmp;
     143                 :            :                 }
     144                 :          0 :                 src++;
     145                 :          0 :                 dst += d_pitch;
     146                 :            :         }
     147                 :          0 : }
     148                 :            : EXPORT_SYMBOL(fb_pad_unaligned_buffer);
     149                 :            : 
     150                 :            : /*
     151                 :            :  * we need to lock this section since fb_cursor
     152                 :            :  * may use fb_imageblit()
     153                 :            :  */
     154                 :          0 : char* fb_get_buffer_offset(struct fb_info *info, struct fb_pixmap *buf, u32 size)
     155                 :            : {
     156                 :          0 :         u32 align = buf->buf_align - 1, offset;
     157                 :          0 :         char *addr = buf->addr;
     158                 :            : 
     159                 :            :         /* If IO mapped, we need to sync before access, no sharing of
     160                 :            :          * the pixmap is done
     161                 :            :          */
     162         [ #  # ]:          0 :         if (buf->flags & FB_PIXMAP_IO) {
     163   [ #  #  #  # ]:          0 :                 if (info->fbops->fb_sync && (buf->flags & FB_PIXMAP_SYNC))
     164                 :          0 :                         info->fbops->fb_sync(info);
     165                 :          0 :                 return addr;
     166                 :            :         }
     167                 :            : 
     168                 :            :         /* See if we fit in the remaining pixmap space */
     169                 :          0 :         offset = buf->offset + align;
     170                 :          0 :         offset &= ~align;
     171         [ #  # ]:          0 :         if (offset + size > buf->size) {
     172                 :            :                 /* We do not fit. In order to be able to re-use the buffer,
     173                 :            :                  * we must ensure no asynchronous DMA'ing or whatever operation
     174                 :            :                  * is in progress, we sync for that.
     175                 :            :                  */
     176   [ #  #  #  # ]:          0 :                 if (info->fbops->fb_sync && (buf->flags & FB_PIXMAP_SYNC))
     177                 :          0 :                         info->fbops->fb_sync(info);
     178                 :            :                 offset = 0;
     179                 :            :         }
     180                 :          0 :         buf->offset = offset + size;
     181                 :          0 :         addr += offset;
     182                 :            : 
     183                 :          0 :         return addr;
     184                 :            : }
     185                 :            : EXPORT_SYMBOL(fb_get_buffer_offset);
     186                 :            : 
     187                 :            : #ifdef CONFIG_LOGO
     188                 :            : 
     189                 :            : static inline unsigned safe_shift(unsigned d, int n)
     190                 :            : {
     191                 :            :         return n < 0 ? d >> -n : d << n;
     192                 :            : }
     193                 :            : 
     194                 :            : static void fb_set_logocmap(struct fb_info *info,
     195                 :            :                                    const struct linux_logo *logo)
     196                 :            : {
     197                 :            :         struct fb_cmap palette_cmap;
     198                 :            :         u16 palette_green[16];
     199                 :            :         u16 palette_blue[16];
     200                 :            :         u16 palette_red[16];
     201                 :            :         int i, j, n;
     202                 :            :         const unsigned char *clut = logo->clut;
     203                 :            : 
     204                 :            :         palette_cmap.start = 0;
     205                 :            :         palette_cmap.len = 16;
     206                 :            :         palette_cmap.red = palette_red;
     207                 :            :         palette_cmap.green = palette_green;
     208                 :            :         palette_cmap.blue = palette_blue;
     209                 :            :         palette_cmap.transp = NULL;
     210                 :            : 
     211                 :            :         for (i = 0; i < logo->clutsize; i += n) {
     212                 :            :                 n = logo->clutsize - i;
     213                 :            :                 /* palette_cmap provides space for only 16 colors at once */
     214                 :            :                 if (n > 16)
     215                 :            :                         n = 16;
     216                 :            :                 palette_cmap.start = 32 + i;
     217                 :            :                 palette_cmap.len = n;
     218                 :            :                 for (j = 0; j < n; ++j) {
     219                 :            :                         palette_cmap.red[j] = clut[0] << 8 | clut[0];
     220                 :            :                         palette_cmap.green[j] = clut[1] << 8 | clut[1];
     221                 :            :                         palette_cmap.blue[j] = clut[2] << 8 | clut[2];
     222                 :            :                         clut += 3;
     223                 :            :                 }
     224                 :            :                 fb_set_cmap(&palette_cmap, info);
     225                 :            :         }
     226                 :            : }
     227                 :            : 
     228                 :            : static void  fb_set_logo_truepalette(struct fb_info *info,
     229                 :            :                                             const struct linux_logo *logo,
     230                 :            :                                             u32 *palette)
     231                 :            : {
     232                 :            :         static const unsigned char mask[] = { 0,0x80,0xc0,0xe0,0xf0,0xf8,0xfc,0xfe,0xff };
     233                 :            :         unsigned char redmask, greenmask, bluemask;
     234                 :            :         int redshift, greenshift, blueshift;
     235                 :            :         int i;
     236                 :            :         const unsigned char *clut = logo->clut;
     237                 :            : 
     238                 :            :         /*
     239                 :            :          * We have to create a temporary palette since console palette is only
     240                 :            :          * 16 colors long.
     241                 :            :          */
     242                 :            :         /* Bug: Doesn't obey msb_right ... (who needs that?) */
     243                 :            :         redmask   = mask[info->var.red.length   < 8 ? info->var.red.length   : 8];
     244                 :            :         greenmask = mask[info->var.green.length < 8 ? info->var.green.length : 8];
     245                 :            :         bluemask  = mask[info->var.blue.length  < 8 ? info->var.blue.length  : 8];
     246                 :            :         redshift   = info->var.red.offset   - (8 - info->var.red.length);
     247                 :            :         greenshift = info->var.green.offset - (8 - info->var.green.length);
     248                 :            :         blueshift  = info->var.blue.offset  - (8 - info->var.blue.length);
     249                 :            : 
     250                 :            :         for ( i = 0; i < logo->clutsize; i++) {
     251                 :            :                 palette[i+32] = (safe_shift((clut[0] & redmask), redshift) |
     252                 :            :                                  safe_shift((clut[1] & greenmask), greenshift) |
     253                 :            :                                  safe_shift((clut[2] & bluemask), blueshift));
     254                 :            :                 clut += 3;
     255                 :            :         }
     256                 :            : }
     257                 :            : 
     258                 :          0 : static void fb_set_logo_directpalette(struct fb_info *info,
     259                 :            :                                              const struct linux_logo *logo,
     260                 :            :                                              u32 *palette)
     261                 :            : {
     262                 :          0 :         int redshift, greenshift, blueshift;
     263                 :          0 :         int i;
     264                 :            : 
     265                 :          0 :         redshift = info->var.red.offset;
     266                 :          0 :         greenshift = info->var.green.offset;
     267                 :          0 :         blueshift = info->var.blue.offset;
     268                 :            : 
     269         [ #  # ]:          0 :         for (i = 32; i < 32 + logo->clutsize; i++)
     270                 :          0 :                 palette[i] = i << redshift | i << greenshift | i << blueshift;
     271                 :            : }
     272                 :            : 
     273                 :          0 : static void fb_set_logo(struct fb_info *info,
     274                 :            :                                const struct linux_logo *logo, u8 *dst,
     275                 :            :                                int depth)
     276                 :            : {
     277                 :          0 :         int i, j, k;
     278                 :          0 :         const u8 *src = logo->data;
     279         [ #  # ]:          0 :         u8 xor = (info->fix.visual == FB_VISUAL_MONO01) ? 0xff : 0;
     280                 :          0 :         u8 fg = 1, d;
     281                 :            : 
     282   [ #  #  #  #  :          0 :         switch (fb_get_color_depth(&info->var, &info->fix)) {
                      # ]
     283                 :            :         case 1:
     284                 :            :                 fg = 1;
     285                 :            :                 break;
     286                 :          0 :         case 2:
     287                 :          0 :                 fg = 3;
     288                 :          0 :                 break;
     289                 :          0 :         default:
     290                 :          0 :                 fg = 7;
     291                 :          0 :                 break;
     292                 :            :         }
     293                 :            : 
     294         [ #  # ]:          0 :         if (info->fix.visual == FB_VISUAL_MONO01 ||
     295                 :            :             info->fix.visual == FB_VISUAL_MONO10)
     296                 :          0 :                 fg = ~((u8) (0xfff << info->var.green.length));
     297                 :            : 
     298      [ #  #  # ]:          0 :         switch (depth) {
     299                 :            :         case 4:
     300         [ #  # ]:          0 :                 for (i = 0; i < logo->height; i++)
     301         [ #  # ]:          0 :                         for (j = 0; j < logo->width; src++) {
     302                 :          0 :                                 *dst++ = *src >> 4;
     303                 :          0 :                                 j++;
     304         [ #  # ]:          0 :                                 if (j < logo->width) {
     305                 :          0 :                                         *dst++ = *src & 0x0f;
     306                 :          0 :                                         j++;
     307                 :            :                                 }
     308                 :            :                         }
     309                 :            :                 break;
     310                 :            :         case 1:
     311         [ #  # ]:          0 :                 for (i = 0; i < logo->height; i++) {
     312         [ #  # ]:          0 :                         for (j = 0; j < logo->width; src++) {
     313                 :          0 :                                 d = *src ^ xor;
     314   [ #  #  #  # ]:          0 :                                 for (k = 7; k >= 0 && j < logo->width; k--) {
     315         [ #  # ]:          0 :                                         *dst++ = ((d >> k) & 1) ? fg : 0;
     316                 :          0 :                                         j++;
     317                 :            :                                 }
     318                 :            :                         }
     319                 :            :                 }
     320                 :            :                 break;
     321                 :            :         }
     322                 :          0 : }
     323                 :            : 
     324                 :            : /*
     325                 :            :  * Three (3) kinds of logo maps exist.  linux_logo_clut224 (>16 colors),
     326                 :            :  * linux_logo_vga16 (16 colors) and linux_logo_mono (2 colors).  Depending on
     327                 :            :  * the visual format and color depth of the framebuffer, the DAC, the
     328                 :            :  * pseudo_palette, and the logo data will be adjusted accordingly.
     329                 :            :  *
     330                 :            :  * Case 1 - linux_logo_clut224:
     331                 :            :  * Color exceeds the number of console colors (16), thus we set the hardware DAC
     332                 :            :  * using fb_set_cmap() appropriately.  The "needs_cmapreset"  flag will be set.
     333                 :            :  *
     334                 :            :  * For visuals that require color info from the pseudo_palette, we also construct
     335                 :            :  * one for temporary use. The "needs_directpalette" or "needs_truepalette" flags
     336                 :            :  * will be set.
     337                 :            :  *
     338                 :            :  * Case 2 - linux_logo_vga16:
     339                 :            :  * The number of colors just matches the console colors, thus there is no need
     340                 :            :  * to set the DAC or the pseudo_palette.  However, the bitmap is packed, ie,
     341                 :            :  * each byte contains color information for two pixels (upper and lower nibble).
     342                 :            :  * To be consistent with fb_imageblit() usage, we therefore separate the two
     343                 :            :  * nibbles into separate bytes. The "depth" flag will be set to 4.
     344                 :            :  *
     345                 :            :  * Case 3 - linux_logo_mono:
     346                 :            :  * This is similar with Case 2.  Each byte contains information for 8 pixels.
     347                 :            :  * We isolate each bit and expand each into a byte. The "depth" flag will
     348                 :            :  * be set to 1.
     349                 :            :  */
     350                 :            : static struct logo_data {
     351                 :            :         int depth;
     352                 :            :         int needs_directpalette;
     353                 :            :         int needs_truepalette;
     354                 :            :         int needs_cmapreset;
     355                 :            :         const struct linux_logo *logo;
     356                 :            : } fb_logo __read_mostly;
     357                 :            : 
     358                 :            : static void fb_rotate_logo_ud(const u8 *in, u8 *out, u32 width, u32 height)
     359                 :            : {
     360                 :            :         u32 size = width * height, i;
     361                 :            : 
     362                 :            :         out += size - 1;
     363                 :            : 
     364                 :            :         for (i = size; i--; )
     365                 :            :                 *out-- = *in++;
     366                 :            : }
     367                 :            : 
     368                 :            : static void fb_rotate_logo_cw(const u8 *in, u8 *out, u32 width, u32 height)
     369                 :            : {
     370                 :            :         int i, j, h = height - 1;
     371                 :            : 
     372                 :            :         for (i = 0; i < height; i++)
     373                 :            :                 for (j = 0; j < width; j++)
     374                 :            :                                 out[height * j + h - i] = *in++;
     375                 :            : }
     376                 :            : 
     377                 :            : static void fb_rotate_logo_ccw(const u8 *in, u8 *out, u32 width, u32 height)
     378                 :            : {
     379                 :            :         int i, j, w = width - 1;
     380                 :            : 
     381                 :            :         for (i = 0; i < height; i++)
     382                 :            :                 for (j = 0; j < width; j++)
     383                 :            :                         out[height * (w - j) + i] = *in++;
     384                 :            : }
     385                 :            : 
     386                 :            : static void fb_rotate_logo(struct fb_info *info, u8 *dst,
     387                 :            :                            struct fb_image *image, int rotate)
     388                 :            : {
     389                 :            :         u32 tmp;
     390                 :            : 
     391                 :            :         if (rotate == FB_ROTATE_UD) {
     392                 :            :                 fb_rotate_logo_ud(image->data, dst, image->width,
     393                 :            :                                   image->height);
     394                 :            :                 image->dx = info->var.xres - image->width - image->dx;
     395                 :            :                 image->dy = info->var.yres - image->height - image->dy;
     396                 :            :         } else if (rotate == FB_ROTATE_CW) {
     397                 :            :                 fb_rotate_logo_cw(image->data, dst, image->width,
     398                 :            :                                   image->height);
     399                 :            :                 tmp = image->width;
     400                 :            :                 image->width = image->height;
     401                 :            :                 image->height = tmp;
     402                 :            :                 tmp = image->dy;
     403                 :            :                 image->dy = image->dx;
     404                 :            :                 image->dx = info->var.xres - image->width - tmp;
     405                 :            :         } else if (rotate == FB_ROTATE_CCW) {
     406                 :            :                 fb_rotate_logo_ccw(image->data, dst, image->width,
     407                 :            :                                    image->height);
     408                 :            :                 tmp = image->width;
     409                 :            :                 image->width = image->height;
     410                 :            :                 image->height = tmp;
     411                 :            :                 tmp = image->dx;
     412                 :            :                 image->dx = image->dy;
     413                 :            :                 image->dy = info->var.yres - image->height - tmp;
     414                 :            :         }
     415                 :            : 
     416                 :            :         image->data = dst;
     417                 :            : }
     418                 :            : 
     419                 :          0 : static void fb_do_show_logo(struct fb_info *info, struct fb_image *image,
     420                 :            :                             int rotate, unsigned int num)
     421                 :            : {
     422                 :          0 :         unsigned int x;
     423                 :            : 
     424   [ #  #  #  # ]:          0 :         if (image->width > info->var.xres || image->height > info->var.yres)
     425                 :            :                 return;
     426                 :            : 
     427         [ #  # ]:          0 :         if (rotate == FB_ROTATE_UR) {
     428                 :          0 :                 for (x = 0;
     429   [ #  #  #  # ]:          0 :                      x < num && image->dx + image->width <= info->var.xres;
     430                 :          0 :                      x++) {
     431                 :          0 :                         info->fbops->fb_imageblit(info, image);
     432                 :          0 :                         image->dx += image->width + 8;
     433                 :            :                 }
     434         [ #  # ]:          0 :         } else if (rotate == FB_ROTATE_UD) {
     435                 :          0 :                 u32 dx = image->dx;
     436                 :            : 
     437   [ #  #  #  # ]:          0 :                 for (x = 0; x < num && image->dx <= dx; x++) {
     438                 :          0 :                         info->fbops->fb_imageblit(info, image);
     439                 :          0 :                         image->dx -= image->width + 8;
     440                 :            :                 }
     441         [ #  # ]:          0 :         } else if (rotate == FB_ROTATE_CW) {
     442                 :          0 :                 for (x = 0;
     443   [ #  #  #  # ]:          0 :                      x < num && image->dy + image->height <= info->var.yres;
     444                 :          0 :                      x++) {
     445                 :          0 :                         info->fbops->fb_imageblit(info, image);
     446                 :          0 :                         image->dy += image->height + 8;
     447                 :            :                 }
     448         [ #  # ]:          0 :         } else if (rotate == FB_ROTATE_CCW) {
     449                 :          0 :                 u32 dy = image->dy;
     450                 :            : 
     451   [ #  #  #  # ]:          0 :                 for (x = 0; x < num && image->dy <= dy; x++) {
     452                 :          0 :                         info->fbops->fb_imageblit(info, image);
     453                 :          0 :                         image->dy -= image->height + 8;
     454                 :            :                 }
     455                 :            :         }
     456                 :            : }
     457                 :            : 
     458                 :          0 : static int fb_show_logo_line(struct fb_info *info, int rotate,
     459                 :            :                              const struct linux_logo *logo, int y,
     460                 :            :                              unsigned int n)
     461                 :            : {
     462                 :          0 :         u32 *palette = NULL, *saved_pseudo_palette = NULL;
     463                 :          0 :         unsigned char *logo_new = NULL, *logo_rotate = NULL;
     464                 :          0 :         struct fb_image image;
     465                 :            : 
     466                 :            :         /* Return if the frame buffer is not mapped or suspended */
     467   [ #  #  #  # ]:          0 :         if (logo == NULL || info->state != FBINFO_STATE_RUNNING ||
     468         [ #  # ]:          0 :             info->fbops->owner)
     469                 :            :                 return 0;
     470                 :            : 
     471                 :          0 :         image.depth = 8;
     472                 :          0 :         image.data = logo->data;
     473                 :            : 
     474         [ #  # ]:          0 :         if (fb_logo.needs_cmapreset)
     475                 :          0 :                 fb_set_logocmap(info, logo);
     476                 :            : 
     477         [ #  # ]:          0 :         if (fb_logo.needs_truepalette ||
     478         [ #  # ]:          0 :             fb_logo.needs_directpalette) {
     479                 :          0 :                 palette = kmalloc(256 * 4, GFP_KERNEL);
     480         [ #  # ]:          0 :                 if (palette == NULL)
     481                 :            :                         return 0;
     482                 :            : 
     483         [ #  # ]:          0 :                 if (fb_logo.needs_truepalette)
     484                 :          0 :                         fb_set_logo_truepalette(info, logo, palette);
     485                 :            :                 else
     486                 :          0 :                         fb_set_logo_directpalette(info, logo, palette);
     487                 :            : 
     488                 :          0 :                 saved_pseudo_palette = info->pseudo_palette;
     489                 :          0 :                 info->pseudo_palette = palette;
     490                 :            :         }
     491                 :            : 
     492         [ #  # ]:          0 :         if (fb_logo.depth <= 4) {
     493                 :          0 :                 logo_new = kmalloc_array(logo->width, logo->height,
     494                 :            :                                          GFP_KERNEL);
     495         [ #  # ]:          0 :                 if (logo_new == NULL) {
     496                 :          0 :                         kfree(palette);
     497         [ #  # ]:          0 :                         if (saved_pseudo_palette)
     498                 :          0 :                                 info->pseudo_palette = saved_pseudo_palette;
     499                 :          0 :                         return 0;
     500                 :            :                 }
     501                 :          0 :                 image.data = logo_new;
     502                 :          0 :                 fb_set_logo(info, logo, logo_new, fb_logo.depth);
     503                 :            :         }
     504                 :            : 
     505         [ #  # ]:          0 :         if (fb_center_logo) {
     506                 :          0 :                 int xres = info->var.xres;
     507                 :          0 :                 int yres = info->var.yres;
     508                 :            : 
     509         [ #  # ]:          0 :                 if (rotate == FB_ROTATE_CW || rotate == FB_ROTATE_CCW) {
     510                 :          0 :                         xres = info->var.yres;
     511                 :          0 :                         yres = info->var.xres;
     512                 :            :                 }
     513                 :            : 
     514   [ #  #  #  # ]:          0 :                 while (n && (n * (logo->width + 8) - 8 > xres))
     515                 :          0 :                         --n;
     516                 :          0 :                 image.dx = (xres - n * (logo->width + 8) - 8) / 2;
     517         [ #  # ]:          0 :                 image.dy = y ?: (yres - logo->height) / 2;
     518                 :            :         } else {
     519                 :          0 :                 image.dx = 0;
     520                 :          0 :                 image.dy = y;
     521                 :            :         }
     522                 :            : 
     523                 :          0 :         image.width = logo->width;
     524                 :          0 :         image.height = logo->height;
     525                 :            : 
     526         [ #  # ]:          0 :         if (rotate) {
     527                 :          0 :                 logo_rotate = kmalloc_array(logo->width, logo->height,
     528                 :            :                                             GFP_KERNEL);
     529         [ #  # ]:          0 :                 if (logo_rotate)
     530                 :          0 :                         fb_rotate_logo(info, logo_rotate, &image, rotate);
     531                 :            :         }
     532                 :            : 
     533                 :          0 :         fb_do_show_logo(info, &image, rotate, n);
     534                 :            : 
     535                 :          0 :         kfree(palette);
     536         [ #  # ]:          0 :         if (saved_pseudo_palette != NULL)
     537                 :          0 :                 info->pseudo_palette = saved_pseudo_palette;
     538                 :          0 :         kfree(logo_new);
     539                 :          0 :         kfree(logo_rotate);
     540                 :          0 :         return image.dy + logo->height;
     541                 :            : }
     542                 :            : 
     543                 :            : 
     544                 :            : #ifdef CONFIG_FB_LOGO_EXTRA
     545                 :            : 
     546                 :            : #define FB_LOGO_EX_NUM_MAX 10
     547                 :            : static struct logo_data_extra {
     548                 :            :         const struct linux_logo *logo;
     549                 :            :         unsigned int n;
     550                 :            : } fb_logo_ex[FB_LOGO_EX_NUM_MAX];
     551                 :            : static unsigned int fb_logo_ex_num;
     552                 :            : 
     553                 :            : void fb_append_extra_logo(const struct linux_logo *logo, unsigned int n)
     554                 :            : {
     555                 :            :         if (!n || fb_logo_ex_num == FB_LOGO_EX_NUM_MAX)
     556                 :            :                 return;
     557                 :            : 
     558                 :            :         fb_logo_ex[fb_logo_ex_num].logo = logo;
     559                 :            :         fb_logo_ex[fb_logo_ex_num].n = n;
     560                 :            :         fb_logo_ex_num++;
     561                 :            : }
     562                 :            : 
     563                 :            : static int fb_prepare_extra_logos(struct fb_info *info, unsigned int height,
     564                 :            :                                   unsigned int yres)
     565                 :            : {
     566                 :            :         unsigned int i;
     567                 :            : 
     568                 :            :         /* FIXME: logo_ex supports only truecolor fb. */
     569                 :            :         if (info->fix.visual != FB_VISUAL_TRUECOLOR)
     570                 :            :                 fb_logo_ex_num = 0;
     571                 :            : 
     572                 :            :         for (i = 0; i < fb_logo_ex_num; i++) {
     573                 :            :                 if (fb_logo_ex[i].logo->type != fb_logo.logo->type) {
     574                 :            :                         fb_logo_ex[i].logo = NULL;
     575                 :            :                         continue;
     576                 :            :                 }
     577                 :            :                 height += fb_logo_ex[i].logo->height;
     578                 :            :                 if (height > yres) {
     579                 :            :                         height -= fb_logo_ex[i].logo->height;
     580                 :            :                         fb_logo_ex_num = i;
     581                 :            :                         break;
     582                 :            :                 }
     583                 :            :         }
     584                 :            :         return height;
     585                 :            : }
     586                 :            : 
     587                 :            : static int fb_show_extra_logos(struct fb_info *info, int y, int rotate)
     588                 :            : {
     589                 :            :         unsigned int i;
     590                 :            : 
     591                 :            :         for (i = 0; i < fb_logo_ex_num; i++)
     592                 :            :                 y = fb_show_logo_line(info, rotate,
     593                 :            :                                       fb_logo_ex[i].logo, y, fb_logo_ex[i].n);
     594                 :            : 
     595                 :            :         return y;
     596                 :            : }
     597                 :            : 
     598                 :            : #else /* !CONFIG_FB_LOGO_EXTRA */
     599                 :            : 
     600                 :          0 : static inline int fb_prepare_extra_logos(struct fb_info *info,
     601                 :            :                                          unsigned int height,
     602                 :            :                                          unsigned int yres)
     603                 :            : {
     604                 :          0 :         return height;
     605                 :            : }
     606                 :            : 
     607                 :          0 : static inline int fb_show_extra_logos(struct fb_info *info, int y, int rotate)
     608                 :            : {
     609                 :          0 :         return y;
     610                 :            : }
     611                 :            : 
     612                 :            : #endif /* CONFIG_FB_LOGO_EXTRA */
     613                 :            : 
     614                 :            : 
     615                 :          0 : int fb_prepare_logo(struct fb_info *info, int rotate)
     616                 :            : {
     617         [ #  # ]:          0 :         int depth = fb_get_color_depth(&info->var, &info->fix);
     618                 :          0 :         unsigned int yres;
     619                 :          0 :         int height;
     620                 :            : 
     621                 :          0 :         memset(&fb_logo, 0, sizeof(struct logo_data));
     622                 :            : 
     623         [ #  # ]:          0 :         if (info->flags & FBINFO_MISC_TILEBLITTING ||
     624   [ #  #  #  # ]:          0 :             info->fbops->owner || !fb_logo_count)
     625                 :            :                 return 0;
     626                 :            : 
     627         [ #  # ]:          0 :         if (info->fix.visual == FB_VISUAL_DIRECTCOLOR) {
     628                 :          0 :                 depth = info->var.blue.length;
     629                 :          0 :                 if (info->var.red.length < depth)
     630                 :            :                         depth = info->var.red.length;
     631         [ #  # ]:          0 :                 if (info->var.green.length < depth)
     632                 :          0 :                         depth = info->var.green.length;
     633                 :            :         }
     634                 :            : 
     635         [ #  # ]:          0 :         if (info->fix.visual == FB_VISUAL_STATIC_PSEUDOCOLOR && depth > 4) {
     636                 :            :                 /* assume console colormap */
     637                 :            :                 depth = 4;
     638                 :            :         }
     639                 :            : 
     640                 :            :         /* Return if no suitable logo was found */
     641                 :          0 :         fb_logo.logo = fb_find_logo(depth);
     642                 :            : 
     643         [ #  # ]:          0 :         if (!fb_logo.logo) {
     644                 :            :                 return 0;
     645                 :            :         }
     646                 :            : 
     647         [ #  # ]:          0 :         if (rotate == FB_ROTATE_UR || rotate == FB_ROTATE_UD)
     648                 :          0 :                 yres = info->var.yres;
     649                 :            :         else
     650                 :          0 :                 yres = info->var.xres;
     651                 :            : 
     652         [ #  # ]:          0 :         if (fb_logo.logo->height > yres) {
     653                 :          0 :                 fb_logo.logo = NULL;
     654                 :          0 :                 return 0;
     655                 :            :         }
     656                 :            : 
     657                 :            :         /* What depth we asked for might be different from what we get */
     658         [ #  # ]:          0 :         if (fb_logo.logo->type == LINUX_LOGO_CLUT224)
     659                 :          0 :                 fb_logo.depth = 8;
     660         [ #  # ]:          0 :         else if (fb_logo.logo->type == LINUX_LOGO_VGA16)
     661                 :          0 :                 fb_logo.depth = 4;
     662                 :            :         else
     663                 :          0 :                 fb_logo.depth = 1;
     664                 :            : 
     665                 :            : 
     666   [ #  #  #  # ]:          0 :         if (fb_logo.depth > 4 && depth > 4) {
     667   [ #  #  #  # ]:          0 :                 switch (info->fix.visual) {
     668                 :          0 :                 case FB_VISUAL_TRUECOLOR:
     669                 :          0 :                         fb_logo.needs_truepalette = 1;
     670                 :          0 :                         break;
     671                 :          0 :                 case FB_VISUAL_DIRECTCOLOR:
     672                 :          0 :                         fb_logo.needs_directpalette = 1;
     673                 :          0 :                         fb_logo.needs_cmapreset = 1;
     674                 :          0 :                         break;
     675                 :          0 :                 case FB_VISUAL_PSEUDOCOLOR:
     676                 :          0 :                         fb_logo.needs_cmapreset = 1;
     677                 :          0 :                         break;
     678                 :            :                 }
     679                 :          0 :         }
     680                 :            : 
     681                 :          0 :         height = fb_logo.logo->height;
     682         [ #  # ]:          0 :         if (fb_center_logo)
     683                 :          0 :                 height += (yres - fb_logo.logo->height) / 2;
     684                 :            : 
     685                 :          0 :         return fb_prepare_extra_logos(info, height, yres);
     686                 :            : }
     687                 :            : 
     688                 :          0 : int fb_show_logo(struct fb_info *info, int rotate)
     689                 :            : {
     690                 :          0 :         unsigned int count;
     691                 :          0 :         int y;
     692                 :            : 
     693         [ #  # ]:          0 :         if (!fb_logo_count)
     694                 :            :                 return 0;
     695                 :            : 
     696         [ #  # ]:          0 :         count = fb_logo_count < 0 ? num_online_cpus() : fb_logo_count;
     697                 :          0 :         y = fb_show_logo_line(info, rotate, fb_logo.logo, 0, count);
     698                 :          0 :         y = fb_show_extra_logos(info, y, rotate);
     699                 :            : 
     700                 :          0 :         return y;
     701                 :            : }
     702                 :            : #else
     703                 :            : int fb_prepare_logo(struct fb_info *info, int rotate) { return 0; }
     704                 :            : int fb_show_logo(struct fb_info *info, int rotate) { return 0; }
     705                 :            : #endif /* CONFIG_LOGO */
     706                 :            : EXPORT_SYMBOL(fb_prepare_logo);
     707                 :            : EXPORT_SYMBOL(fb_show_logo);
     708                 :            : 
     709                 :          0 : static void *fb_seq_start(struct seq_file *m, loff_t *pos)
     710                 :            : {
     711                 :          0 :         mutex_lock(&registration_lock);
     712         [ #  # ]:          0 :         return (*pos < FB_MAX) ? pos : NULL;
     713                 :            : }
     714                 :            : 
     715                 :          0 : static void *fb_seq_next(struct seq_file *m, void *v, loff_t *pos)
     716                 :            : {
     717                 :          0 :         (*pos)++;
     718         [ #  # ]:          0 :         return (*pos < FB_MAX) ? pos : NULL;
     719                 :            : }
     720                 :            : 
     721                 :          0 : static void fb_seq_stop(struct seq_file *m, void *v)
     722                 :            : {
     723                 :          0 :         mutex_unlock(&registration_lock);
     724                 :          0 : }
     725                 :            : 
     726                 :          0 : static int fb_seq_show(struct seq_file *m, void *v)
     727                 :            : {
     728                 :          0 :         int i = *(loff_t *)v;
     729                 :          0 :         struct fb_info *fi = registered_fb[i];
     730                 :            : 
     731         [ #  # ]:          0 :         if (fi)
     732                 :          0 :                 seq_printf(m, "%d %s\n", fi->node, fi->fix.id);
     733                 :          0 :         return 0;
     734                 :            : }
     735                 :            : 
     736                 :            : static const struct seq_operations proc_fb_seq_ops = {
     737                 :            :         .start  = fb_seq_start,
     738                 :            :         .next   = fb_seq_next,
     739                 :            :         .stop   = fb_seq_stop,
     740                 :            :         .show   = fb_seq_show,
     741                 :            : };
     742                 :            : 
     743                 :            : /*
     744                 :            :  * We hold a reference to the fb_info in file->private_data,
     745                 :            :  * but if the current registered fb has changed, we don't
     746                 :            :  * actually want to use it.
     747                 :            :  *
     748                 :            :  * So look up the fb_info using the inode minor number,
     749                 :            :  * and just verify it against the reference we have.
     750                 :            :  */
     751                 :          0 : static struct fb_info *file_fb_info(struct file *file)
     752                 :            : {
     753                 :          0 :         struct inode *inode = file_inode(file);
     754   [ #  #  #  #  :          0 :         int fbidx = iminor(inode);
          #  #  #  #  #  
                      # ]
     755                 :          0 :         struct fb_info *info = registered_fb[fbidx];
     756                 :            : 
     757   [ #  #  #  #  :          0 :         if (info != file->private_data)
          #  #  #  #  #  
                      # ]
     758                 :            :                 info = NULL;
     759                 :          0 :         return info;
     760                 :            : }
     761                 :            : 
     762                 :            : static ssize_t
     763                 :          0 : fb_read(struct file *file, char __user *buf, size_t count, loff_t *ppos)
     764                 :            : {
     765                 :          0 :         unsigned long p = *ppos;
     766         [ #  # ]:          0 :         struct fb_info *info = file_fb_info(file);
     767                 :          0 :         u8 *buffer, *dst;
     768                 :          0 :         u8 __iomem *src;
     769                 :          0 :         int c, cnt = 0, err = 0;
     770                 :          0 :         unsigned long total_size;
     771                 :            : 
     772   [ #  #  #  # ]:          0 :         if (!info || ! info->screen_base)
     773                 :            :                 return -ENODEV;
     774                 :            : 
     775         [ #  # ]:          0 :         if (info->state != FBINFO_STATE_RUNNING)
     776                 :            :                 return -EPERM;
     777                 :            : 
     778         [ #  # ]:          0 :         if (info->fbops->fb_read)
     779                 :          0 :                 return info->fbops->fb_read(info, buf, count, ppos);
     780                 :            :         
     781                 :          0 :         total_size = info->screen_size;
     782                 :            : 
     783         [ #  # ]:          0 :         if (total_size == 0)
     784                 :          0 :                 total_size = info->fix.smem_len;
     785                 :            : 
     786         [ #  # ]:          0 :         if (p >= total_size)
     787                 :            :                 return 0;
     788                 :            : 
     789                 :          0 :         if (count >= total_size)
     790                 :            :                 count = total_size;
     791                 :            : 
     792         [ #  # ]:          0 :         if (count + p > total_size)
     793                 :          0 :                 count = total_size - p;
     794                 :            : 
     795         [ #  # ]:          0 :         buffer = kmalloc((count > PAGE_SIZE) ? PAGE_SIZE : count,
     796                 :            :                          GFP_KERNEL);
     797         [ #  # ]:          0 :         if (!buffer)
     798                 :            :                 return -ENOMEM;
     799                 :            : 
     800                 :          0 :         src = (u8 __iomem *) (info->screen_base + p);
     801                 :            : 
     802         [ #  # ]:          0 :         if (info->fbops->fb_sync)
     803                 :          0 :                 info->fbops->fb_sync(info);
     804                 :            : 
     805         [ #  # ]:          0 :         while (count) {
     806                 :          0 :                 c  = (count > PAGE_SIZE) ? PAGE_SIZE : count;
     807                 :          0 :                 dst = buffer;
     808                 :          0 :                 fb_memcpy_fromfb(dst, src, c);
     809                 :          0 :                 dst += c;
     810                 :          0 :                 src += c;
     811                 :            : 
     812   [ #  #  #  # ]:          0 :                 if (copy_to_user(buf, buffer, c)) {
     813                 :            :                         err = -EFAULT;
     814                 :            :                         break;
     815                 :            :                 }
     816                 :          0 :                 *ppos += c;
     817                 :          0 :                 buf += c;
     818                 :          0 :                 cnt += c;
     819                 :          0 :                 count -= c;
     820                 :            :         }
     821                 :            : 
     822                 :          0 :         kfree(buffer);
     823                 :            : 
     824         [ #  # ]:          0 :         return (err) ? err : cnt;
     825                 :            : }
     826                 :            : 
     827                 :            : static ssize_t
     828                 :          0 : fb_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos)
     829                 :            : {
     830                 :          0 :         unsigned long p = *ppos;
     831         [ #  # ]:          0 :         struct fb_info *info = file_fb_info(file);
     832                 :          0 :         u8 *buffer, *src;
     833                 :          0 :         u8 __iomem *dst;
     834                 :          0 :         int c, cnt = 0, err = 0;
     835                 :          0 :         unsigned long total_size;
     836                 :            : 
     837   [ #  #  #  # ]:          0 :         if (!info || !info->screen_base)
     838                 :            :                 return -ENODEV;
     839                 :            : 
     840         [ #  # ]:          0 :         if (info->state != FBINFO_STATE_RUNNING)
     841                 :            :                 return -EPERM;
     842                 :            : 
     843         [ #  # ]:          0 :         if (info->fbops->fb_write)
     844                 :          0 :                 return info->fbops->fb_write(info, buf, count, ppos);
     845                 :            :         
     846                 :          0 :         total_size = info->screen_size;
     847                 :            : 
     848         [ #  # ]:          0 :         if (total_size == 0)
     849                 :          0 :                 total_size = info->fix.smem_len;
     850                 :            : 
     851         [ #  # ]:          0 :         if (p > total_size)
     852                 :            :                 return -EFBIG;
     853                 :            : 
     854         [ #  # ]:          0 :         if (count > total_size) {
     855                 :          0 :                 err = -EFBIG;
     856                 :          0 :                 count = total_size;
     857                 :            :         }
     858                 :            : 
     859         [ #  # ]:          0 :         if (count + p > total_size) {
     860         [ #  # ]:          0 :                 if (!err)
     861                 :          0 :                         err = -ENOSPC;
     862                 :            : 
     863                 :          0 :                 count = total_size - p;
     864                 :            :         }
     865                 :            : 
     866         [ #  # ]:          0 :         buffer = kmalloc((count > PAGE_SIZE) ? PAGE_SIZE : count,
     867                 :            :                          GFP_KERNEL);
     868         [ #  # ]:          0 :         if (!buffer)
     869                 :            :                 return -ENOMEM;
     870                 :            : 
     871                 :          0 :         dst = (u8 __iomem *) (info->screen_base + p);
     872                 :            : 
     873         [ #  # ]:          0 :         if (info->fbops->fb_sync)
     874                 :          0 :                 info->fbops->fb_sync(info);
     875                 :            : 
     876         [ #  # ]:          0 :         while (count) {
     877                 :          0 :                 c = (count > PAGE_SIZE) ? PAGE_SIZE : count;
     878                 :          0 :                 src = buffer;
     879                 :            : 
     880   [ #  #  #  # ]:          0 :                 if (copy_from_user(src, buf, c)) {
     881                 :            :                         err = -EFAULT;
     882                 :            :                         break;
     883                 :            :                 }
     884                 :            : 
     885                 :          0 :                 fb_memcpy_tofb(dst, src, c);
     886                 :          0 :                 dst += c;
     887                 :          0 :                 src += c;
     888                 :          0 :                 *ppos += c;
     889                 :          0 :                 buf += c;
     890                 :          0 :                 cnt += c;
     891                 :          0 :                 count -= c;
     892                 :            :         }
     893                 :            : 
     894                 :          0 :         kfree(buffer);
     895                 :            : 
     896         [ #  # ]:          0 :         return (cnt) ? cnt : err;
     897                 :            : }
     898                 :            : 
     899                 :            : int
     900                 :          0 : fb_pan_display(struct fb_info *info, struct fb_var_screeninfo *var)
     901                 :            : {
     902                 :          0 :         struct fb_fix_screeninfo *fix = &info->fix;
     903                 :          0 :         unsigned int yres = info->var.yres;
     904                 :          0 :         int err = 0;
     905                 :            : 
     906         [ #  # ]:          0 :         if (var->yoffset > 0) {
     907         [ #  # ]:          0 :                 if (var->vmode & FB_VMODE_YWRAP) {
     908   [ #  #  #  # ]:          0 :                         if (!fix->ywrapstep || (var->yoffset % fix->ywrapstep))
     909                 :            :                                 err = -EINVAL;
     910                 :            :                         else
     911                 :          0 :                                 yres = 0;
     912   [ #  #  #  # ]:          0 :                 } else if (!fix->ypanstep || (var->yoffset % fix->ypanstep))
     913                 :          0 :                         err = -EINVAL;
     914                 :            :         }
     915                 :            : 
     916   [ #  #  #  # ]:          0 :         if (var->xoffset > 0 && (!fix->xpanstep ||
     917         [ #  # ]:          0 :                                  (var->xoffset % fix->xpanstep)))
     918                 :            :                 err = -EINVAL;
     919                 :            : 
     920   [ #  #  #  # ]:          0 :         if (err || !info->fbops->fb_pan_display ||
     921         [ #  # ]:          0 :             var->yoffset > info->var.yres_virtual - yres ||
     922         [ #  # ]:          0 :             var->xoffset > info->var.xres_virtual - info->var.xres)
     923                 :            :                 return -EINVAL;
     924                 :            : 
     925         [ #  # ]:          0 :         if ((err = info->fbops->fb_pan_display(var, info)))
     926                 :            :                 return err;
     927                 :          0 :         info->var.xoffset = var->xoffset;
     928                 :          0 :         info->var.yoffset = var->yoffset;
     929         [ #  # ]:          0 :         if (var->vmode & FB_VMODE_YWRAP)
     930                 :          0 :                 info->var.vmode |= FB_VMODE_YWRAP;
     931                 :            :         else
     932                 :          0 :                 info->var.vmode &= ~FB_VMODE_YWRAP;
     933                 :            :         return 0;
     934                 :            : }
     935                 :            : EXPORT_SYMBOL(fb_pan_display);
     936                 :            : 
     937                 :          0 : static int fb_check_caps(struct fb_info *info, struct fb_var_screeninfo *var,
     938                 :            :                          u32 activate)
     939                 :            : {
     940                 :          0 :         struct fb_blit_caps caps, fbcaps;
     941                 :          0 :         int err = 0;
     942                 :            : 
     943                 :          0 :         memset(&caps, 0, sizeof(caps));
     944                 :          0 :         memset(&fbcaps, 0, sizeof(fbcaps));
     945                 :          0 :         caps.flags = (activate & FB_ACTIVATE_ALL) ? 1 : 0;
     946                 :          0 :         fbcon_get_requirement(info, &caps);
     947                 :          0 :         info->fbops->fb_get_caps(info, &fbcaps, var);
     948                 :            : 
     949         [ #  # ]:          0 :         if (((fbcaps.x ^ caps.x) & caps.x) ||
     950         [ #  # ]:          0 :             ((fbcaps.y ^ caps.y) & caps.y) ||
     951         [ #  # ]:          0 :             (fbcaps.len < caps.len))
     952                 :          0 :                 err = -EINVAL;
     953                 :            : 
     954                 :          0 :         return err;
     955                 :            : }
     956                 :            : 
     957                 :            : int
     958                 :          0 : fb_set_var(struct fb_info *info, struct fb_var_screeninfo *var)
     959                 :            : {
     960                 :          0 :         int flags = info->flags;
     961                 :          0 :         int ret = 0;
     962                 :          0 :         u32 activate;
     963                 :          0 :         struct fb_var_screeninfo old_var;
     964                 :          0 :         struct fb_videomode mode;
     965                 :          0 :         struct fb_event event;
     966                 :            : 
     967         [ #  # ]:          0 :         if (var->activate & FB_ACTIVATE_INV_MODE) {
     968                 :          0 :                 struct fb_videomode mode1, mode2;
     969                 :            : 
     970                 :          0 :                 fb_var_to_videomode(&mode1, var);
     971                 :          0 :                 fb_var_to_videomode(&mode2, &info->var);
     972                 :            :                 /* make sure we don't delete the videomode of current var */
     973                 :          0 :                 ret = fb_mode_is_equal(&mode1, &mode2);
     974                 :            : 
     975         [ #  # ]:          0 :                 if (!ret)
     976                 :          0 :                         fbcon_mode_deleted(info, &mode1);
     977                 :            : 
     978         [ #  # ]:          0 :                 if (!ret)
     979                 :          0 :                         fb_delete_videomode(&mode1, &info->modelist);
     980                 :            : 
     981                 :            : 
     982         [ #  # ]:          0 :                 return ret ? -EINVAL : 0;
     983                 :            :         }
     984                 :            : 
     985         [ #  # ]:          0 :         if (!(var->activate & FB_ACTIVATE_FORCE) &&
     986         [ #  # ]:          0 :             !memcmp(&info->var, var, sizeof(struct fb_var_screeninfo)))
     987                 :            :                 return 0;
     988                 :            : 
     989                 :          0 :         activate = var->activate;
     990                 :            : 
     991                 :            :         /* When using FOURCC mode, make sure the red, green, blue and
     992                 :            :          * transp fields are set to 0.
     993                 :            :          */
     994         [ #  # ]:          0 :         if ((info->fix.capabilities & FB_CAP_FOURCC) &&
     995         [ #  # ]:          0 :             var->grayscale > 1) {
     996   [ #  #  #  # ]:          0 :                 if (var->red.offset     || var->green.offset    ||
     997   [ #  #  #  # ]:          0 :                     var->blue.offset    || var->transp.offset   ||
     998   [ #  #  #  # ]:          0 :                     var->red.length     || var->green.length    ||
     999   [ #  #  #  # ]:          0 :                     var->blue.length    || var->transp.length   ||
    1000   [ #  #  #  # ]:          0 :                     var->red.msb_right  || var->green.msb_right ||
    1001   [ #  #  #  # ]:          0 :                     var->blue.msb_right || var->transp.msb_right)
    1002                 :            :                         return -EINVAL;
    1003                 :            :         }
    1004                 :            : 
    1005         [ #  # ]:          0 :         if (!info->fbops->fb_check_var) {
    1006                 :          0 :                 *var = info->var;
    1007                 :          0 :                 return 0;
    1008                 :            :         }
    1009                 :            : 
    1010                 :          0 :         ret = info->fbops->fb_check_var(var, info);
    1011                 :            : 
    1012         [ #  # ]:          0 :         if (ret)
    1013                 :            :                 return ret;
    1014                 :            : 
    1015         [ #  # ]:          0 :         if ((var->activate & FB_ACTIVATE_MASK) != FB_ACTIVATE_NOW)
    1016                 :            :                 return 0;
    1017                 :            : 
    1018         [ #  # ]:          0 :         if (info->fbops->fb_get_caps) {
    1019                 :          0 :                 ret = fb_check_caps(info, var, activate);
    1020                 :            : 
    1021         [ #  # ]:          0 :                 if (ret)
    1022                 :            :                         return ret;
    1023                 :            :         }
    1024                 :            : 
    1025                 :          0 :         old_var = info->var;
    1026                 :          0 :         info->var = *var;
    1027                 :            : 
    1028         [ #  # ]:          0 :         if (info->fbops->fb_set_par) {
    1029                 :          0 :                 ret = info->fbops->fb_set_par(info);
    1030                 :            : 
    1031         [ #  # ]:          0 :                 if (ret) {
    1032                 :          0 :                         info->var = old_var;
    1033                 :          0 :                         printk(KERN_WARNING "detected "
    1034                 :            :                                 "fb_set_par error, "
    1035                 :            :                                 "error code: %d\n", ret);
    1036                 :          0 :                         return ret;
    1037                 :            :                 }
    1038                 :            :         }
    1039                 :            : 
    1040                 :          0 :         fb_pan_display(info, &info->var);
    1041                 :          0 :         fb_set_cmap(&info->cmap, info);
    1042                 :          0 :         fb_var_to_videomode(&mode, &info->var);
    1043                 :            : 
    1044   [ #  #  #  #  :          0 :         if (info->modelist.prev && info->modelist.next &&
                   #  # ]
    1045         [ #  # ]:          0 :             !list_empty(&info->modelist))
    1046                 :          0 :                 ret = fb_add_videomode(&mode, &info->modelist);
    1047                 :            : 
    1048         [ #  # ]:          0 :         if (ret)
    1049                 :            :                 return ret;
    1050                 :            : 
    1051                 :          0 :         event.info = info;
    1052                 :          0 :         event.data = &mode;
    1053                 :          0 :         fb_notifier_call_chain(FB_EVENT_MODE_CHANGE, &event);
    1054                 :            : 
    1055         [ #  # ]:          0 :         if (flags & FBINFO_MISC_USEREVENT)
    1056                 :          0 :                 fbcon_update_vcs(info, activate & FB_ACTIVATE_ALL);
    1057                 :            : 
    1058                 :            :         return 0;
    1059                 :            : }
    1060                 :            : EXPORT_SYMBOL(fb_set_var);
    1061                 :            : 
    1062                 :            : int
    1063                 :          0 : fb_blank(struct fb_info *info, int blank)
    1064                 :            : {       
    1065                 :          0 :         struct fb_event event;
    1066                 :          0 :         int ret = -EINVAL;
    1067                 :            : 
    1068         [ #  # ]:          0 :         if (blank > FB_BLANK_POWERDOWN)
    1069                 :          0 :                 blank = FB_BLANK_POWERDOWN;
    1070                 :            : 
    1071                 :          0 :         event.info = info;
    1072                 :          0 :         event.data = &blank;
    1073                 :            : 
    1074         [ #  # ]:          0 :         if (info->fbops->fb_blank)
    1075                 :          0 :                 ret = info->fbops->fb_blank(blank, info);
    1076                 :            : 
    1077         [ #  # ]:          0 :         if (!ret)
    1078                 :          0 :                 fb_notifier_call_chain(FB_EVENT_BLANK, &event);
    1079                 :            : 
    1080                 :          0 :         return ret;
    1081                 :            : }
    1082                 :            : EXPORT_SYMBOL(fb_blank);
    1083                 :            : 
    1084                 :          0 : static long do_fb_ioctl(struct fb_info *info, unsigned int cmd,
    1085                 :            :                         unsigned long arg)
    1086                 :            : {
    1087                 :          0 :         const struct fb_ops *fb;
    1088                 :          0 :         struct fb_var_screeninfo var;
    1089                 :          0 :         struct fb_fix_screeninfo fix;
    1090                 :          0 :         struct fb_cmap cmap_from;
    1091                 :          0 :         struct fb_cmap_user cmap;
    1092                 :          0 :         void __user *argp = (void __user *)arg;
    1093                 :          0 :         long ret = 0;
    1094                 :            : 
    1095   [ #  #  #  #  :          0 :         switch (cmd) {
          #  #  #  #  #  
                   #  # ]
    1096                 :            :         case FBIOGET_VSCREENINFO:
    1097                 :          0 :                 lock_fb_info(info);
    1098                 :          0 :                 var = info->var;
    1099                 :          0 :                 unlock_fb_info(info);
    1100                 :            : 
    1101         [ #  # ]:          0 :                 ret = copy_to_user(argp, &var, sizeof(var)) ? -EFAULT : 0;
    1102                 :            :                 break;
    1103                 :            :         case FBIOPUT_VSCREENINFO:
    1104         [ #  # ]:          0 :                 if (copy_from_user(&var, argp, sizeof(var)))
    1105                 :            :                         return -EFAULT;
    1106                 :          0 :                 console_lock();
    1107                 :          0 :                 lock_fb_info(info);
    1108                 :          0 :                 info->flags |= FBINFO_MISC_USEREVENT;
    1109                 :          0 :                 ret = fb_set_var(info, &var);
    1110                 :          0 :                 info->flags &= ~FBINFO_MISC_USEREVENT;
    1111                 :          0 :                 unlock_fb_info(info);
    1112                 :          0 :                 console_unlock();
    1113   [ #  #  #  # ]:          0 :                 if (!ret && copy_to_user(argp, &var, sizeof(var)))
    1114                 :          0 :                         ret = -EFAULT;
    1115                 :            :                 break;
    1116                 :            :         case FBIOGET_FSCREENINFO:
    1117                 :          0 :                 lock_fb_info(info);
    1118                 :          0 :                 fix = info->fix;
    1119         [ #  # ]:          0 :                 if (info->flags & FBINFO_HIDE_SMEM_START)
    1120                 :          0 :                         fix.smem_start = 0;
    1121                 :          0 :                 unlock_fb_info(info);
    1122                 :            : 
    1123         [ #  # ]:          0 :                 ret = copy_to_user(argp, &fix, sizeof(fix)) ? -EFAULT : 0;
    1124                 :            :                 break;
    1125                 :            :         case FBIOPUTCMAP:
    1126         [ #  # ]:          0 :                 if (copy_from_user(&cmap, argp, sizeof(cmap)))
    1127                 :            :                         return -EFAULT;
    1128                 :          0 :                 ret = fb_set_user_cmap(&cmap, info);
    1129                 :          0 :                 break;
    1130                 :            :         case FBIOGETCMAP:
    1131         [ #  # ]:          0 :                 if (copy_from_user(&cmap, argp, sizeof(cmap)))
    1132                 :            :                         return -EFAULT;
    1133                 :          0 :                 lock_fb_info(info);
    1134                 :          0 :                 cmap_from = info->cmap;
    1135                 :          0 :                 unlock_fb_info(info);
    1136                 :          0 :                 ret = fb_cmap_to_user(&cmap_from, &cmap);
    1137                 :          0 :                 break;
    1138                 :            :         case FBIOPAN_DISPLAY:
    1139         [ #  # ]:          0 :                 if (copy_from_user(&var, argp, sizeof(var)))
    1140                 :            :                         return -EFAULT;
    1141                 :          0 :                 console_lock();
    1142                 :          0 :                 lock_fb_info(info);
    1143                 :          0 :                 ret = fb_pan_display(info, &var);
    1144                 :          0 :                 unlock_fb_info(info);
    1145                 :          0 :                 console_unlock();
    1146   [ #  #  #  # ]:          0 :                 if (ret == 0 && copy_to_user(argp, &var, sizeof(var)))
    1147                 :          0 :                         return -EFAULT;
    1148                 :            :                 break;
    1149                 :            :         case FBIO_CURSOR:
    1150                 :            :                 ret = -EINVAL;
    1151                 :            :                 break;
    1152                 :          0 :         case FBIOGET_CON2FBMAP:
    1153                 :          0 :                 ret = fbcon_get_con2fb_map_ioctl(argp);
    1154                 :          0 :                 break;
    1155                 :          0 :         case FBIOPUT_CON2FBMAP:
    1156                 :          0 :                 ret = fbcon_set_con2fb_map_ioctl(argp);
    1157                 :          0 :                 break;
    1158                 :          0 :         case FBIOBLANK:
    1159                 :          0 :                 console_lock();
    1160                 :          0 :                 lock_fb_info(info);
    1161                 :          0 :                 ret = fb_blank(info, arg);
    1162                 :            :                 /* might again call into fb_blank */
    1163                 :          0 :                 fbcon_fb_blanked(info, arg);
    1164                 :          0 :                 unlock_fb_info(info);
    1165                 :          0 :                 console_unlock();
    1166                 :          0 :                 break;
    1167                 :            :         default:
    1168                 :          0 :                 lock_fb_info(info);
    1169                 :          0 :                 fb = info->fbops;
    1170         [ #  # ]:          0 :                 if (fb->fb_ioctl)
    1171                 :          0 :                         ret = fb->fb_ioctl(info, cmd, arg);
    1172                 :            :                 else
    1173                 :            :                         ret = -ENOTTY;
    1174                 :          0 :                 unlock_fb_info(info);
    1175                 :            :         }
    1176                 :            :         return ret;
    1177                 :            : }
    1178                 :            : 
    1179                 :          0 : static long fb_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
    1180                 :            : {
    1181         [ #  # ]:          0 :         struct fb_info *info = file_fb_info(file);
    1182                 :            : 
    1183         [ #  # ]:          0 :         if (!info)
    1184                 :            :                 return -ENODEV;
    1185                 :          0 :         return do_fb_ioctl(info, cmd, arg);
    1186                 :            : }
    1187                 :            : 
    1188                 :            : #ifdef CONFIG_COMPAT
    1189                 :            : struct fb_fix_screeninfo32 {
    1190                 :            :         char                    id[16];
    1191                 :            :         compat_caddr_t          smem_start;
    1192                 :            :         u32                     smem_len;
    1193                 :            :         u32                     type;
    1194                 :            :         u32                     type_aux;
    1195                 :            :         u32                     visual;
    1196                 :            :         u16                     xpanstep;
    1197                 :            :         u16                     ypanstep;
    1198                 :            :         u16                     ywrapstep;
    1199                 :            :         u32                     line_length;
    1200                 :            :         compat_caddr_t          mmio_start;
    1201                 :            :         u32                     mmio_len;
    1202                 :            :         u32                     accel;
    1203                 :            :         u16                     reserved[3];
    1204                 :            : };
    1205                 :            : 
    1206                 :            : struct fb_cmap32 {
    1207                 :            :         u32                     start;
    1208                 :            :         u32                     len;
    1209                 :            :         compat_caddr_t  red;
    1210                 :            :         compat_caddr_t  green;
    1211                 :            :         compat_caddr_t  blue;
    1212                 :            :         compat_caddr_t  transp;
    1213                 :            : };
    1214                 :            : 
    1215                 :          0 : static int fb_getput_cmap(struct fb_info *info, unsigned int cmd,
    1216                 :            :                           unsigned long arg)
    1217                 :            : {
    1218                 :          0 :         struct fb_cmap_user __user *cmap;
    1219                 :          0 :         struct fb_cmap32 __user *cmap32;
    1220                 :          0 :         __u32 data;
    1221                 :          0 :         int err;
    1222                 :            : 
    1223                 :          0 :         cmap = compat_alloc_user_space(sizeof(*cmap));
    1224         [ #  # ]:          0 :         cmap32 = compat_ptr(arg);
    1225                 :            : 
    1226   [ #  #  #  # ]:          0 :         if (copy_in_user(&cmap->start, &cmap32->start, 2 * sizeof(__u32)))
    1227                 :          0 :                 return -EFAULT;
    1228                 :            : 
    1229         [ #  # ]:          0 :         if (get_user(data, &cmap32->red) ||
    1230         [ #  # ]:          0 :             put_user(compat_ptr(data), &cmap->red) ||
    1231         [ #  # ]:          0 :             get_user(data, &cmap32->green) ||
    1232         [ #  # ]:          0 :             put_user(compat_ptr(data), &cmap->green) ||
    1233         [ #  # ]:          0 :             get_user(data, &cmap32->blue) ||
    1234         [ #  # ]:          0 :             put_user(compat_ptr(data), &cmap->blue) ||
    1235         [ #  # ]:          0 :             get_user(data, &cmap32->transp) ||
    1236         [ #  # ]:          0 :             put_user(compat_ptr(data), &cmap->transp))
    1237                 :          0 :                 return -EFAULT;
    1238                 :            : 
    1239                 :          0 :         err = do_fb_ioctl(info, cmd, (unsigned long) cmap);
    1240                 :            : 
    1241         [ #  # ]:          0 :         if (!err) {
    1242   [ #  #  #  # ]:          0 :                 if (copy_in_user(&cmap32->start,
    1243                 :            :                                  &cmap->start,
    1244                 :            :                                  2 * sizeof(__u32)))
    1245                 :            :                         err = -EFAULT;
    1246                 :            :         }
    1247                 :            :         return err;
    1248                 :            : }
    1249                 :            : 
    1250                 :          0 : static int do_fscreeninfo_to_user(struct fb_fix_screeninfo *fix,
    1251                 :            :                                   struct fb_fix_screeninfo32 __user *fix32)
    1252                 :            : {
    1253                 :          0 :         __u32 data;
    1254                 :          0 :         int err;
    1255                 :            : 
    1256         [ #  # ]:          0 :         err = copy_to_user(&fix32->id, &fix->id, sizeof(fix32->id));
    1257                 :            : 
    1258                 :          0 :         data = (__u32) (unsigned long) fix->smem_start;
    1259                 :          0 :         err |= put_user(data, &fix32->smem_start);
    1260                 :            : 
    1261                 :          0 :         err |= put_user(fix->smem_len, &fix32->smem_len);
    1262                 :          0 :         err |= put_user(fix->type, &fix32->type);
    1263                 :          0 :         err |= put_user(fix->type_aux, &fix32->type_aux);
    1264                 :          0 :         err |= put_user(fix->visual, &fix32->visual);
    1265                 :          0 :         err |= put_user(fix->xpanstep, &fix32->xpanstep);
    1266                 :          0 :         err |= put_user(fix->ypanstep, &fix32->ypanstep);
    1267                 :          0 :         err |= put_user(fix->ywrapstep, &fix32->ywrapstep);
    1268                 :          0 :         err |= put_user(fix->line_length, &fix32->line_length);
    1269                 :            : 
    1270                 :          0 :         data = (__u32) (unsigned long) fix->mmio_start;
    1271                 :          0 :         err |= put_user(data, &fix32->mmio_start);
    1272                 :            : 
    1273                 :          0 :         err |= put_user(fix->mmio_len, &fix32->mmio_len);
    1274                 :          0 :         err |= put_user(fix->accel, &fix32->accel);
    1275         [ #  # ]:          0 :         err |= copy_to_user(fix32->reserved, fix->reserved,
    1276                 :            :                             sizeof(fix->reserved));
    1277                 :            : 
    1278         [ #  # ]:          0 :         if (err)
    1279                 :          0 :                 return -EFAULT;
    1280                 :            :         return 0;
    1281                 :            : }
    1282                 :            : 
    1283                 :            : static int fb_get_fscreeninfo(struct fb_info *info, unsigned int cmd,
    1284                 :            :                               unsigned long arg)
    1285                 :            : {
    1286                 :            :         struct fb_fix_screeninfo fix;
    1287                 :            : 
    1288                 :            :         lock_fb_info(info);
    1289                 :            :         fix = info->fix;
    1290                 :            :         if (info->flags & FBINFO_HIDE_SMEM_START)
    1291                 :            :                 fix.smem_start = 0;
    1292                 :            :         unlock_fb_info(info);
    1293                 :            :         return do_fscreeninfo_to_user(&fix, compat_ptr(arg));
    1294                 :            : }
    1295                 :            : 
    1296                 :          0 : static long fb_compat_ioctl(struct file *file, unsigned int cmd,
    1297                 :            :                             unsigned long arg)
    1298                 :            : {
    1299         [ #  # ]:          0 :         struct fb_info *info = file_fb_info(file);
    1300                 :          0 :         const struct fb_ops *fb;
    1301                 :          0 :         long ret = -ENOIOCTLCMD;
    1302                 :            : 
    1303         [ #  # ]:          0 :         if (!info)
    1304                 :            :                 return -ENODEV;
    1305                 :          0 :         fb = info->fbops;
    1306   [ #  #  #  #  :          0 :         switch(cmd) {
                      # ]
    1307                 :          0 :         case FBIOGET_VSCREENINFO:
    1308                 :            :         case FBIOPUT_VSCREENINFO:
    1309                 :            :         case FBIOPAN_DISPLAY:
    1310                 :            :         case FBIOGET_CON2FBMAP:
    1311                 :            :         case FBIOPUT_CON2FBMAP:
    1312                 :          0 :                 arg = (unsigned long) compat_ptr(arg);
    1313                 :            :                 /* fall through */
    1314                 :          0 :         case FBIOBLANK:
    1315                 :          0 :                 ret = do_fb_ioctl(info, cmd, arg);
    1316                 :          0 :                 break;
    1317                 :            : 
    1318                 :          0 :         case FBIOGET_FSCREENINFO:
    1319                 :          0 :                 ret = fb_get_fscreeninfo(info, cmd, arg);
    1320                 :          0 :                 break;
    1321                 :            : 
    1322                 :          0 :         case FBIOGETCMAP:
    1323                 :            :         case FBIOPUTCMAP:
    1324                 :          0 :                 ret = fb_getput_cmap(info, cmd, arg);
    1325                 :          0 :                 break;
    1326                 :            : 
    1327                 :          0 :         default:
    1328         [ #  # ]:          0 :                 if (fb->fb_compat_ioctl)
    1329                 :          0 :                         ret = fb->fb_compat_ioctl(info, cmd, arg);
    1330                 :            :                 break;
    1331                 :            :         }
    1332                 :            :         return ret;
    1333                 :            : }
    1334                 :            : #endif
    1335                 :            : 
    1336                 :            : static int
    1337                 :          0 : fb_mmap(struct file *file, struct vm_area_struct * vma)
    1338                 :            : {
    1339         [ #  # ]:          0 :         struct fb_info *info = file_fb_info(file);
    1340                 :          0 :         int (*fb_mmap_fn)(struct fb_info *info, struct vm_area_struct *vma);
    1341                 :          0 :         unsigned long mmio_pgoff;
    1342                 :          0 :         unsigned long start;
    1343                 :          0 :         u32 len;
    1344                 :            : 
    1345         [ #  # ]:          0 :         if (!info)
    1346                 :            :                 return -ENODEV;
    1347                 :          0 :         mutex_lock(&info->mm_lock);
    1348                 :            : 
    1349                 :          0 :         fb_mmap_fn = info->fbops->fb_mmap;
    1350                 :            : 
    1351                 :            : #if IS_ENABLED(CONFIG_FB_DEFERRED_IO)
    1352         [ #  # ]:          0 :         if (info->fbdefio)
    1353                 :          0 :                 fb_mmap_fn = fb_deferred_io_mmap;
    1354                 :            : #endif
    1355                 :            : 
    1356         [ #  # ]:          0 :         if (fb_mmap_fn) {
    1357                 :          0 :                 int res;
    1358                 :            : 
    1359                 :            :                 /*
    1360                 :            :                  * The framebuffer needs to be accessed decrypted, be sure
    1361                 :            :                  * SME protection is removed ahead of the call
    1362                 :            :                  */
    1363                 :          0 :                 vma->vm_page_prot = pgprot_decrypted(vma->vm_page_prot);
    1364                 :          0 :                 res = fb_mmap_fn(info, vma);
    1365                 :          0 :                 mutex_unlock(&info->mm_lock);
    1366                 :          0 :                 return res;
    1367                 :            :         }
    1368                 :            : 
    1369                 :            :         /*
    1370                 :            :          * Ugh. This can be either the frame buffer mapping, or
    1371                 :            :          * if pgoff points past it, the mmio mapping.
    1372                 :            :          */
    1373                 :          0 :         start = info->fix.smem_start;
    1374                 :          0 :         len = info->fix.smem_len;
    1375                 :          0 :         mmio_pgoff = PAGE_ALIGN((start & ~PAGE_MASK) + len) >> PAGE_SHIFT;
    1376         [ #  # ]:          0 :         if (vma->vm_pgoff >= mmio_pgoff) {
    1377         [ #  # ]:          0 :                 if (info->var.accel_flags) {
    1378                 :          0 :                         mutex_unlock(&info->mm_lock);
    1379                 :          0 :                         return -EINVAL;
    1380                 :            :                 }
    1381                 :            : 
    1382                 :          0 :                 vma->vm_pgoff -= mmio_pgoff;
    1383                 :          0 :                 start = info->fix.mmio_start;
    1384                 :          0 :                 len = info->fix.mmio_len;
    1385                 :            :         }
    1386                 :          0 :         mutex_unlock(&info->mm_lock);
    1387                 :            : 
    1388                 :          0 :         vma->vm_page_prot = vm_get_page_prot(vma->vm_flags);
    1389                 :            :         /*
    1390                 :            :          * The framebuffer needs to be accessed decrypted, be sure
    1391                 :            :          * SME protection is removed
    1392                 :            :          */
    1393                 :          0 :         vma->vm_page_prot = pgprot_decrypted(vma->vm_page_prot);
    1394         [ #  # ]:          0 :         fb_pgprotect(file, vma, start);
    1395                 :            : 
    1396                 :          0 :         return vm_iomap_memory(vma, start, len);
    1397                 :            : }
    1398                 :            : 
    1399                 :            : static int
    1400                 :          0 : fb_open(struct inode *inode, struct file *file)
    1401                 :            : __acquires(&info->lock)
    1402                 :            : __releases(&info->lock)
    1403                 :            : {
    1404                 :          0 :         int fbidx = iminor(inode);
    1405                 :          0 :         struct fb_info *info;
    1406                 :          0 :         int res = 0;
    1407                 :            : 
    1408                 :          0 :         info = get_fb_info(fbidx);
    1409         [ #  # ]:          0 :         if (!info) {
    1410                 :          0 :                 request_module("fb%d", fbidx);
    1411                 :          0 :                 info = get_fb_info(fbidx);
    1412         [ #  # ]:          0 :                 if (!info)
    1413                 :            :                         return -ENODEV;
    1414                 :            :         }
    1415         [ #  # ]:          0 :         if (IS_ERR(info))
    1416                 :          0 :                 return PTR_ERR(info);
    1417                 :            : 
    1418                 :          0 :         lock_fb_info(info);
    1419         [ #  # ]:          0 :         if (!try_module_get(info->fbops->owner)) {
    1420                 :          0 :                 res = -ENODEV;
    1421                 :          0 :                 goto out;
    1422                 :            :         }
    1423                 :          0 :         file->private_data = info;
    1424         [ #  # ]:          0 :         if (info->fbops->fb_open) {
    1425                 :          0 :                 res = info->fbops->fb_open(info,1);
    1426         [ #  # ]:          0 :                 if (res)
    1427                 :          0 :                         module_put(info->fbops->owner);
    1428                 :            :         }
    1429                 :            : #ifdef CONFIG_FB_DEFERRED_IO
    1430         [ #  # ]:          0 :         if (info->fbdefio)
    1431                 :          0 :                 fb_deferred_io_open(info, inode, file);
    1432                 :            : #endif
    1433                 :          0 : out:
    1434                 :          0 :         unlock_fb_info(info);
    1435         [ #  # ]:          0 :         if (res)
    1436                 :          0 :                 put_fb_info(info);
    1437                 :            :         return res;
    1438                 :            : }
    1439                 :            : 
    1440                 :            : static int 
    1441                 :          0 : fb_release(struct inode *inode, struct file *file)
    1442                 :            : __acquires(&info->lock)
    1443                 :            : __releases(&info->lock)
    1444                 :            : {
    1445                 :          0 :         struct fb_info * const info = file->private_data;
    1446                 :            : 
    1447                 :          0 :         lock_fb_info(info);
    1448         [ #  # ]:          0 :         if (info->fbops->fb_release)
    1449                 :          0 :                 info->fbops->fb_release(info,1);
    1450                 :          0 :         module_put(info->fbops->owner);
    1451                 :          0 :         unlock_fb_info(info);
    1452                 :          0 :         put_fb_info(info);
    1453                 :          0 :         return 0;
    1454                 :            : }
    1455                 :            : 
    1456                 :            : #if defined(CONFIG_FB_PROVIDE_GET_FB_UNMAPPED_AREA) && !defined(CONFIG_MMU)
    1457                 :            : unsigned long get_fb_unmapped_area(struct file *filp,
    1458                 :            :                                    unsigned long addr, unsigned long len,
    1459                 :            :                                    unsigned long pgoff, unsigned long flags)
    1460                 :            : {
    1461                 :            :         struct fb_info * const info = filp->private_data;
    1462                 :            :         unsigned long fb_size = PAGE_ALIGN(info->fix.smem_len);
    1463                 :            : 
    1464                 :            :         if (pgoff > fb_size || len > fb_size - pgoff)
    1465                 :            :                 return -EINVAL;
    1466                 :            : 
    1467                 :            :         return (unsigned long)info->screen_base + pgoff;
    1468                 :            : }
    1469                 :            : #endif
    1470                 :            : 
    1471                 :            : static const struct file_operations fb_fops = {
    1472                 :            :         .owner =        THIS_MODULE,
    1473                 :            :         .read =         fb_read,
    1474                 :            :         .write =        fb_write,
    1475                 :            :         .unlocked_ioctl = fb_ioctl,
    1476                 :            : #ifdef CONFIG_COMPAT
    1477                 :            :         .compat_ioctl = fb_compat_ioctl,
    1478                 :            : #endif
    1479                 :            :         .mmap =         fb_mmap,
    1480                 :            :         .open =         fb_open,
    1481                 :            :         .release =      fb_release,
    1482                 :            : #if defined(HAVE_ARCH_FB_UNMAPPED_AREA) || \
    1483                 :            :         (defined(CONFIG_FB_PROVIDE_GET_FB_UNMAPPED_AREA) && \
    1484                 :            :          !defined(CONFIG_MMU))
    1485                 :            :         .get_unmapped_area = get_fb_unmapped_area,
    1486                 :            : #endif
    1487                 :            : #ifdef CONFIG_FB_DEFERRED_IO
    1488                 :            :         .fsync =        fb_deferred_io_fsync,
    1489                 :            : #endif
    1490                 :            :         .llseek =       default_llseek,
    1491                 :            : };
    1492                 :            : 
    1493                 :            : struct class *fb_class;
    1494                 :            : EXPORT_SYMBOL(fb_class);
    1495                 :            : 
    1496                 :          0 : static int fb_check_foreignness(struct fb_info *fi)
    1497                 :            : {
    1498                 :          0 :         const bool foreign_endian = fi->flags & FBINFO_FOREIGN_ENDIAN;
    1499                 :            : 
    1500                 :          0 :         fi->flags &= ~FBINFO_FOREIGN_ENDIAN;
    1501                 :            : 
    1502                 :            : #ifdef __BIG_ENDIAN
    1503                 :            :         fi->flags |= foreign_endian ? 0 : FBINFO_BE_MATH;
    1504                 :            : #else
    1505         [ #  # ]:          0 :         fi->flags |= foreign_endian ? FBINFO_BE_MATH : 0;
    1506                 :            : #endif /* __BIG_ENDIAN */
    1507                 :            : 
    1508         [ #  # ]:          0 :         if (fi->flags & FBINFO_BE_MATH && !fb_be_math(fi)) {
    1509                 :          0 :                 pr_err("%s: enable CONFIG_FB_BIG_ENDIAN to "
    1510                 :            :                        "support this framebuffer\n", fi->fix.id);
    1511                 :          0 :                 return -ENOSYS;
    1512                 :            :         } else if (!(fi->flags & FBINFO_BE_MATH) && fb_be_math(fi)) {
    1513                 :            :                 pr_err("%s: enable CONFIG_FB_LITTLE_ENDIAN to "
    1514                 :            :                        "support this framebuffer\n", fi->fix.id);
    1515                 :            :                 return -ENOSYS;
    1516                 :            :         }
    1517                 :            : 
    1518                 :            :         return 0;
    1519                 :            : }
    1520                 :            : 
    1521                 :          0 : static bool apertures_overlap(struct aperture *gen, struct aperture *hw)
    1522                 :            : {
    1523                 :            :         /* is the generic aperture base the same as the HW one */
    1524                 :          0 :         if (gen->base == hw->base)
    1525                 :            :                 return true;
    1526                 :            :         /* is the generic aperture base inside the hw base->hw base+size */
    1527   [ #  #  #  # ]:          0 :         if (gen->base > hw->base && gen->base < hw->base + hw->size)
    1528                 :            :                 return true;
    1529                 :            :         return false;
    1530                 :            : }
    1531                 :            : 
    1532                 :          0 : static bool fb_do_apertures_overlap(struct apertures_struct *gena,
    1533                 :            :                                     struct apertures_struct *hwa)
    1534                 :            : {
    1535                 :          0 :         int i, j;
    1536         [ #  # ]:          0 :         if (!hwa || !gena)
    1537                 :            :                 return false;
    1538                 :            : 
    1539         [ #  # ]:          0 :         for (i = 0; i < hwa->count; ++i) {
    1540                 :          0 :                 struct aperture *h = &hwa->ranges[i];
    1541         [ #  # ]:          0 :                 for (j = 0; j < gena->count; ++j) {
    1542                 :          0 :                         struct aperture *g = &gena->ranges[j];
    1543                 :          0 :                         printk(KERN_DEBUG "checking generic (%llx %llx) vs hw (%llx %llx)\n",
    1544                 :          0 :                                 (unsigned long long)g->base,
    1545                 :          0 :                                 (unsigned long long)g->size,
    1546                 :          0 :                                 (unsigned long long)h->base,
    1547                 :          0 :                                 (unsigned long long)h->size);
    1548         [ #  # ]:          0 :                         if (apertures_overlap(g, h))
    1549                 :            :                                 return true;
    1550                 :            :                 }
    1551                 :            :         }
    1552                 :            : 
    1553                 :            :         return false;
    1554                 :            : }
    1555                 :            : 
    1556                 :            : static void do_unregister_framebuffer(struct fb_info *fb_info);
    1557                 :            : 
    1558                 :            : #define VGA_FB_PHYS 0xA0000
    1559                 :          0 : static void do_remove_conflicting_framebuffers(struct apertures_struct *a,
    1560                 :            :                                                const char *name, bool primary)
    1561                 :            : {
    1562                 :          0 :         int i;
    1563                 :            : 
    1564                 :            :         /* check all firmware fbs and kick off if the base addr overlaps */
    1565   [ #  #  #  # ]:          0 :         for_each_registered_fb(i) {
    1566                 :          0 :                 struct apertures_struct *gen_aper;
    1567                 :            : 
    1568         [ #  # ]:          0 :                 if (!(registered_fb[i]->flags & FBINFO_MISC_FIRMWARE))
    1569                 :          0 :                         continue;
    1570                 :            : 
    1571                 :          0 :                 gen_aper = registered_fb[i]->apertures;
    1572         [ #  # ]:          0 :                 if (fb_do_apertures_overlap(gen_aper, a) ||
    1573   [ #  #  #  # ]:          0 :                         (primary && gen_aper && gen_aper->count &&
    1574         [ #  # ]:          0 :                          gen_aper->ranges[0].base == VGA_FB_PHYS)) {
    1575                 :            : 
    1576                 :          0 :                         printk(KERN_INFO "fb%d: switching to %s from %s\n",
    1577                 :          0 :                                i, name, registered_fb[i]->fix.id);
    1578                 :          0 :                         do_unregister_framebuffer(registered_fb[i]);
    1579                 :            :                 }
    1580                 :            :         }
    1581                 :          0 : }
    1582                 :            : 
    1583                 :            : static bool lockless_register_fb;
    1584                 :            : module_param_named_unsafe(lockless_register_fb, lockless_register_fb, bool, 0400);
    1585                 :            : MODULE_PARM_DESC(lockless_register_fb,
    1586                 :            :         "Lockless framebuffer registration for debugging [default=off]");
    1587                 :            : 
    1588                 :          0 : static int do_register_framebuffer(struct fb_info *fb_info)
    1589                 :            : {
    1590                 :          0 :         int i, ret;
    1591                 :          0 :         struct fb_videomode mode;
    1592                 :            : 
    1593         [ #  # ]:          0 :         if (fb_check_foreignness(fb_info))
    1594                 :            :                 return -ENOSYS;
    1595                 :            : 
    1596                 :          0 :         do_remove_conflicting_framebuffers(fb_info->apertures,
    1597                 :          0 :                                            fb_info->fix.id,
    1598                 :          0 :                                            fb_is_primary_device(fb_info));
    1599                 :            : 
    1600         [ #  # ]:          0 :         if (num_registered_fb == FB_MAX)
    1601                 :            :                 return -ENXIO;
    1602                 :            : 
    1603                 :          0 :         num_registered_fb++;
    1604         [ #  # ]:          0 :         for (i = 0 ; i < FB_MAX; i++)
    1605         [ #  # ]:          0 :                 if (!registered_fb[i])
    1606                 :            :                         break;
    1607                 :          0 :         fb_info->node = i;
    1608                 :          0 :         atomic_set(&fb_info->count, 1);
    1609                 :          0 :         mutex_init(&fb_info->lock);
    1610                 :          0 :         mutex_init(&fb_info->mm_lock);
    1611                 :            : 
    1612                 :          0 :         fb_info->dev = device_create(fb_class, fb_info->device,
    1613                 :          0 :                                      MKDEV(FB_MAJOR, i), NULL, "fb%d", i);
    1614         [ #  # ]:          0 :         if (IS_ERR(fb_info->dev)) {
    1615                 :            :                 /* Not fatal */
    1616                 :          0 :                 printk(KERN_WARNING "Unable to create device for framebuffer %d; errno = %ld\n", i, PTR_ERR(fb_info->dev));
    1617                 :          0 :                 fb_info->dev = NULL;
    1618                 :            :         } else
    1619                 :          0 :                 fb_init_device(fb_info);
    1620                 :            : 
    1621         [ #  # ]:          0 :         if (fb_info->pixmap.addr == NULL) {
    1622                 :          0 :                 fb_info->pixmap.addr = kmalloc(FBPIXMAPSIZE, GFP_KERNEL);
    1623         [ #  # ]:          0 :                 if (fb_info->pixmap.addr) {
    1624                 :          0 :                         fb_info->pixmap.size = FBPIXMAPSIZE;
    1625                 :          0 :                         fb_info->pixmap.buf_align = 1;
    1626                 :          0 :                         fb_info->pixmap.scan_align = 1;
    1627                 :          0 :                         fb_info->pixmap.access_align = 32;
    1628                 :          0 :                         fb_info->pixmap.flags = FB_PIXMAP_DEFAULT;
    1629                 :            :                 }
    1630                 :            :         }       
    1631                 :          0 :         fb_info->pixmap.offset = 0;
    1632                 :            : 
    1633         [ #  # ]:          0 :         if (!fb_info->pixmap.blit_x)
    1634                 :          0 :                 fb_info->pixmap.blit_x = ~(u32)0;
    1635                 :            : 
    1636         [ #  # ]:          0 :         if (!fb_info->pixmap.blit_y)
    1637                 :          0 :                 fb_info->pixmap.blit_y = ~(u32)0;
    1638                 :            : 
    1639   [ #  #  #  # ]:          0 :         if (!fb_info->modelist.prev || !fb_info->modelist.next)
    1640                 :          0 :                 INIT_LIST_HEAD(&fb_info->modelist);
    1641                 :            : 
    1642         [ #  # ]:          0 :         if (fb_info->skip_vt_switch)
    1643                 :          0 :                 pm_vt_switch_required(fb_info->dev, false);
    1644                 :            :         else
    1645                 :          0 :                 pm_vt_switch_required(fb_info->dev, true);
    1646                 :            : 
    1647                 :          0 :         fb_var_to_videomode(&mode, &fb_info->var);
    1648                 :          0 :         fb_add_videomode(&mode, &fb_info->modelist);
    1649                 :          0 :         registered_fb[i] = fb_info;
    1650                 :            : 
    1651                 :            : #ifdef CONFIG_GUMSTIX_AM200EPD
    1652                 :            :         {
    1653                 :            :                 struct fb_event event;
    1654                 :            :                 event.info = fb_info;
    1655                 :            :                 fb_notifier_call_chain(FB_EVENT_FB_REGISTERED, &event);
    1656                 :            :         }
    1657                 :            : #endif
    1658                 :            : 
    1659         [ #  # ]:          0 :         if (!lockless_register_fb)
    1660                 :          0 :                 console_lock();
    1661                 :            :         else
    1662                 :          0 :                 atomic_inc(&ignore_console_lock_warning);
    1663                 :          0 :         lock_fb_info(fb_info);
    1664                 :          0 :         ret = fbcon_fb_registered(fb_info);
    1665                 :          0 :         unlock_fb_info(fb_info);
    1666                 :            : 
    1667         [ #  # ]:          0 :         if (!lockless_register_fb)
    1668                 :          0 :                 console_unlock();
    1669                 :            :         else
    1670                 :          0 :                 atomic_dec(&ignore_console_lock_warning);
    1671                 :            :         return ret;
    1672                 :            : }
    1673                 :            : 
    1674                 :          0 : static void unbind_console(struct fb_info *fb_info)
    1675                 :            : {
    1676                 :          0 :         int i = fb_info->node;
    1677                 :            : 
    1678   [ #  #  #  #  :          0 :         if (WARN_ON(i < 0 || i >= FB_MAX || registered_fb[i] != fb_info))
             #  #  #  # ]
    1679                 :            :                 return;
    1680                 :            : 
    1681                 :          0 :         console_lock();
    1682                 :          0 :         lock_fb_info(fb_info);
    1683                 :          0 :         fbcon_fb_unbind(fb_info);
    1684                 :          0 :         unlock_fb_info(fb_info);
    1685                 :          0 :         console_unlock();
    1686                 :            : }
    1687                 :            : 
    1688                 :          0 : static void unlink_framebuffer(struct fb_info *fb_info)
    1689                 :            : {
    1690                 :          0 :         int i;
    1691                 :            : 
    1692                 :          0 :         i = fb_info->node;
    1693   [ #  #  #  #  :          0 :         if (WARN_ON(i < 0 || i >= FB_MAX || registered_fb[i] != fb_info))
             #  #  #  # ]
    1694                 :            :                 return;
    1695                 :            : 
    1696         [ #  # ]:          0 :         if (!fb_info->dev)
    1697                 :            :                 return;
    1698                 :            : 
    1699                 :          0 :         device_destroy(fb_class, MKDEV(FB_MAJOR, i));
    1700                 :            : 
    1701                 :          0 :         pm_vt_switch_unregister(fb_info->dev);
    1702                 :            : 
    1703                 :          0 :         unbind_console(fb_info);
    1704                 :            : 
    1705                 :          0 :         fb_info->dev = NULL;
    1706                 :            : }
    1707                 :            : 
    1708                 :          0 : static void do_unregister_framebuffer(struct fb_info *fb_info)
    1709                 :            : {
    1710                 :          0 :         unlink_framebuffer(fb_info);
    1711         [ #  # ]:          0 :         if (fb_info->pixmap.addr &&
    1712         [ #  # ]:          0 :             (fb_info->pixmap.flags & FB_PIXMAP_DEFAULT))
    1713                 :          0 :                 kfree(fb_info->pixmap.addr);
    1714                 :          0 :         fb_destroy_modelist(&fb_info->modelist);
    1715                 :          0 :         registered_fb[fb_info->node] = NULL;
    1716                 :          0 :         num_registered_fb--;
    1717                 :          0 :         fb_cleanup_device(fb_info);
    1718                 :            : #ifdef CONFIG_GUMSTIX_AM200EPD
    1719                 :            :         {
    1720                 :            :                 struct fb_event event;
    1721                 :            :                 event.info = fb_info;
    1722                 :            :                 fb_notifier_call_chain(FB_EVENT_FB_UNREGISTERED, &event);
    1723                 :            :         }
    1724                 :            : #endif
    1725                 :          0 :         console_lock();
    1726                 :          0 :         fbcon_fb_unregistered(fb_info);
    1727                 :          0 :         console_unlock();
    1728                 :            : 
    1729                 :            :         /* this may free fb info */
    1730                 :          0 :         put_fb_info(fb_info);
    1731                 :          0 : }
    1732                 :            : 
    1733                 :            : /**
    1734                 :            :  * remove_conflicting_framebuffers - remove firmware-configured framebuffers
    1735                 :            :  * @a: memory range, users of which are to be removed
    1736                 :            :  * @name: requesting driver name
    1737                 :            :  * @primary: also kick vga16fb if present
    1738                 :            :  *
    1739                 :            :  * This function removes framebuffer devices (initialized by firmware/bootloader)
    1740                 :            :  * which use memory range described by @a. If @a is NULL all such devices are
    1741                 :            :  * removed.
    1742                 :            :  */
    1743                 :          0 : int remove_conflicting_framebuffers(struct apertures_struct *a,
    1744                 :            :                                     const char *name, bool primary)
    1745                 :            : {
    1746                 :          0 :         bool do_free = false;
    1747                 :            : 
    1748         [ #  # ]:          0 :         if (!a) {
    1749                 :          0 :                 a = alloc_apertures(1);
    1750                 :          0 :                 if (!a)
    1751                 :            :                         return -ENOMEM;
    1752                 :            : 
    1753                 :          0 :                 a->ranges[0].base = 0;
    1754                 :          0 :                 a->ranges[0].size = ~0;
    1755                 :          0 :                 do_free = true;
    1756                 :            :         }
    1757                 :            : 
    1758                 :          0 :         mutex_lock(&registration_lock);
    1759                 :          0 :         do_remove_conflicting_framebuffers(a, name, primary);
    1760                 :          0 :         mutex_unlock(&registration_lock);
    1761                 :            : 
    1762         [ #  # ]:          0 :         if (do_free)
    1763                 :          0 :                 kfree(a);
    1764                 :            : 
    1765                 :            :         return 0;
    1766                 :            : }
    1767                 :            : EXPORT_SYMBOL(remove_conflicting_framebuffers);
    1768                 :            : 
    1769                 :            : /**
    1770                 :            :  * remove_conflicting_pci_framebuffers - remove firmware-configured framebuffers for PCI devices
    1771                 :            :  * @pdev: PCI device
    1772                 :            :  * @name: requesting driver name
    1773                 :            :  *
    1774                 :            :  * This function removes framebuffer devices (eg. initialized by firmware)
    1775                 :            :  * using memory range configured for any of @pdev's memory bars.
    1776                 :            :  *
    1777                 :            :  * The function assumes that PCI device with shadowed ROM drives a primary
    1778                 :            :  * display and so kicks out vga16fb.
    1779                 :            :  */
    1780                 :          0 : int remove_conflicting_pci_framebuffers(struct pci_dev *pdev, const char *name)
    1781                 :            : {
    1782                 :          0 :         struct apertures_struct *ap;
    1783                 :          0 :         bool primary = false;
    1784                 :          0 :         int err, idx, bar;
    1785                 :            : 
    1786         [ #  # ]:          0 :         for (idx = 0, bar = 0; bar < PCI_STD_NUM_BARS; bar++) {
    1787         [ #  # ]:          0 :                 if (!(pci_resource_flags(pdev, bar) & IORESOURCE_MEM))
    1788                 :          0 :                         continue;
    1789                 :          0 :                 idx++;
    1790                 :            :         }
    1791                 :            : 
    1792                 :          0 :         ap = alloc_apertures(idx);
    1793                 :          0 :         if (!ap)
    1794                 :            :                 return -ENOMEM;
    1795                 :            : 
    1796         [ #  # ]:          0 :         for (idx = 0, bar = 0; bar < PCI_STD_NUM_BARS; bar++) {
    1797         [ #  # ]:          0 :                 if (!(pci_resource_flags(pdev, bar) & IORESOURCE_MEM))
    1798                 :          0 :                         continue;
    1799                 :          0 :                 ap->ranges[idx].base = pci_resource_start(pdev, bar);
    1800   [ #  #  #  # ]:          0 :                 ap->ranges[idx].size = pci_resource_len(pdev, bar);
    1801                 :          0 :                 pci_dbg(pdev, "%s: bar %d: 0x%lx -> 0x%lx\n", __func__, bar,
    1802                 :            :                         (unsigned long)pci_resource_start(pdev, bar),
    1803                 :            :                         (unsigned long)pci_resource_end(pdev, bar));
    1804                 :          0 :                 idx++;
    1805                 :            :         }
    1806                 :            : 
    1807                 :            : #ifdef CONFIG_X86
    1808                 :          0 :         primary = pdev->resource[PCI_ROM_RESOURCE].flags &
    1809                 :            :                                         IORESOURCE_ROM_SHADOW;
    1810                 :            : #endif
    1811                 :          0 :         err = remove_conflicting_framebuffers(ap, name, primary);
    1812                 :          0 :         kfree(ap);
    1813                 :          0 :         return err;
    1814                 :            : }
    1815                 :            : EXPORT_SYMBOL(remove_conflicting_pci_framebuffers);
    1816                 :            : 
    1817                 :            : /**
    1818                 :            :  *      register_framebuffer - registers a frame buffer device
    1819                 :            :  *      @fb_info: frame buffer info structure
    1820                 :            :  *
    1821                 :            :  *      Registers a frame buffer device @fb_info.
    1822                 :            :  *
    1823                 :            :  *      Returns negative errno on error, or zero for success.
    1824                 :            :  *
    1825                 :            :  */
    1826                 :            : int
    1827                 :          0 : register_framebuffer(struct fb_info *fb_info)
    1828                 :            : {
    1829                 :          0 :         int ret;
    1830                 :            : 
    1831                 :          0 :         mutex_lock(&registration_lock);
    1832                 :          0 :         ret = do_register_framebuffer(fb_info);
    1833                 :          0 :         mutex_unlock(&registration_lock);
    1834                 :            : 
    1835                 :          0 :         return ret;
    1836                 :            : }
    1837                 :            : EXPORT_SYMBOL(register_framebuffer);
    1838                 :            : 
    1839                 :            : /**
    1840                 :            :  *      unregister_framebuffer - releases a frame buffer device
    1841                 :            :  *      @fb_info: frame buffer info structure
    1842                 :            :  *
    1843                 :            :  *      Unregisters a frame buffer device @fb_info.
    1844                 :            :  *
    1845                 :            :  *      Returns negative errno on error, or zero for success.
    1846                 :            :  *
    1847                 :            :  *      This function will also notify the framebuffer console
    1848                 :            :  *      to release the driver.
    1849                 :            :  *
    1850                 :            :  *      This is meant to be called within a driver's module_exit()
    1851                 :            :  *      function. If this is called outside module_exit(), ensure
    1852                 :            :  *      that the driver implements fb_open() and fb_release() to
    1853                 :            :  *      check that no processes are using the device.
    1854                 :            :  */
    1855                 :            : void
    1856                 :          0 : unregister_framebuffer(struct fb_info *fb_info)
    1857                 :            : {
    1858                 :          0 :         mutex_lock(&registration_lock);
    1859                 :          0 :         do_unregister_framebuffer(fb_info);
    1860                 :          0 :         mutex_unlock(&registration_lock);
    1861                 :          0 : }
    1862                 :            : EXPORT_SYMBOL(unregister_framebuffer);
    1863                 :            : 
    1864                 :            : /**
    1865                 :            :  *      fb_set_suspend - low level driver signals suspend
    1866                 :            :  *      @info: framebuffer affected
    1867                 :            :  *      @state: 0 = resuming, !=0 = suspending
    1868                 :            :  *
    1869                 :            :  *      This is meant to be used by low level drivers to
    1870                 :            :  *      signal suspend/resume to the core & clients.
    1871                 :            :  *      It must be called with the console semaphore held
    1872                 :            :  */
    1873                 :          0 : void fb_set_suspend(struct fb_info *info, int state)
    1874                 :            : {
    1875   [ #  #  #  #  :          0 :         WARN_CONSOLE_UNLOCKED();
             #  #  #  # ]
    1876                 :            : 
    1877         [ #  # ]:          0 :         if (state) {
    1878                 :          0 :                 fbcon_suspended(info);
    1879                 :          0 :                 info->state = FBINFO_STATE_SUSPENDED;
    1880                 :            :         } else {
    1881                 :          0 :                 info->state = FBINFO_STATE_RUNNING;
    1882                 :          0 :                 fbcon_resumed(info);
    1883                 :            :         }
    1884                 :          0 : }
    1885                 :            : EXPORT_SYMBOL(fb_set_suspend);
    1886                 :            : 
    1887                 :            : /**
    1888                 :            :  *      fbmem_init - init frame buffer subsystem
    1889                 :            :  *
    1890                 :            :  *      Initialize the frame buffer subsystem.
    1891                 :            :  *
    1892                 :            :  *      NOTE: This function is _only_ to be called by drivers/char/mem.c.
    1893                 :            :  *
    1894                 :            :  */
    1895                 :            : 
    1896                 :            : static int __init
    1897                 :         11 : fbmem_init(void)
    1898                 :            : {
    1899                 :         11 :         int ret;
    1900                 :            : 
    1901         [ +  - ]:         11 :         if (!proc_create_seq("fb", 0, NULL, &proc_fb_seq_ops))
    1902                 :            :                 return -ENOMEM;
    1903                 :            : 
    1904                 :         11 :         ret = register_chrdev(FB_MAJOR, "fb", &fb_fops);
    1905         [ -  + ]:         11 :         if (ret) {
    1906                 :          0 :                 printk("unable to get major %d for fb devs\n", FB_MAJOR);
    1907                 :          0 :                 goto err_chrdev;
    1908                 :            :         }
    1909                 :            : 
    1910                 :         11 :         fb_class = class_create(THIS_MODULE, "graphics");
    1911         [ -  + ]:         11 :         if (IS_ERR(fb_class)) {
    1912                 :          0 :                 ret = PTR_ERR(fb_class);
    1913                 :          0 :                 pr_warn("Unable to create fb class; errno = %d\n", ret);
    1914                 :          0 :                 fb_class = NULL;
    1915                 :          0 :                 goto err_class;
    1916                 :            :         }
    1917                 :            : 
    1918                 :         11 :         fb_console_init();
    1919                 :            : 
    1920                 :         11 :         return 0;
    1921                 :            : 
    1922                 :            : err_class:
    1923                 :          0 :         unregister_chrdev(FB_MAJOR, "fb");
    1924                 :          0 : err_chrdev:
    1925                 :          0 :         remove_proc_entry("fb", NULL);
    1926                 :          0 :         return ret;
    1927                 :            : }
    1928                 :            : 
    1929                 :            : #ifdef MODULE
    1930                 :            : module_init(fbmem_init);
    1931                 :            : static void __exit
    1932                 :            : fbmem_exit(void)
    1933                 :            : {
    1934                 :            :         fb_console_exit();
    1935                 :            : 
    1936                 :            :         remove_proc_entry("fb", NULL);
    1937                 :            :         class_destroy(fb_class);
    1938                 :            :         unregister_chrdev(FB_MAJOR, "fb");
    1939                 :            : }
    1940                 :            : 
    1941                 :            : module_exit(fbmem_exit);
    1942                 :            : MODULE_LICENSE("GPL");
    1943                 :            : MODULE_DESCRIPTION("Framebuffer base");
    1944                 :            : #else
    1945                 :            : subsys_initcall(fbmem_init);
    1946                 :            : #endif
    1947                 :            : 
    1948                 :          0 : int fb_new_modelist(struct fb_info *info)
    1949                 :            : {
    1950                 :          0 :         struct fb_var_screeninfo var = info->var;
    1951                 :          0 :         struct list_head *pos, *n;
    1952                 :          0 :         struct fb_modelist *modelist;
    1953                 :          0 :         struct fb_videomode *m, mode;
    1954                 :          0 :         int err;
    1955                 :            : 
    1956         [ #  # ]:          0 :         list_for_each_safe(pos, n, &info->modelist) {
    1957                 :          0 :                 modelist = list_entry(pos, struct fb_modelist, list);
    1958                 :          0 :                 m = &modelist->mode;
    1959                 :          0 :                 fb_videomode_to_var(&var, m);
    1960                 :          0 :                 var.activate = FB_ACTIVATE_TEST;
    1961                 :          0 :                 err = fb_set_var(info, &var);
    1962                 :          0 :                 fb_var_to_videomode(&mode, &var);
    1963   [ #  #  #  # ]:          0 :                 if (err || !fb_mode_is_equal(m, &mode)) {
    1964                 :          0 :                         list_del(pos);
    1965                 :          0 :                         kfree(pos);
    1966                 :            :                 }
    1967                 :            :         }
    1968                 :            : 
    1969         [ #  # ]:          0 :         if (list_empty(&info->modelist))
    1970                 :            :                 return 1;
    1971                 :            : 
    1972                 :          0 :         fbcon_new_modelist(info);
    1973                 :            : 
    1974                 :          0 :         return 0;
    1975                 :            : }
    1976                 :            : 
    1977                 :            : MODULE_LICENSE("GPL");

Generated by: LCOV version 1.14