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

Configure Feed

Select the types of activity you want to include in your feed.

at v3.5-rc4 570 lines 12 kB view raw
1/* 2 * VRAM manager for OMAP 3 * 4 * Copyright (C) 2009 Nokia Corporation 5 * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com> 6 * 7 * This program is free software; you can redistribute it and/or modify 8 * it under the terms of the GNU General Public License version 2 as 9 * published by the Free Software Foundation. 10 * 11 * This program is distributed in the hope that it will be useful, but 12 * WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 * General Public License for more details. 15 * 16 * You should have received a copy of the GNU General Public License along 17 * with this program; if not, write to the Free Software Foundation, Inc., 18 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 19 */ 20 21/*#define DEBUG*/ 22 23#include <linux/kernel.h> 24#include <linux/mm.h> 25#include <linux/list.h> 26#include <linux/slab.h> 27#include <linux/seq_file.h> 28#include <linux/memblock.h> 29#include <linux/completion.h> 30#include <linux/debugfs.h> 31#include <linux/jiffies.h> 32#include <linux/module.h> 33 34#include <asm/setup.h> 35 36#include <plat/vram.h> 37#include <plat/dma.h> 38 39#ifdef DEBUG 40#define DBG(format, ...) pr_debug("VRAM: " format, ## __VA_ARGS__) 41#else 42#define DBG(format, ...) 43#endif 44 45/* postponed regions are used to temporarily store region information at boot 46 * time when we cannot yet allocate the region list */ 47#define MAX_POSTPONED_REGIONS 10 48 49static bool vram_initialized; 50static int postponed_cnt; 51static struct { 52 unsigned long paddr; 53 size_t size; 54} postponed_regions[MAX_POSTPONED_REGIONS]; 55 56struct vram_alloc { 57 struct list_head list; 58 unsigned long paddr; 59 unsigned pages; 60}; 61 62struct vram_region { 63 struct list_head list; 64 struct list_head alloc_list; 65 unsigned long paddr; 66 unsigned pages; 67}; 68 69static DEFINE_MUTEX(region_mutex); 70static LIST_HEAD(region_list); 71 72static struct vram_region *omap_vram_create_region(unsigned long paddr, 73 unsigned pages) 74{ 75 struct vram_region *rm; 76 77 rm = kzalloc(sizeof(*rm), GFP_KERNEL); 78 79 if (rm) { 80 INIT_LIST_HEAD(&rm->alloc_list); 81 rm->paddr = paddr; 82 rm->pages = pages; 83 } 84 85 return rm; 86} 87 88#if 0 89static void omap_vram_free_region(struct vram_region *vr) 90{ 91 list_del(&vr->list); 92 kfree(vr); 93} 94#endif 95 96static struct vram_alloc *omap_vram_create_allocation(struct vram_region *vr, 97 unsigned long paddr, unsigned pages) 98{ 99 struct vram_alloc *va; 100 struct vram_alloc *new; 101 102 new = kzalloc(sizeof(*va), GFP_KERNEL); 103 104 if (!new) 105 return NULL; 106 107 new->paddr = paddr; 108 new->pages = pages; 109 110 list_for_each_entry(va, &vr->alloc_list, list) { 111 if (va->paddr > new->paddr) 112 break; 113 } 114 115 list_add_tail(&new->list, &va->list); 116 117 return new; 118} 119 120static void omap_vram_free_allocation(struct vram_alloc *va) 121{ 122 list_del(&va->list); 123 kfree(va); 124} 125 126int omap_vram_add_region(unsigned long paddr, size_t size) 127{ 128 struct vram_region *rm; 129 unsigned pages; 130 131 if (vram_initialized) { 132 DBG("adding region paddr %08lx size %d\n", 133 paddr, size); 134 135 size &= PAGE_MASK; 136 pages = size >> PAGE_SHIFT; 137 138 rm = omap_vram_create_region(paddr, pages); 139 if (rm == NULL) 140 return -ENOMEM; 141 142 list_add(&rm->list, &region_list); 143 } else { 144 if (postponed_cnt == MAX_POSTPONED_REGIONS) 145 return -ENOMEM; 146 147 postponed_regions[postponed_cnt].paddr = paddr; 148 postponed_regions[postponed_cnt].size = size; 149 150 ++postponed_cnt; 151 } 152 return 0; 153} 154 155int omap_vram_free(unsigned long paddr, size_t size) 156{ 157 struct vram_region *rm; 158 struct vram_alloc *alloc; 159 unsigned start, end; 160 161 DBG("free mem paddr %08lx size %d\n", paddr, size); 162 163 size = PAGE_ALIGN(size); 164 165 mutex_lock(&region_mutex); 166 167 list_for_each_entry(rm, &region_list, list) { 168 list_for_each_entry(alloc, &rm->alloc_list, list) { 169 start = alloc->paddr; 170 end = alloc->paddr + (alloc->pages >> PAGE_SHIFT); 171 172 if (start >= paddr && end < paddr + size) 173 goto found; 174 } 175 } 176 177 mutex_unlock(&region_mutex); 178 return -EINVAL; 179 180found: 181 omap_vram_free_allocation(alloc); 182 183 mutex_unlock(&region_mutex); 184 return 0; 185} 186EXPORT_SYMBOL(omap_vram_free); 187 188static int _omap_vram_reserve(unsigned long paddr, unsigned pages) 189{ 190 struct vram_region *rm; 191 struct vram_alloc *alloc; 192 size_t size; 193 194 size = pages << PAGE_SHIFT; 195 196 list_for_each_entry(rm, &region_list, list) { 197 unsigned long start, end; 198 199 DBG("checking region %lx %d\n", rm->paddr, rm->pages); 200 201 start = rm->paddr; 202 end = start + (rm->pages << PAGE_SHIFT) - 1; 203 if (start > paddr || end < paddr + size - 1) 204 continue; 205 206 DBG("block ok, checking allocs\n"); 207 208 list_for_each_entry(alloc, &rm->alloc_list, list) { 209 end = alloc->paddr - 1; 210 211 if (start <= paddr && end >= paddr + size - 1) 212 goto found; 213 214 start = alloc->paddr + (alloc->pages << PAGE_SHIFT); 215 } 216 217 end = rm->paddr + (rm->pages << PAGE_SHIFT) - 1; 218 219 if (!(start <= paddr && end >= paddr + size - 1)) 220 continue; 221found: 222 DBG("found area start %lx, end %lx\n", start, end); 223 224 if (omap_vram_create_allocation(rm, paddr, pages) == NULL) 225 return -ENOMEM; 226 227 return 0; 228 } 229 230 return -ENOMEM; 231} 232 233int omap_vram_reserve(unsigned long paddr, size_t size) 234{ 235 unsigned pages; 236 int r; 237 238 DBG("reserve mem paddr %08lx size %d\n", paddr, size); 239 240 size = PAGE_ALIGN(size); 241 pages = size >> PAGE_SHIFT; 242 243 mutex_lock(&region_mutex); 244 245 r = _omap_vram_reserve(paddr, pages); 246 247 mutex_unlock(&region_mutex); 248 249 return r; 250} 251EXPORT_SYMBOL(omap_vram_reserve); 252 253static void _omap_vram_dma_cb(int lch, u16 ch_status, void *data) 254{ 255 struct completion *compl = data; 256 complete(compl); 257} 258 259static int _omap_vram_clear(u32 paddr, unsigned pages) 260{ 261 struct completion compl; 262 unsigned elem_count; 263 unsigned frame_count; 264 int r; 265 int lch; 266 267 init_completion(&compl); 268 269 r = omap_request_dma(OMAP_DMA_NO_DEVICE, "VRAM DMA", 270 _omap_vram_dma_cb, 271 &compl, &lch); 272 if (r) { 273 pr_err("VRAM: request_dma failed for memory clear\n"); 274 return -EBUSY; 275 } 276 277 elem_count = pages * PAGE_SIZE / 4; 278 frame_count = 1; 279 280 omap_set_dma_transfer_params(lch, OMAP_DMA_DATA_TYPE_S32, 281 elem_count, frame_count, 282 OMAP_DMA_SYNC_ELEMENT, 283 0, 0); 284 285 omap_set_dma_dest_params(lch, 0, OMAP_DMA_AMODE_POST_INC, 286 paddr, 0, 0); 287 288 omap_set_dma_color_mode(lch, OMAP_DMA_CONSTANT_FILL, 0x000000); 289 290 omap_start_dma(lch); 291 292 if (wait_for_completion_timeout(&compl, msecs_to_jiffies(1000)) == 0) { 293 omap_stop_dma(lch); 294 pr_err("VRAM: dma timeout while clearing memory\n"); 295 r = -EIO; 296 goto err; 297 } 298 299 r = 0; 300err: 301 omap_free_dma(lch); 302 303 return r; 304} 305 306static int _omap_vram_alloc(unsigned pages, unsigned long *paddr) 307{ 308 struct vram_region *rm; 309 struct vram_alloc *alloc; 310 311 list_for_each_entry(rm, &region_list, list) { 312 unsigned long start, end; 313 314 DBG("checking region %lx %d\n", rm->paddr, rm->pages); 315 316 start = rm->paddr; 317 318 list_for_each_entry(alloc, &rm->alloc_list, list) { 319 end = alloc->paddr; 320 321 if (end - start >= pages << PAGE_SHIFT) 322 goto found; 323 324 start = alloc->paddr + (alloc->pages << PAGE_SHIFT); 325 } 326 327 end = rm->paddr + (rm->pages << PAGE_SHIFT); 328found: 329 if (end - start < pages << PAGE_SHIFT) 330 continue; 331 332 DBG("found %lx, end %lx\n", start, end); 333 334 alloc = omap_vram_create_allocation(rm, start, pages); 335 if (alloc == NULL) 336 return -ENOMEM; 337 338 *paddr = start; 339 340 _omap_vram_clear(start, pages); 341 342 return 0; 343 } 344 345 return -ENOMEM; 346} 347 348int omap_vram_alloc(size_t size, unsigned long *paddr) 349{ 350 unsigned pages; 351 int r; 352 353 BUG_ON(!size); 354 355 DBG("alloc mem size %d\n", size); 356 357 size = PAGE_ALIGN(size); 358 pages = size >> PAGE_SHIFT; 359 360 mutex_lock(&region_mutex); 361 362 r = _omap_vram_alloc(pages, paddr); 363 364 mutex_unlock(&region_mutex); 365 366 return r; 367} 368EXPORT_SYMBOL(omap_vram_alloc); 369 370void omap_vram_get_info(unsigned long *vram, 371 unsigned long *free_vram, 372 unsigned long *largest_free_block) 373{ 374 struct vram_region *vr; 375 struct vram_alloc *va; 376 377 *vram = 0; 378 *free_vram = 0; 379 *largest_free_block = 0; 380 381 mutex_lock(&region_mutex); 382 383 list_for_each_entry(vr, &region_list, list) { 384 unsigned free; 385 unsigned long pa; 386 387 pa = vr->paddr; 388 *vram += vr->pages << PAGE_SHIFT; 389 390 list_for_each_entry(va, &vr->alloc_list, list) { 391 free = va->paddr - pa; 392 *free_vram += free; 393 if (free > *largest_free_block) 394 *largest_free_block = free; 395 pa = va->paddr + (va->pages << PAGE_SHIFT); 396 } 397 398 free = vr->paddr + (vr->pages << PAGE_SHIFT) - pa; 399 *free_vram += free; 400 if (free > *largest_free_block) 401 *largest_free_block = free; 402 } 403 404 mutex_unlock(&region_mutex); 405} 406EXPORT_SYMBOL(omap_vram_get_info); 407 408#if defined(CONFIG_DEBUG_FS) 409static int vram_debug_show(struct seq_file *s, void *unused) 410{ 411 struct vram_region *vr; 412 struct vram_alloc *va; 413 unsigned size; 414 415 mutex_lock(&region_mutex); 416 417 list_for_each_entry(vr, &region_list, list) { 418 size = vr->pages << PAGE_SHIFT; 419 seq_printf(s, "%08lx-%08lx (%d bytes)\n", 420 vr->paddr, vr->paddr + size - 1, 421 size); 422 423 list_for_each_entry(va, &vr->alloc_list, list) { 424 size = va->pages << PAGE_SHIFT; 425 seq_printf(s, " %08lx-%08lx (%d bytes)\n", 426 va->paddr, va->paddr + size - 1, 427 size); 428 } 429 } 430 431 mutex_unlock(&region_mutex); 432 433 return 0; 434} 435 436static int vram_debug_open(struct inode *inode, struct file *file) 437{ 438 return single_open(file, vram_debug_show, inode->i_private); 439} 440 441static const struct file_operations vram_debug_fops = { 442 .open = vram_debug_open, 443 .read = seq_read, 444 .llseek = seq_lseek, 445 .release = single_release, 446}; 447 448static int __init omap_vram_create_debugfs(void) 449{ 450 struct dentry *d; 451 452 d = debugfs_create_file("vram", S_IRUGO, NULL, 453 NULL, &vram_debug_fops); 454 if (IS_ERR(d)) 455 return PTR_ERR(d); 456 457 return 0; 458} 459#endif 460 461static __init int omap_vram_init(void) 462{ 463 int i; 464 465 vram_initialized = 1; 466 467 for (i = 0; i < postponed_cnt; i++) 468 omap_vram_add_region(postponed_regions[i].paddr, 469 postponed_regions[i].size); 470 471#ifdef CONFIG_DEBUG_FS 472 if (omap_vram_create_debugfs()) 473 pr_err("VRAM: Failed to create debugfs file\n"); 474#endif 475 476 return 0; 477} 478 479arch_initcall(omap_vram_init); 480 481/* boottime vram alloc stuff */ 482 483/* set from board file */ 484static u32 omap_vram_sdram_start __initdata; 485static u32 omap_vram_sdram_size __initdata; 486 487/* set from kernel cmdline */ 488static u32 omap_vram_def_sdram_size __initdata; 489static u32 omap_vram_def_sdram_start __initdata; 490 491static int __init omap_vram_early_vram(char *p) 492{ 493 omap_vram_def_sdram_size = memparse(p, &p); 494 if (*p == ',') 495 omap_vram_def_sdram_start = simple_strtoul(p + 1, &p, 16); 496 return 0; 497} 498early_param("vram", omap_vram_early_vram); 499 500/* 501 * Called from map_io. We need to call to this early enough so that we 502 * can reserve the fixed SDRAM regions before VM could get hold of them. 503 */ 504void __init omap_vram_reserve_sdram_memblock(void) 505{ 506 u32 paddr; 507 u32 size = 0; 508 509 /* cmdline arg overrides the board file definition */ 510 if (omap_vram_def_sdram_size) { 511 size = omap_vram_def_sdram_size; 512 paddr = omap_vram_def_sdram_start; 513 } 514 515 if (!size) { 516 size = omap_vram_sdram_size; 517 paddr = omap_vram_sdram_start; 518 } 519 520#ifdef CONFIG_OMAP2_VRAM_SIZE 521 if (!size) { 522 size = CONFIG_OMAP2_VRAM_SIZE * 1024 * 1024; 523 paddr = 0; 524 } 525#endif 526 527 if (!size) 528 return; 529 530 size = ALIGN(size, SZ_2M); 531 532 if (paddr) { 533 if (paddr & ~PAGE_MASK) { 534 pr_err("VRAM start address 0x%08x not page aligned\n", 535 paddr); 536 return; 537 } 538 539 if (!memblock_is_region_memory(paddr, size)) { 540 pr_err("Illegal SDRAM region 0x%08x..0x%08x for VRAM\n", 541 paddr, paddr + size - 1); 542 return; 543 } 544 545 if (memblock_is_region_reserved(paddr, size)) { 546 pr_err("FB: failed to reserve VRAM - busy\n"); 547 return; 548 } 549 550 if (memblock_reserve(paddr, size) < 0) { 551 pr_err("FB: failed to reserve VRAM - no memory\n"); 552 return; 553 } 554 } else { 555 paddr = memblock_alloc(size, SZ_2M); 556 } 557 558 memblock_free(paddr, size); 559 memblock_remove(paddr, size); 560 561 omap_vram_add_region(paddr, size); 562 563 pr_info("Reserving %u bytes SDRAM for VRAM\n", size); 564} 565 566void __init omap_vram_set_sdram_vram(u32 size, u32 start) 567{ 568 omap_vram_sdram_start = start; 569 omap_vram_sdram_size = size; 570}