struct platform_device *platform_device_register_full(const struct platform_device_info *pdevinfo)
这个函数会根据platform_device_info的信息注册一个platform_device并返回这个platform_device。
首先调用 pdev = platform_device_alloc(pdevinfo->name, pdevinfo->id);
来申请一个platform_device,并进行赋值pdevinfo->name 和 pdevinfo->id
struct platform_device *platform_device_alloc(const char *name, int id)
{
struct platform_object *pa;
pa = kzalloc(sizeof(*pa) + strlen(name) + 1, GFP_KERNEL);
if (pa) {
strcpy(pa->name, name);
pa->pdev.name = pa->name;
pa->pdev.id = id;
device_initialize(&pa->pdev.dev);
pa->pdev.dev.release = platform_device_release;
arch_setup_pdev_archdata(&pa->pdev);
}
return pa ? &pa->pdev : NULL;
}
先申请一个platform_object,然后将name和id 赋值给pa,可见pa->name 和 pa->pdev.name是相同.
if (pdevinfo->dma_mask) {
/*
* This memory isn't freed when the device is put,
* I don't have a nice idea for that though. Conceptually
* dma_mask in struct device should not be a pointer.
* See http://thread.gmane.org/gmane.linux.kernel.pci/9081
*/
pdev->dev.dma_mask =
kmalloc(sizeof(*pdev->dev.dma_mask), GFP_KERNEL);
if (!pdev->dev.dma_mask)
goto err;
*pdev->dev.dma_mask = pdevinfo->dma_mask;
pdev->dev.coherent_dma_mask = pdevinfo->dma_mask;
}
其次会判断pdevinfo->dma_mask 是否为NULL,不为NULL的话,就赋值给pdev。从这里可以看出pdev->dev.dma_mask 和 pdev->dev.coherent_dma_mask
也是相等的。如果APCI传递过来的pdevinfo->dma_mask为NULL的话,就给予driver probe函数给dma_mask赋值的机会.
ret = platform_device_add_resources(pdev,
pdevinfo->res, pdevinfo->num_res);
if (ret)
goto err;
ret = platform_device_add_data(pdev,
pdevinfo->data, pdevinfo->size_data);
if (ret)
goto err;
if (pdevinfo->properties) {
ret = platform_device_add_properties(pdev,
pdevinfo->properties);
if (ret)
goto err;
}
这三个函数分别添加resource/data/properties这里写法不是很好,为什么不先判断pdevinfo->res 和 pdevinfo->data为NULL呢?
反而判断是否为NULL 搬到函数里面了,个人感觉这里写法不一致.
int platform_device_add_data(struct platform_device *pdev, const void *data,
size_t size)
{
void *d = NULL;
if (data) {
d = kmemdup(data, size, GFP_KERNEL);
if (!d)
return -ENOMEM;
}
kfree(pdev->dev.platform_data);
pdev->dev.platform_data = d;
return 0;
}
最后会在注册platform_device_add 之前调用一个callback 这样可以在driver probe之前做一些初始化.
if (pdevinfo->pre_add_cb)
pdevinfo->pre_add_cb(&pdev->dev);
这个函数会根据platform_device_info的信息注册一个platform_device并返回这个platform_device。
首先调用 pdev = platform_device_alloc(pdevinfo->name, pdevinfo->id);
来申请一个platform_device,并进行赋值pdevinfo->name 和 pdevinfo->id
struct platform_device *platform_device_alloc(const char *name, int id)
{
struct platform_object *pa;
pa = kzalloc(sizeof(*pa) + strlen(name) + 1, GFP_KERNEL);
if (pa) {
strcpy(pa->name, name);
pa->pdev.name = pa->name;
pa->pdev.id = id;
device_initialize(&pa->pdev.dev);
pa->pdev.dev.release = platform_device_release;
arch_setup_pdev_archdata(&pa->pdev);
}
return pa ? &pa->pdev : NULL;
}
先申请一个platform_object,然后将name和id 赋值给pa,可见pa->name 和 pa->pdev.name是相同.
if (pdevinfo->dma_mask) {
/*
* This memory isn't freed when the device is put,
* I don't have a nice idea for that though. Conceptually
* dma_mask in struct device should not be a pointer.
* See http://thread.gmane.org/gmane.linux.kernel.pci/9081
*/
pdev->dev.dma_mask =
kmalloc(sizeof(*pdev->dev.dma_mask), GFP_KERNEL);
if (!pdev->dev.dma_mask)
goto err;
*pdev->dev.dma_mask = pdevinfo->dma_mask;
pdev->dev.coherent_dma_mask = pdevinfo->dma_mask;
}
其次会判断pdevinfo->dma_mask 是否为NULL,不为NULL的话,就赋值给pdev。从这里可以看出pdev->dev.dma_mask 和 pdev->dev.coherent_dma_mask
也是相等的。如果APCI传递过来的pdevinfo->dma_mask为NULL的话,就给予driver probe函数给dma_mask赋值的机会.
ret = platform_device_add_resources(pdev,
pdevinfo->res, pdevinfo->num_res);
if (ret)
goto err;
ret = platform_device_add_data(pdev,
pdevinfo->data, pdevinfo->size_data);
if (ret)
goto err;
if (pdevinfo->properties) {
ret = platform_device_add_properties(pdev,
pdevinfo->properties);
if (ret)
goto err;
}
这三个函数分别添加resource/data/properties这里写法不是很好,为什么不先判断pdevinfo->res 和 pdevinfo->data为NULL呢?
反而判断是否为NULL 搬到函数里面了,个人感觉这里写法不一致.
int platform_device_add_data(struct platform_device *pdev, const void *data,
size_t size)
{
void *d = NULL;
if (data) {
d = kmemdup(data, size, GFP_KERNEL);
if (!d)
return -ENOMEM;
}
kfree(pdev->dev.platform_data);
pdev->dev.platform_data = d;
return 0;
}
最后会在注册platform_device_add 之前调用一个callback 这样可以在driver probe之前做一些初始化.
if (pdevinfo->pre_add_cb)
pdevinfo->pre_add_cb(&pdev->dev);