Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

sm501: fixup allocation code to be 64bit resource compliant

As pointed out by Andrew Morton, we have a problem when setting the 64bit
resources option. Alter the allocation routines to remove the need to use
the start and end fields, use the proper HEAD_PANEL/HEAD_CRT and update
the comments.

Note, we also fix the bug where we failed to check the size of the
CRT memory allocation.

[akpm@linux-foundation.org: cleanup]
Signed-off-by: Ben Dooks <ben-linux@fluff.org>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>

authored by

Ben Dooks and committed by
Linus Torvalds
d0525419 9b599fb2

+42 -11
+42 -11
drivers/video/sm501fb.c
··· 48 48 HEAD_PANEL = 1, 49 49 }; 50 50 51 - /* SM501 memory address */ 51 + /* SM501 memory address. 52 + * 53 + * This structure is used to track memory usage within the SM501 framebuffer 54 + * allocation. The sm_addr field is stored as an offset as it is often used 55 + * against both the physical and mapped addresses. 56 + */ 52 57 struct sm501_mem { 53 58 unsigned long size; 54 - unsigned long sm_addr; 59 + unsigned long sm_addr; /* offset from base of sm501 fb. */ 55 60 void __iomem *k_addr; 56 61 }; 57 62 ··· 147 142 static int sm501_alloc_mem(struct sm501fb_info *inf, struct sm501_mem *mem, 148 143 unsigned int why, size_t size) 149 144 { 150 - unsigned int ptr = 0; 151 - unsigned int end; 145 + struct sm501fb_par *par; 152 146 struct fb_info *fbi; 147 + unsigned int ptr; 148 + unsigned int end; 153 149 154 150 switch (why) { 155 151 case SM501_MEMF_CURSOR: 156 152 ptr = inf->fbmem_len - size; 157 - inf->fbmem_len = ptr; 153 + inf->fbmem_len = ptr; /* adjust available memory. */ 158 154 break; 159 155 160 156 case SM501_MEMF_PANEL: 161 157 ptr = inf->fbmem_len - size; 162 - fbi = inf->fb[0]; 158 + fbi = inf->fb[HEAD_CRT]; 159 + 160 + /* round down, some programs such as directfb do not draw 161 + * 0,0 correctly unless the start is aligned to a page start. 162 + */ 163 + 164 + if (ptr > 0) 165 + ptr &= ~(PAGE_SIZE - 1); 163 166 164 167 if (fbi && ptr < fbi->fix.smem_len) 168 + return -ENOMEM; 169 + 170 + if (ptr < 0) 165 171 return -ENOMEM; 166 172 167 173 break; 168 174 169 175 case SM501_MEMF_CRT: 170 176 ptr = 0; 177 + 178 + /* check to see if we have panel memory allocated 179 + * which would put an limit on available memory. */ 180 + 181 + fbi = inf->fb[HEAD_PANEL]; 182 + if (fbi) { 183 + par = fbi->par; 184 + end = par->screen.k_addr ? par->screen.sm_addr : inf->fbmem_len; 185 + } else 186 + end = inf->fbmem_len; 187 + 188 + if ((ptr + size) > end) 189 + return -ENOMEM; 190 + 171 191 break; 172 192 173 193 case SM501_MEMF_ACCEL: 174 - fbi = inf->fb[0]; 194 + fbi = inf->fb[HEAD_CRT]; 175 195 ptr = fbi ? fbi->fix.smem_len : 0; 176 196 177 - fbi = inf->fb[1]; 178 - if (fbi) 179 - end = (fbi->fix.smem_start - inf->fbmem_res->start); 180 - else 197 + fbi = inf->fb[HEAD_PANEL]; 198 + if (fbi) { 199 + par = fbi->par; 200 + end = par->screen.sm_addr; 201 + } else 181 202 end = inf->fbmem_len; 182 203 183 204 if ((ptr + size) > end)