设备驱动中的device(kernel-4.7)

本文详细解析了Linux内核4.7中device结构体的定义及设备注册过程,涉及设备与总线、驱动的关系,以及sysfs的初始化。设备注册包括device结构体初始化、分配内存、添加到系统、创建属性文件和链接,以及探测匹配的驱动等功能。
摘要由CSDN通过智能技术生成

device结构体定义,在kernel-4.7/include/linux/device.h中:


/**
 * struct device - The basic device structure
 * @driver_data: Private pointer for driver specific info.
 * @power:  For device power management.
 *      See Documentation/power/devices.txt for details.
 * @pm_domain:  Provide callbacks that are executed during system suspend,
 *      hibernation, system resume and during runtime PM transitions
 *      along with subsystem-level and driver-level callbacks.
 * @pins:   For device pin management.
 *      See Documentation/pinctrl.txt for details.
 * @msi_list:   Hosts MSI descriptors
 * @msi_domain: The generic MSI domain this device is using.
 * @numa_node:  NUMA node this device is close to.
 * @dma_mask:   Dma mask (if dma'ble device).
 * @coherent_dma_mask: Like dma_mask, but for alloc_coherent mapping as not all
 *      hardware supports 64-bit addresses for consistent allocations
 *      such descriptors.
 * @dma_pfn_offset: offset of DMA memory range relatively of RAM
 * @dma_parms:  A low level driver may set these to teach IOMMU code about
 *      segment limitations.
 * @dma_pools:  Dma pools (if dma'ble device).
 * @dma_mem:    Internal for coherent mem override.
 * @cma_area:   Contiguous memory area for dma allocations
 * @archdata:   For arch-specific additions.
 * @of_node:    Associated device tree node.
 * @fwnode: Associated device node supplied by platform firmware.
 * @devt:   For creating the sysfs "dev".
 * @id:     device instance
 * @devres_lock: Spinlock to protect the resource of the device.
 * @devres_head: The resources list of the device.
 * @knode_class: The node used to add the device to the class list.
 * @class:  The class of the device.
 * @groups: Optional attribute groups.
 * @release:    Callback to free the device after all references have
 *      gone away. This should be set by the allocator of the
 *      device (i.e. the bus driver that discovered the device).
 * @iommu_group: IOMMU group the device belongs to.
 *
 * @offline_disabled: If set, the device is permanently online.
 * @offline:    Set after successful invocation of bus type's .offline().
 *
 * At the lowest level, every device in a Linux system is represented by an
 * instance of struct device. The device structure contains the information
 * that the device model core needs to model the system. Most subsystems,
 * however, track additional information about the devices they host. As a
 * result, it is rare for devices to be represented by bare device structures;
 * instead, that structure, like kobject structures, is usually embedded within
 * a higher-level representation of the device.
 */
struct device {
    struct device       *parent;   //指向其父设备。

    struct device_private   *p;   // 设备驱动部分的核心私有数据

    struct kobject kobj;    // kobject类, 用于联系到sysfs中
    const char      *init_name; /* initial name of the device */
    const 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 */
    void        *driver_data;   /* Driver data, set and get with
                       dev_set/get_drvdata */
    struct dev_pm_info  power;
    struct dev_pm_domain    *pm_domain;

#ifdef CONFIG_GENERIC_MSI_IRQ_DOMAIN
    struct irq_domain   *msi_domain;
#endif
#ifdef CONFIG_PINCTRL
    struct dev_pin_info *pins;
#endif
#ifdef CONFIG_GENERIC_MSI_IRQ
    struct list_head    msi_list;
#endif

#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. */
    unsigned long   dma_pfn_offset;

    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 */
#ifdef CONFIG_DMA_CMA
    struct cma *cma_area;       /* contiguous memory area for dma
                       allocations */
#endif
    /* arch specific additions */
    struct dev_archdata archdata;

    struct device_node  *of_node; /* associated device tree node */
    struct fwnode_handle    *fwnode; /* firmware device node */

    dev_t           devt;   /* dev_t, creates the sysfs "dev" */
    u32         id; /* device instance */

    spinlock_t      devres_lock;
    struct list_head    devres_head;

    struct klist_node   knode_class;   //连入class链表时所用的klist节点
    struct class        *class;    //指向类的指针
    const struct attribute_group **groups;  /* optional groups 设备的属性集合*/ 

    void    (*release)(struct device *dev); //设备释放时调用的函数
    struct iommu_group  *iommu_group;

    bool            offline_disabled:1;
    bool            offline:1;
};

device结构体用于描述设备相关的信息设备之间的层次关系,以及设备与总线、驱动的关系。



/**
 * struct device_private - structure to hold the private to the driver core portions of the device structure.
 *
 * @klist_children - klist containing all children of this device
 * @knode_parent - node in sibling list
 * @knode_driver - node in driver list
 * @knode_bus - node in bus list
 * @deferred_probe - entry in deferred_probe_list which is used to retry the
 *  binding of drivers which were unable to get all the resources needed by
 *  the device; typically because it depends on another driver getting
 *  probed first.
 * @device - pointer back to the struct device that this structure is
 * associated with.
 *
 * Nothing outside of the driver core should ever touch these fields.
 */
struct device_private {
    struct klist klist_children;   //子设备的链表
    struct klist_node knode_parent; //连入父设备的klist_children时所用的节点
    struct klist_node knode_driver; //连入驱动的设备链表所用的节点
    struct klist_node knode_bus;  //连入总线的设备链表时所用的节点
    struct list_head deferred_probe;
    struct device *device;
}; 
//从父设备的klist_children上节点,获得相应的device_private
#define to_device_private_parent(obj)   \     
    container_of(obj, struct device_private, knode_parent)

//从驱动的设备链表上节点,获得对应的device_private
#define to_device_private_driver(obj)   \
    container_of(obj, struct device_private, knode_driver) 

从总线的设备链表上节点,获得对应的device_private
#define to_device_private_bus(obj)  \
    container_of(obj, struct device_private, knode_bus)

struct device中有一部分不愿意让外界看到,所以做出struct device_private结构,包括了设备驱动模型内部的链接。这个结构体定义在drivers/base/base.h文件中。


Linux设备模型中,device相关的sysfs结构的初始化是由devices_init函数完成的,该函数定义在drivers/base/core.c文件中,其内容如下:


int __init devices_init(void)
{
    //创建devices_kset,它是所有device的集合,它的名字是“devices”,对应/sys/devices目录
    devices_kset = kset_create_and_add("devices", &device_uevent_ops, NULL);
    if (!devices_kset)
        return -ENOMEM; 

    //创建dev_kobj,它的名字是“dev”,对应/sys/dev目录
    dev_kobj = kobject_create_and_add("dev", NULL);
    if (!dev_kobj)
        goto dev_kobj_err; 

    //创建sysfs_dev_block_kobj,它的名字是“block”,对应/sys/dev/block目录
    sysfs_dev_block_kobj = kobject_create_and_add("block", dev_kobj);
    if (!sysfs_dev_block_kobj)
        goto block_kobj_err; 

    创建sysfs_dev_char_kobj,它的名字是“char”,对应/sys/dev/char目录
    sysfs_dev_char_kobj = kobject_create_and_add("char", dev_kobj);
    if (!sysfs_dev_char_kobj)
        goto char_kobj_err;

    return 0;

 char_kobj_err:
    kobject_put(sysfs_dev_block_kobj);
 block_kobj_err:
    kobject_put(dev_kobj);
 dev_kobj_err:
    kset_unregister(devices_kset);
    return -ENOMEM;
}

注册一个device是通过调用device_register函数完成的,该函数定义在drivers/base/core.c文件中,其内容如下:


/**
 * device_regi
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值