• Linux驱动模型解析bus之platform bus


     这是内核启动之后要调用的驱动模型的开始代码:

    drivers/base/init.c
    /*
    * * driver_init - initialize driver model. * * Call the driver model init functions to initialize their * subsystems. Called early from init/main.c. */ void __init driver_init(void) { /* These are the core pieces */ devices_init(); // /sys/devices buses_init(); // /sys/bus classes_init(); // /sys/class firmware_init(); hypervisor_init(); /* These are also core pieces, but must come after the * core core pieces. */ platform_bus_init(); system_bus_init(); cpu_dev_init(); memory_dev_init(); }

    且看platform_bus_init

    drivers/base/platform.c
    struct device platform_bus = {
            .bus_id         = "platform",
    };
    struct bus_type platform_bus_type = {
            .name           = "platform",
            .dev_attrs      = platform_dev_attrs,
            .match          = platform_match,
            .uevent         = platform_uevent,
            .pm             = PLATFORM_PM_OPS_PTR,
    };
    
    
    int __init platform_bus_init(void)
    {
            int error;
         /* /sys/devices/platform (this platform is bus_id's value) */
         error = device_register(&platform_bus);
         if (error)
            return error;
          /* /sys/bus/platform (this platform is the value of bus_type's name field) */
          error = bus_register(&platform_bus_type); 

         if (error)
             device_unregister(
    &platform_bus);

         return error;
    }

    这里讲述 bus_register(&platform_bus_type):

    /**
     * struct bus_type_private - structure to hold the private to the driver core portions of the bus_type structure.
     *
     * @subsys - the struct kset that defines this bus.  This is the main kobject
     * @drivers_kset - the list of drivers associated with this bus
     * @devices_kset - the list of devices associated with this bus
     * @klist_devices - the klist to iterate over the @devices_kset
     * @klist_drivers - the klist to iterate over the @drivers_kset
     * @bus_notifier - the bus notifier list for anything that cares about things
     * on this bus.
     * @bus - pointer back to the struct bus_type that this structure is associated
     * with.
     *
     * This structure is the one that is the actual kobject allowing struct
     * bus_type to be statically allocated safely.  Nothing outside of the driver
     * core should ever touch these fields.
     */
    struct bus_type_private {
            struct kset subsys;
            struct kset *drivers_kset;
            struct kset *devices_kset;
            struct klist klist_devices;
            struct klist klist_drivers;
            struct blocking_notifier_head bus_notifier;
            unsigned int drivers_autoprobe:1;
            struct bus_type *bus;
    };
    int bus_register(struct bus_type *bus)                                          
    {                                                                               
            int retval;                                                             
            struct bus_type_private *priv;                                          
                                                                                    
            priv = kzalloc(sizeof(struct bus_type_private), GFP_KERNEL);            
            if (!priv)                                                              
                    return -ENOMEM;                                                 
                                                                                    
            priv->bus = bus;                                                        
            bus->p = priv;                                                         
                                                                                    
            BLOCKING_INIT_NOTIFIER_HEAD(&priv->bus_notifier);                       
                                                                                    
            retval = kobject_set_name(&priv->subsys.kobj, "%s", bus->name);         
            if (retval)                                                             
                    goto out;                                                       
                                                                                    
            priv->subsys.kobj.kset = bus_kset;                                      
            priv->subsys.kobj.ktype = &bus_ktype;                                   
            priv->drivers_autoprobe = 1;                                            
                                                                                    
            retval = kset_register(&priv->subsys);                                  
            if (retval)                                                             
                    goto out;                                                       
                                                                                    
            retval = bus_create_file(bus, &bus_attr_uevent);                        
            if (retval)                                                             
                    goto bus_uevent_fail;                                           
                                                                                    
            priv->devices_kset = kset_create_and_add("devices", NULL,               
                                                     &priv->subsys.kobj);   
            if (!priv->devices_kset) {                                              
                    retval = -ENOMEM;                                               
                    goto bus_devices_fail;                                          
            }                                                                       
                                                                                    
            priv->drivers_kset = kset_create_and_add("drivers", NULL,               
                                                     &priv->subsys.kobj);           
            if (!priv->drivers_kset) {                                              
                    retval = -ENOMEM;                                               
                    goto bus_drivers_fail;                                          
            }                                                                       
                                                                                    
            klist_init(&priv->klist_devices, klist_devices_get, klist_devices_put); 
            klist_init(&priv->klist_drivers, NULL, NULL);                           
                                                                                    
            retval = add_probe_files(bus);                                          
            if (retval)                                                             
                    goto bus_probe_files_fail;                                      
                                                                                    
            retval = bus_add_attrs(bus);                                            
            if (retval)                                                             
                    goto bus_attrs_fail;                                            
                                                                                    
            pr_debug("bus: '%s': registered
    ", bus->name);                         
            return 0;

    struct bus_type_private *priv指向struct bus_type,这里会显示/sys/bus/platform

    retval = kobject_set_name(&priv->subsys.kobj, "%s", bus->name); 

    priv->subsys.kobj.kset = bus_kset;

    retval = kset_register(&priv->subsys);// subsys is a kset.

    这里显示/sys/bus/platform/devices

    priv->devices_kset = kset_create_and_add("devices", NULL, &priv->subsys.kobj);

    这里显示/sys/bus/platform/drivers

    priv->drivers_kset = kset_create_and_add("drivers", NULL, &priv->subsys.kobj);

     kset_create_and_add--->kset_register

    /**                                                                                
     * kset_register - initialize and add a kset.                                      
     * @k: kset.                                                                       
     */                                                                                
    int kset_register(struct kset *k)                                                  
    {                                                                                  
            int err;                                                                   
                                                                                       
            if (!k)                                                                    
                    return -EINVAL;                                                    
                                                                                       
            kset_init(k); // INIT_LIST_HEAD(&k->kobj->entry); INIT_LIST_HEAD(&k->list);                                                             
            err = kobject_add_internal(&k->kobj);                                      
            if (err)                                                                   
                    return err;                                                        
            kobject_uevent(&k->kobj, KOBJ_ADD);                                                                                                      
            return 0;                                                                  
    } 
    static int kobject_add_internal(struct kobject *kobj)                           
    {   
        kobj_kset_join(kobj);
        error = create_dir(kobj); // /sys/bus/platform
    }
    /* add the kobject to its kset's list */                                        
    static void kobj_kset_join(struct kobject *kobj)                                                                                                 
    {                                                                               
            if (!kobj->kset)                                                        
                    return;                                                         
                                                                                    
            kset_get(kobj->kset);                                                   
            spin_lock(&kobj->kset->list_lock);                                      
            list_add_tail(&kobj->entry, &kobj->kset->list);                         
            spin_unlock(&kobj->kset->list_lock);                                    
    } 

    If a kset is associated with a kobject, then the parent for the kobject can be set to
    NULL in the call to kobject_add() and then the kobject's parent will be the kset itself.

    确切的说是kobject's parent赋值为kobject关联的kset's kobjcect

    struct kobject {                                                                   
            const char              *name;                                             
            struct list_head        entry;                                             
            struct kobject          *parent;                                           
            struct kset             *kset;                                             
            struct kobj_type        *ktype;                                            
            struct sysfs_dirent     *sd;                                               
            struct kref             kref;                                              
            unsigned int state_initialized:1;                                          
            unsigned int state_in_sysfs:1;                                             
            unsigned int state_add_uevent_sent:1;                                                                                                    
            unsigned int state_remove_uevent_sent:1;                                   
    }; 
     *                                                                              
     * A kset defines a group of kobjects.  They can be individually                
     * different "types" but overall these kobjects all want to be grouped          
     * together and operated on in the same manner.  ksets are used to              
     * define the attribute callbacks and other common events that happen to        
     * a kobject.                                                                   
     *                                                                              
     * @list: the list of all kobjects for this kset                                
     * @list_lock: a lock for iterating over the kobjects                           
     * @kobj: the embedded kobject for this kset (recursion, isn't it fun...)       
     * @uevent_ops: the set of uevent operations for this kset.  These are          
     * called whenever a kobject has something happen to it so that the kset           
     * can add new environment variables, or filter out the uevents if so              
     * desired.                                                                        
     */                                                                                
    struct kset {                                                                                                                                    
            struct list_head list;                                                  
            spinlock_t list_lock;                                                      
            struct kobject kobj;                                                       
            struct kset_uevent_ops *uevent_ops;                                        
    };
    struct list_head {                                                                                                                               
            struct list_head *next, *prev;                                          
    }; 

    从list_add_tail(&kobj->entry, &kobj->kset->list); 调用中,我们一下子就明白了,

    bus =&struct bus_type platform_bus_type;
    bus->p->->subsys.kobj.kset = bus_kset;// bus_kset = kset_create_and_add("bus", &bus_uevent_ops, NULL); 创建了bus的kset显示/sys/bus
    所以&kobj->kset->list就是bus_kset->list,list_add_tail就是把
    bus->p->->subsys.kobj.entry加入到bus_kset->list链表中。
    bus_kset包含不同bus的subsys的kset,而代表subsys的kset的就是这个kset中的kobject。所以把kobjetct的entry加入到表示kset的kset->list中。
    换句话说,struct kset这个集合包含的内容由其嵌入的struct list_head list来表示,这个struct kset自身由其嵌入的struct kobject kobj来表示。
    所以这里就是把platform这个kset加入到bus这个kset中。用户空间的视图表示就是
    /sys/bus/platform。
     
  • 相关阅读:
    python2的比较函数,cmp
    快速排序
    如果a,b,c为自然数,a+b+c=1000,a方+b方=c方,求出abc可能的组合(python实现)
    python之join
    python之functools partial
    Python 3 iter函数用法简述
    python线程之condition
    python 线程 event
    getattr getattribute setattr hasattr delattr
    Properties类
  • 原文地址:https://www.cnblogs.com/georgejguo/p/driver_model-platformbus.html
Copyright © 2020-2023  润新知