歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
Linux教程網 >> Linux編程 >> Linux編程 >> Linux下platform_device中的dma_mask與coherent_dma_mask

Linux下platform_device中的dma_mask與coherent_dma_mask

日期:2017/3/1 10:32:15   编辑:Linux編程

一: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;

/* arch specific additions */
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; /* initial name of the device */
struct device_type *type;

struct mutex mutex; /* mutex to synchronize calls to
* its driver.
*/

struct bus_type *bus; /* type of bus device is on */
struct device_driver *driver; /* which driver has allocated this
device */
void *platform_data; /* Platform specific data, device
core doesn't touch it */
struct dev_pm_info power;

#ifdef CONFIG_NUMA
int numa_node; /* NUMA node this device is close to */
#endif
u64 *dma_mask; /* dma mask (if dma'able device) */
u64 coherent_dma_mask;/* Like dma_mask, but for
alloc_coherent mappings as
not all hardware supports
64 bit addresses for consistent
allocations such descriptors. */

struct device_dma_parameters *dma_parms;

struct list_head dma_pools; /* dma pools (if dma'ble) */

struct dma_coherent_mem *dma_mem; /* internal for coherent mem
override */
/* arch specific additions */
struct dev_archdata archdata;
#ifdef CONFIG_OF
struct device_node *of_node;
#endif

dev_t devt; /* dev_t, creates the sysfs "dev" */

spinlock_t devres_lock;
struct list_head devres_head;

struct klist_node knode_class;
struct class *class;
const struct attribute_group **groups; /* optional 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中:

/* USB EHCI Host Controller */

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;
/*
* Sanity check the allocation size.
*/
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;
}

Copyright © Linux教程網 All Rights Reserved