struct device dev;&nbs…

    xiaoxiao2021-12-14  18

    一:dma_mask与coherent_dma_mask的定义

    在linux内核中,引入了platform_device与platform_driver,这样就很方便了平台的设备与驱动。在include\linux\platform_device.h下:

    struct platform_device {  const char * name;  int  id;  struct device dev; u32  num_resources;  struct resource * resource;

     const struct platform_device_id *id_entry;

       struct pdev_archdata archdata; };

    而struct device dev,在include\linux\device.h中:

    struct device {  struct device  *parent;

     struct device_private *p;

     struct kobject kobj;  const char  *init_name;  struct device_type *type;

     struct mutex  mutex; 

     struct bus_type *bus;    struct device_driver *driver;   void  *platform_data;   struct dev_pm_info power;

    #ifdef CONFIG_NUMA  int  numa_node;  #endif  u64  *dma_mask;   u64  coherent_dma_mask;

     struct device_dma_parameters *dma_parms;

     struct list_head dma_pools; 

     struct dma_coherent_mem *dma_mem;    struct dev_archdata archdata; #ifdef CONFIG_OF  struct device_node *of_node; #endif

     dev_t   devt; 

     spinlock_t  devres_lock;  struct list_head devres_head;

     struct klist_node knode_class;  struct class  *class;  const struct attribute_group **groups; 

     void (*release)(struct device *dev); }; dma_mask与 coherent_dma_mask这两个参数表示它能寻址的物理地址的范围,内核通过这两个参数分配合适的物理内存给 device。其中dma_coherent_mask则作用于申请一致性DMA缓冲区。因为不是所有的硬件都能够支持64bit的地址宽度。如果 addr_phy 是一个物理地址,且 (u64)addr_phy <= *dev->dma_mask,那么 该 device 就可以寻址该物理地址。如果 device 只能寻址32位地址,那么 mask 应为 0xffffffff。依此类推。

    例如,在linux2.6.38中:

    static u64 nuc900_device_usb_ehci_dmamask = 0xffffffffUL;

    static struct platform_device nuc900_device_ehci = {         .name    = "nuc900-ehci",         .id    = -1,         .num_resources   = ARRAY_SIZE(nuc900_ehci_resource),         .resource   = nuc900_ehci_resource,         .dev              = {                 .dma_mask = &nuc900_device_usb_ehci_dmamask,                 .coherent_dma_mask = 0xffffffffUL        } };

    二:sample code

    这段代码摘录自 arch\arm\mm\dma-mapping.c

        u64 limit;         size = PAGE_ALIGN(size);     //这个 limit 就是通过 mask 计算得到的设备最大寻址范围。     limit = (mask + 1) & ~mask;     //当 size 超出 limit 时,说明分配的地址超出了设备的最大寻址能力,这时返回错误。     if ((limit && size >= limit) ||         size >= (CONSISTENT_END - CONSISTENT_BASE)) {         printk(KERN_WARNING "coherent allocation too big "                "(requested %#x mask %#llx)\n", size, mask);         goto no_page;     }

    转载请注明原文地址: https://ju.6miu.com/read-964582.html

    最新回复(0)