Chinaunix首页 | 论坛 | 博客
  • 博客访问: 2149247
  • 博文数量: 438
  • 博客积分: 3871
  • 博客等级: 中校
  • 技术积分: 6075
  • 用 户 组: 普通用户
  • 注册时间: 2011-09-10 00:11
个人简介

邮箱: wangcong02345@163.com

文章分类

全部博文(438)

文章存档

2017年(15)

2016年(119)

2015年(91)

2014年(62)

2013年(56)

2012年(79)

2011年(16)

分类: Android平台

2014-02-28 15:10:50

一. 内核启动时保留内存
start_kernel
    --> setup_arch
        -->arm_memblock_init
            --> rk30_reserve
在内核启动时会保留一部分内存
在arch/arm/mach-rk3188/board-rk3188-ds1006h.c中
  1. static void __init rk30_reserve(void)
  2. {
  3.     //保存在变量 rk30_ion_pdata.heaps[0].base 中
  4.     rk30_ion_pdata.heaps[0].base = board_mem_reserve_add("ion", ION_RESERVE_SIZE);
  5. }
bank.start=0x60000000, size=0x36800000
reserved_base_end就是内存的结束地址: 0x6000000+0x36800000=0x96800000
  1. phys_addr_t __init board_mem_reserve_add(char *name, size_t size)
  2. {
  3.     phys_addr_t base = 0;
  4.     if(reserved_base_end == 0)
  5.         reserved_base_end = meminfo.bank[0].start + meminfo.bank[0].size;
  6.     reserved_size += size;
  7.     base = reserved_base_end - reserved_size;

  8.     return base;
  9. }
分配内存之后base=内存结束地址-80M=0x96800000-0x5000000=0x91800000
memory reserve: Memory(base:0x91800000 size:80M) reserved for


二. ION驱动的初始化
2.1 platform_device
在arch/arm/mach-rk3188/board-rk3188-ds1006h.c中
  1. static struct ion_platform_data rk30_ion_pdata = {
  2.     .nr = 1,
  3.     .heaps = {
  4.         {
  5.             .type = ION_HEAP_TYPE_CARVEOUT,  //reserve memory:这是在保留内存块中分配内存
  6.             .id = ION_NOR_HEAP_ID,
  7.             .name = "norheap",
  8.             .size = ION_RESERVE_SIZE,
  9.         }
  10.     },
  11. };

  12. static struct platform_device device_ion = {
  13.     .name = "ion-rockchip",
  14.     .id = 0,
  15.     .dev = {
  16.         .platform_data = &rk30_ion_pdata,
  17.     },
  18. };
2.2 platform_driver
cong@ubuntu:/rk/rk3188/kernel/drivers/gpu$ tree
├── ion
│   ├── ion.c
│   ├── ion_carveout_heap.c
│   ├── ion_heap.c
│   ├── ion_priv.h
│   ├── ion_system_heap.c
│   ├── ion_system_mapper.c
│   └── rockchip
│       └── rockchip_ion.c
└── Makefile
module_init(ion_init);
    --> ion_init
  1. static struct platform_driver ion_driver = {
  2.     .probe = rockchip_ion_probe,
  3.     .remove = rockchip_ion_remove,
  4.     .driver = { .name = "ion-rockchip" }
  5. };

  6. static int __init ion_init(void)
  7. {
  8.     return platform_driver_register(&ion_driver);
  9. }

module_init(ion_init);
    --> ion_init
        --> rockchip_ion_probe
  1. static int rockchip_ion_probe(struct platform_device *pdev)
  2. {
  3.     struct ion_device *idev;
  4.     struct ion_platform_data *pdata = pdev->dev.platform_data;

  5.     num_heaps = pdata->nr;    //num_heaps =1
  6.     heaps = kzalloc(sizeof(struct ion_heap *) * pdata->nr, GFP_KERNEL);

  7.     idev = ion_device_create(rockchip_custom_ioctl);

  8.     for (i = 0; i < num_heaps; i++) {
  9.         struct ion_platform_heap *heap_data = &pdata->heaps[i];
  10.         heaps[i] = ion_heap_create(heap_data);       
  11.         ion_device_add_heap(idev, heaps[i]);
  12.     }
  13.     platform_set_drvdata(pdev, idev);
  14.     return 0;
  15. }

rockchip_ion_probe
    --> ion_device_create
在drivers/gpu/ion/ion.c中
  1. struct ion_device *ion_device_create(long (*custom_ioctl)(struct ion_client *client, unsigned int cmd, unsigned long arg))
  2. {
  3.     struct ion_device *idev;
  4.     idev = kzalloc(sizeof(struct ion_device), GFP_KERNEL);
  5.     idev->dev.minor = MISC_DYNAMIC_MINOR;
  6.     idev->dev.name = "ion";
  7.     idev->dev.fops = &ion_fops;
  8.     idev->dev.parent = NULL;
  9.     ret = misc_register(&idev->dev);
  10.    
  11.     idev->debug_root = debugfs_create_dir("ion", NULL);

  12.     idev->custom_ioctl = custom_ioctl;
  13.     idev->buffers = RB_ROOT;
  14.     mutex_init(&idev->lock);
  15.     idev->heaps = RB_ROOT;
  16.     idev->user_clients = RB_ROOT;
  17.     idev->kernel_clients = RB_ROOT;
  18.     debugfs_create_file("leak", 0664, idev->debug_root, idev, &debug_leak_fops);
  19.     return idev;
  20. }
rockchip_ion_probe
    --> ion_heap_create
  1. struct ion_heap *ion_heap_create(struct ion_platform_heap *heap_data)
  2. {
  3.     struct ion_heap *heap = NULL;

  4.     switch (heap_data->type) {
  5.     case ION_HEAP_TYPE_SYSTEM_CONTIG:  //通过kmalloc分配内存
  6.         heap = ion_system_contig_heap_create(heap_data);
  7.         break;
  8.     case ION_HEAP_TYPE_SYSTEM:    //通过vmalloc分配内存
  9.         heap = ion_system_heap_create(heap_data);
  10.         break;
  11.     case ION_HEAP_TYPE_CARVEOUT:    //在保留内存块中(reserve memory)分配内存
  12.         heap = ion_carveout_heap_create(heap_data);
  13.         break;
  14.     default:
  15.         pr_err("%s: Invalid heap type %d\n", __func__, heap_data->type);
  16.         return ERR_PTR(-EINVAL);
  17.     }
  18.     heap->name = heap_data->name;
  19.     heap->id = heap_data->id;
  20.     return heap;
  21. }

 rockchip_ion_probe
    --> ion_heap_create
        --> ion_carveout_heap_create  
在drivers/gpu/ion/ion_heap.c中
  1. struct ion_heap *ion_carveout_heap_create(struct ion_platform_heap *heap_data)
  2. {
  3.     struct ion_carveout_heap *carveout_heap;

  4.     carveout_heap = kzalloc(sizeof(struct ion_carveout_heap), GFP_KERNEL);

  5.     carveout_heap->pool = gen_pool_create(12, -1);
  6.     carveout_heap->base = heap_data->base;               //系统保留的物理地址base=0x91800000 
  7.     // 向内存池中加入内存块,起始地址base=0x918000000,size=0x50000000=80M
        gen_pool_add(carveout_heap->pool, carveout_heap->base, heap_data->size, -1);
  8.     carveout_heap->heap.ops = &carveout_heap_ops;
  9.     carveout_heap->heap.type = ION_HEAP_TYPE_CARVEOUT;
  10.     carveout_heap->heap.allocated_size = 0;
  11.     carveout_heap->heap.max_allocated = 0;
  12.     carveout_heap->heap.total_size = heap_data->size;    // size=0x5000000=80M
  13.     //内存的映射位图: 每个bit代表1个PAGE
  14.     carveout_heap->bit_nr = heap_data->size/(PAGE_SIZE * sizeof(unsigned long) * 8)
  15.     carveout_heap->bits =  (unsigned long *)kzalloc(carveout_heap->bit_nr * sizeof(unsigned long), GFP_KERNEL);

  16.     return &carveout_heap->heap;
  17. }
rockchip_ion_probe
    --> ion_device_add_heap
  1. void ion_device_add_heap(struct ion_device *dev, struct ion_heap *heap)
  2. {
  3.     struct rb_node **p = &dev->heaps.rb_node;
  4.     struct rb_node *parent = NULL;
  5.     struct ion_heap *entry;

  6.     heap->dev = dev;
  7.     mutex_lock(&dev->lock);
  8.     while (*p) {
  9.         parent = *p;
  10.         entry = rb_entry(parent, struct ion_heap, node);

  11.         if (heap->id < entry->id) {
  12.             p = &(*p)->rb_left;
  13.         } else if (heap->id > entry->id ) {
  14.             p = &(*p)->rb_right;
  15.         } else {
  16.             pr_err("%s: can not insert multiple heaps with id %d\n", __func__, heap->id);
  17.             goto end;
  18.         }
  19.     }

  20.     rb_link_node(&heap->node, parent, p);
  21.     rb_insert_color(&heap->node, &dev->heaps);
  22.     debugfs_create_file(heap->name, 0664, dev->debug_root, heap, &debug_heap_fops);
  23. end:
  24.     mutex_unlock(&dev->lock);
  25. }

三. ION分配内存的过程
drivers/gpu/ion/ion.c --> ion_ioctl   //cmd=0xc0104900 接收到命令:ION_IOC_ALLOC
    --> ion_alloc
    --> ion_carveout_heap_allocate
    --> drivers/gpu/ion/ion_carveout_heap.c  调用 ion_carveout_allocate[47]:
  1. static int ion_carveout_heap_allocate(struct ion_heap *heap,
  2.        struct ion_buffer *buffer, unsigned long size, unsigned long align,  unsigned long flags)
  3. {
  4.     buffer->priv_phys = ion_carveout_allocate(heap, size, align); //buffer->priv_phy=0x91a00000是物理地址
  5.     return buffer->priv_phys == ION_CARVEOUT_ALLOCATE_FAIL ? -ENOMEM : 0;
  6. }
ion_carveout_heap_allocate
    --> ion_carveout_allocate
在drivers/gpu/ion/ion_carverout_heap.c中
  1. ion_phys_addr_t ion_carveout_allocate(struct ion_heap *heap, unsigned long size, unsigned long align)
  2. {
  3.     struct ion_carveout_heap *carveout_heap = container_of(heap, struct ion_carveout_heap, heap);
  4.     unsigned long offset = gen_pool_alloc(carveout_heap->pool, size);   //offset=0x91a00000,是物理地址
  5.    
  6.     heap->allocated_size += size;     //统计己分配的大小
  7.     //防止越界
  8.     if((offset + size - carveout_heap->base) > heap->max_allocated)
  9.         heap->max_allocated = offset + size - carveout_heap->base;
  10.     //填充位图
  11.     bitmap_set(carveout_heap->bits, (offset - carveout_heap->base)/PAGE_SIZE , size/PAGE_SIZE);
  12.     return offset;
  13. }
原理很简单:
    就是在位图中查找适合的大小,然后把位图所代表的地址返回 (怎么有点表达不清楚了??? 反正就这个意思,呵呵)
ion_carveout_heap_allocate
    --> ion_carveout_allocate
        --> gen_pool_alloc
在lib/genalloc.c中
  1. unsigned long gen_pool_alloc(struct gen_pool *pool, size_t size)
  2. {
  3.     struct list_head *_chunk;
  4.     struct gen_pool_chunk *chunk;
  5.     unsigned long addr, flags;
  6.     int order = pool->min_alloc_order;
  7.     int nbits, start_bit, end_bit;

  8.     if (size == 0)
  9.         return 0;

  10.     nbits = (size + (1UL << order) - 1) >> order;  //由字节转成块,转成位图所代表的大小

  11.     read_lock(&pool->lock);
  12.     list_for_each(_chunk, &pool->chunks) {
  13.         chunk = list_entry(_chunk, struct gen_pool_chunk, next_chunk);

  14.         end_bit = (chunk->end_addr - chunk->start_addr) >> order; 

  15.         spin_lock_irqsave(&chunk->lock, flags);
  16.         //在这个内存位图中查找足够大的内存
  17.         start_bit = bitmap_find_next_zero_area(chunk->bits, end_bit, 0, nbits, 0);
  18.         if (start_bit >= end_bit) {
  19.             spin_unlock_irqrestore(&chunk->lock, flags);
  20.             continue;
  21.         }
  22.         //由位图映射到实际的地址
  23.         addr = chunk->start_addr + ((unsigned long)start_bit << order);
  24.         //填充位图,说明这块内存地方己分配
  25.         bitmap_set(chunk->bits, start_bit, nbits);
  26.         spin_unlock_irqrestore(&chunk->lock, flags);
  27.         read_unlock(&pool->lock);
  28.         return addr;   //返回地址
  29.     }
  30.     read_unlock(&pool->lock);
  31.     return 0;
  32. }
  33. EXPORT_SYMBOL(gen_pool_alloc);



阅读(3517) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~