diff options
author | Ben Dooks <ben-linux@fluff.org> | 2008-07-24 00:31:37 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2008-07-24 13:47:40 -0400 |
commit | d05254190dd1a4751284f4a51efb70fcc16c45a4 (patch) | |
tree | 52dd29629ff489eefe42a9361664ddbcabee67b0 /drivers/video/sm501fb.c | |
parent | 9b599fb2fc23386dfd2965bf7d10b2b0f628b208 (diff) |
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>
Diffstat (limited to 'drivers/video/sm501fb.c')
-rw-r--r-- | drivers/video/sm501fb.c | 53 |
1 files changed, 42 insertions, 11 deletions
diff --git a/drivers/video/sm501fb.c b/drivers/video/sm501fb.c index b473cf665d83..f94ae84a58cd 100644 --- a/drivers/video/sm501fb.c +++ b/drivers/video/sm501fb.c | |||
@@ -48,10 +48,15 @@ enum sm501_controller { | |||
48 | HEAD_PANEL = 1, | 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 | struct sm501_mem { | 57 | struct sm501_mem { |
53 | unsigned long size; | 58 | unsigned long size; |
54 | unsigned long sm_addr; | 59 | unsigned long sm_addr; /* offset from base of sm501 fb. */ |
55 | void __iomem *k_addr; | 60 | void __iomem *k_addr; |
56 | }; | 61 | }; |
57 | 62 | ||
@@ -142,37 +147,63 @@ static inline void sm501fb_sync_regs(struct sm501fb_info *info) | |||
142 | static int sm501_alloc_mem(struct sm501fb_info *inf, struct sm501_mem *mem, | 147 | static int sm501_alloc_mem(struct sm501fb_info *inf, struct sm501_mem *mem, |
143 | unsigned int why, size_t size) | 148 | unsigned int why, size_t size) |
144 | { | 149 | { |
145 | unsigned int ptr = 0; | 150 | struct sm501fb_par *par; |
146 | unsigned int end; | ||
147 | struct fb_info *fbi; | 151 | struct fb_info *fbi; |
152 | unsigned int ptr; | ||
153 | unsigned int end; | ||
148 | 154 | ||
149 | switch (why) { | 155 | switch (why) { |
150 | case SM501_MEMF_CURSOR: | 156 | case SM501_MEMF_CURSOR: |
151 | ptr = inf->fbmem_len - size; | 157 | ptr = inf->fbmem_len - size; |
152 | inf->fbmem_len = ptr; | 158 | inf->fbmem_len = ptr; /* adjust available memory. */ |
153 | break; | 159 | break; |
154 | 160 | ||
155 | case SM501_MEMF_PANEL: | 161 | case SM501_MEMF_PANEL: |
156 | ptr = inf->fbmem_len - size; | 162 | ptr = inf->fbmem_len - size; |
157 | fbi = inf->fb[0]; | 163 | fbi = inf->fb[HEAD_CRT]; |
164 | |||
165 | /* round down, some programs such as directfb do not draw | ||
166 | * 0,0 correctly unless the start is aligned to a page start. | ||
167 | */ | ||
168 | |||
169 | if (ptr > 0) | ||
170 | ptr &= ~(PAGE_SIZE - 1); | ||
158 | 171 | ||
159 | if (fbi && ptr < fbi->fix.smem_len) | 172 | if (fbi && ptr < fbi->fix.smem_len) |
160 | return -ENOMEM; | 173 | return -ENOMEM; |
161 | 174 | ||
175 | if (ptr < 0) | ||
176 | return -ENOMEM; | ||
177 | |||
162 | break; | 178 | break; |
163 | 179 | ||
164 | case SM501_MEMF_CRT: | 180 | case SM501_MEMF_CRT: |
165 | ptr = 0; | 181 | ptr = 0; |
182 | |||
183 | /* check to see if we have panel memory allocated | ||
184 | * which would put an limit on available memory. */ | ||
185 | |||
186 | fbi = inf->fb[HEAD_PANEL]; | ||
187 | if (fbi) { | ||
188 | par = fbi->par; | ||
189 | end = par->screen.k_addr ? par->screen.sm_addr : inf->fbmem_len; | ||
190 | } else | ||
191 | end = inf->fbmem_len; | ||
192 | |||
193 | if ((ptr + size) > end) | ||
194 | return -ENOMEM; | ||
195 | |||
166 | break; | 196 | break; |
167 | 197 | ||
168 | case SM501_MEMF_ACCEL: | 198 | case SM501_MEMF_ACCEL: |
169 | fbi = inf->fb[0]; | 199 | fbi = inf->fb[HEAD_CRT]; |
170 | ptr = fbi ? fbi->fix.smem_len : 0; | 200 | ptr = fbi ? fbi->fix.smem_len : 0; |
171 | 201 | ||
172 | fbi = inf->fb[1]; | 202 | fbi = inf->fb[HEAD_PANEL]; |
173 | if (fbi) | 203 | if (fbi) { |
174 | end = (fbi->fix.smem_start - inf->fbmem_res->start); | 204 | par = fbi->par; |
175 | else | 205 | end = par->screen.sm_addr; |
206 | } else | ||
176 | end = inf->fbmem_len; | 207 | end = inf->fbmem_len; |
177 | 208 | ||
178 | if ((ptr + size) > end) | 209 | if ((ptr + size) > end) |